Add initial exception checks

This commit is contained in:
Peter Rugg
2020-04-06 12:25:44 +01:00
parent 1ecdf73dd3
commit 4ce8f54903
5 changed files with 66 additions and 14 deletions

View File

@@ -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,

View File

@@ -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

View File

@@ -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 *)

View File

@@ -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

View File

@@ -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