#
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}