aboutsummaryrefslogtreecommitdiff
path: root/model
diff options
context:
space:
mode:
authorPrashanth Mundkur <prashanth.mundkur@gmail.com>2019-01-30 14:53:58 -0800
committerPrashanth Mundkur <prashanth.mundkur@gmail.com>2019-01-30 14:53:58 -0800
commit2074a550c3e4020ebd051456aa764bba877c3e5c (patch)
tree4984362047d27df54312d70017f0b4062d853503 /model
parent3c4668386e284b69b988b2629b4dbe0074acdffd (diff)
downloadsail-riscv-2074a550c3e4020ebd051456aa764bba877c3e5c.zip
sail-riscv-2074a550c3e4020ebd051456aa764bba877c3e5c.tar.gz
sail-riscv-2074a550c3e4020ebd051456aa764bba877c3e5c.tar.bz2
Add some missed checks for 'N' to delegation logic.
Diffstat (limited to 'model')
-rw-r--r--model/riscv_sys_control.sail20
1 files changed, 13 insertions, 7 deletions
diff --git a/model/riscv_sys_control.sail b/model/riscv_sys_control.sail
index d8d9452..5b57fb8 100644
--- a/model/riscv_sys_control.sail
+++ b/model/riscv_sys_control.sail
@@ -113,7 +113,10 @@ val cancel_reservation = {ocaml: "Platform.cancel_reservation", c: "cancel_reser
function exception_delegatee(e : ExceptionType, p : Privilege) -> Privilege = {
let idx = num_of_ExceptionType(e);
let super = medeleg.bits()[idx];
- let user = sedeleg.bits()[idx];
+ /* if S-mode is absent, medeleg delegates to U-mode if 'N' is supported. */
+ let user = if haveSupMode()
+ then super & haveNExt() & sedeleg.bits()[idx]
+ else super & haveNExt();
let deleg = if haveUsrMode() & user then User
else if haveSupMode() & super then Supervisor
else Machine;
@@ -164,12 +167,14 @@ function processPending(xip : Minterrupts, xie : Minterrupts, xideleg : xlenbits
}
/* Given the current privilege level, iterate over privileges to get a
- * pending set for an enabled privilege.
+ * pending set for an enabled privilege. This is only called for M/U or
+ * M/S/U systems.
*
* We don't use the lowered views of {xie,xip} here, since the spec
* allows for example the M_Timer to be delegated to the U-mode.
*/
function getPendingSet(priv : Privilege) -> option((xlenbits, Privilege)) = {
+ assert(haveUsrMode());
let effective_pending = mip.bits() & mie.bits();
if effective_pending == EXTZ(0b0) then None() /* fast path */
else {
@@ -179,15 +184,16 @@ function getPendingSet(priv : Privilege) -> option((xlenbits, Privilege)) = {
*/
let mIE = priv != Machine | (priv == Machine & mstatus.MIE() == true);
let sIE = haveSupMode() & (priv == User | (priv == Supervisor & mstatus.SIE() == true));
- let uIE = haveUsrMode() & (priv == User & mstatus.UIE() == true);
+ let uIE = haveNExt() & (priv == User & mstatus.UIE() == true);
match processPending(mip, mie, mideleg.bits(), mIE) {
Ints_Empty() => None(),
Ints_Pending(p) => let r = (p, Machine) in Some(r),
Ints_Delegated(d) =>
if (~ (haveSupMode())) then {
- let r = (d, User) in Some(r)
+ if uIE then let r = (d, User) in Some(r)
+ else None()
} else {
- /* the delegated bits are pending for this privilege */
+ /* the delegated bits are pending for S-mode */
match processPending(Mk_Minterrupts(d), mie, sideleg.bits(), sIE) {
Ints_Empty() => None(),
Ints_Pending(p) => let r = (p, Supervisor) in Some(r),
@@ -204,10 +210,10 @@ function getPendingSet(priv : Privilege) -> option((xlenbits, Privilege)) = {
* handled (if any), and the privilege it should be handled at.
*/
function dispatchInterrupt(priv : Privilege) -> option((InterruptType, Privilege)) = {
- /* if we don't have different privilege levels, we don't need to check delegation.
+ /* If we don't have different privilege levels, we don't need to check delegation.
* Absence of U-mode implies absence of S-mode.
*/
- if (~ (haveUsrMode())) then {
+ if (~ (haveUsrMode())) | ((~ (haveSupMode())) & (~ (haveNExt())))
assert(priv == Machine);
let enabled_pending = mip.bits() & mie.bits();
match findPendingInterrupt(enabled_pending) {