This doesn't add any of the Hurd- or HTL-specific bits yet. Signed-off-by: Sergey Bugaev <buga...@gmail.com> ---
I don't think RPC_aarch64_get_hwcaps.c actually needs no-stack-protector since the stack protector is not (currently?) stored in TLS on AArch64, but let's have it there for consistency. cpu-features.c is heavily based on its Linux version, but hooked up to use the aarch64_get_hwcaps () RPC, invented specifically for this purpose, instead of auxval entries, which we don't have on the Hurd. sys/ucontext.h is mid-way between the Linux version (and x86 Hurd versions) and the FreeBSD version, but laid out to match the Mach aarch64_thread_state. Notably, like on FreeBSD, gregs/fpregs is an actual struct and not an array; but the field naming is like that of Linux and Hurd-on-x86. This unfortunately means there will be no source-level compatibility for applications with either Linux or BSD sys/ucontext.h. mach/Makefile | 1 + sysdeps/mach/aarch64/bits/mach/param.h | 24 ++++++ sysdeps/mach/aarch64/cpu-features.c | 109 +++++++++++++++++++++++++ sysdeps/mach/aarch64/sys/ucontext.h | 73 +++++++++++++++++ sysdeps/mach/aarch64/sysdep.h | 45 ++++++++++ sysdeps/mach/aarch64/thread_state.h | 44 ++++++++++ sysdeps/mach/configure | 1 + sysdeps/mach/configure.ac | 1 + 8 files changed, 298 insertions(+) create mode 100644 sysdeps/mach/aarch64/bits/mach/param.h create mode 100644 sysdeps/mach/aarch64/cpu-features.c create mode 100644 sysdeps/mach/aarch64/sys/ucontext.h create mode 100644 sysdeps/mach/aarch64/sysdep.h create mode 100644 sysdeps/mach/aarch64/thread_state.h diff --git a/mach/Makefile b/mach/Makefile index 0ea3b3c1..92394951 100644 --- a/mach/Makefile +++ b/mach/Makefile @@ -56,6 +56,7 @@ generated = # Avoid ssp before TLS is initialized. CFLAGS-mach_init.o = $(no-stack-protector) +CFLAGS-RPC_aarch64_get_hwcaps.o = $(no-stack-protector) CFLAGS-RPC_vm_statistics.o = $(no-stack-protector) CFLAGS-RPC_vm_map.o = $(no-stack-protector) CFLAGS-RPC_vm_protect.o = $(no-stack-protector) diff --git a/sysdeps/mach/aarch64/bits/mach/param.h b/sysdeps/mach/aarch64/bits/mach/param.h new file mode 100644 index 00000000..4f7b76ed --- /dev/null +++ b/sysdeps/mach/aarch64/bits/mach/param.h @@ -0,0 +1,24 @@ +/* Old-style Unix parameters and limits. aarch64 Mach version. + Copyright (C) 1993-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 + <https://www.gnu.org/licenses/>. */ + +#ifndef _SYS_PARAM_H +# error "Never use <bits/mach/param.h> directly; include <sys/param.h> instead." +#endif + +/* There is no EXEC_PAGESIZE. Use vm_page_size or getpagesize () + or sysconf (_SC_PAGESIZE) instead. */ diff --git a/sysdeps/mach/aarch64/cpu-features.c b/sysdeps/mach/aarch64/cpu-features.c new file mode 100644 index 00000000..a818bf76 --- /dev/null +++ b/sysdeps/mach/aarch64/cpu-features.c @@ -0,0 +1,109 @@ +/* Initialize CPU feature data. Mach aarch64 version. + This file is part of the GNU C Library. + Copyright (C) 2017-2024 Free Software Foundation, Inc. + + 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 + <https://www.gnu.org/licenses/>. */ + +#include <array_length.h> +#include <cpu-features.h> +#include <elf/dl-hwcaps.h> +#include <dl-tunables-parse.h> +#include <mach/aarch64/mach_aarch64.h> + +#define DCZID_DZP_MASK (1 << 4) +#define DCZID_BS_MASK (0xf) + +/* The maximal set of permitted tags that the MTE random tag generation + instruction may use. We exclude tag 0 because a) we want to reserve + that for the libc heap structures and b) because it makes it easier + to see when pointer have been correctly tagged. */ +#define MTE_ALLOWED_TAGS (0xfffe << PR_MTE_TAG_SHIFT) + +struct cpu_list +{ + const char *name; + size_t len; + uint64_t midr; +}; + +static const struct cpu_list cpu_list[] = +{ +#define CPU_LIST_ENTRY(__str, __num) { __str, sizeof (__str) - 1, __num } + CPU_LIST_ENTRY ("thunderxt88", 0x430F0A10), + CPU_LIST_ENTRY ("thunderx2t99", 0x431F0AF0), + CPU_LIST_ENTRY ("thunderx2t99p1", 0x420F5160), + CPU_LIST_ENTRY ("ares", 0x411FD0C0), + CPU_LIST_ENTRY ("emag", 0x503F0001), + CPU_LIST_ENTRY ("kunpeng920", 0x481FD010), + CPU_LIST_ENTRY ("a64fx", 0x460F0010), + CPU_LIST_ENTRY ("generic", 0x0), +}; + +static uint64_t +get_midr_from_mcpu (const struct tunable_str_t *mcpu) +{ + for (int i = 0; i < array_length (cpu_list); i++) + if (tunable_strcmp (mcpu, cpu_list[i].name, cpu_list[i].len)) + return cpu_list[i].midr; + + return UINT64_MAX; +} + +static inline void +init_cpu_features (struct cpu_features *cpu_features) +{ + error_t err; + uint32_t hwcaps[HWCAPS_COUNT]; + mach_msg_type_number_t hwcaps_size = HWCAPS_COUNT; + uint64_t midr, revidr; + + err = __aarch64_get_hwcaps (__mach_host_self (), hwcaps, + &hwcaps_size, &midr, &revidr); + assert_perror (err); + + if (hwcaps_size >= 1) + GLRO (dl_hwcap) = hwcaps[0]; + if (hwcaps_size >= 2) + GLRO (dl_hwcap2) = hwcaps[1]; + + cpu_features->midr_el1 = midr; + + /* Get the tunable override. */ + const struct tunable_str_t *mcpu = TUNABLE_GET (glibc, cpu, name, + struct tunable_str_t *, + NULL); + if (mcpu != NULL) + { + midr = get_midr_from_mcpu (mcpu); + if (midr != UINT64_MAX) + cpu_features->midr_el1 = midr; + } + + /* Check if ZVA is enabled. */ + unsigned dczid; + asm volatile ("mrs %0, dczid_el0" : "=r"(dczid)); + + if ((dczid & DCZID_DZP_MASK) == 0) + cpu_features->zva_size = 4 << (dczid & DCZID_BS_MASK); + + /* Check if BTI is supported. */ + cpu_features->bti = GLRO (dl_hwcap2) & HWCAP2_BTI; + + /* Check if SVE is supported. */ + cpu_features->sve = GLRO (dl_hwcap) & HWCAP_SVE; + + /* Check if MOPS is supported. */ + cpu_features->mops = GLRO (dl_hwcap2) & HWCAP2_MOPS; +} diff --git a/sysdeps/mach/aarch64/sys/ucontext.h b/sysdeps/mach/aarch64/sys/ucontext.h new file mode 100644 index 00000000..f77ebc87 --- /dev/null +++ b/sysdeps/mach/aarch64/sys/ucontext.h @@ -0,0 +1,73 @@ +/* Copyright (C) 1998-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 + <https://www.gnu.org/licenses/>. */ + +/* System V/AArch64 ABI compliant context switching support. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include <features.h> + +#include <bits/types/sigset_t.h> +#include <bits/types/stack_t.h> + +#ifdef __USE_MISC +# define __ctx(fld) fld +#else +# define __ctx(fld) __ ## fld +#endif + +/* Type for general register. */ +__extension__ typedef long long int greg_t; + +/* gregset_t is laid out to match mach/aarch64/thread_status.h:struct aarch64_thread_state */ +typedef struct +{ + greg_t __ctx(x)[31]; + greg_t __ctx(sp); + greg_t __ctx(pc); + greg_t __ctx(tpidr_el0); + unsigned int __ctx(cpsr); +} gregset_t; + +/* fpregset_t is laid out to match mach/aarch64/thread_status.h:struct aarch64_float_state */ +typedef struct +{ + __int128_t __ctx(v)[32]; + unsigned int __ctx(fpsr); + unsigned int __ctx(fpcr); +} fpregset_t; + +typedef struct +{ + gregset_t __ctx(gregs); + fpregset_t __ctx(fpregs); +} mcontext_t; + +typedef struct ucontext_t +{ + unsigned long __ctx(uc_flags); + struct ucontext_t *uc_link; + stack_t uc_stack; + sigset_t uc_sigmask; + mcontext_t uc_mcontext; +} ucontext_t; + +#undef __ctx + +#endif /* sys/ucontext.h */ diff --git a/sysdeps/mach/aarch64/sysdep.h b/sysdeps/mach/aarch64/sysdep.h new file mode 100644 index 00000000..edf8e016 --- /dev/null +++ b/sysdeps/mach/aarch64/sysdep.h @@ -0,0 +1,45 @@ +/* Copyright (C) 1991-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 + <https://www.gnu.org/licenses/>. */ + +#ifndef _MACH_AARCH64_SYSDEP_H +#define _MACH_AARCH64_SYSDEP_H 1 + +/* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO. */ +#include <dl-sysdep.h> +#include <tls.h> +/* Get the hwcap definitions. */ +#include <mach/aarch64/mach_aarch64_types.h> + +#define LOSE asm volatile ("udf #0xdead") + +#define STACK_GROWTH_DOWN + +/* Get the machine-independent Mach definitions. */ +#include <sysdeps/mach/sysdep.h> + +#undef ENTRY +#undef ALIGN + +#define RETURN_TO(sp, pc, retval) \ + asm volatile ("mov sp, %0; mov x30, %1; ret" \ + : : "r" (sp), "r" (pc)) + +#include <sysdeps/aarch64/sysdep.h> +#include <sysdeps/unix/sysdep.h> + +#endif /* mach/aarch64/sysdep.h */ diff --git a/sysdeps/mach/aarch64/thread_state.h b/sysdeps/mach/aarch64/thread_state.h new file mode 100644 index 00000000..5ddf9118 --- /dev/null +++ b/sysdeps/mach/aarch64/thread_state.h @@ -0,0 +1,44 @@ +/* Mach thread state definitions for machine-independent code. aarch64 version. + Copyright (C) 1994-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 + <https://www.gnu.org/licenses/>. */ + +#ifndef _MACH_AARCH64_THREAD_STATE_H +#define _MACH_AARCH64_THREAD_STATE_H 1 + +#include <mach/machine/thread_status.h> +#include <libc-pointer-arith.h> + +#define MACHINE_NEW_THREAD_STATE_FLAVOR AARCH64_THREAD_STATE +#define MACHINE_THREAD_STATE_FLAVOR AARCH64_THREAD_STATE +#define MACHINE_THREAD_STATE_COUNT AARCH64_THREAD_STATE_COUNT + +#define machine_thread_state aarch64_thread_state + +#define PC pc +#define SP sp +#define SYSRETURN x[0] + +struct machine_thread_all_state + { + struct aarch64_thread_state basic; + struct aarch64_float_state fpu; + int set; + }; + +#include <sysdeps/mach/thread_state.h> + +#endif /* mach/aarch64/thread_state.h */ diff --git a/sysdeps/mach/configure b/sysdeps/mach/configure index f15160d0..18f98967 100644 --- a/sysdeps/mach/configure +++ b/sysdeps/mach/configure @@ -268,6 +268,7 @@ for ifc in mach mach4 gnumach \ clock clock_priv host_priv host_security ledger lock_set \ processor processor_set task task_notify thread_act vm_map \ memory_object memory_object_default i386/mach_i386 x86_64/mach_i386 \ + aarch64/mach_aarch64 \ ; do as_ac_Header=`printf "%s\n" "ac_cv_header_mach/${ifc}.defs" | $as_tr_sh` ac_fn_c_check_header_preproc "$LINENO" "mach/${ifc}.defs" "$as_ac_Header" diff --git a/sysdeps/mach/configure.ac b/sysdeps/mach/configure.ac index 730fb25d..03e45df2 100644 --- a/sysdeps/mach/configure.ac +++ b/sysdeps/mach/configure.ac @@ -64,6 +64,7 @@ for ifc in mach mach4 gnumach \ clock clock_priv host_priv host_security ledger lock_set \ processor processor_set task task_notify thread_act vm_map \ memory_object memory_object_default i386/mach_i386 x86_64/mach_i386 \ + aarch64/mach_aarch64 \ ; do AC_CHECK_HEADER(mach/${ifc}.defs, [dnl mach_interface_list="$mach_interface_list $ifc"],, -) -- 2.43.0