## Jove Physical Memory Managment Memory in the Jove kernel is managed by `JOVE_OBJ_REGION` objects which represent a contiguous span of physical memory page frames that can be split into sub-region objects or spawn page-sized `JOVE_OBJ_UNTYPED` objects. Each `JOVE_OBJ_REGION` object is represented in a doubly-linked list datastructure sorted by physical address. ### Reasoning Microkernels need a way to delegate memory alloc and free to userspace programs. Therefore microkernels need to pass information about the available memory regions and provide systems to allocate and release page frames quickly, atomically, and efficiently. For Jove, initially the plan was to represent free pages using untyped objects. However this system would require extensive userspace book-keeping per allocation. To fix this problem, Jove uses "Memory region" objects, which control an allocation bitmap per page-frame so that every allocation is marked and traceable back to any specific region. If a user program tries to free a marked page, it's easy to trace that page back to the allocated region and mark it as released. ### Interface The following functions are made available to user programs through system calls: ``` physaddr_t region_base(jove_owned_obj_t *region_obj); ``` Returns the physical address marking the start of the physical region. ``` unsigned int region_pages(jove_owned_obj_t *region_obj); ``` Returns the total number of pages referenced by the physical region. ``` unsigned int region_freepages(jove_owned_obj_t *region_obj); ``` Returns the number of pages freely alloc-able by the physical region. ``` int region_split(jove_owned_obj_t *source_obj, jove_owned_obj_t *dest_obj, size_t pages); ``` Splits off a new memory region from the source region into the destination object sized by some number of pages. If `pages == 0`, then the kernel will return `-EBADSIZE`. If `pages % JOVE_REGION_GRANULARITY != 0`, then the kernel will return `-EBADSIZE`. If `pages > region_pages(source_obj)`, then the kernel will return `-ETOOBIG`. If `region_pages(source_obj) - pages == 0`, then the kernel will return `-ETOOBIG`. If the source region's mutex is taken, then the kernel will return `-EBUSY`. The final region will be sized for `pages` pages with 1 or more pages marked taken for the region overhead. ``` int region_release(jove_owned_obj_t *region_obj); ``` Returns a sub-region to a super region. Does not remove page allocations. If the region object is a top-level region, then the kernel will return `-EPERM`. If the region object has sub-regions, the kernel will return `-EBUSY`. If the region object's mutex is locked, the kernel will return `-EBUSY`. If the super region's mutex is locked, the kernel will return `-EBUSY`. ``` int region_alloc(jove_owned_obj_t *region_obj, jove_owned_obj_t *dest_obj); ``` Tries to allocate an untyped page frame from the region object into the dest object. If the region's mutex is locked, the kernel will return `-EBUSY`. If the region has no free pages, the kernel will return `-EFULL`. If the region's bitmap was unable to find an allocable page, the kernel will return `-EFULL`. The new page object will be a `JOVE_OBJ_UNTYPED` object aligned and sized to `0x1000`. ``` int region_alloc_contig(jove_owned_obj_t *region_obj, jove_owned_obj_t *dest_obj, size_t pages); ```