@@ -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