failure TYPE_NOT_CREATABLE "Specified capability type is not creatable at runtime. Consider retyping it from another capability.",
// errors specific to page mapping
- failure VNODE_SLOT_INVALID "Destination slot exceeds size of page table",
- failure WRONG_MAPPING "Wrong source/destination mapping type",
- failure FRAME_OFFSET_INVALID "Specified offset exceeds size of frame",
- failure VNODE_SLOT_RESERVED "Destination slot is reserved",
- failure VNODE_SLOT_INUSE "Destination slot in use: unmap first",
- failure VNODE_TYPE "Encountered non-VNode capability when manipulating page tables",
- failure VNODE_LOOKUP_NEXT "Could not find next level page table",
+ failure VNODE_SLOT_INVALID "Destination slot exceeds size of page table",
+ failure WRONG_MAPPING "Wrong source/destination mapping type",
+ failure FRAME_OFFSET_INVALID "Specified offset exceeds size of frame",
+ failure VNODE_SLOT_RESERVED "Destination slot is reserved",
+ failure VNODE_SLOT_INUSE "Destination slot in use: unmap first",
+ failure VNODE_TYPE "Encountered non-VNode capability when manipulating page tables",
+ failure VNODE_LOOKUP_NEXT "Could not find next level page table",
+ failure VM_MAP_START_UNALIGNED "Mapping offset not aligned to BASE_PAGE_SIZE",
+ failure VM_MAP_SIZE "Mapping size too large",
+ failure VM_MAP_OFFSET "Mapping offset too large",
// errors related to IRQ table
failure IRQ_LOOKUP "Specified capability was not found while inserting in IRQ table",
failure VNODE_MAP "Failure in vnode_map()",
failure VNODE_UNMAP "Failure in vnode_unmap()",
failure IDC_ENDPOINT_ALLOC "Failure in idc_endpoint_alloc()",
+ failure VM_MODIFY_MAPPING "Failure in vm_modify_mapping()",
failure SLOT_ALLOC_INIT "Failure in slot_alloc_init()",
failure SLOT_ALLOC_NO_SPACE "Slot allocator is out of space",
return cap_invoke2(cap, VNodeCmd_Unmap, entry).error;
}
+static inline errval_t
+invoke_vm_modify_mapping(struct capref mem, size_t page_count, uint64_t off)
+{
+ return cap_invoke3(mem, FrameCmd_Modify_Mapping, page_count, off).error;
+}
+
/**
* \brief Return the physical address and size of a frame capability
*
return invoke_vnode_unmap(pgtl, entry);
}
+static inline errval_t
+vm_modify_mapping(struct capref mem, size_t page_count, uint64_t off)
+{
+ return invoke_vm_modify_mapping(mem, page_count, off);
+}
+
/**
* \brief Copy a capability between slots in CSpace
*
enum frame_cmd {
FrameCmd_Identify, ///< Return physical address of frame
FrameCmd_SCC_Identify, ///< Return MC route to frame
+ FrameCmd_Modify_Mapping, ///< Modify mapping meta data
};
/**
assert(handler_func != NULL);
lvaddr_t pte;
+
+ size_t mapped_pages = src_cte->mapping_info.mapped_pages;
+
+ if (mapped_pages >= src_cte->mapping_info.page_count) {
+ // exceeded allowed page count for this mapping
+ printf("caps_copy_to_vnode: exceeded allowed page count for this mapping\n");
+ printf(" mapped_pages = %zd, mapping_info.page_count = %zd\n",
+ mapped_pages, src_cte->mapping_info.page_count);
+ return SYS_ERR_VM_MAP_SIZE;
+ }
+
+ if ((param2 - src_cte->mapping_info.offset)/BASE_PAGE_SIZE >= src_cte->mapping_info.page_count) {
+ // requested map offset exceeds mapping region
+ printf("caps_copy_to_vnode: requested map offset exceeds mapping region\n");
+ printf(" offset = %zd, mapping_info.offset = %zd, page_count = %zd",
+ param2, src_cte->mapping_info.offset,
+ src_cte->mapping_info.page_count);
+ return SYS_ERR_VM_MAP_OFFSET;
+ }
+
errval_t r = handler_func(dest_cap, dest_slot, src_cap, param1, param2, &pte);
if (err_is_ok(r)) {
// update mapping
// or do the base page loop here
if (src_cte->mapping_info.pte == 0) {
src_cte->mapping_info.pte = pte;
- src_cte->mapping_info.mapped_offset = param2;
}
src_cte->mapping_info.mapped_pages += 1;
genvaddr_t vaddr = 0;
printf("error in compile_vaddr: 0x%"PRIxERRV"\n", r2);
}
//printf("src_cte->pte = %"PRIxLVADDR"\n", src_cte->mapping_info.pte);
- printf("full vaddr of new mapping (entry = %"PRIuCSLOT"): 0x%"PRIxGENVADDR"\n",
- dest_slot, vaddr);
+ //printf("full vaddr of new mapping (entry = %"PRIuCSLOT"): 0x%"PRIxGENVADDR"\n",
+ // dest_slot, vaddr);
}
return r;
}
return copy_or_mint(root, args, false);
}
-
static struct sysret handle_delete_common(struct capability *root,
uintptr_t *args,
bool from_monitor)
};
}
+static struct sysret handle_modify_mapping(struct capability *mem,
+ int cmd, uintptr_t *args)
+{
+ size_t page_count = args[0];
+ uint64_t off = args[1];
+ return sys_modify_mapping(mem, page_count, off);
+}
+
static struct sysret handle_io(struct capability *to, int cmd, uintptr_t *args)
{
uint64_t port = args[0];
[DispatcherCmd_SetupGuest] = handle_dispatcher_setup_guest
},
[ObjType_Frame] = {
- [FrameCmd_Identify] = handle_frame_identify
+ [FrameCmd_Identify] = handle_frame_identify,
+ [FrameCmd_Modify_Mapping] = handle_modify_mapping,
},
[ObjType_DevFrame] = {
- [FrameCmd_Identify] = handle_frame_identify
+ [FrameCmd_Identify] = handle_frame_identify,
+ [FrameCmd_Modify_Mapping] = handle_modify_mapping,
},
[ObjType_CNode] = {
[CNodeCmd_Copy] = handle_copy,
},
[ObjType_VNode_x86_64_pml4] = {
[VNodeCmd_Unmap] = handle_unmap,
+ [FrameCmd_Modify_Mapping] = handle_modify_mapping,
},
[ObjType_VNode_x86_64_pdpt] = {
[VNodeCmd_Unmap] = handle_unmap,
+ [FrameCmd_Modify_Mapping] = handle_modify_mapping,
},
[ObjType_VNode_x86_64_pdir] = {
[VNodeCmd_Unmap] = handle_unmap,
+ [FrameCmd_Modify_Mapping] = handle_modify_mapping,
},
[ObjType_VNode_x86_64_ptable] = {
[VNodeCmd_Unmap] = handle_unmap,
+ [FrameCmd_Modify_Mapping] = handle_modify_mapping,
},
[ObjType_Kernel] = {
[KernelCmd_Spawn_core] = monitor_spawn_core,
struct mapping_info {
lvaddr_t pte; ///< where the capability is mapped
- size_t mapped_pages; ///< the amount of mapped pages
- size_t mapped_offset; ///< the offset into the physical region identified by the capability where the mapping begins.
+ size_t mapped_pages; ///< the amount of currently mapped pages
+ // target meta data
+ size_t page_count; ///< the targeted amount of mapped pages
+ uint64_t offset; ///< the offset into the physical region identified by the capability where the mapping begins.
};
struct cte;
sys_copy_or_mint(struct capability *root, capaddr_t destcn_cptr, cslot_t dest_slot,
capaddr_t source_cptr, int destcn_vbits, int source_vbits,
uintptr_t param1, uintptr_t param2, bool mint);
+struct sysret sys_modify_mapping(struct capability *mem, size_t page_count, uint64_t off);
struct sysret sys_delete(struct capability *root, capaddr_t cptr, uint8_t bits,
bool from_monitor);
struct sysret sys_revoke(struct capability *root, capaddr_t cptr, uint8_t bits,
#include <syscall.h>
#include <barrelfish_kpi/syscalls.h>
#include <capabilities.h>
+#include <cap_predicates.h>
#include <mdb/mdb.h>
#include <dispatch.h>
#include <wakeup.h>
#include <paging_kernel_helper.h>
+#include <paging_kernel_arch.h>
#include <exec.h>
#include <irq.h>
#include <trace/trace.h>
}
}
+static inline struct cte *cte_for_cap(struct capability *cap)
+{
+ return (struct cte *) (cap - offsetof(struct cte, cap));
+}
+
+struct sysret
+sys_modify_mapping(struct capability *mem, size_t page_count, uint64_t off)
+{
+ /* find cte belonging to cap */
+ struct cte *mem_cap = cte_for_cap(mem);
+ printf("0x%p, 0x%p\n", mem_cap, mem);
+
+ if (!type_is_vnode(mem->type) && mem->type != ObjType_Frame && mem->type != ObjType_DevFrame){
+ // this only works for mappable memory
+ return SYSRET(SYS_ERR_VNODE_TYPE);
+ }
+
+ genpaddr_t map_start = get_address(mem) + off;
+ genpaddr_t frame_end = get_address(mem) + get_size(mem);
+ size_t map_size = page_count*BASE_PAGE_SIZE;
+ if (map_start & BASE_PAGE_MASK) {
+ // return modify error if offset not aligned to base page size
+ return SYSRET(SYS_ERR_VM_MAP_START_UNALIGNED);
+ }
+ if ((map_start + map_size) > frame_end) {
+ // return modify error if offset + map_size after end of memory region
+ printf("map_start = 0x%"PRIxGENPADDR", map_size = %zd, frame_end = 0x%"PRIxGENPADDR"\n",
+ map_start, map_size, frame_end);
+ return SYSRET(SYS_ERR_VM_MAP_SIZE);
+ }
+ mem_cap->mapping_info.page_count = page_count;
+ mem_cap->mapping_info.offset = off;
+
+ return SYSRET(SYS_ERR_OK);
+}
+
struct sysret sys_delete(struct capability *root, capaddr_t cptr, uint8_t bits,
bool from_monitor)
{
return err_push(err, LIB_ERR_VNODE_CREATE);
}
- // TODO: setup mapping size
+ // setup mapping size
+ err = vm_modify_mapping(newvnode->u.vnode.cap, 1, 0);
+ if (err_is_fail(err)) {
+ printf("vm_modify_mapping returned an error: %s\n", err_getstring(err));
+ return err_push(err, LIB_ERR_VM_MODIFY_MAPPING);
+ }
// Map it
+ printf("\talloc_vnode calling vnode_map()\n");
err = vnode_map(root->u.vnode.cap, newvnode->u.vnode.cap, entry,
PTABLE_ACCESS_DEFAULT, 0);
if (err_is_fail(err)) {
errval_t err;
paging_x86_64_flags_t pmap_flags = vregion_to_pmap_flag(flags);
- // TODO: setup mapping info
+ // setup mapping info
+ size_t page_count = ROUND_UP(size, X86_64_BASE_PAGE_SIZE) / X86_64_BASE_PAGE_SIZE;
+ err = vm_modify_mapping(frame, page_count, offset);
+ if (err_is_fail(err)) {
+ printf("vm_modify_mapping returned an error: %s\n", err_getstring(err));
+ return err_push(err, LIB_ERR_VM_MODIFY_MAPPING);
+ }
for (size_t i = offset; i < offset + size; i += X86_64_BASE_PAGE_SIZE) {
// Map entry into the page table in the kernel
uint32_t entry = X86_64_PTABLE_BASE(vaddr);
- printf("mapping vaddr = 0x%"PRIxGENVADDR"\n", vaddr);
+ printf("\tdo_map calling vnode_map()\n");
err = vnode_map(ptable->u.vnode.cap, frame, entry, pmap_flags, i);
if (err_is_fail(err)) {
return err_push(err, LIB_ERR_VNODE_MAP);
// Remap with changed flags
paging_x86_64_flags_t pmap_flags = vregion_to_pmap_flag(flags);
+ printf("\tmodify_flags calling vnode_map()\n");
err = vnode_map(ptable->u.vnode.cap, vn->u.frame.cap, vn->entry,
pmap_flags, vn->u.frame.offset);
if (err_is_fail(err)) {