]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
aarch64: morello: add purecap ucontext support
authorCarlos Eduardo Seo <carlos.seo@arm.com>
Thu, 27 May 2021 20:49:20 +0000 (17:49 -0300)
committerSzabolcs Nagy <szabolcs.nagy@arm.com>
Thu, 27 Oct 2022 13:46:53 +0000 (14:46 +0100)
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.

sysdeps/unix/sysv/linux/aarch64/bits/procfs.h
sysdeps/unix/sysv/linux/aarch64/morello/getcontext.S [new file with mode: 0644]
sysdeps/unix/sysv/linux/aarch64/morello/makecontext.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/aarch64/morello/setcontext.S [new file with mode: 0644]
sysdeps/unix/sysv/linux/aarch64/morello/swapcontext.S [new file with mode: 0644]
sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h
sysdeps/unix/sysv/linux/aarch64/sys/user.h
sysdeps/unix/sysv/linux/aarch64/ucontext-internal.h
sysdeps/unix/sysv/linux/aarch64/ucontext_i.sym

index 154fb95e660bd69342d2dcd3d0aec0e73d3c96f1..596b95e333bf80d98629965be3390b2b8896124c 100644 (file)
@@ -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 (file)
index 0000000..217ca28
--- /dev/null
@@ -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 (file)
index 0000000..3bbfe85
--- /dev/null
@@ -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 (file)
index 0000000..3556d78
--- /dev/null
@@ -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 (file)
index 0000000..90e4eca
--- /dev/null
@@ -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)
index fe91db68e882c7be59ffbeffb22927879be0ff06..cd39a2272b17a36e2ba0788de717080c1aa501ba 100644 (file)
@@ -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
index 32fbfd5f1a5fe16b0c5f67fbed0f787ac8216b7e..e228838bc7d8b7f861b79b4982c15b6063470808 100644 (file)
@@ -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
index 685d41ca04ce09d0d0bd9564d261664d00a5adc9..429a4c1035215208016ebc0a5f35b8e62ba1514e 100644 (file)
 /* 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
 
index ab3930c173c87c620447d1578f21322ea9fc11b8..78022326af92b053a98af5be8b2c5832eccd42bb 100644 (file)
@@ -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