Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ jobs:
uses: taiki-e/install-action@just
- name: Install Rust
run: |
rustup install nightly-2026-01-26
rustup component add rust-src --toolchain nightly-2026-01-26
rustup default nightly-2026-01-26
rustup install nightly-2026-02-26
rustup component add rust-src --toolchain nightly-2026-02-26
rustup default nightly-2026-02-26
- name: Build
run: |
just build-tier3 ${{ matrix.target }}
Expand All @@ -89,9 +89,9 @@ jobs:
uses: taiki-e/install-action@just
- name: Install Rust
run: |
rustup install nightly-2026-01-26
rustup component add rust-src --toolchain nightly-2026-01-26
rustup default nightly-2026-01-26
rustup install nightly-2026-02-26
rustup component add rust-src --toolchain nightly-2026-02-26
rustup default nightly-2026-02-26
- name: Build
run: |
just build-tier3-no-atomics ${{ matrix.target }}
Expand Down
2 changes: 1 addition & 1 deletion examples/mps3-an536/rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[toolchain]
channel = "nightly-2026-01-26"
channel = "nightly-2026-02-26"
targets = [
"armv8r-none-eabihf",
]
Expand Down
42 changes: 15 additions & 27 deletions examples/mps3-an536/src/bin/abt-exception-a32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ fn main() -> ! {
enable_alignment_check();

println!("Hello, this is an data abort exception example");
unsafe {
// Unaligned read
unaligned_from_a32();
}

// Unaligned read
unaligned_from_a32();

// turn it off before we do the stack dump on exit, because println! has been
// observed to do unaligned reads.
Expand All @@ -37,26 +36,17 @@ fn main() -> ! {
mps3_an536::exit(0);
}

// These functions are written in assembly
unsafe extern "C" {
fn unaligned_from_a32();
#[unsafe(naked)]
#[instruction_set(arm::a32)]
extern "C" fn unaligned_from_a32() {
core::arch::naked_asm!(
"ldr r0, =COUNTER",
"adds r0, r0, 1",
"ldr r0, [r0]",
"bx lr",
);
}

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);
Expand Down Expand Up @@ -92,28 +82,26 @@ unsafe fn data_abort_handler(addr: usize) -> usize {
enable_alignment_check();

// note the fault isn't at the start of the function
let expect_fault_at = unaligned_from_a32 as unsafe extern "C" fn() as usize + 8;
let expect_fault_at = unaligned_from_a32 as extern "C" fn() as usize + 8;

if addr == expect_fault_at {
println!("caught unaligned_from_a32");
} else {
println!(
panic!(
"Bad fault address {:08x} is not {:08x}",
addr, expect_fault_at
);
semihosting::process::abort();
}

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!(
panic!(
"Bad DFAR address {:08x} is not {:08x}",
dfar.0, expect_fault_from
);
semihosting::process::abort();
}

match COUNTER.fetch_add(1, Ordering::Relaxed) {
Expand Down
41 changes: 14 additions & 27 deletions examples/mps3-an536/src/bin/abt-exception-t32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@ fn main() -> ! {
enable_alignment_check();

println!("Hello, this is an data abort exception example");
unsafe {
// Unaligned read
unaligned_from_t32();
}
// Unaligned read
unaligned_from_t32();

// turn it off before we do the stack dump on exit, because println! has been
// observed to do unaligned reads.
Expand All @@ -37,26 +35,17 @@ fn main() -> ! {
mps3_an536::exit(0);
}

// These functions are written in assembly
unsafe extern "C" {
fn unaligned_from_t32();
#[unsafe(naked)]
#[instruction_set(arm::t32)]
extern "C" fn unaligned_from_t32() {
core::arch::naked_asm!(
"ldr r0, =COUNTER",
"adds r0, r0, 1",
"ldr r0, [r0]",
"bx lr",
);
}

core::arch::global_asm!(
r#"
// fn unaligned_from_t32();
.thumb
.global unaligned_from_t32
.type unaligned_from_t32, %function
unaligned_from_t32:
ldr r0, =COUNTER
add r0, r0, 1
ldr r0, [r0]
bx lr
.size unaligned_from_t32, . - unaligned_from_t32
"#
);

fn enable_alignment_check() {
let mut sctrl = Sctlr::read();
sctrl.set_a(true);
Expand Down Expand Up @@ -92,28 +81,26 @@ unsafe fn data_abort_handler(addr: usize) -> usize {
enable_alignment_check();

// note the fault isn't at the start of the function
let expect_fault_at = unaligned_from_t32 as unsafe extern "C" fn() as usize + 5;
let expect_fault_at = unaligned_from_t32 as extern "C" fn() as usize + 3;

if addr == expect_fault_at {
println!("caught unaligned_from_t32");
} else {
println!(
panic!(
"Bad fault address {:08x} is not {:08x}",
addr, expect_fault_at
);
semihosting::process::abort();
}

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!(
panic!(
"Bad DFAR address {:08x} is not {:08x}",
dfar.0, expect_fault_from
);
semihosting::process::abort();
}

match COUNTER.fetch_add(1, Ordering::Relaxed) {
Expand Down
53 changes: 27 additions & 26 deletions examples/mps3-an536/src/bin/el2_hello.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,17 @@ fn main() -> ! {
//
// Unlike the default routine, it does not initialise any other stacks, or
// switch to EL1 mode.
core::arch::global_asm!(
r#"
// Work around https://github.com/rust-lang/rust/issues/127269
.fpu vfp3-d16

.section .text.start

.global _start
.type _start, %function
_start:
//
/// # Safety
///
/// This function should not be called manually. It should only be called on reset
/// from the reset vector.
#[unsafe(naked)]
#[unsafe(no_mangle)]
#[instruction_set(arm::t32)]
pub unsafe extern "C" fn _start() {
core::arch::naked_asm!(
r#"
// Set stack pointer
ldr sp, =_hyp_stack
// Set the HVBAR (for EL2) to _vector_table
Expand Down Expand Up @@ -80,19 +81,19 @@ core::arch::global_asm!(
bl kmain
// In case the application returns, loop forever
b .
.size _start, . - _start
"#,
hactlr_bits = const {
Hactlr::new_with_raw_value(0)
.with_cpuactlr(true)
.with_cdbgdci(true)
.with_flashifregionr(true)
.with_periphpregionr(true)
.with_qosr(true)
.with_bustimeoutr(true)
.with_intmonr(true)
.with_err(true)
.with_testr1(true)
.raw_value()
},
);
"#,
hactlr_bits = const {
Hactlr::new_with_raw_value(0)
.with_cpuactlr(true)
.with_cdbgdci(true)
.with_flashifregionr(true)
.with_periphpregionr(true)
.with_qosr(true)
.with_bustimeoutr(true)
.with_intmonr(true)
.with_err(true)
.with_testr1(true)
.raw_value()
},
);
}
37 changes: 14 additions & 23 deletions examples/mps3-an536/src/bin/prefetch-exception-a32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,35 +21,26 @@ fn main() -> ! {

// A BKPT instruction triggers a Prefetch Abort except when Halting debug-mode is enabled.
// See p. 2038 of ARMv7-M Architecture Reference Manual
unsafe {
// trigger an prefetch abort exception, from A32 (Arm) mode
bkpt_from_a32();
}

// trigger an prefetch abort exception, from A32 (Arm) mode
bkpt_from_a32();

println!("Recovered from fault OK!");

mps3_an536::exit(0);
}

// These functions are written in assembly
unsafe extern "C" {
fn bkpt_from_a32();
}

core::arch::global_asm!(
r#"
// fn bkpt_from_a32();
.arm
.global bkpt_from_a32
.type bkpt_from_a32, %function
bkpt_from_a32:
#[unsafe(naked)]
#[instruction_set(arm::a32)]
extern "C" fn bkpt_from_a32() {
core::arch::naked_asm!(
r#"
bkpt #0
bx lr
.size bkpt_from_a32, . - bkpt_from_a32
"#
);
"#
);
}

// Custom link sections are allowed as well.
#[exception(Undefined)]
fn undefined_handler(_addr: usize) -> ! {
panic!("unexpected undefined exception");
Expand All @@ -64,12 +55,12 @@ unsafe fn prefetch_abort_handler(addr: usize) -> usize {
let ifar = Ifar::read();
println!("IFAR (Faulting Address Register): {:?}", ifar);

if addr == bkpt_from_a32 as unsafe extern "C" fn() as usize {
if addr == bkpt_from_a32 as extern "C" fn() as usize {
println!("caught bkpt_from_a32");
} else {
println!(
panic!(
"Bad fault address {:08x} is not {:08x}",
addr, bkpt_from_a32 as unsafe extern "C" fn() as usize
addr, bkpt_from_a32 as extern "C" fn() as usize
);
}

Expand Down
36 changes: 14 additions & 22 deletions examples/mps3-an536/src/bin/prefetch-exception-t32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,25 @@ fn main() -> ! {

// A BKPT instruction triggers a Prefetch Abort except when Halting debug-mode is enabled.
// See p. 2038 of ARMv7-M Architecture Reference Manual
unsafe {
// trigger an prefetch abort exception, from T32 (Thumb) mode
bkpt_from_t32();
}

// trigger an prefetch abort exception, from T32 (Thumb) mode
bkpt_from_t32();

println!("Recovered from fault OK!");

mps3_an536::exit(0);
}

// These functions are written in assembly
unsafe extern "C" {
fn bkpt_from_t32();
}

core::arch::global_asm!(
r#"
// fn bkpt_from_t32();
.thumb
.global bkpt_from_t32
.type bkpt_from_t32, %function
bkpt_from_t32:
#[unsafe(naked)]
#[instruction_set(arm::t32)]
extern "C" fn bkpt_from_t32() {
core::arch::naked_asm!(
r#"
bkpt #0
bx lr
.size bkpt_from_t32, . - bkpt_from_t32
"#
);
"#
);
}

#[exception(Undefined)]
fn undefined_handler(_addr: usize) -> ! {
Expand All @@ -63,15 +55,15 @@ unsafe fn prefetch_abort_handler(addr: usize) -> usize {
let ifar = Ifar::read();
println!("IFAR (Faulting Address Register): {:?}", ifar);

if (addr + 1) == bkpt_from_t32 as unsafe extern "C" fn() as usize {
if (addr + 1) == bkpt_from_t32 as extern "C" fn() as usize {
// note that thumb functions have their LSB set, despite always being a
// multiple of two - that's how the CPU knows they are written in T32
// machine code.
println!("caught bkpt_from_t32");
} else {
println!(
panic!(
"Bad fault address {:08x} is not {:08x}",
addr, bkpt_from_t32 as unsafe extern "C" fn() as usize
addr, bkpt_from_t32 as extern "C" fn() as usize
);
}

Expand Down
Loading