summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boards/qemu-virt/qemu-virt.s50
-rw-r--r--crates/kernel/src/lib.rs44
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();
}