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}