errval_t pmap_current_init(bool init_domain) { struct pmap_arm *pmap_arm = (struct pmap_arm*)get_current_pmap(); // To reserve a block of virtual address space, // a vregion representing the address space is required. // We construct a superficial one here and add it to the vregion list. struct vregion *vregion = &pmap_arm->vregion; assert((void*)vregion > (void*)pmap_arm); assert((void*)vregion < (void*)(pmap_arm + 1)); vregion->vspace = NULL; vregion->memobj = NULL; vregion->base = VSPACE_BEGIN; vregion->offset = 0; vregion->size = META_DATA_RESERVED_SPACE; vregion->flags = 0; vregion->next = NULL; struct vspace *vspace = pmap_arm->p.vspace; assert(!vspace->head); vspace->head = vregion; pmap_arm->vregion_offset = pmap_arm->vregion.base; return SYS_ERR_OK; }
/** * \brief Create page mappings * * \param pmap The pmap object * \param vaddr The virtual address to create the mapping for * \param frame The frame cap to map in * \param offset Offset into the frame cap * \param size Size of the mapping * \param flags Flags for the mapping * \param retoff If non-NULL, filled in with adjusted offset of mapped region * \param retsize If non-NULL, filled in with adjusted size of mapped region */ static errval_t map(struct pmap *pmap, genvaddr_t vaddr, struct capref frame, size_t offset, size_t size, vregion_flags_t flags, size_t *retoff, size_t *retsize) { struct pmap_arm *pmap_arm = (struct pmap_arm *)pmap; size += BASE_PAGE_OFFSET(offset); size = ROUND_UP(size, BASE_PAGE_SIZE); offset -= BASE_PAGE_OFFSET(offset); const size_t slabs_reserve = 3; // == max_slabs_required(1) uint64_t slabs_free = slab_freecount(&pmap_arm->slab); size_t slabs_required = max_slabs_required(size) + slabs_reserve; if (slabs_required > slabs_free) { if (get_current_pmap() == pmap) { errval_t err = refill_slabs(pmap_arm, slabs_required); if (err_is_fail(err)) { return err_push(err, LIB_ERR_SLAB_REFILL); } } else { size_t bytes = SLAB_STATIC_SIZE(slabs_required - slabs_free, sizeof(struct vnode)); void *buf = malloc(bytes); if (!buf) { return LIB_ERR_MALLOC_FAIL; } slab_grow(&pmap_arm->slab, buf, bytes); } } return do_map(pmap_arm, vaddr, frame, offset, size, flags, retoff, retsize); }
int map_unmap(void) { errval_t err; struct capref mem; DEBUG_MAP_UNMAP("ram_alloc\n"); err = ram_alloc(&mem, BASE_PAGE_BITS); if (err_is_fail(err)) { printf("ram_alloc: %s (%"PRIuERRV")\n", err_getstring(err), err); return 1; } struct capref frame; DEBUG_MAP_UNMAP("retype\n"); err = slot_alloc(&frame); if (err_is_fail(err)) { printf("slot_alloc: %s (%"PRIuERRV")\n", err_getstring(err), err); return 1; } err = cap_retype(frame, mem, ObjType_Frame, BASE_PAGE_BITS); if (err_is_fail(err)) { printf("cap_retype: %s (%"PRIuERRV")\n", err_getstring(err), err); return 1; } DEBUG_MAP_UNMAP("delete ram cap\n"); err = cap_destroy(mem); if (err_is_fail(err)) { printf("cap_delete(mem): %s (%"PRIuERRV")\n", err_getstring(err), err); return 1; } struct frame_identity fi; err = invoke_frame_identify(frame, &fi); if (err_is_fail(err)) { printf("frame_identify: %s (%"PRIuERRV")\n", err_getstring(err), err); return 1; } DEBUG_MAP_UNMAP("frame: base = 0x%"PRIxGENPADDR", bits = %d\n", fi.base, fi.bits); #ifdef NKMTEST_DEBUG_MAP_UNMAP dump_pmap(get_current_pmap()); #endif struct vregion *vr; struct memobj *memobj; void *vaddr; DEBUG_MAP_UNMAP("map\n"); err = vspace_map_one_frame(&vaddr, BASE_PAGE_SIZE, frame, &memobj, &vr); if (err_is_fail(err)) { printf("vspace_map_one_frame: %s (%"PRIuERRV")\n", err_getstring(err), err); } char *memory = vaddr; DEBUG_MAP_UNMAP("vaddr = %p\n", vaddr); #ifdef NKMTEST_DEBUG_MAP_UNMAP dump_pmap(get_current_pmap()); #endif DEBUG_MAP_UNMAP("write 1\n"); int i; for (i = 0; i < BASE_PAGE_SIZE; i++) { memory[i] = i % INT8_MAX; } DEBUG_MAP_UNMAP("verify 1\n"); for (i = 0; i < BASE_PAGE_SIZE; i++) { assert(memory[i] == i % INT8_MAX); } DEBUG_MAP_UNMAP("delete frame cap\n"); err = cap_destroy(frame); if (err_is_fail(err)) { printf("cap_delete(frame): %s (%"PRIuERRV")\n", err_getstring(err), err); return 1; } #ifdef NKMTEST_DEBUG_MAP_UNMAP // no mapping should remain here dump_pmap(get_current_pmap()); err = debug_dump_hw_ptables(); if (err_is_fail(err)) { printf("kernel dump ptables: %s (%"PRIuERRV")\n", err_getstring(err), err); return 1; } #endif printf("%s: done\n", __FUNCTION__); return 0; }