Refactor to allow some operations on CapReg

This commit is contained in:
Peter Rugg
2019-11-18 17:14:31 +00:00
parent 5953acc8c1
commit d987f2b035
2 changed files with 176 additions and 131 deletions

View File

@@ -335,7 +335,7 @@ function LCapAddress regToSignedLAddr(Address in);
return signExtend(retVal); return signExtend(retVal);
endfunction endfunction
function Bool isSealed(CapFat cap) = (cap.otype != otype_unsealed); function Bool isSealed(CapFat cap) = (cap.otype != otype_unsealed);
function CType getType(CapFat cap) = VnD{v: (cap.otype != otype_unsealed), d: cap.otype}; function CType getTypeFat(CapFat cap) = VnD{v: (cap.otype != otype_unsealed), d: cap.otype};
function Bit#(31) getPerms(CapFat cap); function Bit#(31) getPerms(CapFat cap);
Bit#(SizeOf#(HPerms)) hardPerms = zeroExtend(pack(cap.perms.hard)); Bit#(SizeOf#(HPerms)) hardPerms = zeroExtend(pack(cap.perms.hard));
Bit#(UPermW) softPerms = zeroExtend(pack(cap.perms.soft)); Bit#(UPermW) softPerms = zeroExtend(pack(cap.perms.soft));
@@ -381,7 +381,7 @@ endfunction
function Bool boundsCheck(CapFat cap, Bit#(CapAddressW) off, TempFields tf); function Bool boundsCheck(CapFat cap, Bit#(CapAddressW) off, TempFields tf);
Bit#(TAdd#(CapAddressW,2)) bo = zeroExtend(off); Bit#(TAdd#(CapAddressW,2)) bo = zeroExtend(off);
cap = incOffset(cap, cap.address+truncate(bo), off, tf, False).d; cap = incOffsetFat(cap, cap.address+truncate(bo), off, tf, False).d;
return cap.isCapability && capInBounds(cap, tf, False); return cap.isCapability && capInBounds(cap, tf, False);
endfunction endfunction
@@ -416,13 +416,13 @@ function Tuple2#(CapFat, Bool) setBoundsFat(CapFat cap, Address lengthFull);
CapAddress tmpAddr = truncate(cap.address); CapAddress tmpAddr = truncate(cap.address);
LCapAddress base = zeroExtend(tmpAddr); LCapAddress base = zeroExtend(tmpAddr);
Bit#(TAdd#(MW,1)) newBaseBits = truncate(base>>e); Bit#(TAdd#(MW,1)) newBaseBits = truncate(base>>e);
// Derive new top bits by extracting MW bits from the capability // Derive new top bits by extracting MW bits from the capability
// address + requested length, starting at the new exponent's position, // address + requested length, starting at the new exponent's position,
// and rounding up if significant bits are lost in the process. // and rounding up if significant bits are lost in the process.
LCapAddress len = zeroExtend(length); LCapAddress len = zeroExtend(length);
LCapAddress top = base + len; LCapAddress top = base + len;
// Create a mask with all bits set below the MSB of length and then masking all bits // Create a mask with all bits set below the MSB of length and then masking all bits
// below the mantissa bits. // below the mantissa bits.
LCapAddress lmask = smearMSBRight(len); LCapAddress lmask = smearMSBRight(len);
@@ -430,7 +430,7 @@ function Tuple2#(CapFat, Bool) setBoundsFat(CapFat cap, Address lengthFull);
// The shift amount required to put the most significant set bit of the // The shift amount required to put the most significant set bit of the
// len just above the bottom HalfExpW bits that are taken by the exp. // len just above the bottom HalfExpW bits that are taken by the exp.
Integer shiftAmount = valueOf(TSub#(TSub#(MW,2),HalfExpW)); Integer shiftAmount = valueOf(TSub#(TSub#(MW,2),HalfExpW));
// Calculate all values associated with E=e (e not rounding up) // Calculate all values associated with E=e (e not rounding up)
// Round up considering the stolen HalfExpW exponent bits if required // Round up considering the stolen HalfExpW exponent bits if required
Bit#(TAdd#(MW,1)) newTopBits = truncate(top>>e); Bit#(TAdd#(MW,1)) newTopBits = truncate(top>>e);
@@ -449,7 +449,7 @@ function Tuple2#(CapFat, Bool) setBoundsFat(CapFat cap, Address lengthFull);
Bool lostSignificantBase = (base&lmaskLo)!=0 && intExp; Bool lostSignificantBase = (base&lmaskLo)!=0 && intExp;
// If either base or top lost significant bits and we wanted an exact setBounds, // If either base or top lost significant bits and we wanted an exact setBounds,
// void the return capability // void the return capability
// Calculate all values associated with E=e+1 (e rounding up due to msb of L increasing by 1) // Calculate all values associated with E=e+1 (e rounding up due to msb of L increasing by 1)
// This value is just to avoid adding later. // This value is just to avoid adding later.
Bit#(MW) newTopBitsHigher = truncateLSB(newTopBits); Bit#(MW) newTopBitsHigher = truncateLSB(newTopBits);
@@ -464,8 +464,8 @@ function Tuple2#(CapFat, Bool) setBoundsFat(CapFat cap, Address lengthFull);
Bool lostSignificantBaseHigher = (base&lmaskLo)!=0 && intExp; Bool lostSignificantBaseHigher = (base&lmaskLo)!=0 && intExp;
// If either base or top lost significant bits and we wanted an exact setBounds, // If either base or top lost significant bits and we wanted an exact setBounds,
// void the return capability // void the return capability
// We need to round up Exp if the length is within 1 of the maximum and if it will increase. // We need to round up Exp if the length is within 1 of the maximum and if it will increase.
// The lomask for checking for potential overflow should mask all but the bottom bit of the mantissa. // The lomask for checking for potential overflow should mask all but the bottom bit of the mantissa.
lmaskLo = lmask>>fromInteger(shiftAmount); lmaskLo = lmask>>fromInteger(shiftAmount);
@@ -481,8 +481,8 @@ function Tuple2#(CapFat, Bool) setBoundsFat(CapFat cap, Address lengthFull);
ret.bounds.baseBits = truncate(newBaseBits); ret.bounds.baseBits = truncate(newBaseBits);
if (lostSignificantBase || lostSignificantTop) resultExact = False; if (lostSignificantBase || lostSignificantTop) resultExact = False;
end end
ret.bounds.exp = e; ret.bounds.exp = e;
// Update the addrBits fields // Update the addrBits fields
ret.addrBits = ret.bounds.baseBits; ret.addrBits = ret.bounds.baseBits;
@@ -496,7 +496,7 @@ function Tuple2#(CapFat, Bool) setBoundsFat(CapFat cap, Address lengthFull);
ret.bounds.baseBits = {truncateLSB(ret.bounds.baseBits), botZeroes}; ret.bounds.baseBits = {truncateLSB(ret.bounds.baseBits), botZeroes};
ret.bounds.topBits = {truncateLSB(ret.bounds.topBits), botZeroes}; ret.bounds.topBits = {truncateLSB(ret.bounds.topBits), botZeroes};
end end
// Return derived capability // Return derived capability
return tuple2(ret, resultExact); return tuple2(ret, resultExact);
endfunction endfunction
@@ -511,7 +511,7 @@ function CapFat unseal(CapFat cap, x _);
ret.otype = otype_unsealed; ret.otype = otype_unsealed;
return ret; return ret;
endfunction endfunction
function VnD#(CapFat) incOffset(CapFat cap, LCapAddress pointer, Bit#(CapAddressW) offset/*this is the increment in inc offset, and the offset in set offset*/, TempFields tf, Bool setOffset); function VnD#(CapFat) incOffsetFat(CapFat cap, LCapAddress pointer, Bit#(CapAddressW) offset/*this is the increment in inc offset, and the offset in set offset*/, TempFields tf, Bool setOffset);
// NOTE: // NOTE:
// The 'offset' argument is the "increment" value when setOffset is false, // The 'offset' argument is the "increment" value when setOffset is false,
// and the actual "offset" value when setOffset is true. // and the actual "offset" value when setOffset is true.
@@ -766,7 +766,7 @@ function Tuple2#(Format, Bounds) decBounds (CBounds raw);
//bounds.topBits = 0; //bounds.topBits = 0;
//bounds.baseBits = 0; //bounds.baseBits = 0;
Bit#(HalfExpW) halfExp0 = 0; Bit#(HalfExpW) halfExp0 = 0;
case (format) case (format)
EmbeddedExp: begin EmbeddedExp: begin
BoundsEmbeddedExp b = unpack(raw); BoundsEmbeddedExp b = unpack(raw);
@@ -870,7 +870,6 @@ instance CHERICap #(CapMem, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
function setType = error("feature not implemented for this cap type"); function setType = error("feature not implemented for this cap type");
function getAddr = error("feature not implemented for this cap type"); function getAddr = error("feature not implemented for this cap type");
function setAddr = error("feature not implemented for this cap type"); function setAddr = error("feature not implemented for this cap type");
function maskAddr = error("feature not implemented for this cap type");
function getOffset = error("feature not implemented for this cap type"); function getOffset = error("feature not implemented for this cap type");
function modifyOffset = error("feature not implemented for this cap type"); function modifyOffset = error("feature not implemented for this cap type");
function getBase = error("feature not implemented for this cap type"); function getBase = error("feature not implemented for this cap type");
@@ -884,72 +883,44 @@ instance CHERICap #(CapMem, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
function validAsType = error("feature not implemented for this cap type"); function validAsType = error("feature not implemented for this cap type");
function fromMem = error("feature not implemented for this cap type"); function fromMem = error("feature not implemented for this cap type");
function toMem = error("feature not implemented for this cap type"); function toMem = error("feature not implemented for this cap type");
function maskAddr = error("feature not implemented for this cap type");
function getBaseAlignment = error("feature not implemented for this cap type");
endinstance endinstance
instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3)); instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
function isValidCap = error("feature not implemented for this cap type");
function setValidCap = error("feature not implemented for this cap type");
function getFlags = error("feature not implemented for this cap type");
function setFlags = error("feature not implemented for this cap type");
function getHardPerms = error("feature not implemented for this cap type");
function setHardPerms = error("feature not implemented for this cap type");
function getSoftPerms = error("feature not implemented for this cap type");
function setSoftPerms = error("feature not implemented for this cap type");
function getKind = error("feature not implemented for this cap type");
function getType = error("feature not implemented for this cap type");
function setType = error("feature not implemented for this cap type");
function getAddr = error("feature not implemented for this cap type");
function setAddr = error("feature not implemented for this cap type");
function maskAddr = error("feature not implemented for this cap type");
function getOffset = error("feature not implemented for this cap type");
function modifyOffset = error("feature not implemented for this cap type");
function getBase = error("feature not implemented for this cap type");
function getTop = error("feature not implemented for this cap type");
function getLength = error("feature not implemented for this cap type");
function isInBounds = error("feature not implemented for this cap type");
function setBounds = error("feature not implemented for this cap type");
function nullWithAddr = error("feature not implemented for this cap type");
function almightyCap = defaultCapFat;
function nullCap = null_cap;
function validAsType = error("feature not implemented for this cap type");
function fromMem = error("feature not implemented for this cap type");
function toMem = error("feature not implemented for this cap type");
endinstance
instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3)); function isValidCap (x) = x.isCapability;
function isValidCap (x) = x.capFat.isCapability; function CapReg setValidCap (CapReg cap, Bool tag);
cap.isCapability = tag;
function CapPipe setValidCap (CapPipe cap, Bool tag);
cap.capFat.isCapability = tag;
return cap; return cap;
endfunction endfunction
function getFlags (cap) = cap.capFat.flags; function getFlags (cap) = cap.flags;
function setFlags (cap, flags); function setFlags (cap, flags);
cap.capFat.flags = flags; cap.flags = flags;
return cap; return cap;
endfunction endfunction
function HardPerms getHardPerms (CapPipe cap); function HardPerms getHardPerms (CapReg cap);
return HardPerms { return HardPerms {
permitSetCID: cap.capFat.perms.hard.permit_set_CID, permitSetCID: cap.perms.hard.permit_set_CID,
accessSysRegs: cap.capFat.perms.hard.access_sys_regs, accessSysRegs: cap.perms.hard.access_sys_regs,
permitUnseal: cap.capFat.perms.hard.permit_unseal, permitUnseal: cap.perms.hard.permit_unseal,
permitCCall: cap.capFat.perms.hard.permit_ccall, permitCCall: cap.perms.hard.permit_ccall,
permitSeal: cap.capFat.perms.hard.permit_seal, permitSeal: cap.perms.hard.permit_seal,
permitStoreLocalCap: cap.capFat.perms.hard.permit_store_ephemeral_cap, permitStoreLocalCap: cap.perms.hard.permit_store_ephemeral_cap,
permitStoreCap: cap.capFat.perms.hard.permit_store_cap, permitStoreCap: cap.perms.hard.permit_store_cap,
permitLoadCap: cap.capFat.perms.hard.permit_load_cap, permitLoadCap: cap.perms.hard.permit_load_cap,
permitStore: cap.capFat.perms.hard.permit_store, permitStore: cap.perms.hard.permit_store,
permitLoad: cap.capFat.perms.hard.permit_load, permitLoad: cap.perms.hard.permit_load,
permitExecute: cap.capFat.perms.hard.permit_execute, permitExecute: cap.perms.hard.permit_execute,
global: cap.capFat.perms.hard.non_ephemeral global: cap.perms.hard.non_ephemeral
}; };
endfunction endfunction
function CapPipe setHardPerms (CapPipe cap, HardPerms perms); function CapReg setHardPerms (CapReg cap, HardPerms perms);
cap.capFat.perms.hard = HPerms { cap.perms.hard = HPerms {
permit_set_CID: perms.permitSetCID, permit_set_CID: perms.permitSetCID,
access_sys_regs: perms.accessSysRegs, access_sys_regs: perms.accessSysRegs,
permit_unseal: perms.permitUnseal, permit_unseal: perms.permitUnseal,
@@ -966,38 +937,148 @@ instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
return cap; return cap;
endfunction endfunction
function SoftPerms getSoftPerms (CapPipe cap); function SoftPerms getSoftPerms (CapReg cap);
return zeroExtend(cap.capFat.perms.soft); return zeroExtend(cap.perms.soft);
endfunction endfunction
function CapPipe setSoftPerms (CapPipe cap, SoftPerms perms); function CapReg setSoftPerms (CapReg cap, SoftPerms perms);
cap.capFat.perms.soft = truncate(perms); cap.perms.soft = truncate(perms);
return cap; return cap;
endfunction endfunction
function Kind getKind (CapPipe cap); function Kind getKind (CapReg cap);
case (cap.capFat.otype) case (cap.otype)
otype_unsealed: return UNSEALED; otype_unsealed: return UNSEALED;
otype_sentry: return SENTRY; otype_sentry: return SENTRY;
default: return (cap.capFat.otype <= otype_max) ? SEALED_WITH_TYPE : RES0; default: return (cap.otype <= otype_max) ? SEALED_WITH_TYPE : RES0;
endcase endcase
endfunction endfunction
function getType (x) = getType(x.capFat).d; function getType (cap) = getTypeFat(cap).d;
function Exact#(CapPipe) setType (CapPipe cap, Bit #(OTypeW) otype); function CapReg setType (CapReg cap, Bit #(OTypeW) otype);
if (otype == -1) begin if (otype == -1) begin
cap.capFat = unseal(cap.capFat, ?); cap = unseal(cap, ?);
end else begin end else begin
cap.capFat = seal(cap.capFat, ?, VnD {v: True, d:otype}); cap = seal(cap, ?, VnD {v: True, d:otype});
end end
return Exact { return cap;
exact: True,
value: cap
};
endfunction endfunction
function getAddr (x) = truncate(getAddress(x.capFat)); function getAddr (cap) = truncate(getAddress(cap));
function setAddr = error("feature not implemented for this cap type");
function getOffset = error("feature not implemented for this cap type");
function modifyOffset = error("feature not implemented for this cap type");
function getBase = error("feature not implemented for this cap type");
function getTop = error("feature not implemented for this cap type");
function getLength = error("feature not implemented for this cap type");
function isInBounds = error("feature not implemented for this cap type");
function Exact#(CapReg) setBounds (CapReg cap, Bit#(CapAddressW) length);
match {.result, .exact} = setBoundsFat(cap, length);
return Exact {exact: exact, value: result};
endfunction
function CapReg nullWithAddr (Bit#(CapAddressW) addr);
CapReg res = nullCap;
res.address = zeroExtend(addr);
return res;
endfunction
function almightyCap = defaultCapFat;
function nullCap = null_cap;
function Bool validAsType (CapReg dummy, Bit#(CapAddressW) checkType);
UInt#(CapAddressW) checkTypeUnsigned = unpack(checkType);
UInt#(CapAddressW) otypeMaxUnsigned = unpack(zeroExtend(otype_max));
return checkTypeUnsigned <= otypeMaxUnsigned;
endfunction
function fromMem (x) = cast(pack(x));
function toMem (x) = unpack(cast(x));
function CapReg maskAddr (CapReg cap, Bit#(TSub#(MW, 3)) mask);
cap.address[valueOf(TSub#(MW, 4)):0] = cap.address[valueOf(TSub#(MW, 4)):0] & mask;
return cap;
endfunction
function Bit#(2) getBaseAlignment (CapReg cap);
// If cap exp is non-zero, we have internal exponent, so the least significant
// two bits of the base are implicitly zero.
// Otherwise, we have a zero exponent, so the least significant two bits
// of the base are the least significant bits of the encoded base
if (cap.bounds.exp == 0) return cap.bounds.baseBits[1:0];
else return 2'b0;
endfunction
endinstance
instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
//Functions supported by CapReg are just passed through
function isValidCap (x) = isValidCap(x.capFat);
function setValidCap (cap, tag);
return CapPipe {capFat: setValidCap(cap.capFat, tag), tempFields: cap.tempFields};
endfunction
function getFlags (cap) = getFlags(cap.capFat);
function setFlags (cap, flags);
return CapPipe {capFat: setFlags(cap.capFat, flags), tempFields: cap.tempFields};
endfunction
function getHardPerms (cap) = getHardPerms(cap.capFat);
function CapPipe setHardPerms (CapPipe cap, HardPerms perms);
return CapPipe {capFat: setHardPerms(cap.capFat, perms), tempFields: cap.tempFields};
endfunction
function getSoftPerms (cap) = getSoftPerms(cap.capFat);
function CapPipe setSoftPerms (CapPipe cap, SoftPerms perms);
return CapPipe {capFat: setSoftPerms(cap.capFat, perms), tempFields: cap.tempFields};
endfunction
function getKind (cap) = getKind(cap.capFat);
function getType (cap) = getType(cap.capFat);
function setType (cap, otype);
return CapPipe{capFat: setType(cap.capFat, otype), tempFields: cap.tempFields};
endfunction
function getAddr (cap) = getAddr(cap.capFat);
function CapPipe maskAddr (CapPipe cap, Bit#(TSub#(MW, 3)) mask);
return CapPipe {capFat: maskAddr(cap.capFat, mask), tempFields: cap.tempFields};
endfunction
function Bool validAsType (CapPipe dummy, Bit#(CapAddressW) checkType);
return validAsType(dummy.capFat, checkType);
endfunction
function toMem (cap) = toMem(cap.capFat);
function getBaseAlignment (cap) = getBaseAlignment(cap.capFat);
//Functions supported by CapReg but which require TempFields to be changed
function Exact#(CapPipe) setBounds (CapPipe cap, Bit#(CapAddressW) length);
let result = setBounds(cap.capFat, length);
return Exact {exact: result.exact, value: CapPipe {capFat: result.value, tempFields: getTempFields(result.value)}};
endfunction
function CapPipe nullWithAddr (Bit#(CapAddressW) addr);
CapReg res = nullWithAddr(addr);
return CapPipe {capFat: res, tempFields: getTempFields(res)};
endfunction
function fromMem (capBits);
CapReg res = fromMem(capBits);
return CapPipe {capFat: res, tempFields: getTempFields(res)};
endfunction
function almightyCap;
CapReg res = almightyCap;
return CapPipe {capFat: res, tempFields: getTempFields(res)};
endfunction
function nullCap;
CapReg res = nullCap;
return CapPipe {capFat: res, tempFields: getTempFields(res)};
endfunction
//Functions that require TempFields
function Exact#(CapPipe) setAddr (CapPipe cap, Bit#(CapAddressW) address); function Exact#(CapPipe) setAddr (CapPipe cap, Bit#(CapAddressW) address);
let result = setAddress(cap.capFat, zeroExtend(address), cap.tempFields); let result = setAddress(cap.capFat, zeroExtend(address), cap.tempFields);
@@ -1006,15 +1087,10 @@ instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
return Exact {exact: result.v, value: cap}; return Exact {exact: result.v, value: cap};
endfunction endfunction
function CapPipe maskAddr (CapPipe cap, Bit#(TSub#(MW, 3)) mask);
cap.capFat.address[valueOf(TSub#(MW, 4)):0] = cap.capFat.address[valueOf(TSub#(MW, 4)):0] & mask;
return cap;
endfunction
function getOffset (x) = getOffsetFat(x.capFat, x.tempFields); function getOffset (x) = getOffsetFat(x.capFat, x.tempFields);
function Exact#(CapPipe) modifyOffset (CapPipe cap, Bit#(CapAddressW) offset, Bool doInc); function Exact#(CapPipe) modifyOffset (CapPipe cap, Bit#(CapAddressW) offset, Bool doInc);
let result = incOffset(cap.capFat, pack(cap.capFat.address) + zeroExtend(offset), zeroExtend(offset), cap.tempFields, !doInc); let result = incOffsetFat(cap.capFat, pack(cap.capFat.address) + zeroExtend(offset), zeroExtend(offset), cap.tempFields, !doInc);
cap.capFat = result.d; cap.capFat = result.d;
cap.tempFields = getTempFields(cap.capFat); cap.tempFields = getTempFields(cap.capFat);
return Exact {exact: result.v, value: cap}; return Exact {exact: result.v, value: cap};
@@ -1036,30 +1112,6 @@ instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3));
return capInBounds(cap.capFat, cap.tempFields, inclusive); return capInBounds(cap.capFat, cap.tempFields, inclusive);
endfunction endfunction
function Exact#(CapPipe) setBounds (CapPipe cap, Bit#(CapAddressW) length);
match {.result, .exact} = setBoundsFat(cap.capFat, length);
return Exact {exact: exact, value: CapPipe {capFat: result, tempFields: getTempFields(result)}};
endfunction
function CapPipe nullWithAddr (Bit#(CapAddressW) addr);
let res = setAddress(nullCap, zeroExtend(addr), getTempFields(nullCap)).d;
return CapPipe {capFat: res, tempFields: getTempFields(res)};
endfunction
function almightyCap = CapPipe { capFat: defaultCapFat, tempFields: getTempFields(defaultCapFat) };
function nullCap = CapPipe { capFat: nullCap, tempFields: getTempFields(nullCap) };
function Bool validAsType (CapPipe dummy, Bit#(CapAddressW) checkType);
UInt#(CapAddressW) checkTypeUnsigned = unpack(checkType);
UInt#(CapAddressW) otypeMaxUnsigned = unpack(zeroExtend(otype_max));
return checkTypeUnsigned <= otypeMaxUnsigned;
endfunction
function fromMem (x) = cast(pack(x));
function toMem (x) = unpack(cast(x));
endinstance endinstance
instance Cast#(CapMem, CapReg); instance Cast#(CapMem, CapReg);
@@ -1086,18 +1138,4 @@ instance Cast#(CapPipe, CapReg);
endfunction endfunction
endinstance endinstance
instance Cast#(CapMem, CapPipe);
function cast(x);
CapReg fat = cast(x);
return cast(fat);
endfunction
endinstance
instance Cast#(CapPipe, CapMem);
function cast(x);
CapReg fat = cast(x);
return cast(fat);
endfunction
endinstance
endpackage endpackage

View File

@@ -116,17 +116,12 @@ typeclass CHERICap#(type t, numeric type ot, numeric type flg, numeric type n, n
// Get the type field, including implicitly whether the cap is sealed/sentry // Get the type field, including implicitly whether the cap is sealed/sentry
function Bit#(ot) getType (t cap); function Bit#(ot) getType (t cap);
// Set the type field, including implicitly sealing/unsealing the capability // Set the type field, including implicitly sealing/unsealing the capability
// In the event the new type makes the cap unrepresentable function t setType (t cap, Bit#(ot) otype);
function Exact#(t) setType (t cap, Bit#(ot) otype);
// Get the address pointed to by the capability
// Get the address pointed to by the capability
function Bit#(n) getAddr (t cap); function Bit#(n) getAddr (t cap);
// Set the address of the capability. Result invalid if not exact // Set the address of the capability. Result invalid if not exact
function Exact#(t) setAddr (t cap, Bit#(n) addr); function Exact#(t) setAddr (t cap, Bit#(n) addr);
// Mask the least significant bits of capability address with a mask
// maskable_width should be small enough to make this
// safe with respect to representability
function t maskAddr (t cap, Bit#(maskable_bits) mask);
// Get the offset of the capability // Get the offset of the capability
function Bit#(n) getOffset (t cap) = getAddr(cap) - getBase(cap); function Bit#(n) getOffset (t cap) = getAddr(cap) - getBase(cap);
@@ -172,6 +167,18 @@ typeclass CHERICap#(type t, numeric type ot, numeric type flg, numeric type n, n
function t fromMem (Tuple2#(Bool, Bit#(mem_sz)) mem_cap); function t fromMem (Tuple2#(Bool, Bit#(mem_sz)) mem_cap);
function Tuple2#(Bool, Bit#(mem_sz)) toMem (t cap); function Tuple2#(Bool, Bit#(mem_sz)) toMem (t cap);
// Functions that can be cheap by relying on current capability representation
// Mask the least significant bits of capability address with a mask
// maskable_width should be small enough to make this
// safe with respect to representability
function t maskAddr (t cap, Bit#(maskable_bits) mask);
// Check the alignment of the base, giving least significant 2 bits.
// This relies on the fact that internal exponents take up 2 bits of the
// base.
function Bit#(2) getBaseAlignment (t cap);
endtypeclass endtypeclass
function Fmt showCHERICap(t cap) provisos (CHERICap#(t, ot, flg, n, mem_sz, maskable_bits)); function Fmt showCHERICap(t cap) provisos (CHERICap#(t, ot, flg, n, mem_sz, maskable_bits));