Reference 1
cheri/trunk/CapCop.bsv
Interface: CapCopIfc
Module: mkCapCop#(Bit#(16) coreId) (CapCopIfc)
Functions: getBase(cap), getLength(cap), getOffset(cap), getType(cap), getSealed(cap), checkRegAccess(Perms, CapReg), privileged(Perms), getPerms(CapFat).
States:
Rules:
regFile.writeRaw
for 32 times and set capState from Init
to Ready
.exception
, an FIFOF#(ExceptionEvent)Methods:
Overview: do length checks for the first lenCheck
in the queue of lenChecks
. If success, response{.valid:True, }
input:
output:
Steps:
ct
from exe2memQ
to mem2wbkQ
.CapCause cause
, update the value cause.exp
if length check fails; put it in queue lenCause
.lenCheck
from lenChecks
, and update the value if certain checks fail.condition
input
Memory
, Branch
, Arithmetic
output
globals:
Steps:
if Arithmetic: the operation (capInst.op) can be Move
, SetOffset
, IncBaseNull
, IncOffset
, …
if Branch: operation (capInst.op) can be:
if Memory: according to diferent operations (capInst.op), check capabilities, might set the lenCheck.valid
, lenCheck.memSize
, aCapReq.memOp
, etc :
response.storeData
=tagged CapLine truncate(pack(capB)); writeback
=capB;testPc=capReq.pc
if jmp: set branch delay flag; testPc=capReq.pc+4; pccUpdate.enq(BufferedPCC{pcc: newPccc, epoch: ct.epoch})
if not jmp: check testPc is in range of forwardedPCC.[base,length]
exe2memQ.enq(ctOut) // after this,
lenChecks.enq(lenCheck) // after this,
check branch delay
…
Steps:
lenCheck = lenChecks.deq()
CapControlToken ct <- toGet(exe2memQ).get()
mem2wbkQ.enq(ct)
Steps:
parse information in wbReq and control token, and update the regFile accordingly
// cheri/trunk/CapCop.bsv
method ActionValue#(CapFat) commitWriteback(CapWritebackRequest wbReq) if (capState == Ready/* && !exception.notEmpty()*/);
//CapCause fetchCheckCause = fetchCause.first;
//fetchCause.deq;
CapCause lenCheckCause <- toGet(lenCause).get();
CapControlToken ct <- toGet(mem2wbkQ).get();
Bool commit = (!wbReq.dead && wbReq.mipsExp == None);
Capability newPcc = pcc;
if (ct.jump && commit) begin
newPcc = pccUpdate.first.pcc;
Capability dc = pccUpdate.first.pcc;
trace($display("Time:%0d, Core:%0d, Thread:0 :: PCC <- tag:%d s:%d perms:0x%x type:0x%x offset:0x%x base:0x%x length:0x%x", $time, coreId, dc.isCapability, dc.sealed, dc.perms, dc.otype, dc.offset-dc.base, dc.base, getLength(dc)));
end// else pcc.offset <= wbReq.pc;
if (ct.jump && pccUpdate.notEmpty) pccUpdate.deq;
if (ct.capInst.op==SetConfig && causeUpdate.notEmpty) causeUpdate.deq;
if (ct.doWrite && commit) begin
if (ct.capInst.op == LC) ct.writeCap = wbReq.memResponse;
`ifdef BLUESIM
debugCaps[ct.writeReg] <= ct.writeCap;
`endif
Capability dc = ct.writeCap;
trace($display("Time:%0d, Core:%0d, Thread:0 :: CapReg %d <- tag:%d s:%d perms:0x%x type:0x%x offset:0x%x base:0x%x length:0x%x", $time, coreId, ct.writeReg, dc.isCapability, dc.sealed, dc.perms, dc.otype, dc.offset-dc.base, dc.base, getLength(dc)));
end
regFile.writeReg(ct.writeCap, commit);
if (!wbReq.dead && (wbReq.mipsExp==CAP ||wbReq.mipsExp==CAPCALL||
wbReq.mipsExp==CTLBS||wbReq.mipsExp==ICAP)) begin
// Length exception has priority over Call exception.
if (ct.cause.exp==None || ct.cause.exp==Call) begin
if (lenCheckCause.exp != None) ct.cause = lenCheckCause;
end
if (wbReq.mipsExp==CTLBS) ct.cause.exp = Ctlbs;
if (wbReq.mipsExp==ICAP) ct.cause = CapCause{exp: Len, pcc: True, capReg: ?};
causeReg <= ct.cause;
trace($display("Time:%0d, Core:%0d, Thread:0 :: Exception CapCause <- CapExpCode: 0x%x CauseReg: %d", $time, coreId, ct.cause.exp, ct.cause.capReg));
end else if (ct.capInst.op == SetConfig && commit) begin
causeReg <= ct.cause;
trace($display("Time:%0d, Core:%0d, Thread:0 :: SetConfig CapCause <- CapExpCode: 0x%x CauseReg: %d", $time, coreId, ct.cause.exp, ct.cause.capReg));
end
if (commit && ct.writeRegMask) regFile.clearRegs(ct.newRegMask);
if (!wbReq.dead) begin
ExceptionEvent ee = None;
if (wbReq.mipsExp!=None) ee = Except;
else if (ct.capInst.op==ERET) ee = Return;
if (ee != None) begin
newPcc.offset = wbReq.pc;
// Request KCC (register 29) from the register file to be placed in PCC
// Or request EPCC (register 31) from the register file to be returned to PCC
CapReg fetch = (ee==Except) ? 29:31;
regFile.readRawPut(fetch);
exception.enq(ee);
end
end
`ifdef BLUESIM
if (reportCapRegs.notEmpty) begin
debugInst($display("====== RegFile ======"));
debugInst($display("DEBUG CAP COREID %d", coreId));
debugInst($display("DEBUG CAP PCC t:%d s:%d perms:0x%x type:0x%x offset:0x%x base:0x%x length:0x%x", pcc.isCapability, pcc.sealed, pcc.perms, pcc.otype, pcc.offset-pcc.base, pcc.base, getLength(pcc)));
for (Integer i = 0; i<32; i=i+1) begin
Capability dc = debugCaps[i];
debugInst($display("DEBUG CAP REG %d t:%d s:%d perms:0x%x type:0x%x offset:0x%x base:0x%x length:0x%x", i, dc.isCapability,
dc.sealed, dc.perms, dc.otype, dc.offset-dc.base, dc.base, getLength(dc)));
end
debugInst(reportCapRegs.deq());
end
`endif
if (!exception.notEmpty()) pcc <= newPcc;
debug2("cap", $display("CapCop Writeback, instID:%d==capWBTags.id:%d, capWBTags.valid:%d, capWB.first.instID:%d", wbReq.instId, ct.instId, ct.doWrite, ct.instId));
return ct.writeCap;
endmethod
If you could revise
the fundmental principles of
computer system design
to improve security...
... what would you change?