From a27ce59a39ec8fa20a3c4e9fa53e9b3db1199e91 Mon Sep 17 00:00:00 2001 From: Alec Roelke Date: Sun, 10 Jun 2018 18:41:34 -0400 Subject: arch-riscv: Add xret instructions This patch adds the uret, sret, and mret instructions for use with returning from user-, supervisor-, and machine-level code, respectively. These instructions read the STATUS register to determine the previous privilege level and modify it to re-enable interrupts at the old privilege level. These instructions can only be executed at the corresponding privilege level or higher. Change-Id: I6125c31cb2fdcc3f83eca86910519e81ffbbbfc9 Reviewed-on: https://gem5-review.googlesource.com/11136 Maintainer: Alec Roelke Reviewed-by: Jason Lowe-Power Reviewed-by: Robert Scheffel --- src/arch/riscv/isa/decoder.isa | 44 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) (limited to 'src/arch/riscv/isa/decoder.isa') diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index a0e3ad19d..0c1d7726c 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -1708,16 +1708,50 @@ decode QUADRANT default Unknown::unknown() { format SystemOp { 0x0: decode FUNCT12 { 0x0: ecall({{ - fault = make_shared(); + fault = make_shared( + (PrivilegeMode)xc->readMiscReg(MISCREG_PRV)); }}, IsSerializeAfter, IsNonSpeculative, IsSyscall, No_OpClass); 0x1: ebreak({{ fault = make_shared(xc->pcState()); }}, IsSerializeAfter, IsNonSpeculative, No_OpClass); - 0x100: eret({{ - fault = make_shared("eret", - machInst); - }}, No_OpClass); + 0x2: uret({{ + STATUS status = xc->readMiscReg(MISCREG_STATUS); + status.uie = status.upie; + status.upie = 1; + xc->setMiscReg(MISCREG_STATUS, status); + NPC = xc->readMiscReg(MISCREG_UEPC); + }}, IsReturn); + 0x102: sret({{ + if (xc->readMiscReg(MISCREG_PRV) == PRV_U) { + fault = make_shared( + "sret in user mode", machInst); + NPC = NPC; + } else { + STATUS status = xc->readMiscReg(MISCREG_STATUS); + xc->setMiscReg(MISCREG_PRV, status.spp); + status.sie = status.spie; + status.spie = 1; + status.spp = PRV_U; + xc->setMiscReg(MISCREG_STATUS, status); + NPC = xc->readMiscReg(MISCREG_SEPC); + } + }}, IsReturn); + 0x302: mret({{ + if (xc->readMiscReg(MISCREG_PRV) != PRV_M) { + fault = make_shared( + "mret at lower privilege", machInst); + NPC = NPC; + } else { + STATUS status = xc->readMiscReg(MISCREG_STATUS); + xc->setMiscReg(MISCREG_PRV, status.mpp); + status.mie = status.mpie; + status.mpie = 1; + status.mpp = PRV_U; + xc->setMiscReg(MISCREG_STATUS, status); + NPC = xc->readMiscReg(MISCREG_MEPC); + } + }}, IsReturn); } } format CSROp { -- cgit v1.2.3