Feed capability checks and bounds checks into the memory pipe and back

into the reorder buffer.
This commit is contained in:
jon
2020-05-05 18:28:28 +01:00
parent 500811430b
commit cbb0d859c7
8 changed files with 69 additions and 31 deletions

View File

@@ -192,7 +192,7 @@ endinterface
module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline);
Bool verbose = False;
Integer verbosity = 1;
Integer verbosity = 0;
// alu reservation station
ReservationStationAlu rsAlu <- mkReservationStationAlu;

View File

@@ -63,6 +63,7 @@ typedef struct {
PhyRegs regs;
InstTag tag;
LdStQTag ldstq_tag;
CapChecks cap_checks;
} MemDispatchToRegRead deriving(Bits, Eq, FShow);
typedef struct {
@@ -74,6 +75,7 @@ typedef struct {
// src reg vals
CapPipe rVal1;
CapPipe rVal2;
CapChecks cap_checks;
} MemRegReadToExe deriving(Bits, FShow);
typedef struct {
@@ -90,6 +92,8 @@ typedef struct {
ByteEn store_data_BE;
`endif
Bool misaligned;
Maybe#(CSR_XCapCause) capException;
Maybe#(BoundsCheck) check;
} MemExeToFinish deriving(Bits, FShow);
// bookkeeping when waiting for MMIO resp which may cause exception
@@ -161,7 +165,7 @@ interface MemExeInput;
CapPipe vaddr,
Data store_data, ByteEn store_data_BE,
Bool access_at_commit, Bool non_mmio_st_done,
Maybe#(Exception) cause
Maybe#(CSR_XCapCause) cause
`ifdef RVFI
, ExtraTraceBundle tb
`endif
@@ -207,7 +211,7 @@ interface MemExePipeline;
endinterface
module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
Bool verbose = False;
Bool verbose = True;
// we change cache request in case of single core, becaues our MSI protocol
// is not good with single core
@@ -396,7 +400,8 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
imm: x.data.imm,
regs: x.regs,
tag: x.tag,
ldstq_tag: x.data.ldstq_tag
ldstq_tag: x.data.ldstq_tag,
cap_checks: x.data.cap_checks
},
spec_bits: x.spec_bits
});
@@ -438,7 +443,8 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
tag: x.tag,
ldstq_tag: x.ldstq_tag,
rVal1: rVal1,
rVal2: rVal2
rVal2: rVal2,
cap_checks: x.cap_checks
},
spec_bits: dispToReg.spec_bits
});
@@ -482,6 +488,8 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
lsq.updateData(stTag, d);
end
CapPipe ddc = cast(inIfc.scaprf_rd(SCR_DDC)); // ToDo: feed DDC into the prepareBoundsCheck function below somehow.
// go to next stage by sending to TLB
dTlb.procReq(DTlbReq {
inst: MemExeToFinish {
@@ -494,7 +502,9 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
store_data: data,
store_data_BE: origBE,
`endif
misaligned: memAddrMisaligned(getAddr(vaddr), origBE)
misaligned: memAddrMisaligned(getAddr(vaddr), origBE),
capException: capChecks(x.rVal1, x.rVal2, x.cap_checks),
check: prepareBoundsCheck(x.rVal1, vaddr, almightyCap, x.cap_checks)
},
specBits: regToExe.spec_bits
});
@@ -564,13 +574,15 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
endcase);
Bool access_at_commit = !isValid(cause) && (isMMIO || isLrScAmo);
Bool non_mmio_st_done = !isValid(cause) && !isMMIO && x.mem_func == St;
CapPipe pcc = cast(inIfc.rob_getPC(x.tag));
CapPipe ddc = cast(inIfc.scaprf_rd(SCR_DDC));
Bool ddc_out_of_bounds = !isInBounds(modifyOffset(ddc,getAddr(x.vaddr),True).value,True);
Bool out_of_bounds = (getFlags(pcc) == 1'b1) ? isInBounds(x.vaddr, False):ddc_out_of_bounds;
if (x.check matches tagged Valid .check &&& x.capException matches tagged Invalid) begin
if (!( (check.check_low >= check.authority_base) &&
(check.check_inclusive ? (check.check_high <= check.authority_top )
: (check.check_high < check.authority_top ))))
x.capException = Valid(CSR_XCapCause{cheri_exc_reg: check.authority_idx, cheri_exc_code: LengthViolation});
end
inIfc.rob_setExecuted_doFinishMem(x.tag, x.vaddr, store_data, store_data_BE,
access_at_commit, non_mmio_st_done,
(out_of_bounds) ? Valid(CHERIFault):Invalid
x.capException
`ifdef RVFI
, ExtraTraceBundle{
regWriteData: memData[pack(x.ldstq_tag)],

View File

@@ -697,7 +697,8 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
data: MemRSData {
mem_func: mem_inst.mem_func,
imm: validValue(dInst.imm),
ldstq_tag: lsqTag
ldstq_tag: lsqTag,
cap_checks: dInst.capChecks
},
regs: phy_regs,
tag: inst_tag,

View File

@@ -1,6 +1,6 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@@ -8,10 +8,10 @@
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -31,6 +31,7 @@ typedef struct {
MemFunc mem_func;
ImmData imm;
LdStQTag ldstq_tag;
CapChecks cap_checks;
} MemRSData deriving(Bits, Eq, FShow);
// MEM pipeline is aggressive, i.e. it recv bypass and early RS wakeup

View File

@@ -34,12 +34,6 @@ Bit#(3) memWU = 3'b110;
// Smaller decode functions
function Maybe#(MemInst) decodeMemInst(Instruction inst);
MemInst mem_inst = MemInst{ mem_func: ?,
amo_func: None,
unsignedLd: False,
byteEn: replicate(False),
aq: False,
rl: False };
Bool illegalInst = False;
Opcode opcode = unpackOpcode(inst[6:0]);
let funct5 = inst[31:27];
@@ -152,7 +146,8 @@ function Maybe#(MemInst) decodeMemInst(Instruction inst);
unsignedLd: unsignedLd,
byteEn: byteEn,
aq: aq,
rl: rl } );
rl: rl,
ddc_bounds: True } );
end
endfunction
@@ -230,7 +225,8 @@ function Maybe#(MemInst) decodeCapMemInst(Instruction inst);
unsignedLd: unsignedLd,
byteEn: byteEn,
aq: aq,
rl: rl } );
rl: rl,
ddc_bounds: ddc} );
end
endfunction
@@ -1133,23 +1129,49 @@ function DecodeResult decode(Instruction inst);
end
f7_cap_Loads: begin
dInst.iType = Ld;
if (cap_mem_inst matches tagged Valid .ci) dInst.execFunc = tagged Mem ci;
MemInst mi = cap_mem_inst.Valid;
if (isValid(cap_mem_inst)) dInst.execFunc = tagged Mem mi;
else illegalInst = True;
regs.dst = Valid(tagged Gpr rd);
regs.src1 = Valid(tagged Gpr rs1);
regs.src2 = Invalid;
dInst.imm = Valid (0);
dInst.csr = tagged Invalid;
dInst.capChecks.check_enable = True;
dInst.capChecks.check_low_src = Src1Addr;
dInst.capChecks.check_high_src = Src1AddrPlus2; // Should add the access size somehow...
dInst.capChecks.check_inclusive = True;
if (mi.ddc_bounds) begin
dInst.capChecks.check_authority_src = Ddc;
end else begin
dInst.capChecks.check_authority_src = Src1;
dInst.capChecks.src1_tag = True;
dInst.capChecks.src1_unsealed = True;
end
end
f7_cap_Stores: begin
dInst.iType = St;
if (cap_mem_inst matches tagged Valid .ci) dInst.execFunc = tagged Mem ci;
MemInst mi = cap_mem_inst.Valid;
if (isValid(cap_mem_inst)) dInst.execFunc = tagged Mem mi;
else illegalInst = True;
regs.dst = Invalid;
regs.src1 = Valid(tagged Gpr rs1);
regs.src2 = Valid(tagged Gpr rs2);
dInst.imm = Valid (0);
dInst.csr = tagged Invalid;
dInst.capChecks.check_enable = True;
dInst.capChecks.check_low_src = Src1Addr;
dInst.capChecks.check_high_src = Src1AddrPlus2; // Should add the access size somehow...
dInst.capChecks.check_inclusive = True;
if (mi.ddc_bounds) begin
dInst.capChecks.check_authority_src = Ddc;
end else begin
dInst.capChecks.check_authority_src = Src1;
dInst.capChecks.src1_tag = True;
dInst.capChecks.src1_unsealed = True;
end
end
f7_cap_TwoOp: begin
case (funct5rs2)

View File

@@ -500,7 +500,8 @@ typedef struct {
typedef enum {
Src1,
Src2,
Pcc
Pcc,
Ddc
} CheckAuthoritySrc deriving(Bits, Eq, FShow);
typedef enum {

View File

@@ -157,7 +157,7 @@ interface ReorderBufferRowEhr#(numeric type aluExeNum, numeric type fpuMulDivExe
method Action setExecuted_doFinishMem(CapPipe vaddr,
Data store_data, ByteEn store_data_BE,
Bool access_at_commit, Bool non_mmio_st_done,
Maybe#(Exception) cause
Maybe#(CSR_XCapCause) cause
`ifdef RVFI
, ExtraTraceBundle tb
`endif
@@ -357,7 +357,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p
method Action setExecuted_doFinishMem(CapPipe vaddr,
Data store_data, ByteEn store_data_BE,
Bool access_at_commit, Bool non_mmio_st_done,
Maybe#(Exception) cause
Maybe#(CSR_XCapCause) cause
`ifdef RVFI
, ExtraTraceBundle tb
`endif
@@ -385,7 +385,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p
// udpate non mmio st
nonMMIOStDone[nonMMIOSt_finishMem_port] <= non_mmio_st_done;
if (cause matches tagged Valid .exp) begin
mem_early_trap[0] <= Valid ( Exception (exp));
mem_early_trap[0] <= Valid ( CapException (exp));
tval[trap_finishMem_port] <= tval[trap_finishMem_port];
end
endmethod
@@ -626,7 +626,7 @@ interface SupReorderBuffer#(numeric type aluExeNum, numeric type fpuMulDivExeNum
CapPipe vaddr,
Data store_data, ByteEn store_data_BE,
Bool access_at_commit, Bool non_mmio_st_done,
Maybe#(Exception) cause
Maybe#(CSR_XCapCause) cause
`ifdef RVFI
, ExtraTraceBundle tb
`endif
@@ -1239,7 +1239,7 @@ module mkSupReorderBuffer#(
method Action setExecuted_doFinishMem(
InstTag x, CapPipe vaddr, Data store_data, ByteEn store_data_BE, Bool access_at_commit,
Bool non_mmio_st_done, Maybe#(Exception) cause
Bool non_mmio_st_done, Maybe#(CSR_XCapCause) cause
`ifdef RVFI
, tb
`endif

View File

@@ -124,6 +124,7 @@ typedef struct {
MemDataByteEn byteEn; // takes place of double word
Bool aq;
Bool rl;
Bool ddc_bounds;
} MemInst deriving(Bits, Eq, FShow);
`ifdef BSIM