diff --git a/aarch32-cpu/src/generic_timer/el0.rs b/aarch32-cpu/src/generic_timer/el0.rs index 90dd61f..192c01b 100644 --- a/aarch32-cpu/src/generic_timer/el0.rs +++ b/aarch32-cpu/src/generic_timer/el0.rs @@ -1,5 +1,7 @@ //! Code and types for Generic Timer support at EL0 on Armv8-R. +use core::marker::PhantomData; + use crate::register; /// Represents our Generic Physical Timer when we are running at EL0. @@ -7,7 +9,12 @@ use crate::register; /// Note that for most of these APIs to work, EL0 needs to have been granted /// access using methods like /// [El1PhysicalTimer::el0_access_physical_counter](crate::generic_timer::El1PhysicalTimer::el0_access_physical_counter). -pub struct El0PhysicalTimer(); +/// +/// This type is not [Send] because it is a per-core type and should not be moved across +/// cores on an SMP system. +pub struct El0PhysicalTimer { + _phantom: PhantomData<*const u8>, +} impl El0PhysicalTimer { /// Create an EL0 Timer handle for the Physical Timer. @@ -17,11 +24,13 @@ impl El0PhysicalTimer { /// /// # Safety /// - /// Only create one of these at any given time, as they access shared - /// mutable state within the processor and do read-modify-writes on that - /// state. + /// Only create one Physical Timer handle (at any EL) at any given time, as + /// they access shared mutable state within the processor and do + /// read-modify-writes on that state. pub unsafe fn new() -> El0PhysicalTimer { - El0PhysicalTimer() + El0PhysicalTimer { + _phantom: PhantomData, + } } } @@ -80,17 +89,25 @@ impl super::GenericTimer for El0PhysicalTimer { /// Note that for most of these APIs to work, EL0 needs to have been granted /// access using methods like /// [El1VirtualTimer::el0_access_virtual_counter](crate::generic_timer::El1VirtualTimer::el0_access_virtual_counter). -pub struct El0VirtualTimer(); +/// +/// This type is not [Send] because it is a per-core type and should not be moved across +/// cores on an SMP system. +pub struct El0VirtualTimer { + _phantom: PhantomData<*const u8>, +} impl El0VirtualTimer { /// Create an EL0 Timer handle for the Virtual Timer. /// /// # Safety /// - /// Only create one of these at any given time, as they access shared - /// mutable state within the processor and do read-modify-writes on that state. + /// Only create one Virtual Timer handle (at any EL) at any given time, as + /// they access shared mutable state within the processor and do + /// read-modify-writes on that state. pub unsafe fn new() -> El0VirtualTimer { - El0VirtualTimer() + El0VirtualTimer { + _phantom: PhantomData, + } } } diff --git a/aarch32-cpu/src/generic_timer/el1.rs b/aarch32-cpu/src/generic_timer/el1.rs index 9af1d90..dde027f 100644 --- a/aarch32-cpu/src/generic_timer/el1.rs +++ b/aarch32-cpu/src/generic_timer/el1.rs @@ -5,6 +5,12 @@ use crate::register; use super::{El0PhysicalTimer, El0VirtualTimer, GenericTimer}; /// Represents our Physical Timer when we are running at EL1. +/// +/// This works exactly like [El0PhysicalTimer], but it gives you extra methods +/// for functionality that only processors running at EL1 can access. +/// +/// This type is not [Send] because it is a per-core type and should not be moved across +/// cores on an SMP system. pub struct El1PhysicalTimer(pub(crate) El0PhysicalTimer); impl El1PhysicalTimer { @@ -12,8 +18,9 @@ impl El1PhysicalTimer { /// /// # Safety /// - /// Only create one of these at any given time, as they access shared - /// mutable state within the processor and do read-modify-writes on that state. + /// Only create one Physical Timer handle (at any EL) at any given time, as + /// they access shared mutable state within the processor and do + /// read-modify-writes on that state. pub unsafe fn new() -> El1PhysicalTimer { unsafe { El1PhysicalTimer(El0PhysicalTimer::new()) } } @@ -80,6 +87,12 @@ impl GenericTimer for El1PhysicalTimer { } /// Represents our Virtual Timer when we are running at EL1. +/// +/// This works exactly like [El0VirtualTimer], but it gives you extra methods +/// for functionality that only processors running at EL1 can access. +/// +/// This type is not [Send] because it is a per-core type and should not be moved across +/// cores on an SMP system. pub struct El1VirtualTimer(El0VirtualTimer); impl El1VirtualTimer { @@ -87,8 +100,9 @@ impl El1VirtualTimer { /// /// # Safety /// - /// Only create one of these at any given time, as they access shared - /// mutable state within the processor and do read-modify-writes on that state. + /// Only create one Virtual Timer handle (at any EL) at any given time, as + /// they access shared mutable state within the processor and do + /// read-modify-writes on that state. pub unsafe fn new() -> El1VirtualTimer { unsafe { El1VirtualTimer(El0VirtualTimer::new()) } } diff --git a/aarch32-cpu/src/generic_timer/el2.rs b/aarch32-cpu/src/generic_timer/el2.rs index fd34c91..3b0aba6 100644 --- a/aarch32-cpu/src/generic_timer/el2.rs +++ b/aarch32-cpu/src/generic_timer/el2.rs @@ -1,10 +1,18 @@ //! Code and types for Generic Timer support at EL2 on Armv8-R. +use core::marker::PhantomData; + use crate::register; use super::{El1PhysicalTimer, El1VirtualTimer, GenericTimer}; /// Represents our Physical Timer when we are running at EL2. +/// +/// This works exactly like [El1PhysicalTimer], but it gives you extra methods +/// for functionality that only processors running at EL2 can access. +/// +/// This type is not [Send] because it is a per-core type and should not be moved across +/// cores on an SMP system. pub struct El2PhysicalTimer(El1PhysicalTimer); impl El2PhysicalTimer { @@ -12,8 +20,9 @@ impl El2PhysicalTimer { /// /// # Safety /// - /// Only create one of these at any given time, as they access shared - /// mutable state within the processor and do read-modify-writes on that state. + /// Only create one Physical Timer handle (at any EL) at any given time, as + /// they access shared mutable state within the processor and do + /// read-modify-writes on that state. pub unsafe fn new() -> El2PhysicalTimer { unsafe { El2PhysicalTimer(El1PhysicalTimer::new()) } } @@ -76,15 +85,22 @@ impl GenericTimer for El2PhysicalTimer { } /// Represents our Virtual Timer when we are running at EL1. +/// +/// This works exactly like [El1VirtualTimer], but it gives you extra methods +/// for functionality that only processors running at EL2 can access. +/// +/// This type is not [Send] because it is a per-core type and should not be moved +/// across cores on an SMP system. pub struct El2VirtualTimer(El1VirtualTimer); impl El2VirtualTimer { - /// Create an EL2 Generic Timer handle + /// Create an EL2 Virtual Timer handle /// /// # Safety /// - /// Only create one of these at any given time, as they access shared - /// mutable state within the processor and do read-modify-writes on that state. + /// Only create one Virtual Timer handle (at any EL) at any given time, as + /// they access shared mutable state within the processor and do + /// read-modify-writes on that state. pub unsafe fn new() -> El2VirtualTimer { unsafe { El2VirtualTimer(El1VirtualTimer::new()) } } @@ -146,8 +162,16 @@ impl GenericTimer for El2VirtualTimer { } } -/// Represents our Hypervisor-specific Physical Timer when we are running at EL1. -pub struct El2HypPhysicalTimer(); +/// Represents our Hypervisor-specific Physical Timer. +/// +/// This is designed for use by a hypervisor, whilst an EL1 application +/// concurrently uses the Physical Timer and/or the Virtual Timer. +/// +/// This type is not [Send] because it is a per-core type and should not be moved across +/// cores on an SMP system. +pub struct El2HypPhysicalTimer { + _phantom: PhantomData<*const u8>, +} impl El2HypPhysicalTimer { /// Create a Timer handle for the EL2-specific Hyp Physical Timer. @@ -155,9 +179,13 @@ impl El2HypPhysicalTimer { /// # Safety /// /// Only create one of these at any given time, as they access shared - /// mutable state within the processor and do read-modify-writes on that state. + /// mutable state within the processor and do read-modify-writes on that + /// state. This timer is distinct from the Physical Timer and the Virtual + /// Timer, and so can exist concurrently. pub unsafe fn new() -> El2HypPhysicalTimer { - El2HypPhysicalTimer() + El2HypPhysicalTimer { + _phantom: PhantomData, + } } } diff --git a/aarch32-cpu/src/pmsav7.rs b/aarch32-cpu/src/pmsav7.rs index 0db24a8..e6c8b8a 100644 --- a/aarch32-cpu/src/pmsav7.rs +++ b/aarch32-cpu/src/pmsav7.rs @@ -5,6 +5,8 @@ //! //! [armv7]: https://developer.arm.com/documentation/ddi0406/latest +use core::marker::PhantomData; + use crate::register; use arbitrary_int::{u2, u3}; @@ -23,7 +25,12 @@ pub enum Error { } /// Represents our PMSAv7 MPU -pub struct Mpu(); +/// +/// This type is not [Send] because it is a per-core type and should not be moved across +/// cores on an SMP system. +pub struct Mpu { + _phantom: PhantomData<*const u8>, +} impl Mpu { /// Create an MPU handle @@ -33,7 +40,9 @@ impl Mpu { /// Only create one of these at any given time, as they access shared /// mutable state within the processor and do read-modify-writes on that state. pub unsafe fn new() -> Mpu { - Mpu() + Mpu { + _phantom: PhantomData, + } } /// How many MPU instruction regions are there? diff --git a/aarch32-cpu/src/pmsav8.rs b/aarch32-cpu/src/pmsav8.rs index 5508fa8..47984fa 100644 --- a/aarch32-cpu/src/pmsav8.rs +++ b/aarch32-cpu/src/pmsav8.rs @@ -6,6 +6,8 @@ //! //! [armv8r]: https://developer.arm.com/documentation/ddi0568/latest/ +use core::marker::PhantomData; + use arbitrary_int::{u26, u3}; use crate::register; @@ -28,7 +30,12 @@ pub enum Error { } /// Represents our PMSAv8-32 EL1 MPU -pub struct El1Mpu(); +/// +/// This type is not [Send] because it is a per-core type and should not be moved across +/// cores on an SMP system. +pub struct El1Mpu { + _phantom: PhantomData<*const u8>, +} impl El1Mpu { /// Create an MPU handle @@ -38,7 +45,9 @@ impl El1Mpu { /// Only create one of these at any given time, as they access shared /// mutable state within the processor and do read-modify-writes on that state. pub unsafe fn new() -> El1Mpu { - El1Mpu() + El1Mpu { + _phantom: PhantomData, + } } /// How many MPU regions are there? @@ -199,7 +208,12 @@ impl El1Mpu { } /// Represents our PMSAv8-32 EL2 MPU -pub struct El2Mpu(); +/// +/// This type is not [Send] because it is a per-core type and should not be moved across +/// cores on an SMP system. +pub struct El2Mpu { + _phantom: PhantomData<*const u8>, +} impl El2Mpu { /// Create an EL2 MPU handle @@ -209,7 +223,9 @@ impl El2Mpu { /// Only create one of these at any given time, as they access shared /// mutable state within the processor and do read-modify-writes on that state. pub unsafe fn new() -> El2Mpu { - El2Mpu() + El2Mpu { + _phantom: PhantomData, + } } /// How many EL2 MPU regions are there? @@ -407,6 +423,7 @@ pub struct El1Region { // Creating a static Region is fine - the pointers within it // only go to the MPU and aren't accessed via Rust code +unsafe impl Send for El1Region {} unsafe impl Sync for El1Region {} /// Configuration for the PMSAv8-32 EL2 MPU @@ -454,6 +471,7 @@ pub struct El2Region { // Creating a static El2Region is fine - the pointers within it // only go to the MPU and aren't accessed via Rust code +unsafe impl Send for El2Region {} unsafe impl Sync for El2Region {} /// Describes the memory ordering and cacheability of a region