diff --git a/arch/ppc64/defs.h b/arch/ppc64/defs.h new file mode 100644 index 0000000..247ee10 --- /dev/null +++ b/arch/ppc64/defs.h @@ -0,0 +1,62 @@ +#ifndef __ARCH_PPC_DEFS_H +#define __ARCH_PPC_DEFS_H + +#define REG_R0 (0) +#define REG_R1 (1) +#define REG_R2 (2) +#define REG_R3 (3) +#define REG_R4 (4) +#define REG_R5 (5) +#define REG_R6 (6) +#define REG_R7 (7) +#define REG_R8 (8) +#define REG_R9 (9) +#define REG_R10 (10) +#define REG_R11 (11) +#define REG_R12 (12) +#define REG_R13 (13) +#define REG_R14 (14) +#define REG_R15 (15) +#define REG_R16 (16) +#define REG_R17 (17) +#define REG_R18 (18) +#define REG_R19 (19) +#define REG_R20 (20) +#define REG_R21 (21) +#define REG_R22 (22) +#define REG_R23 (23) +#define REG_R24 (24) +#define REG_R25 (25) +#define REG_R26 (26) +#define REG_R27 (27) +#define REG_R28 (28) +#define REG_R29 (29) +#define REG_R30 (30) +#define REG_R31 (31) +#define REG_R32 (32) +#define REG_R33 (33) +#define REG_R34 (34) +#define REG_R35 (35) +#define REG_R36 (36) +#define REG_R37 (37) +#define REG_R38 (38) +#define REG_R39 (39) +#define REG_R40 (40) +#define REG_R41 (41) +#define REG_R42 (42) +#define REG_R43 (43) +#define REG_R44 (44) +#define REG_R45 (45) +#define REG_R46 (46) +#define REG_R47 (47) + +/* sp register is actually %r1 */ +#define REG_SP REG_R1 + +/* nip register is actually %srr0 (r32) */ +#define REG_NIP REG_R32 + +/* lnk register is actually r32 */ +#define REG_LNK REG_R36 + +#endif diff --git a/arch/ppc64/getcontext.c b/arch/ppc64/getcontext.c new file mode 100644 index 0000000..5da9dfb --- /dev/null +++ b/arch/ppc64/getcontext.c @@ -0,0 +1,45 @@ +/* + * 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 +#include + + +int +__getcontext(ucontext_t *ucp) +{ +#ifdef SYS_swapcontext + int r; + + r = syscall(SYS_swapcontext, ucp, NULL, sizeof(ucontext_t)); + if (r < 0) + { + errno = -r; + return -1; + } + + return 0; +#else + errno = ENOSYS; + return -1; +#endif +} + + +extern __typeof(__getcontext) getcontext __attribute__((weak, __alias__("__getcontext"))); diff --git a/arch/ppc64/makecontext.c b/arch/ppc64/makecontext.c new file mode 100644 index 0000000..96ed477 --- /dev/null +++ b/arch/ppc64/makecontext.c @@ -0,0 +1,75 @@ +/* + * 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 "defs.h" + + +extern void __start_context(void); + + +void +__makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) +{ + greg_t *sp, *argp; + va_list va; + int i; + unsigned int uc_link, stack_args; + + stack_args = argc > 8 ? argc - 8 : 0; + uc_link = stack_args + 1; + + sp = (greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); + sp -= (uc_link + 1); + sp = (greg_t *) (((uintptr_t) sp & -16L)); + + ucp->uc_mcontext.gp_regs[REG_NIP] = (uintptr_t) func; + ucp->uc_mcontext.gp_regs[REG_LNK] = (uintptr_t) &__start_context; + ucp->uc_mcontext.gp_regs[REG_R31] = (uintptr_t) ucp->uc_link; + ucp->uc_mcontext.gp_regs[REG_SP] = (uintptr_t) sp; + + sp[0] = (uintptr_t) &__start_context; + sp[uc_link] = (uintptr_t) ucp->uc_link; + argp = &sp[2]; + + va_start(va, argc); + + for (i = 0; i < argc; i++) + switch (i) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + ucp->uc_mcontext.gp_regs[i + 3] = va_arg (va, greg_t); + break; + default: + *argp++ = va_arg (va, greg_t); + break; + } + + va_end(va); +} + + +extern __typeof(__makecontext) makecontext __attribute__((weak, __alias__("__makecontext"))); diff --git a/arch/ppc64/setcontext.c b/arch/ppc64/setcontext.c new file mode 100644 index 0000000..59c65b4 --- /dev/null +++ b/arch/ppc64/setcontext.c @@ -0,0 +1,45 @@ +/* + * 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 +#include + + +int +__setcontext(const ucontext_t *ucp) +{ +#ifdef SYS_swapcontext + int r; + + r = syscall(SYS_swapcontext, NULL, (void *) ucp, sizeof(ucontext_t)); + if (r < 0) + { + errno = -r; + return -1; + } + + return r; +#else + errno = ENOSYS; + return -1; +#endif +} + + +extern __typeof(__setcontext) setcontext __attribute__((weak, __alias__("__setcontext"))); diff --git a/arch/ppc64/startcontext.S b/arch/ppc64/startcontext.S new file mode 100644 index 0000000..5abf43c --- /dev/null +++ b/arch/ppc64/startcontext.S @@ -0,0 +1,24 @@ +/* + * 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; +.hidden __start_context; +__start_context: + /* get the proper context into position and test for NULL */ + mr. 3,31 + beq hosed + bl __setcontext + nop + +hosed: + b exit@GOT + nop diff --git a/arch/ppc64/swapcontext.c b/arch/ppc64/swapcontext.c new file mode 100644 index 0000000..af14bc2 --- /dev/null +++ b/arch/ppc64/swapcontext.c @@ -0,0 +1,45 @@ +/* + * 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 +#include + + +int +__swapcontext(ucontext_t *oucp, const ucontext_t *ucp) +{ +#ifdef SYS_swapcontext + int r; + + r = syscall(SYS_swapcontext, oucp, ucp, sizeof(ucontext_t)); + if (r < 0) + { + errno = -r; + return -1; + } + + return r; +#else + errno = ENOSYS; + return -1; +#endif +} + + +extern __typeof(__swapcontext) swapcontext __attribute__((weak, __alias__("__swapcontext")));