Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 26 additions & 9 deletions aarch32-cpu/src/generic_timer/el0.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
//! 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.
///
/// 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.
Expand All @@ -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,
}
}
}

Expand Down Expand Up @@ -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,
}
}
}

Expand Down
22 changes: 18 additions & 4 deletions aarch32-cpu/src/generic_timer/el1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,22 @@ 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 {
/// Create an EL1 Generic 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 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()) }
}
Expand Down Expand Up @@ -80,15 +87,22 @@ 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 {
/// Create an EL1 Generic 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() -> El1VirtualTimer {
unsafe { El1VirtualTimer(El0VirtualTimer::new()) }
}
Expand Down
46 changes: 37 additions & 9 deletions aarch32-cpu/src/generic_timer/el2.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
//! 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 {
/// Create an EL2 Physical 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 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()) }
}
Expand Down Expand Up @@ -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()) }
}
Expand Down Expand Up @@ -146,18 +162,30 @@ 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.
///
/// # 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,
}
}
}

Expand Down
13 changes: 11 additions & 2 deletions aarch32-cpu/src/pmsav7.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
//!
//! [armv7]: https://developer.arm.com/documentation/ddi0406/latest

use core::marker::PhantomData;

use crate::register;

use arbitrary_int::{u2, u3};
Expand All @@ -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
Expand All @@ -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?
Expand Down
26 changes: 22 additions & 4 deletions aarch32-cpu/src/pmsav8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
//!
//! [armv8r]: https://developer.arm.com/documentation/ddi0568/latest/

use core::marker::PhantomData;

use arbitrary_int::{u26, u3};

use crate::register;
Expand All @@ -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
Expand All @@ -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?
Expand Down Expand Up @@ -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
Expand All @@ -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?
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Loading