Explorar el Código

fix: `trap_return` and `captured_trap_handler` should save `from_ctx`

add statically linked busybox for riscv64
greatbridf hace 7 meses
padre
commit
c68b315120

+ 4 - 2
crates/eonix_hal/eonix_hal_traits/src/trap.rs

@@ -1,4 +1,4 @@
-use crate::fault::Fault;
+use crate::{context::RawTaskContext, fault::Fault};
 use core::marker::PhantomData;
 
 /// A raw trap context.
@@ -28,6 +28,8 @@ pub trait RawTrapContext: Copy {
 
 #[doc(notable_trait)]
 pub trait TrapReturn {
+    type TaskContext: RawTaskContext;
+
     /// Return to the context before the trap occurred.
     ///
     /// # Safety
@@ -35,7 +37,7 @@ pub trait TrapReturn {
     /// context before the trap is valid, that is, that the stack pointer
     /// points to a valid stack frame and the program counter points to some
     /// valid instruction.
-    unsafe fn trap_return(&mut self);
+    unsafe fn trap_return(&mut self, task_ctx: &mut Self::TaskContext);
 }
 
 pub trait IrqState {

+ 1 - 1
crates/eonix_hal/src/arch/riscv64/context.rs

@@ -89,7 +89,7 @@ impl TaskContext {
             s: [0; 12],
             sp: 0,
             ra: 0,
-            sstatus: Sstatus::from_bits(1 << 13), // Set FS = Initial
+            sstatus: Sstatus::from_bits((1 << 13) | (1 << 18)), // FS = Initial, SUM = 1.
         }
     }
 

+ 16 - 10
crates/eonix_hal/src/arch/riscv64/trap/mod.rs

@@ -28,6 +28,7 @@ pub struct TrapScratch {
     kernel_tp: Option<NonZero<u64>>,
     trap_context: Option<NonNull<TrapContext>>,
     handler: unsafe extern "C" fn(),
+    captured_context: Option<NonNull<TaskContext>>,
     capturer_context: TaskContext,
 }
 
@@ -38,12 +39,10 @@ pub(crate) static TRAP_SCRATCH: TrapScratch = TrapScratch {
     kernel_tp: None,
     trap_context: None,
     handler: default_trap_handler,
+    captured_context: None,
     capturer_context: TaskContext::new(),
 };
 
-/// This value will never be used.
-static mut DIRTY_TRAP_CONTEXT: TaskContext = TaskContext::new();
-
 #[unsafe(naked)]
 unsafe extern "C" fn _raw_trap_entry() -> ! {
     naked_asm!(
@@ -195,10 +194,10 @@ unsafe extern "C" fn default_trap_handler() {
 #[unsafe(naked)]
 unsafe extern "C" fn captured_trap_handler() {
     naked_asm!(
-        "la a0, {from_context}",
+        "ld   a0, {captured_context_offset}(t0)",
         "addi a1, t0, {capturer_context_offset}",
         "j {switch}",
-        from_context = sym DIRTY_TRAP_CONTEXT,
+        captured_context_offset = const offset_of!(TrapScratch, captured_context),
         capturer_context_offset = const offset_of!(TrapScratch, capturer_context),
         switch = sym TaskContext::switch,
     );
@@ -228,23 +227,30 @@ impl TrapScratch {
 }
 
 impl TrapReturn for TrapContext {
-    unsafe fn trap_return(&mut self) {
+    type TaskContext = TaskContext;
+
+    unsafe fn trap_return(&mut self, to_ctx: &mut Self::TaskContext) {
         let irq_states = disable_irqs_save();
         let old_handler = {
             let trap_scratch = TRAP_SCRATCH.as_mut();
+            trap_scratch.captured_context = Some(NonNull::from(&mut *to_ctx));
             core::mem::replace(&mut trap_scratch.handler, captured_trap_handler)
         };
 
-        let mut to_ctx = TaskContext::new();
-        to_ctx.set_program_counter(captured_trap_return as _);
+        to_ctx.set_program_counter(captured_trap_return as usize);
         to_ctx.set_stack_pointer(&raw mut *self as usize);
         to_ctx.set_interrupt_enabled(false);
 
         unsafe {
-            TaskContext::switch(&mut TRAP_SCRATCH.as_mut().capturer_context, &mut to_ctx);
+            TaskContext::switch(&mut TRAP_SCRATCH.as_mut().capturer_context, to_ctx);
+        }
+
+        {
+            let trap_scratch = TRAP_SCRATCH.as_mut();
+            trap_scratch.handler = old_handler;
+            trap_scratch.captured_context = None;
         }
 
-        TRAP_SCRATCH.as_mut().handler = old_handler;
         irq_states.restore();
     }
 }

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

@@ -104,6 +104,7 @@ impl RawTrapContext for TrapContext {
     fn new() -> Self {
         let mut sstatus = Sstatus::from_bits(0);
         sstatus.set_fs(FS::Initial);
+        sstatus.set_sum(true);
 
         Self {
             regs: Registers::default(),

+ 3 - 3
src/kernel/task/loader/elf.rs

@@ -157,9 +157,9 @@ impl ElfArch for ElfArch64 {
     type Ea = u64;
     type Ph = ProgramHeader64;
 
-    const DYN_BASE_ADDR: usize = 0xaaaa_0000_0000;
-    const LDSO_BASE_ADDR: usize = 0xf000_0000_0000;
-    const STACK_BASE_ADDR: usize = 0xffff_ffff_0000;
+    const DYN_BASE_ADDR: usize = 0x2aaa_0000_0000;
+    const LDSO_BASE_ADDR: usize = 0x7000_0000_0000;
+    const STACK_BASE_ADDR: usize = 0x7fff_ffff_0000;
 }
 
 impl<E: ElfArch> Elf<E> {

+ 4 - 1
src/kernel/task/thread.rs

@@ -23,6 +23,7 @@ use core::{
     task::{Context, Poll, Waker},
 };
 use eonix_hal::{
+    context::TaskContext,
     processor::{UserTLS, CPU},
     traits::{
         fault::Fault,
@@ -344,6 +345,8 @@ impl Thread {
     }
 
     async fn real_run(&self) {
+        let mut task_context = TaskContext::new();
+
         while !self.is_dead() {
             if self.signal_list.has_pending_signal() {
                 self.signal_list
@@ -359,7 +362,7 @@ impl Thread {
 
             unsafe {
                 // SAFETY: We are returning to the context of the user thread.
-                self.trap_ctx.borrow().trap_return();
+                self.trap_ctx.borrow().trap_return(&mut task_context);
             }
 
             self.fpu_state.borrow().save();

BIN
user-programs/busybox.static