Introduced a getMeta method as a counterpart to getAddr for getting all
bits of in-memory architectural capability representation
This commit is contained in:
@@ -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 };
|
||||||
|
|||||||
100
CHERICap.bsv
100
CHERICap.bsv
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user