diff options
author | Szabolcs Nagy <szabolcs.nagy@arm.com> | 2023-02-23 08:54:04 +0000 |
---|---|---|
committer | Yury Khrustalev <yury.khrustalev@arm.com> | 2025-01-20 09:22:41 +0000 |
commit | 5ff5e7836e97a2d87778936b29c9607c120251be (patch) | |
tree | 1f7c452d4706f49efdd14c6e07d0659c70b874d5 | |
parent | 13cbbb0cb29153bab099e040002e7cc78a0ceaaa (diff) | |
download | glibc-5ff5e7836e97a2d87778936b29c9607c120251be.zip glibc-5ff5e7836e97a2d87778936b29c9607c120251be.tar.gz glibc-5ff5e7836e97a2d87778936b29c9607c120251be.tar.bz2 |
aarch64: Add GCS support to longjmp
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.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
-rw-r--r-- | sysdeps/aarch64/__longjmp.S | 30 | ||||
-rw-r--r-- | sysdeps/aarch64/setjmp.S | 10 |
2 files changed, 40 insertions, 0 deletions
diff --git a/sysdeps/aarch64/__longjmp.S b/sysdeps/aarch64/__longjmp.S index 2ef0911..38efddb 100644 --- a/sysdeps/aarch64/__longjmp.S +++ b/sysdeps/aarch64/__longjmp.S @@ -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. diff --git a/sysdeps/aarch64/setjmp.S b/sysdeps/aarch64/setjmp.S index 4c968ae..b630ca0 100644 --- a/sysdeps/aarch64/setjmp.S +++ b/sysdeps/aarch64/setjmp.S @@ -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) |