Files
CappuccinOS/src/mem/mod.rs

162 lines
4.2 KiB
Rust
Executable File

pub mod allocator;
pub mod pmm;
use core::alloc::GlobalAlloc;
use limine::{MemmapEntry, NonNullPtr};
use crate::{
libs::{lazy::Lazy, mutex::Mutex},
usr::tty::CONSOLE,
};
use self::{allocator::BuddyAllocator, pmm::PhysicalMemoryManager};
static MEMMAP_REQUEST: limine::MemmapRequest = limine::MemmapRequest::new(0);
static HHDM_REQUEST: limine::HhdmRequest = limine::HhdmRequest::new(0);
pub static MEMMAP: Lazy<Mutex<&mut [NonNullPtr<MemmapEntry>]>> = Lazy::new(|| {
let memmap_request = MEMMAP_REQUEST
.get_response()
.get_mut()
.expect("Failed to get Memory map!");
return Mutex::new(memmap_request.memmap_mut());
});
pub static HHDM_OFFSET: Lazy<usize> = Lazy::new(|| {
let hhdm = HHDM_REQUEST
.get_response()
.get()
.expect("Failed to get Higher Half Direct Map!");
return hhdm.offset as usize;
});
pub static PHYSICAL_MEMORY_MANAGER: Lazy<PhysicalMemoryManager> =
Lazy::new(PhysicalMemoryManager::new);
pub struct Allocator {
pub inner: Lazy<BuddyAllocator>,
}
unsafe impl GlobalAlloc for Allocator {
unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 {
self.inner.alloc(layout)
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) {
self.inner.dealloc(ptr, layout)
}
}
const HEAP_PAGES: usize = 4096;
const HEAP_SIZE: usize = HEAP_PAGES * 1024;
#[global_allocator]
pub static ALLOCATOR: Allocator = Allocator {
inner: Lazy::new(|| {
let heap_start = PHYSICAL_MEMORY_MANAGER
.alloc(HEAP_PAGES)
.expect("Failed to allocate heap!");
BuddyAllocator::new_unchecked(heap_start, HEAP_SIZE)
}),
};
pub fn log_info() {
crate::log_info!(
"Initialized heap with {} of memory at {:#X}",
HEAP_SIZE.label_bytes(),
ALLOCATOR
.inner
.heap_start
.load(core::sync::atomic::Ordering::SeqCst) as usize
);
if CONSOLE.get_features().doubled_buffered {
let row_size = CONSOLE.second_buffer.lock().read().unwrap().pitch
/ (CONSOLE.second_buffer.lock().read().unwrap().bpp / 8);
let screen_size = row_size * CONSOLE.second_buffer.lock().read().unwrap().height;
crate::log_info!(
"Initialized framebuffer mirroring with {} at {:#X}",
(screen_size * 4).label_bytes(),
CONSOLE.second_buffer.lock().read().unwrap().pointer as usize
);
}
log_memory_map();
}
pub fn log_memory_map() {
let memmap_request = MEMMAP_REQUEST.get_response().get_mut();
if memmap_request.is_none() {
panic!("Memory map was None!");
}
let memmap = memmap_request.unwrap().memmap();
crate::println!("====== MEMORY MAP ======");
for entry in memmap.iter() {
let label = (entry.len as usize).label_bytes();
crate::println!(
"[ {:#018X?} ] Type: \033[{};m{:?}\033[0;m Size: {}",
entry.base..entry.base + entry.len,
match entry.typ {
limine::MemoryMapEntryType::Usable => 32,
_ => 31,
},
entry.typ,
label
)
}
}
pub struct Label {
size: usize,
text_label: &'static str,
}
impl core::fmt::Display for Label {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
return write!(f, "{}{}", self.size, self.text_label);
}
}
// Hacky solution to avoid allocation, but keep the names
static BYTE_LABELS: (&str, &str, &str, &str) = ("GiB", "MiB", "KiB", "Bytes");
pub trait LabelBytes {
fn label_bytes(&self) -> Label;
}
impl LabelBytes for usize {
fn label_bytes(&self) -> Label {
let bytes = *self;
if bytes >> 30 > 0 {
return Label {
size: bytes >> 30,
text_label: BYTE_LABELS.0,
};
} else if bytes >> 20 > 0 {
return Label {
size: bytes >> 20,
text_label: BYTE_LABELS.1,
};
} else if bytes >> 10 > 0 {
return Label {
size: bytes >> 10,
text_label: BYTE_LABELS.2,
};
} else {
return Label {
size: bytes,
text_label: BYTE_LABELS.3,
};
}
}
}