aarch64: exception management and clone fixups
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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",
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
});
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user