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
Defining Extension |
|
||||
---|---|---|---|---|---|
CSR Address |
0x180 |
||||
Length |
|
||||
Privilege Mode |
S |
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) { if (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::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 = ((1 << shamt) - 1); XReg largest_allowed_asid = (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; }