From 4fa20f17e0363957ed519d9abfe28a43256220b5 Mon Sep 17 00:00:00 2001 From: Nathan Ringo Date: Sat, 3 Aug 2024 14:01:53 -0500 Subject: uncommitted changes... --- boards/qemu-virt/qemu-virt.s | 64 ++++++++++++++++++++++++++++++-------------- kernel/src/lib.rs | 2 +- 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/boards/qemu-virt/qemu-virt.s b/boards/qemu-virt/qemu-virt.s index a2618d2..5c58153 100644 --- a/boards/qemu-virt/qemu-virt.s +++ b/boards/qemu-virt/qemu-virt.s @@ -1,14 +1,15 @@ -.section .text.start - .extern main .extern CONSOLE_STRICT_FLUSH +.section .text.start + .global _start .type _start, STT_FUNC _start: - # Have harts other than 0 spin until hart0 wakes them up. - csrr a0, mhartid - c.bnez a0, wait_for_hart0 + # Have harts other than 0 spin until hart0 wakes them up. As a side + # effect, load every hart's thread pointer register with MHARTID. + csrr tp, mhartid + bnez tp, wait_for_hart0 # Set up console_strict_flush. la t0, console_strict_flush @@ -18,16 +19,47 @@ _start: # Set up hart0's stack. la sp, hart0_initial_stack_top - # Call hart0_boot with the address of the DeviceTree. + # Put the address of the DeviceTree into the first argument position + # for hart0_boot. c.mv a0, a1 - call hart0_boot - # Fall through to a spin loop. + + # The rest of this function is to get out of machine mode and into + # supervisor mode by fictitiously returning from a trap. + + # First, set MSTATUS.MPP to Supervisor, so that when we execute mret, + # the privilege level will lower to Supervisor. + csrr t0, mstatus + li t1, ~(0b11 << 11) + and t0, t0, t1 + li t1, (0b01 << 11) + or t0, t0, t1 + csrw 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 + csrw mepc, t0 + + # Delegate all exceptions and interrupts to the Supervisor level. + li t0, 0xffff + csrw medeleg, t0 + csrw mideleg, t0 + + # Set SATP.MODE to Bare, and clear the rest of the bits. This disables + # paging in Supervisor mode. + csrw satp, zero + + mret .size _start, . - _start -.type halt, STT_FUNC -halt: - j halt -.size halt, . - halt +.section .text + +.type wait_for_hart0, STT_FUNC +wait_for_hart0: + # TODO + wfi + j wait_for_hart0 +.size wait_for_hart0, . - wait_for_hart0 .section .text @@ -44,11 +76,3 @@ console_strict_flush: 2: ret .size console_strict_flush, . - console_strict_flush - -.section .text - -.type wait_for_hart0, STT_FUNC -wait_for_hart0: - # TODO - j halt -.size wait_for_hart0, . - wait_for_hart0 diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 4a2483a..842609f 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -9,7 +9,7 @@ mod panic; /// The entrypoint to the kernel. This should be executed by hart0 alone. It performs some early /// boot tasks, then wakes up any other harts. #[no_mangle] -pub extern "C" fn hart0_boot(device_tree: *const u32) { +pub extern "C" fn hart0_boot(device_tree: *const u32) -> ! { console::init(); log::info!("device_tree = {device_tree:?}"); -- cgit v1.2.3