From 94216c60c43a30e39fbc4f347450768699c6c77c Mon Sep 17 00:00:00 2001 From: Bobby Bingham <koorogi@koorogi.info> Date: Mon, 1 Apr 2019 23:02:12 -0500 Subject: [PATCH] test ability to pass 10 args through makecontext --- test_libucontext.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/test_libucontext.c b/test_libucontext.c index 121cc3e..e5eac83 100644 --- a/test_libucontext.c +++ b/test_libucontext.c @@ -6,13 +6,32 @@ #include <stdio.h> #include <ucontext.h> #include <stdint.h> +#include <stdlib.h> #include <string.h> static ucontext_t ctx[3]; -static void f1 (void) { +static void check_arg(int actual, int expected) { + if (actual == expected) return; + fprintf(stderr, "argument has wrong value. got %d, expected %d.\n", actual, expected); + abort(); +} + + +static void f1 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) { + check_arg(a, 1); + check_arg(b, 2); + check_arg(c, 3); + check_arg(d, 4); + check_arg(e, 5); + check_arg(f, 6); + check_arg(g, 7); + check_arg(h, 8); + check_arg(i, 9); + check_arg(j, 10); + printf("start f1\n"); swapcontext(&ctx[1], &ctx[2]); printf("finish f1\n"); @@ -40,7 +59,7 @@ int main (int argc, const char *argv[]) { ctx[1].uc_stack.ss_sp = st1; ctx[1].uc_stack.ss_size = sizeof st1; ctx[1].uc_link = &ctx[0]; - makecontext(&ctx[1], f1, 0); + makecontext(&ctx[1], f1, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); getcontext(&ctx[2]); From cb59e7ee957b389578a3f973484ae3198f6cfed1 Mon Sep 17 00:00:00 2001 From: Bobby Bingham <koorogi@koorogi.info> Date: Mon, 1 Apr 2019 23:03:21 -0500 Subject: [PATCH] test calls to getcontext without makecontext --- test_libucontext.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test_libucontext.c b/test_libucontext.c index e5eac83..a4a9b4c 100644 --- a/test_libucontext.c +++ b/test_libucontext.c @@ -48,6 +48,7 @@ static void f2 (void) { int main (int argc, const char *argv[]) { char st1[8192]; char st2[8192]; + volatile int done = 0; /* poison each coroutine's stack memory for debugging purposes */ @@ -70,5 +71,16 @@ int main (int argc, const char *argv[]) { swapcontext(&ctx[0], &ctx[2]); + + + /* test ability to use getcontext/setcontext without makecontext */ + getcontext(&ctx[1]); + printf("done = %d\n", done); + if (done++ == 0) setcontext(&ctx[1]); + if (done != 2) { + fprintf(stderr, "wrong value for done. got %d, expected 2\n", done); + abort(); + } + return 0; } From b6a9b5e279123f16569e0fd9f8ff14ff04bed7a3 Mon Sep 17 00:00:00 2001 From: Bobby Bingham <koorogi@koorogi.info> Date: Fri, 5 Apr 2019 13:32:03 -0500 Subject: [PATCH] ppc32: fix stack alignment The stack should be 16-byte aligned, not 8 mod 16. --- arch/ppc/makecontext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ppc/makecontext.c b/arch/ppc/makecontext.c index c562ea5..1b9efdf 100644 --- a/arch/ppc/makecontext.c +++ b/arch/ppc/makecontext.c @@ -37,7 +37,7 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) 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) - 8); + sp = (greg_t *) ((uintptr_t) sp & -16L); ucp->uc_mcontext.gregs[REG_NIP] = (uintptr_t) func; ucp->uc_mcontext.gregs[REG_LNK] = (uintptr_t) &__start_context; From b9bd4045fb34f060d6cf37fc7da7ab13b91462de Mon Sep 17 00:00:00 2001 From: Bobby Bingham <koorogi@koorogi.info> Date: Fri, 5 Apr 2019 13:35:00 -0500 Subject: [PATCH] ppc32/64: fix back chain pointer The ABI states that sp[0] should point to the previous stack frame, or be zero if there is no previous stack frame. makecontext previously set this slot to point to the __start_context function, rather than to a valid stack frame. --- arch/ppc/makecontext.c | 2 +- arch/ppc64/makecontext.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/ppc/makecontext.c b/arch/ppc/makecontext.c index 1b9efdf..729f465 100644 --- a/arch/ppc/makecontext.c +++ b/arch/ppc/makecontext.c @@ -44,7 +44,7 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) ucp->uc_mcontext.gregs[REG_R31] = (uintptr_t) ucp->uc_link; ucp->uc_mcontext.gregs[REG_SP] = (uintptr_t) sp; - sp[0] = (uintptr_t) &__start_context; + sp[0] = 0; sp[uc_link] = (uintptr_t) ucp->uc_link; argp = &sp[2]; diff --git a/arch/ppc64/makecontext.c b/arch/ppc64/makecontext.c index 9d6b998..91fb579 100644 --- a/arch/ppc64/makecontext.c +++ b/arch/ppc64/makecontext.c @@ -45,7 +45,7 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) ucp->uc_mcontext.gp_regs[REG_ENTRY] = (uintptr_t) func; ucp->uc_mcontext.gp_regs[REG_R31] = (uintptr_t) ucp->uc_link; - sp[0] = (uintptr_t) &__start_context; + sp[0] = 0; sp[uc_link] = (uintptr_t) ucp->uc_link; argp = &sp[2]; From b500b054c7cf412a6042496afa08b4302f7ed929 Mon Sep 17 00:00:00 2001 From: Bobby Bingham <koorogi@koorogi.info> Date: Fri, 5 Apr 2019 13:38:36 -0500 Subject: [PATCH] ppc32/64: don't store uc_link on the stack This was previously stored either in the CR (ppc64) or LR (ppc32) save area of the stack, or to one of the parameter save slots. In either case, the saved value was unused. This value is also passed to __start_context via r31, so there's no need to pass it on the stack. --- arch/ppc/makecontext.c | 6 ++---- arch/ppc64/makecontext.c | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/arch/ppc/makecontext.c b/arch/ppc/makecontext.c index 729f465..2b7ea67 100644 --- a/arch/ppc/makecontext.c +++ b/arch/ppc/makecontext.c @@ -30,13 +30,12 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) greg_t *sp, *argp; va_list va; int i; - unsigned int uc_link, stack_args; + unsigned int 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 -= stack_args + 2; sp = (greg_t *) ((uintptr_t) sp & -16L); ucp->uc_mcontext.gregs[REG_NIP] = (uintptr_t) func; @@ -45,7 +44,6 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) ucp->uc_mcontext.gregs[REG_SP] = (uintptr_t) sp; sp[0] = 0; - sp[uc_link] = (uintptr_t) ucp->uc_link; argp = &sp[2]; va_start(va, argc); diff --git a/arch/ppc64/makecontext.c b/arch/ppc64/makecontext.c index 91fb579..b060371 100644 --- a/arch/ppc64/makecontext.c +++ b/arch/ppc64/makecontext.c @@ -30,13 +30,12 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) greg_t *sp, *argp; va_list va; int i; - unsigned int uc_link, stack_args; + unsigned int 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 -= stack_args + 2; sp = (greg_t *) (((uintptr_t) sp & -16L)); ucp->uc_mcontext.gp_regs[REG_NIP] = (uintptr_t) func; @@ -46,7 +45,6 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) ucp->uc_mcontext.gp_regs[REG_R31] = (uintptr_t) ucp->uc_link; sp[0] = 0; - sp[uc_link] = (uintptr_t) ucp->uc_link; argp = &sp[2]; va_start(va, argc); From 55168fcb1809dde45c99450f1f3be27716c473db Mon Sep 17 00:00:00 2001 From: Bobby Bingham <koorogi@koorogi.info> Date: Fri, 5 Apr 2019 13:57:53 -0500 Subject: [PATCH] ppc32/64: simplify storage of stack parameters The switch statement is simpler as an if/else, and removing the argp variable makes the code more symmetric between the register and stack parameter cases. --- arch/ppc/makecontext.c | 24 ++++++------------------ arch/ppc64/makecontext.c | 24 ++++++------------------ 2 files changed, 12 insertions(+), 36 deletions(-) diff --git a/arch/ppc/makecontext.c b/arch/ppc/makecontext.c index 2b7ea67..4a404a4 100644 --- a/arch/ppc/makecontext.c +++ b/arch/ppc/makecontext.c @@ -27,7 +27,7 @@ extern void __start_context(void); void __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) { - greg_t *sp, *argp; + greg_t *sp; va_list va; int i; unsigned int stack_args; @@ -44,27 +44,15 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) ucp->uc_mcontext.gregs[REG_SP] = (uintptr_t) sp; sp[0] = 0; - 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: + for (i = 0; i < argc; i++) { + if (i < 8) ucp->uc_mcontext.gregs[i + 3] = va_arg (va, greg_t); - break; - default: - *argp++ = va_arg (va, greg_t); - break; - } + else + sp[i-8 + 2] = va_arg (va, greg_t); + } va_end(va); } diff --git a/arch/ppc64/makecontext.c b/arch/ppc64/makecontext.c index b060371..962f98a 100644 --- a/arch/ppc64/makecontext.c +++ b/arch/ppc64/makecontext.c @@ -27,7 +27,7 @@ extern void __start_context(void); void __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) { - greg_t *sp, *argp; + greg_t *sp; va_list va; int i; unsigned int stack_args; @@ -45,27 +45,15 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) ucp->uc_mcontext.gp_regs[REG_R31] = (uintptr_t) ucp->uc_link; sp[0] = 0; - 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: + for (i = 0; i < argc; i++) { + if (i < 8) ucp->uc_mcontext.gp_regs[i + 3] = va_arg (va, greg_t); - break; - default: - *argp++ = va_arg (va, greg_t); - break; - } + else + sp[i-8 + 2] = va_arg (va, greg_t); + } va_end(va); } From 8ea5f548b9146ffeea2074a33a06bbbd07a74402 Mon Sep 17 00:00:00 2001 From: Bobby Bingham <koorogi@koorogi.info> Date: Fri, 5 Apr 2019 14:01:10 -0500 Subject: [PATCH] ppc64: fix makecontext with more than 8 parameters The ELFv2 ABI used on PPC64 differs from the ELFv1 ABI used on PPC32 here. On PPC64, once there are any parameters that need to be passed on the stack, space needs to be reserved on the stack to pass all parameters. Parameters 0-7 are still only passed by register, but if the callee needs to spill them, it can use the stack space reserved for the corresponding parameter to do so. --- arch/ppc64/makecontext.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/ppc64/makecontext.c b/arch/ppc64/makecontext.c index 962f98a..ea980e9 100644 --- a/arch/ppc64/makecontext.c +++ b/arch/ppc64/makecontext.c @@ -32,7 +32,7 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) int i; unsigned int stack_args; - stack_args = argc > 8 ? argc - 8 : 0; + stack_args = argc > 8 ? argc : 0; sp = (greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); sp -= stack_args + 2; @@ -52,7 +52,7 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) if (i < 8) ucp->uc_mcontext.gp_regs[i + 3] = va_arg (va, greg_t); else - sp[i-8 + 2] = va_arg (va, greg_t); + sp[i + 2] = va_arg (va, greg_t); } va_end(va); From a00a05ce2950ca3b306f8ccc3e817ea8cd675015 Mon Sep 17 00:00:00 2001 From: Bobby Bingham <koorogi@koorogi.info> Date: Fri, 5 Apr 2019 14:03:47 -0500 Subject: [PATCH] ppc64: fix incorrect position of parameters within stack frame On PPC64, there are 4 register-sized stack slots below the parameter save area, which is different from the 2 stack slots on PPC32. --- arch/ppc64/makecontext.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/ppc64/makecontext.c b/arch/ppc64/makecontext.c index ea980e9..a4c1bf9 100644 --- a/arch/ppc64/makecontext.c +++ b/arch/ppc64/makecontext.c @@ -35,7 +35,7 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) stack_args = argc > 8 ? argc : 0; sp = (greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); - sp -= stack_args + 2; + sp -= stack_args + 4; sp = (greg_t *) (((uintptr_t) sp & -16L)); ucp->uc_mcontext.gp_regs[REG_NIP] = (uintptr_t) func; @@ -52,7 +52,7 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) if (i < 8) ucp->uc_mcontext.gp_regs[i + 3] = va_arg (va, greg_t); else - sp[i + 2] = va_arg (va, greg_t); + sp[i + 4] = va_arg (va, greg_t); } va_end(va); From 40d07758a5677e8869d7a62a499236bb6ed01897 Mon Sep 17 00:00:00 2001 From: Bobby Bingham <koorogi@koorogi.info> Date: Fri, 5 Apr 2019 14:09:25 -0500 Subject: [PATCH] ppc32/64: correct signature of function parameter to makecontext Because makecontext can pass a set of integer arguments to the provided function, it is incorrect to require that this function accept no parameters. --- arch/ppc/makecontext.c | 2 +- arch/ppc64/makecontext.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/ppc/makecontext.c b/arch/ppc/makecontext.c index 4a404a4..0633c0f 100644 --- a/arch/ppc/makecontext.c +++ b/arch/ppc/makecontext.c @@ -25,7 +25,7 @@ extern void __start_context(void); void -__makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) +__makecontext(ucontext_t *ucp, void (*func)(), int argc, ...) { greg_t *sp; va_list va; diff --git a/arch/ppc64/makecontext.c b/arch/ppc64/makecontext.c index a4c1bf9..8a293b5 100644 --- a/arch/ppc64/makecontext.c +++ b/arch/ppc64/makecontext.c @@ -25,7 +25,7 @@ extern void __start_context(void); void -__makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) +__makecontext(ucontext_t *ucp, void (*func)(), int argc, ...) { greg_t *sp; va_list va; From edf69879eadaec0c72ba7ef5e7d2389946c6644b Mon Sep 17 00:00:00 2001 From: Bobby Bingham <koorogi@koorogi.info> Date: Fri, 5 Apr 2019 14:09:39 -0500 Subject: [PATCH] ppc64: remove unnecessary parentheses --- arch/ppc64/makecontext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ppc64/makecontext.c b/arch/ppc64/makecontext.c index 8a293b5..84d390a 100644 --- a/arch/ppc64/makecontext.c +++ b/arch/ppc64/makecontext.c @@ -36,7 +36,7 @@ __makecontext(ucontext_t *ucp, void (*func)(), int argc, ...) sp = (greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); sp -= stack_args + 4; - sp = (greg_t *) (((uintptr_t) sp & -16L)); + 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; From 29eac4259adfd85e0f4946a1080bb9e3f8c0cc2e Mon Sep 17 00:00:00 2001 From: Bobby Bingham <koorogi@koorogi.info> Date: Fri, 5 Apr 2019 14:10:28 -0500 Subject: [PATCH] ppc32/64: remove unused includes --- arch/ppc/makecontext.c | 2 -- arch/ppc64/makecontext.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/arch/ppc/makecontext.c b/arch/ppc/makecontext.c index 0633c0f..7214a40 100644 --- a/arch/ppc/makecontext.c +++ b/arch/ppc/makecontext.c @@ -11,10 +11,8 @@ */ #define _GNU_SOURCE -#include <stddef.h> #include <stdarg.h> #include <signal.h> -#include <string.h> #include <stdint.h> diff --git a/arch/ppc64/makecontext.c b/arch/ppc64/makecontext.c index 84d390a..2650f56 100644 --- a/arch/ppc64/makecontext.c +++ b/arch/ppc64/makecontext.c @@ -11,10 +11,8 @@ */ #define _GNU_SOURCE -#include <stddef.h> #include <stdarg.h> #include <signal.h> -#include <string.h> #include <stdint.h> From 90ff6330e62c8f836016668c9f769af365b257cb Mon Sep 17 00:00:00 2001 From: Bobby Bingham <koorogi@koorogi.info> Date: Fri, 5 Apr 2019 14:11:21 -0500 Subject: [PATCH] ppc32/64: update copyright --- arch/ppc/makecontext.c | 1 + arch/ppc64/makecontext.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/ppc/makecontext.c b/arch/ppc/makecontext.c index 7214a40..51c492f 100644 --- a/arch/ppc/makecontext.c +++ b/arch/ppc/makecontext.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org> + * Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/arch/ppc64/makecontext.c b/arch/ppc64/makecontext.c index 2650f56..43da557 100644 --- a/arch/ppc64/makecontext.c +++ b/arch/ppc64/makecontext.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org> + * Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above From 2610c7faa7b9c4114d53bb659264a6be238cd2a3 Mon Sep 17 00:00:00 2001 From: Bobby Bingham <koorogi@koorogi.info> Date: Sat, 23 Feb 2019 17:12:37 -0600 Subject: [PATCH] ppc32/64: rewrite get/set/swapcontext in assembly getcontext cannot be correctly implemented in C. If this calls another function, as it does to call syscall, it needs to first spill its return address to the stack. If, after getcontext returns, its caller then calls other functions, this saved return address can be clobbered. When the context saved by getcontext is later restored, the (now clobbered) return address will be reloaded from the stack, and the second return from getcontext will return to the wrong location. Because the powerpc swapcontext syscall allows either the old context or new context pointers to be null, it is usable for implementing all of get/set/swapcontext. We therefore rewrite swapcontext in assembly, and get/setcontext as simple assembly function wrappers around swapcontext. The one piece we keep in C is the code to check the return value of the system call and to set errno. This code was actually unnecessary before -- libc does this within syscall. However, now that the system call is made directly in assembly, bypassing libc, it is truly necessary. Because errno is thread-local and the details of how to set it can vary by libc, this code remains written in C. --- Makefile | 10 +---- README.md | 2 +- arch/ppc/getcontext.S | 20 +++++++++ arch/ppc/{getcontext.c => retfromsyscall.c} | 30 +++---------- arch/ppc/setcontext.S | 21 +++++++++ arch/ppc/setcontext.c | 45 ------------------- arch/ppc/swapcontext.S | 23 ++++++++++ arch/ppc/swapcontext.c | 45 ------------------- arch/ppc64/getcontext.S | 25 +++++++++++ arch/ppc64/{getcontext.c => retfromsyscall.c} | 30 +++---------- arch/ppc64/setcontext.S | 26 +++++++++++ arch/ppc64/setcontext.c | 45 ------------------- arch/ppc64/swapcontext.S | 28 ++++++++++++ arch/ppc64/swapcontext.c | 45 ------------------- 14 files changed, 156 insertions(+), 239 deletions(-) create mode 100644 arch/ppc/getcontext.S rename arch/ppc/{getcontext.c => retfromsyscall.c} (53%) create mode 100644 arch/ppc/setcontext.S delete mode 100644 arch/ppc/setcontext.c create mode 100644 arch/ppc/swapcontext.S delete mode 100644 arch/ppc/swapcontext.c create mode 100644 arch/ppc64/getcontext.S rename arch/ppc64/{getcontext.c => retfromsyscall.c} (53%) create mode 100644 arch/ppc64/setcontext.S delete mode 100644 arch/ppc64/setcontext.c create mode 100644 arch/ppc64/swapcontext.S delete mode 100644 arch/ppc64/swapcontext.c diff --git a/Makefile b/Makefile index 51365a3..d6ff1b0 100644 --- a/Makefile +++ b/Makefile @@ -2,14 +2,8 @@ ARCH := $(shell uname -m) CFLAGS = -ggdb3 -O2 -Wall -Iarch/${ARCH} -LIBUCONTEXT_C_SRC = \ - arch/${ARCH}/makecontext.c - -LIBUCONTEXT_S_SRC = \ - arch/${ARCH}/getcontext.S \ - arch/${ARCH}/setcontext.S \ - arch/${ARCH}/swapcontext.S \ - arch/${ARCH}/startcontext.S +LIBUCONTEXT_C_SRC = $(wildcard arch/${ARCH}/*.c) +LIBUCONTEXT_S_SRC = $(wildcard arch/${ARCH}/*.S) LIBUCONTEXT_OBJ = ${LIBUCONTEXT_C_SRC:.c=.o} ${LIBUCONTEXT_S_SRC:.S=.o} LIBUCONTEXT_SOVERSION = 0 diff --git a/README.md b/README.md index 6bd4493..27d3d0b 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Right now these archs are supported and should work on bare metal: * aarch64 * s390x -These archs require kernel assistance and use a syscall (the only assembly is the trampoline): +These archs require kernel assistance and use a syscall: * ppc * ppc64 (ELFv2 ABI spec only, ELFv1 not supported) diff --git a/arch/ppc/getcontext.S b/arch/ppc/getcontext.S new file mode 100644 index 0000000..beffaf5 --- /dev/null +++ b/arch/ppc/getcontext.S @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info> + * + * 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. + */ + +.global __getcontext +.hidden __swapcontext +__getcontext: + li 4, 0 + b __swapcontext@local + +.weak getcontext +getcontext = __getcontext diff --git a/arch/ppc/getcontext.c b/arch/ppc/retfromsyscall.c similarity index 53% rename from arch/ppc/getcontext.c rename to arch/ppc/retfromsyscall.c index 5da9dfb..3ad43c0 100644 --- a/arch/ppc/getcontext.c +++ b/arch/ppc/retfromsyscall.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org> + * Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -10,36 +11,15 @@ * from the use of this software. */ -#define _GNU_SOURCE -#include <stddef.h> -#include <stdarg.h> -#include <signal.h> -#include <string.h> -#include <stdint.h> #include <errno.h> -#include <unistd.h> -#include <sys/syscall.h> - -int -__getcontext(ucontext_t *ucp) +__attribute__ ((visibility ("hidden"))) +int __retfromsyscall(long retval) { -#ifdef SYS_swapcontext - int r; - - r = syscall(SYS_swapcontext, ucp, NULL, sizeof(ucontext_t)); - if (r < 0) - { - errno = -r; + if (retval < 0) { + errno = -retval; return -1; } - return 0; -#else - errno = ENOSYS; - return -1; -#endif } - -extern __typeof(__getcontext) getcontext __attribute__((weak, __alias__("__getcontext"))); diff --git a/arch/ppc/setcontext.S b/arch/ppc/setcontext.S new file mode 100644 index 0000000..89e6de0 --- /dev/null +++ b/arch/ppc/setcontext.S @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info> + * + * 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. + */ + +.global __setcontext +.hidden __swapcontext +__setcontext: + mr 4, 3 + li 3, 0 + b __swapcontext@local + +.weak setcontext +setcontext = __setcontext diff --git a/arch/ppc/setcontext.c b/arch/ppc/setcontext.c deleted file mode 100644 index 59c65b4..0000000 --- a/arch/ppc/setcontext.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org> - * - * 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 <stddef.h> -#include <stdarg.h> -#include <signal.h> -#include <string.h> -#include <stdint.h> -#include <errno.h> -#include <unistd.h> -#include <sys/syscall.h> - - -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/ppc/swapcontext.S b/arch/ppc/swapcontext.S new file mode 100644 index 0000000..24b6655 --- /dev/null +++ b/arch/ppc/swapcontext.S @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info> + * + * 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. + */ + +.global __swapcontext +__swapcontext: + li 0, 249 # SYS_swapcontext + li 5, 1184 # sizeof(ucontext_t) + sc + +.hidden __retfromsyscall + b __retfromsyscall@local + +.weak swapcontext +swapcontext = __swapcontext diff --git a/arch/ppc/swapcontext.c b/arch/ppc/swapcontext.c deleted file mode 100644 index af14bc2..0000000 --- a/arch/ppc/swapcontext.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org> - * - * 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 <stddef.h> -#include <stdarg.h> -#include <signal.h> -#include <string.h> -#include <stdint.h> -#include <errno.h> -#include <unistd.h> -#include <sys/syscall.h> - - -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"))); diff --git a/arch/ppc64/getcontext.S b/arch/ppc64/getcontext.S new file mode 100644 index 0000000..935edd2 --- /dev/null +++ b/arch/ppc64/getcontext.S @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info> + * + * 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. + */ + +.global __getcontext +.hidden __swapcontext +__getcontext: + addis 2, 12, .TOC.-__getcontext@ha + addi 2, 12, .TOC.-__getcontext@l + + .localentry __getcontext,.-__getcontext + + li 4, 0 + b __swapcontext + +.weak getcontext +getcontext = __getcontext diff --git a/arch/ppc64/getcontext.c b/arch/ppc64/retfromsyscall.c similarity index 53% rename from arch/ppc64/getcontext.c rename to arch/ppc64/retfromsyscall.c index 5da9dfb..3ad43c0 100644 --- a/arch/ppc64/getcontext.c +++ b/arch/ppc64/retfromsyscall.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org> + * Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -10,36 +11,15 @@ * from the use of this software. */ -#define _GNU_SOURCE -#include <stddef.h> -#include <stdarg.h> -#include <signal.h> -#include <string.h> -#include <stdint.h> #include <errno.h> -#include <unistd.h> -#include <sys/syscall.h> - -int -__getcontext(ucontext_t *ucp) +__attribute__ ((visibility ("hidden"))) +int __retfromsyscall(long retval) { -#ifdef SYS_swapcontext - int r; - - r = syscall(SYS_swapcontext, ucp, NULL, sizeof(ucontext_t)); - if (r < 0) - { - errno = -r; + if (retval < 0) { + errno = -retval; return -1; } - return 0; -#else - errno = ENOSYS; - return -1; -#endif } - -extern __typeof(__getcontext) getcontext __attribute__((weak, __alias__("__getcontext"))); diff --git a/arch/ppc64/setcontext.S b/arch/ppc64/setcontext.S new file mode 100644 index 0000000..5a0cde3 --- /dev/null +++ b/arch/ppc64/setcontext.S @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info> + * + * 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. + */ + +.global __setcontext +.hidden __swapcontext +__setcontext: + addis 2, 12, .TOC.-__setcontext@ha + addi 2, 12, .TOC.-__setcontext@l + + .localentry __setcontext,.-__setcontext + + mr 4, 3 + li 3, 0 + b __swapcontext + +.weak setcontext +setcontext = __setcontext diff --git a/arch/ppc64/setcontext.c b/arch/ppc64/setcontext.c deleted file mode 100644 index 59c65b4..0000000 --- a/arch/ppc64/setcontext.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org> - * - * 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 <stddef.h> -#include <stdarg.h> -#include <signal.h> -#include <string.h> -#include <stdint.h> -#include <errno.h> -#include <unistd.h> -#include <sys/syscall.h> - - -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/swapcontext.S b/arch/ppc64/swapcontext.S new file mode 100644 index 0000000..982537a --- /dev/null +++ b/arch/ppc64/swapcontext.S @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info> + * + * 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. + */ + +.global __swapcontext +__swapcontext: + addis 2, 12, .TOC.-__swapcontext@ha + addi 2, 12, .TOC.-__swapcontext@l + + .localentry __swapcontext,.-__swapcontext + + li 0, 249 # SYS_swapcontext + li 5, 1696 # sizeof(ucontext_t) + sc + +.hidden __retfromsyscall + b __retfromsyscall + +.weak swapcontext +swapcontext = __swapcontext diff --git a/arch/ppc64/swapcontext.c b/arch/ppc64/swapcontext.c deleted file mode 100644 index af14bc2..0000000 --- a/arch/ppc64/swapcontext.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org> - * - * 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 <stddef.h> -#include <stdarg.h> -#include <signal.h> -#include <string.h> -#include <stdint.h> -#include <errno.h> -#include <unistd.h> -#include <sys/syscall.h> - - -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")));