diff options
author | Nathan Ringo <nathan@remexre.com> | 2024-09-02 02:30:32 -0500 |
---|---|---|
committer | Nathan Ringo <nathan@remexre.com> | 2024-09-02 02:30:32 -0500 |
commit | c27e5ca6bf2b4040abd628ef59f8a3bc9326749c (patch) | |
tree | 4108f9177b732f3566ceab52dc5c3f9d802dbca2 | |
parent | 52e33eee454766940d1987199868f0d892ce34a3 (diff) |
Split hart0_boot in half, so stacks can be switched in the middle.
-rw-r--r-- | boards/qemu-virt/qemu-virt.s | 50 | ||||
-rw-r--r-- | crates/kernel/src/lib.rs | 44 |
2 files changed, 71 insertions, 23 deletions
diff --git a/boards/qemu-virt/qemu-virt.s b/boards/qemu-virt/qemu-virt.s index 0d69d4d..bd32676 100644 --- a/boards/qemu-virt/qemu-virt.s +++ b/boards/qemu-virt/qemu-virt.s @@ -1,5 +1,5 @@ -.extern main -.extern CONSOLE_STRICT_FLUSH +.extern hart0_boot +.extern hart0_early_boot .section .text.start @@ -11,18 +11,6 @@ _start: csrr tp, mhartid bnez tp, wait_for_hart0 - ## Set up hart0's stack. - la sp, hart0_initial_stack_top - - ## Write a canary to hart0's stack. - li t0, 0xdead0bad0defaced - la t1, hart0_initial_stack - sd t0, (t1) - - ## Put the address of the DeviceTree into the first argument position - ## for hart0_boot. - c.mv a0, a1 - ### Set up trap handling. ## Set MENVCFG.STCE, to enable the Sstc extension, which will allow us @@ -55,9 +43,9 @@ _start: li t0, 0b01 << 11 csrs mstatus, t0 - ## Next, set MEPC to the address of hart0_boot, so that when we execute - ## mret, execution will continue there. - la t0, hart0_boot + ## Next, set MEPC to the address of hart0_full_boot, so that when we + ## execute mret, execution will continue there. + la t0, hart0_full_boot csrw mepc, t0 ## Set SATP.MODE to Bare, and clear the rest of the bits. This disables @@ -78,6 +66,34 @@ _start: .section .text +.type hart0_full_boot, STT_FUNC +hart0_full_boot: + ## Set up hart0's stack. + la sp, hart0_initial_stack_top + + ## Write a canary to hart0's stack. + li t0, 0xdead0bad0defaced + la t1, hart0_initial_stack + sd t0, (t1) + + ## Call hart0_early_boot, passing it the DeviceTree we received and + ## getting back the address of a stack to switch to. + mv a0, a1 + call hart0_early_boot + + ## Switch to the returned stack. + mv sp, a0 + + ## Load the canary back from hart0's stack. + la t0, hart0_initial_stack + ld a0, (t0) + + ## Jump to hart0_boot. + j hart0_boot +.size hart0_full_boot, . - hart0_full_boot + +.section .text + .type wait_for_hart0, STT_FUNC wait_for_hart0: # TODO diff --git a/crates/kernel/src/lib.rs b/crates/kernel/src/lib.rs index 6e09d2b..c0da3bf 100644 --- a/crates/kernel/src/lib.rs +++ b/crates/kernel/src/lib.rs @@ -15,18 +15,26 @@ mod panic; pub mod arch; pub mod logger; -/// The entrypoint to the kernel. This should be executed by hart0 alone. It performs some early -/// boot tasks, then wakes up any other harts. +/// The first stage of booting the kernel. This should be executed by hart0 alone. It runs with +/// paging disabled, and: +/// +/// - sets up a physical memory allocator +/// - sets up paging +/// - allocates some global structures in the higher half of memory: +/// - a logger's buffer +/// - a stack for this kernel thread +/// - the DeviceTree in tree form +/// +/// It returns the top address of the stack for this kernel thread. /// /// # Safety /// /// - The `device_tree` pointer must be a valid pointer into physical memory. See /// `device_tree::FlattenedDeviceTree::from_ptr` for the precise requirements. -/// - This must be called in supervisor mode with paging and traps disabled, but with all traps -/// delegated to supervisor mode. -/// - Any other harts must not be running concurrently with us. TODO: Define their state. +/// - This must be called in supervisor mode with paging disabled. +/// - Any other harts must not be running concurrently with us. #[no_mangle] -pub unsafe extern "C" fn hart0_boot(device_tree: *const u8) -> ! { +pub unsafe extern "C" fn hart0_early_boot(device_tree: *const u8) -> ! { // Set up the logger. logger::init(); @@ -79,6 +87,25 @@ pub unsafe extern "C" fn hart0_boot(device_tree: *const u8) -> ! { .expect("failed to configure the buddy allocator"); dbg!(alloc_buddy.debug_free_lists()); + todo!() +} + +/// The entrypoint to the kernel, to be run after paging is set up. This should be executed by +/// hart0 alone. It performs some early boot tasks, then wakes up any other harts. +/// +/// It receives the stack canary from the initial stack, and validates it. +/// +/// # Safety +/// +/// - `hart0_early_boot` must have been called. +/// - This must be called in supervisor mode with traps disabled, but with all traps delegated to +/// supervisor mode. +/// - Any other harts must not be running concurrently with us. TODO: Define their state. +#[no_mangle] +pub unsafe extern "C" fn hart0_boot(stack_canary: u64) -> ! { + assert_eq!(stack_canary, 0xdead0bad0defaced); + + /* // After this point, everything else is for debugging. #[cfg(target_arch = "riscv64")] { @@ -98,6 +125,11 @@ pub unsafe extern "C" fn hart0_boot(device_tree: *const u8) -> ! { .unwrap_or_else(|err| void::unreachable(err)); arch::interrupts::example_timer(); } + */ + + if true { + todo!(); + } info!("sleeping forever..."); sleep_forever(); } |