Introduced a getMeta method as a counterpart to getAddr for getting all

bits of in-memory architectural capability representation
This commit is contained in:
gameboo
2021-09-15 17:57:01 +01:00
parent 8ab0d3888f
commit 1741ce43dd
2 changed files with 91 additions and 42 deletions

View File

@@ -92,6 +92,7 @@ typedef `FLAGSW FlagsW;
typedef 64 CapAddrW; typedef 64 CapAddrW;
typedef 128 CapW; typedef 128 CapW;
`endif `endif
// The Address type is used to represent the full sized address returned to the // The Address type is used to represent the full sized address returned to the
// consuming pipeline. In cases where fewer than CapAddrW bits are stored to // consuming pipeline. In cases where fewer than CapAddrW bits are stored to
// represent a memory address (and remaining bits are usable for storing extra // represent a memory address (and remaining bits are usable for storing extra
@@ -145,7 +146,7 @@ typedef struct {
Bit#(OTypeW) otype; Bit#(OTypeW) otype;
CBounds bounds; CBounds bounds;
CapAddr address; CapAddr address;
} CapabilityInMemory deriving(Bits, Eq, FShow); // CapW + 1 (tag bit) } CapabilityInMemory deriving (Bits, Eq, FShow); // CapW + 1 (tag bit)
// The full capability structure as Bits, including the "tag" bit. // The full capability structure as Bits, including the "tag" bit.
typedef Bit#(TAdd#(CapW,1)) Capability; typedef Bit#(TAdd#(CapW,1)) Capability;
// not including the tag bit // not including the tag bit
@@ -180,7 +181,7 @@ typedef struct {
Bit#(OTypeW) otype; Bit#(OTypeW) otype;
Format format; Format format;
Bounds bounds; Bounds bounds;
} CapFat deriving(Bits); } CapFat deriving (Bits);
// "Architectural FShow" // "Architectural FShow"
function Fmt showArchitectural(CapFat cap) = function Fmt showArchitectural(CapFat cap) =
@@ -847,7 +848,7 @@ typedef struct {
TempFields tempFields; TempFields tempFields;
} CapPipe deriving (Bits); } CapPipe deriving (Bits);
instance CHERICap #(CapMem, OTypeW, FlagsW, CapAddrW, CapW, TSub#(MW, 3)); instance CHERICap #(CapMem, OTypeW, FlagsW, CapAddrW, CapW, TSub #(MW, 3));
function isValidCap (capMem); function isValidCap (capMem);
CapabilityInMemory cap = unpack(capMem); CapabilityInMemory cap = unpack(capMem);
return cap.isCapability; return cap.isCapability;
@@ -887,9 +888,17 @@ instance CHERICap #(CapMem, OTypeW, FlagsW, CapAddrW, CapW, TSub#(MW, 3));
function setSoftPerms = error("setSoftPerms not implemented for CapMem"); function setSoftPerms = error("setSoftPerms not implemented for CapMem");
function getKind = error("getKind not implemented for CapMem"); function getKind = error("getKind not implemented for CapMem");
function setKind = error("setKind not implemented for CapMem"); function setKind = error("setKind not implemented for CapMem");
function getMeta(capMem);
CapabilityInMemory cap = unpack(capMem);
return { pack (cap.perms)
, pack (cap.reserved)
, pack (cap.flags)
, pack (cap.otype)
, pack (cap.bounds) };
endfunction
function getAddr(capMem); function getAddr(capMem);
CapabilityInMemory cap = unpack(capMem); CapabilityInMemory cap = unpack(capMem);
return cap.address; return pack (cap.address);
endfunction endfunction
function setAddr = error("setAddr not implemented for CapMem"); function setAddr = error("setAddr not implemented for CapMem");
function setAddrUnsafe (capMem, address); function setAddrUnsafe (capMem, address);
@@ -946,7 +955,7 @@ instance Eq #(CapReg);
// function Bool \/= (CapPipe x, CapPipe y); // function Bool \/= (CapPipe x, CapPipe y);
endinstance endinstance
instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddrW, CapW, TSub#(MW, 3)); instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddrW, CapW, TSub #(MW, 3));
function isValidCap (x) = x.isCapability; function isValidCap (x) = x.isCapability;
@@ -1016,7 +1025,15 @@ instance CHERICap #(CapReg, OTypeW, FlagsW, CapAddrW, CapW, TSub#(MW, 3));
tagged SEALED_WITH_TYPE .ot: seal(cap, ?, VnD {v: True, d:ot}); tagged SEALED_WITH_TYPE .ot: seal(cap, ?, VnD {v: True, d:ot});
endcase; endcase;
function getAddr (cap) = cap.address; function getMeta(capReg);
CapMem cap = unpack (pack (toMem (capReg)));
return getMeta (cap);
endfunction
function getAddr (capReg);
CapMem cap = unpack (pack (toMem (capReg)));
return getAddr (cap);
endfunction
function setAddr = error("setAddr not implemented for CapReg"); function setAddr = error("setAddr not implemented for CapReg");
@@ -1091,7 +1108,9 @@ instance CHERICap #(CapPipe, OTypeW, FlagsW, CapAddrW, CapW, TSub#(MW, 3));
function setKind (cap, kind) = function setKind (cap, kind) =
CapPipe { capFat:setKind(cap.capFat,kind) CapPipe { capFat:setKind(cap.capFat,kind)
, tempFields: cap.tempFields }; , tempFields: cap.tempFields };
function getAddr (cap) = getAddr(cap.capFat);
function getMeta (cap) = getMeta (cap.capFat);
function getAddr (cap) = getAddr (cap.capFat);
function maskAddr (cap, mask) = function maskAddr (cap, mask) =
CapPipe { capFat: maskAddr(cap.capFat, mask) CapPipe { capFat: maskAddr(cap.capFat, mask)
, tempFields: cap.tempFields }; , tempFields: cap.tempFields };

View File

@@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2018-2019 Alexandre Joannou * Copyright (c) 2018-2021 Alexandre Joannou
* Copyright (c) 2019 Peter Rugg * Copyright (c) 2019 Peter Rugg
* All rights reserved. * All rights reserved.
* *
@@ -29,27 +29,29 @@
package CHERICap; package CHERICap;
// CHERI capability typeclass // CHERI public types
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Permission bits // Permission bits
typedef Bit#(16) SoftPerms; typedef Bit #(16) SoftPerms;
typedef struct { typedef struct {
Bool permitSetCID; Bool permitSetCID;
Bool accessSysRegs; Bool accessSysRegs;
Bool permitUnseal; Bool permitUnseal;
Bool permitCCall; Bool permitCCall;
Bool permitSeal; Bool permitSeal;
Bool permitStoreLocalCap; Bool permitStoreLocalCap;
Bool permitStoreCap; Bool permitStoreCap;
Bool permitLoadCap; Bool permitLoadCap;
Bool permitStore; Bool permitStore;
Bool permitLoad; Bool permitLoad;
Bool permitExecute; Bool permitExecute;
Bool global; Bool global;
} HardPerms deriving(Bits, Eq, FShow); } HardPerms deriving(Bits, Eq, FShow);
instance Bitwise#(HardPerms); instance Bitwise #(HardPerms);
function \& (x1, x2) = unpack(pack(x1) & pack(x2)); function \& (x1, x2) = unpack(pack(x1) & pack(x2));
function \| (x1, x2) = unpack(pack(x1) | pack(x2)); function \| (x1, x2) = unpack(pack(x1) | pack(x2));
function \^ (x1, x2) = unpack(pack(x1) ^ pack(x2)); function \^ (x1, x2) = unpack(pack(x1) ^ pack(x2));
@@ -62,31 +64,45 @@ instance Bitwise#(HardPerms);
function lsb (x) = lsb(pack(x)); function lsb (x) = lsb(pack(x));
endinstance endinstance
// Type to return the result of an operation along with whether the operation was exact // Helper type to return the result of an operation along with whether the
// In cases where no sensible inexact representation exists, the only guarantee is that // operation was exact. In cases where no sensible inexact representation
// the tag bit is not set. // exists, the only guarantee is that the tag bit is not set.
typedef struct { typedef struct {
Bool exact; Bool exact;
t value; t value;
} Exact #(type t) deriving (Bits); } Exact #(type t) deriving (Bits);
// Kind of a capability, that is whether it is "sealed with a given otype", or
// if it is a "sentry" or simply "unsealed".
typedef union tagged { typedef union tagged {
void UNSEALED; void UNSEALED;
void SENTRY; void SENTRY;
void RES0; void RES0;
void RES1; void RES1;
Bit#(ot) SEALED_WITH_TYPE; Bit #(ot) SEALED_WITH_TYPE;
} Kind#(numeric type ot) deriving (Bits, Eq, FShow); } Kind #(numeric type ot) deriving (Bits, Eq, FShow);
typedef struct // Helper type for the return value of the 'setBoundsCombined' method
{
typedef struct {
t cap; t cap;
Bool exact; Bool exact;
Bit#(n) length; Bit #(n) length;
Bit#(n) mask; Bit #(n) mask;
} SetBoundsReturn#(type t, numeric type n) deriving (Bits, Eq, FShow); } 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)
// CHERI capability typeclass
////////////////////////////////////////////////////////////////////////////////
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)); dependencies (t determines (ot, flg, n, mem_sz, maskable_bits));
// Return whether the Capability is valid // Return whether the Capability is valid
@@ -112,14 +128,22 @@ typeclass CHERICap#(type t, numeric type ot, numeric type flg, numeric type n, n
zeroExtend({pack(getSoftPerms(cap)), 3'h0, pack(getHardPerms(cap))}); zeroExtend({pack(getSoftPerms(cap)), 3'h0, pack(getHardPerms(cap))});
// Set the architectural permissions // Set the architectural permissions
function t setPerms (t cap, Bit#(31) perms) = function t setPerms (t cap, Bit#(31) perms) =
setSoftPerms(setHardPerms(cap, unpack(perms[11:0])), unpack(truncate(perms[30:15]))); setSoftPerms ( setHardPerms(cap, unpack(perms[11:0]))
, unpack(truncate(perms[30:15])) );
// Manipulate the kind of the capability, i.e. whether it is sealed, sentry, unsealed, ... // Manipulate the kind of the capability, i.e. whether it is sealed, sentry,
// unsealed, ...
function Kind#(ot) getKind (t cap); function Kind#(ot) getKind (t cap);
function t setKind (t cap, Kind#(ot) kind); function t setKind (t cap, Kind#(ot) kind);
// Get the address pointed to by the capability // Get the in-memory architectural representation of the capability metadata
function Bit#(n) getAddr (t cap); function Bit #(TSub #(mem_sz, n)) getMeta (t cap);
// Get the in-memory architectural representation of the capability address
function Bit #(n) getAddr (t cap);
// Note that the following rule is expected to hold:
// fromMem (tuple2 (isValidCap (cap), {getMeta (cap), getAddr (cap)})) == cap
// Set the address of the capability. Result invalid if unrepresentable // Set the address of the capability. Result invalid if unrepresentable
function Exact#(t) setAddr (t cap, Bit#(n) addr); function Exact#(t) setAddr (t cap, Bit#(n) addr);
// Set the address of the capability. Result assumed to be representable // Set the address of the capability. Result assumed to be representable
@@ -153,7 +177,8 @@ typeclass CHERICap#(type t, numeric type ot, numeric type flg, numeric type n, n
return isNotTooLow && isNotTooHigh; return isNotTooLow && isNotTooHigh;
endfunction endfunction
// Set the length of the capability. Inexact: result length may be different to requested // Set the length of the capability. Inexact: result length may be different
// to requested
function Exact#(t) setBounds (t cap, Bit#(n) length); function Exact#(t) setBounds (t cap, Bit#(n) length);
let combinedResult = setBoundsCombined(cap, length); let combinedResult = setBoundsCombined(cap, length);
return Exact {exact: combinedResult.exact, value: combinedResult.cap}; return Exact {exact: combinedResult.exact, value: combinedResult.cap};
@@ -175,7 +200,7 @@ typeclass CHERICap#(type t, numeric type ot, numeric type flg, numeric type n, n
// Check if a type is valid // Check if a type is valid
function Bool validAsType (t dummy, Bit#(n) checkType); function Bool validAsType (t dummy, Bit#(n) checkType);
// convert from and to bit memory representation // Convert from and to bit memory representation
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);
@@ -192,7 +217,8 @@ typeclass CHERICap#(type t, numeric type ot, numeric type flg, numeric type n, n
function Bit#(2) getBaseAlignment (t cap); function Bit#(2) getBaseAlignment (t cap);
// Get representable alignment mask // Get representable alignment mask
function Bit#(n) getRepresentableAlignmentMask (t dummy, Bit#(n) length_request) = function Bit#(n) getRepresentableAlignmentMask ( t dummy
, Bit#(n) length_request) =
setBoundsCombined(nullCapFromDummy(dummy), length_request).mask; setBoundsCombined(nullCapFromDummy(dummy), length_request).mask;
// Get representable length // Get representable length
@@ -204,7 +230,8 @@ typeclass CHERICap#(type t, numeric type ot, numeric type flg, numeric type n, n
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));
return $format( "Valid: 0x%0x", isValidCap(cap)) + return $format( "Valid: 0x%0x", isValidCap(cap)) +
$format(" Perms: 0x%0x", getPerms(cap)) + $format(" Perms: 0x%0x", getPerms(cap)) +
$format(" Kind: ", fshow(getKind(cap))) + $format(" Kind: ", fshow(getKind(cap))) +
@@ -213,6 +240,9 @@ function Fmt showCHERICap(t cap) provisos (CHERICap#(t, ot, flg, n, mem_sz, mask
$format(" Length: 0x%0x", getLength(cap)); $format(" Length: 0x%0x", getLength(cap));
endfunction endfunction
// Cast typeclass to convert from one type to another. Helpful for converting
// a capability format to another.
typeclass Cast#(type src, type dest); typeclass Cast#(type src, type dest);
function dest cast (src x); function dest cast (src x);
endtypeclass endtypeclass