vsatp
Virtual Supervisor Address Translation and Protection
The vsatp register is a VSXLEN-bit read/write register that is VS-mode’s version of supervisor register satp. When V=1, vsatp substitutes for the usual satp, so instructions that normally read or modify satp actually access vsatp instead. vsatp controls VS-stage address translation, the first stage of two-stage translation for guest virtual addresses.
The vsatp register is considered active for the purposes of the address-translation algorithm unless the effective privilege mode is U and hstatus.HU=0. However, even when vsatp is active, VS-stage page-table entries' A bits must not be set as a result of speculative execution, unless the effective privilege mode is VS or VU.
In particular, virtual-machine load/store (hlv, 'hlvx', or 'hsv') instructions that are
misspeculatively executed must not cause VS-stage A bits to be set.
|
Attributes
Defining Extension |
H, version >= H@1.0.0 |
|---|---|
CSR Address |
0x280 |
Virtual CSR Address |
0x180 |
Length |
* 32 when CSR[hstatus].VSXL == 0 * 64 when CSR[hstatus].VSXL == 1 |
Privilege Mode |
VS |
Format
This CSR format changes dynamically.
Field Summary
| Name | Location | Type | Reset Value |
|---|---|---|---|
* 31 when CSR[hstatus].VSXL == 0 * 63:60 when CSR[hstatus].VSXL == 1 |
RW-R |
UNDEFINED_LEGAL |
|
* 30:22 when CSR[hstatus].VSXL == 0 * 59:44 when CSR[hstatus].VSXL == 1 |
RW-R |
UNDEFINED_LEGAL |
|
* 21:0 when CSR[hstatus].VSXL == 0 * 43:0 when CSR[hstatus].VSXL == 1 |
RW-R |
UNDEFINED_LEGAL |
Software write
This CSR may store a value that is different from what software attempts to write.
When a software write occurs (e.g., through csrrw), the following determines the written value:
MODE = if (csr_value.MODE == 0) {
if (virtual_mode?() || IGNORE_INVALID_VSATP_MODE_WRITES_WHEN_V_EQ_ZERO) {
# In Bare, ASID and PPN must be zero, else the entire write is ignored
if (csr_value.ASID == 0 && csr_value.PPN == 0) {
return csr_value.MODE;
} else {
return UNDEFINED_LEGAL_DETERMINISTIC;
}
} else {
return UNDEFINED_LEGAL_DETERMINISTIC;
}
}
else if (implemented?(ExtensionName::Sv39) && csr_value.MODE == 8) { return csr_value.MODE; }
else if (implemented?(ExtensionName::Sv48) && csr_value.MODE == 9) { return csr_value.MODE; }
else if (implemented?(ExtensionName::Sv57) && csr_value.MODE == 10) { return csr_value.MODE; }
else {
return UNDEFINED_LEGAL_DETERMINISTIC;
}
ASID = if (csr_value.MODE == 0) {
if (virtual_mode?() || IGNORE_INVALID_VSATP_MODE_WRITES_WHEN_V_EQ_ZERO) {
# when MODE == Bare, PPN and ASID must be zero
if (csr_value.ASID == 0 && csr_value.PPN == 0) {
return csr_value.ASID;
} else {
return UNDEFINED_LEGAL_DETERMINISTIC;
}
} else {
return UNDEFINED_LEGAL_DETERMINISTIC;
}
} else {
XReg shamt = ((xlen() == 32) || (CSR[mstatus].SXL == $bits(XRegWidth::XLEN32))) ? 9 : 16;
XReg all_ones = ((MXLEN'1 << shamt) - 1);
XReg largest_allowed_asid = (MXLEN'1 << shamt) - 1;
if (csr_value.ASID == all_ones) {
# the specification states that if all 1's are written to the ASID field, then
# you must return the largest asid
return largest_allowed_asid;
} else if (csr_value.ASID > largest_allowed_asid) {
# ... but is silent on what happens on any other illegal value
return UNDEFINED_LEGAL_DETERMINISTIC;
} else {
# unrestricted
return csr_value.ASID;
}
}
PPN = if (csr_value.MODE == 0) {
if (virtual_mode?() || IGNORE_INVALID_VSATP_MODE_WRITES_WHEN_V_EQ_ZERO) {
# when MODE == Bare, PPN and ASID must be zero
if (csr_value.ASID == 0 && csr_value.PPN == 0) {
return csr_value.PPN;
} else {
return UNDEFINED_LEGAL_DETERMINISTIC;
}
} else {
return UNDEFINED_LEGAL_DETERMINISTIC;
}
} else {
# unrestricted
return csr_value.PPN;
}