summaryrefslogtreecommitdiff
path: root/system/libucontext/powerpc.patch
diff options
context:
space:
mode:
Diffstat (limited to 'system/libucontext/powerpc.patch')
-rw-r--r--system/libucontext/powerpc.patch583
1 files changed, 583 insertions, 0 deletions
diff --git a/system/libucontext/powerpc.patch b/system/libucontext/powerpc.patch
new file mode 100644
index 000000000..e6df4cf25
--- /dev/null
+++ b/system/libucontext/powerpc.patch
@@ -0,0 +1,583 @@
+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")));