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 <alec.roelke@gmail.com> Reviewed-by: Jason Lowe-Power <jason@lowepower.com> Reviewed-by: Robert Scheffel <robert.scheffel1@tu-dresden.de>
This commit is contained in:
@@ -34,8 +34,10 @@
|
||||
#ifndef __ARCH_RISCV_FAULTS_HH__
|
||||
#define __ARCH_RISCV_FAULTS_HH__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#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__
|
||||
#endif // __ARCH_RISCV_FAULTS_HH__
|
||||
|
||||
@@ -1708,16 +1708,50 @@ decode QUADRANT default Unknown::unknown() {
|
||||
format SystemOp {
|
||||
0x0: decode FUNCT12 {
|
||||
0x0: ecall({{
|
||||
fault = make_shared<SyscallFault>();
|
||||
fault = make_shared<SyscallFault>(
|
||||
(PrivilegeMode)xc->readMiscReg(MISCREG_PRV));
|
||||
}}, IsSerializeAfter, IsNonSpeculative, IsSyscall,
|
||||
No_OpClass);
|
||||
0x1: ebreak({{
|
||||
fault = make_shared<BreakpointFault>(xc->pcState());
|
||||
}}, IsSerializeAfter, IsNonSpeculative, No_OpClass);
|
||||
0x100: eret({{
|
||||
fault = make_shared<UnimplementedFault>("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<IllegalInstFault>(
|
||||
"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<IllegalInstFault>(
|
||||
"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 {
|
||||
|
||||
@@ -583,6 +583,53 @@ const std::map<int, CSRMetadata> 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;
|
||||
|
||||
Reference in New Issue
Block a user