summaryrefslogtreecommitdiff
path: root/crates/kernel/src/alloc.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/kernel/src/alloc.rs')
-rw-r--r--crates/kernel/src/alloc.rs72
1 files changed, 72 insertions, 0 deletions
diff --git a/crates/kernel/src/alloc.rs b/crates/kernel/src/alloc.rs
new file mode 100644
index 0000000..dbb79ee
--- /dev/null
+++ b/crates/kernel/src/alloc.rs
@@ -0,0 +1,72 @@
+//! Global structures for the allocators.
+
+use crate::arch::{
+ paging::{PageTable, PageTableEntry, ASID, PAGE_TABLE_BITS, PAGE_TABLE_LEVELS},
+ MAX_PAGE_SIZE_BITS, PAGE_SIZE, PAGE_SIZE_BITS,
+};
+use contracts::requires;
+use core::ptr::NonNull;
+use spin::mutex::FairMutex;
+use vernos_alloc_buddy::BuddyAllocator;
+use vernos_utils::BelieveMeSend;
+
+/// The global instance of the physical page allocator.
+static BUDDY_ALLOCATOR: FairMutex<
+ Option<BuddyAllocator<PAGE_SIZE, PAGE_SIZE_BITS, { 1 + MAX_PAGE_SIZE_BITS - PAGE_SIZE_BITS }>>,
+> = FairMutex::new(None);
+
+/// The global kernel page table.
+static KERNEL_PAGE_TABLE: FairMutex<BelieveMeSend<Option<NonNull<PageTable>>>> =
+ FairMutex::new(BelieveMeSend(None));
+
+/// Initializes the allocator and enables paging.
+///
+/// # Safety
+///
+/// - Paging must not have been enabled previously.
+/// - The buddy allocator must be valid.
+#[requires(BUDDY_ALLOCATOR.lock().is_none())]
+#[ensures(BUDDY_ALLOCATOR.lock().is_some())]
+#[requires(KERNEL_PAGE_TABLE.lock().is_none())]
+#[ensures(KERNEL_PAGE_TABLE.lock().is_some())]
+pub unsafe fn init(
+ mut buddy_allocator: BuddyAllocator<
+ 'static,
+ PAGE_SIZE,
+ PAGE_SIZE_BITS,
+ { 1 + MAX_PAGE_SIZE_BITS - PAGE_SIZE_BITS },
+ >,
+) {
+ // Allocate a page to use (for now) as the global kernel page table. Later we'll actually
+ // replace it with the hart0 initial stack's page, since we'll never free the root page of the
+ // kernel page table, and we can't return that page to the buddy allocator anyway.
+ let mut page_table = buddy_allocator
+ .alloc_zeroed::<PageTable>()
+ .expect("failed to allocate the kernel page table");
+
+ // Create identity mappings for the lower half of memory.
+ for (i, entry) in page_table
+ .as_mut()
+ .iter_mut()
+ .enumerate()
+ .take(1 << (PAGE_TABLE_BITS - 1))
+ {
+ let addr = (i as u64) << ((PAGE_TABLE_LEVELS - 1) * PAGE_TABLE_BITS + PAGE_SIZE_BITS);
+ let mut pte = PageTableEntry::default();
+ pte.set_valid(true)
+ .set_rwx(true, true, true)
+ .set_global(true)
+ .set_addr(addr);
+ *entry = pte;
+ }
+
+ // Set the page table as the current page table.
+ page_table.as_mut().make_current(ASID::KERNEL);
+
+ // Save the buddy allocator and kernel page table.
+ *BUDDY_ALLOCATOR.lock() = Some(buddy_allocator);
+ KERNEL_PAGE_TABLE.lock().0 = Some(page_table);
+
+ // Print the page table after this.
+ vernos_utils::dbg!(page_table.as_mut());
+}