Nested virtualization is the ability of a hypervisor to run another hypervisor as a guest. RISC-V nested virtualization requires an L0 hypervisor (running in hypervisor-mode) to trap-and-emulate the RISC-V H-extension [priv_v1.12] functionality (such as CSR accesses, HFENCE instructions, HLV/HSV instructions, etc.) for the L1 hypervisor (running in virtualized supervisor-mode).
The SBI nested acceleration extension defines a shared memory based interface between the SBI implementation (or L0 hypervisor) and the supervisor software (or L1 hypervisor) which allows both to collaboratively reduce traps taken by the L0 hypervisor for emulating RISC-V H-extension functionality. The nested acceleration shared memory allows the L1 hypervisor to batch multiple RISC-V H-extension CSR accesses and HFENCE requests which are then emulated by the L0 hypervisor upon an explicit synchronization SBI call.
Note
|
The M-mode firmware should not implement the SBI nested acceleration extension if the underlying platform has the RISC-V H-extension implemented in hardware. |
This SBI extension defines optional features which MUST be discovered by the supervisor software (or L1 hypervisor) before using the corresponding SBI functions. Each nested acceleration feature is assigned a unique ID which is an unsigned 32-bit integer. The Nested acceleration features below provides a list of all nested acceleration features.
Feature ID | Feature Name | Description |
---|---|---|
0x00000000 |
SBI_NACL_FEAT_SYNC_CSR |
Synchronize CSR |
0x00000001 |
SBI_NACL_FEAT_SYNC_HFENCE |
Synchronize HFENCE |
0x00000002 |
SBI_NACL_FEAT_SYNC_SRET |
Synchronize SRET |
0x00000003 |
SBI_NACL_FEAT_AUTOSWAP_CSR |
Autoswap CSR |
> 0x00000003 |
RESERVED |
Reserved for future use |
To use the SBI nested acceleration extension, the supervisor software
(or L1 hypervisor) MUST set up a nested acceleration shared memory
physical address for each virtual hart at boot-time. The physical base
address of the nested acceleration shared memory MUST be 4096 bytes
(i.e. page) aligned and the size of the nested acceleration shared
memory must be 4096 + (1024 * (XLEN / 8))
bytes. The
Nested acceleration shared memory layout below shows the layout of nested
acceleration shared memory.
Name | Offset | Size (bytes) | Description |
---|---|---|---|
Scratch space |
0x00000000 |
4096 |
Nested acceleration feature specific data. |
CSR space |
0x00001000 |
|
An array of 1024 XLEN-bit words where each word corresponds to a possible RISC-V H-extension CSR defined in the Table 2.1 of the RISC-V privileged specification [priv_v1.12]. |
Any nested acceleration feature may define the contents of the scratch space shown in the Nested acceleration shared memory layout above if required.
The contents of the CSR space shown in the Nested acceleration shared memory layout
above is an array of RISC-V H-extension CSR values where CSR <x>
is at
index <i> = ((<x> & 0xc00) >> 2) | (<x> & 0xff)
. The SBI implementation
(or L0 hypervisor) MUST update the CSR space whenever the state of any
RISC-V H-extension CSR changes unless some nested acceleration feature
defines a different behaviour. The Nested acceleration H-extension CSR index ranges
below shows CSR space index ranges for all possible 1024 RISC-V
H-extension CSRs.
H-extension CSR address | SBI NACL CSR space index | |||
---|---|---|---|---|
[11:10] |
[9:8] |
[7:4] |
Hex Range |
Hex Range |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The synchronize CSR feature describes the ability of the SBI implementation (or L0 hypervisor) to allow supervisor software (or L1 hypervisor) to write RISC-V H-extension CSRs using the CSR space.
This nested acceleration feature defines the scratch space offset range
0x0F80 - 0x0FFF
(128 bytes) as nested CSR dirty bitmap. The nested CSR
dirty bitmap contains 1-bit for each possible RISC-V H-extension CSR.
To write a CSR <x>
in nested acceleration shared memory, the supervisor
software (or L1 hypervisor) MUST do the following:
-
Compute
<i> = ((<x> & 0xc00) >> 2) | (<x> & 0xff)
-
Write a new CSR value at word with index
<i>
in the CSR space -
Set the
<i>
bit in the nested CSR dirty bitmap
To synchronize a CSR <x>
, the SBI implementation (or L0 hypervisor)
MUST do the following:
-
Compute
<i> = ((<x> & 0xc00) >> 2) | (<x> & 0xff)
-
If bit
<i>
is not set in the nested CSR dirty bitmap then goto step 5 -
Emulate write to CSR
<x>
with the new CSR value taken from the word with index<i>
in the CSR space -
Clear the
<i>
bit in the nested CSR dirty bitmap -
Write back the latest CSR value of CSR
<x>
to the word with index<i>
in the CSR space
When synchronizing multiple CSRs, if the value of a CSR <y>
depends on the
value of some other CSR <x>
then the SBI implementation (or L0 hypervisor)
MUST synchronize CSR <x>
before CSR <y>
. For example, the value of CSR
hip
depends on the value of the CSR hvip
, which means hvip
is emulated
and written first, followed by hip
.
The synchronize HFENCE feature describes the ability of the SBI implementation (or L0 hypervisor) to allow supervisor software (or L1 hypervisor) to issue HFENCE using the scratch space.
This nested acceleration feature defines the scratch space offset range
0x0800 - 0x0F7F
(1920 bytes) as an array of nested HFENCE entries. The
total number of nested HFENCE entries are 3840 / XLEN
where each nested
HFENCE entry consists of four XLEN-bit words.
A nested HFENCE entry is equivalent to an HFENCE over a range of guest
addresses. The Nested HFENCE entry format below shows the nested
HFENCE entry format whereas Nested HFENCE entry types below provides
a list of nested HFENCE entry types. Upon an explicit synchronize HFENCE
request from supervisor software (or L1 hypervisor), the SBI implementation
(or L0 hypervisor) will process nested HFENCE entries with the Config.Pending
bit set. After processing pending nested HFENCE entries, the SBI implementation
(or L0 hypervisor) will clear the Config.Pending
bit of these entries.
Word | Name | Encoding |
---|---|---|
0 |
Config |
Config information about the nested HFENCE entry |
1 |
Page_Number |
Page address right shifted by |
2 |
Reserved |
Reserved for future use and must be zero |
3 |
Page_Count |
Number of pages to invalidate |
Type | Name | Description |
---|---|---|
0 |
GVMA |
Invalidate a guest physical address range across
all VMIDs. The |
1 |
GVMA_ALL |
Invalidate all guest physical addresses across
all VMIDs. The |
2 |
GVMA_VMID |
Invalidate a guest physical address range for a
particular VMID. The |
3 |
GVMA_VMID_ALL |
Invalidate all guest physical addresses for a
particular VMID. The |
4 |
VVMA |
Invalidate a guest virtual address range for a
particular VMID. The |
5 |
VVMA_ALL |
Invalidate all guest virtual addresses for a
particular VMID. The |
6 |
VVMA_ASID |
Invalidate a guest virtual address range for a particular VMID and ASID. |
7 |
VVMA_ASID_ALL |
Invalidate all guest virtual addresses for a
particular VMID and ASID. The |
> 7 |
Reserved |
Reserved for future use. |
To add a nested HFENCE entry, the supervisor software (or L1 hypervisor) MUST do the following:
-
Find an unused nested HFENCE entry with
Config.Pending == 0
-
Update the
Page_Number
andPage_Count
words in the nested HFENCE entry -
Update the
Config
word in the nested HFENCE entry such thatConfig.Pending
bit is set
To synchronize a nested HFENCE entry, the SBI implementation (or L0 hypervisor) MUST do the following:
-
If
Config.Pending == 0
then do nothing and skip below steps -
Process HFENCE based on details in the nested HFENCE entry
-
Clear the
Config.Pending
bit in the nested HFENCE entry
The synchronize SRET feature describes the ability of the SBI implementation (or L0 hypervisor) to do synchronization of CSRs and HFENCEs in the nested acceleration shared memory for the supervisor software (or L1 hypervisor) along with SRET emulation.
This nested acceleration feature defines the scratch space offset range
0x0000 - 0x01FF
(512 bytes) as nested SRET context. The
Nested SRET context below shows contents of the nested SRET context.
Offset | Name | Encoding |
---|---|---|
|
Reserved |
Reserved for future use and must be zero |
|
X1 |
Value to be restored in GPR X1 |
|
X2 |
Value to be restored in GPR X2 |
|
X3 |
Value to be restored in GPR X3 |
|
X4 |
Value to be restored in GPR X4 |
|
X5 |
Value to be restored in GPR X5 |
|
X6 |
Value to be restored in GPR X6 |
|
X7 |
Value to be restored in GPR X7 |
|
X8 |
Value to be restored in GPR X8 |
|
X9 |
Value to be restored in GPR X9 |
|
X10 |
Value to be restored in GPR X10 |
|
X11 |
Value to be restored in GPR X11 |
|
X12 |
Value to be restored in GPR X12 |
|
X13 |
Value to be restored in GPR X13 |
|
X14 |
Value to be restored in GPR X14 |
|
X15 |
Value to be restored in GPR X15 |
|
X16 |
Value to be restored in GPR X16 |
|
X17 |
Value to be restored in GPR X17 |
|
X18 |
Value to be restored in GPR X18 |
|
X19 |
Value to be restored in GPR X19 |
|
X20 |
Value to be restored in GPR X20 |
|
X21 |
Value to be restored in GPR X21 |
|
X22 |
Value to be restored in GPR X22 |
|
X23 |
Value to be restored in GPR X23 |
|
X24 |
Value to be restored in GPR X24 |
|
X25 |
Value to be restored in GPR X25 |
|
X26 |
Value to be restored in GPR X26 |
|
X27 |
Value to be restored in GPR X27 |
|
X28 |
Value to be restored in GPR X28 |
|
X29 |
Value to be restored in GPR X29 |
|
X30 |
Value to be restored in GPR X30 |
|
X31 |
Value to be restored in GPR X31 |
|
Reserved |
Reserved for future use |
Before sending a synchronize SRET request to the SBI implementation (or
L0 hypervisor), the supervisor software (or L1 hypervisor) MUST write
the GPR X<i>
values to be restored at offset <i> * (XLEN / 8)
of the
nested SRET context.
Upon a synchronize SRET request from the supervisor software (or L1 hypervisor), the SBI implementation (or L0 hypervisor) MUST do the following:
-
If SBI_NACL_FEAT_SYNC_CSR feature is available then
-
All RISC-V H-extension CSRs implemented by the SBI implementation (or L0 hypervisor) are synchronized as described in the [_feature_synchronize_csr_id_0]. This is equivalent to the SBI call
sbi_nacl_sync_csr(-1UL)
.
-
-
If SBI_NACL_FEAT_SYNC_HFENCE feature is available then
-
All nested HFENCE entries are synchronized as described in the [_feature_synchronize_hfence_id_1]. This is equivalent to the SBI call
sbi_nacl_sync_hfence(-1UL)
.
-
-
Restore GPR
X<i>
registers from the nested SRET context. -
Emulate the SRET instruction as defined by the RISC-V Privilege specification [priv_v1.12].
The autoswap CSR feature describes the ability of the SBI implementation (or L0 hypervisor) to automatically swap certain RISC-V H-extension CSR values from the nested acceleration shared memory in the following situations:
-
Before emulating the SRET instruction for a synchronized SRET request from the supervisor software (or L1 hypervisor).
-
After supervisor (or L1) virtualization state changes from ON to OFF.
Note
|
The supervisor software (or L1 hypervisor) should use the autoswap CSR feature in conjunction with the synchronize SRET feature. |
This nested acceleration feature defines the scratch space offset
range 0x0200 - 0x027F
(128 bytes) as nested autoswap context. The
Nested autoswap context below shows contents of the nested
autoswap context.
Offset | Name | Encoding |
---|---|---|
|
Autoswap_Flags |
Autoswap flags |
|
HSTATUS |
Value to be swapped with |
|
Reserved |
Reserved for future use. |
To enable automatic swapping of CSRs from the nested autoswap context, the supervisor software (or L1 hypervisor) MUST do the following:
-
Write the
HSTATUS
swap value in the nested autoswap context. -
Set
Autoswap_Flags.HSTATUS
bit in the nested autoswap context.
To swap CSRs from the nested autoswap context, the SBI implementation (or L0 hypervisor) MUST do the following:
-
If
Autoswap_Flags.HSTATUS
bit is set in the nested autoswap context then swap the supervisorHSTATUS
CSR value with theHSTATUS
value in the nested autoswap context.
struct sbiret sbi_nacl_probe_feature(uint32_t feature_id)
Probe a nested acceleration feature. This is a mandatory function of the
SBI nested acceleration extension. The feature_id
parameter specifies the
nested acceleration feature to probe. Nested acceleration features provides
a list of possible feature IDs.
This function always returns SBI_SUCCESS in sbiret.error
. It returns 0
in sbiret.value
if the given feature_id
is not available, or 1
in
sbiret.value
if it is available.
struct sbiret sbi_nacl_set_shmem(unsigned long shmem_phys_lo,
unsigned long shmem_phys_hi,
unsigned long flags)
Set and enable the shared memory for nested acceleration on the calling hart. This is a mandatory function of the SBI nested acceleration extension.
If both shmem_phys_lo
and shmem_phys_hi
parameters are not all-ones
bitwise then shmem_phys_lo
specifies the lower XLEN bits and shmem_phys_hi
specifies the upper XLEN bits of the shared memory physical base address.
shmem_phys_lo
MUST be 4096 bytes (i.e. page) aligned and the size of the
shared memory must be 4096 + (XLEN * 128)
bytes.
If both shmem_phys_lo
and shmem_phys_hi
parameters are all-ones bitwise
then the nested acceleration features are disabled.
The flags
parameter is reserved for future use and must be zero.
The possible error codes returned in sbiret.error
are shown in
NACL Set Shared Memory Errors.
Error code | Description |
---|---|
SBI_SUCCESS |
Shared memory was set or cleared successfully. |
SBI_ERR_INVALID_PARAM |
The |
SBI_ERR_INVALID_ADDRESS |
The shared memory pointed to by the |
struct sbiret sbi_nacl_sync_csr(unsigned long csr_num)
Synchronize CSRs in the nested acceleration shared memory. This is an
optional function which is only available if the SBI_NACL_FEAT_SYNC_CSR
feature is available. The parameter csr_num
specifies the set of
RISC-V H-extension CSRs to be synchronized.
If csr_num
is all-ones bitwise then all RISC-V H-extension CSRs
implemented by the SBI implementation (or L0 hypervisor) are
synchronized as described in the [_feature_synchronize_csr_id_0].
If (csr_num & 0x300) == 0x200
and csr_num < 0x1000
then only a
single RISC-V H-extension CSR specified by the csr_num
parameter
is synchronized as described in the [_feature_synchronize_csr_id_0].
The possible error codes returned in sbiret.error
are shown in
NACL Synchronize CSR Errors.
Error code | Description |
---|---|
SBI_SUCCESS |
CSRs synchronized successfully. |
SBI_ERR_NOT_SUPPORTED |
SBI_NACL_FEAT_SYNC_CSR feature is not available. |
SBI_ERR_INVALID_PARAM |
|
SBI_ERR_NO_SHMEM |
Nested acceleration shared memory not available. |
struct sbiret sbi_nacl_sync_hfence(unsigned long entry_index)
Synchronize HFENCEs in the nested acceleration shared memory. This is an
optional function which is only available if the SBI_NACL_FEAT_SYNC_HFENCE
feature is available. The parameter entry_index
specifies the set of
nested HFENCE entries to be synchronized.
If entry_index
is all-ones bitwise then all nested HFENCE entries are
synchronized as described in the [_feature_synchronize_hfence_id_1].
If entry_index < (3840 / XLEN)
then only a single nested HFENCE entry
specified by the entry_index
parameter is synchronized as described
in the [_feature_synchronize_hfence_id_1].
The possible error codes returned in sbiret.error
are shown in
NACL Synchronize HFENCE Errors.
Error code | Description |
---|---|
SBI_SUCCESS |
HFENCEs synchronized successfully. |
SBI_ERR_NOT_SUPPORTED |
SBI_NACL_FEAT_SYNC_HFENCE feature is not available. |
SBI_ERR_INVALID_PARAM |
|
SBI_ERR_NO_SHMEM |
Nested acceleration shared memory not available. |
struct sbiret sbi_nacl_sync_sret(void)
Synchronize CSRs and HFENCEs in the nested acceleration shared memory and emulate the SRET instruction. This is an optional function which is only available if the SBI_NACL_FEAT_SYNC_SRET feature is available.
This function is used by supervisor software (or L1 hypervisor) to do a synchronize SRET request and the SBI implementation (or L0 hypervisor) MUST handle it as described in the [_feature_synchronize_sret_id_2].
This function does not return upon success and the possible error codes
returned in sbiret.error
upon failure are shown in
NACL Synchronize SRET Errors.
Error code | Description |
---|---|
SBI_ERR_NOT_SUPPORTED |
SBI_NACL_FEAT_SYNC_SRET feature is not available. |
SBI_ERR_NO_SHMEM |
Nested acceleration shared memory not available. |