Merged Capability128ccLibs.bsv and CHERICC128Cap.bsv into CHERICC_Fat.bsv and added a CHERICC.bsv library (not currently working)
This commit is contained in:
452
CHERICC.bsv
Normal file
452
CHERICC.bsv
Normal file
@@ -0,0 +1,452 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2018-2019 Alexandre Joannou
|
||||||
|
* 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 CHERICC;
|
||||||
|
|
||||||
|
import CHERICap :: *;
|
||||||
|
|
||||||
|
export CHERICCCap;
|
||||||
|
export CHERICCBounds;
|
||||||
|
|
||||||
|
`define div2(x) TDiv#(x, 2)
|
||||||
|
`define sub2(x) TSub#(x, 2)
|
||||||
|
`define i(x) valueOf(x)
|
||||||
|
|
||||||
|
// CHERICCBounds Bounds type
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// CHERICC compressed bounds type
|
||||||
|
typedef union tagged {
|
||||||
|
struct {
|
||||||
|
Bit#(1) lenMSB;
|
||||||
|
Bit#(`sub2(base_)) top;
|
||||||
|
Bit#(base_) base;
|
||||||
|
} Exp0;
|
||||||
|
struct {
|
||||||
|
Bit#(TSub#(`sub2(base_), `div2(e_))) top;
|
||||||
|
Bit#(TSub#(base_, `div2(e_))) base;
|
||||||
|
Bit#(e_) e;
|
||||||
|
} EmbeddedExp;
|
||||||
|
struct {
|
||||||
|
Bit#(TSub#(`sub2(base_), TAdd#(`div2(t_), `div2(e_)))) top;
|
||||||
|
Bit#(TSub#(base_, TAdd#(`div2(t_), `div2(e_)))) base;
|
||||||
|
Bit#(t_) otype;
|
||||||
|
Bit#(e_) e;
|
||||||
|
} Sealed;
|
||||||
|
} CHERICCBounds#(numeric type base_, numeric type e_, numeric type t_);
|
||||||
|
|
||||||
|
instance Bits#(CHERICCBounds#(b_, e_, t_), TMul#(b_, 2)) provisos(
|
||||||
|
// in pack
|
||||||
|
Add#(TDiv#(e_, 2), a__, e_), // truncates on e
|
||||||
|
Add#(TDiv#(t_, 2), b__, t_), // truncates on t
|
||||||
|
Add#(2, c__, b_), // 2 bits stolen from top
|
||||||
|
// in unpack
|
||||||
|
Add#(d__, TDiv#(e_, 2), TMul#(b_, 2)), // truncates raw into e
|
||||||
|
Add#(e__, TDiv#(t_, 2), TMul#(b_, 2)), // truncates raw into t
|
||||||
|
Add#(2, f__, TSub#(
|
||||||
|
TSub#(
|
||||||
|
TAdd#(b_,
|
||||||
|
TAdd#(
|
||||||
|
TDiv#(t_, 2),
|
||||||
|
TDiv#(e_, 2))),
|
||||||
|
TDiv#(e_, 2)),
|
||||||
|
TDiv#(t_, 2)))
|
||||||
|
);
|
||||||
|
function pack(ccbounds) =
|
||||||
|
case (ccbounds) matches
|
||||||
|
tagged Exp0 .x: return {{{1'b0, x.lenMSB}, x.top}, x.base};
|
||||||
|
tagged EmbeddedExp .x: begin
|
||||||
|
Bit#(`div2(e_)) eHi = truncateLSB(x.e);
|
||||||
|
Bit#(`div2(e_)) eLo = truncate(x.e);
|
||||||
|
return {{2'b10, x.top, eHi}, {x.base, eLo}};
|
||||||
|
end
|
||||||
|
tagged Sealed .x: begin
|
||||||
|
Bit#(`div2(t_)) tHi = truncateLSB(x.otype);
|
||||||
|
Bit#(`div2(t_)) tLo = truncate(x.otype);
|
||||||
|
Bit#(`div2(e_)) eHi = truncateLSB(x.e);
|
||||||
|
Bit#(`div2(e_)) eLo = truncate(x.e);
|
||||||
|
return {{2'b11, x.top, tHi, eHi}, {x.base, tLo, eLo}};
|
||||||
|
/*
|
||||||
|
Bit#(TMul#(b_, 2)) acc = 0;
|
||||||
|
acc = acc | zeroExtend(2'b11);
|
||||||
|
acc = (acc << `i(b_)-2-`i(t_)/2-`i(e_)/2) | zeroExtend(x.top);
|
||||||
|
acc = (acc << `i(t_)/2) | zeroExtend(tHi);
|
||||||
|
acc = (acc << `i(e_)/2) | zeroExtend(eHi);
|
||||||
|
acc = (acc << `i(b_)-`i(t_)/2-`i(e_)/2) | zeroExtend(x.base);
|
||||||
|
acc = (acc << `i(t_)/2) | zeroExtend(tLo);
|
||||||
|
acc = (acc << `i(e_)/2) | zeroExtend(eLo);
|
||||||
|
return acc;
|
||||||
|
*/
|
||||||
|
end
|
||||||
|
endcase;
|
||||||
|
function unpack(raw);
|
||||||
|
if (raw[2*`i(b_)-1] == 0) return Exp0 {
|
||||||
|
lenMSB: raw[2*`i(b_)-2],
|
||||||
|
top: raw[2*`i(b_)-3:`i(b_)],
|
||||||
|
base: raw[`i(b_)-1:0]
|
||||||
|
};
|
||||||
|
else if (raw[2*`i(b_)-2] == 0) begin
|
||||||
|
Bit#(`div2(e_)) eHi = truncate(raw >> `i(b_));
|
||||||
|
Bit#(`div2(e_)) eLo = truncate(raw);
|
||||||
|
// XXX Bit#(e_) new_e = {eHi, eLo}; XXX simpler provisos with equiv line below
|
||||||
|
Bit#(e_) new_e = zeroExtend(eLo) | zeroExtend(eHi) << `i(e_)/2;
|
||||||
|
return EmbeddedExp {
|
||||||
|
top: raw[2*`i(b_)-3:`i(b_)+`i(e_)/2],
|
||||||
|
base: raw[`i(b_)-1:`i(e_)/2],
|
||||||
|
e: new_e
|
||||||
|
};
|
||||||
|
end else begin
|
||||||
|
Bit#(`div2(t_)) tHi = truncate(raw >> (`i(b_)+(`i(e_)/2)));
|
||||||
|
Bit#(`div2(t_)) tLo = truncate(raw >> (`i(e_)/2));
|
||||||
|
// XXX Bit#(t_) new_t = {tHi, tLo}; XXX simpler provisos with equiv line below
|
||||||
|
Bit#(t_) new_t = zeroExtend(tLo) | zeroExtend(tHi) << `i(t_)/2;
|
||||||
|
Bit#(`div2(e_)) eHi = truncate(raw >> `i(b_));
|
||||||
|
Bit#(`div2(e_)) eLo = truncate(raw);
|
||||||
|
// XXX Bit#(e_) new_e = {eHi, eLo}; XXX simpler provisos with equiv line below
|
||||||
|
Bit#(e_) new_e = zeroExtend(eLo) | zeroExtend(eHi) << `i(e_)/2;
|
||||||
|
return Sealed {
|
||||||
|
top: raw[2*`i(b_)-3:`i(b_)+`i(e_)/2+`i(t_)/2],
|
||||||
|
base: raw[`i(b_)-1:`i(e_)/2+`i(t_)/2],
|
||||||
|
otype: new_t,
|
||||||
|
e: new_e
|
||||||
|
};
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
endinstance
|
||||||
|
|
||||||
|
// CHERICC capability type
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
`define CCSoftPerms Bit#(4)
|
||||||
|
`define AllPermsSz TAdd#(SizeOf#(`CCSoftPerms), SizeOf#(HardPerms))
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Bool isCap;
|
||||||
|
`CCSoftPerms softperms;
|
||||||
|
HardPerms hardperms;
|
||||||
|
Bit#(TSub#(addr_, TAdd#(bounds_, `AllPermsSz))) res; // 15 permission bits and bounds_ bits to deduct
|
||||||
|
CHERICCBounds#(`div2(bounds_), e_, t_) bounds;
|
||||||
|
Bit#(addr_) addr;
|
||||||
|
} CHERICCCap#(numeric type addr_, numeric type bounds_, numeric type e_, numeric type t_);
|
||||||
|
|
||||||
|
instance Bits#(CHERICCCap#(addr_, bounds_, e_, t_),
|
||||||
|
TAdd#(1, TAdd#(addr_, TAdd#(bounds_, TAdd#(res_, `AllPermsSz))))) provisos(
|
||||||
|
Bits#(CHERICCBounds#(TDiv#(bounds_, 2), e_, t_), bounds_),
|
||||||
|
Add#(TAdd#(bounds_, `AllPermsSz), res_, addr_)
|
||||||
|
);
|
||||||
|
function pack(cap);
|
||||||
|
Bit#(1) isCap = pack(cap.isCap);
|
||||||
|
Bit#(SizeOf#(`CCSoftPerms)) softperms = cap.softperms;
|
||||||
|
Bit#(SizeOf#(HardPerms)) hardperms = pack(cap.hardperms);
|
||||||
|
Bit#(res_) res = cap.res;
|
||||||
|
Bit#(bounds_) bounds = pack(cap.bounds);
|
||||||
|
Bit#(addr_) addr = cap.addr;
|
||||||
|
return {isCap, softperms, hardperms, res, bounds, addr};
|
||||||
|
endfunction
|
||||||
|
//function pack(cap) = {cap.softperms, pack(cap.perms), cap.res, pack(cap.bounds), cap.addr};
|
||||||
|
function unpack(raw) = CHERICCCap {
|
||||||
|
isCap: unpack(msb(raw)),
|
||||||
|
softperms: raw[2*`i(addr_)-1:2*`i(addr_)-`i(SizeOf#(`CCSoftPerms))],
|
||||||
|
hardperms: unpack(raw[2*`i(addr_)-5:2*`i(addr_)-`i(`AllPermsSz)]),
|
||||||
|
res: raw[2*`i(addr_)-`i(`AllPermsSz)-1:`i(addr_)+`i(bounds_)],
|
||||||
|
bounds: unpack(raw[`i(addr_)+`i(bounds_)-1:`i(addr_)]),
|
||||||
|
addr: raw[`i(addr_)-1:0]
|
||||||
|
};
|
||||||
|
endinstance
|
||||||
|
|
||||||
|
`undef AllPermsSz
|
||||||
|
`undef CCSoftPerms
|
||||||
|
|
||||||
|
// CHERICCCap inner helpers
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
CHERICCCap#(addr_, bounds_, e_, t_) almightyCC = CHERICCCap {
|
||||||
|
isCap: True,
|
||||||
|
softperms: ~0,
|
||||||
|
hardperms: unpack(~0),
|
||||||
|
res: 0,
|
||||||
|
bounds: EmbeddedExp {
|
||||||
|
top: 0, // implied top bits of 01
|
||||||
|
base: 0,
|
||||||
|
// position the 1 of top in the addr_'th bit
|
||||||
|
e: fromInteger(`i(addr_)-((`i(bounds_)/2)-2))
|
||||||
|
},
|
||||||
|
addr: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
CHERICCCap#(addr_, bounds_, e_, t_) nullCC = CHERICCCap {
|
||||||
|
isCap: False,
|
||||||
|
softperms: 0,
|
||||||
|
hardperms: unpack(0),
|
||||||
|
res: 0,
|
||||||
|
bounds: EmbeddedExp {
|
||||||
|
top: 0, // implied top bits of 01
|
||||||
|
base: 0,
|
||||||
|
e: fromInteger(`i(addr_)-((`i(bounds_)/2)-2)) // position the 1 of top in the addr_'th bit
|
||||||
|
},
|
||||||
|
addr: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
function Bit#(e_) getExpCC(CHERICCCap#(addr_, bounds_, e_, t_) cap);
|
||||||
|
case (cap.bounds) matches
|
||||||
|
tagged Exp0 .b: return 0;
|
||||||
|
tagged EmbeddedExp .b: return b.e;
|
||||||
|
tagged Sealed .b: return b.e;
|
||||||
|
endcase
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function Bit#(3) getRepBoundCC(CHERICCCap#(addr_, bounds_, e_, t_) cap)
|
||||||
|
provisos (Add#(3, a__, `div2(bounds_))) =
|
||||||
|
truncateLSB(cap.bounds.Exp0.base) - 3'b001; // always 1/8th of representable space below object
|
||||||
|
|
||||||
|
function Int#(2) getRegionCorrectionCC(Bit#(3) a, Bit#(3) b, Bit#(3) rep) =
|
||||||
|
((b < rep) == (a < rep)) ? 0 : (((b < rep) && (a >= rep)) ? 1 : -1);
|
||||||
|
|
||||||
|
function Bit#(`div2(bounds_))
|
||||||
|
getTopFieldCC(CHERICCCap#(addr_, bounds_, e_, t_) cap);
|
||||||
|
Bit#(2) c_carry = 2'b00;
|
||||||
|
Bit#(2) c_len = 2'b01;
|
||||||
|
Bit#(`sub2(`div2(bounds_))) partialTop = 0;
|
||||||
|
case (cap.bounds) matches
|
||||||
|
tagged Exp0 .b: begin
|
||||||
|
if (zeroExtend(b.top) < b.base) c_carry = 2'b01;
|
||||||
|
c_len = {1'b0, b.lenMSB};
|
||||||
|
partialTop = b.top;
|
||||||
|
end
|
||||||
|
tagged EmbeddedExp .b: begin
|
||||||
|
if (zeroExtend(b.top) < b.base) c_carry = 2'b01;
|
||||||
|
partialTop = {b.top, 0};
|
||||||
|
end
|
||||||
|
tagged Sealed .b: begin
|
||||||
|
if (zeroExtend(b.top) < b.base) c_carry = 2'b01;
|
||||||
|
partialTop = {b.top, 0};
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
return {truncateLSB(cap.bounds.Exp0.base) + c_carry + c_len, partialTop};
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function Bit#(`div2(bounds_))
|
||||||
|
getBaseFieldCC(CHERICCCap#(addr_, bounds_, e_, t_) cap) =
|
||||||
|
case (cap.bounds) matches
|
||||||
|
tagged Exp0 .b: b.base;
|
||||||
|
tagged EmbeddedExp .b: {b.base, 0};
|
||||||
|
tagged Sealed .b: {b.base, 0};
|
||||||
|
endcase;
|
||||||
|
|
||||||
|
// CHERICCCap CHERICap instance
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
instance CHERICap#(CHERICCCap#(addr_, bounds_, e_, t_), t_, addr_) provisos (
|
||||||
|
Add#(3, a__, `div2(bounds_)), // 3 bits of bounds for 1/8th of rep space
|
||||||
|
Add#(3, b__, addr_), // same for addr
|
||||||
|
Add#(c__, TAdd#(2, `div2(bounds_)), addr_), // for base correction
|
||||||
|
Add#(d__, TAdd#(2, `div2(bounds_)), TAdd#(addr_, 1)), // for top 2 bits of Int#(2) correction
|
||||||
|
Add#(e__, `div2(bounds_), addr_), // slice addr into smaller bounds field
|
||||||
|
Add#(f__, `div2(bounds_), TAdd#(addr_, 1)), // same for addr+1
|
||||||
|
Add#(g__, e_, TLog#(TAdd#(1, addr_))) // can fit result of countZerosMSB in e_
|
||||||
|
);
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function isValidCap(cap) = cap.isCap;
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function setValidCap(cap, v);
|
||||||
|
cap.isCap = v;
|
||||||
|
return cap;
|
||||||
|
endfunction
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function getHardPerms(cap) = cap.hardperms;
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function setHardPerms(cap, hardperms);
|
||||||
|
cap.hardperms = hardperms;
|
||||||
|
return cap;
|
||||||
|
endfunction
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function getSoftPerms(cap) = zeroExtend(cap.softperms);
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function setSoftPerms(cap, softperms);
|
||||||
|
cap.softperms = truncate(softperms);
|
||||||
|
return cap;
|
||||||
|
endfunction
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function getKind(cap) = case (cap.bounds) matches
|
||||||
|
tagged Sealed ._: return SEALED_WITH_TYPE;
|
||||||
|
default: return UNSEALED;
|
||||||
|
endcase;
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function getType(cap) = case (cap.bounds) matches
|
||||||
|
tagged Sealed .b: return zeroExtend(b.otype);
|
||||||
|
default: return -1;
|
||||||
|
endcase;
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function setType(cap, otype);
|
||||||
|
let new_cap = cap;
|
||||||
|
let isExact = True;
|
||||||
|
case (cap.bounds) matches
|
||||||
|
tagged Sealed .b: if (otype == -1) begin
|
||||||
|
//Bit#(addr_) addrBits = cap.address >> b.e;
|
||||||
|
//let baseMid = addrBits[`sub1(TAdd#(`div2(t_), `div2(e))):`div2(e_)];
|
||||||
|
//let baseLo = addrBits[`sub1(`div2(e_)):0];
|
||||||
|
//let topMid = baseMid;
|
||||||
|
//let topLo = baseLo;
|
||||||
|
let baseHi = b.base;
|
||||||
|
let topHi = b.top;
|
||||||
|
if (b.e == 0) new_cap.bounds = Exp0 {
|
||||||
|
lenMSB: 1,
|
||||||
|
top: {topHi, 0},
|
||||||
|
base: {baseHi, 0}
|
||||||
|
};
|
||||||
|
else new_cap.bounds = EmbeddedExp {
|
||||||
|
top: {topHi, 0},
|
||||||
|
base: {baseHi, 0},
|
||||||
|
e: b.e
|
||||||
|
};
|
||||||
|
end
|
||||||
|
default: if (otype != -1) begin
|
||||||
|
Bit#(e_) new_e = case (cap.bounds) matches
|
||||||
|
tagged EmbeddedExp .b: b.e;
|
||||||
|
default: 0;
|
||||||
|
endcase;
|
||||||
|
new_cap.bounds = Sealed {
|
||||||
|
top: truncateLSB(cap.bounds.Exp0.top),
|
||||||
|
base: truncateLSB(cap.bounds.Exp0.base),
|
||||||
|
otype: otype,
|
||||||
|
e: new_e
|
||||||
|
};
|
||||||
|
Bit#(`div2(t_)) zero = 0;
|
||||||
|
isExact = cap.bounds.Exp0.top[`i(t_)/2-1:0] == zero &&
|
||||||
|
cap.bounds.Exp0.base[`i(t_)/2-1:0] == zero;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
return Exact{exact: isExact, value: new_cap};
|
||||||
|
endfunction
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function getAddr(cap) = cap.addr;
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function setAddr(cap) = error("setAddr unimplemented");
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function getOffset(cap) = zeroExtend(getAddr(cap)) - getBase(cap);
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function setOffset(cap, offset);
|
||||||
|
Bit#(`div2(bounds_)) e0m = ~(~0 << ((`i(t_)/2)+(`i(e_)/2)));
|
||||||
|
Bit#(TSub#(`div2(bounds_), `div2(e_))) eem = ~(~0 << (`i(t_)/2));
|
||||||
|
// extract specific useful values
|
||||||
|
Bit#(e_) e = getExpCC(cap);
|
||||||
|
Bit#(e_) almighty_e = fromInteger(`i(addr_)-((`i(bounds_)/2)-2)); // position the 1 of top in the addr_'th bit
|
||||||
|
Bit#(addr_) i = offset - getOffset(cap);
|
||||||
|
Bit#(`div2(bounds_)) imid = truncate(i >> e);
|
||||||
|
Bit#(`div2(bounds_)) amid = truncate(cap.addr >> e);
|
||||||
|
Bit#(`div2(bounds_)) r = {getRepBoundCC(cap), 0};
|
||||||
|
// perform inRange and inLimit tests
|
||||||
|
Bit#(addr_) mask = ~0 << (e + fromInteger(`i(bounds_)/2));
|
||||||
|
Bool inRange = ((i & mask) == mask) || ((i & mask) == 0);
|
||||||
|
Bool inLimits = (i >= 0) ? imid < (r - amid - 1) :
|
||||||
|
imid >= (r - amid) && r != amid;
|
||||||
|
Bool isExact = ((inRange && inLimits) || e >= almighty_e);
|
||||||
|
// perform the offset update
|
||||||
|
let new_cap = cap;
|
||||||
|
new_cap.addr = truncate(getBase(cap) + offset);
|
||||||
|
return Exact{exact: isExact, value: new_cap};
|
||||||
|
endfunction
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function getBase(cap);
|
||||||
|
let baseCC = getBaseFieldCC(cap);
|
||||||
|
let e = getExpCC(cap);
|
||||||
|
let correction = getRegionCorrectionCC(truncateLSB(cap.addr),
|
||||||
|
truncateLSB(baseCC),
|
||||||
|
getRepBoundCC(cap));
|
||||||
|
Bit#(addr_) mask = ~0 << (e + fromInteger(`i(bounds_)/2));
|
||||||
|
Bit#(addr_) acc = cap.addr & mask;
|
||||||
|
return acc + (signExtend({pack(correction), baseCC}) << e);
|
||||||
|
endfunction
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function getTop(cap);
|
||||||
|
let topCC = getTopFieldCC(cap);
|
||||||
|
let e = getExpCC(cap);
|
||||||
|
let correction = getRegionCorrectionCC(truncateLSB(cap.addr),
|
||||||
|
truncateLSB(topCC),
|
||||||
|
getRepBoundCC(cap));
|
||||||
|
Bit#(TAdd#(addr_, 1)) mask = ~0 << (e + fromInteger(`i(bounds_)/2));
|
||||||
|
Bit#(TAdd#(addr_, 1)) acc = zeroExtend(cap.addr) & mask;
|
||||||
|
return acc + (signExtend({pack(correction), topCC}) << e);
|
||||||
|
endfunction
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function getLength(cap) = getTop(cap) - zeroExtend(getBase(cap));
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function setBounds(cap, length);
|
||||||
|
let new_cap = cap;
|
||||||
|
let isExact = True;
|
||||||
|
// deriving new exponent
|
||||||
|
Bit#(TLog#(TAdd#(1, addr_))) e =
|
||||||
|
pack(fromInteger(`i(addr_))
|
||||||
|
- countZerosMSB(length >> ((`i(bounds_)/2)-1)));
|
||||||
|
// deriving the new base
|
||||||
|
Bit#(`div2(bounds_)) newBase = truncate(cap.addr >> e);
|
||||||
|
// deriving the new top
|
||||||
|
Bit#(TAdd#(addr_, 1)) fullTop = zeroExtend(cap.addr) + zeroExtend(length);
|
||||||
|
Bit#(`div2(bounds_)) newTop = truncate(fullTop >> e);
|
||||||
|
// fold the derived values back in the new cap
|
||||||
|
if (e == 0) begin
|
||||||
|
new_cap.bounds = Exp0 {
|
||||||
|
lenMSB: length[(`i(bounds_)/2)-2],
|
||||||
|
top: truncate(newTop),
|
||||||
|
base: newBase
|
||||||
|
};
|
||||||
|
end else begin
|
||||||
|
// slice the top and base values appropriately
|
||||||
|
Bit#(TSub#(`sub2(`div2(bounds_)), `div2(e_))) upperTop = truncateLSB(newTop);
|
||||||
|
Bit#(TSub#(`div2(bounds_), `div2(e_))) upperBase = truncateLSB(newBase);
|
||||||
|
// take care of loss of significant bits in the bits stolen/dropped from fullTop
|
||||||
|
Bit#(TAdd#(addr_, 1)) mask = ~(~0 << (e + fromInteger(`i(e_)/2)));
|
||||||
|
if ((fullTop & mask) != 0) upperTop = upperTop + 1;
|
||||||
|
new_cap.bounds = EmbeddedExp {
|
||||||
|
top: upperTop,
|
||||||
|
base: upperBase,
|
||||||
|
e: truncate(e)
|
||||||
|
};
|
||||||
|
// check for exact or not
|
||||||
|
Bit#(addr_) exactMask = ~(~0 << (e - fromInteger(`i(bounds_)/2 - `i(e_)/2 - 1)));
|
||||||
|
if ((cap.addr & exactMask) != 0) isExact = False;
|
||||||
|
if ((length & exactMask) != 0) isExact = False;
|
||||||
|
end
|
||||||
|
return Exact{exact: isExact, value: new_cap};
|
||||||
|
endfunction
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function nullWithAddr(x);
|
||||||
|
let cap = nullCap;
|
||||||
|
cap.addr = x;
|
||||||
|
return cap;
|
||||||
|
endfunction
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function almightyCap = almightyCC;
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
function nullCap = nullCC;
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
endinstance
|
||||||
|
|
||||||
|
`undef div2
|
||||||
|
`undef sub2
|
||||||
|
`undef i
|
||||||
|
|
||||||
|
endpackage
|
||||||
@@ -1,265 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 CHERICC128Cap;
|
|
||||||
|
|
||||||
import DefaultValue::*;
|
|
||||||
import Capability128ccLibs::*;
|
|
||||||
import CHERICap::*;
|
|
||||||
|
|
||||||
export CapMem;
|
|
||||||
export CapReg;
|
|
||||||
export CapPipe;
|
|
||||||
export CHERICap::*;
|
|
||||||
|
|
||||||
|
|
||||||
// ===============================================================================
|
|
||||||
// Typeclass instance for interface
|
|
||||||
|
|
||||||
typedef Bit#(129) CapMem;
|
|
||||||
|
|
||||||
typedef CapFat CapReg;
|
|
||||||
|
|
||||||
typedef Tuple2#(CapFat, TempFields) CapPipe;
|
|
||||||
|
|
||||||
instance CHERICap #(CapMem, 18, 64);
|
|
||||||
function isValidCap (x) = error("feature not implemented for this cap type");
|
|
||||||
function setValidCap (x) = error("feature not implemented for this cap type");
|
|
||||||
function getHardPerms (x) = error("feature not implemented for this cap type");
|
|
||||||
function setHardPerms (x) = error("feature not implemented for this cap type");
|
|
||||||
function getSoftPerms (x) = error("feature not implemented for this cap type");
|
|
||||||
function setSoftPerms (x) = error("feature not implemented for this cap type");
|
|
||||||
function getKind (x) = error("feature not implemented for this cap type");
|
|
||||||
function getType (x) = error("feature not implemented for this cap type");
|
|
||||||
function setType (x) = error("feature not implemented for this cap type");
|
|
||||||
function getAddr (x) = error("feature not implemented for this cap type");
|
|
||||||
function setAddr (x) = error("feature not implemented for this cap type");
|
|
||||||
function getOffset (x) = error("feature not implemented for this cap type");
|
|
||||||
function setOffset (x) = error("feature not implemented for this cap type");
|
|
||||||
function getBase (x) = error("feature not implemented for this cap type");
|
|
||||||
function getTop (x) = error("feature not implemented for this cap type");
|
|
||||||
function getLength (x) = error("feature not implemented for this cap type");
|
|
||||||
function setBounds (x) = error("feature not implemented for this cap type");
|
|
||||||
function nullWithAddr (x) = 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");
|
|
||||||
endinstance
|
|
||||||
|
|
||||||
instance CHERICap #(CapReg, 18, 64);
|
|
||||||
function isValidCap (x) = error("feature not implemented for this cap type");
|
|
||||||
function setValidCap (x) = error("feature not implemented for this cap type");
|
|
||||||
function getHardPerms (x) = error("feature not implemented for this cap type");
|
|
||||||
function setHardPerms (x) = error("feature not implemented for this cap type");
|
|
||||||
function getSoftPerms (x) = error("feature not implemented for this cap type");
|
|
||||||
function setSoftPerms (x) = error("feature not implemented for this cap type");
|
|
||||||
function getKind (x) = error("feature not implemented for this cap type");
|
|
||||||
function getType (x) = error("feature not implemented for this cap type");
|
|
||||||
function setType (x) = error("feature not implemented for this cap type");
|
|
||||||
function getAddr (x) = error("feature not implemented for this cap type");
|
|
||||||
function setAddr (x) = error("feature not implemented for this cap type");
|
|
||||||
function getOffset (x) = error("feature not implemented for this cap type");
|
|
||||||
function setOffset (x) = error("feature not implemented for this cap type");
|
|
||||||
function getBase (x) = error("feature not implemented for this cap type");
|
|
||||||
function getTop (x) = error("feature not implemented for this cap type");
|
|
||||||
function getLength (x) = error("feature not implemented for this cap type");
|
|
||||||
function setBounds (x) = error("feature not implemented for this cap type");
|
|
||||||
function nullWithAddr (x) = error("feature not implemented for this cap type");
|
|
||||||
function almightyCap = defaultCapFat;
|
|
||||||
function nullCap = Capability128ccLibs::nullCap;
|
|
||||||
endinstance
|
|
||||||
|
|
||||||
instance CHERICap #(CapPipe, 18, 64);
|
|
||||||
|
|
||||||
function isValidCap (x) = tpl_1(x).isCapability;
|
|
||||||
|
|
||||||
function CapPipe setValidCap (CapPipe cap, Bool tag);
|
|
||||||
let capReg = tpl_1(cap);
|
|
||||||
let tempFields = tpl_2(cap);
|
|
||||||
capReg.isCapability = tag;
|
|
||||||
return tuple2(capReg, tempFields);
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function HardPerms getHardPerms (CapPipe cap);
|
|
||||||
let capReg = tpl_1(cap);
|
|
||||||
return HardPerms {
|
|
||||||
accessSysRegs: capReg.perms.hard.acces_sys_regs,
|
|
||||||
permitUnseal: capReg.perms.hard.permit_unseal,
|
|
||||||
permitCCall: capReg.perms.hard.permit_ccall,
|
|
||||||
permitSeal: capReg.perms.hard.permit_seal,
|
|
||||||
permitStoreLocalCap: capReg.perms.hard.permit_store_ephemeral_cap,
|
|
||||||
permitStoreCap: capReg.perms.hard.permit_store_cap,
|
|
||||||
permitLoadCap: capReg.perms.hard.permit_load_cap,
|
|
||||||
permitStore: capReg.perms.hard.permit_store,
|
|
||||||
permitLoad: capReg.perms.hard.permit_load,
|
|
||||||
permitExecute: capReg.perms.hard.permit_execute,
|
|
||||||
global: capReg.perms.hard.non_ephemeral
|
|
||||||
};
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function CapPipe setHardPerms (CapPipe cap, HardPerms perms);
|
|
||||||
let capReg = tpl_1(cap);
|
|
||||||
let tempFields = tpl_2(cap);
|
|
||||||
capReg.perms.hard = HPerms {
|
|
||||||
reserved: ?,
|
|
||||||
acces_sys_regs: perms.accessSysRegs,
|
|
||||||
permit_unseal: perms.accessSysRegs,
|
|
||||||
permit_ccall: perms.accessSysRegs,
|
|
||||||
permit_seal: perms.accessSysRegs,
|
|
||||||
permit_store_ephemeral_cap: perms.accessSysRegs,
|
|
||||||
permit_store_cap: perms.accessSysRegs,
|
|
||||||
permit_load_cap: perms.accessSysRegs,
|
|
||||||
permit_store: perms.accessSysRegs,
|
|
||||||
permit_load: perms.accessSysRegs,
|
|
||||||
permit_execute: perms.accessSysRegs,
|
|
||||||
non_ephemeral: perms.accessSysRegs
|
|
||||||
};
|
|
||||||
return tuple2(capReg, tempFields);
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function SoftPerms getSoftPerms (CapPipe cap);
|
|
||||||
let capReg = tpl_1(cap);
|
|
||||||
return zeroExtend(capReg.perms.soft);
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function CapPipe setSoftPerms (CapPipe cap, SoftPerms perms);
|
|
||||||
let capReg = tpl_1(cap);
|
|
||||||
let tempFields = tpl_2(cap);
|
|
||||||
capReg.perms.soft = truncate(perms);
|
|
||||||
return tuple2(capReg, tempFields);
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function Kind getKind (CapPipe cap);
|
|
||||||
let capReg = tpl_1(cap);
|
|
||||||
case (capReg.otype)
|
|
||||||
otype_unsealed: return UNSEALED;
|
|
||||||
otype_sentry: return SENTRY;
|
|
||||||
default: return (capReg.otype <= otype_max) ? SEALED_WITH_TYPE : RES0;
|
|
||||||
endcase
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function getType (x) = getType(tpl_1(x)).d;
|
|
||||||
|
|
||||||
function Exact#(CapPipe) setType (CapPipe cap, Bit #(18) otype);
|
|
||||||
let capReg = tpl_1(cap);
|
|
||||||
let tempFields = tpl_2(cap);
|
|
||||||
if (otype == -1) begin
|
|
||||||
capReg = unseal(capReg, ?);
|
|
||||||
end else begin
|
|
||||||
capReg = seal(capReg, ?, VnD {v: True, d:otype});
|
|
||||||
end
|
|
||||||
return Exact {
|
|
||||||
exact: True,
|
|
||||||
value: tuple2(capReg, tempFields)
|
|
||||||
};
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function getAddr (x) = truncate(getAddress(tpl_1(x)));
|
|
||||||
|
|
||||||
function Exact#(CapPipe) setAddr (CapPipe cap, Bit#(64) address);
|
|
||||||
let capReg = tpl_1(cap);
|
|
||||||
let tempFields = tpl_2(cap);
|
|
||||||
capReg = setAddress(capReg, zeroExtend(address), tempFields);
|
|
||||||
return Exact {exact: capReg.isCapability, value: tuple2(capReg, getTempFields(capReg))};
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function getOffset (x) = getOffset(tpl_1(x));
|
|
||||||
|
|
||||||
function Exact#(CapPipe) setOffset (CapPipe cap, Bit#(64) offset);
|
|
||||||
let capReg = tpl_1(cap);
|
|
||||||
let tempFields = tpl_2(cap);
|
|
||||||
capReg = incOffset(capReg, ?, zeroExtend(offset), tempFields, True); //TODO split into separate incOffset and setOffset functions?
|
|
||||||
return Exact {exact: capReg.isCapability, value: tuple2(capReg, getTempFields(capReg))};
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function Bit#(64) getBase (CapPipe cap);
|
|
||||||
let capReg = tpl_1(cap);
|
|
||||||
let tempFields = tpl_2(cap);
|
|
||||||
return truncate(Capability128ccLibs::getBotFat(capReg, tempFields));
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function Bit#(65) getTop (CapPipe cap);
|
|
||||||
let capReg = tpl_1(cap);
|
|
||||||
let tempFields = tpl_2(cap);
|
|
||||||
return truncate(Capability128ccLibs::getTopFat(capReg, tempFields));
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function Bit#(65) getLength (CapPipe cap);
|
|
||||||
let capReg = tpl_1(cap);
|
|
||||||
let tempFields = tpl_2(cap);
|
|
||||||
return truncate(Capability128ccLibs::getLengthFat(capReg, tempFields));
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function Bool isInBounds (CapPipe cap, Bool inclusive);
|
|
||||||
let capReg = tpl_1(cap);
|
|
||||||
let tempFields = tpl_2(cap);
|
|
||||||
return capInBounds(capReg, tempFields, inclusive);
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function Exact#(CapPipe) setBounds (CapPipe cap, Bit#(64) length);
|
|
||||||
let capReg = tpl_1(cap);
|
|
||||||
let tempFields = tpl_2(cap);
|
|
||||||
match {.result, .exact} = Capability128ccLibs::setBounds(capReg, length);
|
|
||||||
return Exact {exact: exact, value: tuple2(result, getTempFields(result))};
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function CapPipe nullWithAddr (Bit#(64) addr);
|
|
||||||
let res = setAddress (nullCap, zeroExtend(addr), getTempFields(nullCap));
|
|
||||||
return tuple2(res, getTempFields(res));
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function almightyCap = tuple2(defaultCapFat, getTempFields(defaultCapFat));
|
|
||||||
|
|
||||||
function nullCap = tuple2(nullCap, getTempFields(nullCap));
|
|
||||||
|
|
||||||
endinstance
|
|
||||||
|
|
||||||
instance Cast #(CapMem, CapReg);
|
|
||||||
function CapReg cast (CapMem thin);
|
|
||||||
return unpackCap(unpack(thin));
|
|
||||||
endfunction
|
|
||||||
endinstance
|
|
||||||
|
|
||||||
instance Cast #(CapReg, CapMem);
|
|
||||||
function CapMem cast (CapReg fat);
|
|
||||||
return pack(packCap(fat));
|
|
||||||
endfunction
|
|
||||||
endinstance
|
|
||||||
|
|
||||||
instance Cast #(CapReg, CapPipe);
|
|
||||||
function CapPipe cast (CapReg thin);
|
|
||||||
return tuple2(thin, getTempFields(thin));
|
|
||||||
endfunction
|
|
||||||
endinstance
|
|
||||||
|
|
||||||
instance Cast #(CapPipe, CapReg);
|
|
||||||
function CapReg cast (CapPipe fat);
|
|
||||||
return tpl_1(fat);
|
|
||||||
endfunction
|
|
||||||
endinstance
|
|
||||||
|
|
||||||
endpackage
|
|
||||||
@@ -27,9 +27,10 @@
|
|||||||
* @BERI_LICENSE_HEADER_END@
|
* @BERI_LICENSE_HEADER_END@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package Capability128ccLibs;
|
package CHERICC_Fat;
|
||||||
|
|
||||||
import DefaultValue::*;
|
import DefaultValue :: *;
|
||||||
|
import CHERICap :: *;
|
||||||
|
|
||||||
// ===============================================================================
|
// ===============================================================================
|
||||||
|
|
||||||
@@ -332,7 +333,7 @@ function Bit#(n) smearMSBRight(Bit#(n) x);
|
|||||||
return res;
|
return res;
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function Tuple2#(CapFat, Bool) setBounds(CapFat cap, Address lengthFull);
|
function Tuple2#(CapFat, Bool) setBoundsFat(CapFat cap, Address lengthFull);
|
||||||
CapFat ret = cap;
|
CapFat ret = cap;
|
||||||
// Find new exponent by finding the index of the most significant bit of the
|
// 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
|
// length, or counting leading zeros in the high bits of the length, and
|
||||||
@@ -637,7 +638,7 @@ instance DefaultValue #(CapFat);
|
|||||||
};
|
};
|
||||||
endinstance
|
endinstance
|
||||||
|
|
||||||
CapFat nullCap = CapFat {
|
CapFat null_cap = CapFat {
|
||||||
isCapability: False,
|
isCapability: False,
|
||||||
perms : unpack(0),
|
perms : unpack(0),
|
||||||
reserved : 0,
|
reserved : 0,
|
||||||
@@ -767,4 +768,238 @@ function MetaInfo getMetaInfo (CapFat cap);
|
|||||||
baseCorrection : baseCorrection
|
baseCorrection : baseCorrection
|
||||||
};
|
};
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
// ===============================================================================
|
||||||
|
// Typeclass instance for interface
|
||||||
|
|
||||||
|
typedef Bit#(129) CapMem;
|
||||||
|
|
||||||
|
typedef CapFat CapReg;
|
||||||
|
|
||||||
|
typedef Tuple2#(CapFat, TempFields) CapPipe;
|
||||||
|
|
||||||
|
instance CHERICap #(CapMem, 18, 64);
|
||||||
|
function isValidCap = error("feature not implemented for this cap type");
|
||||||
|
function setValidCap = 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 getOffset = error("feature not implemented for this cap type");
|
||||||
|
function setOffset = 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 = error("feature not implemented for this cap type");
|
||||||
|
function nullCap = error("feature not implemented for this cap type");
|
||||||
|
endinstance
|
||||||
|
|
||||||
|
instance CHERICap #(CapReg, 18, 64);
|
||||||
|
function isValidCap = error("feature not implemented for this cap type");
|
||||||
|
function setValidCap = 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 getOffset = error("feature not implemented for this cap type");
|
||||||
|
function setOffset = 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;
|
||||||
|
endinstance
|
||||||
|
|
||||||
|
instance CHERICap #(CapPipe, 18, 64);
|
||||||
|
|
||||||
|
function isValidCap (x) = tpl_1(x).isCapability;
|
||||||
|
|
||||||
|
function CapPipe setValidCap (CapPipe cap, Bool tag);
|
||||||
|
let capReg = tpl_1(cap);
|
||||||
|
let tempFields = tpl_2(cap);
|
||||||
|
capReg.isCapability = tag;
|
||||||
|
return tuple2(capReg, tempFields);
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function HardPerms getHardPerms (CapPipe cap);
|
||||||
|
let capReg = tpl_1(cap);
|
||||||
|
return HardPerms {
|
||||||
|
accessSysRegs: capReg.perms.hard.acces_sys_regs,
|
||||||
|
permitUnseal: capReg.perms.hard.permit_unseal,
|
||||||
|
permitCCall: capReg.perms.hard.permit_ccall,
|
||||||
|
permitSeal: capReg.perms.hard.permit_seal,
|
||||||
|
permitStoreLocalCap: capReg.perms.hard.permit_store_ephemeral_cap,
|
||||||
|
permitStoreCap: capReg.perms.hard.permit_store_cap,
|
||||||
|
permitLoadCap: capReg.perms.hard.permit_load_cap,
|
||||||
|
permitStore: capReg.perms.hard.permit_store,
|
||||||
|
permitLoad: capReg.perms.hard.permit_load,
|
||||||
|
permitExecute: capReg.perms.hard.permit_execute,
|
||||||
|
global: capReg.perms.hard.non_ephemeral
|
||||||
|
};
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CapPipe setHardPerms (CapPipe cap, HardPerms perms);
|
||||||
|
let capReg = tpl_1(cap);
|
||||||
|
let tempFields = tpl_2(cap);
|
||||||
|
capReg.perms.hard = HPerms {
|
||||||
|
reserved: ?,
|
||||||
|
acces_sys_regs: perms.accessSysRegs,
|
||||||
|
permit_unseal: perms.accessSysRegs,
|
||||||
|
permit_ccall: perms.accessSysRegs,
|
||||||
|
permit_seal: perms.accessSysRegs,
|
||||||
|
permit_store_ephemeral_cap: perms.accessSysRegs,
|
||||||
|
permit_store_cap: perms.accessSysRegs,
|
||||||
|
permit_load_cap: perms.accessSysRegs,
|
||||||
|
permit_store: perms.accessSysRegs,
|
||||||
|
permit_load: perms.accessSysRegs,
|
||||||
|
permit_execute: perms.accessSysRegs,
|
||||||
|
non_ephemeral: perms.accessSysRegs
|
||||||
|
};
|
||||||
|
return tuple2(capReg, tempFields);
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function SoftPerms getSoftPerms (CapPipe cap);
|
||||||
|
let capReg = tpl_1(cap);
|
||||||
|
return zeroExtend(capReg.perms.soft);
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CapPipe setSoftPerms (CapPipe cap, SoftPerms perms);
|
||||||
|
let capReg = tpl_1(cap);
|
||||||
|
let tempFields = tpl_2(cap);
|
||||||
|
capReg.perms.soft = truncate(perms);
|
||||||
|
return tuple2(capReg, tempFields);
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function Kind getKind (CapPipe cap);
|
||||||
|
let capReg = tpl_1(cap);
|
||||||
|
case (capReg.otype)
|
||||||
|
otype_unsealed: return UNSEALED;
|
||||||
|
otype_sentry: return SENTRY;
|
||||||
|
default: return (capReg.otype <= otype_max) ? SEALED_WITH_TYPE : RES0;
|
||||||
|
endcase
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function getType (x) = getType(tpl_1(x)).d;
|
||||||
|
|
||||||
|
function Exact#(CapPipe) setType (CapPipe cap, Bit #(18) otype);
|
||||||
|
let capReg = tpl_1(cap);
|
||||||
|
let tempFields = tpl_2(cap);
|
||||||
|
if (otype == -1) begin
|
||||||
|
capReg = unseal(capReg, ?);
|
||||||
|
end else begin
|
||||||
|
capReg = seal(capReg, ?, VnD {v: True, d:otype});
|
||||||
|
end
|
||||||
|
return Exact {
|
||||||
|
exact: True,
|
||||||
|
value: tuple2(capReg, tempFields)
|
||||||
|
};
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function getAddr (x) = truncate(getAddress(tpl_1(x)));
|
||||||
|
|
||||||
|
function Exact#(CapPipe) setAddr (CapPipe cap, Bit#(64) address);
|
||||||
|
let capReg = tpl_1(cap);
|
||||||
|
let tempFields = tpl_2(cap);
|
||||||
|
capReg = setAddress(capReg, zeroExtend(address), tempFields);
|
||||||
|
return Exact {exact: capReg.isCapability, value: tuple2(capReg, getTempFields(capReg))};
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function getOffset (x) = getOffsetFat(tpl_1(x), tpl_2(x));
|
||||||
|
|
||||||
|
function Exact#(CapPipe) setOffset (CapPipe cap, Bit#(64) offset);
|
||||||
|
let capReg = tpl_1(cap);
|
||||||
|
let tempFields = tpl_2(cap);
|
||||||
|
capReg = incOffset(capReg, ?, zeroExtend(offset), tempFields, True); //TODO split into separate incOffset and setOffset functions?
|
||||||
|
return Exact {exact: capReg.isCapability, value: tuple2(capReg, getTempFields(capReg))};
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function Bit#(64) getBase (CapPipe cap);
|
||||||
|
let capReg = tpl_1(cap);
|
||||||
|
let tempFields = tpl_2(cap);
|
||||||
|
return truncate(getBotFat(capReg, tempFields));
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function Bit#(65) getTop (CapPipe cap);
|
||||||
|
let capReg = tpl_1(cap);
|
||||||
|
let tempFields = tpl_2(cap);
|
||||||
|
return truncate(getTopFat(capReg, tempFields));
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function Bit#(65) getLength (CapPipe cap);
|
||||||
|
let capReg = tpl_1(cap);
|
||||||
|
let tempFields = tpl_2(cap);
|
||||||
|
return truncate(getLengthFat(capReg, tempFields));
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function Bool isInBounds (CapPipe cap, Bool inclusive);
|
||||||
|
let capReg = tpl_1(cap);
|
||||||
|
let tempFields = tpl_2(cap);
|
||||||
|
return capInBounds(capReg, tempFields, inclusive);
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function Exact#(CapPipe) setBounds (CapPipe cap, Bit#(64) length);
|
||||||
|
let capReg = tpl_1(cap);
|
||||||
|
let tempFields = tpl_2(cap);
|
||||||
|
match {.result, .exact} = setBoundsFat(capReg, length);
|
||||||
|
return Exact {exact: exact, value: tuple2(result, getTempFields(result))};
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CapPipe nullWithAddr (Bit#(64) addr);
|
||||||
|
let res = setAddress (nullCap, zeroExtend(addr), getTempFields(nullCap));
|
||||||
|
return tuple2(res, getTempFields(res));
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function almightyCap = tuple2(defaultCapFat, getTempFields(defaultCapFat));
|
||||||
|
|
||||||
|
function nullCap = tuple2(nullCap, getTempFields(nullCap));
|
||||||
|
|
||||||
|
endinstance
|
||||||
|
|
||||||
|
instance Cast#(CapMem, CapReg);
|
||||||
|
function CapReg cast (CapMem thin);
|
||||||
|
return unpackCap(thin);
|
||||||
|
endfunction
|
||||||
|
endinstance
|
||||||
|
|
||||||
|
instance Cast#(CapReg, CapMem);
|
||||||
|
function CapMem cast (CapReg fat);
|
||||||
|
return pack(packCap(fat));
|
||||||
|
endfunction
|
||||||
|
endinstance
|
||||||
|
|
||||||
|
instance Cast#(CapReg, CapPipe);
|
||||||
|
function CapPipe cast (CapReg thin);
|
||||||
|
return tuple2(thin, getTempFields(thin));
|
||||||
|
endfunction
|
||||||
|
endinstance
|
||||||
|
|
||||||
|
instance Cast#(CapPipe, CapReg);
|
||||||
|
function CapReg cast (CapPipe fat);
|
||||||
|
return tpl_1(fat);
|
||||||
|
endfunction
|
||||||
|
endinstance
|
||||||
|
|
||||||
|
instance Cast#(Bit#(129), CapPipe);
|
||||||
|
function cast(x);
|
||||||
|
CapReg fat = cast(x);
|
||||||
|
return tuple2(fat, getTempFields(fat));
|
||||||
|
endfunction
|
||||||
|
endinstance
|
||||||
|
|
||||||
endpackage
|
endpackage
|
||||||
13
CHERICap.bsv
13
CHERICap.bsv
@@ -129,7 +129,12 @@ typeclass CHERICap#(type t, numeric type ot, numeric type n)
|
|||||||
function Bit#(TAdd#(n, 1)) getLength (t cap);
|
function Bit#(TAdd#(n, 1)) getLength (t cap);
|
||||||
|
|
||||||
// Assertion that address is between base and top
|
// Assertion that address is between base and top
|
||||||
function Bool isInBounds (t cap, Bool inclusive);
|
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
|
// 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);
|
||||||
@@ -154,12 +159,12 @@ function Fmt showCHERICap(t cap) provisos (CHERICap#(t, ot, n));
|
|||||||
$format(" Length: 0x%0x", getLength(cap));
|
$format(" Length: 0x%0x", getLength(cap));
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
typeclass Cast #(type src, type dest);
|
typeclass Cast#(type src, type dest);
|
||||||
function dest cast (src x);
|
function dest cast (src x);
|
||||||
endtypeclass
|
endtypeclass
|
||||||
|
|
||||||
instance Cast #(t, t);
|
instance Cast#(t, t);
|
||||||
function t cast (t x) = x;
|
function cast = id;
|
||||||
endinstance
|
endinstance
|
||||||
|
|
||||||
endpackage
|
endpackage
|
||||||
|
|||||||
Reference in New Issue
Block a user