feat: implement capability-based memory management foundation

This commit is contained in:
Faynot
2026-05-05 01:30:16 +03:00
parent a45587042b
commit d542b5586d
8 changed files with 200 additions and 80 deletions

View File

@@ -12,8 +12,5 @@ pub fn init(memmap: &limine::response::MemoryMapResponse, hhdm_offset: u64) {
#[allow(dead_code)]
pub fn get_stats() -> (usize, usize) {
unsafe {
let pmm = pmm::get_pmm_unchecked();
(pmm.used_pages(), pmm.total_pages())
}
pmm::get_stats()
}

View File

@@ -2,6 +2,7 @@ use crate::mem::address::{PhysAddr, VirtAddr};
use crate::mem::pmm;
use core::arch::asm;
use bitflags::bitflags;
use crate::mem::pmm::PMM;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -63,10 +64,11 @@ impl PageTable {
}
}
fn get_or_create_next_table(&mut self, index: usize, hhdm: u64) -> &mut Self {
fn get_or_create_next_table(&mut self, index: usize, hhdm: u64) -> &mut Self {
if self.entries[index] & PageTableFlags::PRESENT.bits() == 0 {
let pt_phys = pmm::alloc_page().expect("VMM: Table allocation failed");
let pt_phys = pmm_alloc().expect("VMM: Out of memory for page tables");
let pt_virt = pt_phys.to_virt(hhdm);
unsafe { core::ptr::write_bytes(pt_virt.as_mut_ptr::<u8>(), 0, 4096); }
self.entries[index] = pt_phys.0 | (PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::USER).bits();
@@ -75,3 +77,8 @@ impl PageTable {
unsafe { &mut *next_pt_phys.to_virt(hhdm).as_mut_ptr() }
}
}
pub fn pmm_alloc() -> Option<PhysAddr> {
PMM.lock().as_mut()?.alloc_frame()
}

View File

@@ -0,0 +1,25 @@
use crate::cap::{Capability, CapObject, Relation, CapRights};
use crate::mem::address::PhysAddr;
pub struct PMActor {
pub root_untyped: Capability,
pub managed_range: (PhysAddr, PhysAddr),
}
impl PMActor {
pub fn carve_region(&self, offset: usize, size: usize) -> Capability {
if let CapObject::Memory { phys, .. } = self.root_untyped.object {
Capability {
object: CapObject::Memory {
phys: PhysAddr(phys.0 + offset as u64),
size_pages: size / 4096,
},
rights: CapRights::READ | CapRights::WRITE | CapRights::GRANT,
relation: Relation::Strong,
token_sig: 0xDEAD_BEEF,
}
} else {
panic!("PM: Root is not memory!");
}
}
}

View File

@@ -1,8 +1,8 @@
use crate::mem::address::{PhysAddr};
use crate::mem::address::PhysAddr;
use crate::mem::allocator::Locked;
pub const PAGE_SIZE: u64 = 4096;
#[allow(dead_code)]
pub struct BitmapPMM {
bitmap: &'static mut [u8],
total_pages: usize,
@@ -10,7 +10,7 @@ pub struct BitmapPMM {
last_idx: usize,
}
static mut PMM: Option<BitmapPMM> = None;
pub static PMM: Locked<Option<BitmapPMM>> = Locked::new(None);
impl BitmapPMM {
#[allow(dead_code)]
@@ -33,7 +33,6 @@ impl BitmapPMM {
.expect("PMM: Insufficient memory for bitmap");
let bitmap_virt_ptr = (bitmap_phys_addr + hhdm_offset) as *mut u8;
// Оборачиваем небезопасные операции
let bitmap_slice = unsafe { core::slice::from_raw_parts_mut(bitmap_virt_ptr, bitmap_size) };
bitmap_slice.fill(0xFF);
@@ -58,9 +57,7 @@ impl BitmapPMM {
pmm.lock_frame(PhysAddr(0));
unsafe {
core::ptr::write(core::ptr::addr_of_mut!(PMM), Some(pmm));
}
*PMM.lock() = Some(pmm);
}
pub fn free_frame(&mut self, phys_addr: PhysAddr) {
@@ -87,42 +84,48 @@ impl BitmapPMM {
}
}
pub fn alloc_frame(&mut self) -> Option<PhysAddr> {
for i in self.last_idx..self.total_pages {
let byte_idx = i / 8;
if self.bitmap[byte_idx] == 0xFF { continue; }
let bit_idx = i % 8;
if (self.bitmap[byte_idx] & (1 << bit_idx)) == 0 {
let addr = PhysAddr(i as u64 * PAGE_SIZE);
self.lock_frame(addr);
self.last_idx = i;
return Some(addr);
pub fn alloc_frame(&mut self) -> Option<PhysAddr> {
let start_byte = self.last_idx / 8;
for i in start_byte..(self.bitmap.len()) {
if self.bitmap[i] != 0xFF {
for bit in 0..8 {
let idx = i * 8 + bit;
if idx >= self.total_pages { return None; }
let addr = PhysAddr(idx as u64 * PAGE_SIZE);
if !self.is_locked(addr) {
self.lock_frame(addr);
self.last_idx = idx;
return Some(addr);
}
}
}
}
None
}
}
#[allow(dead_code)]
pub unsafe fn get_pmm_unchecked() -> &'static BitmapPMM {
let pmm_ptr = core::ptr::addr_of!(PMM);
unsafe { (*pmm_ptr).as_ref().expect("PMM: Not initialized") }
}
pub fn alloc_page() -> Option<PhysAddr> {
unsafe {
let pmm_ptr = core::ptr::addr_of_mut!(PMM);
(*pmm_ptr).as_mut()?.alloc_frame()
#[inline]
fn is_locked(&self, addr: PhysAddr) -> bool {
let idx = (addr.0 / PAGE_SIZE) as usize;
(self.bitmap[idx / 8] & (1 << (idx % 8))) != 0
}
}
#[allow(dead_code)]
pub fn free_page(addr: PhysAddr) {
unsafe {
let pmm_ptr = core::ptr::addr_of_mut!(PMM);
if let Some(pmm) = (*pmm_ptr).as_mut() {
pmm.free_frame(addr);
}
pub fn alloc_frame() -> Option<PhysAddr> {
PMM.lock().as_mut()?.alloc_frame()
}
pub fn free_frame(addr: PhysAddr) {
if let Some(pmm) = PMM.lock().as_mut() {
pmm.free_frame(addr);
}
}
pub fn get_stats() -> (usize, usize) {
if let Some(pmm) = PMM.lock().as_ref() {
(pmm.used_pages(), pmm.total_pages())
} else {
(0, 0)
}
}