Browse Source

hal: add a function to setup kernel call frames

Setting up call frames manually is highly architecture dependent, such
as stack alignment at function entry and argument passing rules. Leave
this work to the HAL crate to relief the end users from complexity.

Signed-off-by: greatbridf <greatbridf@icloud.com>
greatbridf 1 tuần trước cách đây
mục cha
commit
425291d85a

+ 9 - 0
crates/eonix_hal/eonix_hal_traits/src/trap.rs

@@ -4,6 +4,10 @@ use eonix_mm::address::VAddr;
 
 
 use crate::fault::Fault;
 use crate::fault::Fault;
 
 
+pub trait Stack {
+    fn get_bottom(&self) -> *mut usize;
+}
+
 /// A raw trap context.
 /// A raw trap context.
 ///
 ///
 /// This should be implemented by the architecture-specific trap context
 /// This should be implemented by the architecture-specific trap context
@@ -35,6 +39,11 @@ pub trait RawTrapContext: Copy {
         &mut self, pc: usize, sp: Option<usize>, ra: Option<usize>,
         &mut self, pc: usize, sp: Option<usize>, ra: Option<usize>,
         args: &[usize], write_memory: impl Fn(VAddr, &[u8]) -> Result<(), E>,
         args: &[usize], write_memory: impl Fn(VAddr, &[u8]) -> Result<(), E>,
     ) -> Result<(), E>;
     ) -> Result<(), E>;
+
+    fn set_kernel_call_frame(
+        &mut self, pc: usize, stack: &impl Stack, ra: Option<usize>,
+        args: &[usize],
+    );
 }
 }
 
 
 #[doc(notable_trait)]
 #[doc(notable_trait)]

+ 26 - 1
crates/eonix_hal/src/arch/riscv64/trap/trap_context.rs

@@ -2,7 +2,7 @@ use core::arch::asm;
 use core::mem::offset_of;
 use core::mem::offset_of;
 
 
 use eonix_hal_traits::fault::{Fault, PageFaultErrorCode};
 use eonix_hal_traits::fault::{Fault, PageFaultErrorCode};
-use eonix_hal_traits::trap::{RawTrapContext, TrapType};
+use eonix_hal_traits::trap::{RawTrapContext, Stack, TrapType};
 use eonix_mm::address::VAddr;
 use eonix_mm::address::VAddr;
 use riscv::interrupt::{Exception, Interrupt, Trap};
 use riscv::interrupt::{Exception, Interrupt, Trap};
 use riscv::register::scause::{self, Scause};
 use riscv::register::scause::{self, Scause};
@@ -276,6 +276,31 @@ impl RawTrapContext for TrapContext {
 
 
         Ok(())
         Ok(())
     }
     }
+
+    fn set_kernel_call_frame(
+        &mut self, pc: usize, sp: &impl Stack, ra: Option<usize>,
+        args: &[usize],
+    ) {
+        self.set_program_counter(pc);
+        self.set_stack_pointer(sp.get_bottom().addr());
+
+        if let Some(ra) = ra {
+            self.regs.ra = ra as u64;
+        }
+
+        let arg_regs = [
+            &mut self.regs.a0,
+            &mut self.regs.a1,
+            &mut self.regs.a2,
+            &mut self.regs.a3,
+            &mut self.regs.a4,
+            &mut self.regs.a5,
+        ];
+
+        for (&arg, reg) in args.iter().zip(arg_regs.into_iter()) {
+            *reg = arg as u64;
+        }
+    }
 }
 }
 
 
 impl TrapContext {
 impl TrapContext {

+ 27 - 1
crates/eonix_hal/src/arch/x86_64/trap/trap_context.rs

@@ -2,7 +2,7 @@ use core::arch::asm;
 use core::mem::offset_of;
 use core::mem::offset_of;
 
 
 use eonix_hal_traits::fault::{Fault, PageFaultErrorCode};
 use eonix_hal_traits::fault::{Fault, PageFaultErrorCode};
-use eonix_hal_traits::trap::{RawTrapContext, TrapType};
+use eonix_hal_traits::trap::{RawTrapContext, Stack, TrapType};
 use eonix_mm::address::VAddr;
 use eonix_mm::address::VAddr;
 
 
 use crate::processor::CPU;
 use crate::processor::CPU;
@@ -221,4 +221,30 @@ impl RawTrapContext for TrapContext {
         self.set_stack_pointer(sp);
         self.set_stack_pointer(sp);
         Ok(())
         Ok(())
     }
     }
+
+    fn set_kernel_call_frame(
+        &mut self, pc: usize, stack: &impl Stack, ra: Option<usize>,
+        args: &[usize],
+    ) {
+        let sp = stack.get_bottom().wrapping_sub(1);
+
+        self.set_program_counter(pc);
+        self.set_stack_pointer(sp.addr());
+
+        unsafe {
+            sp.write(ra.map(|f| f as usize).unwrap_or(0));
+        }
+
+        if let Some(&arg) = args.get(0) {
+            self.rdi = arg as _;
+        }
+
+        if let Some(&arg) = args.get(1) {
+            self.rsi = arg as _;
+        }
+
+        if args.len() > 2 {
+            unimplemented!("More than 2 arguments are not supported for now");
+        }
+    }
 }
 }

+ 3 - 5
src/kernel/task.rs

@@ -109,7 +109,7 @@ where
 
 
     let stack = KernelStack::new();
     let stack = KernelStack::new();
 
 
-    fn execute<F>(
+    unsafe extern "C" fn execute<F>(
         mut future: Pin<&mut F>, output_ptr: NonNull<Option<F::Output>>,
         mut future: Pin<&mut F>, output_ptr: NonNull<Option<F::Output>>,
     ) -> !
     ) -> !
     where
     where
@@ -194,19 +194,17 @@ where
         unreachable!()
         unreachable!()
     }
     }
 
 
-    let sp = stack.get_bottom();
     let mut output = UnsafeCell::new(None);
     let mut output = UnsafeCell::new(None);
 
 
     let mut trap_ctx = TrapContext::new();
     let mut trap_ctx = TrapContext::new();
 
 
     trap_ctx.set_user_mode(false);
     trap_ctx.set_user_mode(false);
     trap_ctx.set_interrupt_enabled(true);
     trap_ctx.set_interrupt_enabled(true);
-    let _ = trap_ctx.set_user_call_frame(
+    trap_ctx.set_kernel_call_frame(
         symbol_addr!(execute::<F>),
         symbol_addr!(execute::<F>),
-        Some(sp.addr().get()),
+        &stack,
         None,
         None,
         &[(&raw mut future) as usize, output.get() as usize],
         &[(&raw mut future) as usize, output.get() as usize],
-        |_, _| Ok::<(), u32>(()),
     );
     );
 
 
     loop {
     loop {

+ 8 - 0
src/kernel/task/kernel_stack.rs

@@ -1,5 +1,7 @@
 use core::ptr::NonNull;
 use core::ptr::NonNull;
 
 
+use eonix_hal::traits::trap::Stack;
+
 use crate::kernel::mem::FolioOwned;
 use crate::kernel::mem::FolioOwned;
 
 
 #[derive(Debug)]
 #[derive(Debug)]
@@ -26,3 +28,9 @@ impl KernelStack {
         unsafe { ptr.cast().byte_add(len) }
         unsafe { ptr.cast().byte_add(len) }
     }
     }
 }
 }
+
+impl Stack for KernelStack {
+    fn get_bottom(&self) -> *mut usize {
+        self.get_bottom().cast().as_ptr()
+    }
+}

+ 8 - 16
src/lib.rs

@@ -67,17 +67,13 @@ fn kernel_init(mut data: eonix_hal::bootstrap::BootStrapData) -> ! {
     drop(data);
     drop(data);
 
 
     let mut ctx = TrapContext::new();
     let mut ctx = TrapContext::new();
-    let stack_bottom = {
-        let stack = KernelStack::new();
-        let bottom = stack.get_bottom().addr().get();
-        core::mem::forget(stack);
+    let stack = KernelStack::new();
 
 
-        bottom
-    };
     ctx.set_interrupt_enabled(true);
     ctx.set_interrupt_enabled(true);
     ctx.set_user_mode(false);
     ctx.set_user_mode(false);
-    ctx.set_program_counter(symbol_addr!(standard_main));
-    ctx.set_stack_pointer(stack_bottom);
+    ctx.set_kernel_call_frame(symbol_addr!(standard_main), &stack, None, &[]);
+
+    core::mem::forget(stack);
 
 
     unsafe {
     unsafe {
         ctx.trap_return_noreturn();
         ctx.trap_return_noreturn();
@@ -94,17 +90,13 @@ fn kernel_ap_main(_stack_range: PRange) -> ! {
     println_debug!("AP{} started", CPU::local().cpuid());
     println_debug!("AP{} started", CPU::local().cpuid());
 
 
     let mut ctx = TrapContext::new();
     let mut ctx = TrapContext::new();
-    let stack_bottom = {
-        let stack = KernelStack::new();
-        let bottom = stack.get_bottom().addr().get();
-        core::mem::forget(stack);
+    let stack = KernelStack::new();
 
 
-        bottom
-    };
     ctx.set_interrupt_enabled(true);
     ctx.set_interrupt_enabled(true);
     ctx.set_user_mode(false);
     ctx.set_user_mode(false);
-    ctx.set_program_counter(symbol_addr!(standard_main));
-    ctx.set_stack_pointer(stack_bottom);
+    ctx.set_kernel_call_frame(symbol_addr!(standard_main), &stack, None, &[]);
+
+    core::mem::forget(stack);
 
 
     unsafe {
     unsafe {
         ctx.trap_return_noreturn();
         ctx.trap_return_noreturn();