blob: 619f979064d4a0457ac0e006a16eb0c8fa7d255a [file] [log] [blame]
diff --git a/src/transport/pci/bus.rs b/src/transport/pci/bus.rs
index ac6e30da..0629b2cc 100644
--- a/src/transport/pci/bus.rs
+++ b/src/transport/pci/bus.rs
@@ -357,7 +357,19 @@ impl ConfigurationAccess for MmioCam {
// resulting pointer is within the MMIO range of the CAM.
unsafe {
// Right shift to convert from byte offset to word offset.
- (self.mmio_base.add((address >> 2) as usize)).write_volatile(data)
+ let ptr = self.mmio_base.add((address >> 2) as usize);
+ #[cfg(not(target_arch = "aarch64"))]
+ {
+ ptr.write_volatile(data)
+ }
+ #[cfg(target_arch = "aarch64")]
+ {
+ core::arch::asm!(
+ "str {value:w}, [{ptr}]",
+ value = in(reg) data,
+ ptr = in(reg) ptr,
+ )
+ }
}
}
diff --git a/src/volatile.rs b/src/volatile.rs
index 74f527b3..caa58e23 100644
--- a/src/volatile.rs
+++ b/src/volatile.rs
@@ -33,12 +33,14 @@ pub trait VolatileReadable<T> {
unsafe fn vread(self) -> T;
}
+#[cfg(not(target_arch = "aarch64"))]
impl<T: Copy> VolatileReadable<T> for *const ReadOnly<T> {
unsafe fn vread(self) -> T {
self.read_volatile().0
}
}
+#[cfg(not(target_arch = "aarch64"))]
impl<T: Copy> VolatileReadable<T> for *const Volatile<T> {
unsafe fn vread(self) -> T {
self.read_volatile().0
@@ -51,18 +53,135 @@ pub trait VolatileWritable<T> {
unsafe fn vwrite(self, value: T);
}
+#[cfg(not(target_arch = "aarch64"))]
impl<T: Copy> VolatileWritable<T> for *mut WriteOnly<T> {
unsafe fn vwrite(self, value: T) {
(self as *mut T).write_volatile(value)
}
}
+#[cfg(not(target_arch = "aarch64"))]
impl<T: Copy> VolatileWritable<T> for *mut Volatile<T> {
unsafe fn vwrite(self, value: T) {
(self as *mut T).write_volatile(value)
}
}
+#[cfg(target_arch = "aarch64")]
+mod aarch64_mmio {
+ use super::{ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly};
+ use crate::transport::DeviceStatus;
+ use core::arch::asm;
+
+ macro_rules! asm_mmio_write {
+ ($t:ty, $assembly:literal) => {
+ impl VolatileWritable<$t> for *mut WriteOnly<$t> {
+ unsafe fn vwrite(self, value: $t) {
+ asm!(
+ $assembly,
+ value = in(reg) value,
+ ptr = in(reg) (self as *mut $t),
+ );
+ }
+ }
+
+ impl VolatileWritable<$t> for *mut Volatile<$t> {
+ unsafe fn vwrite(self, value: $t) {
+ asm!(
+ $assembly,
+ value = in(reg) value,
+ ptr = in(reg) (self as *mut $t),
+ );
+ }
+ }
+ };
+ }
+
+ macro_rules! asm_mmio_read {
+ ($t:ty, $assembly:literal) => {
+ impl VolatileReadable<$t> for *const ReadOnly<$t> {
+ unsafe fn vread(self) -> $t {
+ let value;
+ asm!(
+ $assembly,
+ value = out(reg) value,
+ ptr = in(reg) (self as *const $t),
+ );
+ value
+ }
+ }
+
+ impl VolatileReadable<$t> for *const Volatile<$t> {
+ unsafe fn vread(self) -> $t {
+ let value;
+ asm!(
+ $assembly,
+ value = out(reg) value,
+ ptr = in(reg) (self as *const $t),
+ );
+ value
+ }
+ }
+ };
+ }
+
+ asm_mmio_write!(u8, "strb {value:w}, [{ptr}]");
+ asm_mmio_write!(u16, "strh {value:w}, [{ptr}]");
+ asm_mmio_write!(u32, "str {value:w}, [{ptr}]");
+ asm_mmio_write!(u64, "str {value:x}, [{ptr}]");
+
+ impl VolatileWritable<DeviceStatus> for *mut WriteOnly<DeviceStatus> {
+ unsafe fn vwrite(self, value: DeviceStatus) {
+ let value: u32 = value.bits();
+ asm!(
+ "str {value:w}, [{ptr}]",
+ value = in(reg) value,
+ ptr = in(reg) (self as *mut u32),
+ );
+ }
+ }
+
+ impl VolatileWritable<DeviceStatus> for *mut Volatile<DeviceStatus> {
+ unsafe fn vwrite(self, value: DeviceStatus) {
+ let value: u32 = value.bits();
+ asm!(
+ "str {value:w}, [{ptr}]",
+ value = in(reg) value,
+ ptr = in(reg) (self as *mut u32),
+ );
+ }
+ }
+
+ asm_mmio_read!(u8, "ldrb {value:w}, [{ptr}]");
+ asm_mmio_read!(u16, "ldrh {value:w}, [{ptr}]");
+ asm_mmio_read!(u32, "ldr {value:w}, [{ptr}]");
+ asm_mmio_read!(u64, "ldr {value:x}, [{ptr}]");
+
+ impl VolatileReadable<DeviceStatus> for *const ReadOnly<DeviceStatus> {
+ unsafe fn vread(self) -> DeviceStatus {
+ let value: u32;
+ asm!(
+ "ldr {value:w}, [{ptr}]",
+ value = out(reg) value,
+ ptr = in(reg) (self as *const u32),
+ );
+ DeviceStatus::from_bits_retain(value)
+ }
+ }
+
+ impl VolatileReadable<DeviceStatus> for *const Volatile<DeviceStatus> {
+ unsafe fn vread(self) -> DeviceStatus {
+ let value: u32;
+ asm!(
+ "ldr {value:w}, [{ptr}]",
+ value = out(reg) value,
+ ptr = in(reg) (self as *const u32),
+ );
+ DeviceStatus::from_bits_retain(value)
+ }
+ }
+}
+
/// Performs a volatile read from the given field of pointer to a struct representing an MMIO region.
///
/// # Usage