vm: add vm-region to manage userspace virtual memory address spaces

vm-region supports creating nested regions of virtual memory, each with their
own memory protection restrictions.

vm-objects can be mapped into a vm-region, making the underlying memory
accessible. all mappings are lazy: page tables are not updated until the
mapped memory is accessed.
This commit is contained in:
2026-02-08 12:59:08 +00:00
parent b8ccffd2d4
commit 883b5ac9e2
3 changed files with 831 additions and 0 deletions

126
include/mango/vm-region.h Normal file
View File

@@ -0,0 +1,126 @@
#ifndef MANGO_VM_REGION_H_
#define MANGO_VM_REGION_H_
#include <mango/object.h>
#include <mango/pmap.h>
#include <mango/vm.h>
#define VM_REGION_NAME_MAX 64
#define VM_REGION_ANY_MAP_ADDRESS ((virt_addr_t) - 1)
struct vm_region;
struct vm_object;
enum vm_region_entry_type {
VM_REGION_ENTRY_NONE = 0,
VM_REGION_ENTRY_REGION,
VM_REGION_ENTRY_MAPPING,
};
struct vm_region_entry {
struct btree_node e_node;
struct vm_region_entry *e_parent;
enum vm_region_entry_type e_type;
/* absolute virtual address of the entry */
virt_addr_t e_base_address;
/* size of the entry in bytes */
size_t e_size;
};
struct vm_region_mapping {
struct vm_region_entry m_entry;
struct vm_object *m_object;
/* used to link to vm_object->vo_mappings */
struct queue_entry m_object_entry;
enum vm_prot m_prot;
/* offset in bytes to the start of the object data that was mapped */
off_t m_object_offset;
};
struct vm_region {
struct object vr_base;
struct vm_region_entry vr_entry;
char vr_name[VM_REGION_NAME_MAX];
/* btree of struct vm_region_entry.
* sibling entries cannot overlap each other, and child entries must
* be entirely contained within their immediate parent entry. */
struct btree vr_entries;
/* memory protection restriction mask.
* any mapping in this region, or any of its children, cannot use
* protection flags that are not set in this mask.
* for example, if VM_PROT_EXEC is /not/ set here, no mapping
* can be created in this region or any child region with VM_PROT_EXEC
* set. */
enum vm_prot vr_prot;
/* the physical address space in which mappings in this region (and
* its children) are created */
pmap_t vr_pmap;
};
extern kern_status_t vm_region_type_init(void);
extern kern_status_t vm_region_create(
struct vm_region *parent,
const char *name,
virt_addr_t base,
size_t len,
enum vm_prot prot,
struct vm_region **out);
/* find the child region that has jurisdiction over the specified virtual
* address. returns the lowest-nested region that covers the specified virtual
* address. */
extern struct vm_region *vm_region_find_child(
struct vm_region *region,
virt_addr_t addr);
/* find the child region that has jurisdiction over the specified virtual
* address area. returns the lowest-nested region that covers the specified
* virtual address area. the area must be fully contained within a region, with
* no partial overlaps. if an area is covered by multiple regions, or is only
* partially within a region, returns NULL. */
extern struct vm_region *vm_region_find_child_for_area(
struct vm_region *region,
virt_addr_t addr,
size_t len);
extern struct vm_region_mapping *vm_region_find_mapping(
struct vm_region *region,
virt_addr_t addr);
extern kern_status_t vm_region_map_object(
struct vm_region *region,
virt_addr_t map_address,
struct vm_object *object,
off_t object_offset,
size_t length,
enum vm_prot prot,
virt_addr_t *out);
/* returns true if the memory area defined by [base, base+len] contains:
* - no child regions
* - no vm_object mappings
* if any child regions or mappings exist in the memory area, returns false.
* if the memory area exceeds the bounds of the region, returns false.
*/
extern bool vm_region_is_area_free(
const struct vm_region *region,
virt_addr_t base,
size_t len);
extern kern_status_t vm_region_demand_map(
struct vm_region *region,
virt_addr_t addr,
enum pmap_fault_flags flags);
extern void vm_region_dump(struct vm_region *region, int depth);
DEFINE_OBJECT_LOCK_FUNCTION(vm_region, vr_base)
#endif