diff options
author | Andrew Waterman <andrew@sifive.com> | 2017-02-08 14:16:08 -0800 |
---|---|---|
committer | Andrew Waterman <andrew@sifive.com> | 2017-02-08 14:16:08 -0800 |
commit | a30f1583002563aaae6a0e83c43300eaf81e646e (patch) | |
tree | 268f03b6d3fb941a15b9398abe84d10f65c49875 /riscv/mmu.h | |
parent | daaf28f7296c0a5f5c90fe6646a4f8a73a720af5 (diff) | |
download | spike-a30f1583002563aaae6a0e83c43300eaf81e646e.zip spike-a30f1583002563aaae6a0e83c43300eaf81e646e.tar.gz spike-a30f1583002563aaae6a0e83c43300eaf81e646e.tar.bz2 |
Encode VM type in sptbr, not mstatus
https://github.com/riscv/riscv-isa-manual/issues/4
Also, refactor gdbserver code to not duplicate VM decoding logic.
Diffstat (limited to 'riscv/mmu.h')
-rw-r--r-- | riscv/mmu.h | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/riscv/mmu.h b/riscv/mmu.h index 34bcf99..9365457 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -260,4 +260,35 @@ private: friend class processor_t; }; +struct vm_info { + int levels; + int idxbits; + int ptesize; + reg_t ptbase; +}; + +inline vm_info decode_vm_info(int xlen, reg_t prv, reg_t sptbr) +{ + if (prv == PRV_M) { + return {0, 0, 0, 0}; + } else if (prv <= PRV_S && xlen == 32) { + switch (get_field(sptbr, SPTBR32_MODE)) { + case SPTBR_MODE_OFF: return {0, 0, 0, 0}; + case SPTBR_MODE_SV32: return {2, 10, 4, (sptbr & SPTBR32_PPN) << PGSHIFT}; + default: abort(); + } + } else if (prv <= PRV_S && xlen == 64) { + switch (get_field(sptbr, SPTBR64_MODE)) { + case SPTBR_MODE_OFF: return {0, 0, 0, 0}; + case SPTBR_MODE_SV39: return {3, 9, 8, (sptbr & SPTBR64_PPN) << PGSHIFT}; + case SPTBR_MODE_SV48: return {4, 9, 8, (sptbr & SPTBR64_PPN) << PGSHIFT}; + case SPTBR_MODE_SV57: return {5, 9, 8, (sptbr & SPTBR64_PPN) << PGSHIFT}; + case SPTBR_MODE_SV64: return {6, 9, 8, (sptbr & SPTBR64_PPN) << PGSHIFT}; + default: abort(); + } + } else { + abort(); + } +} + #endif |