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..1d1f5201
--- /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..69b95476
--- /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 long __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 long __ctx(fpsr);
+  unsigned long __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..ad5bf3b5
--- /dev/null
+++ b/sysdeps/mach/aarch64/sysdep.h
@@ -0,0 +1,52 @@
+/* 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)					      \
+do									      \
+  {									      \
+    register long __rv asm ("x0") = (retval);				      \
+    asm volatile ("mov sp, %0\n\t"					      \
+		  "ret %1"						      \
+		  :: "r" (sp), "r" (pc), "r" (__rv));			      \
+    __builtin_unreachable ();						      \
+  }									      \
+while (0)
+
+#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..f15859ee
--- /dev/null
+++ b/sysdeps/mach/aarch64/thread_state.h
@@ -0,0 +1,49 @@
+/* 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]
+
+#define MACHINE_THREAD_STATE_SETUP_CALL(ts, stack, size, func)		      \
+  ((ts)->sp = PTR_ALIGN_DOWN ((uintptr_t) (stack) + (size), 16),	      \
+   (ts)->pc = (uintptr_t) func,						      \
+   (ts)->cpsr = 0x0)	/* notably, reset BTYPE */
+
+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"],, -)
