diff mbox series

[RFC,v2,21/22] aarch64: Add GCS user-space allocation logic

Message ID 20241018100025.2955720-1-yury.khrustalev@arm.com
State New
Headers show
Series aarch64: Add support for Guarded Control Stack extension | expand

Commit Message

Yury Khrustalev Oct. 18, 2024, 10 a.m. UTC
From: Szabolcs Nagy <szabolcs.nagy@arm.com>

Allocate GCS based on the stack size, this can be used for coroutines
(makecontext) and thread creation (if the kernel allows user allocated
GCS).
---
 sysdeps/aarch64/Makefile      |  3 +-
 sysdeps/aarch64/__alloc_gcs.c | 66 +++++++++++++++++++++++++++++++++++
 sysdeps/aarch64/aarch64-gcs.h | 36 +++++++++++++++++++
 3 files changed, 104 insertions(+), 1 deletion(-)
 create mode 100644 sysdeps/aarch64/__alloc_gcs.c
 create mode 100644 sysdeps/aarch64/aarch64-gcs.h
diff mbox series

Patch

diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile
index 74479604f2..4b7f8a5c07 100644
--- a/sysdeps/aarch64/Makefile
+++ b/sysdeps/aarch64/Makefile
@@ -71,7 +71,8 @@  sysdep_headers += sys/ifunc.h
 sysdep_routines += \
   __mtag_tag_zero_region \
   __mtag_tag_region \
-  __arm_za_disable
+  __arm_za_disable \
+  __alloc_gcs
 
 tests += \
   tst-sme-jmp
diff --git a/sysdeps/aarch64/__alloc_gcs.c b/sysdeps/aarch64/__alloc_gcs.c
new file mode 100644
index 0000000000..62b7b6f396
--- /dev/null
+++ b/sysdeps/aarch64/__alloc_gcs.c
@@ -0,0 +1,66 @@ 
+/* AArch64 GCS allocation.
+   Copyright (C) 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 <sysdep.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#ifndef __NR_map_shadow_stack
+# define __NR_map_shadow_stack 453
+#endif
+#ifndef SHADOW_STACK_SET_TOKEN
+# define SHADOW_STACK_SET_TOKEN (1UL << 0)
+# define SHADOW_STACK_SET_MARKER (1UL << 1)
+#endif
+
+static void *
+map_shadow_stack (void *addr, size_t size, unsigned long flags)
+{
+  return (void *) INLINE_SYSCALL_CALL (map_shadow_stack, addr, size, flags);
+}
+
+#define GCS_MAX_SIZE (1UL << 31)
+#define GCS_ALTSTACK_RESERVE 160
+
+void *
+__alloc_gcs (size_t stack_size, void **ss_base, size_t *ss_size)
+{
+  size_t size = (stack_size / 2 + GCS_ALTSTACK_RESERVE) & -8UL;
+  if (size > GCS_MAX_SIZE)
+    size = GCS_MAX_SIZE;
+
+  unsigned long flags = SHADOW_STACK_SET_MARKER | SHADOW_STACK_SET_TOKEN;
+  void *base = map_shadow_stack (NULL, size, flags);
+  if (base == (void *) -1)
+    return NULL;
+
+  *ss_base = base;
+  *ss_size = size;
+
+  uint64_t *gcsp = (uint64_t *) ((char *) base + size);
+  /* Skip end of GCS token.  */
+  gcsp--;
+  /* Verify GCS cap token.  */
+  gcsp--;
+  if (((uint64_t)gcsp & 0xfffffffffffff000) + 1 != *gcsp)
+    {
+      __munmap (base, size);
+      return NULL;
+    }
+  /* Return the target GCS pointer for context switch.  */
+  return gcsp + 1;
+}
diff --git a/sysdeps/aarch64/aarch64-gcs.h b/sysdeps/aarch64/aarch64-gcs.h
new file mode 100644
index 0000000000..cbd1065a5d
--- /dev/null
+++ b/sysdeps/aarch64/aarch64-gcs.h
@@ -0,0 +1,36 @@ 
+/* AArch64 GCS (Guarded Control Stack) declarations.
+   This file is part of the GNU C Library.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   Copyright The GNU Toolchain Authors.
+
+   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 _AARCH64_GCS_H
+#define _AARCH64_GCS_H
+
+#include <stddef.h>
+#include <stdbool.h>
+
+void *__alloc_gcs (size_t, void **, size_t *) attribute_hidden;
+
+static inline bool
+has_gcs (void)
+{
+  register unsigned long x16 asm ("x16") = 1;
+  asm ("hint	40" /* chkfeat x16 */ : "+r" (x16));
+  return x16 == 0;
+}
+
+#endif