core/stdarch/crates/core_arch/src/riscv_shared/mod.rs
1//! Shared RISC-V intrinsics
2//!
3//! ## Missing floating-point register instructions
4//!
5//! We are deliberately *not* providing instructions that could change the floating-point rounding
6//! mode or exception behavior or read the accrued exceptions flags: `frcsr`, `fscsr`, `fsrm`,
7//! `frflags`, `fsflags`.
8//!
9//! Rust makes no guarantees whatsoever about the contents of the accrued exceptions register: Rust
10//! floating-point operations may or may not result in this register getting updated with exception
11//! state, and the register can change between two invocations of this function even when no
12//! floating-point operations appear in the source code (since floating-point operations appearing
13//! earlier or later can be reordered).
14//!
15//! Modifying the rounding mode leads to **immediate Undefined Behavior**: Rust assumes that the
16//! default rounding mode is always set and will optimize accordingly. This even applies when the
17//! rounding mode is altered and later reset to its original value without any floating-point
18//! operations appearing in the source code between those operations (since floating-point
19//! operations appearing earlier or later can be reordered).
20//!
21//! If you need to perform some floating-point operations and check whether they raised an
22//! exception, use a single inline assembly block for the entire sequence of operations.
23//!
24//! If you need to perform some floating-point operations under a differen rounding mode, use a
25//! single inline assembly block and make sure to restore the original rounding mode before the end
26//! of the block.
27mod p;
28mod zb;
29mod zk;
30
31#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
32pub use p::*;
33#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
34pub use zb::*;
35#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
36pub use zk::*;
37
38use crate::arch::asm;
39
40/// Generates the `PAUSE` instruction
41///
42/// The PAUSE instruction is a HINT that indicates the current hart's rate of instruction retirement
43/// should be temporarily reduced or paused. The duration of its effect must be bounded and may be zero.
44#[inline]
45#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
46pub fn pause() {
47 unsafe { asm!(".insn i 0x0F, 0, x0, x0, 0x010", options(nomem, nostack)) }
48}
49
50/// Generates the `NOP` instruction
51///
52/// The NOP instruction does not change any architecturally visible state, except for
53/// advancing the `pc` and incrementing any applicable performance counters.
54#[inline]
55#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
56pub fn nop() {
57 unsafe { asm!("nop", options(nomem, nostack)) }
58}
59
60/// Generates the `WFI` instruction
61///
62/// The WFI instruction provides a hint to the implementation that the current hart can be stalled
63/// until an interrupt might need servicing. This instruction is a hint,
64/// and a legal implementation is to simply implement WFI as a NOP.
65#[inline]
66#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
67pub unsafe fn wfi() {
68 asm!("wfi", options(nomem, nostack))
69}
70
71/// Generates the `FENCE.I` instruction
72///
73/// A FENCE.I instruction ensures that a subsequent instruction fetch on a RISC-V hart will see
74/// any previous data stores already visible to the same RISC-V hart.
75///
76/// FENCE.I does not ensure that other RISC-V harts' instruction fetches will observe the
77/// local hart's stores in a multiprocessor system.
78#[inline]
79#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
80pub unsafe fn fence_i() {
81 asm!("fence.i", options(nostack))
82}
83
84/// Supervisor memory management fence for given virtual address and address space
85///
86/// The fence orders only reads and writes made to leaf page table entries corresponding to
87/// the virtual address in parameter `vaddr`, for the address space identified by integer parameter
88/// `asid`. Accesses to global mappings are not ordered. The fence also invalidates all
89/// address-translation cache entries that contain leaf page table entries corresponding to the
90/// virtual address in parameter `vaddr` and that match the address space identified by integer
91/// parameter `asid`, except for entries containing global mappings.
92#[inline]
93#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
94pub unsafe fn sfence_vma(vaddr: usize, asid: usize) {
95 asm!("sfence.vma {}, {}", in(reg) vaddr, in(reg) asid, options(nostack))
96}
97
98/// Supervisor memory management fence for given virtual address
99///
100/// The fence orders only reads and writes made to leaf page table entries corresponding to
101/// the virtual address in parameter `vaddr`, for all address spaces.
102/// The fence also invalidates all address-translation cache entries that contain leaf page
103/// table entries corresponding to the virtual address in parameter `vaddr`, for all address spaces.
104#[inline]
105#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
106pub unsafe fn sfence_vma_vaddr(vaddr: usize) {
107 asm!("sfence.vma {}, x0", in(reg) vaddr, options(nostack))
108}
109
110/// Supervisor memory management fence for given address space
111///
112/// The fence orders all reads and writes made to any level of the page tables,
113/// but only for the address space identified by integer parameter `asid`.
114///
115/// Accesses to global mappings are not ordered. The fence also invalidates all
116/// address-translation cache entries matching the address space identified by integer
117/// parameter `asid`, except for entries containing global mappings.
118#[inline]
119#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
120pub unsafe fn sfence_vma_asid(asid: usize) {
121 asm!("sfence.vma x0, {}", in(reg) asid, options(nostack))
122}
123
124/// Supervisor memory management fence for all address spaces and virtual addresses
125///
126/// The fence orders all reads and writes made to any level of the page
127/// tables, for all address spaces. The fence also invalidates all address-translation cache entries,
128/// for all address spaces.
129#[inline]
130#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
131pub unsafe fn sfence_vma_all() {
132 asm!("sfence.vma", options(nostack))
133}
134
135/// Invalidate supervisor translation cache for given virtual address and address space
136///
137/// This instruction invalidates any address-translation cache entries that an
138/// `SFENCE.VMA` instruction with the same values of `vaddr` and `asid` would invalidate.
139#[inline]
140#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
141pub unsafe fn sinval_vma(vaddr: usize, asid: usize) {
142 // asm!("sinval.vma {}, {}", in(reg) vaddr, in(reg) asid, options(nostack))
143 asm!(".insn r 0x73, 0, 0x0B, x0, {}, {}", in(reg) vaddr, in(reg) asid, options(nostack))
144}
145
146/// Invalidate supervisor translation cache for given virtual address
147///
148/// This instruction invalidates any address-translation cache entries that an
149/// `SFENCE.VMA` instruction with the same values of `vaddr` and `asid` would invalidate.
150#[inline]
151#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
152pub unsafe fn sinval_vma_vaddr(vaddr: usize) {
153 asm!(".insn r 0x73, 0, 0x0B, x0, {}, x0", in(reg) vaddr, options(nostack))
154}
155
156/// Invalidate supervisor translation cache for given address space
157///
158/// This instruction invalidates any address-translation cache entries that an
159/// `SFENCE.VMA` instruction with the same values of `vaddr` and `asid` would invalidate.
160#[inline]
161#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
162pub unsafe fn sinval_vma_asid(asid: usize) {
163 asm!(".insn r 0x73, 0, 0x0B, x0, x0, {}", in(reg) asid, options(nostack))
164}
165
166/// Invalidate supervisor translation cache for all address spaces and virtual addresses
167///
168/// This instruction invalidates any address-translation cache entries that an
169/// `SFENCE.VMA` instruction with the same values of `vaddr` and `asid` would invalidate.
170#[inline]
171#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
172pub unsafe fn sinval_vma_all() {
173 asm!(".insn r 0x73, 0, 0x0B, x0, x0, x0", options(nostack))
174}
175
176/// Generates the `SFENCE.W.INVAL` instruction
177///
178/// This instruction guarantees that any previous stores already visible to the current RISC-V hart
179/// are ordered before subsequent `SINVAL.VMA` instructions executed by the same hart.
180#[inline]
181#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
182pub unsafe fn sfence_w_inval() {
183 // asm!("sfence.w.inval", options(nostack))
184 asm!(".insn i 0x73, 0, x0, x0, 0x180", options(nostack))
185}
186
187/// Generates the `SFENCE.INVAL.IR` instruction
188///
189/// This instruction guarantees that any previous SINVAL.VMA instructions executed by the current hart
190/// are ordered before subsequent implicit references by that hart to the memory-management data structures.
191#[inline]
192#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
193pub unsafe fn sfence_inval_ir() {
194 // asm!("sfence.inval.ir", options(nostack))
195 asm!(".insn i 0x73, 0, x0, x0, 0x181", options(nostack))
196}
197
198/// Loads virtual machine memory by signed byte integer
199///
200/// This instruction performs an explicit memory access as though `V=1`;
201/// i.e., with the address translation and protection, and the endianness, that apply to memory
202/// accesses in either VS-mode or VU-mode.
203///
204/// This function is unsafe for it accesses the virtual supervisor or user via a `HLV.B`
205/// instruction which is effectively a dereference to any memory address.
206#[inline]
207#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
208pub unsafe fn hlv_b(src: *const i8) -> i8 {
209 let value: i8;
210 asm!(".insn i 0x73, 0x4, {}, {}, 0x600", out(reg) value, in(reg) src, options(readonly, nostack));
211 value
212}
213
214/// Loads virtual machine memory by unsigned byte integer
215///
216/// This instruction performs an explicit memory access as though `V=1`;
217/// i.e., with the address translation and protection, and the endianness, that apply to memory
218/// accesses in either VS-mode or VU-mode.
219///
220/// This function is unsafe for it accesses the virtual supervisor or user via a `HLV.BU`
221/// instruction which is effectively a dereference to any memory address.
222#[inline]
223#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
224pub unsafe fn hlv_bu(src: *const u8) -> u8 {
225 let value: u8;
226 asm!(".insn i 0x73, 0x4, {}, {}, 0x601", out(reg) value, in(reg) src, options(readonly, nostack));
227 value
228}
229
230/// Loads virtual machine memory by signed half integer
231///
232/// This instruction performs an explicit memory access as though `V=1`;
233/// i.e., with the address translation and protection, and the endianness, that apply to memory
234/// accesses in either VS-mode or VU-mode.
235///
236/// This function is unsafe for it accesses the virtual supervisor or user via a `HLV.H`
237/// instruction which is effectively a dereference to any memory address.
238#[inline]
239#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
240pub unsafe fn hlv_h(src: *const i16) -> i16 {
241 let value: i16;
242 asm!(".insn i 0x73, 0x4, {}, {}, 0x640", out(reg) value, in(reg) src, options(readonly, nostack));
243 value
244}
245
246/// Loads virtual machine memory by unsigned half integer
247///
248/// This instruction performs an explicit memory access as though `V=1`;
249/// i.e., with the address translation and protection, and the endianness, that apply to memory
250/// accesses in either VS-mode or VU-mode.
251///
252/// This function is unsafe for it accesses the virtual supervisor or user via a `HLV.HU`
253/// instruction which is effectively a dereference to any memory address.
254#[inline]
255#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
256pub unsafe fn hlv_hu(src: *const u16) -> u16 {
257 let value: u16;
258 asm!(".insn i 0x73, 0x4, {}, {}, 0x641", out(reg) value, in(reg) src, options(readonly, nostack));
259 value
260}
261
262/// Accesses virtual machine instruction by unsigned half integer
263///
264/// This instruction performs an explicit memory access as though `V=1`;
265/// the memory being read must be executable in both stages of address translation,
266/// but read permission is not required.
267///
268/// This function is unsafe for it accesses the virtual supervisor or user via a `HLVX.HU`
269/// instruction which is effectively a dereference to any memory address.
270#[inline]
271#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
272pub unsafe fn hlvx_hu(src: *const u16) -> u16 {
273 let insn: u16;
274 asm!(".insn i 0x73, 0x4, {}, {}, 0x643", out(reg) insn, in(reg) src, options(readonly, nostack));
275 insn
276}
277
278/// Loads virtual machine memory by signed word integer
279///
280/// This instruction performs an explicit memory access as though `V=1`;
281/// i.e., with the address translation and protection, and the endianness, that apply to memory
282/// accesses in either VS-mode or VU-mode.
283///
284/// This function is unsafe for it accesses the virtual supervisor or user via a `HLV.W`
285/// instruction which is effectively a dereference to any memory address.
286#[inline]
287#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
288pub unsafe fn hlv_w(src: *const i32) -> i32 {
289 let value: i32;
290 asm!(".insn i 0x73, 0x4, {}, {}, 0x680", out(reg) value, in(reg) src, options(readonly, nostack));
291 value
292}
293
294/// Accesses virtual machine instruction by unsigned word integer
295///
296/// This instruction performs an explicit memory access as though `V=1`;
297/// the memory being read must be executable in both stages of address translation,
298/// but read permission is not required.
299///
300/// This function is unsafe for it accesses the virtual supervisor or user via a `HLVX.WU`
301/// instruction which is effectively a dereference to any memory address.
302#[inline]
303#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
304pub unsafe fn hlvx_wu(src: *const u32) -> u32 {
305 let insn: u32;
306 asm!(".insn i 0x73, 0x4, {}, {}, 0x683", out(reg) insn, in(reg) src, options(readonly, nostack));
307 insn
308}
309
310/// Stores virtual machine memory by byte integer
311///
312/// This instruction performs an explicit memory access as though `V=1`;
313/// i.e., with the address translation and protection, and the endianness, that apply to memory
314/// accesses in either VS-mode or VU-mode.
315///
316/// This function is unsafe for it accesses the virtual supervisor or user via a `HSV.B`
317/// instruction which is effectively a dereference to any memory address.
318#[inline]
319#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
320pub unsafe fn hsv_b(dst: *mut i8, src: i8) {
321 asm!(".insn r 0x73, 0x4, 0x31, x0, {}, {}", in(reg) dst, in(reg) src, options(nostack));
322}
323
324/// Stores virtual machine memory by half integer
325///
326/// This instruction performs an explicit memory access as though `V=1`;
327/// i.e., with the address translation and protection, and the endianness, that apply to memory
328/// accesses in either VS-mode or VU-mode.
329///
330/// This function is unsafe for it accesses the virtual supervisor or user via a `HSV.H`
331/// instruction which is effectively a dereference to any memory address.
332#[inline]
333#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
334pub unsafe fn hsv_h(dst: *mut i16, src: i16) {
335 asm!(".insn r 0x73, 0x4, 0x33, x0, {}, {}", in(reg) dst, in(reg) src, options(nostack));
336}
337
338/// Stores virtual machine memory by word integer
339///
340/// This instruction performs an explicit memory access as though `V=1`;
341/// i.e., with the address translation and protection, and the endianness, that apply to memory
342/// accesses in either VS-mode or VU-mode.
343///
344/// This function is unsafe for it accesses the virtual supervisor or user via a `HSV.W`
345/// instruction which is effectively a dereference to any memory address.
346#[inline]
347#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
348pub unsafe fn hsv_w(dst: *mut i32, src: i32) {
349 asm!(".insn r 0x73, 0x4, 0x35, x0, {}, {}", in(reg) dst, in(reg) src, options(nostack));
350}
351
352/// Hypervisor memory management fence for given guest virtual address and guest address space
353///
354/// Guarantees that any previous stores already visible to the current hart are ordered before all
355/// implicit reads by that hart done for VS-stage address translation for instructions that:
356/// - are subsequent to the `HFENCE.VVMA`, and
357/// - execute when `hgatp.VMID` has the same setting as it did when `HFENCE.VVMA` executed.
358///
359/// This fence specifies a single guest virtual address, and a single guest address-space identifier.
360#[inline]
361#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
362pub unsafe fn hfence_vvma(vaddr: usize, asid: usize) {
363 // asm!("hfence.vvma {}, {}", in(reg) vaddr, in(reg) asid)
364 asm!(".insn r 0x73, 0, 0x11, x0, {}, {}", in(reg) vaddr, in(reg) asid, options(nostack))
365}
366
367/// Hypervisor memory management fence for given guest virtual address
368///
369/// Guarantees that any previous stores already visible to the current hart are ordered before all
370/// implicit reads by that hart done for VS-stage address translation for instructions that:
371/// - are subsequent to the `HFENCE.VVMA`, and
372/// - execute when `hgatp.VMID` has the same setting as it did when `HFENCE.VVMA` executed.
373///
374/// This fence specifies a single guest virtual address.
375#[inline]
376#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
377pub unsafe fn hfence_vvma_vaddr(vaddr: usize) {
378 asm!(".insn r 0x73, 0, 0x11, x0, {}, x0", in(reg) vaddr, options(nostack))
379}
380
381/// Hypervisor memory management fence for given guest address space
382///
383/// Guarantees that any previous stores already visible to the current hart are ordered before all
384/// implicit reads by that hart done for VS-stage address translation for instructions that:
385/// - are subsequent to the `HFENCE.VVMA`, and
386/// - execute when `hgatp.VMID` has the same setting as it did when `HFENCE.VVMA` executed.
387///
388/// This fence specifies a single guest address-space identifier.
389#[inline]
390#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
391pub unsafe fn hfence_vvma_asid(asid: usize) {
392 asm!(".insn r 0x73, 0, 0x11, x0, x0, {}", in(reg) asid, options(nostack))
393}
394
395/// Hypervisor memory management fence for all guest address spaces and guest virtual addresses
396///
397/// Guarantees that any previous stores already visible to the current hart are ordered before all
398/// implicit reads by that hart done for VS-stage address translation for instructions that:
399/// - are subsequent to the `HFENCE.VVMA`, and
400/// - execute when `hgatp.VMID` has the same setting as it did when `HFENCE.VVMA` executed.
401///
402/// This fence applies to any guest address spaces and guest virtual addresses.
403#[inline]
404#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
405pub unsafe fn hfence_vvma_all() {
406 asm!(".insn r 0x73, 0, 0x11, x0, x0, x0", options(nostack))
407}
408
409/// Hypervisor memory management fence for guest physical address and virtual machine
410///
411/// Guarantees that any previous stores already visible to the current hart are ordered before all implicit reads
412/// by that hart done for G-stage address translation for instructions that follow the HFENCE.GVMA.
413///
414/// This fence specifies a single guest physical address, **shifted right by 2 bits**, and a single virtual machine
415/// by virtual machine identifier (VMID).
416#[inline]
417#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
418pub unsafe fn hfence_gvma(gaddr: usize, vmid: usize) {
419 // asm!("hfence.gvma {}, {}", in(reg) gaddr, in(reg) vmid, options(nostack))
420 asm!(".insn r 0x73, 0, 0x31, x0, {}, {}", in(reg) gaddr, in(reg) vmid, options(nostack))
421}
422
423/// Hypervisor memory management fence for guest physical address
424///
425/// Guarantees that any previous stores already visible to the current hart are ordered before all implicit reads
426/// by that hart done for G-stage address translation for instructions that follow the HFENCE.GVMA.
427///
428/// This fence specifies a single guest physical address; **the physical address should be shifted right by 2 bits**.
429#[inline]
430#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
431pub unsafe fn hfence_gvma_gaddr(gaddr: usize) {
432 asm!(".insn r 0x73, 0, 0x31, x0, {}, x0", in(reg) gaddr, options(nostack))
433}
434
435/// Hypervisor memory management fence for given virtual machine
436///
437/// Guarantees that any previous stores already visible to the current hart are ordered before all implicit reads
438/// by that hart done for G-stage address translation for instructions that follow the HFENCE.GVMA.
439///
440/// This fence specifies a single virtual machine by virtual machine identifier (VMID).
441#[inline]
442#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
443pub unsafe fn hfence_gvma_vmid(vmid: usize) {
444 asm!(".insn r 0x73, 0, 0x31, x0, x0, {}", in(reg) vmid, options(nostack))
445}
446
447/// Hypervisor memory management fence for all virtual machines and guest physical addresses
448///
449/// Guarantees that any previous stores already visible to the current hart are ordered before all implicit reads
450/// by that hart done for G-stage address translation for instructions that follow the HFENCE.GVMA.
451///
452/// This fence specifies all guest physical addresses and all virtual machines.
453#[inline]
454#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
455pub unsafe fn hfence_gvma_all() {
456 asm!(".insn r 0x73, 0, 0x31, x0, x0, x0", options(nostack))
457}
458
459/// Invalidate hypervisor translation cache for given guest virtual address and guest address space
460///
461/// This instruction invalidates any address-translation cache entries that an
462/// `HFENCE.VVMA` instruction with the same values of `vaddr` and `asid` would invalidate.
463///
464/// This fence specifies a single guest virtual address, and a single guest address-space identifier.
465#[inline]
466#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
467pub unsafe fn hinval_vvma(vaddr: usize, asid: usize) {
468 // asm!("hinval.vvma {}, {}", in(reg) vaddr, in(reg) asid, options(nostack))
469 asm!(".insn r 0x73, 0, 0x13, x0, {}, {}", in(reg) vaddr, in(reg) asid, options(nostack))
470}
471
472/// Invalidate hypervisor translation cache for given guest virtual address
473///
474/// This instruction invalidates any address-translation cache entries that an
475/// `HFENCE.VVMA` instruction with the same values of `vaddr` and `asid` would invalidate.
476///
477/// This fence specifies a single guest virtual address.
478#[inline]
479#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
480pub unsafe fn hinval_vvma_vaddr(vaddr: usize) {
481 asm!(".insn r 0x73, 0, 0x13, x0, {}, x0", in(reg) vaddr, options(nostack))
482}
483
484/// Invalidate hypervisor translation cache for given guest address space
485///
486/// This instruction invalidates any address-translation cache entries that an
487/// `HFENCE.VVMA` instruction with the same values of `vaddr` and `asid` would invalidate.
488///
489/// This fence specifies a single guest address-space identifier.
490#[inline]
491#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
492pub unsafe fn hinval_vvma_asid(asid: usize) {
493 asm!(".insn r 0x73, 0, 0x13, x0, x0, {}", in(reg) asid, options(nostack))
494}
495
496/// Invalidate hypervisor translation cache for all guest address spaces and guest virtual addresses
497///
498/// This instruction invalidates any address-translation cache entries that an
499/// `HFENCE.VVMA` instruction with the same values of `vaddr` and `asid` would invalidate.
500///
501/// This fence applies to any guest address spaces and guest virtual addresses.
502#[inline]
503#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
504pub unsafe fn hinval_vvma_all() {
505 asm!(".insn r 0x73, 0, 0x13, x0, x0, x0", options(nostack))
506}
507
508/// Invalidate hypervisor translation cache for guest physical address and virtual machine
509///
510/// This instruction invalidates any address-translation cache entries that an
511/// `HFENCE.GVMA` instruction with the same values of `gaddr` and `vmid` would invalidate.
512///
513/// This fence specifies a single guest physical address, **shifted right by 2 bits**, and a single virtual machine
514/// by virtual machine identifier (VMID).
515#[inline]
516#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
517pub unsafe fn hinval_gvma(gaddr: usize, vmid: usize) {
518 // asm!("hinval.gvma {}, {}", in(reg) gaddr, in(reg) vmid, options(nostack))
519 asm!(".insn r 0x73, 0, 0x33, x0, {}, {}", in(reg) gaddr, in(reg) vmid, options(nostack))
520}
521
522/// Invalidate hypervisor translation cache for guest physical address
523///
524/// This instruction invalidates any address-translation cache entries that an
525/// `HFENCE.GVMA` instruction with the same values of `gaddr` and `vmid` would invalidate.
526///
527/// This fence specifies a single guest physical address; **the physical address should be shifted right by 2 bits**.
528#[inline]
529#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
530pub unsafe fn hinval_gvma_gaddr(gaddr: usize) {
531 asm!(".insn r 0x73, 0, 0x33, x0, {}, x0", in(reg) gaddr, options(nostack))
532}
533
534/// Invalidate hypervisor translation cache for given virtual machine
535///
536/// This instruction invalidates any address-translation cache entries that an
537/// `HFENCE.GVMA` instruction with the same values of `gaddr` and `vmid` would invalidate.
538///
539/// This fence specifies a single virtual machine by virtual machine identifier (VMID).
540#[inline]
541#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
542pub unsafe fn hinval_gvma_vmid(vmid: usize) {
543 asm!(".insn r 0x73, 0, 0x33, x0, x0, {}", in(reg) vmid, options(nostack))
544}
545
546/// Invalidate hypervisor translation cache for all virtual machines and guest physical addresses
547///
548/// This instruction invalidates any address-translation cache entries that an
549/// `HFENCE.GVMA` instruction with the same values of `gaddr` and `vmid` would invalidate.
550///
551/// This fence specifies all guest physical addresses and all virtual machines.
552#[inline]
553#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
554pub unsafe fn hinval_gvma_all() {
555 asm!(".insn r 0x73, 0, 0x33, x0, x0, x0", options(nostack))
556}
557
558/// Reads the floating-point rounding mode register `frm`
559///
560/// According to "F" Standard Extension for Single-Precision Floating-Point, Version 2.2,
561/// the rounding mode field is defined as listed in the table below:
562///
563/// | Rounding Mode | Mnemonic | Meaning |
564/// |:-------------|:----------|:---------|
565/// | 000 | RNE | Round to Nearest, ties to Even |
566/// | 001 | RTZ | Round towards Zero |
567/// | 010 | RDN | Round Down (towards −∞) |
568/// | 011 | RUP | Round Up (towards +∞) |
569/// | 100 | RMM | Round to Nearest, ties to Max Magnitude |
570/// | 101 | | _Reserved for future use._ |
571/// | 110 | | _Reserved for future use._ |
572/// | 111 | DYN | In Rounding Mode register, _reserved_. |
573#[inline]
574#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
575pub fn frrm() -> u32 {
576 let value: u32;
577 unsafe { asm!("frrm {}", out(reg) value, options(nomem, nostack)) };
578 value
579}