Skip to content

Commit 922c163

Browse files
committed
fix(aarch64): pseudo implementation
1 parent fbaf10e commit 922c163

File tree

4 files changed

+63
-99
lines changed

4 files changed

+63
-99
lines changed

src/aarch64/context.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ impl fmt::Debug for TrapFrame {
3434
}
3535

3636
impl TrapFrame {
37+
/// Creates an empty context with all registers set to zero.
38+
pub const fn new() -> Self {
39+
unsafe { core::mem::zeroed() }
40+
}
41+
3742
/// Gets the 0th syscall argument.
3843
pub const fn arg0(&self) -> usize {
3944
self.r[0] as _

src/aarch64/trap.S

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,20 +73,18 @@
7373
b .Lexception_return
7474
.endm
7575

76-
.macro HANDLE_SYNC, source
76+
.macro HANDLE_SYNC
7777
.p2align 7
7878
SAVE_REGS
7979
mov x0, sp
80-
mov x1, \source
8180
bl handle_sync_exception
8281
b .Lexception_return
8382
.endm
8483

85-
.macro HANDLE_IRQ, source
84+
.macro HANDLE_IRQ
8685
.p2align 7
8786
SAVE_REGS
8887
mov x0, sp
89-
mov x1, \source
9088
bl handle_irq_exception
9189
b .Lexception_return
9290
.endm
@@ -102,14 +100,15 @@ exception_vector_base:
102100
INVALID_EXCP 3 0
103101

104102
// current EL, with SP_ELx
105-
HANDLE_SYNC 1
106-
HANDLE_IRQ 1
103+
HANDLE_SYNC
104+
HANDLE_IRQ
107105
INVALID_EXCP 2 1
108106
INVALID_EXCP 3 1
109107

108+
// TODO: handle user trap
110109
// lower EL, aarch64
111-
HANDLE_SYNC 2
112-
HANDLE_IRQ 2
110+
HANDLE_SYNC
111+
HANDLE_IRQ
113112
INVALID_EXCP 2 2
114113
INVALID_EXCP 3 2
115114

src/aarch64/trap.rs

Lines changed: 15 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,6 @@ enum TrapSource {
2929
LowerAArch32 = 3,
3030
}
3131

32-
impl TrapSource {
33-
fn is_from_user(&self) -> bool {
34-
matches!(self, TrapSource::LowerAArch64 | TrapSource::LowerAArch32)
35-
}
36-
}
37-
3832
#[unsafe(no_mangle)]
3933
fn invalid_exception(tf: &TrapFrame, kind: TrapKind, source: TrapSource) {
4034
panic!(
@@ -44,26 +38,21 @@ fn invalid_exception(tf: &TrapFrame, kind: TrapKind, source: TrapSource) {
4438
}
4539

4640
#[unsafe(no_mangle)]
47-
fn handle_irq_exception(tf: &mut TrapFrame, source: TrapSource) {
48-
crate::trap::pre_trap_callback(tf, source.is_from_user());
41+
fn handle_irq_exception(_tf: &mut TrapFrame) {
4942
handle_trap!(IRQ, 0);
50-
crate::trap::post_trap_callback(tf, source.is_from_user());
5143
}
5244

53-
fn handle_instruction_abort(tf: &TrapFrame, iss: u64, is_user: bool) {
54-
let mut access_flags = PageFaultFlags::EXECUTE;
55-
if is_user {
56-
access_flags |= PageFaultFlags::USER;
57-
}
45+
fn handle_instruction_abort(tf: &TrapFrame, iss: u64) {
46+
let access_flags = PageFaultFlags::EXECUTE;
5847
let vaddr = va!(FAR_EL1.get() as usize);
5948

49+
// TODO: fixup_exception
6050
// Only handle Translation fault and Permission fault
6151
if !matches!(iss & 0b111100, 0b0100 | 0b1100) // IFSC or DFSC bits
62-
|| !handle_trap!(PAGE_FAULT, vaddr, access_flags, is_user)
52+
|| !handle_trap!(PAGE_FAULT, vaddr, access_flags)
6353
{
6454
panic!(
65-
"Unhandled {} Instruction Abort @ {:#x}, fault_vaddr={:#x}, ESR={:#x} ({:?}):\n{:#x?}\n{}",
66-
if is_user { "EL0" } else { "EL1" },
55+
"Unhandled EL1 Instruction Abort @ {:#x}, fault_vaddr={:#x}, ESR={:#x} ({:?}):\n{:#x?}\n{}",
6756
tf.elr,
6857
vaddr,
6958
ESR_EL1.get(),
@@ -74,26 +63,23 @@ fn handle_instruction_abort(tf: &TrapFrame, iss: u64, is_user: bool) {
7463
}
7564
}
7665

77-
fn handle_data_abort(tf: &TrapFrame, iss: u64, is_user: bool) {
66+
fn handle_data_abort(tf: &TrapFrame, iss: u64) {
7867
let wnr = (iss & (1 << 6)) != 0; // WnR: Write not Read
7968
let cm = (iss & (1 << 8)) != 0; // CM: Cache maintenance
80-
let mut access_flags = if wnr & !cm {
69+
let access_flags = if wnr & !cm {
8170
PageFaultFlags::WRITE
8271
} else {
8372
PageFaultFlags::READ
8473
};
85-
if is_user {
86-
access_flags |= PageFaultFlags::USER;
87-
}
8874
let vaddr = va!(FAR_EL1.get() as usize);
8975

76+
// TODO: fixup_exception
9077
// Only handle Translation fault and Permission fault
9178
if !matches!(iss & 0b111100, 0b0100 | 0b1100) // IFSC or DFSC bits
92-
|| !handle_trap!(PAGE_FAULT, vaddr, access_flags, is_user)
79+
|| !handle_trap!(PAGE_FAULT, vaddr, access_flags)
9380
{
9481
panic!(
95-
"Unhandled {} Data Abort @ {:#x}, fault_vaddr={:#x}, ESR={:#x} ({:?}):\n{:#x?}\n{}",
96-
if is_user { "EL0" } else { "EL1" },
82+
"Unhandled EL1 Data Abort @ {:#x}, fault_vaddr={:#x}, ESR={:#x} ({:?}):\n{:#x?}\n{}",
9783
tf.elr,
9884
vaddr,
9985
ESR_EL1.get(),
@@ -105,19 +91,12 @@ fn handle_data_abort(tf: &TrapFrame, iss: u64, is_user: bool) {
10591
}
10692

10793
#[unsafe(no_mangle)]
108-
fn handle_sync_exception(tf: &mut TrapFrame, source: TrapSource) {
94+
fn handle_sync_exception(tf: &mut TrapFrame) {
10995
let esr = ESR_EL1.extract();
11096
let iss = esr.read(ESR_EL1::ISS);
111-
crate::trap::pre_trap_callback(tf, source.is_from_user());
11297
match esr.read_as_enum(ESR_EL1::EC) {
113-
#[cfg(feature = "uspace")]
114-
Some(ESR_EL1::EC::Value::SVC64) => {
115-
tf.r[0] = crate::trap::handle_syscall(tf, tf.r[8] as usize) as u64;
116-
}
117-
Some(ESR_EL1::EC::Value::InstrAbortLowerEL) => handle_instruction_abort(tf, iss, true),
118-
Some(ESR_EL1::EC::Value::InstrAbortCurrentEL) => handle_instruction_abort(tf, iss, false),
119-
Some(ESR_EL1::EC::Value::DataAbortLowerEL) => handle_data_abort(tf, iss, true),
120-
Some(ESR_EL1::EC::Value::DataAbortCurrentEL) => handle_data_abort(tf, iss, false),
98+
Some(ESR_EL1::EC::Value::InstrAbortCurrentEL) => handle_instruction_abort(tf, iss),
99+
Some(ESR_EL1::EC::Value::DataAbortCurrentEL) => handle_data_abort(tf, iss),
121100
Some(ESR_EL1::EC::Value::Brk64) => {
122101
debug!("BRK #{:#x} @ {:#x} ", iss, tf.elr);
123102
tf.elr += 4;
@@ -128,10 +107,9 @@ fn handle_sync_exception(tf: &mut TrapFrame, source: TrapSource) {
128107
tf.elr,
129108
esr.get(),
130109
esr.read(ESR_EL1::EC),
131-
esr.read(ESR_EL1::ISS),
110+
iss,
132111
tf.backtrace()
133112
);
134113
}
135114
}
136-
crate::trap::post_trap_callback(tf, source.is_from_user());
137115
}

src/aarch64/uspace.rs

Lines changed: 36 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
//! Structures and functions for user space.
22
3+
use core::ops::{Deref, DerefMut};
4+
5+
use aarch64_cpu::registers::ESR_EL1;
36
use memory_addr::VirtAddr;
47

5-
use crate::TrapFrame;
8+
use crate::{
9+
trap::{ExceptionKind, ReturnReason},
10+
TrapFrame,
11+
};
612

713
/// Context to enter user space.
8-
pub struct UspaceContext(TrapFrame);
14+
pub struct UserContext(TrapFrame);
915

10-
impl UspaceContext {
16+
impl UserContext {
1117
/// Creates an empty context with all registers set to zero.
1218
pub const fn empty() -> Self {
13-
unsafe { core::mem::MaybeUninit::zeroed().assume_init() }
19+
Self(TrapFrame::new())
1420
}
1521

1622
/// Creates a new context with the given entry point, user stack pointer,
@@ -42,68 +48,44 @@ impl UspaceContext {
4248
///
4349
/// It restores the user registers and jumps to the user entry point
4450
/// (saved in `elr`).
45-
/// When an exception or syscall occurs, the kernel stack pointer is
46-
/// switched to `kstack_top`.
47-
///
48-
/// # Safety
4951
///
50-
/// This function is unsafe because it changes processor mode and the stack.
51-
pub unsafe fn enter_uspace(&self, kstack_top: VirtAddr) -> ! {
52-
crate::asm::disable_irqs();
53-
// We do not handle traps that occur at the current exception level,
54-
// so the kstack ptr(`sp_el1`) will not change during running in user space.
55-
// Then we don't need to save the `sp_el1` to the taskctx.
56-
unsafe {
57-
core::arch::asm!(
58-
"
59-
mov sp, x1
60-
61-
// backup kernel tpidr_el0
62-
mrs x1, tpidr_el0
63-
msr tpidrro_el0, x1
64-
65-
ldp x11, x12, [x0, 33 * 8]
66-
ldp x9, x10, [x0, 31 * 8]
67-
msr sp_el0, x9
68-
msr tpidr_el0, x10
69-
msr elr_el1, x11
70-
msr spsr_el1, x12
71-
72-
ldr x30, [x0, 30 * 8]
73-
ldp x28, x29, [x0, 28 * 8]
74-
ldp x26, x27, [x0, 26 * 8]
75-
ldp x24, x25, [x0, 24 * 8]
76-
ldp x22, x23, [x0, 22 * 8]
77-
ldp x20, x21, [x0, 20 * 8]
78-
ldp x18, x19, [x0, 18 * 8]
79-
ldp x16, x17, [x0, 16 * 8]
80-
ldp x14, x15, [x0, 14 * 8]
81-
ldp x12, x13, [x0, 12 * 8]
82-
ldp x10, x11, [x0, 10 * 8]
83-
ldp x8, x9, [x0, 8 * 8]
84-
ldp x6, x7, [x0, 6 * 8]
85-
ldp x4, x5, [x0, 4 * 8]
86-
ldp x2, x3, [x0, 2 * 8]
87-
ldp x0, x1, [x0]
88-
eret",
89-
in("x0") &self.0,
90-
in("x1") kstack_top.as_usize() ,
91-
options(noreturn),
92-
)
93-
}
52+
/// This function returns when an exception or syscall occurs.
53+
pub fn run(&mut self) -> ReturnReason {
54+
// TODO: implement
55+
ReturnReason::Unknown
9456
}
9557
}
9658

97-
impl core::ops::Deref for UspaceContext {
59+
impl Deref for UserContext {
9860
type Target = TrapFrame;
9961

10062
fn deref(&self) -> &Self::Target {
10163
&self.0
10264
}
10365
}
10466

105-
impl core::ops::DerefMut for UspaceContext {
67+
impl DerefMut for UserContext {
10668
fn deref_mut(&mut self) -> &mut Self::Target {
10769
&mut self.0
10870
}
10971
}
72+
73+
impl From<TrapFrame> for UserContext {
74+
fn from(tf: TrapFrame) -> Self {
75+
Self(tf)
76+
}
77+
}
78+
79+
#[derive(Debug, Clone, Copy)]
80+
pub struct ExceptionInfo {
81+
pub ec: ESR_EL1::EC::Value,
82+
pub il: bool,
83+
pub iss: u32,
84+
}
85+
86+
impl ExceptionInfo {
87+
pub fn kind(&self) -> ExceptionKind {
88+
// TODO: implement
89+
ExceptionKind::Other
90+
}
91+
}

0 commit comments

Comments
 (0)