From 7e22ae973e0c4b4fc0368130481ba1a74c5d0276 Mon Sep 17 00:00:00 2001
From: David Harris <david_harris@hmc.edu>
Date: Sun, 4 Jul 2021 13:20:29 -0400
Subject: [PATCH] Fixed MPRV and MXR checks in TLB

---
 wally-pipelined/src/ifu/ifu.sv                |  3 +-
 wally-pipelined/src/lsu/lsu.sv                |  3 +-
 wally-pipelined/src/mmu/mmu.sv                |  3 +-
 wally-pipelined/src/mmu/tlb.sv                | 29 ++++++++++---------
 wally-pipelined/src/privileged/csr.sv         |  3 +-
 wally-pipelined/src/privileged/privileged.sv  |  6 ++--
 .../src/wally/wallypipelinedhart.sv           |  3 +-
 7 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv
index 714119e6..65f8a9b8 100644
--- a/wally-pipelined/src/ifu/ifu.sv
+++ b/wally-pipelined/src/ifu/ifu.sv
@@ -70,7 +70,8 @@ module ifu (
   input logic [`XLEN-1:0]     PageTableEntryF,
   input logic [1:0] 	      PageTypeF,
   input logic [`XLEN-1:0]     SATP_REGW,
-  input logic 		      STATUS_MXR, STATUS_SUM, 
+  input logic              STATUS_MXR, STATUS_SUM, STATUS_MPRV,
+  input logic  [1:0]       STATUS_MPP,
   input logic 		      ITLBWriteF, ITLBFlushF,
   input logic 		      WalkerInstrPageFaultF,
 
diff --git a/wally-pipelined/src/lsu/lsu.sv b/wally-pipelined/src/lsu/lsu.sv
index 2a88b25f..d7ff78d7 100644
--- a/wally-pipelined/src/lsu/lsu.sv
+++ b/wally-pipelined/src/lsu/lsu.sv
@@ -75,7 +75,8 @@ module lsu (
   input logic [`XLEN-1:0]     PageTableEntryM,
   input logic [1:0] 	      PageTypeM,
   input logic [`XLEN-1:0]     SATP_REGW, // from csr
-  input logic 		      STATUS_MXR, STATUS_SUM, // from csr
+  input logic              STATUS_MXR, STATUS_SUM, STATUS_MPRV,
+  input logic  [1:0]       STATUS_MPP,
   input logic 		      DTLBWriteM,
   output logic 		      DTLBMissM,
   input logic 		      DisableTranslation, // used to stop intermediate PTE physical addresses being saved to TLB.
diff --git a/wally-pipelined/src/mmu/mmu.sv b/wally-pipelined/src/mmu/mmu.sv
index 303076b0..e28db2e7 100644
--- a/wally-pipelined/src/mmu/mmu.sv
+++ b/wally-pipelined/src/mmu/mmu.sv
@@ -34,7 +34,8 @@ module mmu #(parameter ENTRY_BITS = 3,
   input logic              clk, reset,
   // Current value of satp CSR (from privileged unit)
   input logic  [`XLEN-1:0] SATP_REGW,
-  input logic              STATUS_MXR, STATUS_SUM,
+  input logic              STATUS_MXR, STATUS_SUM, STATUS_MPRV,
+  input logic  [1:0]       STATUS_MPP,
 
   // Current privilege level of the processeor
   input logic  [1:0]       PrivilegeModeW,
diff --git a/wally-pipelined/src/mmu/tlb.sv b/wally-pipelined/src/mmu/tlb.sv
index 6d8ed46a..9f6a4d25 100644
--- a/wally-pipelined/src/mmu/tlb.sv
+++ b/wally-pipelined/src/mmu/tlb.sv
@@ -55,7 +55,8 @@ module tlb #(parameter ENTRY_BITS = 3,
 
   // Current value of satp CSR (from privileged unit)
   input logic  [`XLEN-1:0] SATP_REGW,
-  input logic              STATUS_MXR, STATUS_SUM,
+  input logic              STATUS_MXR, STATUS_SUM, STATUS_MPRV,
+  input logic  [1:0]       STATUS_MPP,
 
   // Current privilege level of the processeor
   input logic  [1:0]       PrivilegeModeW,
@@ -92,6 +93,7 @@ module tlb #(parameter ENTRY_BITS = 3,
 
   // Store current virtual memory mode (SV32, SV39, SV48, ect...)
   logic [`SVMODE_BITS-1:0] SvMode;
+  logic  [1:0]       EffectivePrivilegeMode; // privilege mode, possibly modified by MPRV
 
   // Index (currently random) to write the next TLB entry
   logic [ENTRY_BITS-1:0] WriteIndex;
@@ -137,16 +139,15 @@ module tlb #(parameter ENTRY_BITS = 3,
     end
   endgenerate
 
-  // Whether translation should occur
-  assign Translate = (SvMode != `NO_TRANSLATE) & (PrivilegeModeW != `M_MODE) & ~ DisableTranslation; // *** needs to account for mprv
-
+  // Whether translation should occur; ITLB ignores MPRVW
+  assign Translate = (SvMode != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~ DisableTranslation; 
+ 
   // Determine how the TLB is currently being used
   // Note that we use ReadAccess for both loads and instruction fetches
   assign ReadAccess = TLBAccessType[1];
   assign WriteAccess = TLBAccessType[0];
   assign TLBAccess = ReadAccess || WriteAccess;
 
-  
   assign PageOffset = VirtualAddress[11:0];
 
   // TLB entries are evicted according to the LRU algorithm
@@ -164,28 +165,30 @@ module tlb #(parameter ENTRY_BITS = 3,
     if (ITLB == 1) begin
       logic ImproperPrivilege;
 
+      assign EffectivePrivilegeMode = PrivilegeModeW; // ITLB ignores MPRV
+
       // User mode may only execute user mode pages, and supervisor mode may
       // only execute non-user mode pages.
-      assign ImproperPrivilege = ((PrivilegeModeW == `U_MODE) && ~PTE_U) ||
-        ((PrivilegeModeW == `S_MODE) && PTE_U);
+      assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) && ~PTE_U) ||
+        ((EffectivePrivilegeMode == `S_MODE) && PTE_U);
       assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || ~PTE_X);
     end else begin
       logic ImproperPrivilege, InvalidRead, InvalidWrite;
 
+      assign EffectivePrivilegeMode = STATUS_MPRV ? STATUS_MPP : PrivilegeModeW; // DTLB uses MPP mode when MPRV is 1
+
       // User mode may only load/store from user mode pages, and supervisor mode
       // may only access user mode pages when STATUS_SUM is low.
-      assign ImproperPrivilege = ((PrivilegeModeW == `U_MODE) && ~PTE_U) ||
-        ((PrivilegeModeW == `S_MODE) && PTE_U && ~STATUS_SUM);
+      assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) && ~PTE_U) ||
+        ((EffectivePrivilegeMode == `S_MODE) && PTE_U && ~STATUS_SUM);
       // Check for read error. Reads are invalid when the page is not readable
       // (and executable pages are not readable) or when the page is neither
       // readable nor executable (and executable pages are readable).
-      assign InvalidRead = ReadAccess &&
-        ((~STATUS_MXR && ~PTE_R) || (STATUS_MXR && ~PTE_R && PTE_X));
+      assign InvalidRead = ReadAccess && ~PTE_R && (~STATUS_MXR | ~PTE_X);
       // Check for write error. Writes are invalid when the page's write bit is
       // low.
       assign InvalidWrite = WriteAccess && ~PTE_W;
-      assign TLBPageFault = Translate && TLBHit &&
-        (ImproperPrivilege || InvalidRead || InvalidWrite);
+      assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || InvalidRead || InvalidWrite);
     end
   endgenerate
 
diff --git a/wally-pipelined/src/privileged/csr.sv b/wally-pipelined/src/privileged/csr.sv
index ba2362c3..7162263c 100644
--- a/wally-pipelined/src/privileged/csr.sv
+++ b/wally-pipelined/src/privileged/csr.sv
@@ -58,8 +58,7 @@ module csr #(parameter
   output logic [`XLEN-1:0] SATP_REGW,
   output logic [11:0]      MIP_REGW, MIE_REGW, SIP_REGW, SIE_REGW,
   output logic             STATUS_MIE, STATUS_SIE,
-  output logic             STATUS_MXR, STATUS_SUM,
-  output logic             STATUS_MPRV,
+  output logic             STATUS_MXR, STATUS_SUM, STATUS_MPRV,
   output var logic [7:0]      PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0],
   output var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0],
   input  logic [4:0]       SetFflagsM,
diff --git a/wally-pipelined/src/privileged/privileged.sv b/wally-pipelined/src/privileged/privileged.sv
index 618b3214..90830137 100644
--- a/wally-pipelined/src/privileged/privileged.sv
+++ b/wally-pipelined/src/privileged/privileged.sv
@@ -67,7 +67,8 @@ module privileged (
   output logic		         IllegalFPUInstrE,
   output logic [1:0]       PrivilegeModeW,
   output logic [`XLEN-1:0] SATP_REGW,
-  output logic             STATUS_MXR, STATUS_SUM,
+  output logic             STATUS_MXR, STATUS_SUM, STATUS_MPRV,
+  output logic  [1:0]      STATUS_MPP,
   output var logic [7:0]   PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0],
   output var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], 
   output logic [2:0]       FRM_REGW
@@ -94,8 +95,7 @@ module privileged (
   logic MTrapM, STrapM, UTrapM;
   logic InterruptM; 
 
-  logic [1:0] STATUS_MPP;
-  logic       STATUS_SPP, STATUS_TSR, STATUS_MPRV; // **** status mprv is unused outside of the csr module as of 4 June 2021. should it be deleted alltogether from the module, or should I leav the pin here in case someone needs it? 
+  logic       STATUS_SPP, STATUS_TSR; 
   logic       STATUS_MIE, STATUS_SIE;
   logic [11:0] MIP_REGW, MIE_REGW, SIP_REGW, SIE_REGW;
   logic md, sd;
diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv
index be59c18b..33d2e13f 100644
--- a/wally-pipelined/src/wally/wallypipelinedhart.sv
+++ b/wally-pipelined/src/wally/wallypipelinedhart.sv
@@ -112,7 +112,8 @@ module wallypipelinedhart
   logic 		    ITLBMissF, ITLBHitF;
   logic 		    DTLBMissM, DTLBHitM;
   logic [`XLEN-1:0] 	    SATP_REGW;
-  logic 		    STATUS_MXR, STATUS_SUM;
+  logic              STATUS_MXR, STATUS_SUM, STATUS_MPRV;
+  logic  [1:0]       STATUS_MPP;
   logic [1:0] 		    PrivilegeModeW;
   logic [`XLEN-1:0] 	    PageTableEntryF, PageTableEntryM;
   logic [1:0] 		    PageTypeF, PageTypeM;