• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff --git a/src/transport/pci/bus.rs b/src/transport/pci/bus.rs
2index ac6e30da..0629b2cc 100644
3--- a/src/transport/pci/bus.rs
4+++ b/src/transport/pci/bus.rs
5@@ -357,7 +357,19 @@ impl ConfigurationAccess for MmioCam {
6         // resulting pointer is within the MMIO range of the CAM.
7         unsafe {
8             // Right shift to convert from byte offset to word offset.
9-            (self.mmio_base.add((address >> 2) as usize)).write_volatile(data)
10+            let ptr = self.mmio_base.add((address >> 2) as usize);
11+            #[cfg(not(target_arch = "aarch64"))]
12+            {
13+                ptr.write_volatile(data)
14+            }
15+            #[cfg(target_arch = "aarch64")]
16+            {
17+                core::arch::asm!(
18+                    "str {value:w}, [{ptr}]",
19+                    value = in(reg) data,
20+                    ptr = in(reg) ptr,
21+                )
22+            }
23         }
24     }
25
26diff --git a/src/volatile.rs b/src/volatile.rs
27index 74f527b3..caa58e23 100644
28--- a/src/volatile.rs
29+++ b/src/volatile.rs
30@@ -33,12 +33,14 @@ pub trait VolatileReadable<T> {
31     unsafe fn vread(self) -> T;
32 }
33
34+#[cfg(not(target_arch = "aarch64"))]
35 impl<T: Copy> VolatileReadable<T> for *const ReadOnly<T> {
36     unsafe fn vread(self) -> T {
37         self.read_volatile().0
38     }
39 }
40
41+#[cfg(not(target_arch = "aarch64"))]
42 impl<T: Copy> VolatileReadable<T> for *const Volatile<T> {
43     unsafe fn vread(self) -> T {
44         self.read_volatile().0
45@@ -51,18 +53,135 @@ pub trait VolatileWritable<T> {
46     unsafe fn vwrite(self, value: T);
47 }
48
49+#[cfg(not(target_arch = "aarch64"))]
50 impl<T: Copy> VolatileWritable<T> for *mut WriteOnly<T> {
51     unsafe fn vwrite(self, value: T) {
52         (self as *mut T).write_volatile(value)
53     }
54 }
55
56+#[cfg(not(target_arch = "aarch64"))]
57 impl<T: Copy> VolatileWritable<T> for *mut Volatile<T> {
58     unsafe fn vwrite(self, value: T) {
59         (self as *mut T).write_volatile(value)
60     }
61 }
62
63+#[cfg(target_arch = "aarch64")]
64+mod aarch64_mmio {
65+    use super::{ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly};
66+    use crate::transport::DeviceStatus;
67+    use core::arch::asm;
68+
69+    macro_rules! asm_mmio_write {
70+        ($t:ty, $assembly:literal) => {
71+            impl VolatileWritable<$t> for *mut WriteOnly<$t> {
72+                unsafe fn vwrite(self, value: $t) {
73+                    asm!(
74+                        $assembly,
75+                        value = in(reg) value,
76+                        ptr = in(reg) (self as *mut $t),
77+                    );
78+                }
79+            }
80+
81+            impl VolatileWritable<$t> for *mut Volatile<$t> {
82+                unsafe fn vwrite(self, value: $t) {
83+                    asm!(
84+                        $assembly,
85+                        value = in(reg) value,
86+                        ptr = in(reg) (self as *mut $t),
87+                    );
88+                }
89+            }
90+        };
91+    }
92+
93+    macro_rules! asm_mmio_read {
94+        ($t:ty, $assembly:literal) => {
95+            impl VolatileReadable<$t> for *const ReadOnly<$t> {
96+                unsafe fn vread(self) -> $t {
97+                    let value;
98+                    asm!(
99+                        $assembly,
100+                        value = out(reg) value,
101+                        ptr = in(reg) (self as *const $t),
102+                    );
103+                    value
104+                }
105+            }
106+
107+            impl VolatileReadable<$t> for *const Volatile<$t> {
108+                unsafe fn vread(self) -> $t {
109+                    let value;
110+                    asm!(
111+                        $assembly,
112+                        value = out(reg) value,
113+                        ptr = in(reg) (self as *const $t),
114+                    );
115+                    value
116+                }
117+            }
118+        };
119+    }
120+
121+    asm_mmio_write!(u8, "strb {value:w}, [{ptr}]");
122+    asm_mmio_write!(u16, "strh {value:w}, [{ptr}]");
123+    asm_mmio_write!(u32, "str {value:w}, [{ptr}]");
124+    asm_mmio_write!(u64, "str {value:x}, [{ptr}]");
125+
126+    impl VolatileWritable<DeviceStatus> for *mut WriteOnly<DeviceStatus> {
127+        unsafe fn vwrite(self, value: DeviceStatus) {
128+            let value: u32 = value.bits();
129+            asm!(
130+                "str {value:w}, [{ptr}]",
131+                value = in(reg) value,
132+                ptr = in(reg) (self as *mut u32),
133+            );
134+        }
135+    }
136+
137+    impl VolatileWritable<DeviceStatus> for *mut Volatile<DeviceStatus> {
138+        unsafe fn vwrite(self, value: DeviceStatus) {
139+            let value: u32 = value.bits();
140+            asm!(
141+                "str {value:w}, [{ptr}]",
142+                value = in(reg) value,
143+                ptr = in(reg) (self as *mut u32),
144+            );
145+        }
146+    }
147+
148+    asm_mmio_read!(u8, "ldrb {value:w}, [{ptr}]");
149+    asm_mmio_read!(u16, "ldrh {value:w}, [{ptr}]");
150+    asm_mmio_read!(u32, "ldr {value:w}, [{ptr}]");
151+    asm_mmio_read!(u64, "ldr {value:x}, [{ptr}]");
152+
153+    impl VolatileReadable<DeviceStatus> for *const ReadOnly<DeviceStatus> {
154+        unsafe fn vread(self) -> DeviceStatus {
155+            let value: u32;
156+            asm!(
157+                "ldr {value:w}, [{ptr}]",
158+                value = out(reg) value,
159+                ptr = in(reg) (self as *const u32),
160+            );
161+            DeviceStatus::from_bits_retain(value)
162+        }
163+    }
164+
165+    impl VolatileReadable<DeviceStatus> for *const Volatile<DeviceStatus> {
166+        unsafe fn vread(self) -> DeviceStatus {
167+            let value: u32;
168+            asm!(
169+                "ldr {value:w}, [{ptr}]",
170+                value = out(reg) value,
171+                ptr = in(reg) (self as *const u32),
172+            );
173+            DeviceStatus::from_bits_retain(value)
174+        }
175+    }
176+}
177+
178 /// Performs a volatile read from the given field of pointer to a struct representing an MMIO region.
179 ///
180 /// # Usage
181