Skip to content

Commit 3bb3690

Browse files
committed
Add support for the 32 Bit Arm architectures.
1 parent 5644679 commit 3bb3690

File tree

9 files changed

+167
-2
lines changed

9 files changed

+167
-2
lines changed

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
TARGET_AARCH64 := aarch64-unknown-none-softfloat
2+
TARGET_AARCH32 := thumbv7em-none-eabi
23
LINKER_SCRIPT_AARCH64 := tests/aarch64_raspi3/link.ld
4+
LINKER_SCRIPT_AARCH32 := tests/armv7m_mps2an500/link.ld
35

46
TARGET_RISCV64 := riscv64gc-unknown-none-elf
57
LINKER_SCRIPT_RISCV64 := tests/riscv64_virt/link.ld
68

79
default:
810
cargo build --target $(TARGET_AARCH64) --release
11+
cargo build --target $(TARGET_AARCH32) --release
912
cargo build --target $(TARGET_RISCV64) --release
1013
cargo build --release
1114

1215
clippy:
1316
cargo clippy --target $(TARGET_AARCH64)
17+
cargo clippy --target $(TARGET_AARCH32)
1418
cargo clippy --target $(TARGET_RISCV64)
1519
cargo clippy
1620

@@ -19,6 +23,10 @@ test:
1923
cargo test \
2024
--target $(TARGET_AARCH64) \
2125
--release
26+
RUSTFLAGS="-C link-arg=-T$(LINKER_SCRIPT_AARCH32) -Clink-args=-Map=/tmp/qemuexit-mapfile.map" \
27+
cargo test \
28+
--target $(TARGET_AARCH32) \
29+
--release
2230
RUSTFLAGS="-C link-arg=-T$(LINKER_SCRIPT_RISCV64)" \
2331
cargo test \
2432
--target $(TARGET_RISCV64) \

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,13 @@ qemu_exit_handle.exit_failure();
3535

3636
## Architecture Specific Configuration
3737

38-
### AArch64
38+
### AArch64/AArch32
3939

4040
Pass the `-semihosting` argument to the QEMU invocation, e.g.:
4141
```
4242
qemu-system-aarch64 -M raspi3 -serial stdio -semihosting -kernel kernel8.img
43+
qemu-system-arm -nographic -M mps2-an500 -cpu cortex-m7 -serial mon:stdio -semihosting -kernel
44+
kernel.img
4345
```
4446

4547
### RISCV64

src/aarch32.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
//
3+
// Copyright (c) 2024 Philipp Schulz <[email protected]>
4+
5+
//! AArch32.
6+
7+
use crate::QEMUExit;
8+
use core::arch::asm;
9+
10+
const EXIT_SUCCESS: u32 = 0;
11+
const EXIT_FAILURE: u32 = 1;
12+
13+
#[allow(non_upper_case_globals)]
14+
const ADP_Stopped_ApplicationExit: u32 = 0x20026;
15+
16+
/// The parameter block layout that is expected by QEMU.
17+
///
18+
/// If QEMU finds `ADP_Stopped_ApplicationExit` in the first parameter, it uses the second parameter
19+
/// as exit code.
20+
///
21+
/// If first paraemter != `ADP_Stopped_ApplicationExit`, exit code `1` is used.
22+
#[repr(C)]
23+
struct QEMUParameterBlock {
24+
arg0: u32,
25+
arg1: u32,
26+
}
27+
28+
/// AArch32 configuration.
29+
pub struct AArch32 {}
30+
31+
/// A Semihosting call using `0x20` - `SYS_EXIT_EXTENDED`.
32+
fn semihosting_sys_exit_call(block: &QEMUParameterBlock) -> ! {
33+
unsafe {
34+
asm!(
35+
"bkpt #0xab",
36+
in("r0") 0x20,
37+
in("r1") block as *const _ as u32,
38+
options(nostack)
39+
);
40+
41+
// For the case that the QEMU exit attempt did not work, transition into an infinite loop.
42+
// Calling `panic!()` here is unfeasible, since there is a good chance this function here is
43+
// the last expression in the `panic!()` handler itself. This prevents a possible
44+
// infinite loop.
45+
loop {
46+
asm!("wfe", options(nomem, nostack));
47+
}
48+
}
49+
}
50+
51+
impl AArch32 {
52+
/// Create an instance.
53+
pub const fn new() -> Self {
54+
AArch32 {}
55+
}
56+
}
57+
58+
impl QEMUExit for AArch32 {
59+
fn exit(&self, code: u32) -> ! {
60+
let block = QEMUParameterBlock {
61+
arg0: ADP_Stopped_ApplicationExit,
62+
arg1: code as u32,
63+
};
64+
65+
semihosting_sys_exit_call(&block)
66+
}
67+
68+
fn exit_success(&self) -> ! {
69+
self.exit(EXIT_SUCCESS)
70+
}
71+
72+
fn exit_failure(&self) -> ! {
73+
self.exit(EXIT_FAILURE)
74+
}
75+
}

src/lib.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
//! #[cfg(target_arch = "aarch64")]
1616
//! let qemu_exit_handle = qemu_exit::AArch64::new();
1717
//!
18+
//! #[cfg(target_arch = "arm")]
19+
//! let qemu_exit_handle = qemu_exit::Aarch32::new();
20+
//!
1821
//! // addr: The address of sifive_test.
1922
//! #[cfg(target_arch = "riscv64")]
2023
//! let qemu_exit_handle = qemu_exit::RISCV64::new(addr);
@@ -36,6 +39,15 @@
3639
//! Pass the `-semihosting` argument to the QEMU invocation, e.g.:
3740
//! ```
3841
//! qemu-system-aarch64 -M raspi3 -serial stdio -semihosting -kernel kernel8.img
42+
//!
43+
//! ```
44+
//!
45+
//! ### AArch32
46+
//!
47+
//! Pass the `-semihosting` argument to the QEMU invocation, e.g.:
48+
//! ```
49+
//! qemu-system-arm -m 16M -nographic -M mps2-an500 -cpu cortex-m7 -serial mon:stdio -semihosting -kernel kernel.img
50+
//!
3951
//! ```
4052
//!
4153
//! ### RISCV64
@@ -78,6 +90,12 @@ pub mod aarch64;
7890
#[cfg(target_arch = "aarch64")]
7991
pub use aarch64::*;
8092

93+
#[cfg(target_arch = "arm")]
94+
pub mod aarch32;
95+
96+
#[cfg(target_arch = "arm")]
97+
pub use aarch32::*;
98+
8199
#[cfg(target_arch = "riscv64")]
82100
pub mod riscv64;
83101

tests/armv7m_mps2an500/link.ld

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* SPDX-License-Identifier: MIT OR Apache-2.0
2+
*
3+
* Copyright (c) 2024 Philipp Schulz <[email protected]>
4+
*/
5+
ENTRY(_vectors)
6+
7+
SECTIONS
8+
{
9+
. = 0x0;
10+
.boot :
11+
{
12+
KEEP(*(.text.boot))
13+
KEEP(*(.data.boot))
14+
}
15+
16+
.text :
17+
{
18+
*(.vectors)
19+
*(.text._start)
20+
*(.text)
21+
}
22+
}

tests/armv7m_mps2an500/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
//
3+
// Copyright (c) 2024 Philipp Schulz <[email protected]>
4+
5+
//! AArch32 specific setup code.
6+
7+
use core::arch::global_asm;
8+
9+
global_asm!(
10+
include_str!("./startup.S")
11+
);
12+
13+
#[no_mangle]
14+
extern "C" fn entry() {
15+
super::test_main()
16+
}

tests/armv7m_mps2an500/startup.S

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.section ".text.boot","ax"
2+
3+
.thumb
4+
.thumb_func
5+
.globl _vectors
6+
_vectors:
7+
.word 0x2000
8+
.word reset
9+
10+
.thumb_func
11+
reset:
12+
bl entry

tests/exit_13.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ const QEMU_EXIT_HANDLE: qemu_exit::AArch64 = qemu_exit::AArch64::new();
2020
#[cfg(target_arch = "aarch64")]
2121
mod aarch64_raspi3;
2222

23+
//--------------------------------------------------------------------------------------------------
24+
// Aarch32
25+
//--------------------------------------------------------------------------------------------------
26+
27+
#[cfg(target_arch = "arm")]
28+
const QEMU_EXIT_HANDLE: qemu_exit::AArch32 = qemu_exit::AArch32::new();
29+
30+
#[cfg(target_arch = "arm")]
31+
mod armv7m_mps2an500;
32+
2333
//--------------------------------------------------------------------------------------------------
2434
// RISCV64
2535
//--------------------------------------------------------------------------------------------------

tests/test_runner_wrapper.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#!/usr/bin/env bash
22

33
TIMEOUT="timeout 10"
4-
54
if [[ $1 == *"aarch64"* ]]; then
65
$TIMEOUT qemu-system-aarch64 -M raspi3b -display none -semihosting -kernel $1
6+
elif [[ $1 == *"thumbv7em"* ]]; then
7+
arm-none-eabi-objcopy -O binary $1 /tmp/qemu_exit_armv7em.bin
8+
qemu-system-arm -m 16M -nographic -M mps2-an500 -cpu cortex-m7 -serial mon:stdio -semihosting -kernel /tmp/qemu_exit_armv7em.bin
79
elif [[ $1 == *"riscv64"* ]]; then
810
$TIMEOUT qemu-system-riscv64 -M virt -bios tests/riscv64_virt/fw_jump.elf -display none -kernel $1
911
fi

0 commit comments

Comments
 (0)