mirror of
https://github.com/obhq/obliteration.git
synced 2024-12-02 08:06:34 +00:00
Implements stage 1 kernel heap (#956)
This commit is contained in:
parent
da46138ba6
commit
8bd35ba9ff
@ -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 }
|
||||
|
@ -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;
|
||||
|
||||
@ -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) };
|
||||
@ -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() };
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user