1diff --git a/src/device/net/mod.rs b/src/device/net/mod.rs
2index fa13b44..8375946 100644
3--- a/src/device/net/mod.rs
4+++ b/src/device/net/mod.rs
5@@ -82,7 +82,7 @@ bitflags! {
6
7 bitflags! {
8     #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
9-    struct Status: u16 {
10+    pub(crate) struct Status: u16 {
11         const LINK_UP = 1;
12         const ANNOUNCE = 2;
13     }
14diff --git a/src/transport/pci/bus.rs b/src/transport/pci/bus.rs
15index 0a3014b..52f861e 100644
16--- a/src/transport/pci/bus.rs
17+++ b/src/transport/pci/bus.rs
18@@ -202,7 +202,19 @@ impl PciRoot {
19         // resulting pointer is within the MMIO range of the CAM.
20         unsafe {
21             // Right shift to convert from byte offset to word offset.
22-            (self.mmio_base.add((address >> 2) as usize)).write_volatile(data)
23+            let ptr = self.mmio_base.add((address >> 2) as usize);
24+            #[cfg(not(target_arch = "aarch64"))]
25+            {
26+                ptr.write_volatile(data)
27+            }
28+            #[cfg(target_arch = "aarch64")]
29+            {
30+                core::arch::asm!(
31+                    "str {value:w}, [{ptr}]",
32+                    value = in(reg) data,
33+                    ptr = in(reg) ptr,
34+                )
35+            }
36         }
37     }
38
39diff --git a/src/volatile.rs b/src/volatile.rs
40index b7059d1..67ebba3 100644
41--- a/src/volatile.rs
42+++ b/src/volatile.rs
43@@ -33,12 +33,14 @@ pub trait VolatileReadable<T> {
44     unsafe fn vread(self) -> T;
45 }
46
47+#[cfg(not(target_arch = "aarch64"))]
48 impl<T: Copy> VolatileReadable<T> for *const ReadOnly<T> {
49     unsafe fn vread(self) -> T {
50         self.read_volatile().0
51     }
52 }
53
54+#[cfg(not(target_arch = "aarch64"))]
55 impl<T: Copy> VolatileReadable<T> for *const Volatile<T> {
56     unsafe fn vread(self) -> T {
57         self.read_volatile().0
58@@ -51,18 +53,173 @@ pub trait VolatileWritable<T> {
59     unsafe fn vwrite(self, value: T);
60 }
61
62+#[cfg(not(target_arch = "aarch64"))]
63 impl<T: Copy> VolatileWritable<T> for *mut WriteOnly<T> {
64     unsafe fn vwrite(self, value: T) {
65         (self as *mut T).write_volatile(value)
66     }
67 }
68
69+#[cfg(not(target_arch = "aarch64"))]
70 impl<T: Copy> VolatileWritable<T> for *mut Volatile<T> {
71     unsafe fn vwrite(self, value: T) {
72         (self as *mut T).write_volatile(value)
73     }
74 }
75
76+#[cfg(target_arch = "aarch64")]
77+mod aarch64_mmio {
78+    use super::{ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly};
79+    use crate::{device::net::Status, transport::DeviceStatus};
80+    use core::arch::asm;
81+
82+    macro_rules! asm_mmio_write {
83+        ($t:ty, $assembly:literal) => {
84+            impl VolatileWritable<$t> for *mut WriteOnly<$t> {
85+                unsafe fn vwrite(self, value: $t) {
86+                    asm!(
87+                        $assembly,
88+                        value = in(reg) value,
89+                        ptr = in(reg) (self as *mut $t),
90+                    );
91+                }
92+            }
93+
94+            impl VolatileWritable<$t> for *mut Volatile<$t> {
95+                unsafe fn vwrite(self, value: $t) {
96+                    asm!(
97+                        $assembly,
98+                        value = in(reg) value,
99+                        ptr = in(reg) (self as *mut $t),
100+                    );
101+                }
102+            }
103+        };
104+    }
105+
106+    macro_rules! asm_mmio_read {
107+        ($t:ty, $assembly:literal) => {
108+            impl VolatileReadable<$t> for *const ReadOnly<$t> {
109+                unsafe fn vread(self) -> $t {
110+                    let value;
111+                    asm!(
112+                        $assembly,
113+                        value = out(reg) value,
114+                        ptr = in(reg) (self as *const $t),
115+                    );
116+                    value
117+                }
118+            }
119+
120+            impl VolatileReadable<$t> for *const Volatile<$t> {
121+                unsafe fn vread(self) -> $t {
122+                    let value;
123+                    asm!(
124+                        $assembly,
125+                        value = out(reg) value,
126+                        ptr = in(reg) (self as *const $t),
127+                    );
128+                    value
129+                }
130+            }
131+        };
132+    }
133+
134+    asm_mmio_write!(u8, "strb {value:w}, [{ptr}]");
135+    asm_mmio_write!(u16, "strh {value:w}, [{ptr}]");
136+    asm_mmio_write!(u32, "str {value:w}, [{ptr}]");
137+    asm_mmio_write!(u64, "str {value:x}, [{ptr}]");
138+
139+    impl VolatileWritable<DeviceStatus> for *mut WriteOnly<DeviceStatus> {
140+        unsafe fn vwrite(self, value: DeviceStatus) {
141+            let value: u32 = value.bits();
142+            asm!(
143+                "str {value:w}, [{ptr}]",
144+                value = in(reg) value,
145+                ptr = in(reg) (self as *mut u32),
146+            );
147+        }
148+    }
149+
150+    impl VolatileWritable<DeviceStatus> for *mut Volatile<DeviceStatus> {
151+        unsafe fn vwrite(self, value: DeviceStatus) {
152+            let value: u32 = value.bits();
153+            asm!(
154+                "str {value:w}, [{ptr}]",
155+                value = in(reg) value,
156+                ptr = in(reg) (self as *mut u32),
157+            );
158+        }
159+    }
160+
161+    asm_mmio_read!(u8, "ldrb {value:w}, [{ptr}]");
162+    asm_mmio_read!(u16, "ldrh {value:w}, [{ptr}]");
163+    asm_mmio_read!(u32, "ldr {value:w}, [{ptr}]");
164+    asm_mmio_read!(u64, "ldr {value:x}, [{ptr}]");
165+
166+    impl VolatileReadable<DeviceStatus> for *const ReadOnly<DeviceStatus> {
167+        unsafe fn vread(self) -> DeviceStatus {
168+            let value: u32;
169+            asm!(
170+                "ldr {value:w}, [{ptr}]",
171+                value = out(reg) value,
172+                ptr = in(reg) (self as *const u32),
173+            );
174+            DeviceStatus::from_bits_retain(value)
175+        }
176+    }
177+
178+    impl VolatileReadable<DeviceStatus> for *const Volatile<DeviceStatus> {
179+        unsafe fn vread(self) -> DeviceStatus {
180+            let value: u32;
181+            asm!(
182+                "ldr {value:w}, [{ptr}]",
183+                value = out(reg) value,
184+                ptr = in(reg) (self as *const u32),
185+            );
186+            DeviceStatus::from_bits_retain(value)
187+        }
188+    }
189+
190+    impl VolatileReadable<Status> for *const ReadOnly<Status> {
191+        unsafe fn vread(self) -> Status {
192+            let value: u16;
193+            asm!(
194+                "ldrh {value:w}, [{ptr}]",
195+                value = out(reg) value,
196+                ptr = in(reg) (self as *const u16),
197+            );
198+            Status::from_bits_retain(value)
199+        }
200+    }
201+
202+    impl VolatileReadable<Status> for *const Volatile<Status> {
203+        unsafe fn vread(self) -> Status {
204+            let value: u16;
205+            asm!(
206+                "ldrh {value:w}, [{ptr}]",
207+                value = out(reg) value,
208+                ptr = in(reg) (self as *const u16),
209+            );
210+            Status::from_bits_retain(value)
211+        }
212+    }
213+
214+    impl<const SIZE: usize> VolatileReadable<[u8; SIZE]> for *const ReadOnly<[u8; SIZE]> {
215+        unsafe fn vread(self) -> [u8; SIZE] {
216+            let mut value = [0; SIZE];
217+            for i in 0..SIZE {
218+                asm!(
219+                    "ldrb {value:w}, [{ptr}]",
220+                    value = out(reg) value[i],
221+                    ptr = in(reg) (self as *const u8).add(i),
222+                );
223+            }
224+            value
225+        }
226+    }
227+}
228+
229 /// Performs a volatile read from the given field of pointer to a struct representing an MMIO region.
230 ///
231 /// # Usage
232