Skip to content

Commit 1704d59

Browse files
committed
Made the tests pass
The QEMU test run with nightly which has thumb-interworking set for all the targets. Stable (and MSRV) do not, so this cannot be merged until our MSRV is updated. Until then we just cannot use naked functions.
1 parent 78a06f5 commit 1704d59

13 files changed

+236
-343
lines changed

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

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,36 +23,27 @@ 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
println!("Recovered from fault OK!");
3231

3332
semihosting::process::exit(0);
3433
}
3534

36-
// These functions are written in assembly
37-
extern "C" {
38-
fn unaligned_from_a32();
35+
#[unsafe(naked)]
36+
#[unsafe(no_mangle)]
37+
#[instruction_set(arm::a32)]
38+
extern "C" fn unaligned_from_a32() {
39+
core::arch::naked_asm!(
40+
"ldr r0, =COUNTER",
41+
"add r0, r0, 1",
42+
"ldr r0, [r0]",
43+
"bx lr",
44+
);
3945
}
4046

41-
core::arch::global_asm!(
42-
r#"
43-
// fn unaligned_from_a32();
44-
.arm
45-
.global unaligned_from_a32
46-
.type unaligned_from_a32, %function
47-
unaligned_from_a32:
48-
ldr r0, =COUNTER
49-
add r0, r0, 1
50-
ldr r0, [r0]
51-
bx lr
52-
.size unaligned_from_a32, . - unaligned_from_a32
53-
"#
54-
);
55-
5647
fn enable_alignment_check() {
5748
let mut sctrl = Sctlr::read();
5849
sctrl.set_a(true);
@@ -88,12 +79,12 @@ unsafe fn data_abort_handler(addr: usize) -> usize {
8879
enable_alignment_check();
8980

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

9384
if addr == expect_fault_at {
9485
println!("caught unaligned_from_a32");
9586
} else {
96-
println!(
87+
panic!(
9788
"Bad fault address {:08x} is not {:08x}",
9889
addr, expect_fault_at
9990
);

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

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,36 +23,26 @@ 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
println!("Recovered from fault OK!");
3230

3331
semihosting::process::exit(0);
3432
}
3533

36-
// These functions are written in assembly
37-
extern "C" {
38-
fn unaligned_from_t32();
34+
#[unsafe(naked)]
35+
#[unsafe(no_mangle)]
36+
#[instruction_set(arm::t32)]
37+
extern "C" fn unaligned_from_t32() {
38+
core::arch::naked_asm!(
39+
"ldr r0, =COUNTER",
40+
"adds r0, r0, 1",
41+
"ldr r0, [r0]",
42+
"bx lr",
43+
);
3944
}
4045

41-
core::arch::global_asm!(
42-
r#"
43-
// fn unaligned_from_t32();
44-
.thumb
45-
.global unaligned_from_t32
46-
.type unaligned_from_t32, %function
47-
unaligned_from_t32:
48-
ldr r0, =COUNTER
49-
add r0, r0, 1
50-
ldr r0, [r0]
51-
bx lr
52-
.size unaligned_from_t32, . - unaligned_from_t32
53-
"#
54-
);
55-
5646
fn enable_alignment_check() {
5747
let mut sctrl = Sctlr::read();
5848
sctrl.set_a(true);
@@ -88,12 +78,12 @@ unsafe fn data_abort_handler(addr: usize) -> usize {
8878
enable_alignment_check();
8979

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

9383
if addr == expect_fault_at {
9484
println!("caught unaligned_from_t32");
9585
} else {
96-
println!(
86+
panic!(
9787
"Bad fault address {:08x} is not {:08x}",
9888
addr, expect_fault_at
9989
);

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

Lines changed: 48 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -33,66 +33,60 @@ 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+
#[unsafe(naked)]
37+
#[unsafe(no_mangle)]
38+
#[instruction_set(arm::t32)]
39+
pub unsafe extern "C" fn _start() {
40+
core::arch::naked_asm!(
4641
// Set stack pointer
47-
ldr sp, =_hyp_stack
42+
"ldr sp, =_hyp_stack",
4843
// Set the HVBAR (for EL2) to _vector_table
49-
ldr r1, =_vector_table
50-
mcr p15, 4, r1, c12, c0, 0
44+
"ldr r1, =_vector_table",
45+
"mcr p15, 4, r1, c12, c0, 0",
5146
// Configure HACTLR to let us enter EL1
52-
mrc p15, 4, r1, c1, c0, 1
53-
mov r2, {hactlr_bits}
54-
orr r1, r1, r2
55-
mcr p15, 4, r1, c1, c0, 1
47+
"mrc p15, 4, r1, c1, c0, 1",
48+
"mov r2, {hactlr_bits}",
49+
"orr r1, r1, r2",
50+
"mcr p15, 4, r1, c1, c0, 1",
5651
// Init .data and .bss
57-
bl _init_segments
52+
"bl _init_segments",
5853
// Allow VFP coprocessor access
59-
mrc p15, 0, r0, c1, c0, 2
60-
orr r0, r0, #0xF00000
61-
mcr p15, 0, r0, c1, c0, 2
54+
"mrc p15, 0, r0, c1, c0, 2",
55+
"orr r0, r0, #0xF00000",
56+
"mcr p15, 0, r0, c1, c0, 2",
6257
// Enable VFP
63-
mov r0, #0x40000000
64-
vmsr fpexc, r0
58+
"mov r0, #0x40000000",
59+
"vmsr fpexc, r0",
6560
// Zero all registers before calling kmain
66-
mov r0, 0
67-
mov r1, 0
68-
mov r2, 0
69-
mov r3, 0
70-
mov r4, 0
71-
mov r5, 0
72-
mov r6, 0
73-
mov r7, 0
74-
mov r8, 0
75-
mov r9, 0
76-
mov r10, 0
77-
mov r11, 0
78-
mov r12, 0
61+
"mov r0, 0",
62+
"mov r1, 0",
63+
"mov r2, 0",
64+
"mov r3, 0",
65+
"mov r4, 0",
66+
"mov r5, 0",
67+
"mov r6, 0",
68+
"mov r7, 0",
69+
"mov r8, 0",
70+
"mov r9, 0",
71+
"mov r10, 0",
72+
"mov r11, 0",
73+
"mov r12, 0",
7974
// Jump to application
80-
bl kmain
75+
"bl kmain",
8176
// In case the application returns, loop forever
82-
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-
);
77+
"b .",
78+
hactlr_bits = const {
79+
Hactlr::new_with_raw_value(0)
80+
.with_cpuactlr(true)
81+
.with_cdbgdci(true)
82+
.with_flashifregionr(true)
83+
.with_periphpregionr(true)
84+
.with_qosr(true)
85+
.with_bustimeoutr(true)
86+
.with_intmonr(true)
87+
.with_err(true)
88+
.with_testr1(true)
89+
.raw_value()
90+
},
91+
);
92+
}

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

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,34 +21,22 @@ 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
semihosting::process::exit(0);
3231
}
3332

34-
// These functions are written in assembly
35-
extern "C" {
36-
fn bkpt_from_a32();
33+
#[unsafe(naked)]
34+
#[unsafe(no_mangle)]
35+
#[instruction_set(arm::a32)]
36+
extern "C" fn bkpt_from_a32() {
37+
core::arch::naked_asm!("bkpt #0", "bx lr",);
3738
}
3839

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:
46-
bkpt #0
47-
bx lr
48-
.size bkpt_from_a32, . - bkpt_from_a32
49-
"#
50-
);
51-
5240
#[exception(Undefined)]
5341
fn undefined_handler(_addr: usize) -> ! {
5442
panic!("unexpected undefined exception");
@@ -63,12 +51,14 @@ unsafe fn prefetch_abort_handler(addr: usize) -> usize {
6351
let ifar = Ifar::read();
6452
println!("IFAR (Faulting Address Register): {:?}", ifar);
6553

66-
if addr == bkpt_from_a32 as unsafe extern "C" fn() as usize {
54+
let expect_fault_at = bkpt_from_a32 as extern "C" fn() as usize;
55+
56+
if addr == expect_fault_at {
6757
println!("caught bkpt_from_a32");
6858
} else {
69-
println!(
59+
panic!(
7060
"Bad fault address {:08x} is not {:08x}",
71-
addr, bkpt_from_a32 as unsafe extern "C" fn() as usize
61+
addr, expect_fault_at
7262
);
7363
}
7464

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

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,34 +21,22 @@ 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
semihosting::process::exit(0);
3231
}
3332

34-
// These functions are written in assembly
35-
extern "C" {
36-
fn bkpt_from_t32();
33+
#[unsafe(naked)]
34+
#[unsafe(no_mangle)]
35+
#[instruction_set(arm::t32)]
36+
extern "C" fn bkpt_from_t32() {
37+
core::arch::naked_asm!("bkpt #0", "bx lr",);
3738
}
3839

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:
46-
bkpt #0
47-
bx lr
48-
.size bkpt_from_t32, . - bkpt_from_t32
49-
"#
50-
);
51-
5240
#[exception(Undefined)]
5341
fn undefined_handler(_addr: usize) -> ! {
5442
panic!("unexpected undefined exception");
@@ -63,15 +51,17 @@ unsafe fn prefetch_abort_handler(addr: usize) -> usize {
6351
let ifar = Ifar::read();
6452
println!("IFAR (Faulting Address Register): {:?}", ifar);
6553

66-
if (addr + 1) == bkpt_from_t32 as unsafe extern "C" fn() as usize {
54+
let expect_fault_at = (bkpt_from_t32 as extern "C" fn() as usize) - 1;
55+
56+
if addr == expect_fault_at {
6757
// note that thumb functions have their LSB set, despite always being a
6858
// multiple of two - that's how the CPU knows they are written in T32
6959
// machine code.
7060
println!("caught bkpt_from_t32");
7161
} else {
72-
println!(
62+
panic!(
7363
"Bad fault address {:08x} is not {:08x}",
74-
addr, bkpt_from_t32 as unsafe extern "C" fn() as usize
64+
addr, expect_fault_at
7565
);
7666
}
7767

0 commit comments

Comments
 (0)