1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use frame::BitmapFrameAllocator;
use limine::request::{HhdmRequest, MemoryMapRequest};
use spin::{Lazy, Mutex};
use x86_64::{instructions::interrupts, PhysAddr, VirtAddr};

mod frame;
mod kernel_heap;
mod manager;
mod page_table;
mod user_heap;

pub use kernel_heap::init;
pub use manager::MemoryManager;
pub use page_table::*;
pub use user_heap::*;

#[used]
#[link_section = ".requests"]
static HHDM_REQUEST: HhdmRequest = HhdmRequest::new();

#[used]
#[link_section = ".requests"]
static MEMORY_MAP_REQUEST: MemoryMapRequest = MemoryMapRequest::new();

pub static PHYSICAL_MEMORY_OFFSET: Lazy<u64> =
    Lazy::new(|| HHDM_REQUEST.get_response().unwrap().offset());

pub static FRAME_ALLOCATOR: Lazy<Mutex<BitmapFrameAllocator>> = Lazy::new(|| {
    let memory_map = MEMORY_MAP_REQUEST.get_response().unwrap();
    Mutex::new(BitmapFrameAllocator::init(memory_map))
});

pub static KERNEL_PAGE_TABLE: Lazy<Mutex<GeneralPageTable>> = Lazy::new(|| {
    let page_table = unsafe { GeneralPageTable::ref_from_current() };
    Mutex::new(page_table)
});

#[inline]
pub fn convert_physical_to_virtual(physical_address: PhysAddr) -> VirtAddr {
    VirtAddr::new(physical_address.as_u64() + PHYSICAL_MEMORY_OFFSET.clone())
}

#[inline]
pub fn convert_virtual_to_physical(virtual_address: VirtAddr) -> PhysAddr {
    PhysAddr::new(virtual_address.as_u64() - PHYSICAL_MEMORY_OFFSET.clone())
}

pub fn create_page_table_from_kernel() -> GeneralPageTable {
    interrupts::without_interrupts(|| {
        let mut frame_allocator = FRAME_ALLOCATOR.lock();
        let page_table_address = KERNEL_PAGE_TABLE.lock().physical_address;
        unsafe { GeneralPageTable::new_from_address(&mut frame_allocator, page_table_address) }
    })
}

pub fn read_from_addr<T>(addr: VirtAddr) -> T {
    unsafe { addr.as_ptr::<T>().read() }
}

pub fn addr_to_mut_ref<T>(addr: VirtAddr) -> &'static mut T {
    unsafe { &mut (*addr.as_mut_ptr()) }
}

pub fn addr_to_array<T>(addr: VirtAddr, len: usize) -> &'static mut [T] {
    unsafe { core::slice::from_raw_parts_mut(addr.as_mut_ptr(), len) }
}