summaryrefslogtreecommitdiff
path: root/crates/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'crates/kernel')
-rw-r--r--crates/kernel/Cargo.toml3
-rw-r--r--crates/kernel/src/alloc.rs58
-rw-r--r--crates/kernel/src/lib.rs4
3 files changed, 50 insertions, 15 deletions
diff --git a/crates/kernel/Cargo.toml b/crates/kernel/Cargo.toml
index 6c28dd8..5fef50b 100644
--- a/crates/kernel/Cargo.toml
+++ b/crates/kernel/Cargo.toml
@@ -7,7 +7,7 @@ edition = "2021"
crate-type = ["staticlib"]
[dependencies]
-allocator-api2 = { version = "0.2.18", default-features = false }
+allocator-api2 = { version = "0.2.18", default-features = false, features = ["alloc"] }
bitflags = { version = "2.6.0", default-features = false }
cfg-if = { version = "1.0.0", default-features = false }
contracts = { version = "0.6.3", default-features = false }
@@ -16,6 +16,7 @@ log = { version = "0.4.20", default-features = false }
spin = { version = "0.9.8", default-features = false, features = ["fair_mutex", "use_ticket_mutex"] }
vernos_alloc_buddy = { path = "../alloc_buddy" }
vernos_alloc_physmem_free_list = { path = "../alloc_physmem_free_list" }
+vernos_alloc_vma_tree = { path = "../alloc_vma_tree" }
vernos_device_tree = { path = "../device_tree" }
vernos_driver_riscv_timer = { path = "../driver_riscv_timer" }
vernos_utils = { path = "../utils" }
diff --git a/crates/kernel/src/alloc.rs b/crates/kernel/src/alloc.rs
index 93d8b15..690b428 100644
--- a/crates/kernel/src/alloc.rs
+++ b/crates/kernel/src/alloc.rs
@@ -1,13 +1,14 @@
//! Global structures for the allocators.
use crate::paging::{
- BuddyAllocator, MapError, MappingFlags, PageTable, ASID, LOMEM_TOP, MAX_PAGE_SIZE_BITS,
- PAGE_SIZE, PAGE_SIZES,
+ BuddyAllocator, MapError, MappingFlags, PageTable, ASID, HIMEM_BOT, LOMEM_TOP,
+ MAX_PAGE_SIZE_BITS, PAGE_SIZE, PAGE_SIZES, PAGE_SIZE_BITS,
};
-use allocator_api2::alloc::AllocError;
+use allocator_api2::alloc::{AllocError, Global, GlobalAlloc, Layout};
use contracts::requires;
use core::{num::NonZero, ptr::NonNull};
use spin::mutex::FairMutex;
+use vernos_alloc_vma_tree::VMATree;
/// The global instance of the physical page allocator.
static BUDDY_ALLOCATOR: FairMutex<Option<BuddyAllocator>> = FairMutex::new(None);
@@ -15,16 +16,24 @@ static BUDDY_ALLOCATOR: FairMutex<Option<BuddyAllocator>> = FairMutex::new(None)
/// The global kernel page table.
static KERNEL_PAGE_TABLE: FairMutex<Option<&'static mut PageTable>> = FairMutex::new(None);
+/// The kernel's virtual memory allocator.
+static KERNEL_VM_ALLOC: FairMutex<VMATree<PAGE_SIZE_BITS, Global>> =
+ FairMutex::new(VMATree::new_in(Global));
+
+/// The global allocator.
+#[global_allocator]
+static GLOBAL_ALLOC: GlobalGenMalloc = GlobalGenMalloc;
+
/// Initializes the kernel page table and enables paging.
///
/// # Safety
///
/// - Paging must not have been enabled previously.
/// - The buddy allocator must be valid.
-#[requires(BUDDY_ALLOCATOR.lock().is_none())]
#[requires(KERNEL_PAGE_TABLE.lock().is_none())]
-#[ensures(BUDDY_ALLOCATOR.lock().is_some())]
+#[requires(BUDDY_ALLOCATOR.lock().is_none())]
#[ensures(KERNEL_PAGE_TABLE.lock().is_some())]
+#[ensures(BUDDY_ALLOCATOR.lock().is_some())]
pub unsafe fn init_kernel_page_table(buddy_allocator: BuddyAllocator) {
// Just making this mut above gets a warning thanks to the contracts macros...
let mut buddy_allocator = buddy_allocator;
@@ -59,8 +68,8 @@ pub unsafe fn init_kernel_page_table(buddy_allocator: BuddyAllocator) {
vernos_utils::dbg!(&page_table);
// Save the buddy allocator and kernel page table.
- *BUDDY_ALLOCATOR.lock() = Some(buddy_allocator);
*KERNEL_PAGE_TABLE.lock() = Some(page_table);
+ *BUDDY_ALLOCATOR.lock() = Some(buddy_allocator);
}
/// Initializes the virtual memory allocator and the regular allocator.
@@ -68,11 +77,19 @@ pub unsafe fn init_kernel_page_table(buddy_allocator: BuddyAllocator) {
/// # Safety
///
/// - `himem_top` must be accurate.
-#[requires(BUDDY_ALLOCATOR.lock().is_some())]
#[requires(KERNEL_PAGE_TABLE.lock().is_some())]
+#[requires(BUDDY_ALLOCATOR.lock().is_some())]
#[requires(himem_top & (PAGE_SIZE - 1) == 0)]
+#[requires(HIMEM_BOT < himem_top)]
pub unsafe fn init_kernel_virtual_memory_allocator(himem_top: usize) {
- todo!()
+ // TODO: Bootstrap the allocator.
+
+ // The error here _really_ ought to be impossible, because we just bootstrapped the allocator!
+ // It definitely has free memory.
+ let mut kernel_vm_alloc = KERNEL_VM_ALLOC.lock();
+ kernel_vm_alloc
+ .add(HIMEM_BOT..himem_top)
+ .expect("failed to set up the kernel's virtual memory allocator");
}
/// Tries to allocate a page of physical memory of the given size, returning its physical address.
@@ -112,12 +129,29 @@ pub fn kernel_map(
len: usize,
flags: MappingFlags,
) -> Result<(), MapError> {
- let mut buddy_allocator = BUDDY_ALLOCATOR.lock();
let mut kernel_page_table = KERNEL_PAGE_TABLE.lock();
- let buddy_allocator = buddy_allocator.as_mut().unwrap();
+ let mut buddy_allocator = BUDDY_ALLOCATOR.lock();
let kernel_page_table = kernel_page_table.as_mut().unwrap();
+ let buddy_allocator = buddy_allocator.as_mut().unwrap();
kernel_page_table.map(&mut *buddy_allocator, vaddr, paddr, len, flags)?;
- log::warn!("TODO: sfence.vma");
- log::warn!("TODO: TLB shootdown");
+ vernos_utils::first_time! {
+ {
+ log::warn!("TODO: sfence.vma");
+ log::warn!("TODO: TLB shootdown");
+ }
+ }
Ok(())
}
+
+/// A global allocator backed by a hart-local `vernos_alloc_genmalloc::Heap`.
+struct GlobalGenMalloc;
+
+unsafe impl GlobalAlloc for GlobalGenMalloc {
+ unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+ todo!("GlobalGenMalloc.alloc({layout:?})")
+ }
+
+ unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+ todo!("GlobalGenMalloc.dealloc({ptr:?}, {layout:?})")
+ }
+}
diff --git a/crates/kernel/src/lib.rs b/crates/kernel/src/lib.rs
index 0ca535a..7421649 100644
--- a/crates/kernel/src/lib.rs
+++ b/crates/kernel/src/lib.rs
@@ -43,7 +43,7 @@ impl EarlyBootAddrs {
/// Looks for a DeviceTree at address in the `EarlyBootAddrs`, and returns it if it looks
/// valid. Panics if the DeviceTree is invalid.
///
- /// ## Safety
+ /// # Safety
///
/// - The `EarlyBootAddrs` must be accurate.
/// - The `device_tree` pointer must be a valid pointer into physical memory. See
@@ -194,7 +194,7 @@ pub unsafe extern "C" fn hart0_early_boot(early_boot_addrs: &mut EarlyBootAddrs)
let new_stack_start = new_stack_end - STACK_SIZE;
vaddr_bump = new_stack_start;
for i in 0..((STACK_SIZE >> PAGE_SIZE_BITS) - 1) {
- let vaddr = new_kernel_start + (i << PAGE_SIZE_BITS);
+ let vaddr = new_stack_start + (i << PAGE_SIZE_BITS);
let paddr =
alloc_page(PAGE_SIZE).expect("failed to allocate memory for a hart0 stack page");
kernel_map(