diff --git a/riscv/insns/dret.h b/riscv/insns/dret.h index 0540c519..2abcc7d9 100644 --- a/riscv/insns/dret.h +++ b/riscv/insns/dret.h @@ -1,7 +1,6 @@ require(STATE.debug_mode); set_pc_and_serialize(STATE.dpc->read()); -p->set_privilege(STATE.dcsr->prv); -p->set_virt(STATE.dcsr->v); +p->set_privilege(STATE.dcsr->prv, STATE.dcsr->v); if (STATE.prv < PRV_M) STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MPRV); diff --git a/riscv/insns/mnret.h b/riscv/insns/mnret.h index bc695106..30f10818 100644 --- a/riscv/insns/mnret.h +++ b/riscv/insns/mnret.h @@ -11,5 +11,4 @@ if (prev_prv != PRV_M) { } s = set_field(s, MNSTATUS_NMIE, 1); STATE.mnstatus->write(s); -p->set_privilege(prev_prv); -p->set_virt(prev_virt); +p->set_privilege(prev_prv, prev_virt); diff --git a/riscv/insns/mret.h b/riscv/insns/mret.h index 5198b8fc..f5f86a2b 100644 --- a/riscv/insns/mret.h +++ b/riscv/insns/mret.h @@ -10,5 +10,4 @@ s = set_field(s, MSTATUS_MPIE, 1); s = set_field(s, MSTATUS_MPP, p->extension_enabled('U') ? PRV_U : PRV_M); s = set_field(s, MSTATUS_MPV, 0); p->put_csr(CSR_MSTATUS, s); -p->set_privilege(prev_prv); -p->set_virt(prev_virt); +p->set_privilege(prev_prv, prev_virt); diff --git a/riscv/insns/sret.h b/riscv/insns/sret.h index 82c238ba..4c7305d0 100644 --- a/riscv/insns/sret.h +++ b/riscv/insns/sret.h @@ -24,5 +24,4 @@ if (!STATE.v) { STATE.mstatus->write(set_field(STATE.mstatus->read(), MSTATUS_MPRV, 0)); } -p->set_privilege(prev_prv); -p->set_virt(prev_virt); +p->set_privilege(prev_prv, prev_virt); diff --git a/riscv/processor.cc b/riscv/processor.cc index 4bcf41f4..ef985a18 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -714,11 +714,13 @@ reg_t processor_t::legalize_privilege(reg_t prv) return prv; } -void processor_t::set_privilege(reg_t prv) +void processor_t::set_privilege(reg_t prv, bool virt) { mmu->flush_tlb(); state.prev_prv = state.prv; + state.prev_v = state.v; state.prv = legalize_privilege(prv); + state.v = virt && state.prv != PRV_M; } const char* processor_t::get_privilege_string() @@ -741,31 +743,11 @@ const char* processor_t::get_privilege_string() abort(); } -void processor_t::set_virt(bool virt) -{ - reg_t tmp, mask; - - if (state.prv == PRV_M) - return; - - /* - * Ideally, we should flush TLB here but we don't need it because - * set_virt() is always used in conjucter with set_privilege() and - * set_privilege() will flush TLB unconditionally. - * - * The virtualized sstatus register also relies on this TLB flush, - * since changing V might change sstatus.MXR and sstatus.SUM. - */ - state.prev_v = state.v; - state.v = virt; -} - void processor_t::enter_debug_mode(uint8_t cause) { state.debug_mode = true; state.dcsr->write_cause_and_prv(cause, state.prv, state.v); - set_virt(false); - set_privilege(PRV_M); + set_privilege(PRV_M, false); state.dpc->write(state.pc); state.pc = DEBUG_ROM_ENTRY; in_wfi = false; @@ -832,8 +814,7 @@ void processor_t::take_trap(trap_t& t, reg_t epc) s = set_field(s, MSTATUS_SPP, state.prv); s = set_field(s, MSTATUS_SIE, 0); state.sstatus->write(s); - set_virt(true); - set_privilege(PRV_S); + set_privilege(PRV_S, true); } else if (state.prv <= PRV_S && bit < max_xlen && ((hsdeleg >> bit) & 1)) { // Handle the trap in HS-mode reg_t vector = (state.nonvirtual_stvec->read() & 1) && interrupt ? 4 * bit : 0; @@ -857,8 +838,7 @@ void processor_t::take_trap(trap_t& t, reg_t epc) s = set_field(s, HSTATUS_GVA, t.has_gva()); state.hstatus->write(s); } - set_virt(false); - set_privilege(PRV_S); + set_privilege(PRV_S, false); } else { // Handle the trap in M-mode const reg_t vector = (state.mtvec->read() & 1) && interrupt ? 4 * bit : 0; @@ -882,8 +862,7 @@ void processor_t::take_trap(trap_t& t, reg_t epc) s = set_field(s, MSTATUS_GVA, t.has_gva()); state.mstatus->write(s); if (state.mstatush) state.mstatush->write(s >> 32); // log mstatush change - set_virt(false); - set_privilege(PRV_M); + set_privilege(PRV_M, false); } } diff --git a/riscv/processor.h b/riscv/processor.h index 26230145..1b008089 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -269,8 +269,7 @@ public: throw trap_instruction_address_misaligned(state.v, pc, 0, 0); } reg_t legalize_privilege(reg_t); - void set_privilege(reg_t); - void set_virt(bool); + void set_privilege(reg_t, bool); const char* get_privilege_string(); void update_histogram(reg_t pc); const disassembler_t* get_disassembler() { return disassembler; }