Skip to content

Commit c882e1f

Browse files
authored
Merge pull request #33 from dinkelhacker/master
Add support for the 32 Bit Arm architectures.
2 parents 5644679 + cf82b4a commit c882e1f

File tree

9 files changed

+168
-3
lines changed

9 files changed

+168
-3
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: 21 additions & 1 deletion
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);
@@ -33,21 +36,32 @@
3336
//!
3437
//! ### AArch64
3538
//!
36-
//! Pass the `-semihosting` argument to the QEMU invocation, e.g.:
39+
//! Pass the `-semihosting` argument to the QEMU invocation, e.g.
40+
//!
3741
//! ```
3842
//! qemu-system-aarch64 -M raspi3 -serial stdio -semihosting -kernel kernel8.img
3943
//! ```
4044
//!
45+
//! ### AArch32
46+
//!
47+
//! Pass the `-semihosting` argument to the QEMU invocation, e.g.
48+
//!
49+
//! ```
50+
//! qemu-system-arm -m 16M -nographic -M mps2-an500 -cpu cortex-m7 -serial mon:stdio -semihosting -kernel kernel.img
51+
//! ```
52+
//!
4153
//! ### RISCV64
4254
//!
4355
//! You need to chose a machine with the `sifive_test` device, for exemple `-M virt`:
56+
//!
4457
//! ```
4558
//! qemu-system-riscv64 -M virt -nographic -monitor none -serial stdio -kernel kernel.elf
4659
//! ```
4760
//!
4861
//! ### x86_64
4962
//!
5063
//! Add the special ISA debug exit device by passing the flags:
64+
//!
5165
//! ```
5266
//! -device isa-debug-exit,iobase=0xf4,iosize=0x04
5367
//! ```
@@ -78,6 +92,12 @@ pub mod aarch64;
7892
#[cfg(target_arch = "aarch64")]
7993
pub use aarch64::*;
8094

95+
#[cfg(target_arch = "arm")]
96+
pub mod aarch32;
97+
98+
#[cfg(target_arch = "arm")]
99+
pub use aarch32::*;
100+
81101
#[cfg(target_arch = "riscv64")]
82102
pub mod riscv64;
83103

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: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
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!(include_str!("./startup.S"));
10+
11+
#[no_mangle]
12+
extern "C" fn entry() {
13+
super::test_main()
14+
}

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)