From c693462f6b5a331c9108dc88e3e4c6fabc2ffd43 Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Wed, 22 Jul 2020 15:54:49 +0100 Subject: [PATCH] Add tag-clearing due to cap load perm and PTE bits --- .../RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv | 2 +- .../procs/RV64G_OOO/MemExePipeline.bsv | 26 ++++++++++++++----- .../RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv | 2 +- src_Core/RISCY_OOO/procs/lib/DTlb.bsv | 15 ++++++----- src_Core/RISCY_OOO/procs/lib/ITlb.bsv | 12 ++++----- src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv | 13 ++++++++-- src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv | 8 +++--- 7 files changed, 51 insertions(+), 27 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv index 6a0c41f..58b665a 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv @@ -616,7 +616,7 @@ module mkFetchStage(FetchStage); f12f2.deq; // Get TLB response - match {.phys_pc, .cause} <- tlb_server.response.get; + match {.phys_pc, .cause, .allow_cap} <- tlb_server.response.get; // Access main mem or boot rom if no TLB exception Bool access_mmio = False; diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv index 1318f6f..df266a2 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv @@ -109,6 +109,7 @@ typedef struct { `endif Bool misaligned; Bool capStore; + Bool allowCap; Maybe#(CSR_XCapCause) capException; Maybe#(BoundsCheck) check; } MemExeToFinish deriving(Bits, FShow); @@ -525,6 +526,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); `endif misaligned: memAddrMisaligned(getAddr(vaddr), origBE), capStore: isValidCap(data) && pack(origBE) == ~0, + allowCap: getHardPerms(x.rVal1).permitLoadCap, 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) @@ -537,7 +539,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); dTlb.deqProcResp; let dTlbResp = dTlb.procResp; let x = dTlbResp.inst; - let {paddr, expCause} = dTlbResp.resp; + let {paddr, expCause, allowCapPTE} = dTlbResp.resp; Maybe#(Trap) cause = Invalid; if (expCause matches tagged Valid .c) cause = Valid(Exception(c)); @@ -618,7 +620,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); // update LSQ LSQUpdateAddrResult updRes <- lsq.updateAddr( - x.ldstq_tag, cause, paddr, isMMIO, x.shiftedBE + x.ldstq_tag, cause, x.allowCap && allowCapPTE, paddr, isMMIO, x.shiftedBE ); // issue non-MMIO Ld which has no exception and is not waiting for @@ -743,7 +745,9 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); LSQRespLdResult res <- lsq.respLd(tag, data); if(verbose) $display("%t : ", $time, rule_name, " ", fshow(tag), "; ", fshow(data), "; ", fshow(res)); if(res.dst matches tagged Valid .dst) begin - inIfc.writeRegFile(dst.indx, fromMem(unpack(pack(res.data)))); + CapPipe dataUnpacked = fromMem(unpack(pack(res.data))); + dataUnpacked = setValidCap(dataUnpacked, res.allowCap && isValidCap(dataUnpacked)); + inIfc.writeRegFile(dst.indx, dataUnpacked); `ifdef INCLUDE_TANDEM_VERIF inIfc.rob_setExecuted_doFinishMem_RegData (res.instTag, res.data); @@ -906,7 +910,9 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); MemTaggedData resp = gatherLoad(lsqDeqLd.paddr, lsqDeqLd.byteEn, lsqDeqLd.unsignedLd, d); // write reg file & set ROB as Executed & wakeup rs if(lsqDeqLd.dst matches tagged Valid .dst) begin - inIfc.writeRegFile(dst.indx, fromMem(unpack(pack(resp)))); + CapPipe dataUnpacked = fromMem(unpack(pack(resp))); + dataUnpacked = setValidCap(dataUnpacked, lsqDeqLd.allowCap && isValidCap(dataUnpacked)); + inIfc.writeRegFile(dst.indx, dataUnpacked); inIfc.setRegReadyAggr_mem(dst.indx); `ifdef INCLUDE_TANDEM_VERIF inIfc.rob_setExecuted_doFinishMem_RegData (lsqDeqLd.instTag, resp); @@ -994,7 +1000,9 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); MemTaggedData resp = gatherLoad(lsqDeqLd.paddr, lsqDeqLd.byteEn, lsqDeqLd.unsignedLd, d); // write reg file & wakeup rs (this wakeup is late but MMIO is rare) & set ROB as Executed if(lsqDeqLd.dst matches tagged Valid .dst) begin - inIfc.writeRegFile(dst.indx, fromMem(tuple2(resp.tag,unpack(pack(resp.data))))); + CapPipe dataUnpacked = fromMem(tuple2(resp.tag,unpack(pack(resp.data)))); + dataUnpacked = setValidCap(dataUnpacked, lsqDeqLd.allowCap && isValidCap(dataUnpacked)); + inIfc.writeRegFile(dst.indx, dataUnpacked); inIfc.setRegReadyAggr_mem(dst.indx); `ifdef INCLUDE_TANDEM_VERIF inIfc.rob_setExecuted_doFinishMem_RegData (lsqDeqLd.instTag, resp); @@ -1247,7 +1255,9 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); MemTaggedData resp <- toGet(respLrScAmoQ).get; // write reg file & set ROB as Executed & wake up rs if(lsqDeqSt.dst matches tagged Valid .dst) begin - inIfc.writeRegFile(dst.indx, fromMem(tuple2(resp.tag, pack(resp.data)))); + CapPipe dataUnpacked = fromMem(tuple2(resp.tag, pack(resp.data))); + dataUnpacked = setValidCap(dataUnpacked, False); // TODO no allowCap around. Can a cap be loaded this way (e.g. AMOSWAP?) + inIfc.writeRegFile(dst.indx, dataUnpacked); inIfc.setRegReadyAggr_mem(dst.indx); `ifdef INCLUDE_TANDEM_VERIF inIfc.rob_setExecuted_doFinishMem_RegData (lsqDeqSt.instTag, resp); @@ -1353,7 +1363,9 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); MemTaggedData resp = inIfc.mmioRespVal.data; // write reg file & wakeup rs (this wakeup is late but MMIO is rare) & set ROB as Executed if(lsqDeqSt.dst matches tagged Valid .dst) begin - inIfc.writeRegFile(dst.indx, fromMem(tuple2(resp.tag, pack(resp.data)))); + CapPipe dataUnpacked = fromMem(tuple2(resp.tag, pack(resp.data))); + dataUnpacked = setValidCap(dataUnpacked, False); // TODO no allowCap around. Can a cap be loaded this way (e.g. AMOSWAP?) + inIfc.writeRegFile(dst.indx, dataUnpacked); inIfc.setRegReadyAggr_mem(dst.indx); `ifdef INCLUDE_TANDEM_VERIF inIfc.rob_setExecuted_doFinishMem_RegData (lsqDeqSt.instTag, resp); diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv index 7657142..6c7cf77 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv @@ -704,7 +704,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); "Mem (non-Fence) needs imm for virtual addr"); // put in ldstq if(isLdQ) begin - lsq.enqLd(inst_tag, mem_inst, phy_regs.dst, spec_bits); + lsq.enqLd(inst_tag, mem_inst, allow_cap, phy_regs.dst, spec_bits); end else begin lsq.enqSt(inst_tag, mem_inst, phy_regs.dst, spec_bits); diff --git a/src_Core/RISCY_OOO/procs/lib/DTlb.bsv b/src_Core/RISCY_OOO/procs/lib/DTlb.bsv index 6d59bc7..28fe5e6 100644 --- a/src_Core/RISCY_OOO/procs/lib/DTlb.bsv +++ b/src_Core/RISCY_OOO/procs/lib/DTlb.bsv @@ -282,7 +282,7 @@ module mkDTlb#( // fill TLB, and record resp tlb.addEntry(en); let trans_addr = translate(r.addr, en.ppn, en.level); - pendResp[idx] <= tuple2(trans_addr, Invalid); + pendResp[idx] <= tuple3(trans_addr, Invalid, permCheck.allowCap); if(verbose) begin $display("[DTLB] refill: idx %d; ", idx, fshow(r), "; ", fshow(trans_addr)); @@ -291,7 +291,7 @@ module mkDTlb#( else begin // page fault Exception fault = permCheck.excCode; - pendResp[idx] <= tuple2(?, Valid (fault)); + pendResp[idx] <= tuple3(?, Valid (fault), False); if(verbose) begin $display("[DTLB] refill no permission: idx %d; ", idx, fshow(r)); end @@ -300,7 +300,7 @@ module mkDTlb#( else begin // page fault Exception fault = r.write ? StorePageFault : LoadPageFault; - pendResp[idx] <= tuple2(?, Valid (fault)); + pendResp[idx] <= tuple3(?, Valid (fault), False); if(verbose) $display("[DTLB] refill page fault: idx %d; ", idx, fshow(r)); end @@ -436,7 +436,7 @@ module mkDTlb#( // (Because we are always non speculative in M mode) if (!vm_info.sanctum_authShared && outOfProtectionDomain(vm_info, r.addr))begin pendWait[idx] <= None; - pendResp[idx] <= tuple2(?, Valid (LoadAccessFault)); + pendResp[idx] <= tuple3(?, Valid (LoadAccessFault), False); end `else // No security check @@ -458,13 +458,14 @@ module mkDTlb#( entry.level, r.write ? DataStore : DataLoad, r.cap); + $display("Permission check output 2: ", fshow(permCheck)); if (permCheck.allowed) begin // update TLB replacement info tlb.updateRepByHit(trans_result.index); // translate addr Addr trans_addr = translate(r.addr, entry.ppn, entry.level); pendWait[idx] <= None; - pendResp[idx] <= tuple2(trans_addr, Invalid); + pendResp[idx] <= tuple3(trans_addr, Invalid, permCheck.allowCap); if(verbose) begin $display("[DTLB] req (hit): idx %d; ", idx, fshow(r), "; ", fshow(trans_result)); @@ -480,7 +481,7 @@ module mkDTlb#( // page fault Exception fault = permCheck.excCode; pendWait[idx] <= None; - pendResp[idx] <= tuple2(?, Valid (fault)); + pendResp[idx] <= tuple3(?, Valid (fault), False); if(verbose) $display("[DTLB] req no permission: idx %d; ", idx, fshow(r)); end end @@ -524,7 +525,7 @@ module mkDTlb#( else begin // bare mode pendWait[idx] <= None; - pendResp[idx] <= tuple2(r.addr, Invalid); + pendResp[idx] <= tuple3(r.addr, Invalid, True); if(verbose) $display("DTLB %m req (bare): ", fshow(r)); end diff --git a/src_Core/RISCY_OOO/procs/lib/ITlb.bsv b/src_Core/RISCY_OOO/procs/lib/ITlb.bsv index da25e62..c172ea6 100644 --- a/src_Core/RISCY_OOO/procs/lib/ITlb.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ITlb.bsv @@ -184,7 +184,7 @@ module mkITlb(ITlb::ITlb); // fill TLB and resp to proc tlb.addEntry(en); let trans_addr = translate(vaddr, en.ppn, en.level); - hitQ.enq(tuple2(trans_addr, Invalid)); + hitQ.enq(tuple3(trans_addr, Invalid, False)); if(verbose) begin $display("ITLB %m refill: ", fshow(vaddr), " ; ", fshow(trans_addr)); @@ -192,7 +192,7 @@ module mkITlb(ITlb::ITlb); end else begin // page fault - hitQ.enq(tuple2(?, Valid (InstPageFault))); + hitQ.enq(tuple3(?, Valid (InstPageFault), False)); if(verbose) begin $display("ITLB %m refill no permission: ", fshow(vaddr)); end @@ -200,7 +200,7 @@ module mkITlb(ITlb::ITlb); end else begin // page fault - hitQ.enq(tuple2(?, Valid (InstPageFault))); + hitQ.enq(tuple3(?, Valid (InstPageFault), False)); if(verbose) $display("ITLB %m refill page fault: ", fshow(vaddr)); end // miss resolved @@ -298,7 +298,7 @@ module mkITlb(ITlb::ITlb); Addr trans_addr = translate( vaddr, entry.ppn, entry.level ); - hitQ.enq(tuple2(trans_addr, Invalid)); + hitQ.enq(tuple3(trans_addr, Invalid, False)); if(verbose) begin $display("ITLB %m req (hit): ", fshow(vaddr), " ; ", fshow(trans_result)); @@ -306,7 +306,7 @@ module mkITlb(ITlb::ITlb); end else begin // page fault - hitQ.enq(tuple2(?, Valid (InstPageFault))); + hitQ.enq(tuple3(?, Valid (InstPageFault), False)); if(verbose) begin $display("ITLB %m req no permission: ", fshow(vaddr)); @@ -330,7 +330,7 @@ module mkITlb(ITlb::ITlb); end else begin // bare mode, no translation - hitQ.enq(tuple2(vaddr, Invalid)); + hitQ.enq(tuple3(vaddr, Invalid, False)); if (verbose) $display("ITLB %m req (bare): ", fshow(vaddr)); end diff --git a/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv b/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv index 25b734f..527721e 100644 --- a/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv +++ b/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv @@ -294,6 +294,7 @@ typedef struct { typedef struct { Bool wrongPath; Maybe#(PhyDst) dst; + Bool allowCap; `ifdef INCLUDE_TANDEM_VERIF InstTag instTag; // For recording Ld data in ROB `endif @@ -318,6 +319,7 @@ typedef struct { Bool isMMIO; MemDataByteEn shiftedBE; Maybe#(Trap) fault; + Bool allowCap; Maybe#(LdKilledBy) killed; } LdQDeqEntry deriving (Bits, Eq, FShow); @@ -332,6 +334,7 @@ typedef struct { Bool isMMIO; MemDataByteEn shiftedBE; MemTaggedData stData; + Bool allowCap; Maybe#(Trap) fault; } StQDeqEntry deriving (Bits, Eq, FShow); @@ -363,7 +366,7 @@ interface SplitLSQ; method ActionValue#(LSQUpdateAddrResult) updateAddr( LdStQTag lsqTag, Maybe#(Trap) fault, // below are only meaningful wen fault is Invalid - Addr paddr, Bool isMMIO, MemDataByteEn shiftedBE + Bool allowCap, Addr paddr, Bool isMMIO, MemDataByteEn shiftedBE ); // Issue a load, and remove dependence on this load issue. method ActionValue#(LSQIssueLdResult) issueLd( @@ -631,6 +634,7 @@ module mkSplitLSQ(SplitLSQ); Vector#(LdQSize, Reg#(LdQMemFunc)) ld_memFunc <- replicateM(mkRegU); Vector#(LdQSize, Reg#(Bool)) ld_unsigned <- replicateM(mkRegU); Vector#(LdQSize, Reg#(MemDataByteEn)) ld_byteEn <- replicateM(mkRegU); + Vector#(LdQSize, Reg#(Bool)) ld_allowCap <- replicateM(mkRegU); Vector#(LdQSize, Reg#(Bool)) ld_acq <- replicateM(mkRegU); Vector#(LdQSize, Reg#(Bool)) ld_rel <- replicateM(mkRegU); Vector#(LdQSize, Reg#(Maybe#(PhyDst))) ld_dst <- replicateM(mkRegU); @@ -1525,7 +1529,7 @@ module mkSplitLSQ(SplitLSQ); method ActionValue#(LSQUpdateAddrResult) updateAddr( LdStQTag lsqTag, Maybe#(Trap) fault, - Addr pa, Bool mmio, MemDataByteEn shift_be + Bool allowCap, Addr pa, Bool mmio, MemDataByteEn shift_be ); // index vec for vector functions Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger); @@ -1566,6 +1570,7 @@ module mkSplitLSQ(SplitLSQ); ld_fault_updAddr[tag] <= fault; ld_computed_updAddr[tag] <= !isValid(fault); ld_paddr_updAddr[tag] <= pa; + ld_allowCap[tag] <= allowCap; ld_isMMIO_updAddr[tag] <= mmio; ld_shiftedBE_updAddr[tag] <= shift_be; @@ -1994,6 +1999,7 @@ module mkSplitLSQ(SplitLSQ); let res = LSQRespLdResult { wrongPath: False, dst: Invalid, + allowCap: False, `ifdef INCLUDE_TANDEM_VERIF instTag: ld_instTag [t], // For recording Ld data in ROB `endif @@ -2021,8 +2027,10 @@ module mkSplitLSQ(SplitLSQ); // In that case, the data needs to be nanboxed before writing to // the register files as the Toooba FPR is 64-bit let bEn = ld_byteEn[t]; + let allowCap = ld_allowCap[t]; let dst = ld_dst[t]; let is32BitLd = (bEn[3] && !bEn[7]); + res.allowCap = allowCap; res.dst = ld_dst[t]; if (dst.Valid.isFpuReg && is32BitLd) res.data = fv_nanbox_MemTaggedData( @@ -2057,6 +2065,7 @@ module mkSplitLSQ(SplitLSQ); isMMIO: ld_isMMIO_deqLd[deqP], shiftedBE: ld_shiftedBE_deqLd[deqP], fault: ld_fault_deqLd[deqP], + allowCap: ld_allowCap[deqP], killed: ld_killed_deqLd[deqP] }; endmethod diff --git a/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv b/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv index b30a2a0..d764f39 100644 --- a/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv @@ -33,7 +33,7 @@ typedef struct{ Bool write; Bool cap; } TlbReq deriving(Eq, Bits, FShow); -typedef Tuple2#(Addr, Maybe#(Exception)) TlbResp; +typedef Tuple3#(Addr, Maybe#(Exception), Bool) TlbResp; // non-blocking DTLB typedef `DTLB_REQ_NUM DTlbReqNum; @@ -180,6 +180,7 @@ typedef enum { typedef struct { Bool allowed; Exception excCode; // Only defined if !allowed + Bool allowCap; // Whether we can load caps } TlbPermissionCheck deriving(Bits, Eq, FShow); function TlbPermissionCheck hasVMPermission( @@ -244,8 +245,9 @@ function TlbPermissionCheck hasVMPermission( endcase TlbPermissionCheck ret = TlbPermissionCheck { - allowed: !fault, - excCode: access == DataStore ? StorePageFault : LoadPageFault}; + allowed: !fault, + excCode: access == DataStore ? StorePageFault : LoadPageFault, + allowCap: pte_upper_type.cap_readable}; if (!fault) begin if (cap && access == DataStore && !pte_upper_type.cap_writable) begin