From 9685bf1931626a26df6a88b1030f2a080eee58de Mon Sep 17 00:00:00 2001 From: jon Date: Tue, 14 Apr 2020 18:10:53 +0100 Subject: [PATCH] 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. --- src_Core/RISCY_OOO/procs/lib/Decode.bsv | 41 +++++++++++----------- src_Core/RISCY_OOO/procs/lib/Exec.bsv | 27 ++++++++++---- src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv | 13 ++++++- 3 files changed, 53 insertions(+), 28 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/lib/Decode.bsv b/src_Core/RISCY_OOO/procs/lib/Decode.bsv index 4a38880..5f0e08c 100755 --- a/src_Core/RISCY_OOO/procs/lib/Decode.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Decode.bsv @@ -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; diff --git a/src_Core/RISCY_OOO/procs/lib/Exec.bsv b/src_Core/RISCY_OOO/procs/lib/Exec.bsv index bceede9..0f5848f 100755 --- a/src_Core/RISCY_OOO/procs/lib/Exec.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Exec.bsv @@ -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; diff --git a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index 3f9b61d..3287fa0 100755 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -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;