Add tag-clearing due to cap load perm and PTE bits

This commit is contained in:
Peter Rugg
2020-07-22 15:54:49 +01:00
parent 0040b05ada
commit c693462f6b
7 changed files with 51 additions and 27 deletions

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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