From 490a10f18cf7e1e5a9020f3745d9131bb66b0a74 Mon Sep 17 00:00:00 2001 From: Simon Moore Date: Tue, 21 Apr 2020 23:40:29 +0100 Subject: [PATCH 1/3] Simplify the definition of macro W() so that the Connectal dependancy checker can handle it. --- CHERICapWrap.bsv | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/CHERICapWrap.bsv b/CHERICapWrap.bsv index 62a9658..dfb6aa8 100644 --- a/CHERICapWrap.bsv +++ b/CHERICapWrap.bsv @@ -31,11 +31,10 @@ import CHERICap :: *; import CHERICC_Fat :: *; `define CAPTYPE CapPipe -`define W(name)\ -`ifndef CAP64\ -wrap128_``name\ -`else\ -wrap64_``name\ +`ifndef CAP64 +`define W(name) wrap128_``name +`else +`define W(name) wrap64_``name `endif (* noinline *) From d24104fa3ecfb5970942e1a0a26f86babef71234 Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Thu, 23 Apr 2020 10:35:14 +0100 Subject: [PATCH 2/3] Revert "Provide combined set bound function" This reverts commit 80ba19db9fdef5a59b4fa1d1f33f3b02d27a7d91. --- CHERICC_Fat.bsv | 39 ++++++++++++++++++++++++++++++++------- CHERICap.bsv | 20 ++------------------ 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/CHERICC_Fat.bsv b/CHERICC_Fat.bsv index 423df64..01f439b 100644 --- a/CHERICC_Fat.bsv +++ b/CHERICC_Fat.bsv @@ -58,7 +58,6 @@ export HPerms; export PermsW; export Exp; export MetaInfo; -export SetBoundsReturn; // =============================================================================== @@ -399,8 +398,15 @@ function Bit#(n) smearMSBRight(Bit#(n) x); return res; endfunction +typedef struct +{ + CapFat cap; + Bool exact; + CapAddress length; + CapAddress mask; +} SetBoundsReturn deriving (Bits, Eq, FShow); -function SetBoundsReturn#(CapFat, CapAddressW) setBoundsFat(CapFat cap, Address lengthFull); +function SetBoundsReturn setBoundsFat(CapFat cap, Address lengthFull); CapFat ret = cap; // Find new exponent by finding the index of the most significant bit of the // length, or counting leading zeros in the high bits of the length, and @@ -901,7 +907,7 @@ instance CHERICap #(CapMem, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3)); 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 setBoundsCombined = 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 = error("feature not implemented for this cap type"); function nullCap = error("feature not implemented for this cap type"); @@ -910,6 +916,8 @@ instance CHERICap #(CapMem, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3)); 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"); + function getRepresentableAlignmentMask = error("feature not implemented for this cap type"); + function getRepresentableLength = error("feature not implemented for this cap type"); function isDerivable = error("feature not implemented for this cap type"); endinstance @@ -1019,7 +1027,10 @@ instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3)); function getLength = error("feature not implemented for this cap type"); function isInBounds = error("feature not implemented for this cap type"); - function SetBoundsReturn#(CapReg, CapAddressW) setBoundsCombined(CapReg cap, Bit#(CapAddressW) length) = setBoundsFat(cap, length); + function Exact#(CapReg) setBounds (CapReg cap, Bit#(CapAddressW) length); + SetBoundsReturn sr = setBoundsFat(cap, length); + return Exact {exact: sr.exact, value: sr.cap}; + endfunction function CapReg nullWithAddr (Bit#(CapAddressW) addr); CapReg res = nullCap; @@ -1055,6 +1066,16 @@ instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3)); else return 2'b0; endfunction + function Bit#(CapAddressW) getRepresentableAlignmentMask (CapReg dummy, Bit#(CapAddressW) length_request); + SetBoundsReturn sr = setBoundsFat(nullCap, length_request); + return sr.mask; + endfunction + + function Bit#(CapAddressW) getRepresentableLength (CapReg dummy, Bit#(CapAddressW) length_request); + SetBoundsReturn sr = setBoundsFat(nullCap, length_request); + return sr.length; + endfunction + function Bool isDerivable (CapReg cap); return cap.bounds.exp <= resetExp && !(cap.bounds.exp == resetExp && ((truncateLSB(cap.bounds.topBits) != 1'b0) || (truncateLSB(cap.bounds.baseBits) != 2'b0))) @@ -1100,9 +1121,9 @@ instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3)); //Functions supported by CapReg but which require TempFields to be changed - function SetBoundsReturn#(CapPipe, CapAddressW) setBoundsCombined(CapPipe cap, Bit#(CapAddressW) length); - let result = setBoundsCombined(cap.capFat, length); - return SetBoundsReturn {cap: CapPipe{capFat: result.cap, tempFields: getTempFields(result.cap)}, exact: result.exact, length: result.length, mask: result.mask}; + 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); @@ -1165,6 +1186,10 @@ instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3)); return capInBounds(cap.capFat, cap.tempFields, inclusive); endfunction + function getRepresentableAlignmentMask (dummy) = getRepresentableAlignmentMask(null_cap); + + function getRepresentableLength (dummy) = getRepresentableLength(null_cap); + function isDerivable (cap) = isDerivable(cap.capFat); endinstance diff --git a/CHERICap.bsv b/CHERICap.bsv index e5857f8..e1e7903 100644 --- a/CHERICap.bsv +++ b/CHERICap.bsv @@ -78,14 +78,6 @@ typedef enum { SEALED_WITH_TYPE } Kind deriving (Bits, Eq, FShow); -typedef struct -{ - t cap; - Bool exact; - Bit#(n) length; - Bit#(n) mask; -} SetBoundsReturn#(type t, numeric type n) deriving (Bits, Eq, FShow); - typeclass CHERICap#(type t, numeric type ot, numeric type flg, numeric type n, numeric type mem_sz, numeric type maskable_bits) dependencies (t determines (ot, flg, n, mem_sz, maskable_bits)); @@ -161,11 +153,6 @@ typeclass CHERICap#(type t, numeric type ot, numeric type flg, numeric type n, n // Set the length of the capability. Inexact: result length may be different to requested function Exact#(t) setBounds (t cap, Bit#(n) length); - let combinedResult = setBoundsCombined(cap, length); - return Exact {exact: combinedResult.exact, value: combinedResult.cap}; - endfunction - - function SetBoundsReturn#(t, n) setBoundsCombined (t cap, Bit#(n) length); // Returns a null cap with an address set to the argument function t nullWithAddr (Bit#(n) addr); @@ -194,14 +181,11 @@ typeclass CHERICap#(type t, numeric type ot, numeric type flg, numeric type n, n // base. function Bit#(2) getBaseAlignment (t cap); - // TODO the following do not compile due to "not enough explicit type information" // Get representable alignment mask - // function Bit#(n) getRepresentableAlignmentMask (t dummy, Bit#(n) length_request) = - // setBoundsCombined(nullCap, length_request).mask; + function Bit#(n) getRepresentableAlignmentMask (t dummy, Bit#(n) length_request); // Get representable length - // function Bit#(n) getRepresentableLength (t dummy, Bit#(n) length_request) = - // setBoundsCombined(nullCap, length_request).length; + function Bit#(n) getRepresentableLength (t dummy, Bit#(n) length_request); // Assert that the encoding is valid function Bool isDerivable (t cap); From 9fb30e0b6f4683d4d848eedc77084278b5ea07dc Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Fri, 1 May 2020 20:01:27 +0100 Subject: [PATCH 3/3] Remove get/setType functions to prevent sealed/sealed_with_type confusion --- CHERICC_Fat.bsv | 46 ++++++++++++++++++++++------------------------ CHERICap.bsv | 29 ++++++++++------------------- 2 files changed, 32 insertions(+), 43 deletions(-) diff --git a/CHERICC_Fat.bsv b/CHERICC_Fat.bsv index 01f439b..5f83040 100644 --- a/CHERICC_Fat.bsv +++ b/CHERICC_Fat.bsv @@ -156,6 +156,8 @@ typedef VnD#(Bit#(OTypeW)) CType; Bit#(OTypeW) otype_max = -5; Bit#(OTypeW) otype_unsealed = -1; Bit#(OTypeW) otype_sentry = -2; +Bit#(OTypeW) otype_res0 = -3; +Bit#(OTypeW) otype_res1 = -4; // unpacked capability format typedef struct { @@ -175,8 +177,7 @@ function Fmt showArchitectural(CapFat cap) = $format("valid:%b", cap.isCapability) + $format(" perms:0x%x", getPerms(cap)) //+ $format(" flags:0x%x", getFlags(cap)) - + $format(" sealed:%b", isSealed(cap)) - + $format(" type:0x%x",getType(cap)) + + $format(" kind:", fshow(getKind(cap))) + $format(" offset:0x%x", getOffsetFat(cap, getTempFields(cap))) + $format(" base:0x%x", getBotFat(cap, getTempFields(cap))) + $format(" length:0x%x", getLengthFat(cap, getTempFields(cap))); @@ -896,8 +897,7 @@ instance CHERICap #(CapMem, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3)); 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 setKind = 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 setAddrUnsafe = error("feature not implemented for this cap type"); @@ -930,7 +930,7 @@ instance FShow #(CapPipe); " t: ", fshow(getTop(cap)), " sp: ", fshow(pack(getSoftPerms(cap))), " hp: ", fshow(pack(getHardPerms(cap))), - " ot: ", fshow(getType(cap)), + " ot: ", fshow(cap.capFat.otype), " f: ", fshow(getFlags(cap))); endinstance @@ -993,23 +993,24 @@ instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3)); return cap; endfunction - function Kind getKind (CapReg cap); - case (cap.otype) - otype_unsealed: return UNSEALED; - otype_sentry: return SENTRY; - default: return (cap.otype <= otype_max) ? SEALED_WITH_TYPE : RES0; - endcase + function Kind#(OTypeW) getKind (CapReg cap); + return (case (cap.otype) + otype_unsealed: UNSEALED; + otype_sentry: SENTRY; + otype_res0: RES0; + otype_res1: RES1; + default: (SEALED_WITH_TYPE (cap.otype)); + endcase); endfunction - function getType (cap) = getTypeFat(cap).d; - - function CapReg setType (CapReg cap, Bit #(OTypeW) otype); - if (otype == -1) begin - cap = unseal(cap, ?); - end else begin - cap = seal(cap, ?, VnD {v: True, d:otype}); - end - return cap; + function CapReg setKind (CapReg cap, Kind #(OTypeW) kind); + return (case (kind) matches + tagged UNSEALED: unseal(cap, ?); + tagged SENTRY: seal(cap, ?, VnD {v: True, d:otype_sentry}); + tagged RES0: seal(cap, ?, VnD {v: True, d:otype_res0}); + tagged RES1: seal(cap, ?, VnD {v: True, d:otype_res1}); + tagged SEALED_WITH_TYPE .ot: seal(cap, ?, VnD {v: True, d:ot}); + endcase); endfunction function getAddr (cap) = truncate(getAddress(cap)); @@ -1105,10 +1106,7 @@ instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddressW, CapW, TSub#(MW, 3)); 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 setKind (cap,kind) = CapPipe {capFat:setKind(cap.capFat,kind), tempFields: cap.tempFields}; 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}; diff --git a/CHERICap.bsv b/CHERICap.bsv index e1e7903..e4c7371 100644 --- a/CHERICap.bsv +++ b/CHERICap.bsv @@ -70,13 +70,13 @@ typedef struct { t value; } Exact #(type t) deriving (Bits); -typedef enum { - UNSEALED, - SENTRY, - RES0, - RES1, - SEALED_WITH_TYPE -} Kind deriving (Bits, Eq, FShow); +typedef union tagged { + void UNSEALED; + void SENTRY; + void RES0; + void RES1; + Bit#(ot) SEALED_WITH_TYPE; +} Kind#(numeric type ot) deriving (Bits, Eq, FShow); typeclass CHERICap#(type t, numeric type ot, numeric type flg, numeric type n, numeric type mem_sz, numeric type maskable_bits) dependencies (t determines (ot, flg, n, mem_sz, maskable_bits)); @@ -106,17 +106,9 @@ typeclass CHERICap#(type t, numeric type ot, numeric type flg, numeric type n, n function t setPerms (t cap, Bit#(31) perms) = setSoftPerms(setHardPerms(cap, unpack(perms[11:0])), unpack(truncate(perms[30:15]))); - // Get the kind of the capability, i.e. whether it is sealed, sentry, unsealed, ... - function Kind getKind (t cap); - // Helper methods for identifying specific kinds - function Bool isSentry (t cap) = getKind(cap) == SENTRY; - function Bool isSealedWithType (t cap) = getKind(cap) == SEALED_WITH_TYPE; - function Bool isSealed (t cap) = getKind(cap) != UNSEALED; - - // Get the type field, including implicitly whether the cap is sealed/sentry - function Bit#(ot) getType (t cap); - // Set the type field, including implicitly sealing/unsealing the capability - function t setType (t cap, Bit#(ot) otype); + // Manipulate the kind of the capability, i.e. whether it is sealed, sentry, unsealed, ... + function Kind#(ot) getKind (t cap); + function t setKind (t cap, Kind#(ot) kind); // Get the address pointed to by the capability function Bit#(n) getAddr (t cap); @@ -196,7 +188,6 @@ function Fmt showCHERICap(t cap) provisos (CHERICap#(t, ot, flg, n, mem_sz, mask return $format( "Valid: 0x%0x", isValidCap(cap)) + $format(" Perms: 0x%0x", getPerms(cap)) + $format(" Kind: ", fshow(getKind(cap))) + - (isSealedWithType(cap) ? $format(" Type: %0d", getType(cap)) : $format("")) + $format(" Addr: 0x%0x", getAddr(cap)) + $format(" Base: 0x%0x", getBase(cap)) + $format(" Length: 0x%0x", getLength(cap));