From 13283f5ebab2e3cc9b7276a1af6c659ae6b79190 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Wed, 31 Jan 2018 21:23:18 +0000 Subject: [PATCH] arch: add aarch64 port --- README.md | 1 + arch/aarch64/defs.h | 18 +++++++++++ arch/aarch64/getcontext.S | 54 ++++++++++++++++++++++++++++++++ arch/aarch64/makecontext.c | 57 ++++++++++++++++++++++++++++++++++ arch/aarch64/setcontext.S | 47 ++++++++++++++++++++++++++++ arch/aarch64/startcontext.S | 20 ++++++++++++ arch/aarch64/swapcontext.S | 61 +++++++++++++++++++++++++++++++++++++ 7 files changed, 258 insertions(+) create mode 100644 arch/aarch64/defs.h create mode 100644 arch/aarch64/getcontext.S create mode 100644 arch/aarch64/makecontext.c create mode 100644 arch/aarch64/setcontext.S create mode 100644 arch/aarch64/startcontext.S create mode 100644 arch/aarch64/swapcontext.S diff --git a/README.md b/README.md index 177aae8..6e27635 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,4 @@ Right now these archs are supported: * x86_64 * armv6+ (`arm`) + * aarch64 diff --git a/arch/aarch64/defs.h b/arch/aarch64/defs.h new file mode 100644 index 0000000..15f61d9 --- /dev/null +++ b/arch/aarch64/defs.h @@ -0,0 +1,18 @@ +#ifndef __ARCH_AARCH64_DEFS_H +#define __ARCH_AARCH64_DEFS_H + +#define REGSZ 8 +#define R0_OFFSET 184 +#define SP_OFFSET 432 +#define PC_OFFSET 440 +#define PSTATE_OFFSET 448 + +#ifndef FPSIMD_MAGIC +# define FPSIMD_MAGIC 0x46508001 +#endif + +#ifndef ESR_MAGIC +# define ESR_MAGIC 0x45535201 +#endif + +#endif diff --git a/arch/aarch64/getcontext.S b/arch/aarch64/getcontext.S new file mode 100644 index 0000000..3fd3645 --- /dev/null +++ b/arch/aarch64/getcontext.S @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018 William Pitcock + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#include "defs.h" + +.globl __getcontext; +__getcontext: + str xzr, [x0, #R0_OFFSET + (0 * REGSZ)] + + /* save GPRs */ + stp x0, x1, [x0, #R0_OFFSET + (0 * REGSZ)] + stp x2, x3, [x0, #R0_OFFSET + (2 * REGSZ)] + stp x4, x5, [x0, #R0_OFFSET + (4 * REGSZ)] + stp x6, x7, [x0, #R0_OFFSET + (6 * REGSZ)] + stp x8, x9, [x0, #R0_OFFSET + (8 * REGSZ)] + stp x10, x11, [x0, #R0_OFFSET + (10 * REGSZ)] + stp x12, x13, [x0, #R0_OFFSET + (12 * REGSZ)] + stp x14, x15, [x0, #R0_OFFSET + (14 * REGSZ)] + stp x16, x17, [x0, #R0_OFFSET + (16 * REGSZ)] + stp x18, x19, [x0, #R0_OFFSET + (18 * REGSZ)] + stp x20, x21, [x0, #R0_OFFSET + (20 * REGSZ)] + stp x22, x23, [x0, #R0_OFFSET + (22 * REGSZ)] + stp x24, x25, [x0, #R0_OFFSET + (24 * REGSZ)] + stp x26, x27, [x0, #R0_OFFSET + (26 * REGSZ)] + stp x28, x29, [x0, #R0_OFFSET + (28 * REGSZ)] + str x30, [x0, #R0_OFFSET + (30 * REGSZ)] + + /* save current program counter in link register */ + str x30, [x0, #PC_OFFSET] + + /* save current stack pointer */ + mov x2, sp + str x2, [x0, #SP_OFFSET] + + /* save pstate */ + str xzr, [x0, #PSTATE_OFFSET] + + /* TODO: SIMD / FPRs */ + + mov x0, #0 + ret + + +.weak getcontext; +getcontext = __getcontext; diff --git a/arch/aarch64/makecontext.c b/arch/aarch64/makecontext.c new file mode 100644 index 0000000..40923c8 --- /dev/null +++ b/arch/aarch64/makecontext.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018 William Pitcock + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include "defs.h" + + +extern void __start_context(void); + + +void +__makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) +{ + unsigned long *sp; + unsigned long *regp; + va_list va; + int i; + + sp = (unsigned long *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); + sp -= argc < 8 ? 0 : argc - 8; + sp = (unsigned long *) (((uintptr_t) sp & -16L)); + + ucp->uc_mcontext.sp = (uintptr_t) sp; + ucp->uc_mcontext.pc = (uintptr_t) func; + ucp->uc_mcontext.regs[19] = (uintptr_t) ucp->uc_link; + ucp->uc_mcontext.regs[30] = (uintptr_t) &__start_context; + + va_start(va, argc); + + regp = &(ucp->uc_mcontext.regs[0]); + + for (i = 0; (i < argc && i < 8); i++) + *regp++ = va_arg (va, unsigned long); + + for (; i < argc; i++) + *sp++ = va_arg (va, unsigned long); + + va_end(va); +} + + +extern __typeof(__makecontext) makecontext __attribute__((weak, __alias__("__makecontext"))); diff --git a/arch/aarch64/setcontext.S b/arch/aarch64/setcontext.S new file mode 100644 index 0000000..e59cc26 --- /dev/null +++ b/arch/aarch64/setcontext.S @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018 William Pitcock + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#include "defs.h" + +.globl __setcontext; +__setcontext: + /* restore GPRs */ + ldp x18, x19, [x0, #R0_OFFSET + (18 * REGSZ)] + ldp x20, x21, [x0, #R0_OFFSET + (20 * REGSZ)] + ldp x22, x23, [x0, #R0_OFFSET + (22 * REGSZ)] + ldp x24, x25, [x0, #R0_OFFSET + (24 * REGSZ)] + ldp x26, x27, [x0, #R0_OFFSET + (26 * REGSZ)] + ldp x28, x29, [x0, #R0_OFFSET + (28 * REGSZ)] + ldr x30, [x0, #R0_OFFSET + (30 * REGSZ)] + + /* save current stack pointer */ + ldr x2, [x0, #SP_OFFSET] + mov sp, x2 + + /* TODO: SIMD / FPRs */ + + /* save current program counter in link register */ + ldr x16, [x0, #PC_OFFSET] + + /* restore args */ + ldp x2, x3, [x0, #R0_OFFSET + (2 * REGSZ)] + ldp x4, x5, [x0, #R0_OFFSET + (4 * REGSZ)] + ldp x6, x7, [x0, #R0_OFFSET + (6 * REGSZ)] + ldp x0, x1, [x0, #R0_OFFSET + (0 * REGSZ)] + + /* jump to new PC */ + br x16 + + +.weak setcontext; +setcontext = __setcontext; + diff --git a/arch/aarch64/startcontext.S b/arch/aarch64/startcontext.S new file mode 100644 index 0000000..4e757a1 --- /dev/null +++ b/arch/aarch64/startcontext.S @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2018 William Pitcock + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +.globl __start_context; +__start_context: + /* get the proper context into position and test for NULL */ + mov x0, x19 + cbnz x0, __setcontext + + /* something went wrong, exit */ + b exit diff --git a/arch/aarch64/swapcontext.S b/arch/aarch64/swapcontext.S new file mode 100644 index 0000000..e8eb13f --- /dev/null +++ b/arch/aarch64/swapcontext.S @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018 William Pitcock + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#include "defs.h" + +.globl __swapcontext; +__swapcontext: + str xzr, [x0, #R0_OFFSET + (0 * REGSZ)] + + /* save GPRs */ + stp x2, x3, [x0, #R0_OFFSET + (2 * REGSZ)] + stp x4, x5, [x0, #R0_OFFSET + (4 * REGSZ)] + stp x6, x7, [x0, #R0_OFFSET + (6 * REGSZ)] + stp x8, x9, [x0, #R0_OFFSET + (8 * REGSZ)] + stp x10, x11, [x0, #R0_OFFSET + (10 * REGSZ)] + stp x12, x13, [x0, #R0_OFFSET + (12 * REGSZ)] + stp x14, x15, [x0, #R0_OFFSET + (14 * REGSZ)] + stp x16, x17, [x0, #R0_OFFSET + (16 * REGSZ)] + stp x18, x19, [x0, #R0_OFFSET + (18 * REGSZ)] + stp x20, x21, [x0, #R0_OFFSET + (20 * REGSZ)] + stp x22, x23, [x0, #R0_OFFSET + (22 * REGSZ)] + stp x24, x25, [x0, #R0_OFFSET + (24 * REGSZ)] + stp x26, x27, [x0, #R0_OFFSET + (26 * REGSZ)] + stp x28, x29, [x0, #R0_OFFSET + (28 * REGSZ)] + str x30, [x0, #R0_OFFSET + (30 * REGSZ)] + + /* save current program counter in link register */ + str x30, [x0, #PC_OFFSET] + + /* save current stack pointer */ + mov x2, sp + str x2, [x0, #SP_OFFSET] + + /* save pstate */ + str xzr, [x0, #PSTATE_OFFSET] + + /* context to swap to is in x1 so... we move to x0 and call setcontext */ + /* store our link register in x28 */ + mov x28, x30 + + /* move x1 to x0 and call setcontext */ + mov x0, x1 + bl __setcontext + + /* hmm, we came back here try to return */ + mov x30, x28 + ret + + + +.weak swapcontext; +swapcontext = __swapcontext;