arch-riscv: Handle the exception following the privilege mode set

Change-Id: I4867941ec286fe485e01db848b8c7357488f6cf4
This commit is contained in:
Roger Chang
2023-10-31 16:33:34 +08:00
parent d56801c240
commit 9a0c671cce
4 changed files with 72 additions and 14 deletions

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)) {