From 4ce8f54903a0d6f2ab3c05b45458c43a107d8588 Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Mon, 6 Apr 2020 12:25:44 +0100 Subject: [PATCH] Add initial exception checks --- src_Core/ISA/ISA_Decls_CHERI.bsv | 9 ++-- .../procs/RV64G_OOO/AluExePipeline.bsv | 6 ++- src_Core/RISCY_OOO/procs/lib/Exec.bsv | 48 +++++++++++++++++-- src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv | 7 +++ .../RISCY_OOO/procs/lib/ReorderBuffer.bsv | 10 ++-- 5 files changed, 66 insertions(+), 14 deletions(-) diff --git a/src_Core/ISA/ISA_Decls_CHERI.bsv b/src_Core/ISA/ISA_Decls_CHERI.bsv index 14851c4..df5a8be 100644 --- a/src_Core/ISA/ISA_Decls_CHERI.bsv +++ b/src_Core/ISA/ISA_Decls_CHERI.bsv @@ -42,10 +42,11 @@ typedef enum { CallTrap = 5'd5, ReturnTrap = 5'd6, StackUnderflow = 5'd7, - MMUStoreCapProhibit = 5'd8, - RepresentViolation = 5'd9, - UnalignedBase = 5'd10, - // 5'd11 - 5'd15 reserved + SoftwarePermViolation = 5'd8, + MMUStoreCapProhibit = 5'd9, + RepresentViolation = 5'd10, + UnalignedBase = 5'd11, + // 5'd12 - 5'd15 reserved GlobalViolation = 5'd16, PermitXViolation = 5'd17, PermitRViolation = 5'd18, diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv index 929fd34..3304cc1 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv @@ -88,6 +88,7 @@ typedef struct { CapPipe data; // alu compute result Maybe#(Data) csrData; // data to write CSR file ControlFlow controlFlow; + Maybe#(CapException) capException; // speculation Maybe#(SpecTag) spec_tag; `ifdef RVFI @@ -154,7 +155,7 @@ interface AluExeInput; CapPipe dst_data, Maybe#(Data) csrData, ControlFlow cf, - Maybe#(Exception) cause, + Maybe#(CapException) capCause, CapPipe pcc `ifdef RVFI , ExtraTraceBundle tb @@ -347,7 +348,7 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline); x.data, x.csrData, x.controlFlow, - tagged Invalid, + x.capException, cast(inIfc.scaprf_rd(SCR_PCC)) `ifdef RVFI , x.traceBundle @@ -355,6 +356,7 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline); ); // handle spec tags for branch predictions + // TODO what happens here if we trap? (* split *) if (x.controlFlow.mispredict) (* nosplit *) begin // wrong branch predictin, we must have spec tag diff --git a/src_Core/RISCY_OOO/procs/lib/Exec.bsv b/src_Core/RISCY_OOO/procs/lib/Exec.bsv index ec8aaff..6bffeb0 100755 --- a/src_Core/RISCY_OOO/procs/lib/Exec.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Exec.bsv @@ -28,6 +28,48 @@ import ProcTypes::*; import Vector::*; import CHERICap::*; import CHERICC_Fat::*; +import ISA_Decls_CHERI::*; + +(* noinline *) +function Maybe#(CapException) capChecks(CapPipe a, CapPipe b, CapChecks toCheck); + // TODO plumb register indices here + Maybe#(CapException) result = Invalid; + if (toCheck.src1_tag && !isValidCap(a)) + result = Valid (CapException {excCode: TagViolation}); + else if (toCheck.src2_tag && !isValidCap(b)) + result = Valid (CapException {excCode: TagViolation}); + else if (toCheck.src1_sealed_with_type && getKind(a) != SEALED_WITH_TYPE) + result = Valid (CapException {excCode: SealViolation}); + else if (toCheck.src1_unsealed && isValidCap(a) && isSealed(a)) + result = Valid (CapException {excCode: SealViolation}); + else if (toCheck.src2_unsealed && isValidCap(b) && isSealed(b)) + result = Valid (CapException {excCode: SealViolation}); + else if (toCheck.src1_sealed && isValidCap(a) && !isSealed(a)) + result = Valid (CapException {excCode: SealViolation}); + else if (toCheck.src2_sealed && isValidCap(b) && !isSealed(b)) + result = Valid (CapException {excCode: SealViolation}); + else if (toCheck.src1_src2_types_match && getType(a) != getType(b)) + result = Valid (CapException {excCode: TypeViolation}); + else if (toCheck.src1_permit_ccall && !getHardPerms(a).permitCCall) + result = Valid (CapException {excCode: PermitCCallViolation}); + else if (toCheck.src2_permit_ccall && !getHardPerms(b).permitCCall) + result = Valid (CapException {excCode: PermitCCallViolation}); + else if (toCheck.src1_permit_x && !getHardPerms(a).permitExecute) + result = Valid (CapException {excCode: PermitXViolation}); + else if (toCheck.src2_no_permit_x && getHardPerms(b).permitExecute) + result = Valid (CapException {excCode: PermitXViolation}); + else if (toCheck.src2_permit_unseal && !getHardPerms(b).permitUnseal) + result = Valid (CapException {excCode: PermitUnsealViolation}); + else if (toCheck.src2_permit_seal && !getHardPerms(b).permitSeal) + result = Valid (CapException {excCode: PermitSealViolation}); + else if (toCheck.src2_points_to_src1_type && getAddr(b) != zeroExtend(getType(a))) + result = Valid (CapException {excCode: TypeViolation}); + else if (toCheck.src2_addr_valid_type && !validAsType(b, truncate(getAddr(b)))) + result = Valid (CapException {excCode: LengthViolation}); + else if (toCheck.src2_perm_subset_src1 && (getPerms(a) & getPerms(b)) != getPerms(b)) + result = Valid (CapException {excCode: SoftwarePermViolation}); + return result; +endfunction (* noinline *) function Data alu(Data a, Data b, AluFunc func); @@ -58,7 +100,7 @@ endfunction (* noinline *) function CapPipe capModify(CapPipe a, CapPipe b, CapModifyFunc func); CapPipe res = (case(func) matches - tagged ModifyOffset .offsetOp: + tagged ModifyOffset .offsetOp : modifyOffset(a, getAddr(b), offsetOp == IncOffset).value; tagged SetBounds .exact : setBounds(a, getAddr(b)).value; @@ -178,9 +220,9 @@ function ExecResult basicExec(DecodedInst dInst, CapPipe rVal1, CapPipe rVal2, A AluFunc alu_f = dInst.execFunc matches tagged Alu .alu_f ? alu_f : Add; Data alu_result = alu(getAddr(rVal1), getAddr(aluVal2), alu_f); - // Pass capabilities into these functions when they are passed in. Data inspect_result = capInspect(rVal1, aluVal2, dInst.execFunc.CapInspect); CapPipe modify_result = capModify(rVal1, aluVal2, dInst.execFunc.CapModify); + Maybe#(CapException) capException = capChecks(rVal1, aluVal2, dInst.capChecks); // TODO use this to throw exceptions // Default branch function is not taken BrFunc br_f = dInst.execFunc matches tagged Br .br_f ? br_f : NT; @@ -205,7 +247,7 @@ function ExecResult basicExec(DecodedInst dInst, CapPipe rVal1, CapPipe rVal2, A default : nullWithAddr(cf.nextPc); endcase); - return ExecResult{data: data, csrData: csr_data, addr: addr, controlFlow: cf}; + return ExecResult{data: data, csrData: csr_data, addr: addr, controlFlow: cf, capException: capException}; endfunction (* noinline *) diff --git a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index 44a919d..f0ee5f1 100755 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -33,6 +33,7 @@ import CHERICC_Fat::*; `ifdef RVFI_DII import RVFI_DII_Types::*; `endif +import ISA_Decls_CHERI::*; typedef `NUM_CORES CoreNum; typedef Bit#(TLog#(CoreNum)) CoreId; @@ -677,6 +678,11 @@ typedef struct { Bool src2_derivable; } CapChecks deriving(Bits, Eq, FShow); +typedef struct { + CHERIException excCode; +// TODO GPR or SCR index of cause; +} CapException deriving(Bits, FShow); + typedef struct { IType iType; ExecFunc execFunc; @@ -694,6 +700,7 @@ typedef struct { Data csrData; CapPipe addr; ControlFlow controlFlow; + Maybe#(CapException) capException; } ExecResult deriving(Bits, FShow); // MMIO diff --git a/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv b/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv index 4f720c4..c429727 100644 --- a/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv @@ -114,7 +114,7 @@ interface Row_setExecuted_doFinishAlu; CapPipe dst_data, Maybe#(Data) csrData, ControlFlow cf, - Maybe#(Exception) cause, + Maybe#(CapException) cause, CapPipe pcc `ifdef RVFI , ExtraTraceBundle tb @@ -285,7 +285,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p CapPipe dst_data, Maybe#(Data) csrData, ControlFlow cf, - Maybe#(Exception) cause, + Maybe#(CapException) cause, CapPipe pcc `ifdef RVFI , ExtraTraceBundle tb @@ -309,7 +309,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p trap[trap_finishAlu_port(i)] <= Valid (tagged Exception CHERIFault); tval[trap_finishAlu_port(i)] <= tval[trap_finishAlu_port(i)]; end else if (cause matches tagged Valid .exp) begin - trap[trap_finishAlu_port(i)] <= Valid (tagged Exception exp); + trap[trap_finishAlu_port(i)] <= Valid (tagged Exception CHERIFault); // TODO propagate CHERI cause tval[trap_finishAlu_port(i)] <= tval[trap_finishAlu_port(i)]; end `ifdef RVFI @@ -587,7 +587,7 @@ interface ROB_setExecuted_doFinishAlu; CapPipe dst_data, Maybe#(Data) csrData, ControlFlow cf, - Maybe#(Exception) cause, + Maybe#(CapException) cause, CapPipe pcc `ifdef RVFI , ExtraTraceBundle tb @@ -1135,7 +1135,7 @@ module mkSupReorderBuffer#( CapPipe dst_data, Maybe#(Data) csrData, ControlFlow cf, - Maybe#(Exception) cause, + Maybe#(CapException) cause, CapPipe pcc `ifdef RVFI , ExtraTraceBundle tb