aboutsummaryrefslogtreecommitdiff
path: root/riscv/insns/sret.h
diff options
context:
space:
mode:
Diffstat (limited to 'riscv/insns/sret.h')
-rw-r--r--riscv/insns/sret.h11
1 files changed, 9 insertions, 2 deletions
diff --git a/riscv/insns/sret.h b/riscv/insns/sret.h
index be837a3..bc063e6 100644
--- a/riscv/insns/sret.h
+++ b/riscv/insns/sret.h
@@ -1,10 +1,17 @@
require_extension('S');
require_privilege(get_field(STATE.mstatus, MSTATUS_TSR) ? PRV_M : PRV_S);
-set_pc_and_serialize(p->get_state()->sepc);
+if (STATE.v && get_field(STATE.hstatus, HSTATUS_VTSR))
+ require_novirt();
+reg_t next_pc = (STATE.v) ? p->get_state()->vsepc : p->get_state()->sepc;
+set_pc_and_serialize(next_pc);
reg_t s = STATE.mstatus;
reg_t prev_prv = get_field(s, MSTATUS_SPP);
s = set_field(s, MSTATUS_SIE, get_field(s, MSTATUS_SPIE));
s = set_field(s, MSTATUS_SPIE, 1);
s = set_field(s, MSTATUS_SPP, PRV_U);
-p->set_privilege(prev_prv);
p->set_csr(CSR_MSTATUS, s);
+p->set_privilege(prev_prv);
+if (!STATE.v) {
+ reg_t prev_virt = get_field(STATE.hstatus, HSTATUS_SPV);
+ p->set_virt(prev_virt);
+}