Implement CCall, hopefully as well as CJALR.

This passes the unmodified TestRIG routine for CHERI Control Flow, which is very promising indeed!
There are some cases that are not covered there, but a lot is covered.
This commit is contained in:
jon
2020-04-14 18:10:53 +01:00
parent 72dc8f8bad
commit 9685bf1931
3 changed files with 53 additions and 28 deletions

View File

@@ -823,21 +823,22 @@ function DecodeResult decode(Instruction inst);
f7_cap_TwoSrc: begin
case (rd)
rd_cap_CCall: begin
// TODO
// dInst.capChecks.src1_tag = True;
// dInst.capChecks.src2_tag = True;
// dInst.capChecks.src1_sealed = True;
// dInst.capChecks.src2_sealed = True;
// dInst.capChecks.src1_src2_types_match = True;
// dInst.capChecks.src1_permit_x = True;
// dInst.capChecks.src2_no_permit_x = True;
// dInst.capChecks.src1_permit_ccall = True;
// dInst.capChecks.src2_permit_ccall = True;
dInst.capChecks.src1_tag = True;
dInst.capChecks.src2_tag = True;
dInst.capChecks.src1_sealed = True;
dInst.capChecks.src2_sealed = True;
dInst.capChecks.src1_src2_types_match = True;
dInst.capChecks.src1_permit_x = True;
dInst.capChecks.src2_no_permit_x = True;
dInst.capChecks.src1_permit_ccall = True;
dInst.capChecks.src2_permit_ccall = True;
// regs.rd = Invalid;
// regs.src1 = Valid(tagged Gpr rs1);
// regs.src2 = Valid(tagged Gpr rs2);
// dInst.imm = Invalid;
dInst.iType = Jr;
dInst.execFunc = tagged Br AT;
regs.dst = Valid(tagged Gpr 31);
regs.src1 = Valid(tagged Gpr rs1);
regs.src2 = Valid(tagged Gpr rs2);
dInst.imm = Invalid;
end
default: begin
illegalInst = True;
@@ -857,7 +858,7 @@ function DecodeResult decode(Instruction inst);
regs.src1 = Valid(tagged Gpr rs1);
regs.src2 = Valid(tagged Gpr rs2);
dInst.imm = Invalid;
dInst.execFunc = CapModify (Unseal);
dInst.execFunc = CapModify (Unseal (Src1));
end
f7_cap_CTestSubset: begin
dInst.iType = Alu;
@@ -1036,16 +1037,16 @@ function DecodeResult decode(Instruction inst);
dInst.execFunc = CapInspect (GetPerm);
end
f5rs2_cap_CJALR: begin
dInst.capChecks.src1_tag = True;
dInst.capChecks.src1_permit_x = True;
dInst.capChecks.src1_unsealed = True;
dInst.iType = Jr;
dInst.execFunc = tagged Br AT;
regs.dst = Valid(tagged Gpr rd);
regs.src1 = Valid(tagged Gpr rs1);
regs.src2 = Invalid;
dInst.imm = Invalid;
//dInst.scr = tagged Valid SCR_PCC;
dInst.execFunc = tagged Br AT;
dInst.capChecks.src1_tag = True;
dInst.capChecks.src1_permit_x = True;
dInst.capChecks.src1_unsealed = True;
end
f5rs2_cap_CGetType: begin
dInst.iType = Alu;

View File

@@ -110,8 +110,8 @@ function CapPipe capModify(CapPipe a, CapPipe b, CapModifyFunc func);
setAddr(a, addrSource == Src2Type ? (isSealed(b) ? zeroExtend(getType(b)) : -1) : getAddr(b)).value;
tagged Seal :
setType(a, truncate(getAddr(b)));
tagged Unseal :
setType(a, -1);
tagged Unseal .src :
setType(((src == Src1) ? a:b), -1);
tagged AndPerm :
setPerms(a, pack(getPerms(a)) & truncate(getAddr(b)));
tagged SetFlags :
@@ -213,7 +213,13 @@ function ExecResult basicExec(DecodedInst dInst, CapPipe rVal1, CapPipe rVal2, C
CapPipe data = nullCap;
Data csr_data = 0;
CapPipe addr = nullCap;
Bool cjalr = (dInst.iType == Jr) && dInst.capChecks.src1_tag;
Bool cjalr = False;
Bool ccall = False;
if (dInst.iType == Jr) begin
if (dInst.capChecks.src1_src2_types_match) ccall = True;
else if (dInst.capChecks.src1_tag) cjalr = True;
end
ControlFlow cf = ControlFlow{pc: pc, nextPc: 0, taken: False, newPcc: cjalr, mispredict: False};
CapPipe aluVal2 = rVal2;
@@ -223,11 +229,13 @@ function ExecResult basicExec(DecodedInst dInst, CapPipe rVal1, CapPipe rVal2, C
Data alu_result = alu(getAddr(rVal1), getAddr(aluVal2), alu_f);
Data inspect_result = capInspect(rVal1, aluVal2, dInst.execFunc.CapInspect);
CapPipe modify_result = capModify(rVal1, aluVal2, dInst.execFunc.CapModify);
CapModifyFunc modFunc = ccall ? (Unseal (Src1)):dInst.execFunc.CapModify;
CapPipe modify_result = capModify(rVal1, aluVal2, modFunc);
Maybe#(CapException) capException = capChecks(rVal1, aluVal2, dInst.capChecks); // TODO use this to throw exceptions
CapPipe cap_alu_result = case (dInst.execFunc) matches tagged CapInspect .x: nullWithAddr(inspect_result);
tagged CapModify .x: modify_result;
tagged Br .x: modify_result;
default: nullWithAddr(alu_result);
endcase;
@@ -240,9 +248,14 @@ function ExecResult basicExec(DecodedInst dInst, CapPipe rVal1, CapPipe rVal2, C
Addr fallthrough_incr = ((orig_inst [1:0] == 2'b11) ? 4 : 2);
CapPipe link_pcc = setAddrUnsafe(pcc, getAddr(pcc) + fallthrough_incr);
data = (case (dInst.iType)
St, Sc, Amo : rVal2;
J, Jr : (cjalr ? link_pcc : nullWithAddr(getAddr(link_pcc))); // could be computed with alu
data = (case (dInst.iType) matches
St : rVal2;
Sc : rVal2;
Amo : rVal2;
J : nullWithAddr(getAddr(link_pcc));
Jr &&& (ccall): cap_alu_result; // Depending on defaults falling through!
Jr &&& (cjalr): link_pcc;
Jr : nullWithAddr(getAddr(link_pcc));
Auipc : nullWithAddr(pc + fromMaybe(?, getDInstImm(dInst))); // could be computed with alu
Csr : rVal1;
default : cap_alu_result;

View File

@@ -224,6 +224,13 @@ function Opcode unpackOpcode(Bit#(7) x);
endcase);
endfunction
/* If Bluespec never allows illegal values of sparse enumerated types, this function should replace the one above:
function Opcode unpackOpcode(Bit#(7) x);
Opcode test = unpack(x);
if (pack(test) != x) return Invalid;
else return test;
endfunction
*/
typedef enum {
// user standard CSRs
CSRfflags = 12'h001,
@@ -420,13 +427,17 @@ typedef enum {
Src2Type, Src2Addr
} AddrSource deriving(Bits, Eq, FShow);
typedef enum {
Src1, Src2
} SrcSelector deriving(Bits, Eq, FShow);
typedef union tagged {
ModifyOffsetFunc ModifyOffset;
Bool SetBounds;
void SpecialRW;
AddrSource SetAddr;
void Seal;
void Unseal;
SrcSelector Unseal;
void AndPerm;
void SetFlags;
void BuildCap;