#define MSTATUS_MPRV 0x00020000
#define MSTATUS_PUM 0x00040000
#define MSTATUS_MXR 0x00080000
+#define MSTATUS_TVM 0x00100000
+#define MSTATUS_TW 0x00200000
+#define MSTATUS_TSR 0x00400000
#define MSTATUS32_SD 0x80000000
#define MSTATUS64_SD 0x8000000000000000
-require_privilege(PRV_S);
+require_privilege(get_field(STATE.mstatus, MSTATUS_TVM) ? PRV_M : PRV_S);
MMU.flush_tlb();
-require_privilege(PRV_S);
+require_privilege(get_field(STATE.mstatus, MSTATUS_TSR) ? PRV_M : PRV_S);
set_pc_and_serialize(p->get_state()->sepc);
reg_t s = STATE.mstatus;
reg_t prev_prv = get_field(s, MSTATUS_SPP);
+require_privilege(get_field(STATE.mstatus, MSTATUS_TW) ? PRV_M : PRV_S);
set_pc_and_serialize(npc);
reg_t mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE
| MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_PUM
- | MSTATUS_MPP | MSTATUS_MXR | (ext ? MSTATUS_XS : 0);
+ | MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TW | MSTATUS_TVM
+ | MSTATUS_TSR | (ext ? MSTATUS_XS : 0);
state.mstatus = (state.mstatus & ~mask) | (val & mask);
if (max_xlen > xlen)
return state.scause | ((state.scause >> (max_xlen-1)) << (xlen-1));
return state.scause;
- case CSR_SPTBR: return state.sptbr;
+ case CSR_SPTBR:
+ if (get_field(state.mstatus, MSTATUS_TVM))
+ require_privilege(PRV_M);
+ return state.sptbr;
case CSR_SSCRATCH: return state.sscratch;
case CSR_MSTATUS: return state.mstatus;
case CSR_MIP: return state.mip;