Add the following to all memory region variants:
- `is_empty()`: Return true if the region has zero size.
- `cap_size()`: Reduces the size if the given size < current.
- `shrink_start()`: Move start address forward, while shrinking the
region.
If a memory list begins at NULL, never give out that address. It trips
up UB checks, instead reserve the null page when that condition has been
detected.
Add `FrameAllocator::init_from_region`, which constructs a buddy frame
allocator over an explicit PhysMemoryRegion rather than the entire
memory span known to smalloc. This is a building block for managing
multiple disjoint memory pools (e.g. per-NUMA-node allocators).
Introduce Smalloc::claim_region, which removes a sub-region from the
free memory pool and transfers ownership to another allocator. The
region is punched out of the memory list rather than being added to the
reservation list.
The current tear down implementation assumes that all data mappings &
intermediate tables need to be free'd. That might not provide enough
flexibility for all tear-down scenarios.
Provide a more flexible API, passing current walk state into a control
function which makes a descision regarding tear-down and recursion.
The `SmallocPageAlloc` type is generic and architecture-independent, so
it belongs in libkernel rather than the kernel's arm64-specific code. It
is placed in memory::paging::smalloc_page_allocator and gated by the
existing paging feature.
The kernel's copy is replaced with a thin re-export so all call sites
are unaffected.
Since the only requirement for a `PageOffsetTranslator` is a constant
offset, pass that in as a generic parameter, allowing it to be decoupled
from the `VirtualMemory` trait.
The generic RecursiveWalker computed the coverage region for each
page-table entry as:
VirtMemoryRegion::new(entry_va, table_coverage).intersection(region)
For the last entry at the PML4 level (PML4[511]) in the kernel
high-half, entry_va + table_coverage wraps past usize::MAX, causing an
arithmetic overflow panic inside end_address().
Fix this in walk.rs by computing the intersection bounds with
saturating_add/min/max directly.
Add regression tests for all levels, ensuring last-element walking is
correct.
Move the NextLevel AT into the TableMapper (descriptor-level) trait.
This allows us to provide a blanket implementation of TableMapperTable
for all tables where, Table::Descriptor : TableMapper.
Since the architectural details of descriptor implementation is hidden
behind traits, the code for walking page tables is arch-agnostic.
Therefore, promote it to shared code for use by other architectures.
Bit 7 on various descriptors in x86_64 can take on varying values
depending upon the descriptor type. Refelect that in the implementation
and fix a bug whereby the PAT bit would have been set when creating a
PTE.
The test harness code is useful across architectures. Therefore, move it
out of the arm64 directory so it can be used by other architectures
implementing paging unit-tests.
We currently define the MAP_SHIFT for a page-table level in two places,
`TableMapper` and `PgTable`. Store only one shift trait constant value
in the `PageTableEntry` trait.
Any traits which are architecture agnostic should be available to be
implemented by other architectures. Move them out from the arm64 module
into a non-architecure specific location.
Move PtePermissions to paging module which is feature-gated behind
`paging`.
Also move all AddressSpace related functionality behind the `proc_vm`
feature gate.