Skip to content

Commit a8d6b07

Browse files
committed
WIP: points-to-PCC indirect sentries
1 parent 650797e commit a8d6b07

File tree

3 files changed

+92
-1
lines changed

3 files changed

+92
-1
lines changed

src/cheri_cap_common.sail

+4
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,10 @@ function isCapSealed(cap) = signed(cap.otype) != otype_unsealed
416416
val hasReservedOType : Capability -> bool
417417
function hasReservedOType(cap) = unsigned(cap.otype) > cap_max_otype
418418

419+
function isCapSentryOrIsentry(cap) : Capability -> bool =
420+
let sotype = signed(cap.otype) in
421+
(sotype == otype_sentry) | (sotype == otype_isentry_pcc)
422+
419423
function sealCap(cap, otyp) : (Capability, bits(cap_otype_width)) -> Capability =
420424
{cap with otype=otyp}
421425

src/cheri_insts.sail

+87-1
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,7 @@ function clause execute (CBuildCap(cd, cs1, cs2)) = {
933933
RETIRE_FAIL
934934
} else {
935935
assert(exact, "CBuildCap: setCapBounds was not exact"); /* base and top came from cs2 originally so will be exact */
936-
let cd5 = if signed(cs2_val.otype) == otype_sentry then sealCap(cd4, to_bits(cap_otype_width, otype_sentry)) else cd4;
936+
let cd5 = if isCapSentryOrIsentry(cs2_val) then sealCap(cd4, cs2_val.otype) else cd4;
937937
C(cd) = cd5;
938938
RETIRE_SUCCESS
939939
}
@@ -1692,6 +1692,89 @@ function clause execute (CLoadTags(rd, cs1)) = {
16921692
}
16931693
}
16941694

1695+
/*
1696+
* Indirect sentries.
1697+
*
1698+
* At the risk of becoming CISC, the invocation instructions load, unseal, and
1699+
* transfer control. They depend on helpers above for most of those tasks.
1700+
*/
1701+
1702+
union clause ast = CSealIPCC : (regidx, regidx)
1703+
/*!
1704+
* Capability register *cd* is replaced with capability register *cs1* and
1705+
* sealed as an indirect, points-to-PCC sentry
1706+
*
1707+
* ## Exceptions
1708+
*
1709+
* An exception is raised if:
1710+
* - *cs1*.**tag** is not set.
1711+
* - *cs1* is sealed.
1712+
* - *cs1*.**perms** does not grant both **Permit_Load** and
1713+
* **Permit_Load_Capability**.
1714+
*/
1715+
function clause execute (CSealIPCC(cd, cs1)) = {
1716+
let cs1_val = C(cs1);
1717+
if not (cs1_val.tag) then {
1718+
handle_cheri_reg_exception(CapEx_TagViolation, cs1);
1719+
RETIRE_FAIL
1720+
} else if (isCapSealed(cs1_val)) then {
1721+
handle_cheri_reg_exception(CapEx_SealViolation, cs1);
1722+
RETIRE_FAIL
1723+
} else if not (cs1_val.permit_load) then {
1724+
handle_cheri_reg_exception(CapEx_PermitLoadViolation, cs1);
1725+
RETIRE_FAIL
1726+
} else if not (cs1_val.permit_load_cap) then {
1727+
handle_cheri_reg_exception(CapEx_PermitLoadCapViolation, cs1);
1728+
RETIRE_FAIL
1729+
} else {
1730+
C(cd) = sealCap(cs1_val, to_bits(cap_otype_width, otype_isentry_pcc));
1731+
RETIRE_SUCCESS
1732+
}
1733+
}
1734+
1735+
union clause ast = CJALR_IPCC : (regidx, regidx)
1736+
/*!
1737+
* Jump through an indirect, points-to-PCC sentry capability held in
1738+
* capability register cs, linking to cd.
1739+
*/
1740+
function clause execute (CJALR_IPCC(cd, cs)) = {
1741+
let cs_val = C(cs);
1742+
1743+
if not (cs_val.tag) then {
1744+
handle_cheri_reg_exception(CapEx_TagViolation, cs);
1745+
RETIRE_FAIL
1746+
} else if not (isCapSealed(cs_val)) |
1747+
signed(cs_val.otype) != otype_isentry_pcc then {
1748+
handle_cheri_reg_exception(CapEx_SealViolation, cs);
1749+
RETIRE_FAIL
1750+
} else {
1751+
let idc = unsealCap(cs_val);
1752+
let idcaddr = cs_val.address;
1753+
1754+
if not (idc.permit_load) | not (idc.permit_load_cap) then {
1755+
handle_cheri_reg_exception(CapEx_PermitLoadViolation, cs);
1756+
RETIRE_FAIL
1757+
} else if not(inCapBounds(idc, idcaddr, cap_size)) then {
1758+
handle_cheri_reg_exception(CapEx_LengthViolation, cs);
1759+
RETIRE_FAIL
1760+
} else if not(is_aligned_addr(idcaddr, cap_size)) then {
1761+
handle_mem_exception(idcaddr, E_Load_Addr_Align());
1762+
RETIRE_FAIL
1763+
} else {
1764+
match load_cap_via_cap(0b0 @ cs, cs_val, idcaddr) {
1765+
None() => RETIRE_FAIL,
1766+
Some(v) => match cjalr_worker(cd, cs, v, zeros()) {
1767+
RETIRE_FAIL => RETIRE_FAIL,
1768+
RETIRE_SUCCESS => {
1769+
C(31) = idc;
1770+
RETIRE_SUCCESS
1771+
}
1772+
}
1773+
}
1774+
}
1775+
}
1776+
}
1777+
16951778
/* avoid platform checks for reservation address misalignment */
16961779
function check_res_misaligned(vaddr : xlenbits, width : word_width) -> bool =
16971780
match width {
@@ -2419,6 +2502,9 @@ mapping clause encdec = JALR_PCC(rd, rs1) if (haveXcheri()) <-> 0b1111111 @ 0b
24192502

24202503
mapping clause encdec = CLoadTags(rd, cs1) if (haveXcheri()) <-> 0b1111111 @ 0b10010 @ cs1 @ 0b000 @ rd @ 0b1011011 if (haveXcheri())
24212504

2505+
mapping clause encdec = CSealIPCC(cd, cs1) if (haveXcheri()) <-> 0b1111111 @ 0b11000 @ cs1 @ 0b000 @ cd @ 0b1011011 if (haveXcheri())
2506+
mapping clause encdec = CJALR_IPCC(cd, cs1) if (haveXcheri()) <-> 0b1111111 @ 0b11001 @ cs1 @ 0b000 @ cd @ 0b1011011 if (haveXcheri())
2507+
24222508
mapping clause encdec = CRRL(rd, rs1) if (haveXcheri()) <-> 0b1111111 @ 0b01000 @ rs1 @ 0b000 @ rd @ 0b1011011 if (haveXcheri())
24232509
mapping clause encdec = CRAM(rd, rs1) if (haveXcheri()) <-> 0b1111111 @ 0b01001 @ rs1 @ 0b000 @ rd @ 0b1011011 if (haveXcheri())
24242510

src/cheri_types.sail

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
let reserved_otypes = 4
6464
let otype_unsealed = -1
6565
let otype_sentry = -2 /* Sealed erstwhile or prospective PCC */
66+
let otype_isentry_pcc = -3 /* Sealed erstwhile IDC pointing at PCC */
6667

6768
enum CPtrCmpOp = {
6869
CEQ,

0 commit comments

Comments
 (0)