-
Notifications
You must be signed in to change notification settings - Fork 12
Don't trash the LR returned from _undefined_handler. #30
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
Merged
jonathanpallant
merged 4 commits into
rust-embedded:main
from
thejpster:fix-exception-return
Apr 27, 2025
Merged
Changes from 2 commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
examples/mps3-an536/reference/abt-exception-t32-armv8r-none-eabihf.out
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
Hello, this is an data abort exception example | ||
data abort occurred | ||
DFSR (Fault Status Register): DFSR { ext=false wnr=false Domain=0b0010 Status=0b00001 } | ||
DFSR Status: Ok(AlignmentFault) | ||
caught unaligned_from_t32 | ||
caught fault on COUNTER | ||
Doing it again | ||
data abort occurred | ||
DFSR (Fault Status Register): DFSR { ext=false wnr=false Domain=0b0010 Status=0b00001 } | ||
DFSR Status: Ok(AlignmentFault) | ||
caught unaligned_from_t32 | ||
caught fault on COUNTER | ||
Skipping instruction | ||
Recovered from fault OK! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
examples/mps3-an536/reference/undef-exception-a32-armv8r-none-eabihf.out
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,8 @@ | ||
Hello, this is a undef exception example | ||
undefined abort occurred | ||
caught udf_from_a32 | ||
Doing it again | ||
undefined abort occurred | ||
caught udf_from_a32 | ||
Skipping instruction | ||
Recovered from fault OK! |
3 changes: 3 additions & 0 deletions
3
examples/mps3-an536/reference/undef-exception-t32-armv8r-none-eabihf.out
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,8 @@ | ||
Hello, this is a undef exception example | ||
undefined abort occurred | ||
caught udf_from_t32 | ||
Doing it again | ||
undefined abort occurred | ||
caught udf_from_t32 | ||
Skipping instruction | ||
Recovered from fault OK! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
//! Example triggering an data abort exception. | ||
|
||
#![no_std] | ||
#![no_main] | ||
|
||
use core::sync::atomic::{AtomicU32, Ordering}; | ||
|
||
use cortex_ar::register::{Dfar, Dfsr, Sctlr}; | ||
// pull in our start-up code | ||
use mps3_an536 as _; | ||
|
||
use semihosting::println; | ||
|
||
#[no_mangle] | ||
static COUNTER: AtomicU32 = AtomicU32::new(0); | ||
|
||
/// The entry-point to the Rust application. | ||
/// | ||
/// It is called by the start-up. | ||
#[no_mangle] | ||
pub extern "C" fn kmain() -> ! { | ||
main(); | ||
} | ||
|
||
/// The main function of our Rust application. | ||
#[export_name = "main"] | ||
#[allow(unreachable_code)] | ||
fn main() -> ! { | ||
// Enable alignment check for Armv7-R. Was not required | ||
// on Cortex-A for some reason, even though the bit was not set. | ||
enable_alignment_check(); | ||
|
||
println!("Hello, this is an data abort exception example"); | ||
unsafe { | ||
// Unaligned read | ||
unaligned_from_a32(); | ||
} | ||
|
||
println!("Recovered from fault OK!"); | ||
|
||
semihosting::process::exit(0); | ||
} | ||
|
||
// These functions are written in assembly | ||
extern "C" { | ||
fn unaligned_from_a32(); | ||
} | ||
|
||
core::arch::global_asm!( | ||
r#" | ||
// fn unaligned_from_a32(); | ||
.arm | ||
.global unaligned_from_a32 | ||
.type unaligned_from_a32, %function | ||
unaligned_from_a32: | ||
ldr r0, =COUNTER | ||
add r0, r0, 1 | ||
ldr r0, [r0] | ||
bx lr | ||
.size unaligned_from_a32, . - unaligned_from_a32 | ||
"# | ||
); | ||
|
||
fn enable_alignment_check() { | ||
let mut sctrl = Sctlr::read(); | ||
sctrl.set_a(true); | ||
Sctlr::write(sctrl); | ||
} | ||
|
||
fn disable_alignment_check() { | ||
let mut sctrl = Sctlr::read(); | ||
sctrl.set_a(false); | ||
Sctlr::write(sctrl); | ||
} | ||
|
||
#[unsafe(no_mangle)] | ||
unsafe extern "C" fn _undefined_handler(_addr: u32) -> ! { | ||
panic!("unexpected undefined exception"); | ||
} | ||
|
||
#[unsafe(no_mangle)] | ||
unsafe extern "C" fn _prefetch_handler(_addr: u32) -> ! { | ||
panic!("unexpected prefetch exception"); | ||
} | ||
|
||
#[unsafe(no_mangle)] | ||
unsafe extern "C" fn _abort_handler(addr: usize) -> usize { | ||
println!("data abort occurred"); | ||
// If this is not disabled, reading DFAR will trigger an alignment fault on Armv8-R, leading | ||
// to a loop. | ||
disable_alignment_check(); | ||
let dfsr = Dfsr::read(); | ||
println!("DFSR (Fault Status Register): {:?}", dfsr); | ||
println!("DFSR Status: {:?}", dfsr.status()); | ||
let dfar = Dfar::read(); | ||
enable_alignment_check(); | ||
|
||
// note the fault isn't at the start of the function | ||
let expect_fault_at = unaligned_from_a32 as usize + 8; | ||
|
||
if addr == expect_fault_at { | ||
println!("caught unaligned_from_a32"); | ||
} else { | ||
println!( | ||
"Bad fault address {:08x} is not {:08x}", | ||
addr, expect_fault_at | ||
); | ||
} | ||
|
||
let expect_fault_from = core::ptr::addr_of!(COUNTER) as usize + 1; | ||
|
||
if dfar.0 as usize == expect_fault_from { | ||
println!("caught fault on COUNTER"); | ||
} else { | ||
println!( | ||
"Bad DFAR address {:08x} is not {:08x}", | ||
dfar.0, expect_fault_from | ||
); | ||
} | ||
|
||
match COUNTER.fetch_add(1, Ordering::Relaxed) { | ||
0 => { | ||
// first time, huh? | ||
// go back and do it again | ||
println!("Doing it again"); | ||
addr | ||
} | ||
1 => { | ||
// second time, huh? | ||
// go back but skip the instruction | ||
println!("Skipping instruction"); | ||
addr + 4 | ||
} | ||
_ => { | ||
// we've faulted thrice - time to quit | ||
println!("We triple faulted"); | ||
semihosting::process::abort(); | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
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.
Am I understanding it correctly that the LR returned by the C/Rust handler is stored here, which does not necessarily have to be the adjusted LR?
Maybe "overwrite the saved LR with the one returned by the C handler" is better?
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.
yeah, fair, the handler could have but might not have adjusted the value
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.
fixed