diff --git a/src/arch/aarch64/interrupt/exception.rs b/src/arch/aarch64/interrupt/exception.rs index 5c92846ec9..fc1b684382 100644 --- a/src/arch/aarch64/interrupt/exception.rs +++ b/src/arch/aarch64/interrupt/exception.rs @@ -6,7 +6,6 @@ use crate::{ memory::{ArchIntCtx, GenericPfFlags}, syscall, syscall::flag::*, - with_exception_stack, }; use super::InterruptStack; @@ -173,12 +172,12 @@ unsafe fn pf_inner(stack: &mut InterruptStack, ty: u8, from: &str) -> bool { exception_stack!(synchronous_exception_at_el0, |stack| { match exception_code(stack.iret.esr_el1) { - 0b010101 => with_exception_stack!(|stack| { + 0b010101 => { let scratch = &stack.scratch; syscall::syscall( scratch.x8, scratch.x0, scratch.x1, scratch.x2, scratch.x3, scratch.x4, stack, - ) - }), + ); + } ty => { if !pf_inner(stack, ty as u8, "sync_exc_el0") { diff --git a/src/arch/aarch64/interrupt/handler.rs b/src/arch/aarch64/interrupt/handler.rs index f43a2019be..82c8fb66b5 100644 --- a/src/arch/aarch64/interrupt/handler.rs +++ b/src/arch/aarch64/interrupt/handler.rs @@ -113,6 +113,22 @@ pub struct InterruptStack { } impl InterruptStack { + pub fn setup_minimal(&mut self, ip: usize, _singlestep: bool) { + self.set_instr_pointer(ip); + } + pub fn set_stack_pointer(&mut self, sp: usize) { + self.iret.sp_el0 = sp; + } + pub fn stack_pointer(&self) -> usize { + self.iret.sp_el0 + } + pub fn set_instr_pointer(&mut self, ip: usize) { + self.iret.elr_el1 = ip; + } + // TODO: This can maybe be done in userspace? + pub fn set_syscall_ret_reg(&mut self, ret: usize) { + self.scratch.x0 = ret; + } pub fn dump(&self) { self.iret.dump(); self.scratch.dump(); @@ -258,24 +274,6 @@ macro_rules! aarch64_asm { }; } -#[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 { () => { @@ -377,21 +375,12 @@ macro_rules! pop_special { #[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) { - let _guard = $crate::ptrace::set_process_regs($stack); - - $code - } - inner(&mut *stack); + #[naked] + unsafe extern "C" fn $name(stack: &mut $crate::arch::aarch64::interrupt::InterruptStack) { + unsafe extern "C" fn inner($stack: &mut $crate::arch::aarch64::interrupt::InterruptStack) { + $code } - - function!($name => { + core::arch::asm!(concat!( // Backup all userspace registers to stack push_preserved!(), push_scratch!(), @@ -400,7 +389,7 @@ macro_rules! exception_stack { // Call inner function with pointer to stack "mov x29, sp\n", "mov x0, sp\n", - "bl __exception_", stringify!($name), "\n", + "bl {}", // Restore all userspace registers pop_special!(), @@ -408,7 +397,18 @@ macro_rules! exception_stack { pop_preserved!(), "eret\n", - }); + ), sym inner, options(noreturn)); } }; } +#[naked] +pub unsafe extern "C" fn enter_usermode() -> ! { + core::arch::asm!(concat!( + // Restore all userspace registers + pop_special!(), + pop_scratch!(), + pop_preserved!(), + + "eret\n", + ), options(noreturn)); +} diff --git a/src/arch/aarch64/interrupt/syscall.rs b/src/arch/aarch64/interrupt/syscall.rs index 906d0ffc05..757cbe5f53 100644 --- a/src/arch/aarch64/interrupt/syscall.rs +++ b/src/arch/aarch64/interrupt/syscall.rs @@ -52,11 +52,4 @@ pub struct SyscallStack { pub x1: usize, pub x0: usize, } - -#[macro_export] -macro_rules! with_exception_stack { - (|$stack:ident| $code:block) => {{ - let $stack = &mut *$stack; - (*$stack).scratch.x0 = $code; - }}; -} +pub use super::handler::enter_usermode; diff --git a/src/context/arch/aarch64.rs b/src/context/arch/aarch64.rs index 68cd2e9ecd..15ce949788 100644 --- a/src/context/arch/aarch64.rs +++ b/src/context/arch/aarch64.rs @@ -23,6 +23,8 @@ pub static CONTEXT_SWITCH_LOCK: AtomicBool = AtomicBool::new(false); // 512 bytes for registers, extra bytes for fpcr and fpsr pub const KFX_ALIGN: usize = 16; +pub const KSTACK_SIZE: usize = 65536; +pub const KSTACK_ALIGN: usize = 16; #[derive(Clone, Debug)] pub struct Context {