Bounds-check the target of CCall.

Also handle more invalid decodings of explicit capability instructions
correctly.
This commit is contained in:
jon
2020-05-08 12:15:35 +01:00
parent 9631a9db4b
commit e3b532089d
3 changed files with 32 additions and 17 deletions

View File

@@ -16,5 +16,6 @@
`CAP_CHECK_FIELD(src2_permit_seal,"src2_permit_seal")
`CAP_CHECK_FIELD(src2_points_to_src1_type,"src2_points_to_src1_type")
`CAP_CHECK_FIELD(src2_addr_valid_type,"src2_addr_valid_type")
`CAP_CHECK_FIELD(src2_type_not_reserved,"src2_type_not_reserved")
`CAP_CHECK_FIELD(src1_perm_subset_src2,"src1_perm_subset_src2")
`CAP_CHECK_FIELD(src1_derivable,"src1_derivable")

View File

@@ -151,7 +151,7 @@ function Maybe#(MemInst) decodeMemInst(Instruction inst);
end
endfunction
function Maybe#(MemInst) decodeCapMemInst(Instruction inst);
function Maybe#(MemInst) decodeExplicitBoundsMemInst(Instruction inst);
// This function trusts that its result will only be used by
// explicit capability instructions as identified by the primary
// decode case, and therefore does not attempt to return sensible
@@ -161,13 +161,24 @@ function Maybe#(MemInst) decodeCapMemInst(Instruction inst);
Bit#(5) mem_code = (funct7==f7_cap_Loads) ? inst[24:20]:inst[11:7];
Bool amo = unpack(mem_code[4]);
Bool bounds_from_register = unpack(mem_code[3]);
Bool unsind = unpack(mem_code[2]);
// unsignedLd
// it doesn't matter if this is set to True for stores
Bool unsignedLd = unpack(mem_code[2]);
Bit#(2) width = mem_code[1:0];
Bool capWidth = (funct7 == f7_cap_Stores && unsind && width == 0);
if (funct7 == f7_cap_Loads && amo && width == 3) begin
Bool capWidth = False;
if (funct7 == f7_cap_Stores && unsignedLd) begin
capWidth = True;
amo = False;
if (width != 0) illegalInst = True;
end
if (funct7 == f7_cap_Loads && amo && unsignedLd) begin
unsignedLd = False;
capWidth = True;
case (width)
0 : amo = amo; // Don't do anything in this case.
3 : amo = False;
default : illegalInst = True;
endcase
end
// mem_func + amo_func
@@ -179,13 +190,7 @@ function Maybe#(MemInst) decodeCapMemInst(Instruction inst);
mem_func = (amo) ? Sc:St;
end
// unsignedLd
// it doesn't matter if this is set to True for stores
Bool unsignedLd = unsind;
// byteEn
// TODO: Some combinations of operations and byteEn's are illegal.
// They should be detected here.
MemDataByteEn byteEn = (capWidth) ? replicate(True):replicate(False);
if (!capWidth) begin
case (width)
@@ -210,7 +215,7 @@ function Maybe#(MemInst) decodeCapMemInst(Instruction inst);
byteEn[6] = True;
byteEn[7] = True;
// In RV64 we don't allow unsigned double operations!
if (unsind) illegalInst = True;
if (unsignedLd) illegalInst = True;
end
endcase
end
@@ -294,7 +299,7 @@ function DecodeResult decode(Instruction inst, Bool cap_mode);
// Results of mini-decoders
Maybe#(MemInst) mem_inst = decodeMemInst(inst);
Maybe#(MemInst) cap_mem_inst = decodeCapMemInst(inst);
Maybe#(MemInst) exp_bnds_mem_inst = decodeExplicitBoundsMemInst(inst);
// TODO better detection of illegal insts
case (opcode)
@@ -1013,11 +1018,18 @@ function DecodeResult decode(Instruction inst, Bool cap_mode);
dInst.capChecks.src1_sealed = True;
dInst.capChecks.src2_sealed = True;
dInst.capChecks.src1_src2_types_match = True;
dInst.capChecks.src2_type_not_reserved = 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.check_enable = True;
dInst.capChecks.check_authority_src = Src1;
dInst.capChecks.check_low_src = Src1Addr;
dInst.capChecks.check_high_src = Src1AddrPlus2;
dInst.capChecks.check_inclusive = True;
dInst.iType = Jr;
dInst.execFunc = tagged Br AT;
regs.dst = Valid(tagged Gpr 31);
@@ -1165,8 +1177,8 @@ function DecodeResult decode(Instruction inst, Bool cap_mode);
end
f7_cap_Loads: begin
dInst.iType = Ld;
MemInst mi = cap_mem_inst.Valid;
if (isValid(cap_mem_inst)) dInst.execFunc = tagged Mem mi;
MemInst mi = exp_bnds_mem_inst.Valid;
if (isValid(exp_bnds_mem_inst)) dInst.execFunc = tagged Mem mi;
else illegalInst = True;
regs.dst = Valid(tagged Gpr rd);
regs.src1 = Valid(tagged Gpr rs1);
@@ -1177,8 +1189,8 @@ function DecodeResult decode(Instruction inst, Bool cap_mode);
end
f7_cap_Stores: begin
dInst.iType = St;
MemInst mi = cap_mem_inst.Valid;
if (isValid(cap_mem_inst)) dInst.execFunc = tagged Mem mi;
MemInst mi = exp_bnds_mem_inst.Valid;
if (isValid(exp_bnds_mem_inst)) dInst.execFunc = tagged Mem mi;
else illegalInst = True;
regs.dst = Invalid;
regs.src1 = Valid(tagged Gpr rs1);

View File

@@ -71,6 +71,8 @@ function Maybe#(CSR_XCapCause) capChecks(CapPipe a, CapPipe b, CapPipe ddc, CapC
result = e2(TypeViolation);
else if (toCheck.src2_addr_valid_type && !validAsType(b, truncate(getAddr(b))))
result = e2(LengthViolation);
else if (toCheck.src2_type_not_reserved && !validAsType(b, zeroExtend(getType(b))))
result = e2(TypeViolation);
else if (toCheck.src1_perm_subset_src2 && (getPerms(a) & getPerms(b)) != getPerms(a))
result = e2(SoftwarePermViolation);
else if (toCheck.src1_derivable && !isDerivable(a))