Files
cheri-cap-lib/CHERICap.bsv
jon 356c7891ee New function for adding to the address unsafely.
Would used an increment size based on mantissa width, but this is not
available in the type class, so just use 1 byte.
This function is currently used for adding small increments to the PC,
so does not need support for larger offsets.
2020-08-21 15:31:31 +01:00

226 lines
8.4 KiB
Plaintext

/*-
* Copyright (c) 2018-2019 Alexandre Joannou
* Copyright (c) 2019 Peter Rugg
* All rights reserved.
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory (Department of Computer Science and
* Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
* DARPA SSITH research programme.
*
* @BERI_LICENSE_HEADER_START@
*
* Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership. BERI licenses this
* file to you under the BERI Hardware-Software License, Version 1.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.beri-open-systems.org/legal/license-1-0.txt
*
* Unless required by applicable law or agreed to in writing, Work distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* @BERI_LICENSE_HEADER_END@
*/
package CHERICap;
// CHERI capability typeclass
////////////////////////////////////////////////////////////////////////////////
// Permission bits
typedef Bit#(16) SoftPerms;
typedef struct {
Bool permitSetCID;
Bool accessSysRegs;
Bool permitUnseal;
Bool permitCCall;
Bool permitSeal;
Bool permitStoreLocalCap;
Bool permitStoreCap;
Bool permitLoadCap;
Bool permitStore;
Bool permitLoad;
Bool permitExecute;
Bool global;
} HardPerms deriving(Bits, Eq, FShow);
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 invert (x) = unpack(invert (pack(x))); //XXX Bluespec ref guide uses x1 here but simply x for other single arg methods...
function \<< (x1, x2) = unpack(pack(x1) << x2);
function \>> (x1, x2) = unpack(pack(x1) >> x2);
function msb (x) = msb(pack(x));
function lsb (x) = lsb(pack(x));
endinstance
// Type to return the result of an operation along with whether the operation was exact
// In cases where no sensible inexact representation exists, the only guarantee is that
// the tag bit is not set.
typedef struct {
Bool exact;
t value;
} Exact #(type t) deriving (Bits);
typedef union tagged {
void UNSEALED;
void SENTRY;
void RES0;
void RES1;
Bit#(ot) SEALED_WITH_TYPE;
} Kind#(numeric type ot) 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));
// Return whether the Capability is valid
function Bool isValidCap (t cap);
// Set the capability as valid. All fields left unchanged
function t setValidCap (t cap, Bool valid);
// Get the flags field
function Bit#(flg) getFlags (t cap);
// Set the flags field
function t setFlags (t cap, Bit#(flg) flags);
// Get the hardware permissions
function HardPerms getHardPerms (t cap);
// Set the hardware permissions
function t setHardPerms (t cap, HardPerms hardperms);
// Get the software permissions
function SoftPerms getSoftPerms (t cap);
// Set the software permissions
function t setSoftPerms (t cap, SoftPerms softperms);
// Get the architectural permissions
function Bit#(31) getPerms (t cap) =
zeroExtend({pack(getSoftPerms(cap)), 3'h0, pack(getHardPerms(cap))});
// Set the architectural permissions
function t setPerms (t cap, Bit#(31) perms) =
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, ...
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);
// Set the address of the capability. Result invalid if unrepresentable
function Exact#(t) setAddr (t cap, Bit#(n) addr);
// Set the address of the capability. Result assumed to be representable
function t setAddrUnsafe (t cap, Bit#(n) addr);
// Add to the address of the capability. Result assumed to be representable
function t addAddrUnsafe (t cap, Bit#(8) inc);
// Get the offset of the capability
function Bit#(n) getOffset (t cap) = getAddr(cap) - getBase(cap);
// Modify the offset of the capability. Result invalid if unrepresentable
function Exact#(t) modifyOffset (t cap, Bit#(n) offset, Bool doInc);
// Set the offset of the capability. Result invalid if unrepresentable
function Exact#(t) setOffset (t cap, Bit#(n) offset) =
modifyOffset(cap, offset, False);
// Set the offset of the capability. Result invalid if unrepresentable
function Exact#(t) incOffset (t cap, Bit#(n) inc) =
modifyOffset(cap, inc, True);
// Get the base
function Bit#(n) getBase (t cap);
// Get the top
function Bit#(TAdd#(n, 1)) getTop (t cap);
// Get the length
function Bit#(TAdd#(n, 1)) getLength (t cap);
// Assertion that address is between base and top
function Bool isInBounds (t cap, Bool isTopIncluded);
Bool isNotTooHigh = isTopIncluded ? zeroExtend(getAddr(cap)) <= getTop(cap)
: zeroExtend(getAddr(cap)) < getTop(cap);
Bool isNotTooLow = getAddr(cap) >= getBase(cap);
return isNotTooLow && isNotTooHigh;
endfunction
// 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);
// Workaround to allow null cap to be derived in default implementations
function t nullCapFromDummy(t dummy);
// Return the maximally permissive capability (initial register state)
function t almightyCap;
// Return the null capability
function t nullCap = nullCapFromDummy(?);
// Check if a type is valid
function Bool validAsType (t dummy, Bit#(n) checkType);
// convert from and to bit memory representation
function t fromMem (Tuple2#(Bool, Bit#(mem_sz)) mem_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);
// 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;
// Get representable length
// function Bit#(n) getRepresentableLength (t dummy, Bit#(n) length_request) =
// setBoundsCombined(nullCap, length_request).length;
// Assert that the encoding is valid
function Bool isDerivable (t cap);
endtypeclass
function Fmt showCHERICap(t cap) provisos (CHERICap#(t, ot, flg, n, mem_sz, maskable_bits));
return $format( "Valid: 0x%0x", isValidCap(cap)) +
$format(" Perms: 0x%0x", getPerms(cap)) +
$format(" Kind: ", fshow(getKind(cap))) +
$format(" Addr: 0x%0x", getAddr(cap)) +
$format(" Base: 0x%0x", getBase(cap)) +
$format(" Length: 0x%0x", getLength(cap));
endfunction
typeclass Cast#(type src, type dest);
function dest cast (src x);
endtypeclass
instance Cast#(t, t);
function cast = id;
endinstance
endpackage