aarch64: implement exception interface & synchronous exception handler

master
equation314 6 years ago
parent 3386a793a5
commit 8c19499112

@ -1,62 +0,0 @@
//! Trapframe and context definitions for aarch64.
/// TODO
#[repr(C)]
#[derive(Debug)]
pub struct TrapFrame {
// TODO
}
///TODO
#[derive(Debug)]
pub struct Context {
// TODO
}
impl Context {
/// TODO
#[inline(never)]
pub unsafe extern fn switch(&mut self, target: &mut Self) {
unimplemented!()
}
/// TODO
pub unsafe fn null() -> Self {
unimplemented!()
}
/// TODO
pub unsafe fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, kstack_top: usize, cr3: usize) -> Self {
unimplemented!()
}
/// TODO
pub unsafe fn new_user_thread(entry_addr: usize, ustack_top: usize, kstack_top: usize, is32: bool, cr3: usize) -> Self {
unimplemented!()
}
/// TODO
pub unsafe fn new_fork(tf: &TrapFrame, kstack_top: usize, cr3: usize) -> Self {
unimplemented!()
}
}
#[inline(always)]
pub unsafe fn enable() {
unimplemented!()
}
#[inline(always)]
pub unsafe fn disable() {
unimplemented!()
}
#[inline(always)]
pub unsafe fn disable_and_store() -> usize {
unimplemented!()
}
#[inline(always)]
pub unsafe fn restore(flags: usize) {
unimplemented!()
}

@ -0,0 +1,60 @@
//! TrapFrame and context definitions for aarch64.
#[repr(C)]
#[derive(Default, Debug, Copy, Clone)]
pub struct TrapFrame {
pub elr: u64,
pub spsr: u64,
pub sp: u64,
pub tpidr: u64,
// pub q0to31: [u128; 32], // disable SIMD/FP registers
pub x1to29: [u64; 29],
pub __reserved: u64,
pub x30: u64, // lr
pub x0: u64,
}
///TODO
#[derive(Debug)]
pub struct Context {
// TODO
}
impl Context {
/// TODO
#[inline(never)]
pub unsafe extern "C" fn switch(&mut self, target: &mut Self) {
unimplemented!()
}
/// TODO
pub unsafe fn null() -> Self {
unimplemented!()
}
/// TODO
pub unsafe fn new_kernel_thread(
entry: extern "C" fn(usize) -> !,
arg: usize,
kstack_top: usize,
cr3: usize,
) -> Self {
unimplemented!()
}
/// TODO
pub unsafe fn new_user_thread(
entry_addr: usize,
ustack_top: usize,
kstack_top: usize,
is32: bool,
cr3: usize,
) -> Self {
unimplemented!()
}
/// TODO
pub unsafe fn new_fork(tf: &TrapFrame, kstack_top: usize, cr3: usize) -> Self {
unimplemented!()
}
}

@ -0,0 +1,67 @@
//! Trap handler
use super::context::TrapFrame;
use super::syndrome::Syndrome;
global_asm!(include_str!("trap.S"));
global_asm!(include_str!("vector.S"));
#[repr(u16)]
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Kind {
Synchronous = 0,
Irq = 1,
Fiq = 2,
SError = 3,
}
#[repr(u16)]
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Source {
CurrentSpEl0 = 0,
CurrentSpElx = 1,
LowerAArch64 = 2,
LowerAArch32 = 3,
}
#[repr(C)]
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct Info {
source: Source,
kind: Kind,
}
/// This function is called when an exception occurs. The `info` parameter
/// specifies the source and kind of exception that has occurred. The `esr` is
/// the value of the exception syndrome register. Finally, `tf` is a pointer to
/// the trap frame for the exception.
#[no_mangle]
pub extern "C" fn rust_trap(info: Info, esr: u32, tf: &mut TrapFrame) {
let syndrome = Syndrome::from(esr);
trace!("Interrupt: {:?} from: {:?}", syndrome, info);
match info.kind {
Kind::Synchronous => {
// syndrome is only valid with sync
match syndrome {
Syndrome::Brk(brk) => handle_break(brk, tf),
Syndrome::Svc(syscall) => handle_syscall(syscall, tf),
_ => ::trap::error(tf),
}
}
Kind::Irq => {
// TODO
}
_ => ::trap::error(tf),
}
::trap::before_return();
trace!("Interrupt end");
}
fn handle_break(num: u16, tf: &mut TrapFrame) {
tf.elr += 4; // Skip the current brk instruction
}
fn handle_syscall(num: u16, tf: &mut TrapFrame) {
// svc instruction has been skipped in syscall
println!("syscall {}", num);
}

@ -1,14 +1,20 @@
//! Interrupt handler implementation on raspi3.
//! Interrupt and exception for aarch64.
pub use self::context::*;
#[path = "context.rs"]
mod handler;
mod context;
mod syndrome;
pub use self::context::*;
pub use self::handler::*;
/// Initialize the trap to enable the interrupt.
/// Set the exception vector address
pub fn init() {
// TODO
// info!("interrupt: init end");
unsafe {
asm!(
"adr x0, __vectors;
msr vbar_el1, x0"
);
}
}
/// Enable the interrupt.

@ -0,0 +1,108 @@
//! Exception syndrome from ESR
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Fault {
AddressSize,
Translation,
AccessFlag,
Permission,
Alignment,
TlbConflict,
Other(u8),
}
impl From<u32> for Fault {
fn from(val: u32) -> Fault {
use self::Fault::*;
// IFSC or DFSC bits (ref: D10.2.39, Page 2457~2464).
match val & 0b111100 {
0b000000 => AddressSize,
0b000100 => Translation,
0b001000 => AccessFlag,
0b001100 => Permission,
0b100000 => Alignment,
0b110000 => TlbConflict,
_ => Other((val & 0b111111) as u8),
}
}
}
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Syndrome {
Unknown,
WfiWfe,
McrMrc,
McrrMrrc,
LdcStc,
SimdFp,
Vmrs,
Mrrc,
IllegalExecutionState,
Svc(u16),
Hvc(u16),
Smc(u16),
MsrMrsSystem,
InstructionAbort { kind: Fault, level: u8 },
PCAlignmentFault,
DataAbort { kind: Fault, level: u8 },
SpAlignmentFault,
TrappedFpu,
SError,
Breakpoint,
Step,
Watchpoint,
Brk(u16),
Other(u32),
}
/// Converts a raw syndrome value (ESR) into a `Syndrome` (ref: D1.10.4, D10.2.39).
impl From<u32> for Syndrome {
fn from(esr: u32) -> Syndrome {
use self::Syndrome::*;
let ec = esr >> 26;
let iss = esr & 0xFFFFFF;
match ec {
0b000000 => Unknown,
0b000001 => WfiWfe,
0b000011 => McrMrc,
0b000100 => McrrMrrc,
0b000101 => McrMrc,
0b000110 => LdcStc,
0b000111 => SimdFp,
0b001000 => Vmrs,
0b001100 => Mrrc,
0b001110 => IllegalExecutionState,
0b010001 => Svc((iss & 0xFFFF) as u16),
0b010010 => Hvc((iss & 0xFFFF) as u16),
0b010011 => Smc((iss & 0xFFFF) as u16),
0b010101 => Svc((iss & 0xFFFF) as u16),
0b010110 => Hvc((iss & 0xFFFF) as u16),
0b010111 => Smc((iss & 0xFFFF) as u16),
0b011000 => MsrMrsSystem,
0b100000 | 0b100001 => InstructionAbort {
kind: Fault::from(iss),
level: (iss & 0b11) as u8,
},
0b100010 => PCAlignmentFault,
0b100100 | 0b100101 => DataAbort {
kind: Fault::from(iss),
level: (iss & 0b11) as u8,
},
0b100110 => SpAlignmentFault,
0b101000 => TrappedFpu,
0b101100 => TrappedFpu,
0b101111 => SError,
0b110000 => Breakpoint,
0b110001 => Breakpoint,
0b110010 => Step,
0b110011 => Step,
0b110100 => Watchpoint,
0b110101 => Watchpoint,
0b111100 => Brk((iss & 0xFFFF) as u16),
other => Other(other),
}
}
}

@ -0,0 +1,103 @@
.section .text
.macro SAVE_ALL
# lr, x0 is saved in HANDLER
str x29, [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]!
stp x17, x18, [sp, #-16]!
stp x15, x16, [sp, #-16]!
stp x13, x14, [sp, #-16]!
stp x11, x12, [sp, #-16]!
stp x9, x10, [sp, #-16]!
stp x7, x8, [sp, #-16]!
stp x5, x6, [sp, #-16]!
stp x3, x4, [sp, #-16]!
stp x1, x2, [sp, #-16]!
# stp q30, q31, [sp, #-32]!
# stp q28, q29, [sp, #-32]!
# stp q26, q27, [sp, #-32]!
# stp q24, q25, [sp, #-32]!
# stp q22, q23, [sp, #-32]!
# stp q20, q21, [sp, #-32]!
# stp q18, q19, [sp, #-32]!
# stp q16, q17, [sp, #-32]!
# stp q14, q15, [sp, #-32]!
# stp q12, q13, [sp, #-32]!
# stp q10, q11, [sp, #-32]!
# stp q8, q9, [sp, #-32]!
# stp q6, q7, [sp, #-32]!
# stp q4, q5, [sp, #-32]!
# stp q2, q3, [sp, #-32]!
# stp q0, q1, [sp, #-32]!
mrs x2, tpidr_el0
mrs x1, sp_el0
stp x1, x2, [sp, #-16]!
mrs x2, spsr_el1
mrs x1, elr_el1
stp x1, x2, [sp, #-16]!
.endm
.macro RESTORE_ALL
ldp x1, x2, [sp], #16
msr elr_el1, x1
msr spsr_el1, x2
ldp x1, x2, [sp], #16
msr sp_el0, x1
msr tpidr_el0, x2
# ldp q0, q1, [sp], #32
# ldp q2, q3, [sp], #32
# ldp q4, q5, [sp], #32
# ldp q6, q7, [sp], #32
# ldp q8, q9, [sp], #32
# ldp q10, q11, [sp], #32
# ldp q12, q13, [sp], #32
# ldp q14, q15, [sp], #32
# ldp q16, q17, [sp], #32
# ldp q18, q19, [sp], #32
# ldp q20, q21, [sp], #32
# ldp q22, q23, [sp], #32
# ldp q24, q25, [sp], #32
# ldp q26, q27, [sp], #32
# ldp q28, q29, [sp], #32
# ldp q30, q31, [sp], #32
ldp x1, x2, [sp], #16
ldp x3, x4, [sp], #16
ldp x5, x6, [sp], #16
ldp x7, x8, [sp], #16
ldp x9, x10, [sp], #16
ldp x11, x12, [sp], #16
ldp x13, x14, [sp], #16
ldp x15, x16, [sp], #16
ldp x17, x18, [sp], #16
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
ldr x29, [sp], #16
ldp lr, x0, [sp], #16
.endm
.global __alltraps
__alltraps:
SAVE_ALL
# x0 is set in HANDLER
mrs x1, esr_el1
mov x2, sp
bl rust_trap
.global trap_ret
trap_ret:
RESTORE_ALL
eret

@ -0,0 +1,29 @@
.section .text
.macro HANDLER source kind
.align 7
stp lr, x0, [sp, #-16]!
mov x0, #\source
movk x0, #\kind, lsl #16
b __alltraps
.endm
.global __vectors
.align 11
__vectors:
HANDLER 0 0
HANDLER 0 1
HANDLER 0 2
HANDLER 0 3
HANDLER 1 0
HANDLER 1 1
HANDLER 1 2
HANDLER 1 3
HANDLER 2 0
HANDLER 2 1
HANDLER 2 2
HANDLER 2 3
HANDLER 3 0
HANDLER 3 1
HANDLER 3 2
HANDLER 3 3

@ -19,6 +19,7 @@ pub extern "C" fn rust_main() -> ! {
// First init log mod, so that we can print log info.
// FIXME
// ::logging::init();
interrupt::init();
super::fs::show_logo();
@ -30,6 +31,14 @@ pub extern "C" fn rust_main() -> ! {
'\u{7f}' => {
print!("\u{7f}");
}
'b' => unsafe {
println!("brk 233");
asm!("brk 233");
},
'c' => unsafe {
println!("svc 666");
asm!("svc 666");
},
' '...'\u{7e}' => {
print!("{}", c);
}

Loading…
Cancel
Save