diff --git a/src/arch/aarch64/start.rs b/src/arch/aarch64/start.rs index cd0b6828b6..a4f71cdb0d 100644 --- a/src/arch/aarch64/start.rs +++ b/src/arch/aarch64/start.rs @@ -1,9 +1,10 @@ //! This function is where the kernel sets up IRQ handlers -//! It is increcibly unsafe, and should be minimal in nature +//! It is incredibly unsafe, and should be minimal in nature //! It must create the IDT with the correct entries, those entries are //! defined in other files inside of the `arch` module use core::{ arch::global_asm, + cell::SyncUnsafeCell, slice, sync::atomic::{AtomicBool, Ordering}, }; @@ -22,6 +23,12 @@ static mut DATA_TEST_NONZERO: usize = 0xFFFF_FFFF_FFFF_FFFF; pub static AP_READY: AtomicBool = AtomicBool::new(false); static BSP_READY: AtomicBool = AtomicBool::new(false); +#[repr(C, align(16))] +struct StackAlign(T); + +static STACK: SyncUnsafeCell> = + SyncUnsafeCell::new(StackAlign([0; 128 * 1024])); + global_asm!(" .globl kstart kstart: @@ -33,6 +40,11 @@ global_asm!(" ldr x9, [x9, :lo12:{data_test_nonzero}] cbz x9, .Lkstart_crash + adrp x1, {stack} + add x1, x1, :lo12:{stack} + mov x2, {stack_size}-16 + add sp, x1, x2 + mov lr, 0 b {start} @@ -42,6 +54,8 @@ global_asm!(" ", bss_test_zero = sym BSS_TEST_ZERO, data_test_nonzero = sym DATA_TEST_NONZERO, + stack = sym STACK, + stack_size = const size_of_val(&STACK), start = sym start, ); diff --git a/src/arch/riscv64/start.rs b/src/arch/riscv64/start.rs index 3af8e917cc..bbce183fe9 100644 --- a/src/arch/riscv64/start.rs +++ b/src/arch/riscv64/start.rs @@ -1,5 +1,6 @@ use core::{ arch::{asm, global_asm}, + cell::SyncUnsafeCell, sync::atomic::{AtomicUsize, Ordering}, }; @@ -36,6 +37,12 @@ fn get_boot_hart_id(env: &[u8]) -> Option { None } +#[repr(C, align(16))] +struct StackAlign(T); + +static STACK: SyncUnsafeCell> = + SyncUnsafeCell::new(StackAlign([0; 128 * 1024])); + global_asm!(" .globl kstart kstart: @@ -49,6 +56,10 @@ global_asm!(" ld t0, {data_test_nonzero} beqz t0, .Lkstart_crash + .Lpcrel_hi0: + auipc sp, %pcrel_hi({stack}+{stack_size}-16) + addi sp, sp, %pcrel_lo(.Lpcrel_hi0) + li ra, 0 j {start} @@ -57,17 +68,14 @@ global_asm!(" ", bss_test_zero = sym BSS_TEST_ZERO, data_test_nonzero = sym DATA_TEST_NONZERO, + stack = sym STACK, + stack_size = const size_of_val(&STACK), start = sym start, ); /// The entry to Rust, all things must be initialized unsafe extern "C" fn start(args_ptr: *const KernelArgs) -> ! { unsafe { - asm!( - "sd x0, -16(fp)", // and stop frame walker here - "sd x0, -8(fp)", - ); - let bootstrap = { let args = args_ptr.read(); diff --git a/src/arch/x86_shared/start.rs b/src/arch/x86_shared/start.rs index b6160f74fe..24315b8845 100644 --- a/src/arch/x86_shared/start.rs +++ b/src/arch/x86_shared/start.rs @@ -1,5 +1,5 @@ //! This function is where the kernel sets up IRQ handlers -//! It is increcibly unsafe, and should be minimal in nature +//! It is incredibly unsafe, and should be minimal in nature //! It must create the IDT with the correct entries, those entries are //! defined in other files inside of the `arch` module use core::{ @@ -30,6 +30,12 @@ static DATA_TEST_NONZERO: SyncUnsafeCell = SyncUnsafeCell::new(usize::MAX pub static AP_READY: AtomicBool = AtomicBool::new(false); static BSP_READY: AtomicBool = AtomicBool::new(false); +#[repr(C, align(16))] +struct StackAlign(T); + +static STACK: SyncUnsafeCell> = + SyncUnsafeCell::new(StackAlign([0; 128 * 1024])); + #[cfg(target_arch = "x86")] global_asm!(" .globl kstart @@ -40,6 +46,11 @@ global_asm!(" cmp dword ptr [{data_test_nonzero}], 0 je .Lkstart_crash + mov eax, [esp + 4] + lea esp, [{stack}+{stack_size}-16] + mov [esp + 4], eax + mov [esp + 8], esp + jmp {start} .Lkstart_crash: @@ -48,6 +59,8 @@ global_asm!(" ", bss_test_zero = sym BSS_TEST_ZERO, data_test_nonzero = sym DATA_TEST_NONZERO, + stack = sym STACK, + stack_size = const size_of_val(&STACK), start = sym start, ); @@ -61,6 +74,14 @@ global_asm!(" cmp qword ptr [rip + {data_test_nonzero}], 0 je .Lkstart_crash + // Note: The System V ABI requires the stack to be aligned to 16 bytes + // before the call instruction. As we jump rather than call it has to + // be offset by 8 bytes. Additionally reserve a bit more space at the + // end of the stack to ensure that the start function returns to + // address 0. + lea rsp, [rip + {stack}+{stack_size}-24] + mov rsi, rsp + jmp {start} .Lkstart_crash: @@ -69,11 +90,13 @@ global_asm!(" ", bss_test_zero = sym BSS_TEST_ZERO, data_test_nonzero = sym DATA_TEST_NONZERO, + stack = sym STACK, + stack_size = const size_of_val(&STACK), start = sym start, ); /// The entry to Rust, all things must be initialized -unsafe extern "C" fn start(args_ptr: *const KernelArgs) -> ! { +unsafe extern "C" fn start(args_ptr: *const KernelArgs, stack_end: usize) -> ! { unsafe { let bootstrap = { let args = args_ptr.read(); @@ -88,7 +111,7 @@ unsafe extern "C" fn start(args_ptr: *const KernelArgs) -> ! { args.print(); // Set up GDT - gdt::init_bsp(args.stack_base as usize + args.stack_size as usize); + gdt::init_bsp(stack_end); // Set up IDT idt::init_bsp(); diff --git a/src/startup/memory.rs b/src/startup/memory.rs index eec03bdb9b..28d3d0186c 100644 --- a/src/startup/memory.rs +++ b/src/startup/memory.rs @@ -155,11 +155,6 @@ fn register_memory_from_kernel_args(args: &KernelArgs) { args.kernel_size as usize, BootloaderMemoryKind::Kernel, ); - register_memory_region( - args.stack_base as usize, - args.stack_size as usize, - BootloaderMemoryKind::IdentityMap, - ); register_memory_region( args.env_base as usize, args.env_size as usize, diff --git a/src/startup/mod.rs b/src/startup/mod.rs index 16e33b1ae7..1499ddde94 100644 --- a/src/startup/mod.rs +++ b/src/startup/mod.rs @@ -40,11 +40,6 @@ impl KernelArgs { { self.kernel_base }, self.kernel_base + self.kernel_size ); - info!( - "Stack: {:X}:{:X}", - { self.stack_base }, - self.stack_base + self.stack_size - ); info!( "Env: {:X}:{:X}", { self.env_base },