@@ -933,7 +933,7 @@ function clause execute (CBuildCap(cd, cs1, cs2)) = {
933
933
RETIRE_FAIL
934
934
} else {
935
935
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;
937
937
C(cd) = cd5;
938
938
RETIRE_SUCCESS
939
939
}
@@ -1695,6 +1695,89 @@ function clause execute (CLoadTags(rd, cs1)) = {
1695
1695
}
1696
1696
}
1697
1697
1698
+ /*
1699
+ * Indirect sentries.
1700
+ *
1701
+ * At the risk of becoming CISC, the invocation instructions load, unseal, and
1702
+ * transfer control. They depend on helpers above for most of those tasks.
1703
+ */
1704
+
1705
+ union clause ast = CSealL : (regidx, regidx)
1706
+ /*!
1707
+ * Capability register *cd* is replaced with capability register *cs1* and
1708
+ * sealed as an indirect, points-to-PCC sentry
1709
+ *
1710
+ * ## Exceptions
1711
+ *
1712
+ * An exception is raised if:
1713
+ * - *cs1*.**tag** is not set.
1714
+ * - *cs1* is sealed.
1715
+ * - *cs1*.**perms** does not grant both **Permit_Load** and
1716
+ * **Permit_Load_Capability**.
1717
+ */
1718
+ function clause execute (CSealL(cd, cs1)) = {
1719
+ let cs1_val = C(cs1);
1720
+ if not (cs1_val.tag) then {
1721
+ handle_cheri_reg_exception(CapEx_TagViolation, cs1);
1722
+ RETIRE_FAIL
1723
+ } else if (isCapSealed(cs1_val)) then {
1724
+ handle_cheri_reg_exception(CapEx_SealViolation, cs1);
1725
+ RETIRE_FAIL
1726
+ } else if not (cs1_val.permit_load) then {
1727
+ handle_cheri_reg_exception(CapEx_PermitLoadViolation, cs1);
1728
+ RETIRE_FAIL
1729
+ } else if not (cs1_val.permit_load_cap) then {
1730
+ handle_cheri_reg_exception(CapEx_PermitLoadCapViolation, cs1);
1731
+ RETIRE_FAIL
1732
+ } else {
1733
+ C(cd) = sealCap(cs1_val, to_bits(cap_otype_width, otype_isentry_pcc));
1734
+ RETIRE_SUCCESS
1735
+ }
1736
+ }
1737
+
1738
+ union clause ast = CInvokeLAL : (regidx, regidx)
1739
+ /*!
1740
+ * Jump through an indirect, points-to-PCC sentry capability held in
1741
+ * capability register cs.
1742
+ */
1743
+ function clause execute (CInvokeLAL(cd, cs)) = {
1744
+ let cs_val = C(cs);
1745
+
1746
+ if not (cs_val.tag) then {
1747
+ handle_cheri_reg_exception(CapEx_TagViolation, cs);
1748
+ RETIRE_FAIL
1749
+ } else if not (isCapSealed(cs_val)) |
1750
+ signed(cs_val.otype) != otype_isentry_pcc then {
1751
+ handle_cheri_reg_exception(CapEx_SealViolation, cs);
1752
+ RETIRE_FAIL
1753
+ } else {
1754
+ let idc = unsealCap(cs_val);
1755
+ let idcaddr = cs_val.address;
1756
+
1757
+ if not (idc.permit_load) | not (idc.permit_load_cap) then {
1758
+ handle_cheri_reg_exception(CapEx_PermitLoadViolation, cs);
1759
+ RETIRE_FAIL
1760
+ } else if not(inCapBounds(idc, idcaddr, cap_size)) then {
1761
+ handle_cheri_reg_exception(CapEx_LengthViolation, cs);
1762
+ RETIRE_FAIL
1763
+ } else if not(is_aligned_addr(idcaddr, cap_size)) then {
1764
+ handle_mem_exception(idcaddr, E_Load_Addr_Align());
1765
+ RETIRE_FAIL
1766
+ } else {
1767
+ match load_cap_via_cap(0b0 @ cs, cs_val, idcaddr) {
1768
+ None() => RETIRE_FAIL,
1769
+ Some(v) => match cjalr_worker(cd, cs, v, zeros()) {
1770
+ RETIRE_FAIL => RETIRE_FAIL,
1771
+ RETIRE_SUCCESS => {
1772
+ C(31) = idc;
1773
+ RETIRE_SUCCESS
1774
+ }
1775
+ }
1776
+ }
1777
+ }
1778
+ }
1779
+ }
1780
+
1698
1781
/* avoid platform checks for reservation address misalignment */
1699
1782
function check_res_misaligned(vaddr : xlenbits, width : word_width) -> bool =
1700
1783
match width {
@@ -2376,6 +2459,9 @@ mapping clause encdec = JALR_PCC(rd, rs1) if (haveXcheri()) <-> 0b1111111 @ 0b
2376
2459
2377
2460
mapping clause encdec = CLoadTags(rd, cs1) if (haveXcheri()) <-> 0b1111111 @ 0b10010 @ cs1 @ 0b000 @ rd @ 0b1011011 if (haveXcheri())
2378
2461
2462
+ mapping clause encdec = CSealL(cd, cs1) if (haveXcheri()) <-> 0b1111111 @ 0b11000 @ cs1 @ 0b000 @ cd @ 0b1011011 if (haveXcheri())
2463
+ mapping clause encdec = CInvokeLAL(cd, cs1) if (haveXcheri()) <-> 0b1111111 @ 0b11001 @ cs1 @ 0b000 @ cd @ 0b1011011 if (haveXcheri())
2464
+
2379
2465
mapping clause encdec = CRRL(rd, rs1) if (haveXcheri()) <-> 0b1111111 @ 0b01000 @ rs1 @ 0b000 @ rd @ 0b1011011 if (haveXcheri())
2380
2466
mapping clause encdec = CRAM(rd, rs1) if (haveXcheri()) <-> 0b1111111 @ 0b01001 @ rs1 @ 0b000 @ rd @ 0b1011011 if (haveXcheri())
2381
2467
@@ -2403,6 +2489,9 @@ mapping clause assembly = JALR_PCC(rd, rs1) <-> "jalr.pcc" ^ spc() ^ reg_
2403
2489
2404
2490
mapping clause assembly = CLoadTags(rd, cs1) <-> "cloadtags" ^ spc() ^ reg_name(rd) ^ sep() ^ "(" ^ cap_reg_name(cs1) ^ ")"
2405
2491
2492
+ mapping clause assembly = CSealL(rd, cs1) <-> "cseall" ^ spc() ^ reg_name(rd) ^ sep() ^ "(" ^ cap_reg_name(cs1) ^ ")"
2493
+ mapping clause assembly = CInvokeLAL(rd, cs1) <-> "cinvokelal" ^ spc() ^ reg_name(rd) ^ sep() ^ "(" ^ cap_reg_name(cs1) ^ ")"
2494
+
2406
2495
mapping clause assembly = CRRL(rd, rs1) <-> "crrl" ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1)
2407
2496
mapping clause assembly = CRAM(rd, rs1) <-> "cram" ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1)
2408
2497
0 commit comments