1use crate::lib::addr::VirtAddr;
7use crate::lib::sync::irq_mutex::IrqMutex;
8use crate::lib::sync::unchecked_cell::UncheckedCell;
9use crate::mm::pmm::Pmm;
10use crate::mm::vmm::address_space::AddressSpace;
11use core::sync::atomic::{AtomicU64, Ordering};
12
13#[cfg(feature = "debug-checks")] use crate::lib::panic::kernel_panic;
14#[cfg(feature = "debug-checks")] use crate::lib::panic_codes::PanicCode;
15
16#[repr(align(64))]
20pub struct Mm {
21 hhdm_offset: AtomicU64,
22 pmm: UncheckedCell<IrqMutex<Pmm>>,
23 kernel_addr_space: UncheckedCell<IrqMutex<AddressSpace>>,
24 next_kernel_stack: AtomicU64
25}
26
27impl Mm {
28 pub const fn new() -> Self {
30 Self {
31 hhdm_offset: AtomicU64::new(0),
32 pmm: UncheckedCell::new(),
33 kernel_addr_space: UncheckedCell::new(),
34 next_kernel_stack: AtomicU64::new(0)
35 }
36 }
37
38 pub fn init(&self) {
40 self.next_kernel_stack.store(super::layout::KERNEL_STACKS_BASE.as_u64(), Ordering::Release);
41 }
42
43 pub fn set_hhdm_offset(&self, offset: u64) {
45 self.hhdm_offset.store(offset, Ordering::Release);
46 }
47
48 pub unsafe fn init_pmm(&self, pmm: Pmm) {
56 unsafe { self.pmm.init(IrqMutex::new(pmm)); }
57 }
58
59 pub unsafe fn init_kernel_addr_space(&self, kernel_addr_space: AddressSpace) {
67 unsafe { self.kernel_addr_space.init(IrqMutex::new(kernel_addr_space)); }
68 }
69
70 pub fn hhdm_offset(&self) -> u64 {
72 let hhdm = self.hhdm_offset.load(Ordering::Acquire);
73
74 #[cfg(feature = "debug-checks")]
75 if hhdm == 0 {
76 kernel_panic(
77 PanicCode::UninitializedAccess,
78 "Attempted to access KSTATE.mm.hhdm_offset before it was initialized"
79 )
80 }
81
82 hhdm
83 }
84
85 pub unsafe fn pmm(&self) -> &IrqMutex<Pmm> {
93 unsafe { self.pmm.get() }
94 }
95
96 pub unsafe fn kernel_addr_space(&self) -> &IrqMutex<AddressSpace> {
104 unsafe { self.kernel_addr_space.get() }
105 }
106
107 pub fn alloc_kernel_stack_slot(&self) -> VirtAddr {
109 use super::layout::*;
110
111 let addr = self.next_kernel_stack.fetch_add(KERNEL_STACK_SLOT_SIZE, Ordering::Relaxed);
112 let addr_virt = VirtAddr::new(addr);
113
114 #[cfg(feature = "debug-checks")]
115 {
116 if addr_virt < KERNEL_STACKS_BASE {
117 kernel_panic(
118 PanicCode::UninitializedAccess,
119 "Attempted to get the next kernel stack address before Mm::init was called"
120 );
121 }
122
123 if addr_virt > KERNEL_STACKS_BASE + KERNEL_STACKS_SIZE - KERNEL_STACK_SLOT_SIZE {
124 kernel_panic(
125 PanicCode::OutOfVirtualMemory,
126 "Could not allocate a kernel stack, out of virtual memory for kernel stacks (somehow)"
127 );
128 }
129 }
130
131 addr_virt
132 }
133}