diff --git a/src/arch/aarch64/init/pre_kstart/helpers/vectors.S b/src/arch/aarch64/init/pre_kstart/helpers/vectors.S index 2241348397ad149e2b5cea03057881b1727075be..dec303bc98eb33131a6cd6a5639cefeae9b611a7 100644 --- a/src/arch/aarch64/init/pre_kstart/helpers/vectors.S +++ b/src/arch/aarch64/init/pre_kstart/helpers/vectors.S @@ -7,95 +7,117 @@ .align 11 exception_vector_base: + // Synchronous .align 7 __vec_00: mov x18, #0xb0b0 - b do_exception_synchronous + b synchronous_exception_at_el1_with_sp0 b __vec_00 + // IRQ .align 7 __vec_01: mov x18, #0xb0b1 b do_exception_irq b __vec_01 + // FIQ .align 7 __vec_02: mov x18, #0xb0b2 b do_exception_unhandled b __vec_02 + // SError .align 7 __vec_03: mov x18, #0xb0b3 b do_exception_unhandled b __vec_03 + // Synchronous .align 7 __vec_04: mov x18, #0xb0b4 - b do_exception_synchronous + b synchronous_exception_at_el1_with_spx b __vec_04 + // IRQ .align 7 __vec_05: mov x18, #0xb0b5 b do_exception_irq b __vec_05 + // FIQ .align 7 __vec_06: mov x18, #0xb0b6 b do_exception_unhandled b __vec_06 + // SError .align 7 __vec_07: mov x18, #0xb0b7 b do_exception_unhandled b __vec_07 + // Synchronous .align 7 __vec_08: mov x18, #0xb0b8 - b do_exception_synchronous + b synchronous_exception_at_el0 b __vec_08 + // IRQ .align 7 __vec_09: mov x18, #0xb0b9 b do_exception_irq b __vec_09 + // FIQ .align 7 __vec_10: mov x18, #0xb0ba b do_exception_unhandled b __vec_10 + // SError .align 7 __vec_11: mov x18, #0xb0bb b do_exception_unhandled b __vec_11 + // Synchronous .align 7 __vec_12: mov x18, #0xb0bc b do_exception_unhandled b __vec_12 + // IRQ .align 7 __vec_13: mov x18, #0xb0bd b do_exception_unhandled b __vec_13 + // FIQ .align 7 __vec_14: mov x18, #0xb0be b do_exception_unhandled b __vec_14 + // SError + .align 7 +__vec_15: + mov x18, #0xb0bf + b do_exception_unhandled + b __vec_15 + .align 7 exception_vector_end: diff --git a/src/arch/aarch64/interrupt/exception.rs b/src/arch/aarch64/interrupt/exception.rs new file mode 100644 index 0000000000000000000000000000000000000000..01d0ef396070c67aa486e6b2ccff05b965459a60 --- /dev/null +++ b/src/arch/aarch64/interrupt/exception.rs @@ -0,0 +1,47 @@ +use crate::{ + interrupt::stack_trace, + syscall, + syscall::flag::*, + + with_exception_stack, + exception_stack, +}; + +exception_stack!(synchronous_exception_at_el1_with_sp0, |stack| { + println!("Synchronous exception at EL1 with SP0"); + stack.dump(); + stack_trace(); + loop {} +}); + +exception_stack!(synchronous_exception_at_el1_with_spx, |stack| { + println!("Synchronous exception at EL1 with SPx"); + stack.dump(); + stack_trace(); + loop {} +}); + +exception_stack!(synchronous_exception_at_el0, |stack| { + with_exception_stack!(|stack| { + let fp; + asm!("mov {}, fp", out(reg) fp); + + let exception_code = (stack.iret.esr_el1 & (0x3f << 26)) >> 26; + if exception_code != 0b010101 { + println!("FATAL: Not an SVC induced synchronous exception"); + stack.dump(); + stack_trace(); + loop {} + } + + let scratch = &stack.scratch; + syscall::syscall(scratch.x8, scratch.x0, scratch.x1, scratch.x2, scratch.x3, scratch.x4, fp, stack) + }); +}); + +exception_stack!(unhandled_exception, |stack| { + println!("Unhandled exception"); + stack.dump(); + stack_trace(); + loop {} +}); diff --git a/src/arch/aarch64/interrupt/handler.rs b/src/arch/aarch64/interrupt/handler.rs index 279c89a36b646a33c58fb33fc44a5676efa2f994..9be3973a5ebcbad009d6b98c1f38bd5cac3563cd 100644 --- a/src/arch/aarch64/interrupt/handler.rs +++ b/src/arch/aarch64/interrupt/handler.rs @@ -1,25 +1,28 @@ +use crate::syscall::IntRegisters; + #[derive(Default)] #[repr(packed)] pub struct ScratchRegisters { - pub x18: usize, - pub x17: usize, - pub x16: usize, - pub x15: usize, - pub x14: usize, - pub x13: usize, - pub x12: usize, - pub x11: usize, - pub x10: usize, - pub x9: usize, - pub x8: usize, - pub x7: usize, - pub x6: usize, - pub x5: usize, - pub x4: usize, - pub x3: usize, - pub x2: usize, - pub x1: usize, pub x0: usize, + pub x1: usize, + pub x2: usize, + pub x3: usize, + pub x4: usize, + pub x5: usize, + pub x6: usize, + pub x7: usize, + pub x8: usize, + pub x9: usize, + pub x10: usize, + pub x11: usize, + pub x12: usize, + pub x13: usize, + pub x14: usize, + pub x15: usize, + pub x16: usize, + pub x17: usize, + pub x18: usize, + pub padding: usize, } impl ScratchRegisters { @@ -50,18 +53,18 @@ impl ScratchRegisters { #[repr(packed)] pub struct PreservedRegisters { //TODO: is X30 a preserved register? - pub x30: usize, - pub x29: usize, - pub x28: usize, - pub x27: usize, - pub x26: usize, - pub x25: usize, - pub x24: usize, - pub x23: usize, - pub x22: usize, - pub x21: usize, - pub x20: usize, pub x19: usize, + pub x20: usize, + pub x21: usize, + pub x22: usize, + pub x23: usize, + pub x24: usize, + pub x25: usize, + pub x26: usize, + pub x27: usize, + pub x28: usize, + pub x29: usize, + pub x30: usize, } impl PreservedRegisters { @@ -83,34 +86,245 @@ impl PreservedRegisters { #[derive(Default)] #[repr(packed)] -pub struct InterruptStack { - pub elr_el1: usize, - //TODO: should this push be removed? - pub unknown: usize, - pub tpidr_el0: usize, - pub tpidrro_el0: usize, - pub spsr_el1: usize, +pub struct IretRegisters { + // occurred + // The exception vector disambiguates at which EL the interrupt + pub sp_el0: usize, // Shouldn't be used if interrupt occurred at EL1 pub esr_el1: usize, - pub sp_el0: usize, - pub preserved: PreservedRegisters, + pub spsr_el1: usize, + pub tpidrro_el0: usize, + pub tpidr_el0: usize, + pub elr_el1: usize, +} + +impl IretRegisters { + pub fn dump(&self) { + println!("ELR_EL1: {:>016X}", { self.elr_el1 }); + println!("TPIDR_EL0: {:>016X}", { self.tpidr_el0 }); + println!("TPIDRRO_EL0: {:>016X}", { self.tpidrro_el0 }); + println!("SPSR_EL1: {:>016X}", { self.spsr_el1 }); + println!("ESR_EL1: {:>016X}", { self.esr_el1 }); + println!("SP_EL0: {:>016X}", { self.sp_el0 }); + } +} + +#[derive(Default)] +#[repr(packed)] +pub struct InterruptStack { + pub iret: IretRegisters, pub scratch: ScratchRegisters, - //TODO: eret registers + pub preserved: PreservedRegisters, } impl InterruptStack { pub fn dump(&self) { + self.iret.dump(); self.scratch.dump(); self.preserved.dump(); - println!("SP_EL0: {:>016X}", { self.sp_el0 }); - println!("ESR_EL1: {:>016X}", { self.esr_el1 }); - println!("SPSR_EL1: {:>016X}", { self.spsr_el1 }); - println!("TPIDRRO_EL0: {:>016X}", { self.tpidrro_el0 }); - println!("TPIDR_EL0: {:>016X}", { self.tpidr_el0 }); - println!("UNKNOWN: {:>016X}", { self.unknown }); - println!("ELR_EL1: {:>016X}", { self.elr_el1 }); + } + + /// Saves all registers to a struct used by the proc: + /// scheme to read/write registers. + pub fn save(&self, all: &mut IntRegisters) { + all.elr_el1 = self.iret.elr_el1; + all.tpidr_el0 = self.iret.tpidr_el0; + all.tpidrro_el0 = self.iret.tpidrro_el0; + all.spsr_el1 = self.iret.spsr_el1; + all.esr_el1 = self.iret.esr_el1; + all.sp_el0 = self.iret.sp_el0; + all.padding = 0; + all.x30 = self.preserved.x30; + all.x29 = self.preserved.x29; + all.x28 = self.preserved.x28; + all.x27 = self.preserved.x27; + all.x26 = self.preserved.x26; + all.x25 = self.preserved.x25; + all.x24 = self.preserved.x24; + all.x23 = self.preserved.x23; + all.x22 = self.preserved.x22; + all.x21 = self.preserved.x21; + all.x20 = self.preserved.x20; + all.x19 = self.preserved.x19; + all.x18 = self.scratch.x18; + all.x17 = self.scratch.x17; + all.x16 = self.scratch.x16; + all.x15 = self.scratch.x15; + all.x14 = self.scratch.x14; + all.x13 = self.scratch.x13; + all.x12 = self.scratch.x12; + all.x11 = self.scratch.x11; + all.x10 = self.scratch.x10; + all.x9 = self.scratch.x9; + all.x8 = self.scratch.x8; + all.x7 = self.scratch.x7; + all.x6 = self.scratch.x6; + all.x5 = self.scratch.x5; + all.x4 = self.scratch.x4; + all.x3 = self.scratch.x3; + all.x2 = self.scratch.x2; + all.x1 = self.scratch.x1; + all.x0 = self.scratch.x0; } //TODO pub fn is_singlestep(&self) -> bool { false } pub fn set_singlestep(&mut self, singlestep: bool) {} } + +#[macro_export] +macro_rules! aarch64_asm { + ($($strings:expr,)+) => { + global_asm!(concat!( + $($strings),+, + )); + }; +} + +#[macro_export] +macro_rules! function { + ($name:ident => { $($body:expr,)+ }) => { + aarch64_asm!( + ".global ", stringify!($name), "\n", + ".type ", stringify!($name), ", @function\n", + ".section .text.", stringify!($name), ", \"ax\", @progbits\n", + stringify!($name), ":\n", + $($body),+, + ".size ", stringify!($name), ", . - ", stringify!($name), "\n", + ".text\n", + ); + extern "C" { + pub fn $name(); + } + }; +} + +#[macro_export] +macro_rules! push_scratch { + () => { " + // Push scratch registers + stp x18, x18, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x14, x15, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x4, x5, [sp, #-16]! + stp x2, x3, [sp, #-16]! + stp x0, x1, [sp, #-16]! + " }; +} + +#[macro_export] +macro_rules! pop_scratch { + () => { " + // Pop scratch registers + ldp x0, x1, [sp], #16 + ldp x2, x3, [sp], #16 + ldp x4, x5, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x14, x15, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x18, x18, [sp], #16 + " }; +} + +#[macro_export] +macro_rules! push_preserved { + () => { " + // Push preserved registers + stp x29, x30, [sp, #-16]! + stp x27, x28, [sp, #-16]! + stp x25, x26, [sp, #-16]! + stp x23, x24, [sp, #-16]! + stp x21, x22, [sp, #-16]! + stp x19, x20, [sp, #-16]! + " }; +} + +#[macro_export] +macro_rules! pop_preserved { + () => { " + // Pop preserved registers + ldp x19, x20, [sp], #16 + ldp x21, x22, [sp], #16 + ldp x23, x24, [sp], #16 + ldp x25, x26, [sp], #16 + ldp x27, x28, [sp], #16 + ldp x29, x30, [sp], #16 + " }; +} + +#[macro_export] +macro_rules! push_special { + () => { " + mrs x14, tpidr_el0 + mrs x15, elr_el1 + stp x14, x15, [sp, #-16]! + + mrs x14, spsr_el1 + mrs x15, tpidrro_el0 + stp x14, x15, [sp, #-16]! + + mrs x14, sp_el0 + mrs x15, esr_el1 + stp x14, x15, [sp, #-16]! + " }; +} + +#[macro_export] +macro_rules! pop_special { + () => { " + ldp x14, x15, [sp], 16 + msr esr_el1, x15 + msr sp_el0, x14 + + ldp x14, x15, [sp], 16 + msr tpidrro_el0, x15 + msr spsr_el1, x14 + + ldp x14, x15, [sp], 16 + msr elr_el1, x15 + msr tpidr_el0, x14 + " }; +} + +#[macro_export] +macro_rules! exception_stack { + ($name:ident, |$stack:ident| $code:block) => { + paste::item! { + #[no_mangle] + unsafe extern "C" fn [<__exception_ $name>](stack: *mut $crate::arch::aarch64::interrupt::InterruptStack) { + // This inner function is needed because macros are buggy: + // https://github.com/dtolnay/paste/issues/7 + #[inline(always)] + unsafe fn inner($stack: &mut $crate::arch::aarch64::interrupt::InterruptStack) { + $code + } + inner(&mut *stack); + } + + function!($name => { + // Backup all userspace registers to stack + push_preserved!(), + push_scratch!(), + push_special!(), + + // Call inner function with pointer to stack + "mov x29, sp\n", + "mov x0, sp\n", + "bl __exception_", stringify!($name), "\n", + + // Restore all userspace registers + pop_special!(), + pop_scratch!(), + pop_preserved!(), + + "eret\n", + }); + } + }; +} diff --git a/src/arch/aarch64/interrupt/mod.rs b/src/arch/aarch64/interrupt/mod.rs index 9811df2f7c5e1a828f72afd91a07ff9848359eb1..4639332f0bcfa84f272305aaa3718862cd2d6edb 100644 --- a/src/arch/aarch64/interrupt/mod.rs +++ b/src/arch/aarch64/interrupt/mod.rs @@ -1,10 +1,12 @@ //! Interrupt instructions +#[macro_use] pub mod handler; + +pub mod exception; pub mod irq; pub mod syscall; pub mod trace; -pub mod unhandled_exceptions; pub use self::handler::InterruptStack; pub use self::trace::stack_trace; diff --git a/src/arch/aarch64/interrupt/syscall.rs b/src/arch/aarch64/interrupt/syscall.rs index 42b64ffa0c1ca2209185dbe699d2ccc34da69732..afd14167d6c593ecd5c29e615f17aea29568b547 100644 --- a/src/arch/aarch64/interrupt/syscall.rs +++ b/src/arch/aarch64/interrupt/syscall.rs @@ -1,6 +1,14 @@ -use crate::interrupt::InterruptStack; -use crate::syscall; +use crate::{ + arch::{interrupt::InterruptStack}, + context, + syscall, + syscall::flag::{PTRACE_FLAG_IGNORE, PTRACE_STOP_PRE_SYSCALL, PTRACE_STOP_POST_SYSCALL}, +}; +#[no_mangle] +pub unsafe extern fn do_exception_unhandled() {} + +/* #[naked] #[no_mangle] pub unsafe extern fn do_exception_unhandled() { @@ -69,7 +77,12 @@ pub unsafe extern fn do_exception_unhandled() { let a = inner(&mut *(sp as *mut InterruptStack)); } +*/ +#[no_mangle] +pub unsafe extern fn do_exception_synchronous() {} + +/* #[naked] #[no_mangle] pub unsafe extern fn do_exception_synchronous() { @@ -219,6 +232,7 @@ pub unsafe extern fn do_exception_synchronous() { llvm_asm!("eret" :::: "volatile"); } +*/ #[allow(dead_code)] #[repr(packed)] @@ -263,8 +277,55 @@ pub struct SyscallStack { pub x0: usize, } -#[naked] -pub unsafe extern fn clone_ret() { - llvm_asm!("ldp x29, x30, [sp], #0x60"); - llvm_asm!("mov x0, 0"); +#[macro_export] +macro_rules! with_exception_stack { + (|$stack:ident| $code:block) => {{ + let $stack = &mut *$stack; + (*$stack).scratch.x0 = $code; + }} +} + +#[no_mangle] +pub unsafe extern "C" fn __inner_syscall_instruction(stack: *mut InterruptStack) { + with_exception_stack!(|stack| { + // Set a restore point for clone + let fp; + asm!("mov {}, fp", out(reg) fp); + + let scratch = &stack.scratch; + syscall::syscall(scratch.x8, scratch.x0, scratch.x1, scratch.x2, scratch.x3, scratch.x4, fp, stack) + }); } + +function!(syscall_instruction => { + " + nop + ", + + // Push context registers + push_preserved!(), + push_scratch!(), + push_special!(), + + // TODO: Map PTI + + // Call inner function + "mov x0, sp\n", + "bl __inner_syscall_instruction\n", + + // TODO: Unmap PTI + + // Pop context registers + pop_special!(), + pop_scratch!(), + pop_preserved!(), + + // Return + "eret\n", +}); + +function!(clone_ret => { + "ldp x29, x30, [sp], #16\n", + "mov sp, x29\n", + "ret\n", +}); diff --git a/src/arch/aarch64/interrupt/unhandled_exceptions.rs b/src/arch/aarch64/interrupt/unhandled_exceptions.rs deleted file mode 100644 index 6897d89a357a688b99ca6d2ae7679672d5440506..0000000000000000000000000000000000000000 --- a/src/arch/aarch64/interrupt/unhandled_exceptions.rs +++ /dev/null @@ -1,145 +0,0 @@ -use crate::{ - context, - cpu_id, - interrupt::{self, InterruptStack, stack_trace}, -}; - -bitflags! { - pub struct ExceptionClasses: u32 { - const SVC_INSN_IN_AARCH64_STATE = 0b10101 << 26; - const DATA_ABORT_FROM_LOWER_EL = 0b100100 << 26; - const BKPT_INSN_IN_AARCH64_STATE = 0b111100 << 26; - } -} - -#[inline(never)] -pub unsafe extern fn report_exception(stack: &InterruptStack) { - println!("Unhandled exception"); - - stack.dump(); - stack_trace(); - - println!("CPU {}, PID {:?}", cpu_id(), context::context_id()); - //WARNING: name cannot be grabed, it may deadlock - - println!("HALT"); - loop { - interrupt::halt(); - } -} - -#[naked] -#[no_mangle] -pub unsafe extern fn do_report_exception() { - llvm_asm!("str x0, [sp, #-8]! - str x1, [sp, #-8]! - str x2, [sp, #-8]! - str x3, [sp, #-8]! - str x4, [sp, #-8]! - str x5, [sp, #-8]! - str x6, [sp, #-8]! - str x7, [sp, #-8]! - str x8, [sp, #-8]! - str x9, [sp, #-8]! - str x10, [sp, #-8]! - str x11, [sp, #-8]! - str x12, [sp, #-8]! - str x13, [sp, #-8]! - str x14, [sp, #-8]! - str x15, [sp, #-8]! - str x16, [sp, #-8]! - str x17, [sp, #-8]! - str x18, [sp, #-8]! - str x19, [sp, #-8]! - str x20, [sp, #-8]! - str x21, [sp, #-8]! - str x22, [sp, #-8]! - str x23, [sp, #-8]! - str x24, [sp, #-8]! - str x25, [sp, #-8]! - str x26, [sp, #-8]! - str x27, [sp, #-8]! - str x28, [sp, #-8]! - str x29, [sp, #-8]! - str x30, [sp, #-8]! - - mrs x18, sp_el0 - str x18, [sp, #-8]! - - mrs x18, esr_el1 - str x18, [sp, #-8]! - - mrs x18, spsr_el1 - str x18, [sp, #-8]! - - mrs x18, tpidrro_el0 - str x18, [sp, #-8]! - - mrs x18, tpidr_el0 - str x18, [sp, #-8]! - - str x18, [sp, #-8]! - - mrs x18, elr_el1 - str x18, [sp, #-8]!" - : : : : "volatile"); - - let sp: usize; - llvm_asm!("" : "={sp}"(sp) : : : "volatile"); - report_exception(&*(sp as *const InterruptStack)); - - llvm_asm!("ldr x18, [sp], #8 - msr elr_el1, x18 - - ldr x18, [sp], #8 - - ldr x18, [sp], #8 - msr tpidr_el0, x18 - - ldr x18, [sp], #8 - msr tpidrro_el0, x18 - - ldr x18, [sp], #8 - msr spsr_el1, x18 - - ldr x18, [sp], #8 - msr esr_el1, x18 - - ldr x18, [sp], #8 - msr sp_el0, x18 - - ldr x30, [sp], #8 - ldr x29, [sp], #8 - ldr x28, [sp], #8 - ldr x27, [sp], #8 - ldr x26, [sp], #8 - ldr x25, [sp], #8 - ldr x24, [sp], #8 - ldr x23, [sp], #8 - ldr x22, [sp], #8 - ldr x21, [sp], #8 - ldr x20, [sp], #8 - ldr x19, [sp], #8 - ldr x18, [sp], #8 - ldr x17, [sp], #8 - ldr x16, [sp], #8 - ldr x15, [sp], #8 - ldr x14, [sp], #8 - ldr x13, [sp], #8 - ldr x12, [sp], #8 - ldr x11, [sp], #8 - ldr x10, [sp], #8 - ldr x9, [sp], #8 - ldr x8, [sp], #8 - ldr x7, [sp], #8 - ldr x6, [sp], #8 - ldr x5, [sp], #8 - ldr x4, [sp], #8 - ldr x3, [sp], #8 - ldr x2, [sp], #8 - ldr x1, [sp], #8 - ldr x0, [sp], #8" - : : : : "volatile"); - - llvm_asm!("eret" :::: "volatile"); -} diff --git a/src/context/arch/aarch64.rs b/src/context/arch/aarch64.rs index 863766506a6ec5f1fc9b2d565599e6b1c9b37e74..3af07fd3a2c398e52b00b8260719f839c623635a 100644 --- a/src/context/arch/aarch64.rs +++ b/src/context/arch/aarch64.rs @@ -150,6 +150,42 @@ impl Context { value } + pub fn dump(&self) { + println!("elr_el1: 0x{:016x}", self.elr_el1); + println!("sp_el0: 0x{:016x}", self.sp_el0); + println!("ttbr0_el1: 0x{:016x}", self.ttbr0_el1); + println!("ttbr1_el1: 0x{:016x}", self.ttbr1_el1); + println!("tpidr_el0: 0x{:016x}", self.tpidr_el0); + println!("tpidrro_el0: 0x{:016x}", self.tpidrro_el0); + println!("rflags: 0x{:016x}", self.rflags); + println!("esr_el1: 0x{:016x}", self.esr_el1); + println!("padding: 0x{:016x}", self.padding); + println!("sp: 0x{:016x}", self.sp); + println!("lr: 0x{:016x}", self.lr); + println!("fp: 0x{:016x}", self.fp); + println!("x28: 0x{:016x}", self.x28); + println!("x27: 0x{:016x}", self.x27); + println!("x26: 0x{:016x}", self.x26); + println!("x25: 0x{:016x}", self.x25); + println!("x24: 0x{:016x}", self.x24); + println!("x23: 0x{:016x}", self.x23); + println!("x22: 0x{:016x}", self.x22); + println!("x21: 0x{:016x}", self.x21); + println!("x20: 0x{:016x}", self.x20); + println!("x19: 0x{:016x}", self.x19); + println!("x18: 0x{:016x}", self.x18); + println!("x17: 0x{:016x}", self.x17); + println!("x16: 0x{:016x}", self.x16); + println!("x15: 0x{:016x}", self.x15); + println!("x14: 0x{:016x}", self.x14); + println!("x13: 0x{:016x}", self.x13); + println!("x12: 0x{:016x}", self.x12); + println!("x11: 0x{:016x}", self.x11); + println!("x10: 0x{:016x}", self.x10); + println!("x9: 0x{:016x}", self.x9); + println!("x8: 0x{:016x}", self.x8); + } + #[cold] #[inline(never)] #[naked] diff --git a/src/syscall/process.rs b/src/syscall/process.rs index 05b66e266757429f01cca2c7e01e7bef5c258216..5e7dd27c080dc9e6b67a52e19ac4489ac3f06e4d 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -510,14 +510,25 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> { { if let Some(stack) = &mut context.kstack { unsafe { - let interrupt_stack_offset_from_stack_base = *(stack_base as *const u64) - stack_base as u64; - let mut interrupt_stack = &mut *(stack.as_mut_ptr().add(offset + interrupt_stack_offset_from_stack_base as usize) as *mut crate::arch::interrupt::InterruptStack); - interrupt_stack.tpidr_el0 = tcb_addr; + // stack_base contains a pointer to InterruptStack. Get its offset from + // stack_base itself + let istack_offset = *(stack_base as *const u64) - stack_base as u64; + + // Get the top of the new process' stack + let new_sp = stack.as_mut_ptr().add(offset); + + // Update the pointer to the InterruptStack to reflect the new process' + // stack. (Without this the pointer would be InterruptStack on the parent + // process' stack. + *(new_sp as *mut u64) = new_sp as u64 + istack_offset; + + // Update tpidr_el0 in the new process' InterruptStack + let mut interrupt_stack = &mut *(stack.as_mut_ptr().add(offset + istack_offset as usize) as *mut crate::arch::interrupt::InterruptStack); + interrupt_stack.iret.tpidr_el0 = tcb_addr; } } } - - + // Setup user TLS if let Some(mut tls) = tls_opt { // Copy TLS mapping