@@ -887,8 +887,8 @@ function sealCapIfAmbient(cap, otyp) : (Capability, bits(cap_otype_width)) -> Am
887887 if cap . permit_execute
888888 then seal_ok
889889 else AmbientSeal_CapEx (CapEx_PermitExecuteViolation )
890- } else if sotype == otype_isentry_load then {
891- // CSealL requires PermitLoad and PermitLoadCap
890+ } else if sotype == otype_isentry_load | sotype == otype_isentry_load_pair then {
891+ // CSealL and CSealLP require PermitLoad and PermitLoadCap
892892 if cap . permit_load then {
893893 if cap . permit_load_cap
894894 then seal_ok
@@ -1809,6 +1809,89 @@ function clause execute (CInvokeLAL(cd, cs)) = {
18091809 }
18101810}
18111811
1812+ union clause ast = CInvokeLPAL : (regidx , regidx )
1813+ /*!
1814+ * Jump through an indirect, points-to-pair sentry capability held in
1815+ * capability register cs.
1816+ */
1817+ function clause execute (CInvokeLAL (cd , cs )) = {
1818+ let cs_val = C (cs );
1819+
1820+ if not (cs_val . tag ) then {
1821+ handle_cheri_reg_exception (CapEx_TagViolation , cs );
1822+ RETIRE_FAIL
1823+ } else if not (isCapSealed (cs_val )) |
1824+ signed (cs_val . otype ) != otype_isentry_load_pair then {
1825+ handle_cheri_reg_exception (CapEx_SealViolation , cs );
1826+ RETIRE_FAIL
1827+ } else {
1828+ let pair = unsealCap (cs_val );
1829+ let pairaddr = cs_val . address ;
1830+
1831+ if not (pair . permit_load ) | not (pair . permit_load_cap ) then {
1832+ handle_cheri_reg_exception (CapEx_PermitLoadViolation , cs );
1833+ RETIRE_FAIL
1834+ } else if not (inCapBounds (pair , pairaddr , 2 * cap_size )) then {
1835+ handle_cheri_reg_exception (CapEx_LengthViolation , cs );
1836+ RETIRE_FAIL
1837+ } else if not (is_aligned_addr (pairaddr , cap_size )) then {
1838+ handle_mem_exception (pairaddr , E_Load_Addr_Align ());
1839+ RETIRE_FAIL
1840+ } else {
1841+ match load_cap_via_cap (0b0 @ cs , cs_val , pairaddr , false , false , PrivDefault ()) {
1842+ None () => RETIRE_FAIL ,
1843+ Some (_, npcc ) => {
1844+ match load_cap_via_cap (0b0 @ cs , cs_val , pairaddr + cap_size , false , false , PrivDefault ()) {
1845+ None () => RETIRE_FAIL ,
1846+ Some (_, nidc ) => match cjalr_worker (cd , cs , npcc , zeros ()) {
1847+ RETIRE_FAIL => RETIRE_FAIL ,
1848+ RETIRE_SUCCESS => {
1849+ C (31 ) = nidc ;
1850+ RETIRE_SUCCESS
1851+ }
1852+ }
1853+ }
1854+ }
1855+ }
1856+ }
1857+ }
1858+ }
1859+
1860+
1861+ union clause ast = CSealLP : (regidx , regidx )
1862+ /*!
1863+ * Capability register *cd* is replaced with capability register *cs1* and
1864+ * sealed as an indirect, points-to-pair sentry
1865+ *
1866+ * ## Exceptions
1867+ *
1868+ * An exception is raised if:
1869+ * - *cs1*.**tag** is not set.
1870+ * - *cs1* is sealed.
1871+ * - *cs1*.**perms** does not grant both **Permit_Load** and
1872+ * **Permit_Load_Capability**.
1873+ */
1874+ function clause execute (CSealLP (cd , cs1 )) = {
1875+ let cs1_val = C (cs1 );
1876+ if not (cs1_val . tag ) then {
1877+ handle_cheri_reg_exception (CapEx_TagViolation , cs1 );
1878+ RETIRE_FAIL
1879+ } else if (isCapSealed (cs1_val )) then {
1880+ handle_cheri_reg_exception (CapEx_SealViolation , cs1 );
1881+ RETIRE_FAIL
1882+ } else if not (cs1_val . permit_load ) then {
1883+ handle_cheri_reg_exception (CapEx_PermitLoadViolation , cs1 );
1884+ RETIRE_FAIL
1885+ } else if not (cs1_val . permit_load_cap ) then {
1886+ handle_cheri_reg_exception (CapEx_PermitLoadCapViolation , cs1 );
1887+ RETIRE_FAIL
1888+ } else {
1889+ C (cd ) = sealCap (cs1_val , to_bits (cap_otype_width , otype_isentry_load_pair ));
1890+ RETIRE_SUCCESS
1891+ }
1892+ }
1893+
1894+
18121895/* avoid platform checks for reservation address misalignment */
18131896function check_res_misaligned (vaddr : xlenbits , width : word_width ) -> bool =
18141897 match width {
0 commit comments