public inbox for glibc-cvs@sourceware.org
help / color / mirror / Atom feed
* [glibc/arm/morello/main] aarch64: morello: add purecap ucontext support
@ 2022-08-05 19:36 Szabolcs Nagy
  0 siblings, 0 replies; 4+ messages in thread
From: Szabolcs Nagy @ 2022-08-05 19:36 UTC (permalink / raw)
  To: glibc-cvs

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=ec5240f821f475379330283349fb9efd569c1ce6

commit ec5240f821f475379330283349fb9efd569c1ce6
Author: Carlos Eduardo Seo <carlos.seo@arm.com>
Date:   Thu May 27 17:49:20 2021 -0300

    aarch64: morello: add purecap ucontext support
    
    Adjust ucontext layout for purecap ABI and add make/get/set/swapcontext
    implementations accordingly.
    
    Note: mcontext layout follows the linux sigcontext struct, in userspace
    *context functions rely on the c registers stored in the extension area
    and ignore the mcontext fields for x registers.

Diff:
---
 sysdeps/unix/sysv/linux/aarch64/bits/procfs.h      |   5 +
 .../unix/sysv/linux/aarch64/morello/getcontext.S   | 121 +++++++++++++++++++
 .../unix/sysv/linux/aarch64/morello/makecontext.c  |  80 +++++++++++++
 .../unix/sysv/linux/aarch64/morello/setcontext.S   | 133 +++++++++++++++++++++
 .../unix/sysv/linux/aarch64/morello/swapcontext.S  | 120 +++++++++++++++++++
 sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h     |   4 +
 sysdeps/unix/sysv/linux/aarch64/sys/user.h         |  10 ++
 .../unix/sysv/linux/aarch64/ucontext-internal.h    |   5 +
 sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym     |  15 +++
 9 files changed, 493 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/procfs.h b/sysdeps/unix/sysv/linux/aarch64/bits/procfs.h
index 154fb95e66..596b95e333 100644
--- a/sysdeps/unix/sysv/linux/aarch64/bits/procfs.h
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/procfs.h
@@ -33,3 +33,8 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 
 /* Register set for the floating-point registers.  */
 typedef struct user_fpsimd_struct elf_fpregset_t;
+
+#ifdef __CHERI_PURE_CAPABILITY__
+/* Register set for the capability registers.  */
+typedef struct user_morello_struct elf_cregset_t;
+#endif
diff --git a/sysdeps/unix/sysv/linux/aarch64/morello/getcontext.S b/sysdeps/unix/sysv/linux/aarch64/morello/getcontext.S
new file mode 100644
index 0000000000..217ca28285
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/morello/getcontext.S
@@ -0,0 +1,121 @@
+/* Save current context.
+
+   Copyright (C) 2009-2022 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/>.  */
+
+#include <sysdep.h>
+#include "ucontext_i.h"
+#include "ucontext-internal.h"
+
+/* int getcontext (ucontext_t *ucp)
+
+   Returns 0 on success -1 and errno on failure.
+ */
+
+	.text
+
+ENTRY(__getcontext)
+	/* For Morello, we will save only the capability registers. These are saved
+	   in a special area in the context extension block after the FPSIMD
+	   context.  */
+	add	c9, c0, #oEXTENSION + FPSIMD_CONTEXT_SIZE
+
+	/* Write the context extension morello header.  */
+	mov	w3, #(MORELLO_MAGIC & 0xffff)
+	movk	w3, #(MORELLO_MAGIC >> 16), lsl #16
+	str	w3, [c9, #oCHEAD + oMAGIC]
+	mov	w3, #MORELLO_CONTEXT_SIZE
+	str	w3, [c9, #oCHEAD + oSIZE]
+
+	add	c10, c9, #oC0
+	/* The saved context will return to the getcontext() call point
+	   with a return value of 0 */
+	str	czr,	  [c10, 0 * SZCREG]
+
+	stp	c18, c19, [c10, 18 * SZCREG]
+	stp	c20, c21, [c10, 20 * SZCREG]
+	stp	c22, c23, [c10, 22 * SZCREG]
+	stp	c24, c25, [c10, 24 * SZCREG]
+	stp	c26, c27, [c10, 26 * SZCREG]
+	stp	c28, c29, [c10, 28 * SZCREG]
+	str     c30,      [c10, 30 * SZCREG]
+
+	/* Place LR into the saved PC, this will ensure that when
+	   switching to this saved context with setcontext() control
+	   will pass back to the caller of getcontext(), we have
+	   already arrange to return the appropriate return value in x0
+	   above.  */
+	str	c30, [c9, oPCC]
+
+	/* Save the current CSP */
+	mov	c2, csp
+	str     c2, [c9, oCSP]
+
+	/* Initialize the pstate.  */
+	str	xzr, [c0, oPSTATE]
+
+	/* Figure out where to place the first context extension
+	   block.  */
+	add     c2, c0, #oEXTENSION
+
+	/* Write the context extension fpsimd header.  */
+	mov	w3, #(FPSIMD_MAGIC & 0xffff)
+	movk	w3, #(FPSIMD_MAGIC >> 16), lsl #16
+	str	w3, [c2, #oHEAD + oMAGIC]
+	mov	w3, #FPSIMD_CONTEXT_SIZE
+	str	w3, [c2, #oHEAD + oSIZE]
+
+	/* Fill in the FP SIMD context.  */
+	add	c3, c2, #oV0 + 8 * SZVREG
+	stp	 q8,  q9, [c3], # 2 * SZVREG
+	stp	q10, q11, [c3], # 2 * SZVREG
+	stp	q12, q13, [c3], # 2 * SZVREG
+	stp	q14, q15, [c3], # 2 * SZVREG
+
+	add	c3, c2, oFPSR
+
+	mrs	x4, fpsr
+	str	w4, [c3]
+
+	mrs	x4, fpcr
+	str	w4, [c3, oFPCR - oFPSR]
+
+	/* Write the termination context extension header after the Morello
+	   context.  */
+	add	c2, c2, #FPSIMD_CONTEXT_SIZE + MORELLO_CONTEXT_SIZE
+	str	wzr, [c2, #oHEAD + oMAGIC]
+	str	wzr, [c2, #oHEAD + oSIZE]
+
+	/* Grab the signal mask */
+	/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
+	add	c2, c0, #UCONTEXT_SIGMASK
+	mov	x0, SIG_BLOCK
+	mov	x1, 0
+	mov	x3, _NSIG8
+	mov	x8, SYS_ify (rt_sigprocmask)
+	svc	0
+	cbnz	x0, 1f
+
+	/* Return 0 for success */
+	mov	x0, 0
+	RET
+1:
+	b	C_SYMBOL_NAME(__syscall_error)
+
+	PSEUDO_END (__getcontext)
+weak_alias (__getcontext, getcontext)
diff --git a/sysdeps/unix/sysv/linux/aarch64/morello/makecontext.c b/sysdeps/unix/sysv/linux/aarch64/morello/makecontext.c
new file mode 100644
index 0000000000..3bbfe85887
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/morello/makecontext.c
@@ -0,0 +1,80 @@
+/* Create new context.
+   Copyright (C) 2002-2022 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/>.  */
+
+#include <sysdep.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+#include <ucontext.h>
+#include <asm/sigcontext.h>
+#include "ucontext-internal.h"
+
+/* makecontext sets up a stack and the registers for the
+   user context.  The stack looks like this:
+
+               +-----------------------+
+	       | padding as required   |
+               +-----------------------+
+    sp ->      | parameter 7-n         |
+               +-----------------------+
+
+   The registers are set up like this:
+     %c0 .. %c7: parameter 1 to 8
+     %c19   : uc_link
+     %csp   : stack pointer.
+*/
+
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+  extern void __startcontext (void);
+  uint64_t *sp;
+  va_list ap;
+  int i;
+  struct morello_context *c_context;
+
+  sp = (uint64_t *)
+    ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
+
+  /* Allocate stack arguments.  */
+  sp -= argc < 8 ? 0 : argc - 8;
+
+  /* Keep the stack aligned.  */
+  sp = (uint64_t *) (((uintptr_t) sp) & -16L);
+
+  c_context = (void *) (ucp->uc_mcontext.__reserved
+			+ sizeof (struct fpsimd_context));
+
+  c_context->cregs[19] = (uintptr_t) ucp->uc_link;
+  c_context->csp = (uintptr_t) sp;
+  c_context->pcc = (uintptr_t) func;
+  c_context->cregs[29] = (uintptr_t) 0;
+  c_context->cregs[30] = (uintptr_t) &__startcontext;
+
+  va_start (ap, argc);
+  for (i = 0; i < argc; ++i)
+    if (i < 8)
+      c_context->cregs[i] = va_arg (ap, uint64_t);
+    else
+      sp[i - 8] = va_arg (ap, uint64_t);
+
+  va_end (ap);
+}
+
+weak_alias (__makecontext, makecontext)
diff --git a/sysdeps/unix/sysv/linux/aarch64/morello/setcontext.S b/sysdeps/unix/sysv/linux/aarch64/morello/setcontext.S
new file mode 100644
index 0000000000..3556d783fc
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/morello/setcontext.S
@@ -0,0 +1,133 @@
+/* Set current context.
+
+   Copyright (C) 2009-2022 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/>.  */
+
+#include <sysdep.h>
+#include "ucontext_i.h"
+#include "ucontext-internal.h"
+
+/*  int __setcontext (const ucontext_t *ucp)
+
+  Restores the machine context in UCP and thereby resumes execution
+  in that context.
+
+  This implementation is intended to be used for *synchronous* context
+  switches only.  Therefore, it does not have to restore anything
+  other than the PRESERVED state.  */
+
+	.text
+
+ENTRY (__setcontext)
+	/* Save a copy of UCP.  */
+	mov	c9, c0
+
+	/* Set the signal mask with
+	   rt_sigprocmask (SIG_SETMASK, mask, NULL, _NSIG/8).  */
+	mov	x0, #SIG_SETMASK
+	add	c1, c9, #UCONTEXT_SIGMASK
+	mov	x2, #0
+	mov	x3, #_NSIG8
+	mov	x8, SYS_ify (rt_sigprocmask)
+	svc	0
+	cbz	x0, 1f
+	b	C_SYMBOL_NAME (__syscall_error)
+1:
+	/* Restore the capability registers. For Morello, they are saved after the
+	   FPSIMD context.  */
+	mov	c0, c9
+	cfi_def_cfa (c0, 0)
+	cfi_offset (c18, oC0 + 18 * SZCREG)
+	cfi_offset (c19, oC0 + 19 * SZCREG)
+	cfi_offset (c20, oC0 + 20 * SZCREG)
+	cfi_offset (c21, oC0 + 21 * SZCREG)
+	cfi_offset (c22, oC0 + 22 * SZCREG)
+	cfi_offset (c23, oC0 + 23 * SZCREG)
+	cfi_offset (c24, oC0 + 24 * SZCREG)
+	cfi_offset (c25, oC0 + 25 * SZCREG)
+	cfi_offset (c26, oC0 + 26 * SZCREG)
+	cfi_offset (c27, oC0 + 27 * SZCREG)
+	cfi_offset (c28, oC0 + 28 * SZCREG)
+	cfi_offset (c29, oC0 + 29 * SZCREG)
+	cfi_offset (c30, oC0 + 30 * SZCREG)
+
+	cfi_offset ( d8, oV0 + 8 * SZVREG)
+	cfi_offset ( d9, oV0 + 9 * SZVREG)
+	cfi_offset (d10, oV0 + 10 * SZVREG)
+	cfi_offset (d11, oV0 + 11 * SZVREG)
+	cfi_offset (d12, oV0 + 12 * SZVREG)
+	cfi_offset (d13, oV0 + 13 * SZVREG)
+	cfi_offset (d14, oV0 + 14 * SZVREG)
+	cfi_offset (d15, oV0 + 15 * SZVREG)
+
+	add	c9, c0, #oEXTENSION + FPSIMD_CONTEXT_SIZE
+	add	c10, c9, #oC0
+	ldp	c18, c19, [c10, 18 * SZCREG]
+	ldp	c20, c21, [c10, 20 * SZCREG]
+	ldp	c22, c23, [c10, 22 * SZCREG]
+	ldp	c24, c25, [c10, 24 * SZCREG]
+	ldp	c26, c27, [c10, 26 * SZCREG]
+	ldp	c28, c29, [c10, 28 * SZCREG]
+	ldr     c30,      [c10, 30 * SZCREG]
+	ldr     c2, [c9, oCSP]
+	mov	csp, c2
+
+	/* Check for FP SIMD context.  We don't support restoring
+	   contexts created by the kernel, so this context must have
+	   been created by getcontext.  Hence we can rely on the
+	   first extension block being the FP SIMD context.  */
+	add     c2, c0, #oEXTENSION
+
+	mov	w3, #(FPSIMD_MAGIC & 0xffff)
+	movk	w3, #(FPSIMD_MAGIC >> 16), lsl #16
+	ldr	w1, [c2, #oHEAD + oMAGIC]
+	cmp	w1, w3
+	b.ne	2f
+
+	/* Restore the FP SIMD context.  */
+	add	c3, c2, #oV0 + 8 * SZVREG
+	ldp	 q8,  q9, [c3], #2 * SZVREG
+	ldp	q10, q11, [c3], #2 * SZVREG
+	ldp	q12, q13, [c3], #2 * SZVREG
+	ldp	q14, q15, [c3], #2 * SZVREG
+
+	add	c3, c2, oFPSR
+
+	ldr	w4, [c3]
+	msr	fpsr, x4
+
+	ldr	w4, [c3, oFPCR - oFPSR]
+	msr	fpcr, x4
+
+2:
+	ldr     c16, [c9, oPCC]
+	/* Restore arg registers.  */
+	ldp	c2, c3, [c10, 2 * SZCREG]
+	ldp	c4, c5, [c10, 4 * SZCREG]
+	ldp	c6, c7, [c10, 6 * SZCREG]
+	ldp	c0, c1, [c10, 0 * SZCREG]
+	/* Jump to the new pc value.  */
+	br	c16
+PSEUDO_END (__setcontext)
+weak_alias (__setcontext, setcontext)
+
+ENTRY (__startcontext)
+	mov	c0, c19
+	cbnz	x0, __setcontext
+1:	b       HIDDEN_JUMPTARGET (exit)
+END (__startcontext)
diff --git a/sysdeps/unix/sysv/linux/aarch64/morello/swapcontext.S b/sysdeps/unix/sysv/linux/aarch64/morello/swapcontext.S
new file mode 100644
index 0000000000..90e4eca413
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/morello/swapcontext.S
@@ -0,0 +1,120 @@
+/* Modify saved context.
+
+   Copyright (C) 2009-2022 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/>.  */
+
+#include <sysdep.h>
+
+#include "ucontext_i.h"
+#include "ucontext-internal.h"
+
+/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */
+
+	.text
+ENTRY(__swapcontext)
+	/* Set the value returned when swapcontext() returns in this context.
+	   And set up x1 to become the return address of the caller, so we
+	   can return there with a normal RET instead of an indirect jump.  */
+
+	/* For Morello, the capability registers are located in after the FPSIMD
+	   context.  */
+	add	c9, c0, #oEXTENSION + FPSIMD_CONTEXT_SIZE
+
+	/* Write the context extension morello header.  */
+	mov	w3, #(MORELLO_MAGIC & 0xffff)
+	movk	w3, #(MORELLO_MAGIC >> 16), lsl #16
+	str	w3, [c9, #oCHEAD + oMAGIC]
+	mov	w3, #MORELLO_CONTEXT_SIZE
+	str	w3, [c9, #oCHEAD + oSIZE]
+
+	add	c10, c9, #oC0
+	stp	czr, c30, [c10, 0 * SZCREG]
+	/* Arrange the oucp context to return to 2f.  */
+	adr	c30, 2f
+
+	stp	c18, c19, [c10, 18 * SZCREG]
+	stp	c20, c21, [c10, 20 * SZCREG]
+	stp	c22, c23, [c10, 22 * SZCREG]
+	stp	c24, c25, [c10, 24 * SZCREG]
+	stp	c26, c27, [c10, 26 * SZCREG]
+	stp	c28, c29, [c10, 28 * SZCREG]
+	str     c30,      [c10, 30 * SZCREG]
+	str     c30,      [c9, oPCC]
+	mov	c11, csp
+	str     c11,       [c9, oCSP]
+
+	/* Figure out where to place the fpsimd context extension
+	   block.  */
+	add     c9, c0, #oEXTENSION
+
+	/* Write the context extension fpsimd header.  */
+	mov	w3, #(FPSIMD_MAGIC & 0xffff)
+	movk	w3, #(FPSIMD_MAGIC >> 16), lsl #16
+	str	w3, [c9, #oHEAD + oMAGIC]
+	mov	w3, #FPSIMD_CONTEXT_SIZE
+	str	w3, [c9, #oHEAD + oSIZE]
+
+	/* Fill in the FP SIMD context.  */
+	add	c10, c9, #oV0 + 8 * SZVREG
+	stp	 q8,  q9, [c10], #2 * SZVREG
+	stp	q10, q11, [c10], #2 * SZVREG
+	stp	q12, q13, [c10], #2 * SZVREG
+	stp	q14, q15, [c10], #2 * SZVREG
+
+	add	c10, c9, #oFPSR
+	mrs	x4, fpsr
+	str	w4, [c10, #oFPSR - oFPSR]
+	mrs	x4, fpcr
+	str	w4, [c10, #oFPCR - oFPSR]
+
+	/* Write the termination context extension header after the Morello
+	   context.  */
+	add	c9, c9, #FPSIMD_CONTEXT_SIZE + MORELLO_CONTEXT_SIZE
+	str	wzr, [c9, #oHEAD + oMAGIC]
+	str	wzr, [c9, #oHEAD + oSIZE]
+
+	/* Preserve ucp.  */
+	mov	c11, c1
+
+	/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask,
+			   _NSIG8) */
+	/* Grab the signal mask */
+	/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
+	add	c2, c0, #UCONTEXT_SIGMASK
+	mov	x0, SIG_BLOCK
+	mov	x1, 0
+	mov	x3, _NSIG8
+	mov	x8, SYS_ify (rt_sigprocmask)
+	svc	0
+	cbnz	x0, 1f
+
+	mov     c15, c30
+	mov	c0, c11
+	bl	JUMPTARGET (__setcontext)
+	mov     c30, c15
+	RET
+
+1:
+	b	C_SYMBOL_NAME(__syscall_error)
+2:
+	/* The oucp context is restored here via an indirect branch,
+	   x1 must be restored too which has the real return address.  */
+	mov	c30, c1
+	RET
+PSEUDO_END (__swapcontext)
+weak_alias (__swapcontext, swapcontext)
diff --git a/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h b/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h
index fe91db68e8..cd39a2272b 100644
--- a/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h
+++ b/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h
@@ -43,6 +43,10 @@ typedef elf_gregset_t gregset_t;
 
 /* Structure to describe FPU registers.  */
 typedef elf_fpregset_t	fpregset_t;
+# ifdef __CHERI_PURE_CAPABILITY__
+/* Structure to describe capability registers.  */
+typedef elf_cregset_t cregset_t;
+# endif
 #endif
 
 /* Context to describe whole processor state.  This only describes
diff --git a/sysdeps/unix/sysv/linux/aarch64/sys/user.h b/sysdeps/unix/sysv/linux/aarch64/sys/user.h
index 32fbfd5f1a..e228838bc7 100644
--- a/sysdeps/unix/sysv/linux/aarch64/sys/user.h
+++ b/sysdeps/unix/sysv/linux/aarch64/sys/user.h
@@ -34,4 +34,14 @@ struct user_fpsimd_struct
   unsigned int fpcr;
 };
 
+# ifdef __CHERI_PURE_CAPABILITY__
+struct user_morello_struct
+{
+  __uintcap_t cregs[31];
+  __uintcap_t csp;
+  __uintcap_t rcsp;
+  __uintcap_t pcc;
+};
+# endif
+
 #endif
diff --git a/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h b/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h
index 685d41ca04..429a4c1035 100644
--- a/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h
+++ b/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h
@@ -23,6 +23,11 @@
 /* Size of an X regiser in bytes. */
 #define SZREG                8
 
+#ifdef __CHERI_PURE_CAPABILITY__
+/* Size of a C register in bytes. */
+# define SZCREG             16
+#endif
+
 /* Size of a V register in bytes. */
 #define SZVREG              16
 
diff --git a/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym b/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym
index ab3930c173..78022326af 100644
--- a/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym
+++ b/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym
@@ -18,6 +18,9 @@ RT_SIGFRAME_UCONTEXT		rt_sigframe (uc)
 
 RT_SIGFRAME_SIZE		sizeof (struct kernel_rt_sigframe)
 FPSIMD_CONTEXT_SIZE             sizeof (struct fpsimd_context)
+#ifdef __CHERI_PURE_CAPABILITY__
+MORELLO_CONTEXT_SIZE		sizeof (struct morello_context)
+#endif
 
 #define ucontext(member)	offsetof (ucontext_t, member)
 #define stack(member)		ucontext (uc_stack.member)
@@ -53,3 +56,15 @@ oMAGIC                          aarch64_ctx (magic)
 oSIZE                           aarch64_ctx (size)
 
 FPSIMD_MAGIC
+
+#ifdef __CHERI_PURE_CAPABILITY__
+#define morello_context(member) offsetof (struct morello_context, member)
+
+oCHEAD				morello_context (head)
+oC0				morello_context (cregs)
+oCSP				morello_context (csp)
+oRCSP				morello_context (rcsp)
+oPCC				morello_context (pcc)
+
+MORELLO_MAGIC
+#endif


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [glibc/arm/morello/main] aarch64: morello: add purecap ucontext support
@ 2022-11-23 14:47 Szabolcs Nagy
  0 siblings, 0 replies; 4+ messages in thread
From: Szabolcs Nagy @ 2022-11-23 14:47 UTC (permalink / raw)
  To: glibc-cvs

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=2f33e8ec62cf2a9b5715948edd2b5bb553fd4ac8

commit 2f33e8ec62cf2a9b5715948edd2b5bb553fd4ac8
Author: Carlos Eduardo Seo <carlos.seo@arm.com>
Date:   Thu May 27 17:49:20 2021 -0300

    aarch64: morello: add purecap ucontext support
    
    Adjust ucontext layout for purecap ABI and add make/get/set/swapcontext
    implementations accordingly.
    
    Note: mcontext layout follows the linux sigcontext struct, in userspace
    *context functions rely on the c registers stored in the extension area
    and ignore the mcontext fields for x registers.

Diff:
---
 sysdeps/unix/sysv/linux/aarch64/bits/procfs.h      |   5 +
 .../unix/sysv/linux/aarch64/morello/getcontext.S   | 121 +++++++++++++++++++
 .../unix/sysv/linux/aarch64/morello/makecontext.c  |  80 +++++++++++++
 .../unix/sysv/linux/aarch64/morello/setcontext.S   | 133 +++++++++++++++++++++
 .../unix/sysv/linux/aarch64/morello/swapcontext.S  | 120 +++++++++++++++++++
 sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h     |   4 +
 sysdeps/unix/sysv/linux/aarch64/sys/user.h         |  10 ++
 .../unix/sysv/linux/aarch64/ucontext-internal.h    |   5 +
 sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym     |  15 +++
 9 files changed, 493 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/procfs.h b/sysdeps/unix/sysv/linux/aarch64/bits/procfs.h
index 154fb95e66..596b95e333 100644
--- a/sysdeps/unix/sysv/linux/aarch64/bits/procfs.h
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/procfs.h
@@ -33,3 +33,8 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 
 /* Register set for the floating-point registers.  */
 typedef struct user_fpsimd_struct elf_fpregset_t;
+
+#ifdef __CHERI_PURE_CAPABILITY__
+/* Register set for the capability registers.  */
+typedef struct user_morello_struct elf_cregset_t;
+#endif
diff --git a/sysdeps/unix/sysv/linux/aarch64/morello/getcontext.S b/sysdeps/unix/sysv/linux/aarch64/morello/getcontext.S
new file mode 100644
index 0000000000..217ca28285
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/morello/getcontext.S
@@ -0,0 +1,121 @@
+/* Save current context.
+
+   Copyright (C) 2009-2022 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/>.  */
+
+#include <sysdep.h>
+#include "ucontext_i.h"
+#include "ucontext-internal.h"
+
+/* int getcontext (ucontext_t *ucp)
+
+   Returns 0 on success -1 and errno on failure.
+ */
+
+	.text
+
+ENTRY(__getcontext)
+	/* For Morello, we will save only the capability registers. These are saved
+	   in a special area in the context extension block after the FPSIMD
+	   context.  */
+	add	c9, c0, #oEXTENSION + FPSIMD_CONTEXT_SIZE
+
+	/* Write the context extension morello header.  */
+	mov	w3, #(MORELLO_MAGIC & 0xffff)
+	movk	w3, #(MORELLO_MAGIC >> 16), lsl #16
+	str	w3, [c9, #oCHEAD + oMAGIC]
+	mov	w3, #MORELLO_CONTEXT_SIZE
+	str	w3, [c9, #oCHEAD + oSIZE]
+
+	add	c10, c9, #oC0
+	/* The saved context will return to the getcontext() call point
+	   with a return value of 0 */
+	str	czr,	  [c10, 0 * SZCREG]
+
+	stp	c18, c19, [c10, 18 * SZCREG]
+	stp	c20, c21, [c10, 20 * SZCREG]
+	stp	c22, c23, [c10, 22 * SZCREG]
+	stp	c24, c25, [c10, 24 * SZCREG]
+	stp	c26, c27, [c10, 26 * SZCREG]
+	stp	c28, c29, [c10, 28 * SZCREG]
+	str     c30,      [c10, 30 * SZCREG]
+
+	/* Place LR into the saved PC, this will ensure that when
+	   switching to this saved context with setcontext() control
+	   will pass back to the caller of getcontext(), we have
+	   already arrange to return the appropriate return value in x0
+	   above.  */
+	str	c30, [c9, oPCC]
+
+	/* Save the current CSP */
+	mov	c2, csp
+	str     c2, [c9, oCSP]
+
+	/* Initialize the pstate.  */
+	str	xzr, [c0, oPSTATE]
+
+	/* Figure out where to place the first context extension
+	   block.  */
+	add     c2, c0, #oEXTENSION
+
+	/* Write the context extension fpsimd header.  */
+	mov	w3, #(FPSIMD_MAGIC & 0xffff)
+	movk	w3, #(FPSIMD_MAGIC >> 16), lsl #16
+	str	w3, [c2, #oHEAD + oMAGIC]
+	mov	w3, #FPSIMD_CONTEXT_SIZE
+	str	w3, [c2, #oHEAD + oSIZE]
+
+	/* Fill in the FP SIMD context.  */
+	add	c3, c2, #oV0 + 8 * SZVREG
+	stp	 q8,  q9, [c3], # 2 * SZVREG
+	stp	q10, q11, [c3], # 2 * SZVREG
+	stp	q12, q13, [c3], # 2 * SZVREG
+	stp	q14, q15, [c3], # 2 * SZVREG
+
+	add	c3, c2, oFPSR
+
+	mrs	x4, fpsr
+	str	w4, [c3]
+
+	mrs	x4, fpcr
+	str	w4, [c3, oFPCR - oFPSR]
+
+	/* Write the termination context extension header after the Morello
+	   context.  */
+	add	c2, c2, #FPSIMD_CONTEXT_SIZE + MORELLO_CONTEXT_SIZE
+	str	wzr, [c2, #oHEAD + oMAGIC]
+	str	wzr, [c2, #oHEAD + oSIZE]
+
+	/* Grab the signal mask */
+	/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
+	add	c2, c0, #UCONTEXT_SIGMASK
+	mov	x0, SIG_BLOCK
+	mov	x1, 0
+	mov	x3, _NSIG8
+	mov	x8, SYS_ify (rt_sigprocmask)
+	svc	0
+	cbnz	x0, 1f
+
+	/* Return 0 for success */
+	mov	x0, 0
+	RET
+1:
+	b	C_SYMBOL_NAME(__syscall_error)
+
+	PSEUDO_END (__getcontext)
+weak_alias (__getcontext, getcontext)
diff --git a/sysdeps/unix/sysv/linux/aarch64/morello/makecontext.c b/sysdeps/unix/sysv/linux/aarch64/morello/makecontext.c
new file mode 100644
index 0000000000..3bbfe85887
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/morello/makecontext.c
@@ -0,0 +1,80 @@
+/* Create new context.
+   Copyright (C) 2002-2022 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/>.  */
+
+#include <sysdep.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+#include <ucontext.h>
+#include <asm/sigcontext.h>
+#include "ucontext-internal.h"
+
+/* makecontext sets up a stack and the registers for the
+   user context.  The stack looks like this:
+
+               +-----------------------+
+	       | padding as required   |
+               +-----------------------+
+    sp ->      | parameter 7-n         |
+               +-----------------------+
+
+   The registers are set up like this:
+     %c0 .. %c7: parameter 1 to 8
+     %c19   : uc_link
+     %csp   : stack pointer.
+*/
+
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+  extern void __startcontext (void);
+  uint64_t *sp;
+  va_list ap;
+  int i;
+  struct morello_context *c_context;
+
+  sp = (uint64_t *)
+    ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
+
+  /* Allocate stack arguments.  */
+  sp -= argc < 8 ? 0 : argc - 8;
+
+  /* Keep the stack aligned.  */
+  sp = (uint64_t *) (((uintptr_t) sp) & -16L);
+
+  c_context = (void *) (ucp->uc_mcontext.__reserved
+			+ sizeof (struct fpsimd_context));
+
+  c_context->cregs[19] = (uintptr_t) ucp->uc_link;
+  c_context->csp = (uintptr_t) sp;
+  c_context->pcc = (uintptr_t) func;
+  c_context->cregs[29] = (uintptr_t) 0;
+  c_context->cregs[30] = (uintptr_t) &__startcontext;
+
+  va_start (ap, argc);
+  for (i = 0; i < argc; ++i)
+    if (i < 8)
+      c_context->cregs[i] = va_arg (ap, uint64_t);
+    else
+      sp[i - 8] = va_arg (ap, uint64_t);
+
+  va_end (ap);
+}
+
+weak_alias (__makecontext, makecontext)
diff --git a/sysdeps/unix/sysv/linux/aarch64/morello/setcontext.S b/sysdeps/unix/sysv/linux/aarch64/morello/setcontext.S
new file mode 100644
index 0000000000..3556d783fc
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/morello/setcontext.S
@@ -0,0 +1,133 @@
+/* Set current context.
+
+   Copyright (C) 2009-2022 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/>.  */
+
+#include <sysdep.h>
+#include "ucontext_i.h"
+#include "ucontext-internal.h"
+
+/*  int __setcontext (const ucontext_t *ucp)
+
+  Restores the machine context in UCP and thereby resumes execution
+  in that context.
+
+  This implementation is intended to be used for *synchronous* context
+  switches only.  Therefore, it does not have to restore anything
+  other than the PRESERVED state.  */
+
+	.text
+
+ENTRY (__setcontext)
+	/* Save a copy of UCP.  */
+	mov	c9, c0
+
+	/* Set the signal mask with
+	   rt_sigprocmask (SIG_SETMASK, mask, NULL, _NSIG/8).  */
+	mov	x0, #SIG_SETMASK
+	add	c1, c9, #UCONTEXT_SIGMASK
+	mov	x2, #0
+	mov	x3, #_NSIG8
+	mov	x8, SYS_ify (rt_sigprocmask)
+	svc	0
+	cbz	x0, 1f
+	b	C_SYMBOL_NAME (__syscall_error)
+1:
+	/* Restore the capability registers. For Morello, they are saved after the
+	   FPSIMD context.  */
+	mov	c0, c9
+	cfi_def_cfa (c0, 0)
+	cfi_offset (c18, oC0 + 18 * SZCREG)
+	cfi_offset (c19, oC0 + 19 * SZCREG)
+	cfi_offset (c20, oC0 + 20 * SZCREG)
+	cfi_offset (c21, oC0 + 21 * SZCREG)
+	cfi_offset (c22, oC0 + 22 * SZCREG)
+	cfi_offset (c23, oC0 + 23 * SZCREG)
+	cfi_offset (c24, oC0 + 24 * SZCREG)
+	cfi_offset (c25, oC0 + 25 * SZCREG)
+	cfi_offset (c26, oC0 + 26 * SZCREG)
+	cfi_offset (c27, oC0 + 27 * SZCREG)
+	cfi_offset (c28, oC0 + 28 * SZCREG)
+	cfi_offset (c29, oC0 + 29 * SZCREG)
+	cfi_offset (c30, oC0 + 30 * SZCREG)
+
+	cfi_offset ( d8, oV0 + 8 * SZVREG)
+	cfi_offset ( d9, oV0 + 9 * SZVREG)
+	cfi_offset (d10, oV0 + 10 * SZVREG)
+	cfi_offset (d11, oV0 + 11 * SZVREG)
+	cfi_offset (d12, oV0 + 12 * SZVREG)
+	cfi_offset (d13, oV0 + 13 * SZVREG)
+	cfi_offset (d14, oV0 + 14 * SZVREG)
+	cfi_offset (d15, oV0 + 15 * SZVREG)
+
+	add	c9, c0, #oEXTENSION + FPSIMD_CONTEXT_SIZE
+	add	c10, c9, #oC0
+	ldp	c18, c19, [c10, 18 * SZCREG]
+	ldp	c20, c21, [c10, 20 * SZCREG]
+	ldp	c22, c23, [c10, 22 * SZCREG]
+	ldp	c24, c25, [c10, 24 * SZCREG]
+	ldp	c26, c27, [c10, 26 * SZCREG]
+	ldp	c28, c29, [c10, 28 * SZCREG]
+	ldr     c30,      [c10, 30 * SZCREG]
+	ldr     c2, [c9, oCSP]
+	mov	csp, c2
+
+	/* Check for FP SIMD context.  We don't support restoring
+	   contexts created by the kernel, so this context must have
+	   been created by getcontext.  Hence we can rely on the
+	   first extension block being the FP SIMD context.  */
+	add     c2, c0, #oEXTENSION
+
+	mov	w3, #(FPSIMD_MAGIC & 0xffff)
+	movk	w3, #(FPSIMD_MAGIC >> 16), lsl #16
+	ldr	w1, [c2, #oHEAD + oMAGIC]
+	cmp	w1, w3
+	b.ne	2f
+
+	/* Restore the FP SIMD context.  */
+	add	c3, c2, #oV0 + 8 * SZVREG
+	ldp	 q8,  q9, [c3], #2 * SZVREG
+	ldp	q10, q11, [c3], #2 * SZVREG
+	ldp	q12, q13, [c3], #2 * SZVREG
+	ldp	q14, q15, [c3], #2 * SZVREG
+
+	add	c3, c2, oFPSR
+
+	ldr	w4, [c3]
+	msr	fpsr, x4
+
+	ldr	w4, [c3, oFPCR - oFPSR]
+	msr	fpcr, x4
+
+2:
+	ldr     c16, [c9, oPCC]
+	/* Restore arg registers.  */
+	ldp	c2, c3, [c10, 2 * SZCREG]
+	ldp	c4, c5, [c10, 4 * SZCREG]
+	ldp	c6, c7, [c10, 6 * SZCREG]
+	ldp	c0, c1, [c10, 0 * SZCREG]
+	/* Jump to the new pc value.  */
+	br	c16
+PSEUDO_END (__setcontext)
+weak_alias (__setcontext, setcontext)
+
+ENTRY (__startcontext)
+	mov	c0, c19
+	cbnz	x0, __setcontext
+1:	b       HIDDEN_JUMPTARGET (exit)
+END (__startcontext)
diff --git a/sysdeps/unix/sysv/linux/aarch64/morello/swapcontext.S b/sysdeps/unix/sysv/linux/aarch64/morello/swapcontext.S
new file mode 100644
index 0000000000..90e4eca413
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/morello/swapcontext.S
@@ -0,0 +1,120 @@
+/* Modify saved context.
+
+   Copyright (C) 2009-2022 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/>.  */
+
+#include <sysdep.h>
+
+#include "ucontext_i.h"
+#include "ucontext-internal.h"
+
+/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */
+
+	.text
+ENTRY(__swapcontext)
+	/* Set the value returned when swapcontext() returns in this context.
+	   And set up x1 to become the return address of the caller, so we
+	   can return there with a normal RET instead of an indirect jump.  */
+
+	/* For Morello, the capability registers are located in after the FPSIMD
+	   context.  */
+	add	c9, c0, #oEXTENSION + FPSIMD_CONTEXT_SIZE
+
+	/* Write the context extension morello header.  */
+	mov	w3, #(MORELLO_MAGIC & 0xffff)
+	movk	w3, #(MORELLO_MAGIC >> 16), lsl #16
+	str	w3, [c9, #oCHEAD + oMAGIC]
+	mov	w3, #MORELLO_CONTEXT_SIZE
+	str	w3, [c9, #oCHEAD + oSIZE]
+
+	add	c10, c9, #oC0
+	stp	czr, c30, [c10, 0 * SZCREG]
+	/* Arrange the oucp context to return to 2f.  */
+	adr	c30, 2f
+
+	stp	c18, c19, [c10, 18 * SZCREG]
+	stp	c20, c21, [c10, 20 * SZCREG]
+	stp	c22, c23, [c10, 22 * SZCREG]
+	stp	c24, c25, [c10, 24 * SZCREG]
+	stp	c26, c27, [c10, 26 * SZCREG]
+	stp	c28, c29, [c10, 28 * SZCREG]
+	str     c30,      [c10, 30 * SZCREG]
+	str     c30,      [c9, oPCC]
+	mov	c11, csp
+	str     c11,       [c9, oCSP]
+
+	/* Figure out where to place the fpsimd context extension
+	   block.  */
+	add     c9, c0, #oEXTENSION
+
+	/* Write the context extension fpsimd header.  */
+	mov	w3, #(FPSIMD_MAGIC & 0xffff)
+	movk	w3, #(FPSIMD_MAGIC >> 16), lsl #16
+	str	w3, [c9, #oHEAD + oMAGIC]
+	mov	w3, #FPSIMD_CONTEXT_SIZE
+	str	w3, [c9, #oHEAD + oSIZE]
+
+	/* Fill in the FP SIMD context.  */
+	add	c10, c9, #oV0 + 8 * SZVREG
+	stp	 q8,  q9, [c10], #2 * SZVREG
+	stp	q10, q11, [c10], #2 * SZVREG
+	stp	q12, q13, [c10], #2 * SZVREG
+	stp	q14, q15, [c10], #2 * SZVREG
+
+	add	c10, c9, #oFPSR
+	mrs	x4, fpsr
+	str	w4, [c10, #oFPSR - oFPSR]
+	mrs	x4, fpcr
+	str	w4, [c10, #oFPCR - oFPSR]
+
+	/* Write the termination context extension header after the Morello
+	   context.  */
+	add	c9, c9, #FPSIMD_CONTEXT_SIZE + MORELLO_CONTEXT_SIZE
+	str	wzr, [c9, #oHEAD + oMAGIC]
+	str	wzr, [c9, #oHEAD + oSIZE]
+
+	/* Preserve ucp.  */
+	mov	c11, c1
+
+	/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask,
+			   _NSIG8) */
+	/* Grab the signal mask */
+	/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
+	add	c2, c0, #UCONTEXT_SIGMASK
+	mov	x0, SIG_BLOCK
+	mov	x1, 0
+	mov	x3, _NSIG8
+	mov	x8, SYS_ify (rt_sigprocmask)
+	svc	0
+	cbnz	x0, 1f
+
+	mov     c15, c30
+	mov	c0, c11
+	bl	JUMPTARGET (__setcontext)
+	mov     c30, c15
+	RET
+
+1:
+	b	C_SYMBOL_NAME(__syscall_error)
+2:
+	/* The oucp context is restored here via an indirect branch,
+	   x1 must be restored too which has the real return address.  */
+	mov	c30, c1
+	RET
+PSEUDO_END (__swapcontext)
+weak_alias (__swapcontext, swapcontext)
diff --git a/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h b/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h
index fe91db68e8..cd39a2272b 100644
--- a/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h
+++ b/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h
@@ -43,6 +43,10 @@ typedef elf_gregset_t gregset_t;
 
 /* Structure to describe FPU registers.  */
 typedef elf_fpregset_t	fpregset_t;
+# ifdef __CHERI_PURE_CAPABILITY__
+/* Structure to describe capability registers.  */
+typedef elf_cregset_t cregset_t;
+# endif
 #endif
 
 /* Context to describe whole processor state.  This only describes
diff --git a/sysdeps/unix/sysv/linux/aarch64/sys/user.h b/sysdeps/unix/sysv/linux/aarch64/sys/user.h
index 32fbfd5f1a..e228838bc7 100644
--- a/sysdeps/unix/sysv/linux/aarch64/sys/user.h
+++ b/sysdeps/unix/sysv/linux/aarch64/sys/user.h
@@ -34,4 +34,14 @@ struct user_fpsimd_struct
   unsigned int fpcr;
 };
 
+# ifdef __CHERI_PURE_CAPABILITY__
+struct user_morello_struct
+{
+  __uintcap_t cregs[31];
+  __uintcap_t csp;
+  __uintcap_t rcsp;
+  __uintcap_t pcc;
+};
+# endif
+
 #endif
diff --git a/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h b/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h
index 685d41ca04..429a4c1035 100644
--- a/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h
+++ b/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h
@@ -23,6 +23,11 @@
 /* Size of an X regiser in bytes. */
 #define SZREG                8
 
+#ifdef __CHERI_PURE_CAPABILITY__
+/* Size of a C register in bytes. */
+# define SZCREG             16
+#endif
+
 /* Size of a V register in bytes. */
 #define SZVREG              16
 
diff --git a/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym b/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym
index ab3930c173..78022326af 100644
--- a/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym
+++ b/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym
@@ -18,6 +18,9 @@ RT_SIGFRAME_UCONTEXT		rt_sigframe (uc)
 
 RT_SIGFRAME_SIZE		sizeof (struct kernel_rt_sigframe)
 FPSIMD_CONTEXT_SIZE             sizeof (struct fpsimd_context)
+#ifdef __CHERI_PURE_CAPABILITY__
+MORELLO_CONTEXT_SIZE		sizeof (struct morello_context)
+#endif
 
 #define ucontext(member)	offsetof (ucontext_t, member)
 #define stack(member)		ucontext (uc_stack.member)
@@ -53,3 +56,15 @@ oMAGIC                          aarch64_ctx (magic)
 oSIZE                           aarch64_ctx (size)
 
 FPSIMD_MAGIC
+
+#ifdef __CHERI_PURE_CAPABILITY__
+#define morello_context(member) offsetof (struct morello_context, member)
+
+oCHEAD				morello_context (head)
+oC0				morello_context (cregs)
+oCSP				morello_context (csp)
+oRCSP				morello_context (rcsp)
+oPCC				morello_context (pcc)
+
+MORELLO_MAGIC
+#endif

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [glibc/arm/morello/main] aarch64: morello: add purecap ucontext support
@ 2022-10-27 13:57 Szabolcs Nagy
  0 siblings, 0 replies; 4+ messages in thread
From: Szabolcs Nagy @ 2022-10-27 13:57 UTC (permalink / raw)
  To: glibc-cvs

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=45f35bca7d80322d25f16b4794f812f2e9c7f936

commit 45f35bca7d80322d25f16b4794f812f2e9c7f936
Author: Carlos Eduardo Seo <carlos.seo@arm.com>
Date:   Thu May 27 17:49:20 2021 -0300

    aarch64: morello: add purecap ucontext support
    
    Adjust ucontext layout for purecap ABI and add make/get/set/swapcontext
    implementations accordingly.
    
    Note: mcontext layout follows the linux sigcontext struct, in userspace
    *context functions rely on the c registers stored in the extension area
    and ignore the mcontext fields for x registers.

Diff:
---
 sysdeps/unix/sysv/linux/aarch64/bits/procfs.h      |   5 +
 .../unix/sysv/linux/aarch64/morello/getcontext.S   | 121 +++++++++++++++++++
 .../unix/sysv/linux/aarch64/morello/makecontext.c  |  80 +++++++++++++
 .../unix/sysv/linux/aarch64/morello/setcontext.S   | 133 +++++++++++++++++++++
 .../unix/sysv/linux/aarch64/morello/swapcontext.S  | 120 +++++++++++++++++++
 sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h     |   4 +
 sysdeps/unix/sysv/linux/aarch64/sys/user.h         |  10 ++
 .../unix/sysv/linux/aarch64/ucontext-internal.h    |   5 +
 sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym     |  15 +++
 9 files changed, 493 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/procfs.h b/sysdeps/unix/sysv/linux/aarch64/bits/procfs.h
index 154fb95e66..596b95e333 100644
--- a/sysdeps/unix/sysv/linux/aarch64/bits/procfs.h
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/procfs.h
@@ -33,3 +33,8 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 
 /* Register set for the floating-point registers.  */
 typedef struct user_fpsimd_struct elf_fpregset_t;
+
+#ifdef __CHERI_PURE_CAPABILITY__
+/* Register set for the capability registers.  */
+typedef struct user_morello_struct elf_cregset_t;
+#endif
diff --git a/sysdeps/unix/sysv/linux/aarch64/morello/getcontext.S b/sysdeps/unix/sysv/linux/aarch64/morello/getcontext.S
new file mode 100644
index 0000000000..217ca28285
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/morello/getcontext.S
@@ -0,0 +1,121 @@
+/* Save current context.
+
+   Copyright (C) 2009-2022 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/>.  */
+
+#include <sysdep.h>
+#include "ucontext_i.h"
+#include "ucontext-internal.h"
+
+/* int getcontext (ucontext_t *ucp)
+
+   Returns 0 on success -1 and errno on failure.
+ */
+
+	.text
+
+ENTRY(__getcontext)
+	/* For Morello, we will save only the capability registers. These are saved
+	   in a special area in the context extension block after the FPSIMD
+	   context.  */
+	add	c9, c0, #oEXTENSION + FPSIMD_CONTEXT_SIZE
+
+	/* Write the context extension morello header.  */
+	mov	w3, #(MORELLO_MAGIC & 0xffff)
+	movk	w3, #(MORELLO_MAGIC >> 16), lsl #16
+	str	w3, [c9, #oCHEAD + oMAGIC]
+	mov	w3, #MORELLO_CONTEXT_SIZE
+	str	w3, [c9, #oCHEAD + oSIZE]
+
+	add	c10, c9, #oC0
+	/* The saved context will return to the getcontext() call point
+	   with a return value of 0 */
+	str	czr,	  [c10, 0 * SZCREG]
+
+	stp	c18, c19, [c10, 18 * SZCREG]
+	stp	c20, c21, [c10, 20 * SZCREG]
+	stp	c22, c23, [c10, 22 * SZCREG]
+	stp	c24, c25, [c10, 24 * SZCREG]
+	stp	c26, c27, [c10, 26 * SZCREG]
+	stp	c28, c29, [c10, 28 * SZCREG]
+	str     c30,      [c10, 30 * SZCREG]
+
+	/* Place LR into the saved PC, this will ensure that when
+	   switching to this saved context with setcontext() control
+	   will pass back to the caller of getcontext(), we have
+	   already arrange to return the appropriate return value in x0
+	   above.  */
+	str	c30, [c9, oPCC]
+
+	/* Save the current CSP */
+	mov	c2, csp
+	str     c2, [c9, oCSP]
+
+	/* Initialize the pstate.  */
+	str	xzr, [c0, oPSTATE]
+
+	/* Figure out where to place the first context extension
+	   block.  */
+	add     c2, c0, #oEXTENSION
+
+	/* Write the context extension fpsimd header.  */
+	mov	w3, #(FPSIMD_MAGIC & 0xffff)
+	movk	w3, #(FPSIMD_MAGIC >> 16), lsl #16
+	str	w3, [c2, #oHEAD + oMAGIC]
+	mov	w3, #FPSIMD_CONTEXT_SIZE
+	str	w3, [c2, #oHEAD + oSIZE]
+
+	/* Fill in the FP SIMD context.  */
+	add	c3, c2, #oV0 + 8 * SZVREG
+	stp	 q8,  q9, [c3], # 2 * SZVREG
+	stp	q10, q11, [c3], # 2 * SZVREG
+	stp	q12, q13, [c3], # 2 * SZVREG
+	stp	q14, q15, [c3], # 2 * SZVREG
+
+	add	c3, c2, oFPSR
+
+	mrs	x4, fpsr
+	str	w4, [c3]
+
+	mrs	x4, fpcr
+	str	w4, [c3, oFPCR - oFPSR]
+
+	/* Write the termination context extension header after the Morello
+	   context.  */
+	add	c2, c2, #FPSIMD_CONTEXT_SIZE + MORELLO_CONTEXT_SIZE
+	str	wzr, [c2, #oHEAD + oMAGIC]
+	str	wzr, [c2, #oHEAD + oSIZE]
+
+	/* Grab the signal mask */
+	/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
+	add	c2, c0, #UCONTEXT_SIGMASK
+	mov	x0, SIG_BLOCK
+	mov	x1, 0
+	mov	x3, _NSIG8
+	mov	x8, SYS_ify (rt_sigprocmask)
+	svc	0
+	cbnz	x0, 1f
+
+	/* Return 0 for success */
+	mov	x0, 0
+	RET
+1:
+	b	C_SYMBOL_NAME(__syscall_error)
+
+	PSEUDO_END (__getcontext)
+weak_alias (__getcontext, getcontext)
diff --git a/sysdeps/unix/sysv/linux/aarch64/morello/makecontext.c b/sysdeps/unix/sysv/linux/aarch64/morello/makecontext.c
new file mode 100644
index 0000000000..3bbfe85887
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/morello/makecontext.c
@@ -0,0 +1,80 @@
+/* Create new context.
+   Copyright (C) 2002-2022 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/>.  */
+
+#include <sysdep.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+#include <ucontext.h>
+#include <asm/sigcontext.h>
+#include "ucontext-internal.h"
+
+/* makecontext sets up a stack and the registers for the
+   user context.  The stack looks like this:
+
+               +-----------------------+
+	       | padding as required   |
+               +-----------------------+
+    sp ->      | parameter 7-n         |
+               +-----------------------+
+
+   The registers are set up like this:
+     %c0 .. %c7: parameter 1 to 8
+     %c19   : uc_link
+     %csp   : stack pointer.
+*/
+
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+  extern void __startcontext (void);
+  uint64_t *sp;
+  va_list ap;
+  int i;
+  struct morello_context *c_context;
+
+  sp = (uint64_t *)
+    ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
+
+  /* Allocate stack arguments.  */
+  sp -= argc < 8 ? 0 : argc - 8;
+
+  /* Keep the stack aligned.  */
+  sp = (uint64_t *) (((uintptr_t) sp) & -16L);
+
+  c_context = (void *) (ucp->uc_mcontext.__reserved
+			+ sizeof (struct fpsimd_context));
+
+  c_context->cregs[19] = (uintptr_t) ucp->uc_link;
+  c_context->csp = (uintptr_t) sp;
+  c_context->pcc = (uintptr_t) func;
+  c_context->cregs[29] = (uintptr_t) 0;
+  c_context->cregs[30] = (uintptr_t) &__startcontext;
+
+  va_start (ap, argc);
+  for (i = 0; i < argc; ++i)
+    if (i < 8)
+      c_context->cregs[i] = va_arg (ap, uint64_t);
+    else
+      sp[i - 8] = va_arg (ap, uint64_t);
+
+  va_end (ap);
+}
+
+weak_alias (__makecontext, makecontext)
diff --git a/sysdeps/unix/sysv/linux/aarch64/morello/setcontext.S b/sysdeps/unix/sysv/linux/aarch64/morello/setcontext.S
new file mode 100644
index 0000000000..3556d783fc
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/morello/setcontext.S
@@ -0,0 +1,133 @@
+/* Set current context.
+
+   Copyright (C) 2009-2022 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/>.  */
+
+#include <sysdep.h>
+#include "ucontext_i.h"
+#include "ucontext-internal.h"
+
+/*  int __setcontext (const ucontext_t *ucp)
+
+  Restores the machine context in UCP and thereby resumes execution
+  in that context.
+
+  This implementation is intended to be used for *synchronous* context
+  switches only.  Therefore, it does not have to restore anything
+  other than the PRESERVED state.  */
+
+	.text
+
+ENTRY (__setcontext)
+	/* Save a copy of UCP.  */
+	mov	c9, c0
+
+	/* Set the signal mask with
+	   rt_sigprocmask (SIG_SETMASK, mask, NULL, _NSIG/8).  */
+	mov	x0, #SIG_SETMASK
+	add	c1, c9, #UCONTEXT_SIGMASK
+	mov	x2, #0
+	mov	x3, #_NSIG8
+	mov	x8, SYS_ify (rt_sigprocmask)
+	svc	0
+	cbz	x0, 1f
+	b	C_SYMBOL_NAME (__syscall_error)
+1:
+	/* Restore the capability registers. For Morello, they are saved after the
+	   FPSIMD context.  */
+	mov	c0, c9
+	cfi_def_cfa (c0, 0)
+	cfi_offset (c18, oC0 + 18 * SZCREG)
+	cfi_offset (c19, oC0 + 19 * SZCREG)
+	cfi_offset (c20, oC0 + 20 * SZCREG)
+	cfi_offset (c21, oC0 + 21 * SZCREG)
+	cfi_offset (c22, oC0 + 22 * SZCREG)
+	cfi_offset (c23, oC0 + 23 * SZCREG)
+	cfi_offset (c24, oC0 + 24 * SZCREG)
+	cfi_offset (c25, oC0 + 25 * SZCREG)
+	cfi_offset (c26, oC0 + 26 * SZCREG)
+	cfi_offset (c27, oC0 + 27 * SZCREG)
+	cfi_offset (c28, oC0 + 28 * SZCREG)
+	cfi_offset (c29, oC0 + 29 * SZCREG)
+	cfi_offset (c30, oC0 + 30 * SZCREG)
+
+	cfi_offset ( d8, oV0 + 8 * SZVREG)
+	cfi_offset ( d9, oV0 + 9 * SZVREG)
+	cfi_offset (d10, oV0 + 10 * SZVREG)
+	cfi_offset (d11, oV0 + 11 * SZVREG)
+	cfi_offset (d12, oV0 + 12 * SZVREG)
+	cfi_offset (d13, oV0 + 13 * SZVREG)
+	cfi_offset (d14, oV0 + 14 * SZVREG)
+	cfi_offset (d15, oV0 + 15 * SZVREG)
+
+	add	c9, c0, #oEXTENSION + FPSIMD_CONTEXT_SIZE
+	add	c10, c9, #oC0
+	ldp	c18, c19, [c10, 18 * SZCREG]
+	ldp	c20, c21, [c10, 20 * SZCREG]
+	ldp	c22, c23, [c10, 22 * SZCREG]
+	ldp	c24, c25, [c10, 24 * SZCREG]
+	ldp	c26, c27, [c10, 26 * SZCREG]
+	ldp	c28, c29, [c10, 28 * SZCREG]
+	ldr     c30,      [c10, 30 * SZCREG]
+	ldr     c2, [c9, oCSP]
+	mov	csp, c2
+
+	/* Check for FP SIMD context.  We don't support restoring
+	   contexts created by the kernel, so this context must have
+	   been created by getcontext.  Hence we can rely on the
+	   first extension block being the FP SIMD context.  */
+	add     c2, c0, #oEXTENSION
+
+	mov	w3, #(FPSIMD_MAGIC & 0xffff)
+	movk	w3, #(FPSIMD_MAGIC >> 16), lsl #16
+	ldr	w1, [c2, #oHEAD + oMAGIC]
+	cmp	w1, w3
+	b.ne	2f
+
+	/* Restore the FP SIMD context.  */
+	add	c3, c2, #oV0 + 8 * SZVREG
+	ldp	 q8,  q9, [c3], #2 * SZVREG
+	ldp	q10, q11, [c3], #2 * SZVREG
+	ldp	q12, q13, [c3], #2 * SZVREG
+	ldp	q14, q15, [c3], #2 * SZVREG
+
+	add	c3, c2, oFPSR
+
+	ldr	w4, [c3]
+	msr	fpsr, x4
+
+	ldr	w4, [c3, oFPCR - oFPSR]
+	msr	fpcr, x4
+
+2:
+	ldr     c16, [c9, oPCC]
+	/* Restore arg registers.  */
+	ldp	c2, c3, [c10, 2 * SZCREG]
+	ldp	c4, c5, [c10, 4 * SZCREG]
+	ldp	c6, c7, [c10, 6 * SZCREG]
+	ldp	c0, c1, [c10, 0 * SZCREG]
+	/* Jump to the new pc value.  */
+	br	c16
+PSEUDO_END (__setcontext)
+weak_alias (__setcontext, setcontext)
+
+ENTRY (__startcontext)
+	mov	c0, c19
+	cbnz	x0, __setcontext
+1:	b       HIDDEN_JUMPTARGET (exit)
+END (__startcontext)
diff --git a/sysdeps/unix/sysv/linux/aarch64/morello/swapcontext.S b/sysdeps/unix/sysv/linux/aarch64/morello/swapcontext.S
new file mode 100644
index 0000000000..90e4eca413
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/morello/swapcontext.S
@@ -0,0 +1,120 @@
+/* Modify saved context.
+
+   Copyright (C) 2009-2022 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/>.  */
+
+#include <sysdep.h>
+
+#include "ucontext_i.h"
+#include "ucontext-internal.h"
+
+/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */
+
+	.text
+ENTRY(__swapcontext)
+	/* Set the value returned when swapcontext() returns in this context.
+	   And set up x1 to become the return address of the caller, so we
+	   can return there with a normal RET instead of an indirect jump.  */
+
+	/* For Morello, the capability registers are located in after the FPSIMD
+	   context.  */
+	add	c9, c0, #oEXTENSION + FPSIMD_CONTEXT_SIZE
+
+	/* Write the context extension morello header.  */
+	mov	w3, #(MORELLO_MAGIC & 0xffff)
+	movk	w3, #(MORELLO_MAGIC >> 16), lsl #16
+	str	w3, [c9, #oCHEAD + oMAGIC]
+	mov	w3, #MORELLO_CONTEXT_SIZE
+	str	w3, [c9, #oCHEAD + oSIZE]
+
+	add	c10, c9, #oC0
+	stp	czr, c30, [c10, 0 * SZCREG]
+	/* Arrange the oucp context to return to 2f.  */
+	adr	c30, 2f
+
+	stp	c18, c19, [c10, 18 * SZCREG]
+	stp	c20, c21, [c10, 20 * SZCREG]
+	stp	c22, c23, [c10, 22 * SZCREG]
+	stp	c24, c25, [c10, 24 * SZCREG]
+	stp	c26, c27, [c10, 26 * SZCREG]
+	stp	c28, c29, [c10, 28 * SZCREG]
+	str     c30,      [c10, 30 * SZCREG]
+	str     c30,      [c9, oPCC]
+	mov	c11, csp
+	str     c11,       [c9, oCSP]
+
+	/* Figure out where to place the fpsimd context extension
+	   block.  */
+	add     c9, c0, #oEXTENSION
+
+	/* Write the context extension fpsimd header.  */
+	mov	w3, #(FPSIMD_MAGIC & 0xffff)
+	movk	w3, #(FPSIMD_MAGIC >> 16), lsl #16
+	str	w3, [c9, #oHEAD + oMAGIC]
+	mov	w3, #FPSIMD_CONTEXT_SIZE
+	str	w3, [c9, #oHEAD + oSIZE]
+
+	/* Fill in the FP SIMD context.  */
+	add	c10, c9, #oV0 + 8 * SZVREG
+	stp	 q8,  q9, [c10], #2 * SZVREG
+	stp	q10, q11, [c10], #2 * SZVREG
+	stp	q12, q13, [c10], #2 * SZVREG
+	stp	q14, q15, [c10], #2 * SZVREG
+
+	add	c10, c9, #oFPSR
+	mrs	x4, fpsr
+	str	w4, [c10, #oFPSR - oFPSR]
+	mrs	x4, fpcr
+	str	w4, [c10, #oFPCR - oFPSR]
+
+	/* Write the termination context extension header after the Morello
+	   context.  */
+	add	c9, c9, #FPSIMD_CONTEXT_SIZE + MORELLO_CONTEXT_SIZE
+	str	wzr, [c9, #oHEAD + oMAGIC]
+	str	wzr, [c9, #oHEAD + oSIZE]
+
+	/* Preserve ucp.  */
+	mov	c11, c1
+
+	/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask,
+			   _NSIG8) */
+	/* Grab the signal mask */
+	/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
+	add	c2, c0, #UCONTEXT_SIGMASK
+	mov	x0, SIG_BLOCK
+	mov	x1, 0
+	mov	x3, _NSIG8
+	mov	x8, SYS_ify (rt_sigprocmask)
+	svc	0
+	cbnz	x0, 1f
+
+	mov     c15, c30
+	mov	c0, c11
+	bl	JUMPTARGET (__setcontext)
+	mov     c30, c15
+	RET
+
+1:
+	b	C_SYMBOL_NAME(__syscall_error)
+2:
+	/* The oucp context is restored here via an indirect branch,
+	   x1 must be restored too which has the real return address.  */
+	mov	c30, c1
+	RET
+PSEUDO_END (__swapcontext)
+weak_alias (__swapcontext, swapcontext)
diff --git a/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h b/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h
index fe91db68e8..cd39a2272b 100644
--- a/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h
+++ b/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h
@@ -43,6 +43,10 @@ typedef elf_gregset_t gregset_t;
 
 /* Structure to describe FPU registers.  */
 typedef elf_fpregset_t	fpregset_t;
+# ifdef __CHERI_PURE_CAPABILITY__
+/* Structure to describe capability registers.  */
+typedef elf_cregset_t cregset_t;
+# endif
 #endif
 
 /* Context to describe whole processor state.  This only describes
diff --git a/sysdeps/unix/sysv/linux/aarch64/sys/user.h b/sysdeps/unix/sysv/linux/aarch64/sys/user.h
index 32fbfd5f1a..e228838bc7 100644
--- a/sysdeps/unix/sysv/linux/aarch64/sys/user.h
+++ b/sysdeps/unix/sysv/linux/aarch64/sys/user.h
@@ -34,4 +34,14 @@ struct user_fpsimd_struct
   unsigned int fpcr;
 };
 
+# ifdef __CHERI_PURE_CAPABILITY__
+struct user_morello_struct
+{
+  __uintcap_t cregs[31];
+  __uintcap_t csp;
+  __uintcap_t rcsp;
+  __uintcap_t pcc;
+};
+# endif
+
 #endif
diff --git a/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h b/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h
index 685d41ca04..429a4c1035 100644
--- a/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h
+++ b/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h
@@ -23,6 +23,11 @@
 /* Size of an X regiser in bytes. */
 #define SZREG                8
 
+#ifdef __CHERI_PURE_CAPABILITY__
+/* Size of a C register in bytes. */
+# define SZCREG             16
+#endif
+
 /* Size of a V register in bytes. */
 #define SZVREG              16
 
diff --git a/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym b/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym
index ab3930c173..78022326af 100644
--- a/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym
+++ b/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym
@@ -18,6 +18,9 @@ RT_SIGFRAME_UCONTEXT		rt_sigframe (uc)
 
 RT_SIGFRAME_SIZE		sizeof (struct kernel_rt_sigframe)
 FPSIMD_CONTEXT_SIZE             sizeof (struct fpsimd_context)
+#ifdef __CHERI_PURE_CAPABILITY__
+MORELLO_CONTEXT_SIZE		sizeof (struct morello_context)
+#endif
 
 #define ucontext(member)	offsetof (ucontext_t, member)
 #define stack(member)		ucontext (uc_stack.member)
@@ -53,3 +56,15 @@ oMAGIC                          aarch64_ctx (magic)
 oSIZE                           aarch64_ctx (size)
 
 FPSIMD_MAGIC
+
+#ifdef __CHERI_PURE_CAPABILITY__
+#define morello_context(member) offsetof (struct morello_context, member)
+
+oCHEAD				morello_context (head)
+oC0				morello_context (cregs)
+oCSP				morello_context (csp)
+oRCSP				morello_context (rcsp)
+oPCC				morello_context (pcc)
+
+MORELLO_MAGIC
+#endif

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [glibc/arm/morello/main] aarch64: morello: add purecap ucontext support
@ 2022-10-26 15:18 Szabolcs Nagy
  0 siblings, 0 replies; 4+ messages in thread
From: Szabolcs Nagy @ 2022-10-26 15:18 UTC (permalink / raw)
  To: glibc-cvs

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=9eb64fc2d4cbc4186f5693258ade72398e6de397

commit 9eb64fc2d4cbc4186f5693258ade72398e6de397
Author: Carlos Eduardo Seo <carlos.seo@arm.com>
Date:   Thu May 27 17:49:20 2021 -0300

    aarch64: morello: add purecap ucontext support
    
    Adjust ucontext layout for purecap ABI and add make/get/set/swapcontext
    implementations accordingly.
    
    Note: mcontext layout follows the linux sigcontext struct, in userspace
    *context functions rely on the c registers stored in the extension area
    and ignore the mcontext fields for x registers.

Diff:
---
 sysdeps/unix/sysv/linux/aarch64/bits/procfs.h      |   5 +
 .../unix/sysv/linux/aarch64/morello/getcontext.S   | 121 +++++++++++++++++++
 .../unix/sysv/linux/aarch64/morello/makecontext.c  |  80 +++++++++++++
 .../unix/sysv/linux/aarch64/morello/setcontext.S   | 133 +++++++++++++++++++++
 .../unix/sysv/linux/aarch64/morello/swapcontext.S  | 120 +++++++++++++++++++
 sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h     |   4 +
 sysdeps/unix/sysv/linux/aarch64/sys/user.h         |  10 ++
 .../unix/sysv/linux/aarch64/ucontext-internal.h    |   5 +
 sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym     |  15 +++
 9 files changed, 493 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/procfs.h b/sysdeps/unix/sysv/linux/aarch64/bits/procfs.h
index 154fb95e66..596b95e333 100644
--- a/sysdeps/unix/sysv/linux/aarch64/bits/procfs.h
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/procfs.h
@@ -33,3 +33,8 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 
 /* Register set for the floating-point registers.  */
 typedef struct user_fpsimd_struct elf_fpregset_t;
+
+#ifdef __CHERI_PURE_CAPABILITY__
+/* Register set for the capability registers.  */
+typedef struct user_morello_struct elf_cregset_t;
+#endif
diff --git a/sysdeps/unix/sysv/linux/aarch64/morello/getcontext.S b/sysdeps/unix/sysv/linux/aarch64/morello/getcontext.S
new file mode 100644
index 0000000000..217ca28285
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/morello/getcontext.S
@@ -0,0 +1,121 @@
+/* Save current context.
+
+   Copyright (C) 2009-2022 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/>.  */
+
+#include <sysdep.h>
+#include "ucontext_i.h"
+#include "ucontext-internal.h"
+
+/* int getcontext (ucontext_t *ucp)
+
+   Returns 0 on success -1 and errno on failure.
+ */
+
+	.text
+
+ENTRY(__getcontext)
+	/* For Morello, we will save only the capability registers. These are saved
+	   in a special area in the context extension block after the FPSIMD
+	   context.  */
+	add	c9, c0, #oEXTENSION + FPSIMD_CONTEXT_SIZE
+
+	/* Write the context extension morello header.  */
+	mov	w3, #(MORELLO_MAGIC & 0xffff)
+	movk	w3, #(MORELLO_MAGIC >> 16), lsl #16
+	str	w3, [c9, #oCHEAD + oMAGIC]
+	mov	w3, #MORELLO_CONTEXT_SIZE
+	str	w3, [c9, #oCHEAD + oSIZE]
+
+	add	c10, c9, #oC0
+	/* The saved context will return to the getcontext() call point
+	   with a return value of 0 */
+	str	czr,	  [c10, 0 * SZCREG]
+
+	stp	c18, c19, [c10, 18 * SZCREG]
+	stp	c20, c21, [c10, 20 * SZCREG]
+	stp	c22, c23, [c10, 22 * SZCREG]
+	stp	c24, c25, [c10, 24 * SZCREG]
+	stp	c26, c27, [c10, 26 * SZCREG]
+	stp	c28, c29, [c10, 28 * SZCREG]
+	str     c30,      [c10, 30 * SZCREG]
+
+	/* Place LR into the saved PC, this will ensure that when
+	   switching to this saved context with setcontext() control
+	   will pass back to the caller of getcontext(), we have
+	   already arrange to return the appropriate return value in x0
+	   above.  */
+	str	c30, [c9, oPCC]
+
+	/* Save the current CSP */
+	mov	c2, csp
+	str     c2, [c9, oCSP]
+
+	/* Initialize the pstate.  */
+	str	xzr, [c0, oPSTATE]
+
+	/* Figure out where to place the first context extension
+	   block.  */
+	add     c2, c0, #oEXTENSION
+
+	/* Write the context extension fpsimd header.  */
+	mov	w3, #(FPSIMD_MAGIC & 0xffff)
+	movk	w3, #(FPSIMD_MAGIC >> 16), lsl #16
+	str	w3, [c2, #oHEAD + oMAGIC]
+	mov	w3, #FPSIMD_CONTEXT_SIZE
+	str	w3, [c2, #oHEAD + oSIZE]
+
+	/* Fill in the FP SIMD context.  */
+	add	c3, c2, #oV0 + 8 * SZVREG
+	stp	 q8,  q9, [c3], # 2 * SZVREG
+	stp	q10, q11, [c3], # 2 * SZVREG
+	stp	q12, q13, [c3], # 2 * SZVREG
+	stp	q14, q15, [c3], # 2 * SZVREG
+
+	add	c3, c2, oFPSR
+
+	mrs	x4, fpsr
+	str	w4, [c3]
+
+	mrs	x4, fpcr
+	str	w4, [c3, oFPCR - oFPSR]
+
+	/* Write the termination context extension header after the Morello
+	   context.  */
+	add	c2, c2, #FPSIMD_CONTEXT_SIZE + MORELLO_CONTEXT_SIZE
+	str	wzr, [c2, #oHEAD + oMAGIC]
+	str	wzr, [c2, #oHEAD + oSIZE]
+
+	/* Grab the signal mask */
+	/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
+	add	c2, c0, #UCONTEXT_SIGMASK
+	mov	x0, SIG_BLOCK
+	mov	x1, 0
+	mov	x3, _NSIG8
+	mov	x8, SYS_ify (rt_sigprocmask)
+	svc	0
+	cbnz	x0, 1f
+
+	/* Return 0 for success */
+	mov	x0, 0
+	RET
+1:
+	b	C_SYMBOL_NAME(__syscall_error)
+
+	PSEUDO_END (__getcontext)
+weak_alias (__getcontext, getcontext)
diff --git a/sysdeps/unix/sysv/linux/aarch64/morello/makecontext.c b/sysdeps/unix/sysv/linux/aarch64/morello/makecontext.c
new file mode 100644
index 0000000000..3bbfe85887
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/morello/makecontext.c
@@ -0,0 +1,80 @@
+/* Create new context.
+   Copyright (C) 2002-2022 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/>.  */
+
+#include <sysdep.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+#include <ucontext.h>
+#include <asm/sigcontext.h>
+#include "ucontext-internal.h"
+
+/* makecontext sets up a stack and the registers for the
+   user context.  The stack looks like this:
+
+               +-----------------------+
+	       | padding as required   |
+               +-----------------------+
+    sp ->      | parameter 7-n         |
+               +-----------------------+
+
+   The registers are set up like this:
+     %c0 .. %c7: parameter 1 to 8
+     %c19   : uc_link
+     %csp   : stack pointer.
+*/
+
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+  extern void __startcontext (void);
+  uint64_t *sp;
+  va_list ap;
+  int i;
+  struct morello_context *c_context;
+
+  sp = (uint64_t *)
+    ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
+
+  /* Allocate stack arguments.  */
+  sp -= argc < 8 ? 0 : argc - 8;
+
+  /* Keep the stack aligned.  */
+  sp = (uint64_t *) (((uintptr_t) sp) & -16L);
+
+  c_context = (void *) (ucp->uc_mcontext.__reserved
+			+ sizeof (struct fpsimd_context));
+
+  c_context->cregs[19] = (uintptr_t) ucp->uc_link;
+  c_context->csp = (uintptr_t) sp;
+  c_context->pcc = (uintptr_t) func;
+  c_context->cregs[29] = (uintptr_t) 0;
+  c_context->cregs[30] = (uintptr_t) &__startcontext;
+
+  va_start (ap, argc);
+  for (i = 0; i < argc; ++i)
+    if (i < 8)
+      c_context->cregs[i] = va_arg (ap, uint64_t);
+    else
+      sp[i - 8] = va_arg (ap, uint64_t);
+
+  va_end (ap);
+}
+
+weak_alias (__makecontext, makecontext)
diff --git a/sysdeps/unix/sysv/linux/aarch64/morello/setcontext.S b/sysdeps/unix/sysv/linux/aarch64/morello/setcontext.S
new file mode 100644
index 0000000000..3556d783fc
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/morello/setcontext.S
@@ -0,0 +1,133 @@
+/* Set current context.
+
+   Copyright (C) 2009-2022 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/>.  */
+
+#include <sysdep.h>
+#include "ucontext_i.h"
+#include "ucontext-internal.h"
+
+/*  int __setcontext (const ucontext_t *ucp)
+
+  Restores the machine context in UCP and thereby resumes execution
+  in that context.
+
+  This implementation is intended to be used for *synchronous* context
+  switches only.  Therefore, it does not have to restore anything
+  other than the PRESERVED state.  */
+
+	.text
+
+ENTRY (__setcontext)
+	/* Save a copy of UCP.  */
+	mov	c9, c0
+
+	/* Set the signal mask with
+	   rt_sigprocmask (SIG_SETMASK, mask, NULL, _NSIG/8).  */
+	mov	x0, #SIG_SETMASK
+	add	c1, c9, #UCONTEXT_SIGMASK
+	mov	x2, #0
+	mov	x3, #_NSIG8
+	mov	x8, SYS_ify (rt_sigprocmask)
+	svc	0
+	cbz	x0, 1f
+	b	C_SYMBOL_NAME (__syscall_error)
+1:
+	/* Restore the capability registers. For Morello, they are saved after the
+	   FPSIMD context.  */
+	mov	c0, c9
+	cfi_def_cfa (c0, 0)
+	cfi_offset (c18, oC0 + 18 * SZCREG)
+	cfi_offset (c19, oC0 + 19 * SZCREG)
+	cfi_offset (c20, oC0 + 20 * SZCREG)
+	cfi_offset (c21, oC0 + 21 * SZCREG)
+	cfi_offset (c22, oC0 + 22 * SZCREG)
+	cfi_offset (c23, oC0 + 23 * SZCREG)
+	cfi_offset (c24, oC0 + 24 * SZCREG)
+	cfi_offset (c25, oC0 + 25 * SZCREG)
+	cfi_offset (c26, oC0 + 26 * SZCREG)
+	cfi_offset (c27, oC0 + 27 * SZCREG)
+	cfi_offset (c28, oC0 + 28 * SZCREG)
+	cfi_offset (c29, oC0 + 29 * SZCREG)
+	cfi_offset (c30, oC0 + 30 * SZCREG)
+
+	cfi_offset ( d8, oV0 + 8 * SZVREG)
+	cfi_offset ( d9, oV0 + 9 * SZVREG)
+	cfi_offset (d10, oV0 + 10 * SZVREG)
+	cfi_offset (d11, oV0 + 11 * SZVREG)
+	cfi_offset (d12, oV0 + 12 * SZVREG)
+	cfi_offset (d13, oV0 + 13 * SZVREG)
+	cfi_offset (d14, oV0 + 14 * SZVREG)
+	cfi_offset (d15, oV0 + 15 * SZVREG)
+
+	add	c9, c0, #oEXTENSION + FPSIMD_CONTEXT_SIZE
+	add	c10, c9, #oC0
+	ldp	c18, c19, [c10, 18 * SZCREG]
+	ldp	c20, c21, [c10, 20 * SZCREG]
+	ldp	c22, c23, [c10, 22 * SZCREG]
+	ldp	c24, c25, [c10, 24 * SZCREG]
+	ldp	c26, c27, [c10, 26 * SZCREG]
+	ldp	c28, c29, [c10, 28 * SZCREG]
+	ldr     c30,      [c10, 30 * SZCREG]
+	ldr     c2, [c9, oCSP]
+	mov	csp, c2
+
+	/* Check for FP SIMD context.  We don't support restoring
+	   contexts created by the kernel, so this context must have
+	   been created by getcontext.  Hence we can rely on the
+	   first extension block being the FP SIMD context.  */
+	add     c2, c0, #oEXTENSION
+
+	mov	w3, #(FPSIMD_MAGIC & 0xffff)
+	movk	w3, #(FPSIMD_MAGIC >> 16), lsl #16
+	ldr	w1, [c2, #oHEAD + oMAGIC]
+	cmp	w1, w3
+	b.ne	2f
+
+	/* Restore the FP SIMD context.  */
+	add	c3, c2, #oV0 + 8 * SZVREG
+	ldp	 q8,  q9, [c3], #2 * SZVREG
+	ldp	q10, q11, [c3], #2 * SZVREG
+	ldp	q12, q13, [c3], #2 * SZVREG
+	ldp	q14, q15, [c3], #2 * SZVREG
+
+	add	c3, c2, oFPSR
+
+	ldr	w4, [c3]
+	msr	fpsr, x4
+
+	ldr	w4, [c3, oFPCR - oFPSR]
+	msr	fpcr, x4
+
+2:
+	ldr     c16, [c9, oPCC]
+	/* Restore arg registers.  */
+	ldp	c2, c3, [c10, 2 * SZCREG]
+	ldp	c4, c5, [c10, 4 * SZCREG]
+	ldp	c6, c7, [c10, 6 * SZCREG]
+	ldp	c0, c1, [c10, 0 * SZCREG]
+	/* Jump to the new pc value.  */
+	br	c16
+PSEUDO_END (__setcontext)
+weak_alias (__setcontext, setcontext)
+
+ENTRY (__startcontext)
+	mov	c0, c19
+	cbnz	x0, __setcontext
+1:	b       HIDDEN_JUMPTARGET (exit)
+END (__startcontext)
diff --git a/sysdeps/unix/sysv/linux/aarch64/morello/swapcontext.S b/sysdeps/unix/sysv/linux/aarch64/morello/swapcontext.S
new file mode 100644
index 0000000000..90e4eca413
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/morello/swapcontext.S
@@ -0,0 +1,120 @@
+/* Modify saved context.
+
+   Copyright (C) 2009-2022 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/>.  */
+
+#include <sysdep.h>
+
+#include "ucontext_i.h"
+#include "ucontext-internal.h"
+
+/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */
+
+	.text
+ENTRY(__swapcontext)
+	/* Set the value returned when swapcontext() returns in this context.
+	   And set up x1 to become the return address of the caller, so we
+	   can return there with a normal RET instead of an indirect jump.  */
+
+	/* For Morello, the capability registers are located in after the FPSIMD
+	   context.  */
+	add	c9, c0, #oEXTENSION + FPSIMD_CONTEXT_SIZE
+
+	/* Write the context extension morello header.  */
+	mov	w3, #(MORELLO_MAGIC & 0xffff)
+	movk	w3, #(MORELLO_MAGIC >> 16), lsl #16
+	str	w3, [c9, #oCHEAD + oMAGIC]
+	mov	w3, #MORELLO_CONTEXT_SIZE
+	str	w3, [c9, #oCHEAD + oSIZE]
+
+	add	c10, c9, #oC0
+	stp	czr, c30, [c10, 0 * SZCREG]
+	/* Arrange the oucp context to return to 2f.  */
+	adr	c30, 2f
+
+	stp	c18, c19, [c10, 18 * SZCREG]
+	stp	c20, c21, [c10, 20 * SZCREG]
+	stp	c22, c23, [c10, 22 * SZCREG]
+	stp	c24, c25, [c10, 24 * SZCREG]
+	stp	c26, c27, [c10, 26 * SZCREG]
+	stp	c28, c29, [c10, 28 * SZCREG]
+	str     c30,      [c10, 30 * SZCREG]
+	str     c30,      [c9, oPCC]
+	mov	c11, csp
+	str     c11,       [c9, oCSP]
+
+	/* Figure out where to place the fpsimd context extension
+	   block.  */
+	add     c9, c0, #oEXTENSION
+
+	/* Write the context extension fpsimd header.  */
+	mov	w3, #(FPSIMD_MAGIC & 0xffff)
+	movk	w3, #(FPSIMD_MAGIC >> 16), lsl #16
+	str	w3, [c9, #oHEAD + oMAGIC]
+	mov	w3, #FPSIMD_CONTEXT_SIZE
+	str	w3, [c9, #oHEAD + oSIZE]
+
+	/* Fill in the FP SIMD context.  */
+	add	c10, c9, #oV0 + 8 * SZVREG
+	stp	 q8,  q9, [c10], #2 * SZVREG
+	stp	q10, q11, [c10], #2 * SZVREG
+	stp	q12, q13, [c10], #2 * SZVREG
+	stp	q14, q15, [c10], #2 * SZVREG
+
+	add	c10, c9, #oFPSR
+	mrs	x4, fpsr
+	str	w4, [c10, #oFPSR - oFPSR]
+	mrs	x4, fpcr
+	str	w4, [c10, #oFPCR - oFPSR]
+
+	/* Write the termination context extension header after the Morello
+	   context.  */
+	add	c9, c9, #FPSIMD_CONTEXT_SIZE + MORELLO_CONTEXT_SIZE
+	str	wzr, [c9, #oHEAD + oMAGIC]
+	str	wzr, [c9, #oHEAD + oSIZE]
+
+	/* Preserve ucp.  */
+	mov	c11, c1
+
+	/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask,
+			   _NSIG8) */
+	/* Grab the signal mask */
+	/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
+	add	c2, c0, #UCONTEXT_SIGMASK
+	mov	x0, SIG_BLOCK
+	mov	x1, 0
+	mov	x3, _NSIG8
+	mov	x8, SYS_ify (rt_sigprocmask)
+	svc	0
+	cbnz	x0, 1f
+
+	mov     c15, c30
+	mov	c0, c11
+	bl	JUMPTARGET (__setcontext)
+	mov     c30, c15
+	RET
+
+1:
+	b	C_SYMBOL_NAME(__syscall_error)
+2:
+	/* The oucp context is restored here via an indirect branch,
+	   x1 must be restored too which has the real return address.  */
+	mov	c30, c1
+	RET
+PSEUDO_END (__swapcontext)
+weak_alias (__swapcontext, swapcontext)
diff --git a/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h b/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h
index fe91db68e8..cd39a2272b 100644
--- a/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h
+++ b/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h
@@ -43,6 +43,10 @@ typedef elf_gregset_t gregset_t;
 
 /* Structure to describe FPU registers.  */
 typedef elf_fpregset_t	fpregset_t;
+# ifdef __CHERI_PURE_CAPABILITY__
+/* Structure to describe capability registers.  */
+typedef elf_cregset_t cregset_t;
+# endif
 #endif
 
 /* Context to describe whole processor state.  This only describes
diff --git a/sysdeps/unix/sysv/linux/aarch64/sys/user.h b/sysdeps/unix/sysv/linux/aarch64/sys/user.h
index 32fbfd5f1a..e228838bc7 100644
--- a/sysdeps/unix/sysv/linux/aarch64/sys/user.h
+++ b/sysdeps/unix/sysv/linux/aarch64/sys/user.h
@@ -34,4 +34,14 @@ struct user_fpsimd_struct
   unsigned int fpcr;
 };
 
+# ifdef __CHERI_PURE_CAPABILITY__
+struct user_morello_struct
+{
+  __uintcap_t cregs[31];
+  __uintcap_t csp;
+  __uintcap_t rcsp;
+  __uintcap_t pcc;
+};
+# endif
+
 #endif
diff --git a/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h b/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h
index 685d41ca04..429a4c1035 100644
--- a/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h
+++ b/sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h
@@ -23,6 +23,11 @@
 /* Size of an X regiser in bytes. */
 #define SZREG                8
 
+#ifdef __CHERI_PURE_CAPABILITY__
+/* Size of a C register in bytes. */
+# define SZCREG             16
+#endif
+
 /* Size of a V register in bytes. */
 #define SZVREG              16
 
diff --git a/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym b/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym
index ab3930c173..78022326af 100644
--- a/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym
+++ b/sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym
@@ -18,6 +18,9 @@ RT_SIGFRAME_UCONTEXT		rt_sigframe (uc)
 
 RT_SIGFRAME_SIZE		sizeof (struct kernel_rt_sigframe)
 FPSIMD_CONTEXT_SIZE             sizeof (struct fpsimd_context)
+#ifdef __CHERI_PURE_CAPABILITY__
+MORELLO_CONTEXT_SIZE		sizeof (struct morello_context)
+#endif
 
 #define ucontext(member)	offsetof (ucontext_t, member)
 #define stack(member)		ucontext (uc_stack.member)
@@ -53,3 +56,15 @@ oMAGIC                          aarch64_ctx (magic)
 oSIZE                           aarch64_ctx (size)
 
 FPSIMD_MAGIC
+
+#ifdef __CHERI_PURE_CAPABILITY__
+#define morello_context(member) offsetof (struct morello_context, member)
+
+oCHEAD				morello_context (head)
+oC0				morello_context (cregs)
+oCSP				morello_context (csp)
+oRCSP				morello_context (rcsp)
+oPCC				morello_context (pcc)
+
+MORELLO_MAGIC
+#endif

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-11-23 14:47 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-05 19:36 [glibc/arm/morello/main] aarch64: morello: add purecap ucontext support Szabolcs Nagy
2022-10-26 15:18 Szabolcs Nagy
2022-10-27 13:57 Szabolcs Nagy
2022-11-23 14:47 Szabolcs Nagy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).