From 0040b05ada856a2697bae6c980058b9c3e1c8242 Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Tue, 21 Jul 2020 16:02:37 +0100 Subject: [PATCH] Add page table cap store checking --- .../procs/RV64G_OOO/MemExePipeline.bsv | 5 +- src_Core/RISCY_OOO/procs/lib/DTlb.bsv | 30 +++++++----- src_Core/RISCY_OOO/procs/lib/ITlb.bsv | 8 ++- src_Core/RISCY_OOO/procs/lib/L2Tlb.bsv | 1 + src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv | 2 + src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv | 49 ++++++++++++++----- 6 files changed, 69 insertions(+), 26 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv index aba8ed8..1318f6f 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv @@ -108,6 +108,7 @@ typedef struct { ByteEn store_data_BE; `endif Bool misaligned; + Bool capStore; Maybe#(CSR_XCapCause) capException; Maybe#(BoundsCheck) check; } MemExeToFinish deriving(Bits, FShow); @@ -158,7 +159,8 @@ module mkDTlbSynth(DTlbSynth); write: (case(x.mem_func) St, Sc, Amo: True; default: False; - endcase) + endcase), + cap: x.capStore }; endfunction let m <- mkDTlb(getTlbReq); @@ -522,6 +524,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); store_data_BE: origBE, `endif misaligned: memAddrMisaligned(getAddr(vaddr), origBE), + capStore: isValidCap(data) && pack(origBE) == ~0, capException: capChecksMem(x.rVal1, x.rVal2, x.cap_checks, x.mem_func, origBE), check: prepareBoundsCheck(x.rVal1, x.rVal2, almightyCap/*ToDo: pcc*/, ddc, getAddr(vaddr), pack(countOnes(pack(origBE))), x.cap_checks) diff --git a/src_Core/RISCY_OOO/procs/lib/DTlb.bsv b/src_Core/RISCY_OOO/procs/lib/DTlb.bsv index c0eedf9..6d59bc7 100644 --- a/src_Core/RISCY_OOO/procs/lib/DTlb.bsv +++ b/src_Core/RISCY_OOO/procs/lib/DTlb.bsv @@ -271,11 +271,14 @@ module mkDTlb#( end else if(pRs.entry matches tagged Valid .en) begin // check permission - if(hasVMPermission(vm_info, - en.pteType, - en.ppn, - en.level, - r.write ? DataStore : DataLoad)) begin + let permCheck = hasVMPermission(vm_info, + en.pteType, + en.pteUpperType, + en.ppn, + en.level, + r.write ? DataStore : DataLoad, + r.cap); + if (permCheck.allowed) begin // fill TLB, and record resp tlb.addEntry(en); let trans_addr = translate(r.addr, en.ppn, en.level); @@ -287,7 +290,7 @@ module mkDTlb#( end else begin // page fault - Exception fault = r.write ? StorePageFault : LoadPageFault; + Exception fault = permCheck.excCode; pendResp[idx] <= tuple2(?, Valid (fault)); if(verbose) begin $display("[DTLB] refill no permission: idx %d; ", idx, fshow(r)); @@ -448,11 +451,14 @@ module mkDTlb#( // TLB hit let entry = trans_result.entry; // check permission - if (hasVMPermission(vm_info, - entry.pteType, - entry.ppn, - entry.level, - r.write ? DataStore : DataLoad)) begin + let permCheck = hasVMPermission(vm_info, + entry.pteType, + entry.pteUpperType, + entry.ppn, + entry.level, + r.write ? DataStore : DataLoad, + r.cap); + if (permCheck.allowed) begin // update TLB replacement info tlb.updateRepByHit(trans_result.index); // translate addr @@ -472,7 +478,7 @@ module mkDTlb#( end else begin // page fault - Exception fault = r.write ? StorePageFault : LoadPageFault; + Exception fault = permCheck.excCode; pendWait[idx] <= None; pendResp[idx] <= tuple2(?, Valid (fault)); if(verbose) $display("[DTLB] req no permission: idx %d; ", idx, fshow(r)); diff --git a/src_Core/RISCY_OOO/procs/lib/ITlb.bsv b/src_Core/RISCY_OOO/procs/lib/ITlb.bsv index 485044f..da25e62 100644 --- a/src_Core/RISCY_OOO/procs/lib/ITlb.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ITlb.bsv @@ -176,9 +176,11 @@ module mkITlb(ITlb::ITlb); // check permission if(hasVMPermission(vm_info, en.pteType, + en.pteUpperType, en.ppn, en.level, - InstFetch)) begin + InstFetch, + False).allowed) begin // fill TLB and resp to proc tlb.addEntry(en); let trans_addr = translate(vaddr, en.ppn, en.level); @@ -285,9 +287,11 @@ module mkITlb(ITlb::ITlb); // check permission if(hasVMPermission(vm_info, entry.pteType, + entry.pteUpperType, entry.ppn, entry.level, - InstFetch)) begin + InstFetch, + False).allowed) begin // update replacement info tlb.updateRepByHit(trans_result.index); // translate addr diff --git a/src_Core/RISCY_OOO/procs/lib/L2Tlb.bsv b/src_Core/RISCY_OOO/procs/lib/L2Tlb.bsv index ab8b58e..139169f 100644 --- a/src_Core/RISCY_OOO/procs/lib/L2Tlb.bsv +++ b/src_Core/RISCY_OOO/procs/lib/L2Tlb.bsv @@ -653,6 +653,7 @@ module mkL2Tlb(L2Tlb::L2Tlb); vpn: masked_vpn, ppn: masked_ppn, pteType: pte.pteType, + pteUpperType: pte.pteUpperType, level: walkLevel, asid: vm_info.asid }; diff --git a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index c64bb22..00cf212 100755 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -393,6 +393,8 @@ typedef enum { InstPageFault = 5'd12, LoadPageFault = 5'd13, StorePageFault = 5'd15, + LoadCapPageFault = 5'd26, + StoreCapPageFault = 5'd27, CHERIFault = 5'd28 } Exception deriving(Bits, Eq, FShow); diff --git a/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv b/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv index 41f4eda..b30a2a0 100644 --- a/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv @@ -31,6 +31,7 @@ import ProcTypes::*; typedef struct{ Addr addr; Bool write; + Bool cap; } TlbReq deriving(Eq, Bits, FShow); typedef Tuple2#(Addr, Maybe#(Exception)) TlbResp; @@ -66,7 +67,13 @@ typedef struct { } PTEType deriving (Bits, Eq, FShow); typedef struct { - Bit#(10) reserved; + Bool cap_writable; + Bool cap_readable; +} PTEUpperType deriving (Bits, Eq, FShow); + +typedef struct { + PTEUpperType pteUpperType; + Bit#(8) reserved; Ppn ppn; Bit#(2) reserved_sw; // reserved for supervisor software PTEType pteType; @@ -78,6 +85,7 @@ typedef struct { Vpn vpn; Ppn ppn; PTEType pteType; + PTEUpperType pteUpperType; PageWalkLevel level; Asid asid; } TlbEntry deriving (Bits, Eq, FShow); @@ -169,10 +177,16 @@ typedef enum { DataStore // also contain DataLoad } TlbAccessType deriving(Bits, Eq, FShow); -function Bool hasVMPermission( +typedef struct { + Bool allowed; + Exception excCode; // Only defined if !allowed +} TlbPermissionCheck deriving(Bits, Eq, FShow); + +function TlbPermissionCheck hasVMPermission( VMInfo vm_info, - PTEType pte_type, Ppn ppn, PageWalkLevel level, - TlbAccessType access + PTEType pte_type, PTEUpperType pte_upper_type, + Ppn ppn, PageWalkLevel level, + TlbAccessType access, Bool cap ); // try to find any page fault Bool fault = False; @@ -229,13 +243,26 @@ function Bool hasVMPermission( end endcase - // check if accessed or dirty bit needs to be set - if(!pte_type.accessed) begin - fault = True; - end - if(access == DataStore && !pte_type.dirty) begin - fault = True; + TlbPermissionCheck ret = TlbPermissionCheck { + allowed: !fault, + excCode: access == DataStore ? StorePageFault : LoadPageFault}; + + if (!fault) begin + if (cap && access == DataStore && !pte_upper_type.cap_writable) begin + ret.allowed = False; + ret.excCode = StoreCapPageFault; + end else begin + // check if accessed or dirty bit needs to be set + if(!pte_type.accessed) begin + ret.allowed = False; + ret.excCode = access == DataStore ? StorePageFault : LoadPageFault; + end + if(access == DataStore && !pte_type.dirty) begin + ret.allowed = False; + ret.excCode = access == DataStore ? StorePageFault : LoadPageFault; + end + end end - return !fault; + return ret; endfunction