-
Notifications
You must be signed in to change notification settings - Fork 8
Add default exception handlers and simplify default handler #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add default exception handlers and simplify default handler #16
Conversation
robamu
commented
Mar 25, 2025
- Add three new default assembly exception handlers for data abort, prefetch abort and undefined exception. These handlers implement the ARM exception return model.
- The new ASM handlers will call the Rust _default_handler by default, but the Rust handler can be overriden with _undefined_handler, _prefetch_handler and _abort_handler
- The default handler is now a simple empty permanent loop
cortex-a-rt/src/lib.rs
Outdated
// state save from compiled code | ||
srsfd sp!, {und_mode} | ||
"#, | ||
save_context_ignore_fpu!(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's worth a comment explaining why FPU regs don't have to be saved here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm.. Maybe we should save them? I have not put too much thought in this. I searched the code for various exception handlers (did not find much), none of them really saved the FPU regs. But I guess if the exception return works, it would be correct to safe them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The handler could touch them, so I think they should be saved when you have the FPU feature on or are using the eabihf ABI.
cortex-r-rt/src/lib.rs
Outdated
//! | ||
//! ```rust | ||
//! #[unsafe(no_mangle)] | ||
//! extern "C" fn boot_core(cpu_id: u32) -> !; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the right function name? I'm fine with harmonising A and R run-times here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, copy & paste error.. Harmonizing them should not be too difficult actually. If I try this, should I do it in a separate PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, a separate PR I think
examples/mps3-an536/src/bin/svc.rs
Outdated
@@ -30,7 +30,7 @@ pub fn main() -> ! { | |||
} | |||
|
|||
/// This is our SVC exception handler | |||
#[no_mangle] | |||
#[unsafe(no_mangle)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this OK with our MRSV?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would CI not catch this? This is edition 2024 related I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://doc.rust-lang.org/edition-guide/rust-2024/unsafe-attributes.html
To reflect the fact that these attributes can undermine Rust's safety guarantees, they are now considered "unsafe" and should be written as follows:
So it was added in Rust 1.82, and works in any edition. Edition 2024 just makes the new style mandatory.
This looks amazing. Just a couple of minor notes. |
cortex-a-rt/src/lib.rs
Outdated
// state save from compiled code | ||
srsfd sp!, {und_mode} | ||
"#, | ||
save_context_ignore_fpu!(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm.. Maybe we should save them? I have not put too much thought in this. I searched the code for various exception handlers (did not find much), none of them really saved the FPU regs. But I guess if the exception return works, it would be correct to safe them?
examples/mps3-an536/src/bin/svc.rs
Outdated
@@ -30,7 +30,7 @@ pub fn main() -> ! { | |||
} | |||
|
|||
/// This is our SVC exception handler | |||
#[no_mangle] | |||
#[unsafe(no_mangle)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would CI not catch this? This is edition 2024 related I think.
cortex-a-rt/src/lib.rs
Outdated
//! * `_asm_fiq_handler` - a naked function to call when a Fast Interrupt | ||
//! Request (FIQ) occurs. Our linker script PROVIDEs a default function at | ||
//! `_asm_default_fiq_handler` but you can override it. | ||
//! * `_asm_undefined_handler` - a naked function to call when an Undefined | ||
//! Exception occurs. Our linker script PROVIDEs a default function at | ||
//! `_asm_default_handler` but you can override it. | ||
//! `_asm_defeault_undefined_handler` but you can override it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops
cortex-r-rt/src/lib.rs
Outdated
//! | ||
//! ```rust | ||
//! #[unsafe(no_mangle)] | ||
//! extern "C" fn boot_core(cpu_id: u32) -> !; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, copy & paste error.. Harmonizing them should not be too difficult actually. If I try this, should I do it in a separate PR?
I now use the regular context saving/ restoration, tests still all run without issues. |
By the way, I manually checked the faulting address argument against the binary disassembly when I wrote the tests, but I do not check them in the tests anymore. I think this would lead to extremely brittle tests, if a new version of the nightly compiler generates code with different layout. |
4f36a44
to
7d892c7
Compare
I think that's fine. Another PR could try and run |
cortex-a-rt/src/lib.rs
Outdated
tst r4, {t_bit} | ||
// If not in Thumb mode, branch to not_thumb | ||
beq not_thumb | ||
subs lr, lr, #2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a sneaky tab snuck in.
cortex-r-rt/src/lib.rs
Outdated
tst r4, {t_bit} | ||
// If not in Thumb mode, branch to not_thumb | ||
beq not_thumb | ||
subs lr, lr, #2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
subs lr, lr, #2 | |
subs lr, lr, #2 |
cortex-r-rt/src/lib.rs
Outdated
.type _asm_default_prefetch_handler, %function | ||
_asm_default_prefetch_handler: | ||
// Subtract 4 from the stored LR, see p.1212 of the ARMv7-A architecture manual. | ||
subs lr, lr, #4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
subs lr, lr, #4 | |
subs lr, lr, #4 |
cortex-r-rt/src/lib.rs
Outdated
.type _asm_default_abort_handler, %function | ||
_asm_default_abort_handler: | ||
// Subtract 8 from the stored LR, see p.1214 of the ARMv7-A architecture manual. | ||
subs lr, lr, #8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
subs lr, lr, #8 | |
subs lr, lr, #8 |
|
||
#[no_mangle] | ||
unsafe extern "C" fn _undefined_handler(_faulting_instruction: u32) { | ||
static mut COUNTER: u32 = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re-entering this function using a static mut is UB. It should probably be at AtomicU32 using fetch_add.
|
||
#[unsafe(no_mangle)] | ||
unsafe extern "C" fn _prefetch_handler(_faulting_instruction: u32) { | ||
static mut COUNTER: u32 = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re-entering this function using a static mut is UB. It should probably be at AtomicU32 using fetch_add.
|
||
#[unsafe(no_mangle)] | ||
unsafe extern "C" fn _abort_handler(_faulting_instruction: u32) { | ||
static mut COUNTER: u32 = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re-entering this function using a static mut is UB. It should probably be at AtomicU32 using fetch_add.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, replaced those with Atomics.
I did a second pass on my desktop rather than my phone, and I observed some misalignment in the assembly code. |
- Add three new default assembly exception handlers for data abort, prefetch abort and undefined exception. These handlers implement the ARM exception return model. - The new ASM handlers will call the Rust _default_handler by default, but the Rust handler can be overriden with _undefined_handler, _prefetch_handler and _abort_handler - The default handler is now a simple empty permanent loop
04cd215
to
ca2c26c
Compare
One thing that would be good is tests for the mps3-an536, but we can't run those in CI, I'll just open a ticket. |