satp
Supervisor Address Translation and Protection
Controls the translation mode in (H)S-mode and U-mode, and holds the current ASID and page table base pointer.
Attributes
Requirement |
|||
|---|---|---|---|
Defining extensions |
|
||
CSR Address |
0x180 |
||
Length |
* 32 when CSR[mstatus].SXL == 0 * 64 when CSR[mstatus].SXL == 1 |
||
Privilege Mode |
S |
Format
This CSR format changes dynamically.
Field Summary
| Name | Location | Type | Reset Value |
|---|---|---|---|
* 31 when CSR[mstatus].SXL == 0 * 63:60 when CSR[mstatus].SXL == 1 |
RW-R |
0 |
|
* 30:22 when CSR[mstatus].SXL == 0 * 59:44 when CSR[mstatus].SXL == 1 |
RW-R |
UNDEFINED_LEGAL |
|
* 21:0 when CSR[mstatus].SXL == 0 * 43:0 when CSR[mstatus].SXL == 1 |
RW-R |
UNDEFINED_LEGAL |
Fields
MODE
- Location
-
-
31 when CSR[mstatus].SXL == 0
-
63:60 when CSR[mstatus].SXL == 1
-
- Description
-
Translation Mode
Controls the current translation mode according to the table below.
| Value | Name | Description |
|---|---|---|
0 |
Bare |
No translation → virtual address == physical address <%- if ext?(:Sv39) -%> |
8 |
Sv39 |
39-bit virtual address translation <%- end -%> <%- if ext?(:Sv48) -%> |
9 |
Sv48 |
48-bit virtual address translation <%- end -%> <%- if ext?(:Sv57) -%> |
10 |
Sv57 |
57-bit virtual address translation <%- end -%> |
Any other value shall be ignored on a write.
- Type
-
RW-R
- Reset value
-
0
ASID
- Location
-
-
30:22 when CSR[mstatus].SXL == 0
-
59:44 when CSR[mstatus].SXL == 1
-
- Description
-
Address Space ID
- Type
-
RW-R
- Reset value
-
UNDEFINED_LEGAL
PPN
- Location
-
-
21:0 when CSR[mstatus].SXL == 0
-
43:0 when CSR[mstatus].SXL == 1
-
- Description
-
Physical Page Number
The physical address of the active root page table is PPN << 12.
Can only hold values that correspond to a valid page table base, which will be implementation-dependent.
- Type
-
RW-R
- Reset value
-
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 (SATP_MODE_BARE && (csr_value.MODE == 0)) {
# In Bare, ASID and PPN must be zero, else the entire write is ignored
if (csr_value.ASID == 0 && csr_value.PPN == 0) {
if (CSR[satp].MODE != 0) {
# changes *to* Bare mode take effect immediately without needing sfence.vma
# thus, an implicit sfence.vma occurs now
VmaOrderType order_type;
order_type.global = true;
order_pgtbl_writes_before_vmafence(order_type);
invalidate_translations(order_type);
order_pgtbl_reads_after_vmafence(order_type);
}
return csr_value.MODE;
} else {
return UNDEFINED_LEGAL_DETERMINISTIC;
}
}
else if (implemented?(ExtensionName::Sv32) && csr_value.MODE == 1) {
if (CSR[satp].MODE == 0) {
# changes *from* Bare mode take effect immediately without needing sfence.vma
# thus, an implicit sfence.vma occurs now
VmaOrderType order_type;
order_type.global = true;
order_pgtbl_writes_before_vmafence(order_type);
invalidate_translations(order_type);
order_pgtbl_reads_after_vmafence(order_type);
}
return csr_value.MODE;
}else if (implemented?(ExtensionName::Sv39) && csr_value.MODE == 8) {
if (CSR[satp].MODE == 0) {
# changes *from* Bare mode take effect immediately without needing sfence.vma
# thus, an implicit sfence.vma occurs now
VmaOrderType order_type;
order_type.global = true;
order_pgtbl_writes_before_vmafence(order_type);
invalidate_translations(order_type);
order_pgtbl_reads_after_vmafence(order_type);
}
return csr_value.MODE;
}
else if (implemented?(ExtensionName::Sv48) && csr_value.MODE == 9) {
if (CSR[satp].MODE == 0) {
# changes *from* Bare mode take effect immediately without needing sfence.vma
# thus, an implicit sfence.vma occurs now
VmaOrderType order_type;
order_type.global = true;
order_pgtbl_writes_before_vmafence(order_type);
invalidate_translations(order_type);
order_pgtbl_reads_after_vmafence(order_type);
}
return csr_value.MODE;
}
else if (implemented?(ExtensionName::Sv57) && csr_value.MODE == 10) {
if (CSR[satp].MODE == 0) {
# changes *from* Bare mode take effect immediately without needing sfence.vma
# thus, an implicit sfence.vma occurs now
VmaOrderType order_type;
order_type.global = true;
order_pgtbl_writes_before_vmafence(order_type);
invalidate_translations(order_type);
order_pgtbl_reads_after_vmafence(order_type);
}
return csr_value.MODE;
}
else {
return UNDEFINED_LEGAL_DETERMINISTIC;
}
ASID = if (csr_value.MODE == 0) {
# 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 {
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) {
# 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 {
# unrestricted
return csr_value.PPN;
}