Skip to content

Commit

Permalink
Implements stage 1 kernel heap (#956)
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon authored Aug 31, 2024
1 parent da46138 commit 8bd35ba
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 9 deletions.
2 changes: 2 additions & 0 deletions src/obkrnl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ anstyle = { version = "1.0.8", default-features = false }
macros = { path = "../macros" }
obconf = { path = "../obconf" }
obvirt = { path = "../obvirt" }
spin = { version = "0.9.8", features = ["spin_mutex"], default-features = false }
talc = { version = "4.4.1", default-features = false }
9 changes: 7 additions & 2 deletions src/obkrnl/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::config::set_boot_env;
use crate::malloc::KernelHeap;
use alloc::string::String;
use core::arch::asm;
use core::mem::zeroed;
use core::panic::PanicInfo;
use obconf::BootEnv;

Expand All @@ -26,7 +27,7 @@ extern crate alloc;
///
/// See PS4 kernel entry point for a reference.
#[allow(dead_code)]
#[cfg_attr(not(test), no_mangle)]
#[cfg_attr(target_os = "none", no_mangle)]
extern "C" fn _start(env: &'static BootEnv) -> ! {
// SAFETY: This is safe because we called it as the first thing here.
unsafe { set_boot_env(env) };
Expand Down Expand Up @@ -67,6 +68,10 @@ fn panic(i: &PanicInfo) -> ! {
crate::panic::panic();
}

// SAFETY: STAGE1_HEAP is a mutable static so it valid for reads and writes. This will be safe as
// long as no one access STAGE1_HEAP.
#[allow(dead_code)]
#[cfg_attr(target_os = "none", global_allocator)]
static mut KERNEL_HEAP: KernelHeap = KernelHeap::new();
static mut KERNEL_HEAP: KernelHeap =
unsafe { KernelHeap::new(STAGE1_HEAP.as_mut_ptr(), STAGE1_HEAP.len()) };
static mut STAGE1_HEAP: [u8; 1024 * 1024] = unsafe { zeroed() };
36 changes: 29 additions & 7 deletions src/obkrnl/src/malloc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,42 @@
use core::alloc::{GlobalAlloc, Layout};
use core::ptr::{null_mut, NonNull};
use talc::{ClaimOnOom, Span, Talc};

/// Implementation of [`GlobalAlloc`] for objects belong to kernel space.
pub struct KernelHeap {}
///
/// This allocator has 2 stages. The first stage will allocate a memory from a static buffer (AKA
/// arena). This stage will be primary used for bootstrapping the kernel. The second stage will be
/// activated once the required subsystems has been initialized.
pub struct KernelHeap {
stage1: spin::Mutex<Talc<ClaimOnOom>>,
}

impl KernelHeap {
pub const fn new() -> Self {
Self {}
/// # Safety
/// The specified memory must be valid for reads and writes and it must be exclusively available
/// to [`KernelHeap`].
pub const unsafe fn new(stage1: *mut u8, len: usize) -> Self {
let stage1 = Talc::new(unsafe { ClaimOnOom::new(Span::from_base_size(stage1, len)) });

Self {
stage1: spin::Mutex::new(stage1),
}
}
}

unsafe impl GlobalAlloc for KernelHeap {
unsafe fn alloc(&self, _: Layout) -> *mut u8 {
todo!()
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
// SAFETY: GlobalAlloc::alloc required layout to be non-zero.
self.stage1
.lock()
.malloc(layout)
.map(|v| v.as_ptr())
.unwrap_or(null_mut())
}

unsafe fn dealloc(&self, _: *mut u8, _: Layout) {
todo!()
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
// SAFETY: GlobalAlloc::dealloc required ptr to be the same one that returned from our
// GlobalAlloc::alloc and layout to be the same one that passed to it.
self.stage1.lock().free(NonNull::new_unchecked(ptr), layout);
}
}

0 comments on commit 8bd35ba

Please sign in to comment.