aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2017-11-09 18:45:48 -0800
committerAndrew Waterman <andrew@sifive.com>2017-11-09 18:45:48 -0800
commite0e462ddd40e5799ab3b2670b4f85aadf860b205 (patch)
tree78120bab7db00ca45012f5810c32adcfadff9131
parent8feec3d0a5f6b98e4e5b333d2f2c78f7da1ec1f5 (diff)
downloadspike-e0e462ddd40e5799ab3b2670b4f85aadf860b205.zip
spike-e0e462ddd40e5799ab3b2670b4f85aadf860b205.tar.gz
spike-e0e462ddd40e5799ab3b2670b4f85aadf860b205.tar.bz2
MPP is now WARL
-rw-r--r--riscv/processor.cc28
-rw-r--r--riscv/processor.h1
2 files changed, 23 insertions, 6 deletions
diff --git a/riscv/processor.cc b/riscv/processor.cc
index d23c1ea..ebae384 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -193,13 +193,23 @@ static int xlen_to_uxl(int xlen)
abort();
}
-void processor_t::set_privilege(reg_t prv)
+reg_t processor_t::legalize_privilege(reg_t prv)
{
assert(prv <= PRV_M);
- if (prv == PRV_H)
- prv = PRV_U;
+
+ if (!supports_extension('U'))
+ return PRV_M;
+
+ if (prv == PRV_H || !supports_extension('S'))
+ return PRV_U;
+
+ return prv;
+}
+
+void processor_t::set_privilege(reg_t prv)
+{
mmu->flush_tlb();
- state.prv = prv;
+ state.prv = legalize_privilege(prv);
}
void processor_t::enter_debug_mode(uint8_t cause)
@@ -328,11 +338,16 @@ void processor_t::set_csr(int which, reg_t val)
mmu->flush_tlb();
reg_t mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE
- | MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM
- | MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TW | MSTATUS_TVM
+ | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM
+ | MSTATUS_MXR | MSTATUS_TW | MSTATUS_TVM
| MSTATUS_TSR | MSTATUS_UXL | MSTATUS_SXL |
(ext ? MSTATUS_XS : 0);
+ reg_t requested_mpp = legalize_privilege(get_field(val, MSTATUS_MPP));
+ state.mstatus = set_field(state.mstatus, MSTATUS_MPP, requested_mpp);
+ if (supports_extension('S'))
+ mask |= MSTATUS_SPP;
+
state.mstatus = (state.mstatus & ~mask) | (val & mask);
bool dirty = (state.mstatus & MSTATUS_FS) == MSTATUS_FS;
@@ -343,6 +358,7 @@ void processor_t::set_csr(int which, reg_t val)
state.mstatus = set_field(state.mstatus, MSTATUS64_SD, dirty);
state.mstatus = set_field(state.mstatus, MSTATUS_UXL, xlen_to_uxl(max_xlen));
+ state.mstatus = set_field(state.mstatus, MSTATUS_UXL, xlen_to_uxl(max_xlen));
state.mstatus = set_field(state.mstatus, MSTATUS_SXL, xlen_to_uxl(max_xlen));
// U-XLEN == S-XLEN == M-XLEN
xlen = max_xlen;
diff --git a/riscv/processor.h b/riscv/processor.h
index d80da4f..16416a4 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -184,6 +184,7 @@ public:
if (ext >= 'a' && ext <= 'z') ext += 'A' - 'a';
return ext >= 'A' && ext <= 'Z' && ((isa >> (ext - 'A')) & 1);
}
+ reg_t legalize_privilege(reg_t);
void set_privilege(reg_t);
void yield_load_reservation() { state.load_reservation = (reg_t)-1; }
void update_histogram(reg_t pc);