This doesn't add any of the Hurd- or HTL-specific bits yet.
Signed-off-by: Sergey Bugaev <bugaevc@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
@@ -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)
new file mode 100644
@@ -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. */
new file mode 100644
@@ -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;
+}
new file mode 100644
@@ -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 */
new file mode 100644
@@ -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 */
new file mode 100644
@@ -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 */
@@ -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"
@@ -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"],, -)