From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1944) id 2D54D385E44E; Wed, 14 Feb 2024 15:06:48 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2D54D385E44E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1707923208; bh=zCqzNR8BojdN6eokhgxANiR2BJ/atM2oZFfNHg04N3A=; h=From:To:Subject:Date:From; b=W5PyKvGwY2r1vheAWuFZFzSrrVg75r6VsFaucY0azcZDP6C9IH0Qtq9RMlxezjZHp B6oH7S2aAFnH4ABP6XUnlFzQu2zK2dhA+EuEGERvv7hOQzaGeNUafADtrQjiINVaKi b6xJzdkrHqk8/QeGgegwaR68SKyZZ2zvsK4Ze4ws= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Szabolcs Nagy To: glibc-cvs@sourceware.org Subject: [glibc/arm/gcs] aarch64: Add GCS support for setcontext X-Act-Checkin: glibc X-Git-Author: Szabolcs Nagy X-Git-Refname: refs/heads/arm/gcs X-Git-Oldrev: 868c129b90a52f7c30b8a560dc580f851db4b6fc X-Git-Newrev: 996a31b2a3313039b5c66d7de15577e5bc145278 Message-Id: <20240214150648.2D54D385E44E@sourceware.org> Date: Wed, 14 Feb 2024 15:06:48 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=996a31b2a3313039b5c66d7de15577e5bc145278 commit 996a31b2a3313039b5c66d7de15577e5bc145278 Author: Szabolcs Nagy Date: Fri Feb 24 16:29:32 2023 +0000 aarch64: Add GCS support for setcontext Userspace ucontext needs to store GCSPR, it does not have to be compatible with the kernel ucontext. For now we use the linux struct gcs_context layout but only use the gcspr field from it. Similar implementation to the longjmp code, supports switching GCS if the target GCS is capped, and unwinding a continous GCS to a previous state. Diff: --- sysdeps/unix/sysv/linux/aarch64/getcontext.S | 17 +++++++++- sysdeps/unix/sysv/linux/aarch64/setcontext.S | 39 ++++++++++++++++++++++ sysdeps/unix/sysv/linux/aarch64/swapcontext.S | 32 +++++++++++++----- .../unix/sysv/linux/aarch64/ucontext-internal.h | 5 +++ 4 files changed, 84 insertions(+), 9 deletions(-) diff --git a/sysdeps/unix/sysv/linux/aarch64/getcontext.S b/sysdeps/unix/sysv/linux/aarch64/getcontext.S index e5b69c9a82..30e2b39399 100644 --- a/sysdeps/unix/sysv/linux/aarch64/getcontext.S +++ b/sysdeps/unix/sysv/linux/aarch64/getcontext.S @@ -83,9 +83,24 @@ ENTRY(__getcontext) mrs x4, fpcr str w4, [x3, oFPCR - oFPSR] - /* Write the termination context extension header. */ add x2, x2, #FPSIMD_CONTEXT_SIZE + /* Save the GCSPR. */ + mov x16, 1 + CHKFEAT_X16 + tbnz x16, 0, L(gcs_done) + mov w3, #(GCS_MAGIC & 0xffff) + movk w3, #(GCS_MAGIC >> 16), lsl #16 + str w3, [x2, #oHEAD + oMAGIC] + mov w3, #GCS_CONTEXT_SIZE + str w3, [x2, #oHEAD + oSIZE] + MRS_GCSPR (x4) + add x4, x4, 8 /* GCS state right after getcontext returns. */ + str x4, [x2, #oGCSPR] + add x2, x2, #GCS_CONTEXT_SIZE +L(gcs_done): + + /* Write the termination context extension header. */ str wzr, [x2, #oHEAD + oMAGIC] str wzr, [x2, #oHEAD + oSIZE] diff --git a/sysdeps/unix/sysv/linux/aarch64/setcontext.S b/sysdeps/unix/sysv/linux/aarch64/setcontext.S index ba659438c5..c08e83ee60 100644 --- a/sysdeps/unix/sysv/linux/aarch64/setcontext.S +++ b/sysdeps/unix/sysv/linux/aarch64/setcontext.S @@ -130,6 +130,45 @@ ENTRY (__setcontext) ldr w4, [x3, oFPCR - oFPSR] msr fpcr, x4 + /* Restore the GCS. */ + mov x16, 1 + CHKFEAT_X16 + tbnz x16, 0, L(gcs_done) + /* Get target GCS from GCS context. */ + ldr w1, [x2, #oHEAD + oSIZE] + add x2, x2, x1 + mov w3, #(GCS_MAGIC & 0xffff) + movk w3, #(GCS_MAGIC >> 16), lsl #16 + ldr w1, [x2, #oHEAD + oMAGIC] + cmp w1, w3 + b.ne L(gcs_done) + ldr x3, [x2, #oGCSPR] + MRS_GCSPR (x2) + 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.eq L(gcs_switch) + b 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): + 2: ldr x16, [x0, oPC] /* Restore arg registers. */ diff --git a/sysdeps/unix/sysv/linux/aarch64/swapcontext.S b/sysdeps/unix/sysv/linux/aarch64/swapcontext.S index f049140d35..45b1277c74 100644 --- a/sysdeps/unix/sysv/linux/aarch64/swapcontext.S +++ b/sysdeps/unix/sysv/linux/aarch64/swapcontext.S @@ -32,8 +32,15 @@ ENTRY(__swapcontext) And set up x1 to become the return address of the caller, so we can return there with a normal RET instead of an indirect jump. */ stp xzr, x30, [x0, oX0 + 0 * SZREG] + + /* With GCS, swapcontext calls are followed by BTI J, otherwise + we have to be compatible with old BTI enabled binaries. */ + mov x16, 1 + CHKFEAT_X16 + tbz x16, 0, L(skip_x30_redirect) /* Arrange the oucp context to return to 2f. */ adr x30, 2f +L(skip_x30_redirect): stp x18, x19, [x0, oX0 + 18 * SZREG] stp x20, x21, [x0, oX0 + 20 * SZREG] @@ -72,14 +79,27 @@ ENTRY(__swapcontext) mrs x4, fpcr str w4, [x3, #oFPCR - oFPSR] - /* Write the termination context extension header. */ add x2, x2, #FPSIMD_CONTEXT_SIZE + /* Save the GCSPR. */ + tbnz x16, 0, L(gcs_done) + mov w3, #(GCS_MAGIC & 0xffff) + movk w3, #(GCS_MAGIC >> 16), lsl #16 + str w3, [x2, #oHEAD + oMAGIC] + mov w3, #GCS_CONTEXT_SIZE + str w3, [x2, #oHEAD + oSIZE] + MRS_GCSPR (x4) + add x4, x4, 8 /* GCSPR of the caller. */ + str x4, [x2, #oGCSPR] + add x2, x2, #GCS_CONTEXT_SIZE +L(gcs_done): + + /* Write the termination context extension header. */ str wzr, [x2, #oHEAD + oMAGIC] str wzr, [x2, #oHEAD + oSIZE] /* Preserve ucp. */ - mov x21, x1 + mov x9, x1 /* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask, _NSIG8) */ @@ -93,12 +113,8 @@ ENTRY(__swapcontext) svc 0 cbnz x0, 1f - mov x22, x30 - mov x0, x21 - bl JUMPTARGET (__setcontext) - mov x30, x22 - RET - + mov x0, x9 + b JUMPTARGET (__setcontext) 1: b C_SYMBOL_NAME(__syscall_error) 2: diff --git a/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h b/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h index 096d5fb7c7..84f5365c0e 100644 --- a/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h +++ b/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h @@ -43,3 +43,8 @@ #define oX21 (oX0 + 21*8) #define oFP (oX0 + 29*8) #define oLR (oX0 + 30*8) + +/* Use kernel layout for saving GCSPR in ucontext. */ +#define GCS_MAGIC 0x47435300 +#define GCS_CONTEXT_SIZE 32 +#define oGCSPR 8