From patchwork Wed Jan 3 17:14:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergey Bugaev X-Patchwork-Id: 1882032 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=a9/SX2X5; dkim-atps=neutral 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 4T4xLV3xbJz1ydb for ; Thu, 4 Jan 2024 04:20:18 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 85573386180E for ; Wed, 3 Jan 2024 17:20:16 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-lf1-x133.google.com (mail-lf1-x133.google.com [IPv6:2a00:1450:4864:20::133]) by sourceware.org (Postfix) with ESMTPS id D1980385803F for ; Wed, 3 Jan 2024 17:15:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D1980385803F Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D1980385803F Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::133 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1704302127; cv=none; b=q7LHoZG/cjOin06xAR/iSl4KlP3iE5cTHBX2IyyVNS8ae6ip7cQCFc2y06koneAKtbplJfDxrZdL4eOjIrk2ykVzBDTHeymLkmllCU9lixJ+RPuUuukcQB/dBXAmnlzsIHDgXhHCXxEgzTWjcayCdf3QRLIQlg+ZeCYu1rWPpKE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1704302127; c=relaxed/simple; bh=JDV8XZBeyCt8RZP1KhPnneI6cHdaYK4RtrAHBm69m/Q=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=guSa5q0xwgOwMT7AmoKwDjHWlA3HQolpXcdRD++vkbyvTHSyIDGfqY7eS2faISNTyLlSDYVRBsyc0dvIITG8UwxkTHzPP2JEo8jBZBdJV/C4U+vdhvy/DsiYJ4HRHiCpEGcxnVyZF/1QcTjuDhTCKk1K3pJc7paXyLpLlKi9ssY= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-lf1-x133.google.com with SMTP id 2adb3069b0e04-50e80d40a41so8573742e87.1 for ; Wed, 03 Jan 2024 09:15:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1704302121; x=1704906921; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=oXrZ0jDGnrz18x3OaYtYtBj+c/wIyj9qA9s9Mj5ysa0=; b=a9/SX2X5QjxlIYpwkQJ8VO0GPbACdFZgNAvzNLszFZf0mRKlvCmwhJaXpNzx6adXXn YQYI6GMoW1vCegBjzrKitqdRzSlphsNRllOot84/HKy+1Qmx/drL7uVD9Nn8ne6uSUEz KNnjIc2Jct51DnAGKjbJopKMXaClNWBWN/JHTJa2f1SpMDYsWtZxQ/IoRDhoY7L4ne2t Pr+H5smyE8ndMB6xSS7ixpDtFJXolLt6Or9yqckQxjZ5uEkgHGI5M0VDiVQ3de2VJGd5 +eofvBxHMyzV+U7mjZwlSqBRBJdcHRx4k1YfPrbFOJV6+86pluzeiRPhH29sJ0KK8UVA z+GQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704302121; x=1704906921; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=oXrZ0jDGnrz18x3OaYtYtBj+c/wIyj9qA9s9Mj5ysa0=; b=TQS/CZdRE2QuEtZawxJE+SktN0sygZyAMGQnV6D5Dckh3TiPW2/hWkBDnMy7nT3fQQ jSqO8zm6Im1LfVOzdQIggPEPzRcpquISCvykHfw1Onde22kuRjqi1zuMgpOM/bBG+f+n xeY3w/x3b4JQAR69rY7HeO5HlRCV6juOA0IHZaZ9VmsL97x7kjshUWHDngose+OzrSTH jHq2eQWqboe7G4aL6tXo7f5Gwc1rGQ7q1reQHG42cwc7q+eVc/GG3cERn1mVwrN1duZ5 tsFlY2rcvwJ+H4dY22CZ7QSgbyZ0f6Wz/u4UAIldkOlZAZ5MIj0NCIGeHfuAbQBek7Ym qAHw== X-Gm-Message-State: AOJu0YyjPn/UKEULLW1jlpYBgJfleCiMZMpNHGVUl35sNIoemPSMkf33 fs4HkMj8r8XMrJtsj4Ttiu/plb2j2ec= X-Google-Smtp-Source: AGHT+IEHwFCMAWB4etDm+36cSAhpeUN9mQk2djDEuem7dpM/LPpxcrUpGWU52mH7vbtZSjGR/zVtJA== X-Received: by 2002:ac2:5f55:0:b0:50e:758f:b2ce with SMTP id 21-20020ac25f55000000b0050e758fb2cemr7194959lfz.52.1704302120754; Wed, 03 Jan 2024 09:15:20 -0800 (PST) Received: from surface-pro-6.. ([2a00:1370:818c:b32f:ebdc:fd0:376b:8006]) by smtp.gmail.com with ESMTPSA id y23-20020a196417000000b0050e6d84d177sm3546068lfb.279.2024.01.03.09.15.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jan 2024 09:15:20 -0800 (PST) From: Sergey Bugaev To: libc-alpha@sourceware.org, bug-hurd@gnu.org Subject: [RFC PATCH 17/23] hurd: Implement TLS on AArch64 Date: Wed, 3 Jan 2024 20:14:50 +0300 Message-ID: <20240103171502.1358371-18-bugaevc@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240103171502.1358371-1-bugaevc@gmail.com> References: <20240103171502.1358371-1-bugaevc@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-11.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_NUMSUBJECT, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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 This is using TLS_DTV_AT_TP, aka "Variant I" layout. tpidr_el0, which is both readable and writable from userspace, is used as the thread pointer. We store our Hurd-specific data (sigstate and reply port) *before* the TCB head, in a tcbprehead_t structure. This tcbprehead_t structure is also what THREAD_SELF, THREAD_GETMEM, and THREAD_SETMEM macros access. Signed-off-by: Sergey Bugaev --- .../mach/hurd/aarch64/dl-tls-initialized.c | 19 ++ sysdeps/mach/hurd/aarch64/tls.h | 206 ++++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 sysdeps/mach/hurd/aarch64/dl-tls-initialized.c create mode 100644 sysdeps/mach/hurd/aarch64/tls.h diff --git a/sysdeps/mach/hurd/aarch64/dl-tls-initialized.c b/sysdeps/mach/hurd/aarch64/dl-tls-initialized.c new file mode 100644 index 00000000..65080099 --- /dev/null +++ b/sysdeps/mach/hurd/aarch64/dl-tls-initialized.c @@ -0,0 +1,19 @@ +/* Determine whether TLS is initialized, for aarch64/Hurd. + Copyright (C) 1995-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* Nothing here, it's all handled in tls.h */ diff --git a/sysdeps/mach/hurd/aarch64/tls.h b/sysdeps/mach/hurd/aarch64/tls.h new file mode 100644 index 00000000..69dfa9aa --- /dev/null +++ b/sysdeps/mach/hurd/aarch64/tls.h @@ -0,0 +1,206 @@ +/* Copyright (C) 2005-2024 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _AARCH64_TLS_H +#define _AARCH64_TLS_H 1 + +/* Some things really need not be machine-dependent. */ +#include + +#include + +#ifndef __ASSEMBLER__ +# include +# include +# include +# include +# include +# include +# include +#endif /* __ASSEMBLER__ */ + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +# include + +/* The TP points to the start of the thread blocks. */ +# define TLS_DTV_AT_TP 1 +# define TLS_TCB_AT_TP 0 + +typedef struct +{ + /* Used by the exception handling implementation in the dynamic loader. */ + struct rtld_catch *rtld_catch; + + struct hurd_sigstate *_hurd_sigstate; + mach_port_t reply_port; /* This thread's reply port. */ + + int gscope_flag; +} tcbprehead_t; + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (tcbprehead_t) + +# define TCB_ALIGNMENT 64 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + (THREAD_DTV() = (dtv)) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) __builtin_thread_pointer ())->dtv) + +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF \ + ((tcbprehead_t *)__builtin_thread_pointer () - 1) + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) \ + ((descr)->member) + +/* Write member of the thread descriptor directly. */ +# define THREAD_SETMEM(descr, member, value) \ + ((descr)->member = (value)) + +/* Return the TCB address of a thread given its state. + Note: this is expensive. */ +static inline tcbprehead_t * __attribute__ ((unused)) +THREAD_TCB (thread_t thread, + struct machine_thread_all_state *all_state) +{ + int ok; + const struct aarch64_thread_state *state; + tcbhead_t *tcb; + + ok = machine_get_basic_state (thread, all_state); + assert (ok); + state = &((struct machine_thread_all_state *) all_state)->basic; + tcb = (tcbhead_t *) state->tpidr_el0; + return (tcbprehead_t *) tcb - 1; +} + +/* From hurd.h, reproduced here to avoid a circular include. */ +extern thread_t __hurd_thread_self (void); +libc_hidden_proto (__hurd_thread_self); + +/* Set up TLS in the new thread of a fork child, copying from the original. */ +static inline kern_return_t __attribute__ ((unused)) +_hurd_tls_fork (thread_t child, thread_t orig, + struct aarch64_thread_state *state) +{ + error_t err; + struct aarch64_thread_state orig_state; + mach_msg_type_number_t state_count = AARCH64_THREAD_STATE_COUNT; + + if (orig != __hurd_thread_self ()) + { + err = __thread_get_state (orig, AARCH64_THREAD_STATE, + (thread_state_t) &orig_state, + &state_count); + if (err) + return err; + assert (state_count == AARCH64_THREAD_STATE_COUNT); + state->tpidr_el0 = orig_state.tpidr_el0; + } + else + state->tpidr_el0 = (uintptr_t) __builtin_thread_pointer (); + return 0; +} + +static inline kern_return_t __attribute__ ((unused)) +_hurd_tls_new (thread_t child, tcbhead_t *tcb) +{ + error_t err; + struct aarch64_thread_state state; + mach_msg_type_number_t state_count = AARCH64_THREAD_STATE; + + err = __thread_get_state (child, AARCH64_THREAD_STATE, + (thread_state_t) &state, + &state_count); + if (err) + return err; + assert (state_count == AARCH64_THREAD_STATE_COUNT); + + state.tpidr_el0 = (uintptr_t) tcb; + + return __thread_set_state (child, AARCH64_THREAD_STATE, + (thread_state_t) &state, + state_count); +} + +# if !defined (SHARED) || IS_IN (rtld) +# define __LIBC_NO_TLS() __builtin_expect (!__builtin_thread_pointer (), 0) + +static inline bool __attribute__ ((unused)) +_hurd_tls_init (tcbhead_t *tcb, bool full) +{ + extern mach_port_t __hurd_reply_port0; + + if (full) + /* Take over the reply port we've been using. */ + (((tcbprehead_t *) tcb) - 1)->reply_port = __hurd_reply_port0; + + __asm __volatile ("msr tpidr_el0, %0" : : "r" (tcb)); + if (full) + /* This port is now owned by the TCB. */ + __hurd_reply_port0 = MACH_PORT_NULL; + return true; +} + +# define TLS_INIT_TP(descr) _hurd_tls_init ((tcbhead_t *) (descr), 1) +# else /* defined (SHARED) && !IS_IN (rtld) */ +# define __LIBC_NO_TLS() 0 +# endif + +/* Global scope switch support. */ +# define THREAD_GSCOPE_FLAG_UNUSED 0 +# define THREAD_GSCOPE_FLAG_USED 1 +# define THREAD_GSCOPE_FLAG_WAIT 2 + +# define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) + +# define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __flag \ + = atomic_exchange_release (&THREAD_SELF->gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__flag == THREAD_GSCOPE_FLAG_WAIT) \ + lll_wake (THREAD_SELF->gscope_flag, LLL_PRIVATE); \ + } \ + while (0) + +# endif /* __ASSEMBLER__ */ + +#endif /* tls.h */