veridian_kernel/arch/barriers.rs
1//! Architecture-independent memory barrier abstractions.
2//!
3//! Centralizes memory barrier/fence operations so that non-arch code does not
4//! need scattered `#[cfg(target_arch)]` blocks with inline assembly.
5//!
6//! # Barrier types
7//!
8//! * [`memory_fence`] -- full read/write fence (strongest).
9//! * [`data_sync_barrier`] -- data synchronization barrier with instruction
10//! synchronization on AArch64; equivalent to a full fence on other
11//! architectures.
12//! * [`instruction_sync_barrier`] -- instruction stream synchronization
13//! (AArch64 ISB, RISC-V FENCE.I, x86_64 no-op because of strong ordering).
14
15/// Full memory fence -- all reads and writes issued before this barrier are
16/// globally visible before any reads or writes issued after it.
17///
18/// * **x86_64**: `core::sync::atomic::fence(SeqCst)` -- MFENCE semantics.
19/// * **AArch64**: `dsb sy` -- Data Synchronization Barrier (full system).
20/// * **RISC-V**: `fence rw, rw` -- read/write ordering fence.
21#[inline(always)]
22pub fn memory_fence() {
23 #[cfg(target_arch = "x86_64")]
24 {
25 core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
26 }
27
28 #[cfg(target_arch = "aarch64")]
29 {
30 // SAFETY: `dsb sy` is a data synchronization barrier that ensures all
31 // preceding memory accesses are complete before subsequent ones begin.
32 // No side effects beyond ordering.
33 unsafe {
34 core::arch::asm!("dsb sy", options(nostack, nomem, preserves_flags));
35 }
36 }
37
38 #[cfg(target_arch = "riscv64")]
39 {
40 // SAFETY: `fence rw, rw` ensures all prior reads and writes are ordered
41 // before subsequent reads and writes. Standard RISC-V fence instruction.
42 unsafe {
43 core::arch::asm!("fence rw, rw", options(nostack, nomem, preserves_flags));
44 }
45 }
46}
47
48/// Data synchronization barrier with instruction synchronization.
49///
50/// On AArch64 this issues `dsb sy` followed by `isb`, which is the standard
51/// pattern used when a data store must be visible before instruction fetch
52/// proceeds (e.g., writing to a pointer that will be dereferenced
53/// immediately after).
54///
55/// On other architectures this is equivalent to [`memory_fence`] because
56/// their memory models already guarantee the necessary ordering.
57///
58/// * **x86_64**: `core::sync::atomic::fence(SeqCst)`.
59/// * **AArch64**: `dsb sy` + `isb`.
60/// * **RISC-V**: `fence rw, rw`.
61#[inline(always)]
62pub fn data_sync_barrier() {
63 #[cfg(target_arch = "x86_64")]
64 {
65 core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
66 }
67
68 #[cfg(target_arch = "aarch64")]
69 {
70 // SAFETY: `dsb sy` ensures all data accesses are complete; `isb`
71 // flushes the instruction pipeline so subsequent instructions see
72 // the updated data. Standard AArch64 barrier pair.
73 unsafe {
74 core::arch::asm!("dsb sy", "isb", options(nostack, nomem, preserves_flags));
75 }
76 }
77
78 #[cfg(target_arch = "riscv64")]
79 {
80 // SAFETY: `fence rw, rw` is the RISC-V full read/write ordering fence.
81 unsafe {
82 core::arch::asm!("fence rw, rw", options(nostack, nomem, preserves_flags));
83 }
84 }
85}
86
87/// Instruction synchronization barrier.
88///
89/// Ensures that all preceding instructions have completed and the instruction
90/// pipeline is flushed before subsequent instructions execute. This is
91/// primarily needed on AArch64 and RISC-V after modifying code pages or
92/// after a data barrier that affects instruction fetch.
93///
94/// * **x86_64**: no-op -- x86_64's strong ordering model and unified cache make
95/// an explicit instruction barrier unnecessary in most scenarios.
96/// * **AArch64**: `isb` -- Instruction Synchronization Barrier.
97/// * **RISC-V**: `fence.i` -- Instruction fence.
98#[inline(always)]
99pub fn instruction_sync_barrier() {
100 #[cfg(target_arch = "x86_64")]
101 {
102 // x86_64 has a strongly ordered memory model; no explicit ISB needed.
103 }
104
105 #[cfg(target_arch = "aarch64")]
106 {
107 // SAFETY: `isb` flushes the instruction pipeline. No side effects
108 // beyond pipeline synchronization.
109 unsafe {
110 core::arch::asm!("isb", options(nostack, nomem, preserves_flags));
111 }
112 }
113
114 #[cfg(target_arch = "riscv64")]
115 {
116 // SAFETY: `fence.i` synchronizes the instruction and data streams.
117 // Required after modifying code in memory. No memory side effects.
118 unsafe {
119 core::arch::asm!("fence.i", options(nostack, nomem));
120 }
121 }
122}