Skip to content

Commit 6bd93f7

Browse files
Switch the examples to use naked functions.
We cannot use this on the main library, because it means we'd need to use the instruction_set attribute (rather than a .arm or .thumb directive) and that isn't available on stable for most of our targets.
1 parent 989190f commit 6bd93f7

17 files changed

+191
-300
lines changed

.github/workflows/build.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ jobs:
6363
uses: taiki-e/install-action@just
6464
- name: Install Rust
6565
run: |
66-
rustup install nightly-2026-01-26
67-
rustup component add rust-src --toolchain nightly-2026-01-26
68-
rustup default nightly-2026-01-26
66+
rustup install nightly-2026-02-26
67+
rustup component add rust-src --toolchain nightly-2026-02-26
68+
rustup default nightly-2026-02-26
6969
- name: Build
7070
run: |
7171
just build-tier3 ${{ matrix.target }}
@@ -89,9 +89,9 @@ jobs:
8989
uses: taiki-e/install-action@just
9090
- name: Install Rust
9191
run: |
92-
rustup install nightly-2026-01-26
93-
rustup component add rust-src --toolchain nightly-2026-01-26
94-
rustup default nightly-2026-01-26
92+
rustup install nightly-2026-02-26
93+
rustup component add rust-src --toolchain nightly-2026-02-26
94+
rustup default nightly-2026-02-26
9595
- name: Build
9696
run: |
9797
just build-tier3-no-atomics ${{ matrix.target }}

examples/mps3-an536/rust-toolchain.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[toolchain]
2-
channel = "nightly-2026-01-26"
2+
channel = "nightly-2026-02-26"
33
targets = [
44
"armv8r-none-eabihf",
55
]

examples/mps3-an536/src/bin/abt-exception-a32.rs

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,9 @@ fn main() -> ! {
2323
enable_alignment_check();
2424

2525
println!("Hello, this is an data abort exception example");
26-
unsafe {
27-
// Unaligned read
28-
unaligned_from_a32();
29-
}
26+
27+
// Unaligned read
28+
unaligned_from_a32();
3029

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

40-
// These functions are written in assembly
41-
unsafe extern "C" {
42-
fn unaligned_from_a32();
39+
#[unsafe(naked)]
40+
#[instruction_set(arm::a32)]
41+
extern "C" fn unaligned_from_a32() {
42+
core::arch::naked_asm!(
43+
"ldr r0, =COUNTER",
44+
"add r0, r0, 1",
45+
"ldr r0, [r0]",
46+
"bx lr",
47+
);
4348
}
4449

45-
core::arch::global_asm!(
46-
r#"
47-
// fn unaligned_from_a32();
48-
.arm
49-
.global unaligned_from_a32
50-
.type unaligned_from_a32, %function
51-
unaligned_from_a32:
52-
ldr r0, =COUNTER
53-
add r0, r0, 1
54-
ldr r0, [r0]
55-
bx lr
56-
.size unaligned_from_a32, . - unaligned_from_a32
57-
"#
58-
);
59-
6050
fn enable_alignment_check() {
6151
let mut sctrl = Sctlr::read();
6252
sctrl.set_a(true);
@@ -92,7 +82,7 @@ unsafe fn data_abort_handler(addr: usize) -> usize {
9282
enable_alignment_check();
9383

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

9787
if addr == expect_fault_at {
9888
println!("caught unaligned_from_a32");

examples/mps3-an536/src/bin/abt-exception-t32.rs

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,8 @@ fn main() -> ! {
2323
enable_alignment_check();
2424

2525
println!("Hello, this is an data abort exception example");
26-
unsafe {
27-
// Unaligned read
28-
unaligned_from_t32();
29-
}
26+
// Unaligned read
27+
unaligned_from_t32();
3028

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

40-
// These functions are written in assembly
41-
unsafe extern "C" {
42-
fn unaligned_from_t32();
38+
#[unsafe(naked)]
39+
#[instruction_set(arm::t32)]
40+
extern "C" fn unaligned_from_t32() {
41+
core::arch::naked_asm!(
42+
"ldr r0, =COUNTER",
43+
"adds r0, r0, 1",
44+
"ldr r0, [r0]",
45+
"bx lr",
46+
);
4347
}
4448

45-
core::arch::global_asm!(
46-
r#"
47-
// fn unaligned_from_t32();
48-
.thumb
49-
.global unaligned_from_t32
50-
.type unaligned_from_t32, %function
51-
unaligned_from_t32:
52-
ldr r0, =COUNTER
53-
add r0, r0, 1
54-
ldr r0, [r0]
55-
bx lr
56-
.size unaligned_from_t32, . - unaligned_from_t32
57-
"#
58-
);
59-
6049
fn enable_alignment_check() {
6150
let mut sctrl = Sctlr::read();
6251
sctrl.set_a(true);
@@ -92,7 +81,7 @@ unsafe fn data_abort_handler(addr: usize) -> usize {
9281
enable_alignment_check();
9382

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

9786
if addr == expect_fault_at {
9887
println!("caught unaligned_from_t32");

examples/mps3-an536/src/bin/el2_hello.rs

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,17 @@ fn main() -> ! {
3333
//
3434
// Unlike the default routine, it does not initialise any other stacks, or
3535
// switch to EL1 mode.
36-
core::arch::global_asm!(
37-
r#"
38-
// Work around https://github.com/rust-lang/rust/issues/127269
39-
.fpu vfp3-d16
40-
41-
.section .text.start
42-
43-
.global _start
44-
.type _start, %function
45-
_start:
36+
//
37+
/// # Safety
38+
///
39+
/// This function should not be called manually. It should only be called on reset
40+
/// from the reset vector.
41+
#[unsafe(naked)]
42+
#[unsafe(no_mangle)]
43+
#[instruction_set(arm::t32)]
44+
pub unsafe extern "C" fn _start() {
45+
core::arch::naked_asm!(
46+
r#"
4647
// Set stack pointer
4748
ldr sp, =_hyp_stack
4849
// Set the HVBAR (for EL2) to _vector_table
@@ -80,19 +81,19 @@ core::arch::global_asm!(
8081
bl kmain
8182
// In case the application returns, loop forever
8283
b .
83-
.size _start, . - _start
84-
"#,
85-
hactlr_bits = const {
86-
Hactlr::new_with_raw_value(0)
87-
.with_cpuactlr(true)
88-
.with_cdbgdci(true)
89-
.with_flashifregionr(true)
90-
.with_periphpregionr(true)
91-
.with_qosr(true)
92-
.with_bustimeoutr(true)
93-
.with_intmonr(true)
94-
.with_err(true)
95-
.with_testr1(true)
96-
.raw_value()
97-
},
98-
);
84+
"#,
85+
hactlr_bits = const {
86+
Hactlr::new_with_raw_value(0)
87+
.with_cpuactlr(true)
88+
.with_cdbgdci(true)
89+
.with_flashifregionr(true)
90+
.with_periphpregionr(true)
91+
.with_qosr(true)
92+
.with_bustimeoutr(true)
93+
.with_intmonr(true)
94+
.with_err(true)
95+
.with_testr1(true)
96+
.raw_value()
97+
},
98+
);
99+
}

examples/mps3-an536/src/bin/prefetch-exception-a32.rs

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,35 +21,26 @@ fn main() -> ! {
2121

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

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

3130
mps3_an536::exit(0);
3231
}
3332

34-
// These functions are written in assembly
35-
unsafe extern "C" {
36-
fn bkpt_from_a32();
37-
}
38-
39-
core::arch::global_asm!(
40-
r#"
41-
// fn bkpt_from_a32();
42-
.arm
43-
.global bkpt_from_a32
44-
.type bkpt_from_a32, %function
45-
bkpt_from_a32:
33+
#[unsafe(naked)]
34+
#[instruction_set(arm::a32)]
35+
extern "C" fn bkpt_from_a32() {
36+
core::arch::naked_asm!(
37+
r#"
4638
bkpt #0
4739
bx lr
48-
.size bkpt_from_a32, . - bkpt_from_a32
49-
"#
50-
);
40+
"#
41+
);
42+
}
5143

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

67-
if addr == bkpt_from_a32 as unsafe extern "C" fn() as usize {
58+
if addr == bkpt_from_a32 as extern "C" fn() as usize {
6859
println!("caught bkpt_from_a32");
6960
} else {
7061
println!(
7162
"Bad fault address {:08x} is not {:08x}",
72-
addr, bkpt_from_a32 as unsafe extern "C" fn() as usize
63+
addr, bkpt_from_a32 as extern "C" fn() as usize
7364
);
7465
}
7566

examples/mps3-an536/src/bin/prefetch-exception-t32.rs

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,33 +21,25 @@ fn main() -> ! {
2121

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

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

3130
mps3_an536::exit(0);
3231
}
3332

34-
// These functions are written in assembly
35-
unsafe extern "C" {
36-
fn bkpt_from_t32();
37-
}
38-
39-
core::arch::global_asm!(
40-
r#"
41-
// fn bkpt_from_t32();
42-
.thumb
43-
.global bkpt_from_t32
44-
.type bkpt_from_t32, %function
45-
bkpt_from_t32:
33+
#[unsafe(naked)]
34+
#[instruction_set(arm::t32)]
35+
extern "C" fn bkpt_from_t32() {
36+
core::arch::naked_asm!(
37+
r#"
4638
bkpt #0
4739
bx lr
48-
.size bkpt_from_t32, . - bkpt_from_t32
49-
"#
50-
);
40+
"#
41+
);
42+
}
5143

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

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

examples/mps3-an536/src/bin/undef-exception-a32.rs

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,34 +18,25 @@ static COUNTER: AtomicU32 = AtomicU32::new(0);
1818
fn main() -> ! {
1919
println!("Hello, this is a undef exception example");
2020

21-
unsafe {
22-
// trigger an Undefined exception, from A32 (Arm) mode
23-
udf_from_a32();
24-
}
21+
// trigger an Undefined exception, from A32 (Arm) mode
22+
udf_from_a32();
2523

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

2826
mps3_an536::exit(0);
2927
}
3028

31-
// These functions are written in assembly
32-
unsafe extern "C" {
33-
fn udf_from_a32();
29+
#[unsafe(naked)]
30+
#[instruction_set(arm::a32)]
31+
extern "C" fn udf_from_a32() {
32+
core::arch::naked_asm!(
33+
// Do a UDF
34+
"udf #0",
35+
// Return
36+
"bx lr",
37+
);
3438
}
3539

36-
core::arch::global_asm!(
37-
r#"
38-
// fn udf_from_a32();
39-
.arm
40-
.global udf_from_a32
41-
.type udf_from_a32, %function
42-
udf_from_a32:
43-
udf #0
44-
bx lr
45-
.size udf_from_a32, . - udf_from_a32
46-
"#
47-
);
48-
4940
#[exception(PrefetchAbort)]
5041
fn prefetch_abort_handler(_addr: usize) -> ! {
5142
panic!("unexpected undefined exception");
@@ -55,12 +46,12 @@ fn prefetch_abort_handler(_addr: usize) -> ! {
5546
unsafe fn undefined_handler(addr: usize) -> usize {
5647
println!("undefined abort occurred");
5748

58-
if addr == udf_from_a32 as unsafe extern "C" fn() as usize {
49+
if addr == udf_from_a32 as extern "C" fn() as usize {
5950
println!("caught udf_from_a32");
6051
} else {
6152
println!(
6253
"Bad fault address {:08x} is not {:08x}",
63-
addr, udf_from_a32 as unsafe extern "C" fn() as usize
54+
addr, udf_from_a32 as extern "C" fn() as usize
6455
);
6556
}
6657

0 commit comments

Comments
 (0)