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    // Use `.option` directives to expose this HINT instruction
48    // (no-op if not supported by the hardware) without `#[target_feature]`.
49    unsafe {
50        asm!(
51            ".option push",
52            ".option arch, +zihintpause",
53            "pause",
54            ".option pop",
55            options(nomem, nostack, preserves_flags)
56        );
57    }
58}
59
60/// Generates the `NOP` instruction
61///
62/// The NOP instruction does not change any architecturally visible state, except for
63/// advancing the `pc` and incrementing any applicable performance counters.
64#[inline]
65#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
66pub fn nop() {
67    unsafe {
68        asm!("nop", options(nomem, nostack, preserves_flags));
69    }
70}
71
72/// Generates the `WFI` instruction
73///
74/// The WFI instruction provides a hint to the implementation that the current hart can be stalled
75/// until an interrupt might need servicing. This instruction is a hint,
76/// and a legal implementation is to simply implement WFI as a NOP.
77#[inline]
78#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
79pub unsafe fn wfi() {
80    asm!("wfi", options(nomem, nostack, preserves_flags));
81}
82
83/// Generates the `FENCE.I` instruction
84///
85/// A FENCE.I instruction ensures that a subsequent instruction fetch on a RISC-V hart will see
86/// any previous data stores already visible to the same RISC-V hart.
87///
88/// FENCE.I does not ensure that other RISC-V harts' instruction fetches will observe the
89/// local hart's stores in a multiprocessor system.
90#[inline]
91#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
92pub unsafe fn fence_i() {
93    asm!("fence.i", options(nostack, preserves_flags));
94}
95
96/// Supervisor memory management fence for given virtual address and address space
97///
98/// The fence orders only reads and writes made to leaf page table entries corresponding to
99/// the virtual address in parameter `vaddr`, for the address space identified by integer parameter
100/// `asid`. Accesses to global mappings are not ordered. The fence also invalidates all
101/// address-translation cache entries that contain leaf page table entries corresponding to the
102/// virtual address in parameter `vaddr` and that match the address space identified by integer
103/// parameter `asid`, except for entries containing global mappings.
104#[inline]
105#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
106pub unsafe fn sfence_vma(vaddr: usize, asid: usize) {
107    asm!("sfence.vma {}, {}", in(reg) vaddr, in(reg) asid, options(nostack, preserves_flags));
108}
109
110/// Supervisor memory management fence for given virtual address
111///
112/// The fence orders only reads and writes made to leaf page table entries corresponding to
113/// the virtual address in parameter `vaddr`, for all address spaces.
114/// The fence also invalidates all address-translation cache entries that contain leaf page
115/// table entries corresponding to the virtual address in parameter `vaddr`, for all address spaces.
116#[inline]
117#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
118pub unsafe fn sfence_vma_vaddr(vaddr: usize) {
119    asm!("sfence.vma {}, x0", in(reg) vaddr, options(nostack, preserves_flags));
120}
121
122/// Supervisor memory management fence for given address space
123///
124/// The fence orders all reads and writes made to any level of the page tables,
125/// but only for the address space identified by integer parameter `asid`.
126///
127/// Accesses to global mappings are not ordered. The fence also invalidates all
128/// address-translation cache entries matching the address space identified by integer
129/// parameter `asid`, except for entries containing global mappings.
130#[inline]
131#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
132pub unsafe fn sfence_vma_asid(asid: usize) {
133    asm!("sfence.vma x0, {}", in(reg) asid, options(nostack, preserves_flags));
134}
135
136/// Supervisor memory management fence for all address spaces and virtual addresses
137///
138/// The fence orders all reads and writes made to any level of the page
139/// tables, for all address spaces. The fence also invalidates all address-translation cache entries,
140/// for all address spaces.
141#[inline]
142#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
143pub unsafe fn sfence_vma_all() {
144    asm!("sfence.vma", options(nostack, preserves_flags));
145}
146
147/// Invalidate supervisor translation cache for given virtual address and address space
148///
149/// This instruction invalidates any address-translation cache entries that an
150/// `SFENCE.VMA` instruction with the same values of `vaddr` and `asid` would invalidate.
151#[inline]
152#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
153pub unsafe fn sinval_vma(vaddr: usize, asid: usize) {
154    // asm!("sinval.vma {}, {}", in(reg) vaddr, in(reg) asid, options(nostack, preserves_flags));
155    asm!(
156        ".insn r 0x73, 0, 0x0B, x0, {}, {}",
157        in(reg) vaddr,
158        in(reg) asid,
159        options(nostack, preserves_flags)
160    );
161}
162
163/// Invalidate supervisor translation cache for given virtual address
164///
165/// This instruction invalidates any address-translation cache entries that an
166/// `SFENCE.VMA` instruction with the same values of `vaddr` and `asid` would invalidate.
167#[inline]
168#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
169pub unsafe fn sinval_vma_vaddr(vaddr: usize) {
170    asm!(
171        ".insn r 0x73, 0, 0x0B, x0, {}, x0",
172        in(reg) vaddr,
173        options(nostack, preserves_flags)
174    );
175}
176
177/// Invalidate supervisor translation cache for given address space
178///
179/// This instruction invalidates any address-translation cache entries that an
180/// `SFENCE.VMA` instruction with the same values of `vaddr` and `asid` would invalidate.
181#[inline]
182#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
183pub unsafe fn sinval_vma_asid(asid: usize) {
184    asm!(
185        ".insn r 0x73, 0, 0x0B, x0, x0, {}",
186        in(reg) asid,
187        options(nostack, preserves_flags)
188    );
189}
190
191/// Invalidate supervisor translation cache for all address spaces and virtual addresses
192///
193/// This instruction invalidates any address-translation cache entries that an
194/// `SFENCE.VMA` instruction with the same values of `vaddr` and `asid` would invalidate.
195#[inline]
196#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
197pub unsafe fn sinval_vma_all() {
198    asm!(
199        ".insn r 0x73, 0, 0x0B, x0, x0, x0",
200        options(nostack, preserves_flags)
201    );
202}
203
204/// Generates the `SFENCE.W.INVAL` instruction
205///
206/// This instruction guarantees that any previous stores already visible to the current RISC-V hart
207/// are ordered before subsequent `SINVAL.VMA` instructions executed by the same hart.
208#[inline]
209#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
210pub unsafe fn sfence_w_inval() {
211    // asm!("sfence.w.inval", options(nostack, preserves_flags));
212    asm!(
213        ".insn i 0x73, 0, x0, x0, 0x180",
214        options(nostack, preserves_flags)
215    );
216}
217
218/// Generates the `SFENCE.INVAL.IR` instruction
219///
220/// This instruction guarantees that any previous SINVAL.VMA instructions executed by the current hart
221/// are ordered before subsequent implicit references by that hart to the memory-management data structures.
222#[inline]
223#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
224pub unsafe fn sfence_inval_ir() {
225    // asm!("sfence.inval.ir", options(nostack, preserves_flags));
226    asm!(
227        ".insn i 0x73, 0, x0, x0, 0x181",
228        options(nostack, preserves_flags)
229    );
230}
231
232/// Loads virtual machine memory by signed byte integer
233///
234/// This instruction performs an explicit memory access as though `V=1`;
235/// i.e., with the address translation and protection, and the endianness, that apply to memory
236/// accesses in either VS-mode or VU-mode.
237///
238/// This function is unsafe for it accesses the virtual supervisor or user via a `HLV.B`
239/// instruction which is effectively a dereference to any memory address.
240#[inline]
241#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
242pub unsafe fn hlv_b(src: *const i8) -> i8 {
243    let value: i8;
244    asm!(
245        ".insn i 0x73, 0x4, {}, {}, 0x600",
246        lateout(reg) value,
247        in(reg) src,
248        options(readonly, nostack, preserves_flags)
249    );
250    value
251}
252
253/// Loads virtual machine memory by unsigned byte integer
254///
255/// This instruction performs an explicit memory access as though `V=1`;
256/// i.e., with the address translation and protection, and the endianness, that apply to memory
257/// accesses in either VS-mode or VU-mode.
258///
259/// This function is unsafe for it accesses the virtual supervisor or user via a `HLV.BU`
260/// instruction which is effectively a dereference to any memory address.
261#[inline]
262#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
263pub unsafe fn hlv_bu(src: *const u8) -> u8 {
264    let value: u8;
265    asm!(
266        ".insn i 0x73, 0x4, {}, {}, 0x601",
267        lateout(reg) value,
268        in(reg) src,
269        options(readonly, nostack, preserves_flags)
270    );
271    value
272}
273
274/// Loads virtual machine memory by signed half integer
275///
276/// This instruction performs an explicit memory access as though `V=1`;
277/// i.e., with the address translation and protection, and the endianness, that apply to memory
278/// accesses in either VS-mode or VU-mode.
279///
280/// This function is unsafe for it accesses the virtual supervisor or user via a `HLV.H`
281/// instruction which is effectively a dereference to any memory address.
282#[inline]
283#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
284pub unsafe fn hlv_h(src: *const i16) -> i16 {
285    let value: i16;
286    asm!(
287        ".insn i 0x73, 0x4, {}, {}, 0x640",
288        lateout(reg) value,
289        in(reg) src,
290        options(readonly, nostack, preserves_flags)
291    );
292    value
293}
294
295/// Loads virtual machine memory by unsigned half integer
296///
297/// This instruction performs an explicit memory access as though `V=1`;
298/// i.e., with the address translation and protection, and the endianness, that apply to memory
299/// accesses in either VS-mode or VU-mode.
300///
301/// This function is unsafe for it accesses the virtual supervisor or user via a `HLV.HU`
302/// instruction which is effectively a dereference to any memory address.
303#[inline]
304#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
305pub unsafe fn hlv_hu(src: *const u16) -> u16 {
306    let value: u16;
307    asm!(
308        ".insn i 0x73, 0x4, {}, {}, 0x641",
309        lateout(reg) value,
310        in(reg) src,
311        options(readonly, nostack, preserves_flags)
312    );
313    value
314}
315
316/// Accesses virtual machine instruction by unsigned half integer
317///
318/// This instruction performs an explicit memory access as though `V=1`;
319/// the memory being read must be executable in both stages of address translation,
320/// but read permission is not required.
321///
322/// This function is unsafe for it accesses the virtual supervisor or user via a `HLVX.HU`
323/// instruction which is effectively a dereference to any memory address.
324#[inline]
325#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
326pub unsafe fn hlvx_hu(src: *const u16) -> u16 {
327    let insn: u16;
328    asm!(
329        ".insn i 0x73, 0x4, {}, {}, 0x643",
330        lateout(reg) insn,
331        in(reg) src,
332        options(readonly, nostack, preserves_flags)
333    );
334    insn
335}
336
337/// Loads virtual machine memory by signed word integer
338///
339/// This instruction performs an explicit memory access as though `V=1`;
340/// i.e., with the address translation and protection, and the endianness, that apply to memory
341/// accesses in either VS-mode or VU-mode.
342///
343/// This function is unsafe for it accesses the virtual supervisor or user via a `HLV.W`
344/// instruction which is effectively a dereference to any memory address.
345#[inline]
346#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
347pub unsafe fn hlv_w(src: *const i32) -> i32 {
348    let value: i32;
349    asm!(
350        ".insn i 0x73, 0x4, {}, {}, 0x680",
351        lateout(reg) value,
352        in(reg) src,
353        options(readonly, nostack, preserves_flags)
354    );
355    value
356}
357
358/// Accesses virtual machine instruction by unsigned word integer
359///
360/// This instruction performs an explicit memory access as though `V=1`;
361/// the memory being read must be executable in both stages of address translation,
362/// but read permission is not required.
363///
364/// This function is unsafe for it accesses the virtual supervisor or user via a `HLVX.WU`
365/// instruction which is effectively a dereference to any memory address.
366#[inline]
367#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
368pub unsafe fn hlvx_wu(src: *const u32) -> u32 {
369    let insn: u32;
370    asm!(
371        ".insn i 0x73, 0x4, {}, {}, 0x683",
372        lateout(reg) insn,
373        in(reg) src,
374        options(readonly, nostack, preserves_flags)
375    );
376    insn
377}
378
379/// Stores virtual machine memory by byte integer
380///
381/// This instruction performs an explicit memory access as though `V=1`;
382/// i.e., with the address translation and protection, and the endianness, that apply to memory
383/// accesses in either VS-mode or VU-mode.
384///
385/// This function is unsafe for it accesses the virtual supervisor or user via a `HSV.B`
386/// instruction which is effectively a dereference to any memory address.
387#[inline]
388#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
389pub unsafe fn hsv_b(dst: *mut i8, src: i8) {
390    asm!(
391        ".insn r 0x73, 0x4, 0x31, x0, {}, {}",
392        in(reg) dst,
393        in(reg) src,
394        options(nostack, preserves_flags)
395    );
396}
397
398/// Stores virtual machine memory by half integer
399///
400/// This instruction performs an explicit memory access as though `V=1`;
401/// i.e., with the address translation and protection, and the endianness, that apply to memory
402/// accesses in either VS-mode or VU-mode.
403///
404/// This function is unsafe for it accesses the virtual supervisor or user via a `HSV.H`
405/// instruction which is effectively a dereference to any memory address.
406#[inline]
407#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
408pub unsafe fn hsv_h(dst: *mut i16, src: i16) {
409    asm!(
410        ".insn r 0x73, 0x4, 0x33, x0, {}, {}",
411        in(reg) dst,
412        in(reg) src,
413        options(nostack, preserves_flags)
414    );
415}
416
417/// Stores virtual machine memory by word integer
418///
419/// This instruction performs an explicit memory access as though `V=1`;
420/// i.e., with the address translation and protection, and the endianness, that apply to memory
421/// accesses in either VS-mode or VU-mode.
422///
423/// This function is unsafe for it accesses the virtual supervisor or user via a `HSV.W`
424/// instruction which is effectively a dereference to any memory address.
425#[inline]
426#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
427pub unsafe fn hsv_w(dst: *mut i32, src: i32) {
428    asm!(
429        ".insn r 0x73, 0x4, 0x35, x0, {}, {}",
430        in(reg) dst,
431        in(reg) src,
432        options(nostack, preserves_flags)
433    );
434}
435
436/// Hypervisor memory management fence for given guest virtual address and guest address space
437///
438/// Guarantees that any previous stores already visible to the current hart are ordered before all
439/// implicit reads by that hart done for VS-stage address translation for instructions that:
440/// - are subsequent to the `HFENCE.VVMA`, and
441/// - execute when `hgatp.VMID` has the same setting as it did when `HFENCE.VVMA` executed.
442///
443/// This fence specifies a single guest virtual address, and a single guest address-space identifier.
444#[inline]
445#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
446pub unsafe fn hfence_vvma(vaddr: usize, asid: usize) {
447    // asm!("hfence.vvma {}, {}", in(reg) vaddr, in(reg) asid, options(nostack, preserves_flags));
448    asm!(
449        ".insn r 0x73, 0, 0x11, x0, {}, {}",
450        in(reg) vaddr,
451        in(reg) asid,
452        options(nostack, preserves_flags)
453    );
454}
455
456/// Hypervisor memory management fence for given guest virtual address
457///
458/// Guarantees that any previous stores already visible to the current hart are ordered before all
459/// implicit reads by that hart done for VS-stage address translation for instructions that:
460/// - are subsequent to the `HFENCE.VVMA`, and
461/// - execute when `hgatp.VMID` has the same setting as it did when `HFENCE.VVMA` executed.
462///
463/// This fence specifies a single guest virtual address.
464#[inline]
465#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
466pub unsafe fn hfence_vvma_vaddr(vaddr: usize) {
467    asm!(
468        ".insn r 0x73, 0, 0x11, x0, {}, x0",
469        in(reg) vaddr,
470        options(nostack, preserves_flags)
471    );
472}
473
474/// Hypervisor memory management fence for given guest address space
475///
476/// Guarantees that any previous stores already visible to the current hart are ordered before all
477/// implicit reads by that hart done for VS-stage address translation for instructions that:
478/// - are subsequent to the `HFENCE.VVMA`, and
479/// - execute when `hgatp.VMID` has the same setting as it did when `HFENCE.VVMA` executed.
480///
481/// This fence specifies a single guest address-space identifier.
482#[inline]
483#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
484pub unsafe fn hfence_vvma_asid(asid: usize) {
485    asm!(
486        ".insn r 0x73, 0, 0x11, x0, x0, {}",
487        in(reg) asid,
488        options(nostack, preserves_flags)
489    );
490}
491
492/// Hypervisor memory management fence for all guest address spaces and guest virtual addresses
493///
494/// Guarantees that any previous stores already visible to the current hart are ordered before all
495/// implicit reads by that hart done for VS-stage address translation for instructions that:
496/// - are subsequent to the `HFENCE.VVMA`, and
497/// - execute when `hgatp.VMID` has the same setting as it did when `HFENCE.VVMA` executed.
498///
499/// This fence applies to any guest address spaces and guest virtual addresses.
500#[inline]
501#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
502pub unsafe fn hfence_vvma_all() {
503    asm!(
504        ".insn r 0x73, 0, 0x11, x0, x0, x0",
505        options(nostack, preserves_flags)
506    );
507}
508
509/// Hypervisor memory management fence for guest physical address and virtual machine
510///
511/// Guarantees that any previous stores already visible to the current hart are ordered before all implicit reads
512/// by that hart done for G-stage address translation for instructions that follow the HFENCE.GVMA.
513///
514/// This fence specifies a single guest physical address, **shifted right by 2 bits**, and a single virtual machine
515/// by virtual machine identifier (VMID).
516#[inline]
517#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
518pub unsafe fn hfence_gvma(gaddr: usize, vmid: usize) {
519    // asm!("hfence.gvma {}, {}", in(reg) gaddr, in(reg) vmid, options(nostack, preserves_flags));
520    asm!(
521        ".insn r 0x73, 0, 0x31, x0, {}, {}",
522        in(reg) gaddr,
523        in(reg) vmid,
524        options(nostack, preserves_flags)
525    );
526}
527
528/// Hypervisor memory management fence for guest physical address
529///
530/// Guarantees that any previous stores already visible to the current hart are ordered before all implicit reads
531/// by that hart done for G-stage address translation for instructions that follow the HFENCE.GVMA.
532///
533/// This fence specifies a single guest physical address; **the physical address should be shifted right by 2 bits**.
534#[inline]
535#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
536pub unsafe fn hfence_gvma_gaddr(gaddr: usize) {
537    asm!(
538        ".insn r 0x73, 0, 0x31, x0, {}, x0",
539        in(reg) gaddr,
540        options(nostack, preserves_flags)
541    );
542}
543
544/// Hypervisor memory management fence for given virtual machine
545///
546/// Guarantees that any previous stores already visible to the current hart are ordered before all implicit reads
547/// by that hart done for G-stage address translation for instructions that follow the HFENCE.GVMA.
548///
549/// This fence specifies a single virtual machine by virtual machine identifier (VMID).
550#[inline]
551#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
552pub unsafe fn hfence_gvma_vmid(vmid: usize) {
553    asm!(
554        ".insn r 0x73, 0, 0x31, x0, x0, {}",
555        in(reg) vmid,
556        options(nostack, preserves_flags)
557    );
558}
559
560/// Hypervisor memory management fence for all virtual machines and guest physical addresses
561///
562/// Guarantees that any previous stores already visible to the current hart are ordered before all implicit reads
563/// by that hart done for G-stage address translation for instructions that follow the HFENCE.GVMA.
564///
565/// This fence specifies all guest physical addresses and all virtual machines.
566#[inline]
567#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
568pub unsafe fn hfence_gvma_all() {
569    asm!(
570        ".insn r 0x73, 0, 0x31, x0, x0, x0",
571        options(nostack, preserves_flags)
572    );
573}
574
575/// Invalidate hypervisor translation cache for given guest virtual address and guest address space
576///
577/// This instruction invalidates any address-translation cache entries that an
578/// `HFENCE.VVMA` instruction with the same values of `vaddr` and `asid` would invalidate.
579///
580/// This fence specifies a single guest virtual address, and a single guest address-space identifier.
581#[inline]
582#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
583pub unsafe fn hinval_vvma(vaddr: usize, asid: usize) {
584    // asm!("hinval.vvma {}, {}", in(reg) vaddr, in(reg) asid, options(nostack, preserves_flags));
585    asm!(
586        ".insn r 0x73, 0, 0x13, x0, {}, {}",
587        in(reg) vaddr,
588        in(reg) asid,
589        options(nostack, preserves_flags)
590    );
591}
592
593/// Invalidate hypervisor translation cache for given guest virtual address
594///
595/// This instruction invalidates any address-translation cache entries that an
596/// `HFENCE.VVMA` instruction with the same values of `vaddr` and `asid` would invalidate.
597///
598/// This fence specifies a single guest virtual address.
599#[inline]
600#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
601pub unsafe fn hinval_vvma_vaddr(vaddr: usize) {
602    asm!(
603        ".insn r 0x73, 0, 0x13, x0, {}, x0",
604        in(reg) vaddr,
605        options(nostack, preserves_flags)
606    );
607}
608
609/// Invalidate hypervisor translation cache for given guest address space
610///
611/// This instruction invalidates any address-translation cache entries that an
612/// `HFENCE.VVMA` instruction with the same values of `vaddr` and `asid` would invalidate.
613///
614/// This fence specifies a single guest address-space identifier.
615#[inline]
616#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
617pub unsafe fn hinval_vvma_asid(asid: usize) {
618    asm!(
619        ".insn r 0x73, 0, 0x13, x0, x0, {}",
620        in(reg) asid,
621        options(nostack, preserves_flags)
622    );
623}
624
625/// Invalidate hypervisor translation cache for all guest address spaces and guest virtual addresses
626///
627/// This instruction invalidates any address-translation cache entries that an
628/// `HFENCE.VVMA` instruction with the same values of `vaddr` and `asid` would invalidate.
629///
630/// This fence applies to any guest address spaces and guest virtual addresses.
631#[inline]
632#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
633pub unsafe fn hinval_vvma_all() {
634    asm!(
635        ".insn r 0x73, 0, 0x13, x0, x0, x0",
636        options(nostack, preserves_flags)
637    );
638}
639
640/// Invalidate hypervisor translation cache for guest physical address and virtual machine
641///
642/// This instruction invalidates any address-translation cache entries that an
643/// `HFENCE.GVMA` instruction with the same values of `gaddr` and `vmid` would invalidate.
644///
645/// This fence specifies a single guest physical address, **shifted right by 2 bits**, and a single virtual machine
646/// by virtual machine identifier (VMID).
647#[inline]
648#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
649pub unsafe fn hinval_gvma(gaddr: usize, vmid: usize) {
650    // asm!("hinval.gvma {}, {}", in(reg) gaddr, in(reg) vmid, options(nostack, preserves_flags));
651    asm!(
652        ".insn r 0x73, 0, 0x33, x0, {}, {}",
653        in(reg) gaddr,
654        in(reg) vmid,
655        options(nostack, preserves_flags)
656    );
657}
658
659/// Invalidate hypervisor translation cache for guest physical address
660///
661/// This instruction invalidates any address-translation cache entries that an
662/// `HFENCE.GVMA` instruction with the same values of `gaddr` and `vmid` would invalidate.
663///
664/// This fence specifies a single guest physical address; **the physical address should be shifted right by 2 bits**.
665#[inline]
666#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
667pub unsafe fn hinval_gvma_gaddr(gaddr: usize) {
668    asm!(
669        ".insn r 0x73, 0, 0x33, x0, {}, x0",
670        in(reg) gaddr,
671        options(nostack, preserves_flags)
672    );
673}
674
675/// Invalidate hypervisor translation cache for given virtual machine
676///
677/// This instruction invalidates any address-translation cache entries that an
678/// `HFENCE.GVMA` instruction with the same values of `gaddr` and `vmid` would invalidate.
679///
680/// This fence specifies a single virtual machine by virtual machine identifier (VMID).
681#[inline]
682#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
683pub unsafe fn hinval_gvma_vmid(vmid: usize) {
684    asm!(
685        ".insn r 0x73, 0, 0x33, x0, x0, {}",
686        in(reg) vmid,
687        options(nostack, preserves_flags)
688    );
689}
690
691/// Invalidate hypervisor translation cache for all virtual machines and guest physical addresses
692///
693/// This instruction invalidates any address-translation cache entries that an
694/// `HFENCE.GVMA` instruction with the same values of `gaddr` and `vmid` would invalidate.
695///
696/// This fence specifies all guest physical addresses and all virtual machines.
697#[inline]
698#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
699pub unsafe fn hinval_gvma_all() {
700    asm!(
701        ".insn r 0x73, 0, 0x33, x0, x0, x0",
702        options(nostack, preserves_flags)
703    );
704}
705
706/// Reads the floating-point rounding mode register `frm`
707///
708/// According to "F" Standard Extension for Single-Precision Floating-Point, Version 2.2,
709/// the rounding mode field is defined as listed in the table below:
710///
711/// | Rounding Mode | Mnemonic | Meaning |
712/// |:-------------|:----------|:---------|
713/// | 000 | RNE | Round to Nearest, ties to Even |
714/// | 001 | RTZ | Round towards Zero |
715/// | 010 | RDN | Round Down (towards −∞) |
716/// | 011 | RUP | Round Up (towards +∞) |
717/// | 100 | RMM | Round to Nearest, ties to Max Magnitude |
718/// | 101 |     | _Reserved for future use._ |
719/// | 110 |     | _Reserved for future use._ |
720/// | 111 | DYN | In Rounding Mode register, _reserved_. |
721#[inline]
722#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
723pub fn frrm() -> u32 {
724    let value: u32;
725    unsafe {
726        asm!(
727            "frrm {}",
728            out(reg) value,
729            options(nomem, nostack, preserves_flags)
730        );
731    }
732    value
733}