Feed capability checks and bounds checks into the memory pipe and back
into the reorder buffer.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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)],
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -500,7 +500,8 @@ typedef struct {
|
||||
typedef enum {
|
||||
Src1,
|
||||
Src2,
|
||||
Pcc
|
||||
Pcc,
|
||||
Ddc
|
||||
} CheckAuthoritySrc deriving(Bits, Eq, FShow);
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user