]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
aarch64: Add GCS support to longjmp
authorSzabolcs Nagy <szabolcs.nagy@arm.com>
Thu, 23 Feb 2023 08:54:04 +0000 (08:54 +0000)
committerYury Khrustalev <yury.khrustalev@arm.com>
Thu, 10 Oct 2024 12:40:34 +0000 (13:40 +0100)
This implementations ensures that longjmp across different stacks
works: it scans for GCS cap token and switches GCS if necessary
then the target GCSPR is restored with a GCSPOPM loop once the
current GCSPR is on the same GCS.

This makes longjmp linear time in the number of jumped over stack
frames when GCS is enabled.

sysdeps/aarch64/__longjmp.S
sysdeps/aarch64/setjmp.S

index 7b6add751e6bd96bd08599d0ab3f65ffe572a768..d8670d8995828f8934a803700b0e6d69ef2e7eb8 100644 (file)
@@ -91,6 +91,36 @@ ENTRY (__longjmp)
        ldp     d12, d13, [x0, #JB_D12<<3]
        ldp     d14, d15, [x0, #JB_D14<<3]
 
+       /* GCS support.  */
+       mov     x16, 1
+       CHKFEAT_X16
+       tbnz    x16, 0, L(gcs_done)
+       MRS_GCSPR (x2)
+       ldr     x3, [x0, #JB_GCSPR]
+       mov     x4, x3
+       /* x2: GCSPR now.  x3, x4: target GCSPR.  x5, x6: tmp regs.  */
+L(gcs_scan):
+       cmp     x2, x4
+       b.eq    L(gcs_pop)
+       sub     x4, x4, 8
+       /* Check for a cap token.  */
+       ldr     x5, [x4]
+       and     x6, x4, 0xfffffffffffff000
+       orr     x6, x6, 1
+       cmp     x5, x6
+       b.ne    L(gcs_scan)
+L(gcs_switch):
+       add     x2, x4, 8
+       GCSSS1 (x4)
+       GCSSS2 (xzr)
+L(gcs_pop):
+       cmp     x2, x3
+       b.eq    L(gcs_done)
+       GCSPOPM (xzr)
+       add     x2, x2, 8
+       b       L(gcs_pop)
+L(gcs_done):
+
         /* Originally this was implemented with a series of
           .cfi_restore() directives.
 
index 43fdb1b2fb1b7b7883b335e2b1fec97a2bf5b8e0..f7ffccfabad86f931e8d5d01458944675c9506a9 100644 (file)
@@ -57,6 +57,16 @@ ENTRY (__sigsetjmp)
        stp     d10, d11, [x0, #JB_D10<<3]
        stp     d12, d13, [x0, #JB_D12<<3]
        stp     d14, d15, [x0, #JB_D14<<3]
+
+       /* GCS support.  */
+       mov     x16, 1
+       CHKFEAT_X16
+       tbnz    x16, 0, L(gcs_done)
+       MRS_GCSPR (x2)
+       add     x2, x2, 8 /* GCS state right after setjmp returns.  */
+       str     x2, [x0, #JB_GCSPR]
+L(gcs_done):
+
 #ifdef PTR_MANGLE
        mov     x4, sp
        PTR_MANGLE (5, 4, 3, 2)