From 921c91c02abdee43335f704891fa5df47eb55e07 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Thu, 12 Mar 2026 20:39:28 +0000 Subject: [PATCH] vm: add vm-controller object --- include/kernel/syscall.h | 4 ++ include/kernel/vm-controller.h | 68 +++++++++++++++++++ libmango/include-user/mango/vm.h | 25 +++++++ vm/vm-controller.c | 112 +++++++++++++++++++++++++++++++ 4 files changed, 209 insertions(+) create mode 100644 include/kernel/vm-controller.h create mode 100644 vm/vm-controller.c diff --git a/include/kernel/syscall.h b/include/kernel/syscall.h index 4bbcdb8..c71fe74 100644 --- a/include/kernel/syscall.h +++ b/include/kernel/syscall.h @@ -176,6 +176,10 @@ extern kern_status_t sys_msg_write( size_t nr_in, size_t *nr_written); +extern kern_status_t sys_kern_object_wait( + kern_wait_item_t *items, + size_t nr_items); + extern virt_addr_t syscall_get_function(unsigned int sysid); #endif diff --git a/include/kernel/vm-controller.h b/include/kernel/vm-controller.h new file mode 100644 index 0000000..e5b88ac --- /dev/null +++ b/include/kernel/vm-controller.h @@ -0,0 +1,68 @@ +#ifndef KERNEL_VM_CONTROLLER_H_ +#define KERNEL_VM_CONTROLLER_H_ + +#include +#include +#include + +struct thread; +struct equeue; +struct vm_object; + +enum page_request_status { + PAGE_REQUEST_PENDING = 0, + PAGE_REQUEST_IN_PROGRESS, + PAGE_REQUEST_COMPLETE, +}; + +struct vm_controller { + struct object vc_base; + /* tree of struct vm_objects bound to this controller, keyed with the + * vm_key_t specified when the object(s) were created. */ + struct btree vc_objects; + /* tree of pending page requests */ + struct btree vc_requests; +}; + +struct page_request { + uint64_t req_id; + enum page_request_status req_status; + kern_status_t req_result; + struct vm_object *req_object; + struct thread *req_sender; + struct btree_node req_node; + off_t req_offset; + size_t req_length; +}; + +extern kern_status_t vm_controller_type_init(void); +extern struct vm_controller *vm_controller_cast(struct object *obj); + +extern struct vm_controller *vm_controller_create(void); + +extern kern_status_t vm_controller_recv( + struct vm_controller *ctrl, + equeue_packet_page_request_t *out); +extern kern_status_t vm_controller_recv_async( + struct vm_controller *ctrl, + struct equeue *eq); + +extern kern_status_t vm_controller_create_object( + struct vm_controller *ctrl, + const char *name, + size_t name_len, + equeue_key_t key, + size_t data_len, + vm_prot_t prot, + struct vm_object **out); +extern kern_status_t vm_controller_detach_object( + struct vm_controller *ctrl, + struct vm_object *vmo); + +extern kern_status_t vm_controller_send_request( + struct vm_controller *ctrl, + struct page_request *req); + +DEFINE_OBJECT_LOCK_FUNCTION(vm_controller, vc_base) + +#endif diff --git a/libmango/include-user/mango/vm.h b/libmango/include-user/mango/vm.h index d044291..ebf1d74 100644 --- a/libmango/include-user/mango/vm.h +++ b/libmango/include-user/mango/vm.h @@ -77,4 +77,29 @@ extern kern_status_t vm_region_unmap_relative( off_t offset, size_t length); +extern kern_status_t vm_controller_create(kern_handle_t *out); +extern kern_status_t vm_controller_recv( + kern_handle_t ctrl, + equeue_packet_page_request_t *out); +extern kern_status_t vm_controller_recv_async( + kern_handle_t ctrl, + kern_handle_t eq); +extern kern_status_t vm_controller_create_object( + kern_handle_t ctrl, + const char *name, + size_t name_len, + size_t data_len, + vm_prot_t prot, + kern_handle_t *out); +extern kern_status_t vm_controller_detach_object( + kern_handle_t ctrl, + kern_handle_t vmo); +extern kern_status_t vm_controller_supply_pages( + kern_handle_t ctrl, + kern_handle_t dst_vmo, + off_t dst_offset, + kern_handle_t src_vmo, + off_t src_offset, + size_t length); + #endif diff --git a/vm/vm-controller.c b/vm/vm-controller.c new file mode 100644 index 0000000..6ceaa39 --- /dev/null +++ b/vm/vm-controller.c @@ -0,0 +1,112 @@ +#include +#include +#include +#include + +kern_status_t vm_controller_type_init(void) +{ + return KERN_UNIMPLEMENTED; +} + +struct vm_controller *vm_controller_cast(struct object *obj) +{ + return NULL; +} + +struct vm_controller *vm_controller_create(void) +{ + return NULL; +} + +kern_status_t vm_controller_create_object( + struct vm_controller *ctrl, + const char *name, + size_t name_len, + equeue_key_t key, + size_t data_len, + vm_prot_t prot, + struct vm_object **out) +{ + return KERN_UNIMPLEMENTED; +} + +kern_status_t vm_controller_detach_object( + struct vm_controller *ctrl, + struct vm_object *vmo) +{ + return KERN_UNIMPLEMENTED; +} + +static kern_status_t try_enqueue(struct btree *tree, struct page_request *req) +{ + if (!tree->b_root) { + tree->b_root = &req->req_node; + btree_insert_fixup(tree, &req->req_node); + return true; + } + + struct btree_node *cur = tree->b_root; + while (1) { + struct page_request *cur_node + = BTREE_CONTAINER(struct page_request, req_node, cur); + struct btree_node *next = NULL; + + if (req->req_id > cur_node->req_id) { + next = btree_right(cur); + + if (!next) { + btree_put_right(cur, &req->req_node); + break; + } + } else if (req->req_id < cur_node->req_id) { + next = btree_left(cur); + + if (!next) { + btree_put_left(cur, &req->req_node); + break; + } + } else { + return false; + } + + cur = next; + } + + btree_insert_fixup(tree, &req->req_node); + return true; +} + +static void wait_for_reply( + struct vm_controller *ctrl, + struct page_request *req, + unsigned long *lock_flags) +{ + struct wait_item waiter; + struct thread *self = current_thread(); + + wait_item_init(&waiter, self); + for (;;) { + self->tr_state = THREAD_SLEEPING; + if (req->req_status == PAGE_REQUEST_COMPLETE) { + break; + } + + vm_controller_unlock_irqrestore(ctrl, *lock_flags); + schedule(SCHED_NORMAL); + vm_controller_lock_irqsave(ctrl, lock_flags); + } + + self->tr_state = THREAD_READY; +} + +kern_status_t vm_controller_send_request( + struct vm_controller *ctrl, + struct page_request *req) +{ + fill_random(&req->req_id, sizeof req->req_id); + while (!try_enqueue(&ctrl->vc_requests, req)) { + req->req_id++; + } + + return KERN_OK; +}