diff --git a/cortex-ar/CHANGELOG.md b/cortex-ar/CHANGELOG.md index 617bca0..32489a1 100644 --- a/cortex-ar/CHANGELOG.md +++ b/cortex-ar/CHANGELOG.md @@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - `dmb` data memory barrier in ASM module. +- API for inner cache maintenance as part of the new `cache` module. This includes functions to + completely clean, invalidate or clean & invalidate the L1 data cache or perform data cache + maintenance by MVA (specific address). ## [v0.2.0] diff --git a/cortex-ar/src/cache.rs b/cortex-ar/src/cache.rs new file mode 100644 index 0000000..0dfec35 --- /dev/null +++ b/cortex-ar/src/cache.rs @@ -0,0 +1,108 @@ +use arbitrary_int::u3; + +use crate::register::{Dccimvac, Dccisw, Dccmvac, Dccsw, Dcimvac, Dcisw, SysRegWrite}; + +/// Invalidate the full L1 data cache. +/// +/// ## Generics +/// +/// - A: log2(ASSOCIATIVITY) rounded up to the next integer if necessary. For example, a 4-way +/// associative cache will have a value of 2 and a 8-way associative cache will have a value of +/// 3. +/// - N: log2(LINE LENGTH). For example, a 32-byte line length (4 words) will have a value of +/// 5. +/// - S: log2(NUM OF SETS). For systems with a fixed cache size, the number of sets can be +/// calculated using `CACHE SIZE / (LINE LENGTH * ASSOCIATIVITY)`. +/// For example, a 4-way associative 32kB L1 cache with a 32-byte line length (4 words) will +/// have 32768 / (32 * 4) == 256 sets and S will have a value of 8. +#[inline] +pub fn invalidate_l1_data_cache() { + let ways = 1 << A; + let sets = 1 << S; + + for set in 0..sets { + for way in 0..ways { + unsafe { Dcisw::write(Dcisw::new::(way, set, u3::new(0))) }; + } + } +} + +/// Clean the full L1 data cache. +/// +/// ## Generics +/// +/// - A: log2(ASSOCIATIVITY) rounded up to the next integer if necessary. For example, a 4-way +/// associative cache will have a value of 2 and a 8-way associative cache will have a value of +/// 3. +/// - N: log2(LINE LENGTH). For example, a 32-byte line length (4 words) will have a value of +/// 5. +/// - S: log2(NUM OF SETS). For systems with a fixed cache size, the number of sets can be +/// calculated using `CACHE SIZE / (LINE LENGTH * ASSOCIATIVITY)`. +/// For example, a 4-way associative 32kB L1 cache with a 32-byte line length (4 words) will +/// have 32768 / (32 * 4) == 256 sets and S will have a value of 8. +#[inline] +pub fn clean_l1_data_cache() { + let ways = 1 << A; + let sets = 1 << S; + + for set in 0..sets { + for way in 0..ways { + unsafe { Dccsw::write(Dccsw::new::(way, set, u3::new(0))) }; + } + } +} + +/// Clean and Invalidate the full L1 data cache. +/// +/// ## Generics +/// +/// - A: log2(ASSOCIATIVITY) rounded up to the next integer if necessary. For example, a 4-way +/// associative cache will have a value of 2 and a 8-way associative cache will have a value of +/// 3. +/// - N: log2(LINE LENGTH). For example, a 32-byte line length (4 words) will have a value of +/// 5. +/// - S: log2(NUM OF SETS). For systems with a fixed cache size, the number of sets can be +/// calculated using `CACHE SIZE / (LINE LENGTH * ASSOCIATIVITY)`. +/// For example, a 4-way associative 32kB L1 cache with a 32-byte line length (4 words) will +/// have 32768 / (32 * 4) == 256 sets and S will have a value of 8. +#[inline] +pub fn clean_and_invalidate_l1_data_cache() { + let ways = 1 << A; + let sets = 1 << S; + + for set in 0..sets { + for way in 0..ways { + unsafe { Dccisw::write(Dccisw::new::(way, set, u3::new(0))) }; + } + } +} + +/// Invalidates a data cache line to the point of coherence. +/// +/// See p.1735 of the ARMv7-A Architecture Reference Manual for more information. +#[inline] +pub fn invalidate_data_cache_line_to_poc(addr: u32) { + unsafe { + Dcimvac::write_raw(addr); + } +} + +/// Cleans a data cache line to the point of coherence. +/// +/// See p.1735 of the ARMv7-A Architecture Reference Manual for more information. +#[inline] +pub fn clean_data_cache_line_to_poc(addr: u32) { + unsafe { + Dccmvac::write_raw(addr); + } +} + +/// Cleans and invalidates a data cache line to the point of coherence. +/// +/// See p.1735 of the ARMv7-A Architecture Reference Manual for more information. +#[inline] +pub fn clean_and_invalidate_data_cache_line_to_poc(addr: u32) { + unsafe { + Dccimvac::write_raw(addr); + } +} diff --git a/cortex-ar/src/lib.rs b/cortex-ar/src/lib.rs index 283fde1..22d76d1 100644 --- a/cortex-ar/src/lib.rs +++ b/cortex-ar/src/lib.rs @@ -7,6 +7,7 @@ mod critical_section; #[cfg(target_arch = "arm")] pub mod asm; +pub mod cache; pub mod interrupt; pub mod mmu; pub mod register; diff --git a/cortex-ar/src/register/bpiall.rs b/cortex-ar/src/register/bpiall.rs new file mode 100644 index 0000000..0a26505 --- /dev/null +++ b/cortex-ar/src/register/bpiall.rs @@ -0,0 +1,23 @@ +//! BPIALL: Invalidate all entries from branch predictors + +use crate::register::SysReg; + +/// BPIALL: Invalidate all entries from branch predictors +pub struct BpIAll; + +impl SysReg for BpIAll { + const CP: u32 = 15; + const CRN: u32 = 7; + const OP1: u32 = 0; + const CRM: u32 = 5; + const OP2: u32 = 6; +} + +impl crate::register::SysRegWrite for BpIAll {} + +impl BpIAll { + #[inline] + pub fn write() { + unsafe { ::write_raw(0) } + } +} diff --git a/cortex-ar/src/register/ccsidr.rs b/cortex-ar/src/register/ccsidr.rs index 007c89f..289a977 100644 --- a/cortex-ar/src/register/ccsidr.rs +++ b/cortex-ar/src/register/ccsidr.rs @@ -1,9 +1,28 @@ //! Code for managing CCSIDR (*Current Cache Size ID Register*) use crate::register::{SysReg, SysRegRead}; +use arbitrary_int::{u10, u15, u3}; /// CCSIDR (*Current Cache Size ID Register*) -pub struct Ccsidr(pub u32); +#[bitbybit::bitfield(u32)] +#[derive(Debug)] +pub struct Ccsidr { + #[bit(31, rw)] + write_through: bool, + #[bit(30, rw)] + write_back: bool, + #[bit(29, rw)] + read_alloc: bool, + #[bit(28, rw)] + write_alloc: bool, + #[bits(13..=27, rw)] + num_sets: u15, + #[bits(3..=12, rw)] + associativity: u10, + #[bits(0..=2, rw)] + line_size: u3, +} + impl SysReg for Ccsidr { const CP: u32 = 15; const CRN: u32 = 0; @@ -11,11 +30,13 @@ impl SysReg for Ccsidr { const CRM: u32 = 0; const OP2: u32 = 0; } + impl crate::register::SysRegRead for Ccsidr {} + impl Ccsidr { #[inline] /// Reads CCSIDR (*Current Cache Size ID Register*) pub fn read() -> Ccsidr { - unsafe { Self(::read_raw()) } + unsafe { Self::new_with_raw_value(::read_raw()) } } } diff --git a/cortex-ar/src/register/csselr.rs b/cortex-ar/src/register/csselr.rs index 4dbcdaf..794227d 100644 --- a/cortex-ar/src/register/csselr.rs +++ b/cortex-ar/src/register/csselr.rs @@ -1,9 +1,26 @@ //! Code for managing CSSELR (*Cache Size Selection Register*) +use arbitrary_int::u3; use crate::register::{SysReg, SysRegRead, SysRegWrite}; +#[bitbybit::bitenum(u1, exhaustive = true)] +#[derive(Debug, PartialEq, Eq)] +pub enum CacheType { + DataOrUnified = 0, + Instruction = 1, +} + /// CSSELR (*Cache Size Selection Register*) -pub struct Csselr(pub u32); +#[bitbybit::bitfield(u32)] +#[derive(Debug, PartialEq, Eq)] +pub struct Csselr { + /// 0 for L1 cache, 1 for L2, etc. + #[bits(1..=3, rw)] + level: u3, + #[bit(0, rw)] + cache_type: CacheType, +} + impl SysReg for Csselr { const CP: u32 = 15; const CRN: u32 = 0; @@ -16,7 +33,7 @@ impl Csselr { #[inline] /// Reads CSSELR (*Cache Size Selection Register*) pub fn read() -> Csselr { - unsafe { Self(::read_raw()) } + unsafe { Self::new_with_raw_value(::read_raw()) } } } impl crate::register::SysRegWrite for Csselr {} @@ -29,7 +46,7 @@ impl Csselr { /// Ensure that this value is appropriate for this register pub unsafe fn write(value: Self) { unsafe { - ::write_raw(value.0); + ::write_raw(value.raw_value()); } } } diff --git a/cortex-ar/src/register/dc_sw_ops.rs b/cortex-ar/src/register/dc_sw_ops.rs new file mode 100644 index 0000000..951061e --- /dev/null +++ b/cortex-ar/src/register/dc_sw_ops.rs @@ -0,0 +1,38 @@ +use arbitrary_int::u3; + +/// Create input data register value for cache maintenance operations by set and way. +/// +/// ## Generics +/// +/// - A: log2(ASSOCIATIVITY) rounded up to the next integer if necessary. For example, a 4-way +/// associative cache will have a value of 2 and a 8-way associative cache will have a value of +/// 4. +/// - N: log2(LINE LENGTH). For example, a 32-byte line length (4 words) will have a value of +/// 5. +#[inline] +pub const fn new(way: u8, set: u16, level: u3) -> u32 { + if A == 0 { + ((set as u32) << N) | level.value() as u32 + } else { + ((way as u32) << (32 - A)) | ((set as u32) << N) | level.value() as u32 + } +} + +/// Create input data register value for cache maintenance operations by set and way. +/// Returns [None] on invalid input. +/// +/// # Arguments +/// +/// - a: log2(ASSOCIATIVITY) rounded up to the next integer if necessary. For example, a 4-way +/// associative cache will have a value of 2 and a 8-way associative cache will have a value of +/// 4. +/// - n: log2(LINE LENGTH). For example, a 32-byte line length (4 words) will have a value of +/// 5. +#[inline] +pub const fn new_with_offsets(a: usize, way: u8, n: usize, set: u16, level: u3) -> u32 { + if a == 0 { + ((set as u32) << n) | level.value() as u32 + } else { + ((way as u32) << (32 - a)) | ((set as u32) << n) | level.value() as u32 + } +} diff --git a/cortex-ar/src/register/dccimvac.rs b/cortex-ar/src/register/dccimvac.rs new file mode 100644 index 0000000..404f055 --- /dev/null +++ b/cortex-ar/src/register/dccimvac.rs @@ -0,0 +1,36 @@ +//! DCCIMVAC (*Clean And Invalidate Data Cache Or Unified Cache Line by MVA to Point of Coherence.*) +use crate::register::{SysReg, SysRegWrite}; + +pub struct Dccimvac(pub u32); + +impl Dccimvac { + #[inline] + pub const fn new(addr: u32) -> Self { + Self(addr) + } +} + +impl SysReg for Dccimvac { + const CP: u32 = 15; + const CRN: u32 = 7; + const OP1: u32 = 0; + const CRM: u32 = 14; + const OP2: u32 = 1; +} + +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.*) + /// + /// # Safety + /// + /// Ensure that this value is appropriate for this register. Generally, the address passed + /// to the write call should be aligned to the cache line size. + pub unsafe fn write(value: Self) { + unsafe { + ::write_raw(value.0); + } + } +} diff --git a/cortex-ar/src/register/dccisw.rs b/cortex-ar/src/register/dccisw.rs new file mode 100644 index 0000000..3787f46 --- /dev/null +++ b/cortex-ar/src/register/dccisw.rs @@ -0,0 +1,61 @@ +//! DCCISW (*Clean and Invalidate Data or Unified cache line by Set/Way.*) + +use arbitrary_int::u3; + +use crate::register::{SysReg, SysRegWrite}; + +pub struct Dccisw(pub u32); + +impl Dccisw { + /// Create DCCISW value for cache cleaning and invalidation by set and way. + /// + /// ## Generics + /// + /// - A: log2(ASSOCIATIVITY) rounded up to the next integer if necessary. For example, a 4-way + /// associative cache will have a value of 2 and a 8-way associative cache will have a value of + /// 3. + /// - N: log2(LINE LENGTH). For example, a 32-byte line length (4 words) will have a value of + /// 5. + #[inline] + pub const fn new(way: u8, set: u16, level: u3) -> Self { + Self(super::dc_sw_ops::new::(way, set, level)) + } + + /// Create DCCISW value for cache cleaning and invalidation by set and way. + /// Returns [None] on invalid input. + /// + /// # Arguments + /// + /// - a: log2(ASSOCIATIVITY) rounded up to the next integer if necessary. For example, a 4-way + /// associative cache will have a value of 2 and a 8-way associative cache will have a value of + /// 3. + /// - n: log2(LINE LENGTH). For example, a 32-byte line length (4 words) will have a value of + /// 5. + #[inline] + pub const fn new_with_offsets(a: usize, way: u8, n: usize, set: u16, level: u3) -> Self { + Self(super::dc_sw_ops::new_with_offsets(a, way, n, set, level)) + } +} +impl SysReg for Dccisw { + const CP: u32 = 15; + const CRN: u32 = 7; + const OP1: u32 = 0; + const CRM: u32 = 14; + const OP2: u32 = 2; +} + +impl crate::register::SysRegWrite for Dccisw {} + +impl Dccisw { + #[inline] + /// Writes DCCISW (*Clean and Invalidate data or unified cache line by set/way.*) + /// + /// # Safety + /// + /// Ensure that this value is appropriate for this register + pub unsafe fn write(value: Self) { + unsafe { + ::write_raw(value.0); + } + } +} diff --git a/cortex-ar/src/register/dccmvac.rs b/cortex-ar/src/register/dccmvac.rs new file mode 100644 index 0000000..8090830 --- /dev/null +++ b/cortex-ar/src/register/dccmvac.rs @@ -0,0 +1,36 @@ +//! DCCMVAC (*Clean Data Cache Or Unified Cache Line by MVA to Point of Coherence.*) +use crate::register::{SysReg, SysRegWrite}; + +pub struct Dccmvac(pub u32); + +impl Dccmvac { + #[inline] + pub const fn new(addr: u32) -> Self { + Self(addr) + } +} + +impl SysReg for Dccmvac { + const CP: u32 = 15; + const CRN: u32 = 7; + const OP1: u32 = 0; + const CRM: u32 = 10; + const OP2: u32 = 1; +} + +impl crate::register::SysRegWrite for Dccmvac {} + +impl Dccmvac { + #[inline] + /// Writes DCCMVAC (*Clean Data Cache Or Unified Cache Line by MVA to Point of Coherence.*) + /// + /// # Safety + /// + /// Ensure that this value is appropriate for this register. Generally, the address passed + /// to the write call should be aligned to the cache line size. + pub unsafe fn write(value: Self) { + unsafe { + ::write_raw(value.0); + } + } +} diff --git a/cortex-ar/src/register/dccmvau.rs b/cortex-ar/src/register/dccmvau.rs new file mode 100644 index 0000000..0132afa --- /dev/null +++ b/cortex-ar/src/register/dccmvau.rs @@ -0,0 +1,35 @@ +//! DCCMVAU (*Clean Data Cache Or Unified Cache Line by MVA to Point of Unification.*) +use crate::register::{SysReg, SysRegWrite}; + +pub struct Dccmvau(pub u32); + +impl Dccmvau { + #[inline] + pub const fn new(addr: u32) -> Self { + Self(addr) + } +} +impl SysReg for Dccmvau { + const CP: u32 = 15; + const CRN: u32 = 7; + const OP1: u32 = 0; + const CRM: u32 = 11; + const OP2: u32 = 1; +} + +impl crate::register::SysRegWrite for Dccmvau {} + +impl Dccmvau { + #[inline] + /// Writes DCCMVAU (*Clean Data Cache Or Unified Cache Line by MVA to Point of Unification.*) + /// + /// # Safety + /// + /// Ensure that this value is appropriate for this register. Generally, the address passed + /// to the write call should be aligned to the cache line size. + pub unsafe fn write(value: Self) { + unsafe { + ::write_raw(value.0); + } + } +} diff --git a/cortex-ar/src/register/dccsw.rs b/cortex-ar/src/register/dccsw.rs new file mode 100644 index 0000000..1215c2e --- /dev/null +++ b/cortex-ar/src/register/dccsw.rs @@ -0,0 +1,61 @@ +//! DCCSW (*Clean Data or Unified Cache line by Set/Way.*) + +use arbitrary_int::u3; + +use crate::register::{SysReg, SysRegWrite}; + +pub struct Dccsw(pub u32); + +impl Dccsw { + /// Create DCCSW value for cache cleaning by set and way. + /// + /// ## Generics + /// + /// - A: log2(ASSOCIATIVITY) rounded up to the next integer if necessary. For example, a 4-way + /// associative cache will have a value of 2 and a 8-way associative cache will have a value of + /// 3. + /// - N: log2(LINE LENGTH). For example, a 32-byte line length (4 words) will have a value of + /// 5. + #[inline] + pub const fn new(way: u8, set: u16, level: u3) -> Self { + Self(super::dc_sw_ops::new::(way, set, level)) + } + + /// Create DCCSW value for cache cleaning by set and way. + /// Returns [None] on invalid input. + /// + /// # Arguments + /// + /// - a: log2(ASSOCIATIVITY) rounded up to the next integer if necessary. For example, a 4-way + /// associative cache will have a value of 2 and a 8-way associative cache will have a value of + /// 3. + /// - n: log2(LINE LENGTH). For example, a 32-byte line length (4 words) will have a value of + /// 5. + #[inline] + pub const fn new_with_offsets(a: usize, way: u8, n: usize, set: u16, level: u3) -> Self { + Self(super::dc_sw_ops::new_with_offsets(a, way, n, set, level)) + } +} +impl SysReg for Dccsw { + const CP: u32 = 15; + const CRN: u32 = 7; + const OP1: u32 = 0; + const CRM: u32 = 10; + const OP2: u32 = 2; +} + +impl crate::register::SysRegWrite for Dccsw {} + +impl Dccsw { + #[inline] + /// Writes DCCSW (*Clean Data or Unified Cache line by Set/Way.*) + /// + /// # Safety + /// + /// Ensure that this value is appropriate for this register + pub unsafe fn write(value: Self) { + unsafe { + ::write_raw(value.0); + } + } +} diff --git a/cortex-ar/src/register/dcimvac.rs b/cortex-ar/src/register/dcimvac.rs new file mode 100644 index 0000000..22f50f3 --- /dev/null +++ b/cortex-ar/src/register/dcimvac.rs @@ -0,0 +1,36 @@ +//! DCIMVAC (*Invalidate Data Cache Or Unified Cache Line by MVA to Point of Coherence.*) +use crate::register::{SysReg, SysRegWrite}; + +pub struct Dcimvac(pub u32); + +impl Dcimvac { + #[inline] + pub const fn new(addr: u32) -> Self { + Self(addr) + } +} + +impl SysReg for Dcimvac { + const CP: u32 = 15; + const CRN: u32 = 7; + const OP1: u32 = 0; + const CRM: u32 = 6; + const OP2: u32 = 1; +} + +impl crate::register::SysRegWrite for Dcimvac {} + +impl Dcimvac { + #[inline] + /// Writes DCIMVAC (*Invalidate Data Cache Or Unified Cache Line by MVA to Point of Coherence.*) + /// + /// # Safety + /// + /// Ensure that this value is appropriate for this register. Generally, the address passed + /// to the write call should be aligned to the cache line size. + pub unsafe fn write(value: Self) { + unsafe { + ::write_raw(value.0); + } + } +} diff --git a/cortex-ar/src/register/dcisw.rs b/cortex-ar/src/register/dcisw.rs new file mode 100644 index 0000000..2c2fe38 --- /dev/null +++ b/cortex-ar/src/register/dcisw.rs @@ -0,0 +1,61 @@ +//! DCISW (*Invalidate Data or Unified Cache line by Set/Way.*) + +use arbitrary_int::u3; + +use crate::register::{SysReg, SysRegWrite}; + +pub struct Dcisw(pub u32); + +impl Dcisw { + /// Create DCISW value for cache invalidation by set and way. + /// + /// ## Generics + /// + /// - A: log2(ASSOCIATIVITY) rounded up to the next integer if necessary. For example, a 4-way + /// associative cache will have a value of 2 and a 8-way associative cache will have a value of + /// 3. + /// - N: log2(LINE LENGTH). For example, a 32-byte line length (4 words) will have a value of + /// 5. + #[inline] + pub const fn new(way: u8, set: u16, level: u3) -> Self { + Self(super::dc_sw_ops::new::(way, set, level)) + } + + /// Create DCISW value for cache invalidation by set and way. + /// Returns [None] on invalid input. + /// + /// # Arguments + /// + /// - a: log2(ASSOCIATIVITY) rounded up to the next integer if necessary. For example, a 4-way + /// associative cache will have a value of 2 and a 8-way associative cache will have a value of + /// 3. + /// - n: log2(LINE LENGTH). For example, a 32-byte line length (4 words) will have a value of + /// 5. + #[inline] + pub const fn new_with_offsets(a: usize, way: u8, n: usize, set: u16, level: u3) -> Self { + Self(super::dc_sw_ops::new_with_offsets(a, way, n, set, level)) + } +} +impl SysReg for Dcisw { + const CP: u32 = 15; + const CRN: u32 = 7; + const OP1: u32 = 0; + const CRM: u32 = 6; + const OP2: u32 = 2; +} + +impl crate::register::SysRegWrite for Dcisw {} + +impl Dcisw { + #[inline] + /// Writes DCSW (*Invalidate Data or Unified Cache line by Set/Way.*) + /// + /// # Safety + /// + /// Ensure that this value is appropriate for this register + pub unsafe fn write(value: Self) { + unsafe { + ::write_raw(value.0); + } + } +} diff --git a/cortex-ar/src/register/mod.rs b/cortex-ar/src/register/mod.rs index 96b0380..04be4c2 100644 --- a/cortex-ar/src/register/mod.rs +++ b/cortex-ar/src/register/mod.rs @@ -7,6 +7,7 @@ pub mod aidr; pub mod aifsr; pub mod amair0; pub mod amair1; +pub mod bpiall; pub mod ccsidr; pub mod clidr; pub mod contextidr; @@ -14,6 +15,14 @@ pub mod cpacr; pub mod cpsr; pub mod csselr; pub mod ctr; +pub mod dc_sw_ops; +pub mod dccimvac; +pub mod dccisw; +pub mod dccmvac; +pub mod dccmvau; +pub mod dccsw; +pub mod dcimvac; +pub mod dcisw; pub mod dfar; pub mod dfsr; pub mod dlr; @@ -80,6 +89,7 @@ pub mod rgnr; pub mod rvbar; pub mod sctlr; pub mod tcmtr; +pub mod tlbiall; pub mod tlbtr; pub mod tpidrprw; pub mod tpidruro; @@ -95,6 +105,7 @@ pub use aidr::Aidr; pub use aifsr::Aifsr; pub use amair0::Amair0; pub use amair1::Amair1; +pub use bpiall::BpIAll; pub use ccsidr::Ccsidr; pub use clidr::Clidr; pub use contextidr::Contextidr; @@ -102,6 +113,13 @@ pub use cpacr::Cpacr; pub use cpsr::Cpsr; pub use csselr::Csselr; pub use ctr::Ctr; +pub use dccimvac::Dccimvac; +pub use dccisw::Dccisw; +pub use dccmvac::Dccmvac; +pub use dccmvau::Dccmvau; +pub use dccsw::Dccsw; +pub use dcimvac::Dcimvac; +pub use dcisw::Dcisw; pub use dfar::Dfar; pub use dfsr::Dfsr; pub use dlr::Dlr; @@ -167,6 +185,7 @@ pub use rgnr::Rgnr; pub use rvbar::Rvbar; pub use sctlr::Sctlr; pub use tcmtr::Tcmtr; +pub use tlbiall::TlbIAll; pub use tlbtr::Tlbtr; pub use tpidrprw::Tpidrprw; pub use tpidruro::Tpidruro; diff --git a/cortex-ar/src/register/tlbiall.rs b/cortex-ar/src/register/tlbiall.rs new file mode 100644 index 0000000..0a59256 --- /dev/null +++ b/cortex-ar/src/register/tlbiall.rs @@ -0,0 +1,23 @@ +//! TLBIALL (*TLB Invalidate All Register*) + +use crate::register::SysReg; + +/// TLBIALL (*TLB Invalidate All Register*) +pub struct TlbIAll; + +impl SysReg for TlbIAll { + const CP: u32 = 15; + const CRN: u32 = 8; + const OP1: u32 = 0; + const CRM: u32 = 7; + const OP2: u32 = 0; +} + +impl crate::register::SysRegWrite for TlbIAll {} + +impl TlbIAll { + #[inline] + pub fn write() { + unsafe { ::write_raw(0) } + } +}