Skip to content
Merged
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
6 changes: 6 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,11 @@ runner = "qemu-system-arm -machine versatileab -cpu arm926 -semihosting -nograph
[target.armv4t-none-eabi]
runner = "qemu-system-arm -machine versatileab -cpu pxa250 -semihosting -nographic -audio none -kernel"

[target.thumbv5te-none-eabi]
runner = "qemu-system-arm -machine versatileab -cpu arm926 -semihosting -nographic -audio none -kernel"

[target.thumbv4t-none-eabi]
runner = "qemu-system-arm -machine versatileab -cpu pxa250 -semihosting -nographic -audio none -kernel"

[unstable]
build-std = ["core", "alloc"]
2 changes: 1 addition & 1 deletion aarch32-cpu/build.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! # Build script for the Cortex-R library
//! # Build script for the aarch32-cpu library
//!
//! This script only executes when using `cargo` to build the project.
//!
Expand Down
71 changes: 71 additions & 0 deletions aarch32-cpu/src/asmv4.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//! Simple assembly routines for ARMv4

/// Emit an NOP instruction
#[cfg_attr(not(feature = "check-asm"), inline)]
pub fn nop() {
unsafe { core::arch::asm!("nop", options(nomem, nostack, preserves_flags)) }
}

/// Mask IRQ
#[cfg_attr(not(feature = "check-asm"), inline)]
#[cfg_attr(target_arch = "arm", instruction_set(arm::a32))]
pub fn irq_disable() {
#[cfg(target_arch = "arm")]
unsafe {
core::arch::asm!(r#"
mrs {0}, cpsr
orr {0}, {flag}
msr cpsr, {0}
"#,
in(reg) 0,
flag = const {
crate::register::Cpsr::new_with_raw_value(0)
.with_i(true)
.raw_value()
},
options(nomem, nostack, preserves_flags));
};
}

/// Unmask IRQ
#[cfg_attr(not(feature = "check-asm"), inline)]
#[cfg_attr(target_arch = "arm", instruction_set(arm::a32))]
pub fn irq_enable() {
#[cfg(target_arch = "arm")]
unsafe {
core::arch::asm!(r#"
mrs {0}, cpsr
bic {0}, #{flag}
msr cpsr, {0}
"#,
in(reg) 0,
flag = const {
crate::register::Cpsr::new_with_raw_value(0)
.with_i(true)
.raw_value()
},
options(nomem, nostack, preserves_flags));
};
}

/// Which core are we?
///
/// Return the bottom 24-bits of the MPIDR
#[cfg_attr(not(feature = "check-asm"), inline)]
#[cfg(target_arch = "arm")]
#[instruction_set(arm::a32)]
pub fn core_id() -> u32 {
let r: u32;
unsafe {
core::arch::asm!("MRC p15, 0, {}, c0, c0, 5", out(reg) r, options(nomem, nostack, preserves_flags));
}
r & 0x00FF_FFFF
}

#[no_mangle]
pub extern "C" fn __sync_synchronize() {
// we don't have a barrier instruction - the linux kernel just uses an empty inline asm block
unsafe {
core::arch::asm!("");
}
}
57 changes: 17 additions & 40 deletions aarch32-cpu/src/asm.rs → aarch32-cpu/src/asmv7.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
//! Simple assembly routines
//! Simple assembly routines for ARMv7

/// Data Memory Barrier
///
/// Ensures that all explicit memory accesses that appear in program order before the `DMB`
/// instruction are observed before any explicit memory accesses that appear in program order
/// after the `DMB` instruction.
#[cfg_attr(not(feature = "check-asm"), inline)]
#[cfg(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))]
pub fn dmb() {
use core::sync::atomic::{compiler_fence, Ordering};
compiler_fence(Ordering::SeqCst);
Expand All @@ -28,11 +23,6 @@ pub fn dmb() {
/// * any explicit memory access made before this instruction is complete
/// * all cache and branch predictor maintenance operations before this instruction complete
#[cfg_attr(not(feature = "check-asm"), inline)]
#[cfg(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))]
pub fn dsb() {
use core::sync::atomic::{compiler_fence, Ordering};
compiler_fence(Ordering::SeqCst);
Expand All @@ -47,11 +37,6 @@ pub fn dsb() {
/// Flushes the pipeline in the processor, so that all instructions following the `ISB` are fetched
/// from cache or memory, after the instruction has been completed.
#[cfg_attr(not(feature = "check-asm"), inline)]
#[cfg(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))]
pub fn isb() {
use core::sync::atomic::{compiler_fence, Ordering};
compiler_fence(Ordering::SeqCst);
Expand All @@ -69,39 +54,40 @@ pub fn nop() {

/// Emit an WFI instruction
#[cfg_attr(not(feature = "check-asm"), inline)]
#[cfg(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))]
pub fn wfi() {
unsafe { core::arch::asm!("wfi", options(nomem, nostack, preserves_flags)) }
}

/// Emit an WFE instruction
#[cfg_attr(not(feature = "check-asm"), inline)]
#[cfg(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))]
pub fn wfe() {
unsafe { core::arch::asm!("wfe", options(nomem, nostack, preserves_flags)) }
}

/// Emit an SEV instruction
#[cfg_attr(not(feature = "check-asm"), inline)]
#[cfg(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))]
pub fn sev() {
unsafe {
core::arch::asm!("sev");
}
}

/// Mask IRQ
#[cfg_attr(not(feature = "check-asm"), inline)]
pub fn irq_disable() {
unsafe {
core::arch::asm!("cpsid i");
}
}

/// Unmask IRQ
#[cfg_attr(not(feature = "check-asm"), inline)]
pub fn irq_enable() {
unsafe {
core::arch::asm!("cpsie i");
}
}

/// Which core are we?
///
/// Return the bottom 24-bits of the MPIDR
Expand All @@ -113,12 +99,3 @@ pub fn core_id() -> u32 {
}
r & 0x00FF_FFFF
}

#[cfg(any(arm_architecture = "v4t", arm_architecture = "v5te"))]
#[no_mangle]
pub extern "C" fn __sync_synchronize() {
// we don't have a barrier instruction - the linux kernel just uses an empty inline asm block
unsafe {
core::arch::asm!("");
}
}
2 changes: 1 addition & 1 deletion aarch32-cpu/src/critical_section.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Code that implements the `critical-section` traits on Cortex-R or Cortex-A
//! Code that implements the `critical-section` traits on AArch32
//!
//! We have single-core and multi-core versions. Select with the
//! `critical-section-single-core` and `critical-section-multi-core` features.
Expand Down
72 changes: 3 additions & 69 deletions aarch32-cpu/src/interrupt.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Interrupts on Arm Cortex-R
//! Interrupts on Arm AArch32

use core::sync::atomic::{compiler_fence, Ordering};

Expand All @@ -14,40 +14,7 @@ use core::sync::atomic::{compiler_fence, Ordering};
pub unsafe fn enable() {
// Ensure no preceeding memory accesses are reordered to after interrupts are enabled.
compiler_fence(Ordering::SeqCst);
// Safety: A Data Store Barrier is OK to call anywhere, and we're
// atomically setting a bit in a special register, and we're in an unsafe
// function that places restrictions on when you can call it
#[cfg(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))]
unsafe {
core::arch::asm!(
r#"
dsb
cpsie i
"#,
options(nomem, nostack, preserves_flags)
);
};
#[cfg(all(
target_arch = "arm",
not(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))
))]
unsafe {
core::arch::asm!(r#"
mrs {0}, cpsr
orr {0}, #0xC0
msr cpsr, {0}
"#,
in(reg) 0,
options(nomem, nostack, preserves_flags));
};
crate::asm::irq_enable();
}

/// Disable IRQ
Expand All @@ -56,40 +23,7 @@ pub unsafe fn enable() {
/// * Doesn't disable FIQ.
#[inline]
pub fn disable() {
// Safety: A Data Store Barrier is OK to call anywhere, and we're
// atomically setting a bit in a special register, and we're in an unsafe
// function that places restrictions on when you can call it
#[cfg(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))]
unsafe {
core::arch::asm!(
r#"
cpsid i
dsb
"#,
options(nomem, nostack, preserves_flags)
);
};
#[cfg(all(
target_arch = "arm",
not(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))
))]
unsafe {
core::arch::asm!(r#"
mrs {0}, cpsr
bic {0}, #0xC0
msr cpsr, {0}
"#,
in(reg) 0,
options(nomem, nostack, preserves_flags));
};
crate::asm::irq_disable();
// Ensure no subsequent memory accesses are reordered to before interrupts are disabled.
compiler_fence(Ordering::SeqCst);
}
Expand Down
20 changes: 17 additions & 3 deletions aarch32-cpu/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
//! CPU/peripheral support for Arm Cortex-R

//! CPU/peripheral support for Arm AArch32
#![no_std]

mod critical_section;

#[cfg(any(doc, target_arch = "arm"))]
#[cfg(any(
doc,
arm_architecture = "v7-a",
arm_architecture = "v7-r",
arm_architecture = "v8-r"
))]
#[path = "asmv7.rs"]
pub mod asm;

#[cfg(not(any(
doc,
arm_architecture = "v7-a",
arm_architecture = "v7-r",
arm_architecture = "v8-r"
)))]
#[path = "asmv4.rs"]
pub mod asm;

pub mod cache;
Expand Down
2 changes: 1 addition & 1 deletion aarch32-cpu/src/register/armv8r/hvbar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ impl Hvbar {
///
/// # Safety
///
/// You must supply a correctly-aligned address of a valid Arm Cortex-R
/// You must supply a correctly-aligned address of a valid Arm AArch32
/// Vector Table.
#[inline]
pub unsafe fn write(value: Self) {
Expand Down
2 changes: 1 addition & 1 deletion aarch32-cpu/src/register/armv8r/vbar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl Vbar {
///
/// # Safety
///
/// You must supply a correctly-aligned address of a valid Arm Cortex-R
/// You must supply a correctly-aligned address of a valid Arm AArch32
/// Vector Table.
#[inline]
pub unsafe fn write(value: Self) {
Expand Down
18 changes: 16 additions & 2 deletions aarch32-cpu/src/register/cpsr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,14 @@ pub struct Cpsr {

impl Cpsr {
/// Read CPSR (*Current Program Status Register*)
#[inline]
///
/// On Armv4T and Armv5TE this will be an Arm function, even on the
/// `thumb*` targets, as Thumb-1 cannot do an MRS.
#[cfg_attr(not(feature = "check-asm"), inline)]
#[cfg_attr(
any(arm_architecture = "v4t", arm_architecture = "v5te"),
instruction_set(arm::a32)
)]
pub fn read() -> Self {
let r: u32;
// Safety: Reading this register has no side-effects and is atomic
Expand All @@ -96,7 +103,14 @@ impl Cpsr {
///
/// You almost certainly want to follow this with an [ISB](crate::asm::isb)
/// instruction.
#[inline]
///
/// On Armv4T and Armv5TE this will be an Arm function, even on the
/// `thumb*` targets, as Thumb-1 cannot do an MSR.
#[cfg_attr(not(feature = "check-asm"), inline)]
#[cfg_attr(
any(arm_architecture = "v4t", arm_architecture = "v5te"),
instruction_set(arm::a32)
)]
pub unsafe fn write(_value: Self) {
// Safety: This is risky, but we're in an unsafe function
#[cfg(target_arch = "arm")]
Expand Down
Loading