Add tag-clearing due to cap load perm and PTE bits
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user