From a27ce59a39ec8fa20a3c4e9fa53e9b3db1199e91 Mon Sep 17 00:00:00 2001 From: Alec Roelke Date: Sun, 10 Jun 2018 18:41:34 -0400 Subject: [PATCH] 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/faults.hh | 77 +++++++++++----------------------- src/arch/riscv/isa/decoder.isa | 44 ++++++++++++++++--- src/arch/riscv/registers.hh | 47 +++++++++++++++++++++ 3 files changed, 110 insertions(+), 58 deletions(-) diff --git a/src/arch/riscv/faults.hh b/src/arch/riscv/faults.hh index 6d3fdebbe..d9cb44c3d 100644 --- a/src/arch/riscv/faults.hh +++ b/src/arch/riscv/faults.hh @@ -34,8 +34,10 @@ #ifndef __ARCH_RISCV_FAULTS_HH__ #define __ARCH_RISCV_FAULTS_HH__ +#include #include +#include "arch/riscv/isa.hh" #include "arch/riscv/registers.hh" #include "cpu/thread_context.hh" #include "sim/faults.hh" @@ -71,59 +73,12 @@ enum ExceptionCode : MiscReg { AMO_PAGE = 15 }; -/** - * These fields are specified in the RISC-V Instruction Set Manual, Volume II, - * v1.10, accessible at www.riscv.org. in Figure 3.7. The main register that - * uses these fields is the MSTATUS register, which is shadowed by two others - * accessible at lower privilege levels (SSTATUS and USTATUS) that can't see - * the fields for higher privileges. - */ -BitUnion64(STATUS) - Bitfield<63> sd; - Bitfield<35, 34> sxl; - Bitfield<33, 32> uxl; - Bitfield<22> tsr; - Bitfield<21> tw; - Bitfield<20> tvm; - Bitfield<19> mxr; - Bitfield<18> sum; - Bitfield<17> mprv; - Bitfield<16, 15> xs; - Bitfield<14, 13> fs; - Bitfield<12, 11> mpp; - Bitfield<8> spp; - Bitfield<7> mpie; - Bitfield<5> spie; - Bitfield<4> upie; - Bitfield<3> mie; - Bitfield<1> sie; - Bitfield<0> uie; -EndBitUnion(STATUS) - -/** - * These fields are specified in the RISC-V Instruction Set Manual, Volume II, - * v1.10 in Figures 3.11 and 3.12, accessible at www.riscv.org. Both the MIP - * and MIE registers have the same fields, so accesses to either should use - * this bit union. - */ -BitUnion64(INTERRUPT) - Bitfield<11> mei; - Bitfield<9> sei; - Bitfield<8> uei; - Bitfield<7> mti; - Bitfield<5> sti; - Bitfield<4> uti; - Bitfield<3> msi; - Bitfield<1> ssi; - Bitfield<0> usi; -EndBitUnion(INTERRUPT) - class RiscvFault : public FaultBase { protected: const FaultName _name; - bool _interrupt; - const ExceptionCode _code; + const bool _interrupt; + ExceptionCode _code; RiscvFault(FaultName n, bool i, ExceptionCode c) : _name(n), _interrupt(i), _code(c) @@ -254,12 +209,28 @@ class BreakpointFault : public RiscvFault class SyscallFault : public RiscvFault { public: - // TODO: replace ECALL_USER with the appropriate privilege level of the - // caller - SyscallFault() : RiscvFault("System call", false, ECALL_USER) {} + SyscallFault(PrivilegeMode prv) + : RiscvFault("System call", false, ECALL_USER) + { + switch (prv) { + case PRV_U: + _code = ECALL_USER; + break; + case PRV_S: + _code = ECALL_SUPER; + break; + case PRV_M: + _code = ECALL_MACHINE; + break; + default: + panic("Unknown privilege mode %d.", prv); + break; + } + } + void invokeSE(ThreadContext *tc, const StaticInstPtr &inst) override; }; } // namespace RiscvISA -#endif // __ARCH_RISCV_FAULTS_HH__ \ No newline at end of file +#endif // __ARCH_RISCV_FAULTS_HH__ 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 { diff --git a/src/arch/riscv/registers.hh b/src/arch/riscv/registers.hh index e1d57ee53..bd95cf821 100644 --- a/src/arch/riscv/registers.hh +++ b/src/arch/riscv/registers.hh @@ -583,6 +583,53 @@ const std::map CSRData = { {CSR_DSCRATCH, {"dscratch", MISCREG_DSCRATCH}} }; +/** + * These fields are specified in the RISC-V Instruction Set Manual, Volume II, + * v1.10, accessible at www.riscv.org. in Figure 3.7. The main register that + * uses these fields is the MSTATUS register, which is shadowed by two others + * accessible at lower privilege levels (SSTATUS and USTATUS) that can't see + * the fields for higher privileges. + */ +BitUnion64(STATUS) + Bitfield<63> sd; + Bitfield<35, 34> sxl; + Bitfield<33, 32> uxl; + Bitfield<22> tsr; + Bitfield<21> tw; + Bitfield<20> tvm; + Bitfield<19> mxr; + Bitfield<18> sum; + Bitfield<17> mprv; + Bitfield<16, 15> xs; + Bitfield<14, 13> fs; + Bitfield<12, 11> mpp; + Bitfield<8> spp; + Bitfield<7> mpie; + Bitfield<5> spie; + Bitfield<4> upie; + Bitfield<3> mie; + Bitfield<1> sie; + Bitfield<0> uie; +EndBitUnion(STATUS) + +/** + * These fields are specified in the RISC-V Instruction Set Manual, Volume II, + * v1.10 in Figures 3.11 and 3.12, accessible at www.riscv.org. Both the MIP + * and MIE registers have the same fields, so accesses to either should use + * this bit union. + */ +BitUnion64(INTERRUPT) + Bitfield<11> mei; + Bitfield<9> sei; + Bitfield<8> uei; + Bitfield<7> mti; + Bitfield<5> sti; + Bitfield<4> uti; + Bitfield<3> msi; + Bitfield<1> ssi; + Bitfield<0> usi; +EndBitUnion(INTERRUPT) + const off_t MXL_OFFSET = (sizeof(MiscReg) * 8 - 2); const off_t SXL_OFFSET = 34; const off_t UXL_OFFSET = 32; -- 2.30.2