mod.rs - source
Description: Source of the Rust file `library/core/src/../../stdarch/crates/core_arch/src/riscv_shared/mod.rs`.

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