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