From patchwork Sat Mar 23 17:32:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergey Bugaev X-Patchwork-Id: 87591 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A83653858285 for ; Sat, 23 Mar 2024 17:39:29 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-lj1-x22c.google.com (mail-lj1-x22c.google.com [IPv6:2a00:1450:4864:20::22c]) by sourceware.org (Postfix) with ESMTPS id 6EC3A3858C52 for ; Sat, 23 Mar 2024 17:35:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 6EC3A3858C52 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 6EC3A3858C52 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::22c ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711215331; cv=none; b=JvBWwHvjy+9IMgPI1jhGDbt23w/SjqXARuVR4AZPYcrP4RN1TLnimidZTQZwKRt0F334xZWF8BB2rW3QwGQwCR+ncruS33bMvzm+rQS7cPTuVpsXQX1Z7wZtI/dhfgRnuqeg7c/YVhRSx9ZvC04XSV4HYitE839W3n/teL+rI5o= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711215331; c=relaxed/simple; bh=IT0ONfgfzH/h4ISmxbZZXV20NXo3bKwuf0TDu5X1cyc=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=nr55+1ZJjMIC1rZsoWjcOhKgvpSQLVKU5Any7fnp5ydTljcO/LwKz0LzE7nPEatDRlTd2BzAuQVL+0qZlB/LBVd3beQ3ipYQL20jbKED3eyPDXfa0Lpns3/heuYEdCt8JRI3c69UQ4RJcwltgKk9G1FC/k+qTVdP01eBFHn+uXQ= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-lj1-x22c.google.com with SMTP id 38308e7fff4ca-2d52e65d4a8so42680461fa.0 for ; Sat, 23 Mar 2024 10:35:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711215326; x=1711820126; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=a9l3YZR5YpgFqq8POIxegvf33p5MInnlEiLYkSCHsDQ=; b=Ifl9KiW9xtwsBoUF94BAbKguYGyPT0sHL6GUs+M71cmvys52Tp0J56kwJpcaN5iq7r oJy0X09mcritoxDcqqfebtOhRw1euV+bwy5n/jIdKjhNcSm1+UlCET373gktl6yqlmDu RP0nhTJ7Ub6ykOZg5kBWrx4T4qM6Xm9bttTXi3DAAEZtrTZSMV1VRKOs+QIkKUSZXC8Z xyJUgP6gkNsIKdBpR4rFt9s+bbpV71lAJyB+mlod/eu5vnuT/3AU/jA91FNKrjgVuDLg IwzpQZ4WiAKeuMGwJYPZtqY5KP8me73o6W8sTfr82a2VUe7zUOHvnSruq2hNilrYKpgM 7tKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711215326; x=1711820126; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=a9l3YZR5YpgFqq8POIxegvf33p5MInnlEiLYkSCHsDQ=; b=aO+pouOy1XeiEJtGwTy5Ue6bZYkkePtOZkqZO1h9Xz2Cx8Yh9RLyDim14IVp7u0GN7 joF60ZKfV1eOAbB0y91suB0d4z6hkbvMlPdKqE3YTlcJPfccP+7tgRek0PZnfWVNvlVh x98nlbapFmF2wNlfWP/M+UBuS2heck4CUUPynC5R71bxN94nXjmHuJrYEUWvmCr5V0VM 2/YIZ+QEZanFkI7+MG/yEcic2MMxO59S/AgxAtnrzkhDwq6/eHlUEL53wH6kHRnRj0M7 lgTd3l539xiviSDjKiO7aSZqVe+E8SG1kyIxEOSULvASpawNCoddzFtWAx0/wUyizFck 3K5Q== X-Gm-Message-State: AOJu0Yxm8YsHBjoXdx702LVhP/kK6s2VfUOwoGoY9JWDqyNERaZ7giN2 sxJ+18Sta6rPPNI5dSUCMgQfwg5nKfueRKDlNH4hQv1j+V23dLhe5gOjplzp X-Google-Smtp-Source: AGHT+IGCACqy8W7CAQ9QkjE6Gc8WTvS5JNeZQ7sTDu32JyqIxX4WWT6rfxUrV4wyWbB4XsziVBaKgA== X-Received: by 2002:a19:6917:0:b0:513:5dc3:9ebb with SMTP id e23-20020a196917000000b005135dc39ebbmr1710919lfc.4.1711215325566; Sat, 23 Mar 2024 10:35:25 -0700 (PDT) Received: from surface-pro-6.. (79-139-171-253.dynamic.spd-mgts.ru. [79.139.171.253]) by smtp.gmail.com with ESMTPSA id g20-20020ac25394000000b00513973dee6fsm361290lfh.150.2024.03.23.10.35.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 23 Mar 2024 10:35:25 -0700 (PDT) From: Sergey Bugaev To: libc-alpha@sourceware.org, bug-hurd@gnu.org Cc: Maxim Kuvyrkov , Luca Subject: [PATCH v2 14/20] hurd: Implement TLS on AArch64 Date: Sat, 23 Mar 2024 20:32:55 +0300 Message-ID: <20240323173301.151066-15-bugaevc@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240323173301.151066-1-bugaevc@gmail.com> References: <20240323173301.151066-1-bugaevc@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-9.2 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_BARRACUDACENTRAL, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, 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+patchwork=sourceware.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..9beafec3 --- /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..712134e1 --- /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_COUNT; + + 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 */