Skip to content

Commit 5422ffd

Browse files
committed
riscv: more instruction intrinsics
todo: wait before supervisor extension in rustc risc-v target is available (e.g. when we're developing kernel modules or kernels themselves, S extension is enabled) sinval.vma instructions FENCE.I instruction
1 parent 293d4bc commit 5422ffd

File tree

1 file changed

+136
-1
lines changed
  • crates/core_arch/src/riscv

1 file changed

+136
-1
lines changed

crates/core_arch/src/riscv/mod.rs

+136-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,145 @@
11
//! RISC-V intrinsics
22
3+
use crate::arch::asm;
4+
35
/// Generates the `PAUSE` instruction
46
///
57
/// The PAUSE instruction is a HINT that indicates the current hart's rate of instruction retirement
68
/// should be temporarily reduced or paused. The duration of its effect must be bounded and may be zero.
79
#[inline]
810
pub fn pause() {
9-
unsafe { crate::arch::asm!(".word 0x0100000F", options(nomem, nostack)) }
11+
unsafe { asm!(".insn i 0x0F, 0, x0, x0, 0x010", options(nomem, nostack)) }
12+
}
13+
14+
/// Generates the `NOP` instruction
15+
///
16+
/// The NOP instruction does not change any architecturally visible state, except for
17+
/// advancing the `pc` and incrementing any applicable performance counters.
18+
#[inline]
19+
pub fn nop() {
20+
unsafe { asm!("nop") }
21+
}
22+
23+
/// Generates the `WFI` instruction
24+
///
25+
/// The WFI instruction provides a hint to the implementation that the current hart can be stalled
26+
/// until an interrupt might need servicing. This instruction is a hint,
27+
/// and a legal implementation is to simply implement WFI as a NOP.
28+
#[inline]
29+
pub unsafe fn wfi() {
30+
asm!("wfi")
31+
}
32+
33+
/// Generates the `FENCE.I` instruction
34+
///
35+
/// A FENCE.I instruction ensures that a subsequent instruction fetch on a RISC-V hart will see
36+
/// any previous data stores already visible to the same RISC-V hart.
37+
///
38+
/// FENCE.I does not ensure that other RISC-V harts' instruction fetches will observe the
39+
/// local hart's stores in a multiprocessor system.
40+
#[inline]
41+
pub unsafe fn fence_i() {
42+
asm!("fence.i")
43+
}
44+
45+
/// Generates the `SFENCE.VMA` instruction for given virtual address and address space
46+
///
47+
/// The fence orders only reads and writes made to leaf page table entries corresponding to
48+
/// the virtual address in parameter `vaddr`, for the address space identified by integer parameter
49+
/// `asid`. Accesses to global mappings are not ordered. The fence also invalidates all
50+
/// address-translation cache entries that contain leaf page table entries corresponding to the
51+
/// virtual address in parameter `vaddr` and that match the address space identified by integer
52+
/// parameter `asid`, except for entries containing global mappings.
53+
#[inline]
54+
pub unsafe fn sfence_vma(vaddr: usize, asid: usize) {
55+
asm!("sfence.vma {}, {}", in(reg) vaddr, in(reg) asid)
56+
}
57+
58+
/// Generates the `SFENCE.VMA` instruction for given virtual address
59+
///
60+
/// The fence orders only reads and writes made to leaf page table entries corresponding to
61+
/// the virtual address in parameter `vaddr`, for all address spaces.
62+
/// The fence also invalidates all address-translation cache entries that contain leaf page
63+
/// table entries corresponding to the virtual address in parameter `vaddr`, for all address spaces.
64+
#[inline]
65+
pub unsafe fn sfence_vma_vaddr(vaddr: usize) {
66+
asm!("sfence.vma {}, x0", in(reg) vaddr)
67+
}
68+
69+
/// Generates the `SFENCE.VMA` instruction for given address space
70+
///
71+
/// The fence orders all reads and writes made to any level of the page tables,
72+
/// but only for the address space identified by integer parameter `asid`.
73+
///
74+
/// Accesses to global mappings are not ordered. The fence also invalidates all
75+
/// address-translation cache entries matching the address space identified by integer
76+
/// parameter `asid`, except for entries containing global mappings.
77+
#[inline]
78+
pub unsafe fn sfence_vma_asid(asid: usize) {
79+
asm!("sfence.vma x0, {}", in(reg) asid)
80+
}
81+
82+
/// Generates the `SFENCE.VMA` instruction for all address spaces and virtual addresses
83+
///
84+
/// The fence orders all reads and writes made to any level of the page
85+
/// tables, for all address spaces. The fence also invalidates all address-translation cache entries,
86+
/// for all address spaces.
87+
#[inline]
88+
pub unsafe fn sfence_vma_all() {
89+
asm!("sfence.vma")
90+
}
91+
92+
/// Generates the `SINVAL.VMA` instruction for given virtual address and address space
93+
///
94+
/// This instruction invalidates any address-translation cache entries that an
95+
/// `SFENCE.VMA` instruction with the same values of `vaddr` and `asid` would invalidate.
96+
#[inline]
97+
pub unsafe fn sinval_vma(vaddr: usize, asid: usize) {
98+
// asm!("sinval.vma {}, {}", in(reg) vaddr, in(reg) asid)
99+
asm!(".insn r 0x73, 0, 0x0B, x0, {}, {}", in(reg) vaddr, in(reg) asid)
100+
}
101+
102+
/// Generates the `SINVAL.VMA` instruction for given virtual address
103+
///
104+
/// This instruction invalidates any address-translation cache entries that an
105+
/// `SFENCE.VMA` instruction with the same values of `vaddr` and `asid` would invalidate.
106+
#[inline]
107+
pub unsafe fn sinval_vma_vaddr(vaddr: usize) {
108+
asm!(".insn r 0x73, 0, 0x0B, x0, {}, x0", in(reg) vaddr)
109+
}
110+
111+
/// Generates the `SINVAL.VMA` instruction for given address space
112+
///
113+
/// This instruction invalidates any address-translation cache entries that an
114+
/// `SFENCE.VMA` instruction with the same values of `vaddr` and `asid` would invalidate.
115+
#[inline]
116+
pub unsafe fn sinval_vma_asid(asid: usize) {
117+
asm!(".insn r 0x73, 0, 0x0B, x0, x0, {}", in(reg) asid)
118+
}
119+
120+
/// Generates the `SINVAL.VMA` instruction for all address spaces and virtual addresses
121+
///
122+
/// This instruction invalidates any address-translation cache entries that an
123+
/// `SFENCE.VMA` instruction with the same values of `vaddr` and `asid` would invalidate.
124+
#[inline]
125+
pub unsafe fn sinval_vma_all() {
126+
asm!(".insn r 0x73, 0, 0x0B, x0, x0, x0")
127+
}
128+
129+
/// Generates the `SFENCE.W.INVAL` instruction
130+
///
131+
/// This instruction guarantees that any previous stores already visible to the current RISC-V hart
132+
/// are ordered before subsequent `SINVAL.VMA` instructions executed by the same hart.
133+
#[inline]
134+
pub unsafe fn sfence_w_inval() {
135+
asm!(".insn i 0x73, 0, x0, x0, 0x180")
136+
}
137+
138+
/// Generates the `SFENCE.INVAL.IR` instruction
139+
///
140+
/// This instruction guarantees that any previous SINVAL.VMA instructions executed by the current hart
141+
/// are ordered before subsequent implicit references by that hart to the memory-management data structures.
142+
#[inline]
143+
pub unsafe fn sfence_inval_ir() {
144+
asm!(".insn i 0x73, 0, x0, x0, 0x181")
10145
}

0 commit comments

Comments
 (0)