feat: add pmm, add vmm, add allocator, create memory management foundation
This commit is contained in:
128
kernel/src/mem/pmm.rs
Normal file
128
kernel/src/mem/pmm.rs
Normal file
@@ -0,0 +1,128 @@
|
||||
use crate::mem::address::{PhysAddr};
|
||||
|
||||
pub const PAGE_SIZE: u64 = 4096;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct BitmapPMM {
|
||||
bitmap: &'static mut [u8],
|
||||
total_pages: usize,
|
||||
used_pages: usize,
|
||||
last_idx: usize,
|
||||
}
|
||||
|
||||
static mut PMM: Option<BitmapPMM> = None;
|
||||
|
||||
impl BitmapPMM {
|
||||
#[allow(dead_code)]
|
||||
pub fn used_pages(&self) -> usize { self.used_pages }
|
||||
#[allow(dead_code)]
|
||||
pub fn total_pages(&self) -> usize { self.total_pages }
|
||||
|
||||
pub unsafe fn init(mmap: &limine::response::MemoryMapResponse, hhdm_offset: u64) {
|
||||
let max_addr = mmap.entries().iter()
|
||||
.map(|e| e.base + e.length)
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
|
||||
let total_pages = (max_addr / PAGE_SIZE) as usize;
|
||||
let bitmap_size = total_pages.div_ceil(8);
|
||||
|
||||
let bitmap_phys_addr = mmap.entries().iter()
|
||||
.find(|e| e.entry_type == limine::memory_map::EntryType::USABLE && e.length >= bitmap_size as u64)
|
||||
.map(|e| e.base)
|
||||
.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);
|
||||
|
||||
let mut pmm = Self {
|
||||
bitmap: bitmap_slice,
|
||||
total_pages,
|
||||
used_pages: total_pages,
|
||||
last_idx: 0,
|
||||
};
|
||||
|
||||
for entry in mmap.entries() {
|
||||
if entry.entry_type == limine::memory_map::EntryType::USABLE {
|
||||
for addr in (entry.base..entry.base + entry.length).step_by(PAGE_SIZE as usize) {
|
||||
pmm.free_frame(PhysAddr(addr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for addr in (bitmap_phys_addr..bitmap_phys_addr + bitmap_size as u64).step_by(PAGE_SIZE as usize) {
|
||||
pmm.lock_frame(PhysAddr(addr));
|
||||
}
|
||||
|
||||
pmm.lock_frame(PhysAddr(0));
|
||||
|
||||
unsafe {
|
||||
core::ptr::write(core::ptr::addr_of_mut!(PMM), Some(pmm));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn free_frame(&mut self, phys_addr: PhysAddr) {
|
||||
let idx = (phys_addr.0 / PAGE_SIZE) as usize;
|
||||
if idx < self.total_pages {
|
||||
let byte_idx = idx / 8;
|
||||
let bit_idx = idx % 8;
|
||||
if (self.bitmap[byte_idx] & (1 << bit_idx)) != 0 {
|
||||
self.bitmap[byte_idx] &= !(1 << bit_idx);
|
||||
self.used_pages -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lock_frame(&mut self, phys_addr: PhysAddr) {
|
||||
let idx = (phys_addr.0 / PAGE_SIZE) as usize;
|
||||
if idx < self.total_pages {
|
||||
let byte_idx = idx / 8;
|
||||
let bit_idx = idx % 8;
|
||||
if (self.bitmap[byte_idx] & (1 << bit_idx)) == 0 {
|
||||
self.bitmap[byte_idx] |= 1 << bit_idx;
|
||||
self.used_pages += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
#[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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user