From 5b2080c26023bc6a9c8ce68a419071ad7ce5fc94 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sat, 28 Mar 2026 21:35:53 +0000 Subject: [PATCH 1/6] Comment updates. * Turned on deny(missing_docs), and added missing docs * Turned on deny(clippy::missing_safety_doc) and added missing safety docs * Turned on some more useful lints * Clippy fixes * Rationalised/renamed the various CachePolicy types --- aarch32-cpu/Cargo.toml | 24 +++- aarch32-cpu/src/asmv4.rs | 1 + aarch32-cpu/src/generic_timer/el0.rs | 6 +- aarch32-cpu/src/lib.rs | 27 ++-- aarch32-cpu/src/mmu.rs | 123 +++++++++++++----- aarch32-cpu/src/pmsav7.rs | 86 +++++++----- aarch32-cpu/src/pmsav8.rs | 27 ++-- aarch32-cpu/src/register/armv8r/hmpuir.rs | 1 + aarch32-cpu/src/register/armv8r/hprbar.rs | 1 + aarch32-cpu/src/register/armv8r/hprlar.rs | 1 + aarch32-cpu/src/register/armv8r/prbar.rs | 1 + aarch32-cpu/src/register/armv8r/prlar.rs | 1 + aarch32-cpu/src/register/bpiall.rs | 1 + aarch32-cpu/src/register/ccsidr.rs | 8 ++ aarch32-cpu/src/register/csselr.rs | 5 + aarch32-cpu/src/register/dacr.rs | 2 + aarch32-cpu/src/register/dccimvac.rs | 6 +- aarch32-cpu/src/register/dccisw.rs | 5 +- aarch32-cpu/src/register/dccmvac.rs | 6 +- aarch32-cpu/src/register/dccmvau.rs | 6 +- aarch32-cpu/src/register/dccsw.rs | 5 +- aarch32-cpu/src/register/dcimvac.rs | 6 +- aarch32-cpu/src/register/dcisw.rs | 5 +- aarch32-cpu/src/register/dfsr.rs | 26 +++- aarch32-cpu/src/register/dracr.rs | 1 + aarch32-cpu/src/register/drsr.rs | 4 + .../src/register/generic_timer/cnthctl.rs | 40 ++---- .../src/register/generic_timer/cnthp_ctl.rs | 1 + .../src/register/generic_timer/cntkctl.rs | 1 + .../src/register/generic_timer/cntp_ctl.rs | 1 + .../src/register/generic_timer/cntv_ctl.rs | 1 + aarch32-cpu/src/register/hyp/hcptr.rs | 1 + aarch32-cpu/src/register/hyp/hcr.rs | 5 + aarch32-cpu/src/register/hyp/hsctlr.rs | 1 + aarch32-cpu/src/register/hyp/hsr.rs | 42 ++++++ aarch32-cpu/src/register/hyp/hvbar.rs | 2 +- aarch32-cpu/src/register/iciallu.rs | 5 +- aarch32-cpu/src/register/ifsr.rs | 58 +++++++++ aarch32-cpu/src/register/imp/imp_cdbgdcd.rs | 6 +- aarch32-cpu/src/register/imp/imp_cdbgdct.rs | 6 +- aarch32-cpu/src/register/imp/imp_cdbgdr0.rs | 6 +- aarch32-cpu/src/register/imp/imp_cdbgdr1.rs | 6 +- aarch32-cpu/src/register/imp/imp_cdbgdr2.rs | 6 +- aarch32-cpu/src/register/imp/imp_cdbgicd.rs | 6 +- aarch32-cpu/src/register/imp/imp_cdbgict.rs | 6 +- aarch32-cpu/src/register/iracr.rs | 1 + aarch32-cpu/src/register/irsr.rs | 1 + aarch32-cpu/src/register/mod.rs | 11 +- aarch32-cpu/src/register/mpuir.rs | 1 + aarch32-cpu/src/register/sctlr.rs | 1 + aarch32-cpu/src/register/tlbiall.rs | 1 + aarch32-cpu/src/register/ttbr0.rs | 5 +- aarch32-cpu/src/stacks.rs | 52 ++++---- .../mps3-an536-el2/src/bin/generic-timer.rs | 4 +- examples/mps3-an536-el2/src/bin/hvc-a32.rs | 2 +- examples/mps3-an536-el2/src/bin/hvc-t32.rs | 2 +- examples/mps3-an536-el2/src/bin/svc-a32.rs | 2 +- examples/mps3-an536-el2/src/bin/svc-t32.rs | 2 +- examples/mps3-an536/src/bin/mpu_setup.rs | 10 +- examples/mps3-an536/src/bin/registers.rs | 14 +- .../reference/registers-armv7r-none-eabi.out | 2 +- .../registers-armv7r-none-eabihf.out | 2 +- .../registers-thumbv7r-none-eabi.out | 2 +- .../registers-thumbv7r-none-eabihf.out | 2 +- examples/versatileab/src/bin/registers.rs | 6 +- examples/versatileab/src/mmu.rs | 8 +- 66 files changed, 496 insertions(+), 220 deletions(-) diff --git a/aarch32-cpu/Cargo.toml b/aarch32-cpu/Cargo.toml index 76903a97..b0a9d72c 100644 --- a/aarch32-cpu/Cargo.toml +++ b/aarch32-cpu/Cargo.toml @@ -51,11 +51,25 @@ serde = ["dep:serde", "arbitrary-int/serde"] check-asm = [] [package.metadata.docs.rs] -# This is a list of supported Tier 2 targets, as of latest stable targets = [ - "armv7r-none-eabihf", - "armv7r-none-eabi", - "armv7a-none-eabihf", + "armebv7r-none-eabi", + "armebv7r-none-eabihf", + "armv4t-none-eabi", + "armv5te-none-eabi", + "armv6-none-eabi", + "armv6-none-eabihf", "armv7a-none-eabi", - "armv8r-none-eabihf" + "armv7a-none-eabihf", + "armv7r-none-eabi", + "armv7r-none-eabihf", + "armv8r-none-eabihf", + "thumbv4t-none-eabi", + "thumbv5te-none-eabi", + "thumbv6-none-eabi", + "thumbv7a-none-eabi", + "thumbv7a-none-eabihf", + "thumbv7r-none-eabi", + "thumbv7r-none-eabihf", + "thumbv8r-none-eabihf", ] +cargo-args = ["-Z", "build-std"] diff --git a/aarch32-cpu/src/asmv4.rs b/aarch32-cpu/src/asmv4.rs index b6db42af..83424294 100644 --- a/aarch32-cpu/src/asmv4.rs +++ b/aarch32-cpu/src/asmv4.rs @@ -66,6 +66,7 @@ pub fn core_id() -> u32 { r & 0x00FF_FFFF } +/// LLVM intrinsic for memory barriers #[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 diff --git a/aarch32-cpu/src/generic_timer/el0.rs b/aarch32-cpu/src/generic_timer/el0.rs index d4a571e6..90dd61f3 100644 --- a/aarch32-cpu/src/generic_timer/el0.rs +++ b/aarch32-cpu/src/generic_timer/el0.rs @@ -2,7 +2,7 @@ use crate::register; -/// Represents our Physical Timer when we are running at EL0. +/// Represents our Generic Physical Timer when we are running at EL0. /// /// Note that for most of these APIs to work, EL0 needs to have been granted /// access using methods like @@ -75,11 +75,11 @@ impl super::GenericTimer for El0PhysicalTimer { } } -/// Represents our Virtual Timer when we are running at EL0. +/// Represents our Generic Virtual Timer when we are running at EL0. /// /// Note that for most of these APIs to work, EL0 needs to have been granted /// access using methods like -/// [El1PhysicalTimer::el0_access_virtual_counter](crate::generic_timer::El1VirtualTimer::el0_access_virtual_counter). +/// [El1VirtualTimer::el0_access_virtual_counter](crate::generic_timer::El1VirtualTimer::el0_access_virtual_counter). pub struct El0VirtualTimer(); impl El0VirtualTimer { diff --git a/aarch32-cpu/src/lib.rs b/aarch32-cpu/src/lib.rs index 4df0fce5..3db2b991 100644 --- a/aarch32-cpu/src/lib.rs +++ b/aarch32-cpu/src/lib.rs @@ -1,7 +1,14 @@ //! CPU/peripheral support for Arm AArch32 #![no_std] +#![deny(missing_docs)] +#![deny(unsafe_op_in_unsafe_fn)] +#![deny(clippy::missing_safety_doc)] +#![deny(clippy::unnecessary_safety_comment)] +#![deny(clippy::unnecessary_safety_doc)] -mod critical_section; +pub mod cache; +pub mod interrupt; +pub mod register; #[cfg(any( doc, @@ -21,26 +28,22 @@ pub mod asm; #[path = "asmv4.rs"] pub mod asm; -pub mod cache; - #[cfg(any(test, doc, arm_architecture = "v7-a", arm_architecture = "v8-r"))] pub mod generic_timer; -pub mod interrupt; - -#[cfg(any(test, doc, arm_architecture = "v7-a"))] +#[cfg(any(test, arm_profile = "a", arm_profile = "legacy"))] pub mod mmu; -pub mod register; +#[cfg(any(test, arm_architecture = "v7-r"))] +pub mod pmsav7; + +#[cfg(any(test, arm_architecture = "v8-r"))] +pub mod pmsav8; #[cfg(target_arch = "arm")] pub mod stacks; -#[cfg(any(test, doc, arm_architecture = "v7-r"))] -pub mod pmsav7; - -#[cfg(any(test, doc, arm_architecture = "v8-r"))] -pub mod pmsav8; +mod critical_section; /// Generate an SVC call with no parameters. /// diff --git a/aarch32-cpu/src/mmu.rs b/aarch32-cpu/src/mmu.rs index baafeacc..2763b5d9 100644 --- a/aarch32-cpu/src/mmu.rs +++ b/aarch32-cpu/src/mmu.rs @@ -9,7 +9,11 @@ pub const NUM_L1_PAGE_TABLE_ENTRIES: usize = 4096; /// /// You should create a static variable of this type, to represent your page table. #[repr(C, align(1048576))] +#[derive(Debug)] pub struct L1Table { + /// Our mutable list of MMU table entries + /// + /// This table is read by the hardware. pub entries: core::cell::UnsafeCell<[L1Section; NUM_L1_PAGE_TABLE_ENTRIES]>, } @@ -24,25 +28,39 @@ unsafe impl Sync for L1Table {} pub struct InvalidL1EntryType(pub L1EntryType); /// Access permissions for a region of memory -#[bitbybit::bitenum(u3, exhaustive = true)] +#[bitbybit::bitenum(u3)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Debug, PartialEq, Eq)] pub enum AccessPermissions { + /// All accesses generate Permission faults PermissionFault = 0b000, + /// Privileged access only PrivilegedOnly = 0b001, + /// Writes in User mode generate Permission faults NoUserWrite = 0b010, + /// Full access FullAccess = 0b011, - _Reserved1 = 0b100, + /// Privileged read-only PrivilegedReadOnly = 0b101, - ReadOnly = 0b110, - _Reserved2 = 0b111, + /// Privileged and User read-only (deprecated in VMSAv7) + ReadOnlyv6 = 0b110, + /// Privileged and User read-only + ReadOnly = 0b111, } impl AccessPermissions { + /// Create a new [`AccessPermissions`] value from the APX bit at the AP bit + /// pair + /// + /// Will panic if you select an invalid value. #[inline] pub const fn new(apx: bool, ap: u2) -> Self { - Self::new_with_raw_value(u3::new(((apx as u8) << 2) | ap.value())) + let x = u3::new(((apx as u8) << 2) | ap.value()); + let Ok(ap) = Self::new_with_raw_value(x) else { + panic!("Invalid access permissions"); + }; + ap } /// AP bit for the given access permission. @@ -65,21 +83,25 @@ impl AccessPermissions { #[derive(Debug, PartialEq, Eq)] #[repr(u8)] pub enum L1EntryType { - /// Access generates an abort exception. Indicates an unmapped virtual address. + /// Access generates an abort exception. Indicates an unmapped virtual + /// address. Fault = 0b00, - /// Entry points to a L2 translation table, allowing 1 MB of memory to be further divided + /// Entry points to a L2 translation table, allowing 1 MB of memory to be + /// further divided PageTable = 0b01, /// Maps a 1 MB region to a physical address. Section = 0b10, - /// Special 1MB section entry which requires 16 entries in the translation table. + /// Special 1MB section entry which requires 16 entries in the translation + /// table. Supersection = 0b11, } -/// The ARM Cortex-A architecture reference manual p.1363 specifies these attributes in more detail. +/// The ARM Cortex-A architecture reference manual p.1363 specifies these +/// attributes in more detail. /// -/// The B (Bufferable), C (Cacheable), and TEX (Type extension) bit names are inherited from -/// earlier versions of the architecture. These names no longer adequately describe the function -/// of the B, C, and TEX bits. +/// The B (Bufferable), C (Cacheable), and TEX (Type extension) bit names are +/// inherited from earlier versions of the architecture. These names no longer +/// adequately describe the function of the B, C, and TEX bits. #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -91,6 +113,7 @@ pub struct MemoryRegionAttributesRaw { } impl MemoryRegionAttributesRaw { + /// Create a new [`MemoryRegionAttributesRaw`] from constituent parts #[inline] pub const fn new(type_extensions: u3, c: bool, b: bool) -> Self { Self { @@ -105,11 +128,15 @@ impl MemoryRegionAttributesRaw { #[bitbybit::bitenum(u2, exhaustive = true)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[derive(Debug)] -pub enum CacheableMemoryAttribute { +#[derive(Debug, PartialEq, Eq)] +pub enum CachePolicy { + /// Non-cacheable NonCacheable = 0b00, + /// Write-Back Cacheable, Write-Allocate WriteBackWriteAlloc = 0b01, + /// Write-Through Cacheable WriteThroughNoWriteAlloc = 0b10, + /// Write-Back Cacheable, no Write-Allocate WriteBackNoWriteAlloc = 0b11, } @@ -118,20 +145,43 @@ pub enum CacheableMemoryAttribute { #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum MemoryRegionAttributes { + /// Strongly- ordered + /// + /// All memory accesses to Strongly-ordered memory occur in program order. + /// All Strongly-ordered regions are assumed to be Shareable. StronglyOrdered, + /// Device Shareable + /// + /// Intended to handle memory-mapped peripherals that are shared by several + /// processors. ShareableDevice, + /// Normal Memory, Write-Through Cacheable for both Inner and Outer Cache OuterAndInnerWriteThroughNoWriteAlloc, + /// Normal Memory, Write-Back no Write-Allocate Cacheable for both Inner and + /// Outer Cache OuterAndInnerWriteBackNoWriteAlloc, + /// Normal Memory, Non-cacheable for both Inner and Outer Cache OuterAndInnerNonCacheable, + /// Normal Memory, Write-Back Write-Allocate Cacheable for both Inner and + /// Outer Cache OuterAndInnerWriteBackWriteAlloc, + /// Device Non-Shareable + /// + /// Intended to handle memory-mapped peripherals that are used only by a + /// single processor. NonShareableDevice, + /// Normal Memory, where Inner and Outer cache have different settings CacheableMemory { - inner: CacheableMemoryAttribute, - outer: CacheableMemoryAttribute, + /// Settings for the Inner Cache + inner: CachePolicy, + /// Settings for the Outer Cache + outer: CachePolicy, }, } impl MemoryRegionAttributes { + /// Convert the Rust enum type [`MemoryRegionAttributes`] into a raw + /// [`MemoryRegionAttributesRaw`] value for the hardware pub const fn as_raw(&self) -> MemoryRegionAttributesRaw { match self { MemoryRegionAttributes::StronglyOrdered => { @@ -175,10 +225,13 @@ pub struct SectionAttributes { pub non_global: bool, /// Implementation defined bit. pub p_bit: bool, + /// Is memory shareable across multiple CPUs pub shareable: bool, - /// AP bits + /// Access permissions pub access: AccessPermissions, + /// Raw memory attributes pub memory_attrs: MemoryRegionAttributesRaw, + /// Domain value for this section pub domain: u4, /// xN bit. pub execute_never: bool, @@ -195,7 +248,8 @@ impl SectionAttributes { Ok(Self::from_raw_unchecked(raw)) } - /// Retrieves the corresponding L1 section part without the section base address being set. + /// Retrieves the corresponding L1 section part without the section base + /// address being set. const fn l1_section_part(&self) -> L1Section { L1Section::builder() .with_base_addr_upper_bits(u12::new(0)) @@ -231,8 +285,9 @@ impl SectionAttributes { /// 1 MB section translation entry, mapping a 1 MB region to a physical address. /// -/// The ARM Cortex-A architecture programmers manual chapter 9.4 (p.163) or the ARMv7-A and ArmV7-R -/// architecture reference manual p.1323 specify these attributes in more detail. +/// The ARM Cortex-A architecture programmers manual chapter 9.4 (p.163) or the +/// ARMv7-A and ArmV7-R architecture reference manual p.1323 specify these +/// attributes in more detail. #[bitbybit::bitfield(u32, default = 0, defmt_fields(feature = "defmt"))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(PartialEq, Eq)] @@ -246,23 +301,31 @@ pub struct L1Section { /// Shareable bit. #[bit(16, rw)] s: bool, + /// Part of the access permissions field #[bit(15, rw)] apx: bool, - /// Type extension bits. + /// Memory Region Attribute bit #[bits(12..=14, rw)] tex: u3, + /// Part of the access permissions field #[bits(10..=11, rw)] ap: u2, + /// Implementation defined bit #[bit(9, rw)] p_bit: bool, + /// Domain field #[bits(5..=8, rw)] domain: u4, + /// Execute-never bit #[bit(4, rw)] xn: bool, + /// Memory Region Attribute bit #[bit(3, rw)] c: bool, + /// Memory Region Attribute bit #[bit(2, rw)] b: bool, + /// Entry Type #[bits(0..=1, rw)] entry_type: L1EntryType, } @@ -287,11 +350,12 @@ impl core::fmt::Debug for L1Section { } impl L1Section { - /// Generates a new L1 section from a physical address and section attributes. + /// Generates a new L1 section from a physical address and section + /// attributes. /// - /// The uppermost 12 bits of the physical address define which 1 MB of virtual address space - /// are being accessed. They will be stored in the L1 section table. This address MUST be - /// aligned to 1 MB. + /// The uppermost 12 bits of the physical address define which 1 MB of + /// virtual address space are being accessed. They will be stored in the L1 + /// section table. This address MUST be aligned to 1 MB. /// /// # Panics /// @@ -316,7 +380,8 @@ impl L1Section { *self = Self::new_with_addr_upper_bits_and_attrs(self.base_addr_upper_bits(), section_attrs) } - /// Create a new L1 section with the given upper 12 bits of the address and section attributes. + /// Create a new L1 section with the given upper 12 bits of the address and + /// section attributes. #[inline] pub const fn new_with_addr_upper_bits_and_attrs( addr_upper_twelve_bits: u12, @@ -368,8 +433,8 @@ mod tests { access: AccessPermissions::FullAccess, // TEX 0b101, c false, b true memory_attrs: MemoryRegionAttributes::CacheableMemory { - inner: CacheableMemoryAttribute::WriteBackWriteAlloc, - outer: CacheableMemoryAttribute::WriteBackWriteAlloc, + inner: CachePolicy::WriteBackWriteAlloc, + outer: CachePolicy::WriteBackWriteAlloc, } .as_raw(), domain: u4::new(0b1010), @@ -431,7 +496,7 @@ mod tests { p_bit: true, shareable: false, // APX true, AP 0b10 - access: AccessPermissions::ReadOnly, + access: AccessPermissions::ReadOnlyv6, // TEX 0b000, c false, b false memory_attrs: MemoryRegionAttributes::StronglyOrdered.as_raw(), domain: u4::new(0b1001), diff --git a/aarch32-cpu/src/pmsav7.rs b/aarch32-cpu/src/pmsav7.rs index 2b55a457..9706d3e2 100644 --- a/aarch32-cpu/src/pmsav7.rs +++ b/aarch32-cpu/src/pmsav7.rs @@ -8,6 +8,7 @@ use crate::register; use arbitrary_int::{u2, u3}; + #[doc(inline)] pub use register::drsr::RegionSize; @@ -235,21 +236,42 @@ pub enum MemAttr { /// Strongly-ordered memory StronglyOrdered, /// Device (shareable or non-shareable) - Device { shareable: bool }, - /// Outer and Inner Write-Through, no Write-Allocate - WriteThroughNoWriteAllocate { shareable: bool }, - /// Outer and Inner Write-Back, no Write-Allocate - WriteBackNoWriteAllocate { shareable: bool }, - /// Outer and Inner Non-cacheable - NonCacheable { shareable: bool }, + Device { + /// Is device shareable (across multiple CPUs) + shareable: bool, + }, + /// Normal Memory, Outer and Inner Cache are Write-Through, no Write-Allocate + WriteThroughNoWriteAlloc { + /// Is memory shareable (across multiple CPUs) + shareable: bool, + }, + /// Normal Memory, Outer and Inner Cache are Write-Back, no Write-Allocate + WriteBackNoWriteAlloc { + /// Is memory shareable (across multiple CPUs) + shareable: bool, + }, + /// Normal Memory, Non-cacheable in Outer and Inner Caches + NonCacheable { + /// Is memory shareable (across multiple CPUs) + shareable: bool, + }, /// Implementation Defined - ImplementationDefined { shareable: bool }, + ImplementationDefined { + /// Is memory shareable (across multiple CPUs) + shareable: bool, + }, /// Outer and Inner Write-Back, Write-Allocate - WriteBackWriteAllocate { shareable: bool }, - /// Cacheable memory + WriteBackWriteAlloc { + /// Is memory shareable (across multiple CPUs) + shareable: bool, + }, + /// Normal Memory, where Inner and Outer cache have different settings Cacheable { - outer: CacheablePolicy, - inner: CacheablePolicy, + /// Settings for the Outer Cache + outer: CachePolicy, + /// Settings for the Inner Cache + inner: CachePolicy, + /// Is memory shareable (across multiple CPUs) shareable: bool, }, } @@ -276,13 +298,13 @@ impl MemAttr { b: false, s: false, }, - MemAttr::WriteThroughNoWriteAllocate { shareable } => MemAttrBits { + MemAttr::WriteThroughNoWriteAlloc { shareable } => MemAttrBits { tex: u3::from_u8(0b000), c: true, b: false, s: *shareable, }, - MemAttr::WriteBackNoWriteAllocate { shareable } => MemAttrBits { + MemAttr::WriteBackNoWriteAlloc { shareable } => MemAttrBits { tex: u3::from_u8(0b000), c: true, b: true, @@ -300,7 +322,7 @@ impl MemAttr { b: false, s: *shareable, }, - MemAttr::WriteBackWriteAllocate { shareable } => MemAttrBits { + MemAttr::WriteBackWriteAlloc { shareable } => MemAttrBits { tex: u3::from_u8(0b000), c: true, b: true, @@ -338,20 +360,18 @@ impl MemAttrBits { match (self.tex.value(), self.c, self.b) { (0b000, false, false) => Some(MemAttr::StronglyOrdered), (0b000, false, true) => Some(MemAttr::Device { shareable: true }), - (0b000, true, false) => { - Some(MemAttr::WriteThroughNoWriteAllocate { shareable: self.s }) - } - (0b000, true, true) => Some(MemAttr::WriteBackNoWriteAllocate { shareable: self.s }), + (0b000, true, false) => Some(MemAttr::WriteThroughNoWriteAlloc { shareable: self.s }), + (0b000, true, true) => Some(MemAttr::WriteBackNoWriteAlloc { shareable: self.s }), (0b001, false, false) => Some(MemAttr::NonCacheable { shareable: self.s }), (0b001, true, false) => Some(MemAttr::ImplementationDefined { shareable: self.s }), - (0b001, true, true) => Some(MemAttr::WriteBackWriteAllocate { shareable: self.s }), + (0b001, true, true) => Some(MemAttr::WriteBackWriteAlloc { shareable: self.s }), (0b010, false, false) => Some(MemAttr::Device { shareable: false }), (tex, c, b) if tex >= 0b100 => { let outer = tex & 0b11; let inner = ((c as u8) << 1) | (b as u8); Some(MemAttr::Cacheable { - outer: CacheablePolicy::new_with_raw_value(u2::from_u8(outer)), - inner: CacheablePolicy::new_with_raw_value(u2::from_u8(inner)), + outer: CachePolicy::new_with_raw_value(u2::from_u8(outer)), + inner: CachePolicy::new_with_raw_value(u2::from_u8(inner)), shareable: self.s, }) } @@ -363,14 +383,20 @@ impl MemAttrBits { } } -/// Describes the cache policy of a region -#[derive(Debug, PartialEq, Eq)] +/// Whether/how a region is cacheable #[bitbybit::bitenum(u2, exhaustive = true)] -pub enum CacheablePolicy { +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Debug, PartialEq, Eq)] +pub enum CachePolicy { + /// Non-cacheable NonCacheable = 0b00, - WriteBackWriteAllocate = 0b01, - WriteThroughNoWriteAllocate = 0b10, - WriteBackNoWriteAllocate = 0b11, + /// Write-Back Cacheable, Write-Allocate + WriteBackWriteAlloc = 0b01, + /// Write-Through Cacheable + WriteThroughNoWriteAlloc = 0b10, + /// Write-Back Cacheable, no Write-Allocate + WriteBackNoWriteAlloc = 0b11, } #[cfg(test)] @@ -398,9 +424,9 @@ mod test { fn mem_attr_complex() { let mem_attr = MemAttr::Cacheable { // 0b01 - outer: CacheablePolicy::WriteBackWriteAllocate, + outer: CachePolicy::WriteBackWriteAlloc, // 0b10 - inner: CacheablePolicy::WriteThroughNoWriteAllocate, + inner: CachePolicy::WriteThroughNoWriteAlloc, shareable: true, }; let mem_attr_bits = mem_attr.to_bits(); diff --git a/aarch32-cpu/src/pmsav8.rs b/aarch32-cpu/src/pmsav8.rs index 91be34ed..5d03a24e 100644 --- a/aarch32-cpu/src/pmsav8.rs +++ b/aarch32-cpu/src/pmsav8.rs @@ -461,9 +461,9 @@ pub enum MemAttr { /// Normal memory NormalMemory { /// Controls outer access - outer: Cacheable, + outer: CachePolicy, /// Controls inner access - inner: Cacheable, + inner: CachePolicy, }, } @@ -484,23 +484,28 @@ impl MemAttr { /// Cacheability of a region #[derive(Debug, Clone, PartialEq, Eq)] -pub enum Cacheable { +pub enum CachePolicy { + /// Normal memory, Outer Write-Through Transient WriteThroughTransient(RwAllocPolicy), + /// Normal memory, Outer Write-Back Transient WriteBackTransient(RwAllocPolicy), + /// Normal memory, Outer Write-Through Non-transient WriteThroughNonTransient(RwAllocPolicy), + /// Normal memory, Outer Write-Back Non-transient WriteBackNonTransient(RwAllocPolicy), + /// Normal memory, Outer Non-cacheable NonCacheable, } -impl Cacheable { +impl CachePolicy { const fn to_bits(&self) -> u8 { #[allow(clippy::identity_op)] match self { - Cacheable::WriteThroughTransient(rw_alloc) => 0b0000 | (*rw_alloc as u8), - Cacheable::WriteBackTransient(rw_alloc) => 0b0100 | (*rw_alloc as u8), - Cacheable::WriteThroughNonTransient(rw_alloc) => 0b1000 | (*rw_alloc as u8), - Cacheable::WriteBackNonTransient(rw_alloc) => 0b1100 | (*rw_alloc as u8), - Cacheable::NonCacheable => 0b0100, + CachePolicy::WriteThroughTransient(rw_alloc) => 0b0000 | (*rw_alloc as u8), + CachePolicy::WriteBackTransient(rw_alloc) => 0b0100 | (*rw_alloc as u8), + CachePolicy::WriteThroughNonTransient(rw_alloc) => 0b1000 | (*rw_alloc as u8), + CachePolicy::WriteBackNonTransient(rw_alloc) => 0b1100 | (*rw_alloc as u8), + CachePolicy::NonCacheable => 0b0100, } } } @@ -536,8 +541,8 @@ mod test { #[test] fn mem_attr_normal() { let mem_attr = MemAttr::NormalMemory { - outer: Cacheable::NonCacheable, - inner: Cacheable::WriteBackNonTransient(RwAllocPolicy::W), + outer: CachePolicy::NonCacheable, + inner: CachePolicy::WriteBackNonTransient(RwAllocPolicy::W), }; assert_eq!( mem_attr.to_bits(), diff --git a/aarch32-cpu/src/register/armv8r/hmpuir.rs b/aarch32-cpu/src/register/armv8r/hmpuir.rs index 090fc4b6..211bf932 100644 --- a/aarch32-cpu/src/register/armv8r/hmpuir.rs +++ b/aarch32-cpu/src/register/armv8r/hmpuir.rs @@ -25,6 +25,7 @@ impl Hmpuir { #[inline] /// Reads HMPUIR (*Hyp MPU Type Register*) pub fn read() -> Hmpuir { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/armv8r/hprbar.rs b/aarch32-cpu/src/register/armv8r/hprbar.rs index e313c1ef..1efae36e 100644 --- a/aarch32-cpu/src/register/armv8r/hprbar.rs +++ b/aarch32-cpu/src/register/armv8r/hprbar.rs @@ -67,6 +67,7 @@ impl Hprbar { #[inline] /// Reads HPRBAR (*Hyp Protection Region Base Address Register*) pub fn read() -> Hprbar { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/armv8r/hprlar.rs b/aarch32-cpu/src/register/armv8r/hprlar.rs index b4f4549c..67559591 100644 --- a/aarch32-cpu/src/register/armv8r/hprlar.rs +++ b/aarch32-cpu/src/register/armv8r/hprlar.rs @@ -32,6 +32,7 @@ impl Hprlar { #[inline] /// Reads HPRLAR (*Hyp Protection Region Limit Address Register*) pub fn read() -> Hprlar { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/armv8r/prbar.rs b/aarch32-cpu/src/register/armv8r/prbar.rs index 4acabd14..454ad850 100644 --- a/aarch32-cpu/src/register/armv8r/prbar.rs +++ b/aarch32-cpu/src/register/armv8r/prbar.rs @@ -67,6 +67,7 @@ impl Prbar { #[inline] /// Reads PRBAR (*Protection Region Base Address Register*) pub fn read() -> Prbar { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/armv8r/prlar.rs b/aarch32-cpu/src/register/armv8r/prlar.rs index 6285fefd..2e3f2891 100644 --- a/aarch32-cpu/src/register/armv8r/prlar.rs +++ b/aarch32-cpu/src/register/armv8r/prlar.rs @@ -32,6 +32,7 @@ impl Prlar { #[inline] /// Reads PRLAR (*Protection Region Limit Address Register*) pub fn read() -> Prlar { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/bpiall.rs b/aarch32-cpu/src/register/bpiall.rs index 7f0ce864..71d68659 100644 --- a/aarch32-cpu/src/register/bpiall.rs +++ b/aarch32-cpu/src/register/bpiall.rs @@ -17,6 +17,7 @@ impl crate::register::SysRegWrite for BpIAll {} impl BpIAll { #[inline] + /// Writes 0 to BPIALL (*Branch Predictor Invalidate All*) to trigger operation pub fn write() { unsafe { ::write_raw(0) } } diff --git a/aarch32-cpu/src/register/ccsidr.rs b/aarch32-cpu/src/register/ccsidr.rs index f9955761..9cfaa7a5 100644 --- a/aarch32-cpu/src/register/ccsidr.rs +++ b/aarch32-cpu/src/register/ccsidr.rs @@ -7,18 +7,25 @@ use arbitrary_int::{u10, u15, u3}; #[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Ccsidr { + /// Indicates whether the cache level supports Write-Through #[bit(31, rw)] write_through: bool, + /// Indicates whether the cache level supports Write-Back #[bit(30, rw)] write_back: bool, + /// Indicates whether the cache level supports Read-Allocation #[bit(29, rw)] read_alloc: bool, + /// Indicates whether the cache level supports Write-Allocation #[bit(28, rw)] write_alloc: bool, + /// Number of sets in cache, minus 1 #[bits(13..=27, rw)] num_sets: u15, + /// Associativity of cache, minus 1 #[bits(3..=12, rw)] associativity: u10, + /// log2(cache line size in words), minus 1 #[bits(0..=2, rw)] line_size: u3, } @@ -37,6 +44,7 @@ impl Ccsidr { #[inline] /// Reads CCSIDR (*Current Cache Size ID Register*) pub fn read() -> Ccsidr { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/csselr.rs b/aarch32-cpu/src/register/csselr.rs index eed48318..580f4f54 100644 --- a/aarch32-cpu/src/register/csselr.rs +++ b/aarch32-cpu/src/register/csselr.rs @@ -7,8 +7,11 @@ use crate::register::{SysReg, SysRegRead, SysRegWrite}; #[derive(Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +/// Type of processor cache pub enum CacheType { + /// Data or Unified Cache DataOrUnified = 0, + /// Instruction Cache Instruction = 1, } @@ -20,6 +23,7 @@ pub struct Csselr { /// 0 for L1 cache, 1 for L2, etc. #[bits(1..=3, rw)] level: u3, + /// The type of cache #[bit(0, rw)] cache_type: CacheType, } @@ -38,6 +42,7 @@ impl Csselr { #[inline] /// Reads CSSELR (*Cache Size Selection Register*) pub fn read() -> Csselr { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/dacr.rs b/aarch32-cpu/src/register/dacr.rs index 1c52743e..a597d8ee 100644 --- a/aarch32-cpu/src/register/dacr.rs +++ b/aarch32-cpu/src/register/dacr.rs @@ -6,6 +6,7 @@ use crate::register::{SysReg, SysRegRead, SysRegWrite}; #[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Dacr { + /// An array of bits controlling access to each of the 16 domains #[bits(0..=1, rw)] d: [DomainAccess; 16], } @@ -40,6 +41,7 @@ impl Dacr { #[inline] /// Reads DACR (*Domain Access Control Register*) pub fn read() -> Dacr { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/dccimvac.rs b/aarch32-cpu/src/register/dccimvac.rs index 9cd5f18e..6df24fca 100644 --- a/aarch32-cpu/src/register/dccimvac.rs +++ b/aarch32-cpu/src/register/dccimvac.rs @@ -1,7 +1,8 @@ -//! Code for managing DCCIMVAC (*Clean And Invalidate Data Cache Or Unified Cache Line by MVA to Point of Coherence.*) +//! Code for managing DCCIMVAC (*Data Cache line Clean and Invalidate by VA to PoC Register*) use crate::register::{SysReg, SysRegWrite}; +/// DCCIMVAC (*Data Cache line Clean and Invalidate by VA to PoC Register*) #[derive(Debug, Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -9,6 +10,7 @@ pub struct Dccimvac(pub u32); impl Dccimvac { #[inline] + /// Create a new DCCIMVAC containing the address to clean and invalidate pub const fn new(addr: u32) -> Self { Self(addr) } @@ -26,7 +28,7 @@ impl crate::register::SysRegWrite for Dccimvac {} impl Dccimvac { #[inline] - /// Writes DCCIMVAC (*Clean And Invalidate Data Cache Or Unified Cache Line by MVA to Point of Coherence.*) + /// Writes DCCIMVAC (*Data Cache line Clean and Invalidate by VA to PoC Register*) /// /// # Safety /// diff --git a/aarch32-cpu/src/register/dccisw.rs b/aarch32-cpu/src/register/dccisw.rs index e8152f24..987686a6 100644 --- a/aarch32-cpu/src/register/dccisw.rs +++ b/aarch32-cpu/src/register/dccisw.rs @@ -1,4 +1,4 @@ -//! Code for managing DCCISW (*Clean and Invalidate Data or Unified cache line by Set/Way.*) +//! Code for managing DCCISW (*Data Cache line Clean and Invalidate by Set/Way Register*) use arbitrary_int::u3; @@ -7,6 +7,7 @@ use crate::register::{SysReg, SysRegWrite}; #[derive(Debug, Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +/// DCCISW (*Data Cache line Clean and Invalidate by Set/Way Register*) pub struct Dccisw(pub u32); impl Dccisw { @@ -52,7 +53,7 @@ impl crate::register::SysRegWrite for Dccisw {} impl Dccisw { #[inline] - /// Writes DCCISW (*Clean and Invalidate data or unified cache line by set/way.*) + /// Writes DCCISW (*Data Cache line Clean and Invalidate by Set/Way Register*) /// /// # Safety /// diff --git a/aarch32-cpu/src/register/dccmvac.rs b/aarch32-cpu/src/register/dccmvac.rs index abf7ad27..b24bb507 100644 --- a/aarch32-cpu/src/register/dccmvac.rs +++ b/aarch32-cpu/src/register/dccmvac.rs @@ -1,14 +1,16 @@ -//! Code for managing DCCMVAC (*Clean Data Cache Or Unified Cache Line by MVA to Point of Coherence.*) +//! Code for managing DCCMVAC (*Data Cache line Clean by VA to PoC Register*) use crate::register::{SysReg, SysRegWrite}; #[derive(Debug, Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +/// DCCMVAC (*Data Cache line Clean by VA to PoC Register*) pub struct Dccmvac(pub u32); impl Dccmvac { #[inline] + /// Create a new DCCMVAC containing the Virtual Address to clean pub const fn new(addr: u32) -> Self { Self(addr) } @@ -26,7 +28,7 @@ impl crate::register::SysRegWrite for Dccmvac {} impl Dccmvac { #[inline] - /// Writes DCCMVAC (*Clean Data Cache Or Unified Cache Line by MVA to Point of Coherence.*) + /// Writes DCCMVAC (*Data Cache line Clean by VA to PoC Register*) /// /// # Safety /// diff --git a/aarch32-cpu/src/register/dccmvau.rs b/aarch32-cpu/src/register/dccmvau.rs index 98fdc70e..8c1f3ecb 100644 --- a/aarch32-cpu/src/register/dccmvau.rs +++ b/aarch32-cpu/src/register/dccmvau.rs @@ -1,14 +1,16 @@ -//! Code for managing DCCMVAU (*Clean Data Cache Or Unified Cache Line by MVA to Point of Unification.*) +//! Code for managing DCCMVAU (*Data Cache line Clean by VA to PoU Register*) use crate::register::{SysReg, SysRegWrite}; #[derive(Debug, Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +/// DCCMVAU (*Data Cache line Clean by VA to PoU Register*) pub struct Dccmvau(pub u32); impl Dccmvau { #[inline] + /// Create a new DCCMVAU value containing the Virtual Address to clean pub const fn new(addr: u32) -> Self { Self(addr) } @@ -26,7 +28,7 @@ impl crate::register::SysRegWrite for Dccmvau {} impl Dccmvau { #[inline] - /// Writes DCCMVAU (*Clean Data Cache Or Unified Cache Line by MVA to Point of Unification.*) + /// Writes DCCMVAU (*Data Cache line Clean by VA to PoU Register*) /// /// # Safety /// diff --git a/aarch32-cpu/src/register/dccsw.rs b/aarch32-cpu/src/register/dccsw.rs index 77f58b9e..40817a1e 100644 --- a/aarch32-cpu/src/register/dccsw.rs +++ b/aarch32-cpu/src/register/dccsw.rs @@ -1,4 +1,4 @@ -//! Code for managing DCCSW (*Clean Data or Unified Cache line by Set/Way.*) +//! Code for managing DCCSW (*Data Cache line Clean by Set/Way Register*) use arbitrary_int::u3; @@ -7,6 +7,7 @@ use crate::register::{SysReg, SysRegWrite}; #[derive(Debug, Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +/// DCCSW (*Data Cache line Clean by Set/Way Register*) pub struct Dccsw(pub u32); impl Dccsw { @@ -52,7 +53,7 @@ impl crate::register::SysRegWrite for Dccsw {} impl Dccsw { #[inline] - /// Writes DCCSW (*Clean Data or Unified Cache line by Set/Way.*) + /// Writes DCCSW (*Data Cache line Clean by Set/Way Register*) /// /// # Safety /// diff --git a/aarch32-cpu/src/register/dcimvac.rs b/aarch32-cpu/src/register/dcimvac.rs index 9848585a..a86f4080 100644 --- a/aarch32-cpu/src/register/dcimvac.rs +++ b/aarch32-cpu/src/register/dcimvac.rs @@ -1,14 +1,16 @@ -//! Code for managing DCIMVAC (*Invalidate Data Cache Or Unified Cache Line by MVA to Point of Coherence.*) +//! Code for managing DCIMVAC (*Data Cache line Invalidate by VA to PoC Register*) use crate::register::{SysReg, SysRegWrite}; #[derive(Debug, Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +/// DCIMVAC (*Data Cache line Invalidate by VA to PoC Register*) pub struct Dcimvac(pub u32); impl Dcimvac { #[inline] + /// Create a new DCIMVAC value, given an address pub const fn new(addr: u32) -> Self { Self(addr) } @@ -26,7 +28,7 @@ impl crate::register::SysRegWrite for Dcimvac {} impl Dcimvac { #[inline] - /// Writes DCIMVAC (*Invalidate Data Cache Or Unified Cache Line by MVA to Point of Coherence.*) + /// Writes DCIMVAC (*Data Cache line Invalidate by VA to PoC Register*) /// /// # Safety /// diff --git a/aarch32-cpu/src/register/dcisw.rs b/aarch32-cpu/src/register/dcisw.rs index 444b79d4..1cfbd2f6 100644 --- a/aarch32-cpu/src/register/dcisw.rs +++ b/aarch32-cpu/src/register/dcisw.rs @@ -1,4 +1,4 @@ -//! Code for managing DCISW (*Invalidate Data or Unified Cache line by Set/Way.*) +//! Code for managing DCISW (*Data Cache line Invalidate by Set/Way Register*) use arbitrary_int::u3; @@ -7,6 +7,7 @@ use crate::register::{SysReg, SysRegWrite}; #[derive(Debug, Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +/// DCISW (*Data Cache line Invalidate by Set/Way Register*) pub struct Dcisw(pub u32); impl Dcisw { @@ -52,7 +53,7 @@ impl crate::register::SysRegWrite for Dcisw {} impl Dcisw { #[inline] - /// Writes DCSW (*Invalidate Data or Unified Cache line by Set/Way.*) + /// Writes DCSW (*Data Cache line Invalidate by Set/Way Register*) /// /// # Safety /// diff --git a/aarch32-cpu/src/register/dfsr.rs b/aarch32-cpu/src/register/dfsr.rs index fe132db2..6742388c 100644 --- a/aarch32-cpu/src/register/dfsr.rs +++ b/aarch32-cpu/src/register/dfsr.rs @@ -92,18 +92,31 @@ pub struct Dfsr { #[derive(Debug, PartialEq, Eq)] #[repr(u8)] pub enum DfsrStatus { + /// Alignment fault AlignmentFault = 1, + /// Debug Exception Debug = 2, + /// Alternate value for Alignment fault AlignmentAlt = 3, + /// Translation fault, level 1 TranslationFaultFirstLevel = 5, + /// Translation fault, level 2 TranslationFaultSecondLevel = 7, + /// Synchronous External Abort SyncExtAbort = 8, + /// Domain fault, level 1 DomainFaultFirstLevel = 9, + /// Alternate value for Synchronous External Abort SyncExtAbortAlt = 10, + /// Domain fault, level 2 DomainFaultSecondLevel = 11, + /// Synchronous External abort, on translation table walk, level 1 SyncExtAbortOnTranslationTableWalkFirstLevel = 12, + /// Permission fault, level 1 PermissionFaultFirstLevel = 13, + /// Synchronous External abort, on translation table walk, level 2 SyncExtAbortOnTranslationTableWalkSecondLevel = 14, + /// Permission fault, level 2 PermissionFaultSecondLevel = 15, } @@ -185,11 +198,11 @@ pub enum DfsrStatus { AlignmentFault = 0b00001, /// Debug exception. Debug = 0b00010, - /// Access flag fault, level 1. + /// Access flag fault, level 1 AccessFlagFaultFirstLevel = 0b00011, /// Fault on instruction cache maintenance. CacheMaintenance = 0b00100, - /// Translation fault, level 1. + /// Translation fault, level 1 TranslationFaultFirstLevel = 0b00101, /// Access flag fault, level 2. AccessFlagFaultSecondLevel = 0b00110, @@ -197,13 +210,13 @@ pub enum DfsrStatus { TranslationFaultSecondLevel = 0b00111, /// Synchronous External abort, not on translation table walk. SyncExtAbort = 0b01000, - /// Domain fault, level 1. + /// Domain fault, level 1 DomainFaultFirstLevel = 0b01001, /// Domain fault, level 2. DomainFaultSecondLevel = 0b01011, - /// Synchronous External abort, on translation table walk, level 1. + /// Synchronous External abort, on translation table walk, level 1 SyncExtAbortOnTranslationTableWalkFirstLevel = 0b01100, - /// Permission fault, level 1. + /// Permission fault, level 1 PermissionFaultFirstLevel = 0b01101, /// Synchronous External abort, on translation table walk, level 2. SyncExtAbortOnTranslationTableWalkSecondLevel = 0b01110, @@ -217,7 +230,7 @@ pub enum DfsrStatus { SErrorParityEccError = 0b11000, /// Synchronous parity or ECC error on memory access, not on translation table walk. SyncParErrorOnMemAccess = 0b11001, - /// Synchronous parity or ECC error on translation table walk, level 1. + /// Synchronous parity or ECC error on translation table walk, level 1 SyncParErrorOnTranslationTableWalkFirstLevel = 0b11100, /// Synchronous parity or ECC error on translation table walk, level 2. SyncParErrorOnTranslationTableWalkSecondLevel = 0b11110, @@ -263,6 +276,7 @@ impl Dfsr { #[inline] /// Reads DFSR (*Data Fault Status Register*) pub fn read() -> Dfsr { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/dracr.rs b/aarch32-cpu/src/register/dracr.rs index 5edd99cc..94f01649 100644 --- a/aarch32-cpu/src/register/dracr.rs +++ b/aarch32-cpu/src/register/dracr.rs @@ -44,6 +44,7 @@ impl Dracr { /// /// Set RGNR to control which region this reads. pub fn read() -> Dracr { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/drsr.rs b/aarch32-cpu/src/register/drsr.rs index b0d893c8..b99cb605 100644 --- a/aarch32-cpu/src/register/drsr.rs +++ b/aarch32-cpu/src/register/drsr.rs @@ -77,6 +77,9 @@ pub enum RegionSize { } impl RegionSize { + /// Check address alignment + /// + /// Reports whether an address is aligned according to this region size pub fn is_aligned(&self, addr: *const u8) -> bool { let addr = addr as usize; if *self == RegionSize::_4G { @@ -127,6 +130,7 @@ impl Drsr { /// /// Set RGNR to control which region this reads. pub fn read() -> Drsr { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/generic_timer/cnthctl.rs b/aarch32-cpu/src/register/generic_timer/cnthctl.rs index 3bbf894c..e83992d5 100644 --- a/aarch32-cpu/src/register/generic_timer/cnthctl.rs +++ b/aarch32-cpu/src/register/generic_timer/cnthctl.rs @@ -8,40 +8,27 @@ use crate::register::{SysReg, SysRegRead, SysRegWrite}; #[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Cnthctl { - #[bits(19..=19, rw)] - cntpmask: bool, - #[bits(18..=18, rw)] - cntvmask: bool, - #[bits(17..=17, rw)] - evntis: bool, - #[bits(16..=16, rw)] - el1nvvct: bool, - #[bits(15..=15, rw)] - el1nvpct: bool, - #[bits(14..=14, rw)] - el1tvct: bool, - #[bits(13..=13, rw)] - el1tvt: bool, - #[bits(12..=12, rw)] - ecv: bool, - #[bits(11..=11, rw)] - el1pten: bool, - #[bits(10..=10, rw)] - el1pcten: bool, - #[bits(9..=9, rw)] - el0pten: bool, - #[bits(8..=8, rw)] - el0vten: bool, + /// Selects which bit of CNTPCT, as seen from EL2, is the trigger for the + /// event stream generated from that counter when that stream is enabled. #[bits(4..=7, rw)] evnti: u4, + /// Controls which transition of the CNTPCT trigger bit, as seen from EL2 + /// and defined by EVNTI, generates an event when the event stream is + /// enabled. #[bits(3..=3, rw)] evntdir: bool, + /// Enables the generation of an event stream from CNTPCT as seen from EL2. #[bits(2..=2, rw)] evnten: bool, + /// Traps Non-secure EL0 and EL1 MRC or MCR accesses, reported using EC + /// syndrome value 0x03, and MRRC or MCRR accesses, reported using EC + /// syndrome value 0x04, to the physical timer registers to Hyp mode. #[bits(1..=1, rw)] - el0vcten: bool, + pl1pcen: bool, + /// Traps Non-secure EL0 and EL1 MRRC or MCRR accesses, reported using EC + /// syndrome value 0x04, to the physical counter register to Hyp mode. #[bits(0..=0, rw)] - el0pcten: bool, + pl1pcten: bool, } impl SysReg for Cnthctl { @@ -58,6 +45,7 @@ impl Cnthctl { #[inline] /// Reads CNTHCTL (*Hyp Counter-timer Control Register*) pub fn read() -> Cnthctl { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/generic_timer/cnthp_ctl.rs b/aarch32-cpu/src/register/generic_timer/cnthp_ctl.rs index 9dd3aa9e..b0162b70 100644 --- a/aarch32-cpu/src/register/generic_timer/cnthp_ctl.rs +++ b/aarch32-cpu/src/register/generic_timer/cnthp_ctl.rs @@ -34,6 +34,7 @@ impl CnthpCtl { #[inline] /// Reads CNTHP_CTL (*Hyp Physical Counter-timer Control Register (EL2)*) pub fn read() -> CnthpCtl { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/generic_timer/cntkctl.rs b/aarch32-cpu/src/register/generic_timer/cntkctl.rs index 92db33f1..49fc9c70 100644 --- a/aarch32-cpu/src/register/generic_timer/cntkctl.rs +++ b/aarch32-cpu/src/register/generic_timer/cntkctl.rs @@ -68,6 +68,7 @@ impl Cntkctl { #[inline] /// Reads CNTKCTL (*Counter-timer Kernel Control Register*) pub fn read() -> Cntkctl { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/generic_timer/cntp_ctl.rs b/aarch32-cpu/src/register/generic_timer/cntp_ctl.rs index a61da3b9..0a78b081 100644 --- a/aarch32-cpu/src/register/generic_timer/cntp_ctl.rs +++ b/aarch32-cpu/src/register/generic_timer/cntp_ctl.rs @@ -44,6 +44,7 @@ impl CntpCtl { #[inline] /// Reads CNTP_CTL (*Physical Counter-timer Control Register*) pub fn read() -> CntpCtl { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/generic_timer/cntv_ctl.rs b/aarch32-cpu/src/register/generic_timer/cntv_ctl.rs index e7b4bc45..55bd739f 100644 --- a/aarch32-cpu/src/register/generic_timer/cntv_ctl.rs +++ b/aarch32-cpu/src/register/generic_timer/cntv_ctl.rs @@ -44,6 +44,7 @@ impl CntvCtl { #[inline] /// Reads CNTV_CTL (*Virtual Counter-timer Control Register*) pub fn read() -> CntvCtl { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/hyp/hcptr.rs b/aarch32-cpu/src/register/hyp/hcptr.rs index 864adea7..448b8b3c 100644 --- a/aarch32-cpu/src/register/hyp/hcptr.rs +++ b/aarch32-cpu/src/register/hyp/hcptr.rs @@ -34,6 +34,7 @@ impl Hcptr { #[inline] /// Reads HCPTR (*Hyp Architectural Feature Trap Register*) pub fn read() -> Hcptr { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } diff --git a/aarch32-cpu/src/register/hyp/hcr.rs b/aarch32-cpu/src/register/hyp/hcr.rs index 9424f92b..4b7b8022 100644 --- a/aarch32-cpu/src/register/hyp/hcr.rs +++ b/aarch32-cpu/src/register/hyp/hcr.rs @@ -98,9 +98,13 @@ pub struct Hcr { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Debug, PartialEq, Eq)] pub enum Bsu { + /// No effect NoEffect = 0b00, + /// Inner Shareable InnerShareable = 0b01, + /// Outer Shareable OuterShareable = 0b10, + /// Full System FullSystem = 0b11, } @@ -118,6 +122,7 @@ impl Hcr { #[inline] /// Reads HCR (*Hyp Configuration Register*) pub fn read() -> Hcr { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/hyp/hsctlr.rs b/aarch32-cpu/src/register/hyp/hsctlr.rs index b09e65e6..0e03ff4a 100644 --- a/aarch32-cpu/src/register/hyp/hsctlr.rs +++ b/aarch32-cpu/src/register/hyp/hsctlr.rs @@ -57,6 +57,7 @@ impl Hsctlr { #[inline] /// Reads HSCTLR (*Hyp System Control Register*) pub fn read() -> Hsctlr { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/hyp/hsr.rs b/aarch32-cpu/src/register/hyp/hsr.rs index b499db95..b4ff09ae 100644 --- a/aarch32-cpu/src/register/hyp/hsr.rs +++ b/aarch32-cpu/src/register/hyp/hsr.rs @@ -42,24 +42,43 @@ impl Hsr { #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Debug, PartialEq, Eq)] +/// Exception Class value from the HSR (*Hyp Syndrome Register*) pub enum ExceptionClass { + /// Unknown reason Unknown = 0b00_0000, + /// Trapped WFI or WFE instruction execution TrappedWfiWfe = 0b00_0001, + /// Trapped MCR or MRC access with (coproc==`0b1111`) that is not reported using EC value `0b000000`` TrappedCp15McrMrc = 0b00_0011, + /// Trapped MCRR or MRRC access with (coproc==`0b1111`) that is not reported using EC value `0b000000`` TrappedCp15McrrMrrc = 0b00_0100, + /// Trapped MCR or MRC access with (coproc==`0b1110``) TrappedCp14McrMrc = 0b00_0101, + /// Trapped LDC or STC access TrappedLdcStc = 0b00_0110, + /// Access to Advanced SIMD or floating-point functionality trapped by a `HCPTR.{TASE, TCP10}` control TrappedFpu = 0b00_0111, + /// Trapped VMRS access, from ID group trap, that is not reported using EC value `0b000111` TrappedVmrs = 0b00_1000, + /// Trapped MRRC access with (coproc==`0b1110`) TrappedCp14McrrMrrc = 0b00_1100, + /// Illegal exception return to AArch32 state IllegalAArch32Eret = 0b00_1110, + /// Exception on SVC instruction execution in AArch32 state routed to EL2 Svc = 0b01_0001, + /// HVC instruction execution in AArch32 state, when HVC is not disabled Hvc = 0b01_0010, + /// Trapped execution of SMC instruction in AArch32 state Smc = 0b01_0011, + /// Prefetch Abort from a lower Exception level PrefetchAbortFromLower = 0b10_0000, + /// Prefetch Abort taken without a change in Exception level PrefetchAbortFromCurrent = 0b10_0001, + /// PC alignment fault exception PcAlignment = 0b10_0010, + /// Data Abort exception from a lower Exception level DataAbortFromLower = 0b10_0100, + /// Data Abort exception taken without a change in Exception level DataAbortFromCurrent = 0b10_0101, } @@ -68,27 +87,46 @@ pub enum ExceptionClass { /// ISS is a 25 bit field whose meaning varies depending on the value of the EC field. #[derive(Debug, Clone)] pub enum Iss { + /// ISS for [`ExceptionClass::Unknown`] Unknown(IssUnknown), + /// ISS for [`ExceptionClass::TrappedWfiWfe`] TrappedWfiWfe(IssTrappedWfiWfe), + /// ISS for [`ExceptionClass::TrappedCp15McrMrc`] TrappedCp15McrMrc(IssTrappedMcrMrc), + /// ISS for [`ExceptionClass::TrappedCp15McrrMrrc`] TrappedCp15McrrMrrc(IssTrappedMcrrMrrc), + /// ISS for [`ExceptionClass::TrappedCp14McrMrc`] TrappedCp14McrMrc(IssTrappedMcrMrc), + /// ISS for [`ExceptionClass::TrappedLdcStc`] TrappedLdcStc(IssTrappedLdcStc), + /// ISS for [`ExceptionClass::TrappedFpu`] TrappedFpu(IssTrappedFpu), + /// ISS for [`ExceptionClass::TrappedVmrs`] TrappedVmrs(IssTrappedVmrs), + /// ISS for [`ExceptionClass::TrappedCp14McrrMrrc`] TrappedCp14McrrMrrc(IssTrappedMcrrMrrc), + /// ISS for [`ExceptionClass::IllegalAArch32Eret`] IllegalAArch32Eret, + /// ISS for [`ExceptionClass::Svc`] Svc(IssCall), + /// ISS for [`ExceptionClass::Hvc`] Hvc(IssCall), + /// ISS for [`ExceptionClass::Smc`] Smc(IssSmc), + /// ISS for [`ExceptionClass::PrefetchAbortFromLower`] PrefetchAbortFromLower(IssPrefetchAbort), + /// ISS for [`ExceptionClass::PrefetchAbortFromCurrent`] PrefetchAbortFromCurrent(IssPrefetchAbort), + /// ISS for [`ExceptionClass::PcAlignment`] PcAlignment, + /// ISS for [`ExceptionClass::DataAbortFromLower`] DataAbortFromLower(IssDataAbort), + /// ISS for [`ExceptionClass::DataAbortFromCurrent`] DataAbortFromCurrent(IssDataAbort), } impl ExceptionClass { + /// Convert an ISS value based on the Exception Class pub fn decode_iss(&self, iss: u25) -> Iss { match self { ExceptionClass::Unknown => Iss::Unknown(IssUnknown(iss.value())), @@ -324,8 +362,11 @@ pub struct IssDataAbort { #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Debug, PartialEq, Eq)] +/// The length of the instruction that trapped pub enum InstructionLength { + /// A 16-bit instruction SixteenBit = 0b0, + /// A 32-bit instruction ThirtyTwoBit = 0b1, } @@ -343,6 +384,7 @@ impl Hsr { #[inline] /// Reads HSR (*Hyp Syndrome Register*) pub fn read() -> Hsr { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/hyp/hvbar.rs b/aarch32-cpu/src/register/hyp/hvbar.rs index 13e238c5..bc076e93 100644 --- a/aarch32-cpu/src/register/hyp/hvbar.rs +++ b/aarch32-cpu/src/register/hyp/hvbar.rs @@ -1,4 +1,4 @@ -//! Code for HVBAR (*Hyp Vector Base Address Register*) +//! Code for managing HVBAR (*Hyp Vector Base Address Register*) use crate::register::{SysReg, SysRegRead, SysRegWrite}; diff --git a/aarch32-cpu/src/register/iciallu.rs b/aarch32-cpu/src/register/iciallu.rs index 589bd949..a0c1d552 100644 --- a/aarch32-cpu/src/register/iciallu.rs +++ b/aarch32-cpu/src/register/iciallu.rs @@ -1,4 +1,4 @@ -//! Code for managing ICIALLU (*Invalidate all instruction caches to PoU.*) +//! Code for managing ICIALLU (*Invalidate entire instruction cache to PoU Register*) //! //! Starting with ARMv6, the type of cache can be determined from the System Coprocessor register 0, //! and controlled through registers 1, 7 and 9. In earlier architecture variants, it is @@ -8,6 +8,7 @@ use crate::register::{SysReg, SysRegWrite}; #[derive(Debug, Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +/// ICIALLU (*Invalidate entire instruction cache to PoU Register*) pub struct Iciallu; impl SysReg for Iciallu { @@ -22,7 +23,7 @@ impl crate::register::SysRegWrite for Iciallu {} impl Iciallu { #[inline] - /// Writes ICIALLU (*Invalidate all instruction caches to PoU.*) + /// Writes 0 to ICIALLU (*Invalidate entire instruction cache to PoU Register*) to trigger operation pub fn write() { unsafe { ::write_raw(0); diff --git a/aarch32-cpu/src/register/ifsr.rs b/aarch32-cpu/src/register/ifsr.rs index 00efa8d7..4a0232f8 100644 --- a/aarch32-cpu/src/register/ifsr.rs +++ b/aarch32-cpu/src/register/ifsr.rs @@ -86,18 +86,31 @@ pub struct Ifsr { #[derive(Debug, PartialEq, Eq)] #[cfg(arm_architecture = "v5te")] pub enum IfsrStatus { + /// PC Alignment Fault Alignment = 1, + /// Debug Exception DebugEvent = 2, + /// Alternate value for PC Alignment Fault AlignmentAlt = 3, + /// Translation fault, level 1 TranslationFaultFirstLevel = 5, + /// Translation fault, level 2 TranslationFaultSecondLevel = 7, + /// Synchronous External abort SyncExtAbort = 8, + /// Domain fault, level 1 DomainFaultFirstLevel = 9, + /// Alternate value for Synchronous External abort SyncExtAbortAlt = 10, + /// Domain fault, level 2 DomainFaultSecondLevel = 11, + /// Synchronous External abort, on translation table walk, level 1 SyncExtAbortOnTranslationTableWalkFirstLevel = 12, + /// Permission fault, level 1 PermissionFaultFirstLevel = 13, + /// Synchronous External abort, on translation table walk, level 2 SyncExtAbortOnTranslationTableWalkSecondLevel = 14, + /// Permission fault, level 2 PermissionFaultSecondLevel = 15, } @@ -108,18 +121,31 @@ pub enum IfsrStatus { #[derive(Debug, PartialEq, Eq)] #[cfg(arm_architecture = "v6")] pub enum IfsrStatus { + /// PC Alignment Fault Alignment = 1, + /// Debug Exception DebugEvent = 2, + /// Access Flag fault, level 1 AccessFlagFaultFirstLevel = 3, + /// Translation fault, level 1 TranslationFaultFirstLevel = 5, + /// Access Flag fault, level 2 AccessFlagFaultSecondLevel = 6, + /// Translation fault, level 2 TranslationFaultSecondLevel = 7, + /// Synchronouse External Abort SyncExtAbort = 8, + /// Domain fault, level 1 DomainFaultFirstLevel = 9, + /// Domain fault, level 2 DomainFaultSecondLevel = 11, + /// Synchronous External abort, on translation table walk, level 1 SyncExtAbortOnTranslationTableWalkFirstLevel = 12, + /// Permission fault, level 1 PermissionFaultFirstLevel = 13, + /// Synchronous External abort, on translation table walk, level 2 SyncExtAbortOnTranslationTableWalkSecondLevel = 14, + /// Permission fault, level 2 PermissionFaultSecondLevel = 15, } @@ -130,12 +156,19 @@ pub enum IfsrStatus { #[derive(Debug, PartialEq, Eq)] #[cfg(arm_architecture = "v7-r")] pub enum IfsrStatus { + /// PC Alignment Fault Alignment = 1, + /// Debug Exception DebugEvent = 2, + /// Synchronous External abort SyncExtAbort = 8, + /// Permission fault, level 1 PermissionFaultFirstLevel = 13, + /// Asynchronous External abort AsyncExtAbort = 21, + /// Synchronous parity or ECC error SyncParityEccError = 25, + /// asynchronous parity or ECC error AsyncParityEccError = 24, } @@ -146,23 +179,41 @@ pub enum IfsrStatus { #[derive(Debug, PartialEq, Eq)] #[cfg(arm_architecture = "v7-a")] pub enum IfsrStatus { + /// Synchronous External abort, on translation table walk, level 1 SyncExtAbortOnTranslationTableWalkFirstLevel = 0b01100, + /// Synchronous External abort, on translation table walk, level 2 SyncExtAbortOnTranslationTableWalkSecondLevel = 0b01110, + /// Synchronous parity or ECC error on memory access, on translation table walk, level 1 SyncParErrorOnTranslationTableWalkFirstLevel = 0b11100, + /// Synchronous parity or ECC error on memory access, on translation table walk, level 2 SyncParErrorOnTranslationTableWalkSecondLevel = 0b11110, + /// Translation fault, level 1 TranslationFaultFirstLevel = 0b00101, + /// Translation fault, level 2 TranslationFaultSecondLevel = 0b00111, + /// Access flag fault, level 1 AccessFlagFaultFirstLevel = 0b00011, + /// Access flag fault, level 2 AccessFlagFaultSecondLevel = 0b00110, + /// Domain fault, level 1 DomainFaultFirstLevel = 0b01001, + /// Domain fault, level 2 DomainFaultSecondLevel = 0b01011, + /// Permission fault, level 1 PermissionFaultFirstLevel = 0b01101, + /// Permission fault, level 2 PermissionFaultSecondLevel = 0b01111, + /// Debug exception DebugEvent = 0b00010, + /// Synchronous External abort SyncExtAbort = 0b01000, + /// TLB conflict abort TlbConflictAbort = 0b10000, + /// IMPLEMENTATION DEFINED fault (Lockdown fault) Lockdown = 0b10100, + /// Co-Processor Abort CoprocessorAbort = 0b11010, + /// Synchronous parity or ECC error on memory access, not on translation table walk SyncParErrorOnMemAccess = 0b11001, } @@ -173,11 +224,17 @@ pub enum IfsrStatus { #[derive(Debug, PartialEq, Eq)] #[cfg(arm_architecture = "v8-r")] pub enum IfsrStatus { + /// Translation fault Translation = 4, + /// Permission fault Permission = 12, + /// Synchronous External abort SyncExtAbort = 16, + /// Synchronous parity or ECC error on memory access SyncParityEccError = 24, + /// PC alignment fault PcAlignment = 33, + /// Debug exception Debug = 34, } @@ -195,6 +252,7 @@ impl Ifsr { #[inline] /// Reads IFSR (*Instruction Fault Status Register*) pub fn read() -> Ifsr { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/imp/imp_cdbgdcd.rs b/aarch32-cpu/src/register/imp/imp_cdbgdcd.rs index 9abc129a..fbbb8e15 100644 --- a/aarch32-cpu/src/register/imp/imp_cdbgdcd.rs +++ b/aarch32-cpu/src/register/imp/imp_cdbgdcd.rs @@ -1,8 +1,8 @@ -//! Code for managing IMP_CDBGDCD (*Data Cache Data Read Operation.*) +//! Code for managing IMP_CDBGDCD (*Data Cache Data Read Operation*) use crate::register::{SysReg, SysRegWrite}; -/// IMP_CDBGDCD (*Data Cache Data Read Operation.*) +/// IMP_CDBGDCD (*Data Cache Data Read Operation*) #[derive(Debug, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -20,7 +20,7 @@ impl crate::register::SysRegWrite for ImpCdbgdcd {} impl ImpCdbgdcd { #[inline] - /// Writes IMP_CDBGDCD (*Data Cache Data Read Operation.*) + /// Writes IMP_CDBGDCD (*Data Cache Data Read Operation*) /// /// # Safety /// diff --git a/aarch32-cpu/src/register/imp/imp_cdbgdct.rs b/aarch32-cpu/src/register/imp/imp_cdbgdct.rs index 00194b37..5933a5ae 100644 --- a/aarch32-cpu/src/register/imp/imp_cdbgdct.rs +++ b/aarch32-cpu/src/register/imp/imp_cdbgdct.rs @@ -1,8 +1,8 @@ -//! Code for managing IMP_CDBGDCT (*Data Cache Tag Read Operation.*) +//! Code for managing IMP_CDBGDCT (*Data Cache Tag Read Operation*) use crate::register::{SysReg, SysRegWrite}; -/// IMP_CDBGDCT (*Data Cache Tag Read Operation.*) +/// IMP_CDBGDCT (*Data Cache Tag Read Operation*) #[derive(Debug, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -20,7 +20,7 @@ impl crate::register::SysRegWrite for ImpCdbgdct {} impl ImpCdbgdct { #[inline] - /// Writes IMP_CDBGDCT (*Data Cache Tag Read Operation.*) + /// Writes IMP_CDBGDCT (*Data Cache Tag Read Operation*) /// /// # Safety /// diff --git a/aarch32-cpu/src/register/imp/imp_cdbgdr0.rs b/aarch32-cpu/src/register/imp/imp_cdbgdr0.rs index 1d3e87b7..a1414030 100644 --- a/aarch32-cpu/src/register/imp/imp_cdbgdr0.rs +++ b/aarch32-cpu/src/register/imp/imp_cdbgdr0.rs @@ -1,8 +1,8 @@ -//! Code for managing IMP_CDBGDR0 (*Cache Debug Data Register 0.*) +//! Code for managing IMP_CDBGDR0 (*Cache Debug Data Register 0*) use crate::register::{SysReg, SysRegRead}; -/// IMP_CDBGDR0 (*Cache Debug Data Register 0.*) +/// IMP_CDBGDR0 (*Cache Debug Data Register 0*) #[derive(Debug, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -20,7 +20,7 @@ impl crate::register::SysRegRead for ImpCdbgdr0 {} impl ImpCdbgdr0 { #[inline] - /// Reads IMP_CDBGDR0 (*Cache Debug Data Register 0.*) + /// Reads IMP_CDBGDR0 (*Cache Debug Data Register 0*) pub fn read() -> ImpCdbgdr0 { unsafe { Self(::read_raw()) } } diff --git a/aarch32-cpu/src/register/imp/imp_cdbgdr1.rs b/aarch32-cpu/src/register/imp/imp_cdbgdr1.rs index 128919dd..3c6d9c2e 100644 --- a/aarch32-cpu/src/register/imp/imp_cdbgdr1.rs +++ b/aarch32-cpu/src/register/imp/imp_cdbgdr1.rs @@ -1,8 +1,8 @@ -//! Code for managing IMP_CDBGDR1 (*Cache Debug Data Register 1.*) +//! Code for managing IMP_CDBGDR1 (*Cache Debug Data Register 1*) use crate::register::{SysReg, SysRegRead}; -/// IMP_CDBGDR1 (*Cache Debug Data Register 1.*) +/// IMP_CDBGDR1 (*Cache Debug Data Register 1*) #[derive(Debug, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -20,7 +20,7 @@ impl crate::register::SysRegRead for ImpCdbgdr1 {} impl ImpCdbgdr1 { #[inline] - /// Reads IMP_CDBGDR1 (*Cache Debug Data Register 1.*) + /// Reads IMP_CDBGDR1 (*Cache Debug Data Register 1*) pub fn read() -> ImpCdbgdr1 { unsafe { Self(::read_raw()) } } diff --git a/aarch32-cpu/src/register/imp/imp_cdbgdr2.rs b/aarch32-cpu/src/register/imp/imp_cdbgdr2.rs index 4fc3e103..ef109e1f 100644 --- a/aarch32-cpu/src/register/imp/imp_cdbgdr2.rs +++ b/aarch32-cpu/src/register/imp/imp_cdbgdr2.rs @@ -1,8 +1,8 @@ -//! Code for managing IMP_CDBGDR2 (*Cache Debug Data Register 2.*) +//! Code for managing IMP_CDBGDR2 (*Cache Debug Data Register 2*) use crate::register::{SysReg, SysRegRead}; -/// IMP_CDBGDR2 (*Cache Debug Data Register 2.*) +/// IMP_CDBGDR2 (*Cache Debug Data Register 2*) #[derive(Debug, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -20,7 +20,7 @@ impl crate::register::SysRegRead for ImpCdbgdr2 {} impl ImpCdbgdr2 { #[inline] - /// Reads IMP_CDBGDR2 (*Cache Debug Data Register 2.*) + /// Reads IMP_CDBGDR2 (*Cache Debug Data Register 2*) pub fn read() -> ImpCdbgdr2 { unsafe { Self(::read_raw()) } } diff --git a/aarch32-cpu/src/register/imp/imp_cdbgicd.rs b/aarch32-cpu/src/register/imp/imp_cdbgicd.rs index 9847be2b..64d5705f 100644 --- a/aarch32-cpu/src/register/imp/imp_cdbgicd.rs +++ b/aarch32-cpu/src/register/imp/imp_cdbgicd.rs @@ -1,8 +1,8 @@ -//! Code for managing IMP_CDBGICD (*Instruction Cache Data Read Operation.*) +//! Code for managing IMP_CDBGICD (*Instruction Cache Data Read Operation*) use crate::register::{SysReg, SysRegWrite}; -/// IMP_CDBGICD (*Instruction Cache Data Read Operation.*) +/// IMP_CDBGICD (*Instruction Cache Data Read Operation*) #[derive(Debug, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -20,7 +20,7 @@ impl crate::register::SysRegWrite for ImpCdbgicd {} impl ImpCdbgicd { #[inline] - /// Writes IMP_CDBGICD (*Instruction Cache Data Read Operation.*) + /// Writes IMP_CDBGICD (*Instruction Cache Data Read Operation*) /// /// # Safety /// diff --git a/aarch32-cpu/src/register/imp/imp_cdbgict.rs b/aarch32-cpu/src/register/imp/imp_cdbgict.rs index cab5cec1..f6c847b4 100644 --- a/aarch32-cpu/src/register/imp/imp_cdbgict.rs +++ b/aarch32-cpu/src/register/imp/imp_cdbgict.rs @@ -1,8 +1,8 @@ -//! Code for managing IMP_CDBGICT (*Instruction Cache Tag Read Operation.*) +//! Code for managing IMP_CDBGICT (*Instruction Cache Tag Read Operation*) use crate::register::{SysReg, SysRegWrite}; -/// IMP_CDBGICT (*Instruction Cache Tag Read Operation.*) +/// IMP_CDBGICT (*Instruction Cache Tag Read Operation*) #[derive(Debug, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -20,7 +20,7 @@ impl crate::register::SysRegWrite for ImpCdbgict {} impl ImpCdbgict { #[inline] - /// Writes IMP_CDBGICT (*Instruction Cache Tag Read Operation.*) + /// Writes IMP_CDBGICT (*Instruction Cache Tag Read Operation*) /// /// # Safety /// diff --git a/aarch32-cpu/src/register/iracr.rs b/aarch32-cpu/src/register/iracr.rs index ae640f09..4d427c1d 100644 --- a/aarch32-cpu/src/register/iracr.rs +++ b/aarch32-cpu/src/register/iracr.rs @@ -44,6 +44,7 @@ impl Iracr { /// /// Set RGNR to control which region this reads. pub fn read() -> Iracr { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/irsr.rs b/aarch32-cpu/src/register/irsr.rs index 5e249923..1552c05f 100644 --- a/aarch32-cpu/src/register/irsr.rs +++ b/aarch32-cpu/src/register/irsr.rs @@ -42,6 +42,7 @@ impl Irsr { /// /// Set RGNR to control which region this reads. pub fn read() -> Irsr { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/mod.rs b/aarch32-cpu/src/register/mod.rs index 94a79de4..bde57d65 100644 --- a/aarch32-cpu/src/register/mod.rs +++ b/aarch32-cpu/src/register/mod.rs @@ -1,4 +1,6 @@ -//! CPU system register access code +//! Defines various AArch32 system registers +//! +//! These are all ready using Co-Processor read/write instructions pub mod actlr; pub mod actlr2; @@ -204,9 +206,10 @@ pub use vmpidr::Vmpidr; pub use vpidr::Vpidr; pub use vsctlr::Vsctlr; -#[cfg(any(test, doc, arm_architecture = "v8-r"))] -pub mod armv8r; -#[cfg(any(test, doc, arm_architecture = "v8-r"))] +#[cfg(any(test, arm_architecture = "v8-r"))] +mod armv8r; +#[cfg(any(test, arm_architecture = "v8-r"))] +#[doc(inline)] pub use armv8r::*; #[cfg(any(test, doc, arm_architecture = "v7-a", arm_architecture = "v8-r"))] diff --git a/aarch32-cpu/src/register/mpuir.rs b/aarch32-cpu/src/register/mpuir.rs index f28df795..25a652e2 100644 --- a/aarch32-cpu/src/register/mpuir.rs +++ b/aarch32-cpu/src/register/mpuir.rs @@ -33,6 +33,7 @@ impl Mpuir { #[inline] /// Reads MPUIR (*MPU Type Register*) pub fn read() -> Mpuir { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/aarch32-cpu/src/register/sctlr.rs b/aarch32-cpu/src/register/sctlr.rs index 486857a1..f52d4750 100644 --- a/aarch32-cpu/src/register/sctlr.rs +++ b/aarch32-cpu/src/register/sctlr.rs @@ -72,6 +72,7 @@ impl Sctlr { /// Read SCTLR (*System Control Register*) #[inline] pub fn read() -> Self { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } diff --git a/aarch32-cpu/src/register/tlbiall.rs b/aarch32-cpu/src/register/tlbiall.rs index e6f664eb..c5298367 100644 --- a/aarch32-cpu/src/register/tlbiall.rs +++ b/aarch32-cpu/src/register/tlbiall.rs @@ -17,6 +17,7 @@ impl crate::register::SysRegWrite for TlbIAll {} impl TlbIAll { #[inline] + /// Writes 0 to TLBIALL (*TLB Invalidate All Register*) to trigger operation pub fn write() { unsafe { ::write_raw(0) } } diff --git a/aarch32-cpu/src/register/ttbr0.rs b/aarch32-cpu/src/register/ttbr0.rs index ea9c8dd2..4fb9a523 100644 --- a/aarch32-cpu/src/register/ttbr0.rs +++ b/aarch32-cpu/src/register/ttbr0.rs @@ -87,11 +87,11 @@ pub enum Region { /// Normal memory, Outer Non-cacheable NonCacheable = 0b00, /// Normal memory, Outer Write-Back Write-Allocate Cacheable - WriteBackWriteAllocateCacheable = 0b01, + WriteBackWriteAllocCacheable = 0b01, /// Normal memory, Outer Write-Through Cacheable WriteThroughCacheable = 0b10, /// Normal memory, Outer Write-Back no Write-Allocate Cacheable - WriteBackNoWriteAllocateCacheable = 0b11, + WriteBackNoWriteAllocCacheable = 0b11, } impl SysReg for Ttbr0 { @@ -110,6 +110,7 @@ impl Ttbr0 { #[inline] /// Reads TTBR0 (*Translation Table Base Register 0*) pub fn read() -> Ttbr0 { + // Safety: it's OK to set bits with no accessors specified unsafe { Self::new_with_raw_value(::read_raw()) } } diff --git a/aarch32-cpu/src/stacks.rs b/aarch32-cpu/src/stacks.rs index 161902f7..20ee7a2a 100644 --- a/aarch32-cpu/src/stacks.rs +++ b/aarch32-cpu/src/stacks.rs @@ -33,30 +33,32 @@ pub unsafe fn stack_used_bytes(stack: core::ops::Range<*const u32>) -> (usize, u /// of at least `size` words in length. unsafe fn stack_unused_bytes_asm(start: *const u32, size: usize) -> usize { let result: usize; - core::arch::asm!( - r#" - // skip out if size is zero - movs {result}, #0 - cmp {size}, #0 - beq 3f -2: // loop - ldr {scratch}, [{start}] - cmp {scratch}, #0 - // break out if value is non-zero - bne 3f - // otherwise increment counter - adds {result}, {result}, #1 - adds {start}, {start}, #4 - // loop if not finished yet - cmp {result}, {size} - bne 2b - // all finished -3: - "#, - size = in(reg) size, - start = inout(reg) start => _, - result = out(reg) result, - scratch = out(reg) _, - ); + unsafe { + core::arch::asm!( + r#" + // skip out if size is zero + movs {result}, #0 + cmp {size}, #0 + beq 3f + 2: // loop + ldr {scratch}, [{start}] + cmp {scratch}, #0 + // break out if value is non-zero + bne 3f + // otherwise increment counter + adds {result}, {result}, #1 + adds {start}, {start}, #4 + // loop if not finished yet + cmp {result}, {size} + bne 2b + // all finished + 3: + "#, + size = in(reg) size, + start = inout(reg) start => _, + result = out(reg) result, + scratch = out(reg) _, + ); + } result } diff --git a/examples/mps3-an536-el2/src/bin/generic-timer.rs b/examples/mps3-an536-el2/src/bin/generic-timer.rs index 102a3220..3a20c547 100644 --- a/examples/mps3-an536-el2/src/bin/generic-timer.rs +++ b/examples/mps3-an536-el2/src/bin/generic-timer.rs @@ -44,7 +44,7 @@ fn main() -> ! { hyp_timer.countdown_set(hyp_timer.frequency_hz() / 5); hyp_timer.enable(true); // used in interrupt handler - drop(hyp_timer); + let _ = hyp_timer; println!("Enabling interrupts..."); dump_sctlr(); @@ -111,5 +111,5 @@ fn hvc_handler(hsr: u32, frame: &aarch32_rt::Frame) -> u32 { hsr.get_iss(), frame ); - return frame.r0; + frame.r0 } diff --git a/examples/mps3-an536-el2/src/bin/hvc-a32.rs b/examples/mps3-an536-el2/src/bin/hvc-a32.rs index 8d12237b..5bb2aa89 100644 --- a/examples/mps3-an536-el2/src/bin/hvc-a32.rs +++ b/examples/mps3-an536-el2/src/bin/hvc-a32.rs @@ -34,7 +34,7 @@ fn hvc_handler(hsr: u32, frame: &aarch32_rt::Frame) -> u32 { if hsr.iss().value() == 0xABCD { do_hvc2(); } - return 0x12345678; + 0x12345678 } #[instruction_set(arm::a32)] diff --git a/examples/mps3-an536-el2/src/bin/hvc-t32.rs b/examples/mps3-an536-el2/src/bin/hvc-t32.rs index 98ad5808..9b63655c 100644 --- a/examples/mps3-an536-el2/src/bin/hvc-t32.rs +++ b/examples/mps3-an536-el2/src/bin/hvc-t32.rs @@ -34,7 +34,7 @@ fn hvc_handler(hsr: u32, frame: &aarch32_rt::Frame) -> u32 { if hsr.iss().value() == 0xABCD { do_hvc2(); } - return 0x12345678; + 0x12345678 } #[instruction_set(arm::t32)] diff --git a/examples/mps3-an536-el2/src/bin/svc-a32.rs b/examples/mps3-an536-el2/src/bin/svc-a32.rs index e131b768..02adc0a3 100644 --- a/examples/mps3-an536-el2/src/bin/svc-a32.rs +++ b/examples/mps3-an536-el2/src/bin/svc-a32.rs @@ -34,7 +34,7 @@ fn hvc_handler(hsr: u32, frame: &aarch32_rt::Frame) -> u32 { if hsr.iss().value() == 0xABCD { do_svc2(); } - return 0x12345678; + 0x12345678 } #[instruction_set(arm::a32)] diff --git a/examples/mps3-an536-el2/src/bin/svc-t32.rs b/examples/mps3-an536-el2/src/bin/svc-t32.rs index 6957aea0..e542a727 100644 --- a/examples/mps3-an536-el2/src/bin/svc-t32.rs +++ b/examples/mps3-an536-el2/src/bin/svc-t32.rs @@ -34,7 +34,7 @@ fn hvc_handler(hsr: u32, frame: &aarch32_rt::Frame) -> u32 { if hsr.iss().value() == 0x12 { do_svc2(); } - return 0x12345678; + 0x12345678 } #[instruction_set(arm::t32)] diff --git a/examples/mps3-an536/src/bin/mpu_setup.rs b/examples/mps3-an536/src/bin/mpu_setup.rs index ae84cac8..42d5881e 100644 --- a/examples/mps3-an536/src/bin/mpu_setup.rs +++ b/examples/mps3-an536/src/bin/mpu_setup.rs @@ -6,7 +6,7 @@ #![no_main] use aarch32_cpu::pmsav8::{ - Cacheable, El1AccessPerms, El1Mpu, El1Region, El1Shareability, MemAttr, RwAllocPolicy, + CachePolicy, El1AccessPerms, El1Mpu, El1Region, El1Shareability, MemAttr, RwAllocPolicy, }; use aarch32_rt::{entry, sections::Section, stacks::Stack}; use semihosting::println; @@ -31,13 +31,13 @@ const MAIR_DEVICE: u8 = 2; static MEM_ATTRS: [MemAttr; 8] = [ // Read-only Code RAM MemAttr::NormalMemory { - outer: Cacheable::WriteThroughNonTransient(RwAllocPolicy::R), - inner: Cacheable::WriteThroughNonTransient(RwAllocPolicy::R), + outer: CachePolicy::WriteThroughNonTransient(RwAllocPolicy::R), + inner: CachePolicy::WriteThroughNonTransient(RwAllocPolicy::R), }, // Read-write RAM MemAttr::NormalMemory { - outer: Cacheable::WriteBackNonTransient(RwAllocPolicy::W), - inner: Cacheable::WriteBackNonTransient(RwAllocPolicy::W), + outer: CachePolicy::WriteBackNonTransient(RwAllocPolicy::W), + inner: CachePolicy::WriteBackNonTransient(RwAllocPolicy::W), }, // Device Memory MemAttr::DeviceMemory, diff --git a/examples/mps3-an536/src/bin/registers.rs b/examples/mps3-an536/src/bin/registers.rs index 46cb0b9d..5fdce39b 100644 --- a/examples/mps3-an536/src/bin/registers.rs +++ b/examples/mps3-an536/src/bin/registers.rs @@ -36,7 +36,7 @@ fn chip_info() { #[cfg(arm_architecture = "v7-r")] fn mpu_pmsa_v7() { use aarch32_cpu::{ - pmsav7::{CacheablePolicy, Config, MemAttr, Mpu, Region, RegionSize}, + pmsav7::{Cacheable, Config, MemAttr, Mpu, Region, RegionSize}, register::Mpuir, }; @@ -69,8 +69,8 @@ fn mpu_pmsa_v7() { enabled: true, no_exec: false, mem_attr: MemAttr::Cacheable { - inner: CacheablePolicy::WriteThroughNoWriteAllocate, - outer: CacheablePolicy::NonCacheable, + inner: Cacheable::WriteThroughNoWriteAlloc, + outer: Cacheable::NonCacheable, shareable: true, }, }], @@ -90,10 +90,10 @@ fn mpu_pmsa_v7() { fn mpu_pmsa_v8() { use aarch32_cpu::{ pmsav8::{ - Cacheable, El1AccessPerms, El1Config, El1Mpu, El1Region, El1Shareability, MemAttr, + CachePolicy, El1AccessPerms, El1Config, El1Mpu, El1Region, El1Shareability, MemAttr, RwAllocPolicy, }, - register::{Mpuir, armv8r::*}, + register::*, }; // How many regions? @@ -261,8 +261,8 @@ fn mpu_pmsa_v8() { }, ], memory_attributes: &[MemAttr::NormalMemory { - outer: Cacheable::WriteThroughNonTransient(RwAllocPolicy::RW), - inner: Cacheable::WriteThroughNonTransient(RwAllocPolicy::RW), + outer: CachePolicy::WriteThroughNonTransient(RwAllocPolicy::RW), + inner: CachePolicy::WriteThroughNonTransient(RwAllocPolicy::RW), }], }) .unwrap(); diff --git a/examples/versatileab/reference/registers-armv7r-none-eabi.out b/examples/versatileab/reference/registers-armv7r-none-eabi.out index de0f7f8e..a1d95060 100644 --- a/examples/versatileab/reference/registers-armv7r-none-eabi.out +++ b/examples/versatileab/reference/registers-armv7r-none-eabi.out @@ -20,7 +20,7 @@ DRegion 12: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false DRegion 13: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } DRegion 14: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } DRegion 15: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } -DRegion 0: Region { base: 0x20000000, size: _16M, subregion_mask: 0, enabled: true, no_exec: false, mem_attr: Cacheable { outer: NonCacheable, inner: WriteThroughNoWriteAllocate, shareable: true } } +DRegion 0: Region { base: 0x20000000, size: _16M, subregion_mask: 0, enabled: true, no_exec: false, mem_attr: Cacheable { outer: NonCacheable, inner: WriteThroughNoWriteAlloc, shareable: true } } DRegion 1: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } DRegion 2: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } DRegion 3: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } diff --git a/examples/versatileab/reference/registers-armv7r-none-eabihf.out b/examples/versatileab/reference/registers-armv7r-none-eabihf.out index de0f7f8e..a1d95060 100644 --- a/examples/versatileab/reference/registers-armv7r-none-eabihf.out +++ b/examples/versatileab/reference/registers-armv7r-none-eabihf.out @@ -20,7 +20,7 @@ DRegion 12: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false DRegion 13: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } DRegion 14: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } DRegion 15: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } -DRegion 0: Region { base: 0x20000000, size: _16M, subregion_mask: 0, enabled: true, no_exec: false, mem_attr: Cacheable { outer: NonCacheable, inner: WriteThroughNoWriteAllocate, shareable: true } } +DRegion 0: Region { base: 0x20000000, size: _16M, subregion_mask: 0, enabled: true, no_exec: false, mem_attr: Cacheable { outer: NonCacheable, inner: WriteThroughNoWriteAlloc, shareable: true } } DRegion 1: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } DRegion 2: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } DRegion 3: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } diff --git a/examples/versatileab/reference/registers-thumbv7r-none-eabi.out b/examples/versatileab/reference/registers-thumbv7r-none-eabi.out index de0f7f8e..a1d95060 100644 --- a/examples/versatileab/reference/registers-thumbv7r-none-eabi.out +++ b/examples/versatileab/reference/registers-thumbv7r-none-eabi.out @@ -20,7 +20,7 @@ DRegion 12: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false DRegion 13: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } DRegion 14: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } DRegion 15: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } -DRegion 0: Region { base: 0x20000000, size: _16M, subregion_mask: 0, enabled: true, no_exec: false, mem_attr: Cacheable { outer: NonCacheable, inner: WriteThroughNoWriteAllocate, shareable: true } } +DRegion 0: Region { base: 0x20000000, size: _16M, subregion_mask: 0, enabled: true, no_exec: false, mem_attr: Cacheable { outer: NonCacheable, inner: WriteThroughNoWriteAlloc, shareable: true } } DRegion 1: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } DRegion 2: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } DRegion 3: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } diff --git a/examples/versatileab/reference/registers-thumbv7r-none-eabihf.out b/examples/versatileab/reference/registers-thumbv7r-none-eabihf.out index de0f7f8e..a1d95060 100644 --- a/examples/versatileab/reference/registers-thumbv7r-none-eabihf.out +++ b/examples/versatileab/reference/registers-thumbv7r-none-eabihf.out @@ -20,7 +20,7 @@ DRegion 12: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false DRegion 13: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } DRegion 14: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } DRegion 15: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } -DRegion 0: Region { base: 0x20000000, size: _16M, subregion_mask: 0, enabled: true, no_exec: false, mem_attr: Cacheable { outer: NonCacheable, inner: WriteThroughNoWriteAllocate, shareable: true } } +DRegion 0: Region { base: 0x20000000, size: _16M, subregion_mask: 0, enabled: true, no_exec: false, mem_attr: Cacheable { outer: NonCacheable, inner: WriteThroughNoWriteAlloc, shareable: true } } DRegion 1: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } DRegion 2: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } DRegion 3: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered } diff --git a/examples/versatileab/src/bin/registers.rs b/examples/versatileab/src/bin/registers.rs index 7951be3c..e882dbb9 100644 --- a/examples/versatileab/src/bin/registers.rs +++ b/examples/versatileab/src/bin/registers.rs @@ -29,7 +29,7 @@ fn chip_info() { #[cfg(arm_architecture = "v7-r")] fn mpu_pmsa_v7() { use aarch32_cpu::{ - pmsav7::{CacheablePolicy, Config, MemAttr, Mpu, Region, RegionSize}, + pmsav7::{CachePolicy, Config, MemAttr, Mpu, Region, RegionSize}, register::Mpuir, }; @@ -62,8 +62,8 @@ fn mpu_pmsa_v7() { enabled: true, no_exec: false, mem_attr: MemAttr::Cacheable { - inner: CacheablePolicy::WriteThroughNoWriteAllocate, - outer: CacheablePolicy::NonCacheable, + inner: CachePolicy::WriteThroughNoWriteAlloc, + outer: CachePolicy::NonCacheable, shareable: true, }, }], diff --git a/examples/versatileab/src/mmu.rs b/examples/versatileab/src/mmu.rs index 60da0210..afe918a0 100644 --- a/examples/versatileab/src/mmu.rs +++ b/examples/versatileab/src/mmu.rs @@ -18,7 +18,7 @@ //! all the hardware either on the real board or emulated by QEMU. use aarch32_cpu::mmu::{ - AccessPermissions, CacheableMemoryAttribute, L1Section, L1Table, MemoryRegionAttributes, + AccessPermissions, CachePolicy, L1Section, L1Table, MemoryRegionAttributes, NUM_L1_PAGE_TABLE_ENTRIES, SectionAttributes, }; use arbitrary_int::u4; @@ -32,8 +32,8 @@ const SDRAM_ATTRS: SectionAttributes = SectionAttributes { shareable: true, access: AccessPermissions::FullAccess, memory_attrs: MemoryRegionAttributes::CacheableMemory { - inner: CacheableMemoryAttribute::WriteBackWriteAlloc, - outer: CacheableMemoryAttribute::WriteBackWriteAlloc, + inner: CachePolicy::WriteBackWriteAlloc, + outer: CachePolicy::WriteBackWriteAlloc, } .as_raw(), domain: u4::new(0b0), @@ -84,7 +84,7 @@ pub fn set_mmu() { .with_address(core::ptr::addr_of!(MMU_L1_PAGE_TABLE) as usize) .with_irgn(false) .with_nos(false) - .with_rgn(aarch32_cpu::register::ttbr0::Region::WriteBackWriteAllocateCacheable) + .with_rgn(aarch32_cpu::register::ttbr0::Region::WriteBackWriteAllocCacheable) .with_s(true) .with_c(true); unsafe { aarch32_cpu::register::Ttbr0::write(ttbr0) } From 662a153c0077489a4b2e09e857d0d8f944f7b1f7 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sat, 18 Apr 2026 17:38:14 +0100 Subject: [PATCH 2/6] Un-deprecate arm_targets::process_target. It's still useful for unit testing, and the CLI uses it. --- arm-targets/src/lib.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/arm-targets/src/lib.rs b/arm-targets/src/lib.rs index 649867be..45986f9f 100644 --- a/arm-targets/src/lib.rs +++ b/arm-targets/src/lib.rs @@ -123,8 +123,15 @@ impl TargetInfo { } } -/// Process the ${TARGET} environment variable, and emit cargo configuration to -/// standard out. +/// Process the `${TARGET}` environment variable, and emit cargo configuration +/// to standard out. +/// +/// You probably want to call this from your build script. +/// +/// When `${TARGET}` isn't known to this library, it falls back to using +/// `CARGO_CFG_TARGET_*` variables. These are only really useful on nightly Rust +/// currently, because the ones that give us details about the architecture are +/// not yet stable. pub fn process() -> TargetInfo { let target = std::env::var("TARGET").expect("build script TARGET variable"); let target_info_from_target = TargetInfo::get(&target); @@ -149,10 +156,10 @@ pub fn process() -> TargetInfo { } /// Process a given target string, and emit cargo configuration to standard out. -#[deprecated( - since = "0.4.2", - note = "This function does not take `CARGO_CFG_TARGET_*` variables into account." -)] +/// +/// Note that this function does not take `CARGO_CFG_TARGET_*` variables into +/// account. You probably do not want to call this from your build script - it's +/// mainly for unit testing this library or if you want to know about a specific target. pub fn process_target(target: &str) -> TargetInfo { let target_info = TargetInfo::get(target); target_info.dump(); From 1a787508822276c7ca3ca96eb96d38cac01e7baf Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sat, 18 Apr 2026 17:38:21 +0100 Subject: [PATCH 3/6] arm-targets typos --- arm-targets/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arm-targets/src/lib.rs b/arm-targets/src/lib.rs index 45986f9f..5639e4a0 100644 --- a/arm-targets/src/lib.rs +++ b/arm-targets/src/lib.rs @@ -169,11 +169,11 @@ pub fn process_target(target: &str) -> TargetInfo { /// The Arm Instruction Set #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum Isa { - /// A64 instructions are executed by Arm processors in Aarch64 mode + /// A64 instructions are executed by Arm processors in AArch64 mode A64, - /// A32 instructions are executed by Arm processors in Aarch32 Arm mode + /// A32 instructions are executed by Arm processors in AArch32 Arm mode A32, - /// T32 instructions are executed by Arm processors in Aarch32 Thumb mode + /// T32 instructions are executed by Arm processors in AArch32 Thumb mode T32, } From bd85ca7fefffb682a87df98f449cd8c1da868481 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sat, 18 Apr 2026 17:38:38 +0100 Subject: [PATCH 4/6] arm-targets switch to HashSet It just seems to make more sense than doing a linear walk of a Vec. --- arm-targets/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arm-targets/src/lib.rs b/arm-targets/src/lib.rs index 5639e4a0..f1896571 100644 --- a/arm-targets/src/lib.rs +++ b/arm-targets/src/lib.rs @@ -40,7 +40,7 @@ //! cargo:rustc-check-cfg=cfg(arm_abi, values("eabi", "eabihf")) //! ``` -use std::env; +use std::{collections::HashSet, env}; #[derive(Default, Debug)] pub struct TargetInfo { @@ -265,7 +265,7 @@ impl Arch { pub fn from_cargo_env() -> Option { let arch = env::var("CARGO_CFG_TARGET_ARCH").ok()?; let features = env::var("CARGO_CFG_TARGET_FEATURE").ok()?; - let features = features.split(",").collect::>(); + let features: HashSet<&str> = features.split(",").collect(); if (arch == "arm" && features.contains(&"v8")) || arch == "aarch64" { if features.contains(&"mclass") { From bf3f8f380b81a0b047fbbee86fecd99566ace029 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sat, 18 Apr 2026 18:05:29 +0100 Subject: [PATCH 5/6] Remove more nightly Rust. It all works on stable now (with RUSTC_BOOTSTRAP=1) --- .github/workflows/build.yml | 10 ++++------ justfile | 11 +++++------ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9e600605..dcfd58dc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -63,9 +63,8 @@ jobs: uses: taiki-e/install-action@just - name: Install Rust run: | - rustup install nightly-2026-02-26 - rustup component add rust-src --toolchain nightly-2026-02-26 - rustup default nightly-2026-02-26 + rustup install stable + rustup default stable - name: Build run: | just build-tier3 ${{ matrix.target }} @@ -89,9 +88,8 @@ jobs: uses: taiki-e/install-action@just - name: Install Rust run: | - rustup install nightly-2026-02-26 - rustup component add rust-src --toolchain nightly-2026-02-26 - rustup default nightly-2026-02-26 + rustup install stable + rustup default stable - name: Build run: | just build-tier3-no-atomics ${{ matrix.target }} diff --git a/justfile b/justfile index 07e66086..57a2b8a6 100644 --- a/justfile +++ b/justfile @@ -11,7 +11,6 @@ export RUSTC_BOOTSTRAP := "1" # If you run with `just --set v 1` then we make cargo run in verbose mode v := "0" verbose := if v == "1" { "--verbose" } else { "" } -nightly := "nightly-2026-02-26" # Our default target. It does everything that you might want to do pre-checkin. check: build-all build-all-examples fmt-check clippy-examples clippy-targets clippy-host test @@ -57,14 +56,14 @@ build-arm-targets: # Builds our workspace with various features, building core from source, but skipping anything that requires atomics build-tier3-no-atomics target: - cargo +{{nightly}} build --target {{target}} -Zbuild-std=core {{verbose}} - cargo +{{nightly}} build --target {{target}} -Zbuild-std=core --features "serde, defmt, critical-section-single-core, check-asm" {{verbose}} + cargo build --target {{target}} -Zbuild-std=core {{verbose}} + cargo build --target {{target}} -Zbuild-std=core --features "serde, defmt, critical-section-single-core, check-asm" {{verbose}} # Builds our workspace with various features, building core from source build-tier3 target: - cargo +{{nightly}} build --target {{target}} -Zbuild-std=core {{verbose}} - cargo +{{nightly}} build --target {{target}} -Zbuild-std=core --features "serde, defmt, critical-section-multi-core, check-asm" {{verbose}} - cargo +{{nightly}} build --target {{target}} -Zbuild-std=core --features "serde, defmt, critical-section-single-core, check-asm" {{verbose}} + cargo build --target {{target}} -Zbuild-std=core {{verbose}} + cargo build --target {{target}} -Zbuild-std=core --features "serde, defmt, critical-section-multi-core, check-asm" {{verbose}} + cargo build --target {{target}} -Zbuild-std=core --features "serde, defmt, critical-section-single-core, check-asm" {{verbose}} # Builds our workspace with various features build-tier2 target: From 52839db7ebdc7ac5a5c2194cb97d09cbd291f066 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sat, 18 Apr 2026 20:59:03 +0100 Subject: [PATCH 6/6] Need rust-src --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dcfd58dc..8551bb2e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -65,6 +65,7 @@ jobs: run: | rustup install stable rustup default stable + rustup component add rust-src - name: Build run: | just build-tier3 ${{ matrix.target }} @@ -90,6 +91,7 @@ jobs: run: | rustup install stable rustup default stable + rustup component add rust-src - name: Build run: | just build-tier3-no-atomics ${{ matrix.target }}