arch-riscv: fix the wrong cause register setting
authorCui Jin <cuijin7@huawei.com>
Thu, 31 Dec 2020 08:17:35 +0000 (16:17 +0800)
committerCui Jin <cuijin7@huawei.com>
Wed, 6 Jan 2021 01:18:15 +0000 (01:18 +0000)
The most significant bit should be set based on interrupt or
exception. I assume in current RV64 implementation the bit should
be 63rd, rather than 31st. This causes interrupt handler to get
invalid cause code.

Minor bug is for the mpie is suppossed to be set to the value of
old mie.

The fix is verified in FS.

Jira Issue: https://gem5.atlassian.net/browse/GEM5-858

Change-Id: I1cc166c254b35f5c1acb3f5774c43149c61cc37a
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/38755
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
src/arch/riscv/faults.cc

index ac4c5823ed9d39848d04fc08210302aa193ef0c3..5ac2a3c7908894093786efc49811bad32660371f 100644 (file)
@@ -113,7 +113,7 @@ RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
             tval = MISCREG_MTVAL;
 
             status.mpp = pp;
-            status.mpie = status.sie;
+            status.mpie = status.mie;
             status.mie = 0;
             break;
           default:
@@ -122,8 +122,12 @@ RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
         }
 
         // Set fault cause, privilege, and return PC
-        tc->setMiscReg(cause,
-                       (isInterrupt() << (sizeof(uint64_t) * 4 - 1)) | _code);
+        // Interrupt is indicated on the MSB of cause (bit 63 in RV64)
+        uint64_t _cause = _code;
+        if (isInterrupt()) {
+           _cause |= (1L << 63);
+        }
+        tc->setMiscReg(cause, _cause);
         tc->setMiscReg(epc, tc->instAddr());
         tc->setMiscReg(tval, trap_value());
         tc->setMiscReg(MISCREG_PRV, prv);