cortex_ar/asm.rs
1//! Simple assembly routines
2
3use core::sync::atomic::{compiler_fence, Ordering};
4
5/// Data Memory Barrier
6///
7/// Ensures that all explicit memory accesses that appear in program order before the `DMB`
8/// instruction are observed before any explicit memory accesses that appear in program order
9/// after the `DMB` instruction.
10#[inline]
11pub fn dmb() {
12 compiler_fence(Ordering::SeqCst);
13 unsafe {
14 core::arch::asm!("dmb", options(nostack, preserves_flags));
15 }
16 compiler_fence(Ordering::SeqCst);
17}
18
19/// Data Synchronization Barrier
20///
21/// Acts as a special kind of memory barrier. No instruction in program order after this instruction
22/// can execute until this instruction completes. This instruction completes only when both:
23///
24/// * any explicit memory access made before this instruction is complete
25/// * all cache and branch predictor maintenance operations before this instruction complete
26#[inline]
27pub fn dsb() {
28 compiler_fence(Ordering::SeqCst);
29 unsafe {
30 core::arch::asm!("dsb", options(nostack, preserves_flags));
31 }
32 compiler_fence(Ordering::SeqCst);
33}
34
35/// Instruction Synchronization Barrier
36///
37/// Flushes the pipeline in the processor, so that all instructions following the `ISB` are fetched
38/// from cache or memory, after the instruction has been completed.
39#[inline]
40pub fn isb() {
41 compiler_fence(Ordering::SeqCst);
42 unsafe {
43 core::arch::asm!("isb", options(nostack, preserves_flags));
44 }
45 compiler_fence(Ordering::SeqCst);
46}
47
48/// Emit an NOP instruction
49#[inline]
50pub fn nop() {
51 unsafe { core::arch::asm!("nop", options(nomem, nostack, preserves_flags)) }
52}
53
54/// Emit an WFI instruction
55#[inline]
56pub fn wfi() {
57 unsafe { core::arch::asm!("wfi", options(nomem, nostack, preserves_flags)) }
58}
59
60/// Emit an WFE instruction
61#[inline]
62pub fn wfe() {
63 unsafe { core::arch::asm!("wfe", options(nomem, nostack, preserves_flags)) }
64}
65
66/// Emit an SEV instruction
67#[inline]
68pub fn sev() {
69 unsafe {
70 core::arch::asm!("sev");
71 }
72}
73
74/// Which core are we?
75///
76/// Return the bottom 24-bits of the MPIDR
77#[inline]
78pub fn core_id() -> u32 {
79 let r: u32;
80 unsafe {
81 core::arch::asm!("MRC p15, 0, {}, c0, c0, 5", out(reg) r, options(nomem, nostack, preserves_flags));
82 }
83 r & 0x00FF_FFFF
84}