From a0a6a061a489a40256b2c62c7341a32bb85211e8 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Tue, 24 Mar 2026 20:24:12 +0000 Subject: [PATCH] vm: controller: add an auto-detach flag for vm-objects --- include/kernel/vm-object.h | 10 ++++++++-- vm/address-space.c | 31 ++++++++++++++++++++++++++----- vm/vm-controller.c | 3 ++- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/include/kernel/vm-object.h b/include/kernel/vm-object.h index a5137d9..30a98f8 100644 --- a/include/kernel/vm-object.h +++ b/include/kernel/vm-object.h @@ -14,19 +14,25 @@ enum vm_object_flags { VMO_IN_PLACE = 0x01u, /* this vm-object is/was attached to a vm-controller */ VMO_CONTROLLER = 0x02u, + /* when a vm-object is attached to a controller, and the ref-count of + * the object falls to one (i.e. the last reference is the handle to + * the object held by the server that created it), the object will + * be detached, allowing the server to close the last handle to the + * object and dispose of it. */ + VMO_AUTO_DETACH = 0x04u, /* these flags are for use with vm_object_get_page */ /**************************************************/ /* if the relevant page hasn't been allocated yet, it will be allocated * and returned. if this flag isn't specified, NULL will be returned. */ - VMO_ALLOCATE_MISSING_PAGE = 0x04u, + VMO_ALLOCATE_MISSING_PAGE = 0x08u, /* if the vm-object is attached to a vm-controller, and the relevant * page is uncommitted, send a request to the vm-controller to provide * the missing page. will result in the vm-object being unlocked and * the current thread sleeping until the request is fulfilled. the * vm-object will be re-locked before the function returns. */ - VMO_REQUEST_MISSING_PAGE = 0x08u, + VMO_REQUEST_MISSING_PAGE = 0x10u, }; struct vm_object { diff --git a/vm/address-space.c b/vm/address-space.c index 2b3cf2a..891fca7 100644 --- a/vm/address-space.c +++ b/vm/address-space.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -721,6 +722,9 @@ kern_status_t address_space_map( } tracek("address_space_map(%zx, %zx)", map_address, length); + if (map_address == 0xc6a55000) { + printk("break"); + } if (!root || !object) { tracek("null pointer"); @@ -838,7 +842,7 @@ static kern_status_t split_area( put_entry(&root->s_mappings, right); for (size_t i = unmap_base; i < unmap_limit; i += VM_PAGE_SIZE) { - tracek("unmapping %zx", i); + tracek("pmap_remove %zx", i); pmap_remove(root->s_pmap, i); } @@ -875,7 +879,7 @@ static kern_status_t left_reduce_area( return KERN_OK; } - tracek(" unmapping %zx-%zx (%zx bytes)", base, base + length, length); + tracek(" pmap_remove %zx-%zx (%zx bytes)", base, base + length, length); for (size_t i = base; i < limit; i += VM_PAGE_SIZE) { pmap_remove(root->s_pmap, i); } @@ -912,7 +916,7 @@ static kern_status_t right_reduce_area( return KERN_OK; } - tracek(" unmapping %zx-%zx (%zx bytes)", base, base + length, length); + tracek(" pmap_remove %zx-%zx (%zx bytes)", base, base + length, length); for (size_t i = base; i < limit; i += VM_PAGE_SIZE) { pmap_remove(root->s_pmap, i); } @@ -930,9 +934,10 @@ static kern_status_t delete_area( return KERN_OK; } - tracek("delete mapping [%zx-%zx]", + tracek("delete mapping [%zx-%zx] (%zx bytes)", mapping->vma_base, - mapping->vma_limit); + mapping->vma_limit, + mapping->vma_limit - mapping->vma_base); for (size_t i = mapping->vma_base; i < mapping->vma_limit; i += VM_PAGE_SIZE) { @@ -946,7 +951,23 @@ static kern_status_t delete_area( &mapping->vma_object->vo_mappings, &mapping->vma_object_entry); mapping->vma_object = NULL; + /* if the object is attached to a controller and the ref-count is 2, + * then the only other remaining reference to this object is held by + * the controller. */ + struct vm_controller *ctrl = object->vo_ctrl; + bool detach = ctrl != NULL && object->vo_base.ob_refcount == 2 + && (object->vo_flags & VMO_AUTO_DETACH); vm_object_unlock_irqrestore(object, flags); + + if (detach) { + /* TODO find a better way to achieve this, and/or give the + * server that created the object more control over when it + * should be detached */ + vm_controller_lock_irqsave(ctrl, &flags); + vm_controller_detach_object(ctrl, object); + vm_controller_unlock_irqrestore(ctrl, flags); + } + object_unref(&object->vo_base); /* don't actually delete the mapping yet. that will be done by diff --git a/vm/vm-controller.c b/vm/vm-controller.c index 36d503d..15d8a18 100644 --- a/vm/vm-controller.c +++ b/vm/vm-controller.c @@ -198,7 +198,8 @@ kern_status_t vm_controller_create_object( object_ref(&ctrl->vc_base); - vmo->vo_flags |= VMO_CONTROLLER; + /* TODO expose the VMO_AUTO_DETACH flag to userspace */ + vmo->vo_flags |= VMO_CONTROLLER | VMO_AUTO_DETACH; vmo->vo_ctrl = ctrl; vmo->vo_key = key;