Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for the 32 Bit Arm architectures. #33

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
TARGET_AARCH64 := aarch64-unknown-none-softfloat
TARGET_AARCH32 := thumbv7em-none-eabi
LINKER_SCRIPT_AARCH64 := tests/aarch64_raspi3/link.ld
LINKER_SCRIPT_AARCH32 := tests/armv7m_mps2an500/link.ld

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

default:
cargo build --target $(TARGET_AARCH64) --release
cargo build --target $(TARGET_AARCH32) --release
cargo build --target $(TARGET_RISCV64) --release
cargo build --release

clippy:
cargo clippy --target $(TARGET_AARCH64)
cargo clippy --target $(TARGET_AARCH32)
cargo clippy --target $(TARGET_RISCV64)
cargo clippy

Expand All @@ -19,6 +23,10 @@ test:
cargo test \
--target $(TARGET_AARCH64) \
--release
RUSTFLAGS="-C link-arg=-T$(LINKER_SCRIPT_AARCH32) -Clink-args=-Map=/tmp/qemuexit-mapfile.map" \
cargo test \
--target $(TARGET_AARCH32) \
--release
RUSTFLAGS="-C link-arg=-T$(LINKER_SCRIPT_RISCV64)" \
cargo test \
--target $(TARGET_RISCV64) \
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ qemu_exit_handle.exit_failure();

## Architecture Specific Configuration

### AArch64
### AArch64/AArch32

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

### RISCV64
Expand Down
75 changes: 75 additions & 0 deletions src/aarch32.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2024 Philipp Schulz <[email protected]>

//! AArch32.
use crate::QEMUExit;
use core::arch::asm;

const EXIT_SUCCESS: u32 = 0;
const EXIT_FAILURE: u32 = 1;

#[allow(non_upper_case_globals)]
const ADP_Stopped_ApplicationExit: u32 = 0x20026;

/// The parameter block layout that is expected by QEMU.
///
/// If QEMU finds `ADP_Stopped_ApplicationExit` in the first parameter, it uses the second parameter
/// as exit code.
///
/// If first paraemter != `ADP_Stopped_ApplicationExit`, exit code `1` is used.
#[repr(C)]
struct QEMUParameterBlock {
arg0: u32,
arg1: u32,
}

/// AArch32 configuration.
pub struct AArch32 {}

/// A Semihosting call using `0x20` - `SYS_EXIT_EXTENDED`.
fn semihosting_sys_exit_call(block: &QEMUParameterBlock) -> ! {
unsafe {
asm!(
"bkpt #0xab",
in("r0") 0x20,
in("r1") block as *const _ as u32,
options(nostack)
);

// For the case that the QEMU exit attempt did not work, transition into an infinite loop.
// Calling `panic!()` here is unfeasible, since there is a good chance this function here is
// the last expression in the `panic!()` handler itself. This prevents a possible
// infinite loop.
loop {
asm!("wfe", options(nomem, nostack));
}
}
}

impl AArch32 {
/// Create an instance.
pub const fn new() -> Self {
AArch32 {}
}
}

impl QEMUExit for AArch32 {
fn exit(&self, code: u32) -> ! {
let block = QEMUParameterBlock {
arg0: ADP_Stopped_ApplicationExit,
arg1: code as u32,
};

semihosting_sys_exit_call(&block)
}

fn exit_success(&self) -> ! {
self.exit(EXIT_SUCCESS)
}

fn exit_failure(&self) -> ! {
self.exit(EXIT_FAILURE)
}
}
18 changes: 18 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
//! #[cfg(target_arch = "aarch64")]
//! let qemu_exit_handle = qemu_exit::AArch64::new();
//!
//! #[cfg(target_arch = "arm")]
//! let qemu_exit_handle = qemu_exit::Aarch32::new();
//!
//! // addr: The address of sifive_test.
//! #[cfg(target_arch = "riscv64")]
//! let qemu_exit_handle = qemu_exit::RISCV64::new(addr);
Expand All @@ -36,6 +39,15 @@
//! Pass the `-semihosting` argument to the QEMU invocation, e.g.:
//! ```
//! qemu-system-aarch64 -M raspi3 -serial stdio -semihosting -kernel kernel8.img
//!
//! ```
//!
//! ### AArch32
//!
//! Pass the `-semihosting` argument to the QEMU invocation, e.g.:
//! ```
//! qemu-system-arm -m 16M -nographic -M mps2-an500 -cpu cortex-m7 -serial mon:stdio -semihosting -kernel kernel.img
//!
//! ```
//!
//! ### RISCV64
Expand Down Expand Up @@ -78,6 +90,12 @@ pub mod aarch64;
#[cfg(target_arch = "aarch64")]
pub use aarch64::*;

#[cfg(target_arch = "arm")]
pub mod aarch32;

#[cfg(target_arch = "arm")]
pub use aarch32::*;

#[cfg(target_arch = "riscv64")]
pub mod riscv64;

Expand Down
22 changes: 22 additions & 0 deletions tests/armv7m_mps2an500/link.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* SPDX-License-Identifier: MIT OR Apache-2.0
*
* Copyright (c) 2024 Philipp Schulz <[email protected]>
*/
ENTRY(_vectors)

SECTIONS
{
. = 0x0;
.boot :
{
KEEP(*(.text.boot))
KEEP(*(.data.boot))
}

.text :
{
*(.vectors)
*(.text._start)
*(.text)
}
}
16 changes: 16 additions & 0 deletions tests/armv7m_mps2an500/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2024 Philipp Schulz <[email protected]>

//! AArch32 specific setup code.
use core::arch::global_asm;

global_asm!(
include_str!("./startup.S")
);

#[no_mangle]
extern "C" fn entry() {
super::test_main()
}
12 changes: 12 additions & 0 deletions tests/armv7m_mps2an500/startup.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.section ".text.boot","ax"

.thumb
.thumb_func
.globl _vectors
_vectors:
.word 0x2000
.word reset

.thumb_func
reset:
bl entry
10 changes: 10 additions & 0 deletions tests/exit_13.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ const QEMU_EXIT_HANDLE: qemu_exit::AArch64 = qemu_exit::AArch64::new();
#[cfg(target_arch = "aarch64")]
mod aarch64_raspi3;

//--------------------------------------------------------------------------------------------------
// Aarch32
//--------------------------------------------------------------------------------------------------

#[cfg(target_arch = "arm")]
const QEMU_EXIT_HANDLE: qemu_exit::AArch32 = qemu_exit::AArch32::new();

#[cfg(target_arch = "arm")]
mod armv7m_mps2an500;

//--------------------------------------------------------------------------------------------------
// RISCV64
//--------------------------------------------------------------------------------------------------
Expand Down
4 changes: 3 additions & 1 deletion tests/test_runner_wrapper.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#!/usr/bin/env bash

TIMEOUT="timeout 10"

if [[ $1 == *"aarch64"* ]]; then
$TIMEOUT qemu-system-aarch64 -M raspi3b -display none -semihosting -kernel $1
elif [[ $1 == *"thumbv7em"* ]]; then
arm-none-eabi-objcopy -O binary $1 /tmp/qemu_exit_armv7em.bin
qemu-system-arm -m 16M -nographic -M mps2-an500 -cpu cortex-m7 -serial mon:stdio -semihosting -kernel /tmp/qemu_exit_armv7em.bin
elif [[ $1 == *"riscv64"* ]]; then
$TIMEOUT qemu-system-riscv64 -M virt -bios tests/riscv64_virt/fw_jump.elf -display none -kernel $1
fi
Expand Down