arch-riscv: Handle the exception following the privilege mode set
Change-Id: I4867941ec286fe485e01db848b8c7357488f6cf4
This commit is contained in:
@@ -67,6 +67,7 @@ RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
|
||||
if (FullSystem) {
|
||||
PrivilegeMode pp = (PrivilegeMode)tc->readMiscReg(MISCREG_PRV);
|
||||
PrivilegeMode prv = PRV_M;
|
||||
MISA misa = tc->readMiscRegNoEffect(MISCREG_ISA);
|
||||
STATUS status = tc->readMiscReg(MISCREG_STATUS);
|
||||
|
||||
// According to riscv-privileged-v1.11, if a NMI occurs at the middle
|
||||
@@ -82,18 +83,18 @@ RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
|
||||
} else if (isInterrupt()) {
|
||||
if (pp != PRV_M &&
|
||||
bits(tc->readMiscReg(MISCREG_MIDELEG), _code) != 0) {
|
||||
prv = PRV_S;
|
||||
prv = (misa.rvs) ? PRV_S : ((misa.rvn) ? PRV_U : PRV_M);
|
||||
}
|
||||
if (pp == PRV_U &&
|
||||
if (pp == PRV_U && misa.rvs && misa.rvn &&
|
||||
bits(tc->readMiscReg(MISCREG_SIDELEG), _code) != 0) {
|
||||
prv = PRV_U;
|
||||
}
|
||||
} else {
|
||||
if (pp != PRV_M &&
|
||||
bits(tc->readMiscReg(MISCREG_MEDELEG), _code) != 0) {
|
||||
prv = PRV_S;
|
||||
prv = (misa.rvs) ? PRV_S : ((misa.rvn) ? PRV_U : PRV_M);
|
||||
}
|
||||
if (pp == PRV_U &&
|
||||
if (pp == PRV_U && misa.rvs && misa.rvn &&
|
||||
bits(tc->readMiscReg(MISCREG_SEDELEG), _code) != 0) {
|
||||
prv = PRV_U;
|
||||
}
|
||||
|
||||
@@ -69,21 +69,41 @@ class Interrupts : public BaseInterrupts
|
||||
{
|
||||
INTERRUPT mask = 0;
|
||||
STATUS status = tc->readMiscReg(MISCREG_STATUS);
|
||||
INTERRUPT mideleg = tc->readMiscReg(MISCREG_MIDELEG);
|
||||
INTERRUPT sideleg = tc->readMiscReg(MISCREG_SIDELEG);
|
||||
MISA misa = tc->readMiscRegNoEffect(MISCREG_ISA);
|
||||
INTERRUPT mideleg = 0;
|
||||
if (misa.rvs || misa.rvn) {
|
||||
mideleg = tc->readMiscReg(MISCREG_MIDELEG);
|
||||
}
|
||||
INTERRUPT sideleg = 0;
|
||||
if (misa.rvs && misa.rvn) {
|
||||
sideleg = tc->readMiscReg(MISCREG_SIDELEG);
|
||||
}
|
||||
PrivilegeMode prv = (PrivilegeMode)tc->readMiscReg(MISCREG_PRV);
|
||||
switch (prv) {
|
||||
case PRV_U:
|
||||
mask.mei = (!sideleg.mei) | (sideleg.mei & status.uie);
|
||||
mask.mti = (!sideleg.mti) | (sideleg.mti & status.uie);
|
||||
mask.msi = (!sideleg.msi) | (sideleg.msi & status.uie);
|
||||
mask.sei = (!sideleg.sei) | (sideleg.sei & status.uie);
|
||||
mask.sti = (!sideleg.sti) | (sideleg.sti & status.uie);
|
||||
mask.ssi = (!sideleg.ssi) | (sideleg.ssi & status.uie);
|
||||
// status.uie is always 0 if misa.rvn is disabled
|
||||
if (misa.rvs) {
|
||||
mask.mei = (!sideleg.mei) | (sideleg.mei & status.uie);
|
||||
mask.mti = (!sideleg.mti) | (sideleg.mti & status.uie);
|
||||
mask.msi = (!sideleg.msi) | (sideleg.msi & status.uie);
|
||||
mask.sei = (!sideleg.sei) | (sideleg.sei & status.uie);
|
||||
mask.sti = (!sideleg.sti) | (sideleg.sti & status.uie);
|
||||
mask.ssi = (!sideleg.ssi) | (sideleg.ssi & status.uie);
|
||||
} else {
|
||||
// According to the RISC-V privilege spec v1.10, if the
|
||||
// S privilege mode is not implemented and user-trap
|
||||
// support, setting mideleg/medeleg bits will delegate the
|
||||
// trap to U-mode trap handler
|
||||
mask.mei = (!mideleg.mei) | (mideleg.mei & status.uie);
|
||||
mask.mti = (!mideleg.mti) | (mideleg.mti & status.uie);
|
||||
mask.msi = (!mideleg.msi) | (mideleg.msi & status.uie);
|
||||
mask.sei = mask.sti = mask.ssi = 0;
|
||||
}
|
||||
if (status.uie)
|
||||
mask.uei = mask.uti = mask.usi = 1;
|
||||
break;
|
||||
case PRV_S:
|
||||
// status.sie is always 0 if misa.rvn is disabled
|
||||
mask.mei = (!mideleg.mei) | (mideleg.mei & status.sie);
|
||||
mask.mti = (!mideleg.mti) | (mideleg.mti & status.sie);
|
||||
mask.msi = (!mideleg.msi) | (mideleg.msi & status.sie);
|
||||
|
||||
@@ -528,6 +528,24 @@ ISA::readMiscReg(RegIndex idx)
|
||||
default:
|
||||
panic("%s: Unknown _rvType: %d", name(), (int)_rvType);
|
||||
}
|
||||
// Check status.mpp
|
||||
MISA misa = readMiscRegNoEffect(MISCREG_ISA);
|
||||
switch(status.mpp) {
|
||||
case PRV_U:
|
||||
status.mpp = (misa.rvu) ? PRV_U : PRV_M;
|
||||
break;
|
||||
case PRV_S:
|
||||
if (misa.rvs)
|
||||
status.mpp = PRV_S;
|
||||
else
|
||||
status.mpp = (misa.rvu) ? PRV_U : PRV_M;
|
||||
break;
|
||||
case PRV_M:
|
||||
break;
|
||||
default:
|
||||
status.mpp = (misa.rvu) ? PRV_U : PRV_M;
|
||||
}
|
||||
|
||||
setMiscRegNoEffect(idx, status);
|
||||
|
||||
return readMiscRegNoEffect(idx);
|
||||
|
||||
@@ -4595,6 +4595,12 @@ decode QUADRANT default Unknown::unknown() {
|
||||
xc->pcState());
|
||||
}}, IsSerializeAfter, IsNonSpeculative, No_OpClass);
|
||||
0x2: uret({{
|
||||
MISA misa = xc->readMiscReg(MISCREG_ISA);
|
||||
if (!misa.rvn) {
|
||||
return std::make_shared<IllegalInstFault>(
|
||||
"sret can't execute without N systems",
|
||||
machInst);
|
||||
}
|
||||
STATUS status = xc->readMiscReg(MISCREG_STATUS);
|
||||
status.uie = status.upie;
|
||||
status.upie = 1;
|
||||
@@ -4604,6 +4610,12 @@ decode QUADRANT default Unknown::unknown() {
|
||||
}
|
||||
0x8: decode RS2 {
|
||||
0x2: sret({{
|
||||
MISA misa = xc->readMiscReg(MISCREG_ISA);
|
||||
if (!misa.rvs) {
|
||||
return std::make_shared<IllegalInstFault>(
|
||||
"sret can't execute without RVS",
|
||||
machInst);
|
||||
}
|
||||
STATUS status = xc->readMiscReg(MISCREG_STATUS);
|
||||
auto pm = (PrivilegeMode)xc->readMiscReg(
|
||||
MISCREG_PRV);
|
||||
@@ -4623,11 +4635,12 @@ decode QUADRANT default Unknown::unknown() {
|
||||
}
|
||||
}}, IsSerializeAfter, IsNonSpeculative, IsReturn);
|
||||
0x5: wfi({{
|
||||
MISA misa = xc->readMiscReg(MISCREG_ISA);
|
||||
STATUS status = xc->readMiscReg(MISCREG_STATUS);
|
||||
auto pm = (PrivilegeMode)xc->readMiscReg(
|
||||
MISCREG_PRV);
|
||||
if (pm == PRV_U ||
|
||||
(pm == PRV_S && status.tw == 1)) {
|
||||
if (misa.rvs && (pm == PRV_U ||
|
||||
(pm == PRV_S && status.tw == 1))) {
|
||||
return std::make_shared<IllegalInstFault>(
|
||||
"wfi in user mode or TW enabled",
|
||||
machInst);
|
||||
@@ -4647,6 +4660,12 @@ decode QUADRANT default Unknown::unknown() {
|
||||
IsSerializeAfter, No_OpClass);
|
||||
}
|
||||
0x9: sfence_vma({{
|
||||
MISA misa = xc->readMiscReg(MISCREG_ISA);
|
||||
if (!misa.rvs) {
|
||||
return std::make_shared<IllegalInstFault>(
|
||||
"sfence_vma can't execute without RVS",
|
||||
machInst);
|
||||
}
|
||||
STATUS status = xc->readMiscReg(MISCREG_STATUS);
|
||||
auto pm = (PrivilegeMode)xc->readMiscReg(MISCREG_PRV);
|
||||
if (pm == PRV_U || (pm == PRV_S && status.tvm == 1)) {
|
||||
|
||||
Reference in New Issue
Block a user