/// Create page mappings errval_t caps_copy_to_vnode(struct cte *dest_vnode_cte, cslot_t dest_slot, struct cte *src_cte, uintptr_t flags, uintptr_t offset, uintptr_t pte_count, struct cte *mapping_cte) { struct capability *src_cap = &src_cte->cap; struct capability *dest_cap = &dest_vnode_cte->cap; assert(mapping_cte->cap.type == ObjType_Null); mapping_handler_t handler_func = handler[dest_cap->type]; assert(handler_func != NULL); errval_t err; err = handler_func(dest_cap, dest_slot, src_cap, flags, offset, pte_count, mapping_cte); if (err_is_fail(err)) { assert(mapping_cte->cap.type == ObjType_Null); debug(SUBSYS_PAGING, "caps_copy_to_vnode: handler func returned %"PRIuERRV"\n", err); return err; } /* insert mapping cap into mdb */ err = mdb_insert(mapping_cte); if (err_is_fail(err)) { printk(LOG_ERR, "%s: mdb_insert: %"PRIuERRV"\n", __FUNCTION__, err); } TRACE_CAP_MSG("created", mapping_cte); return err; }
/// Create page mappings errval_t caps_copy_to_vnode(struct cte *dest_vnode_cte, cslot_t dest_slot, struct cte *src_cte, uintptr_t flags, uintptr_t offset, uintptr_t pte_count, struct cte *mapping_cte) { assert(type_is_vnode(dest_vnode_cte->cap.type)); assert(mapping_cte->cap.type == ObjType_Null); struct capability *src_cap = &src_cte->cap; struct capability *dest_cap = &dest_vnode_cte->cap; mapping_handler_t handler_func = handler[dest_cap->type]; assert(handler_func != NULL); cslot_t last_slot = dest_slot + pte_count; // TODO: PAE if (last_slot > X86_32_PTABLE_SIZE) { // requested map overlaps leaf page table debug(SUBSYS_CAPS, "caps_copy_to_vnode: requested mapping spans multiple leaf page tables\n"); return SYS_ERR_VM_RETRY_SINGLE; } errval_t r = handler_func(dest_cap, dest_slot, src_cap, flags, offset, pte_count, mapping_cte); if (err_is_fail(r)) { assert(mapping_cte->cap.type == ObjType_Null); debug(SUBSYS_PAGING, "caps_copy_to_vnode: handler func returned %d\n", r); return r; } /* insert mapping cap into mdb */ errval_t err = mdb_insert(mapping_cte); if (err_is_fail(err)) { printk(LOG_ERR, "%s: mdb_insert: %"PRIuERRV"\n", __FUNCTION__, err); } TRACE_CAP_MSG("created", mapping_cte); return err; }
/** * \brief Cleanup the last cap copy for an object and the object itself */ static errval_t cleanup_last(struct cte *cte, struct cte *ret_ram_cap) { errval_t err; TRACE_CAP_MSG("cleaning up last copy", cte); struct capability *cap = &cte->cap; assert(!has_copies(cte)); if (cte->mdbnode.remote_copies) { printk(LOG_WARN, "cleanup_last but remote_copies is set\n"); } if (ret_ram_cap && ret_ram_cap->cap.type != ObjType_Null) { return SYS_ERR_SLOT_IN_USE; } struct RAM ram = { .bits = 0 }; size_t len = sizeof(struct RAM) / sizeof(uintptr_t) + 1; if (!has_descendants(cte) && !has_ancestors(cte)) { // List all RAM-backed capabilities here // NB: ObjType_PhysAddr and ObjType_DevFrame caps are *not* RAM-backed! switch(cap->type) { case ObjType_RAM: ram.base = cap->u.ram.base; ram.bits = cap->u.ram.bits; break; case ObjType_Frame: ram.base = cap->u.frame.base; ram.bits = cap->u.frame.bits; break; case ObjType_CNode: ram.base = cap->u.cnode.cnode; ram.bits = cap->u.cnode.bits + OBJBITS_CTE; break; case ObjType_Dispatcher: // Convert to genpaddr ram.base = local_phys_to_gen_phys(mem_to_local_phys((lvaddr_t)cap->u.dispatcher.dcb)); ram.bits = OBJBITS_DISPATCHER; break; default: // Handle VNodes here if(type_is_vnode(cap->type)) { ram.base = get_address(cap); ram.bits = vnode_objbits(cap->type); } break; } } err = cleanup_copy(cte); if (err_is_fail(err)) { return err; } if(ram.bits > 0) { // Send back as RAM cap to monitor if (ret_ram_cap) { if (dcb_current != monitor_ep.u.endpoint.listener) { printk(LOG_WARN, "sending fresh ram cap to non-monitor?\n"); } assert(ret_ram_cap->cap.type == ObjType_Null); ret_ram_cap->cap.u.ram = ram; ret_ram_cap->cap.type = ObjType_RAM; err = mdb_insert(ret_ram_cap); TRACE_CAP_MSG("reclaimed", ret_ram_cap); assert(err_is_ok(err)); // note: this is a "success" code! err = SYS_ERR_RAM_CAP_CREATED; } else if (monitor_ep.type && monitor_ep.u.endpoint.listener != 0) { #ifdef TRACE_PMEM_CAPS struct cte ramcte; memset(&ramcte, 0, sizeof(ramcte)); ramcte.cap.u.ram = ram; ramcte.cap.type = ObjType_RAM; TRACE_CAP_MSG("reclaimed", ret_ram_cap); #endif // XXX: This looks pretty ugly. We need an interface. err = lmp_deliver_payload(&monitor_ep, NULL, (uintptr_t *)&ram, len, false); } else { printk(LOG_WARN, "dropping ram cap base %08"PRIxGENPADDR" bits %"PRIu8"\n", ram.base, ram.bits); } if (err_no(err) == SYS_ERR_LMP_BUF_OVERFLOW) { printk(LOG_WARN, "dropped ram cap base %08"PRIxGENPADDR" bits %"PRIu8"\n", ram.base, ram.bits); err = SYS_ERR_OK; } else { assert(err_is_ok(err)); } } return err; } /* * Mark phase of revoke mark & sweep */ static void caps_mark_revoke_copy(struct cte *cte) { errval_t err; err = caps_try_delete(cte); if (err_is_fail(err)) { // this should not happen as there is a copy of the cap panic("error while marking/deleting cap copy for revoke:" " 0x%"PRIuERRV"\n", err); } }