From patchwork Wed Oct 23 08:39:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yury Khrustalev X-Patchwork-Id: 2000849 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XYMxR6h24z1xwy for ; Wed, 23 Oct 2024 19:42:35 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 167B83858C48 for ; Wed, 23 Oct 2024 08:42:34 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by sourceware.org (Postfix) with ESMTP id 1E8013858C48 for ; Wed, 23 Oct 2024 08:42:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1E8013858C48 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=arm.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 1E8013858C48 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729672930; cv=none; b=ObKQhJhyrRukqU9ZMYMnSN5F0U4oaOgA2IlGTVrnvOaakuQb8WQTSOTKol41wiYKT96n56tU70Q37nO/7teItkk8NUyAzKov4BWK/w0IjExAHfjUCHNuKLWRhU4IIaFoWcXjJUNQDOTdWsqLuVZDO5Te/ApiQ+3FPYuCTIzVaMs= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729672930; c=relaxed/simple; bh=sSiJ2As3jnFiz+mw19mes0h5j+xMWP2O2uyo4+3NoDs=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=EsMhGVs5WYB8Cr/t3DtDLitaDMU3jngV19tup5/+nDSH7Gl1Jg1agWOxCq/VO9ErXjTzIB1eHdDwUedXcjlrsdthu6cf8eBnpQg8z0MY8x2r1fm7SvYGs2cjPu51/2nwVIcWfYip2MfkSTs+AxyswUdAzFJLZvlYFS8fwaQre2g= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 972931575; Wed, 23 Oct 2024 01:42:34 -0700 (PDT) Received: from udebian.localdomain (unknown [10.1.39.30]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 3E54C3F528; Wed, 23 Oct 2024 01:42:04 -0700 (PDT) From: Yury Khrustalev To: libc-alpha@sourceware.org Cc: fweimer@redhat.com, adhemerval.zanella@linaro.org, codonell@redhat.com, nsz@gcc.gnu.org Subject: [PATCH v3 07/23] aarch64: Add GCS support for setcontext Date: Wed, 23 Oct 2024 09:39:04 +0100 Message-Id: <20241023083920.466015-8-yury.khrustalev@arm.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241023083920.466015-1-yury.khrustalev@arm.com> References: <20241023083920.466015-1-yury.khrustalev@arm.com> MIME-Version: 1.0 X-Spam-Status: No, score=-12.2 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, KAM_LAZY_DOMAIN_SECURITY, KAM_STOCKGEN, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org From: Szabolcs Nagy 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. --- sysdeps/unix/sysv/linux/aarch64/getcontext.S | 17 ++++++++- sysdeps/unix/sysv/linux/aarch64/setcontext.S | 38 +++++++++++++++++++ sysdeps/unix/sysv/linux/aarch64/swapcontext.S | 32 ++++++++++++---- .../sysv/linux/aarch64/ucontext-internal.h | 5 +++ 4 files changed, 83 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..bdfd4580ec 100644 --- a/sysdeps/unix/sysv/linux/aarch64/setcontext.S +++ b/sysdeps/unix/sysv/linux/aarch64/setcontext.S @@ -130,6 +130,44 @@ 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.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): + 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