From bcec1ed96f2aadb32a6ad86a0e5a7af45573107e Mon Sep 17 00:00:00 2001 From: "L. Pereira" Date: Wed, 7 Aug 2024 01:21:04 +0000 Subject: [PATCH] Bundle libucontext to allow building without internet connection --- README.md | 8 - src/3rdparty/libucontext/LICENSE | 9 + src/3rdparty/libucontext/Makefile | 292 ++++++++++++++++++ src/3rdparty/libucontext/NEWS | 133 ++++++++ src/3rdparty/libucontext/README.md | 105 +++++++ src/3rdparty/libucontext/VERSION | 1 + src/3rdparty/libucontext/arch/aarch64/defs.h | 27 ++ .../libucontext/arch/aarch64/getcontext.S | 61 ++++ .../arch/aarch64/include/libucontext/bits.h | 34 ++ .../libucontext/arch/aarch64/makecontext.c | 62 ++++ .../libucontext/arch/aarch64/setcontext.S | 53 ++++ .../libucontext/arch/aarch64/swapcontext.S | 69 +++++ .../libucontext/arch/aarch64/trampoline.c | 3 + src/3rdparty/libucontext/arch/arm/defs.h | 15 + .../libucontext/arch/arm/getcontext.S | 49 +++ .../arch/arm/include/libucontext/bits.h | 30 ++ .../libucontext/arch/arm/makecontext.c | 62 ++++ .../libucontext/arch/arm/setcontext.S | 43 +++ .../libucontext/arch/arm/swapcontext.S | 51 +++ .../libucontext/arch/arm/trampoline.c | 3 + .../libucontext/arch/common/common-defs.h | 61 ++++ .../arch/common/common-trampoline.c | 29 ++ .../arch/common/include/libucontext/bits.h | 13 + .../libucontext/arch/loongarch64/defs.h | 76 +++++ .../arch/loongarch64/freestanding/bits.h | 43 +++ .../libucontext/arch/loongarch64/getcontext.S | 46 +++ .../arch/loongarch64/makecontext.S | 108 +++++++ .../libucontext/arch/loongarch64/setcontext.S | 55 ++++ .../arch/loongarch64/startcontext.S | 33 ++ .../arch/loongarch64/swapcontext.S | 89 ++++++ src/3rdparty/libucontext/arch/m68k/defs.h | 34 ++ .../libucontext/arch/m68k/getcontext.S | 30 ++ .../arch/m68k/include/libucontext/bits.h | 28 ++ .../libucontext/arch/m68k/makecontext.c | 61 ++++ .../libucontext/arch/m68k/setcontext.S | 31 ++ .../libucontext/arch/m68k/swapcontext.S | 40 +++ .../libucontext/arch/m68k/trampoline.c | 3 + src/3rdparty/libucontext/arch/mips/defs.h | 94 ++++++ .../libucontext/arch/mips/getcontext.S | 47 +++ .../arch/mips/include/libucontext/bits.h | 27 ++ .../libucontext/arch/mips/makecontext.S | 101 ++++++ .../libucontext/arch/mips/setcontext.S | 51 +++ .../libucontext/arch/mips/startcontext.S | 35 +++ .../libucontext/arch/mips/swapcontext.S | 82 +++++ src/3rdparty/libucontext/arch/mips64/defs.h | 92 ++++++ .../libucontext/arch/mips64/getcontext.S | 47 +++ .../arch/mips64/include/libucontext/bits.h | 47 +++ .../libucontext/arch/mips64/makecontext.S | 107 +++++++ .../libucontext/arch/mips64/setcontext.S | 55 ++++ .../libucontext/arch/mips64/startcontext.S | 35 +++ .../libucontext/arch/mips64/swapcontext.S | 87 ++++++ src/3rdparty/libucontext/arch/or1k/defs.h | 22 ++ .../libucontext/arch/or1k/getcontext.S | 39 +++ .../arch/or1k/include/libucontext/bits.h | 28 ++ .../libucontext/arch/or1k/makecontext.c | 61 ++++ .../libucontext/arch/or1k/setcontext.S | 48 +++ .../libucontext/arch/or1k/swapcontext.S | 68 ++++ .../libucontext/arch/or1k/trampoline.c | 3 + src/3rdparty/libucontext/arch/ppc/defs.h | 64 ++++ .../libucontext/arch/ppc/getcontext.S | 22 ++ .../libucontext/arch/ppc/makecontext.c | 61 ++++ .../libucontext/arch/ppc/retfromsyscall.c | 25 ++ .../libucontext/arch/ppc/setcontext.S | 23 ++ .../libucontext/arch/ppc/startcontext.S | 28 ++ .../libucontext/arch/ppc/swapcontext.S | 29 ++ src/3rdparty/libucontext/arch/ppc64/defs.h | 67 ++++ .../libucontext/arch/ppc64/getcontext.S | 27 ++ .../libucontext/arch/ppc64/makecontext.c | 62 ++++ .../libucontext/arch/ppc64/retfromsyscall.c | 25 ++ .../libucontext/arch/ppc64/setcontext.S | 28 ++ .../libucontext/arch/ppc64/startcontext.S | 33 ++ .../libucontext/arch/ppc64/swapcontext.S | 34 ++ src/3rdparty/libucontext/arch/riscv32/defs.h | 55 ++++ .../libucontext/arch/riscv32/getcontext.S | 45 +++ .../arch/riscv32/include/libucontext/bits.h | 48 +++ .../libucontext/arch/riscv32/makecontext.c | 62 ++++ .../libucontext/arch/riscv32/setcontext.S | 56 ++++ .../libucontext/arch/riscv32/swapcontext.S | 81 +++++ .../libucontext/arch/riscv32/trampoline.c | 3 + src/3rdparty/libucontext/arch/riscv64/defs.h | 55 ++++ .../libucontext/arch/riscv64/getcontext.S | 45 +++ .../arch/riscv64/include/libucontext/bits.h | 48 +++ .../libucontext/arch/riscv64/makecontext.c | 62 ++++ .../libucontext/arch/riscv64/setcontext.S | 56 ++++ .../libucontext/arch/riscv64/swapcontext.S | 81 +++++ .../libucontext/arch/riscv64/trampoline.c | 3 + src/3rdparty/libucontext/arch/s390x/defs.h | 15 + .../libucontext/arch/s390x/getcontext.S | 26 ++ .../arch/s390x/include/libucontext/bits.h | 41 +++ .../libucontext/arch/s390x/makecontext.c | 68 ++++ .../libucontext/arch/s390x/setcontext.S | 25 ++ .../libucontext/arch/s390x/startcontext.S | 30 ++ .../libucontext/arch/s390x/swapcontext.S | 30 ++ src/3rdparty/libucontext/arch/sh/defs.h | 20 ++ src/3rdparty/libucontext/arch/sh/getcontext.S | 56 ++++ .../arch/sh/include/libucontext/bits.h | 29 ++ .../libucontext/arch/sh/makecontext.c | 59 ++++ src/3rdparty/libucontext/arch/sh/setcontext.S | 60 ++++ .../libucontext/arch/sh/swapcontext.S | 95 ++++++ src/3rdparty/libucontext/arch/sh/trampoline.c | 3 + src/3rdparty/libucontext/arch/x86/defs.h | 65 ++++ .../libucontext/arch/x86/getcontext.S | 50 +++ .../arch/x86/include/libucontext/bits.h | 48 +++ .../libucontext/arch/x86/makecontext.c | 59 ++++ .../libucontext/arch/x86/setcontext.S | 45 +++ .../libucontext/arch/x86/swapcontext.S | 73 +++++ .../libucontext/arch/x86/trampoline.c | 3 + src/3rdparty/libucontext/arch/x86_64/defs.h | 105 +++++++ .../libucontext/arch/x86_64/getcontext.S | 49 +++ .../arch/x86_64/include/libucontext/bits.h | 64 ++++ .../libucontext/arch/x86_64/makecontext.c | 80 +++++ .../libucontext/arch/x86_64/setcontext.S | 46 +++ .../libucontext/arch/x86_64/swapcontext.S | 75 +++++ .../libucontext/arch/x86_64/trampoline.c | 3 + src/3rdparty/libucontext/doc/libucontext.scd | 174 +++++++++++ src/3rdparty/libucontext/doc/meson.build | 21 ++ .../examples/cooperative_threading.c | 94 ++++++ .../include/libucontext/libucontext.h | 20 ++ src/3rdparty/libucontext/libucontext.pc.in | 9 + src/3rdparty/libucontext/libucontext_posix.c | 59 ++++ src/3rdparty/libucontext/meson.build | 172 +++++++++++ src/3rdparty/libucontext/meson_options.txt | 8 + src/3rdparty/libucontext/test_libucontext.c | 102 ++++++ .../libucontext/test_libucontext_posix.c | 102 ++++++ src/lib/CMakeLists.txt | 8 +- 125 files changed, 6373 insertions(+), 12 deletions(-) create mode 100644 src/3rdparty/libucontext/LICENSE create mode 100644 src/3rdparty/libucontext/Makefile create mode 100644 src/3rdparty/libucontext/NEWS create mode 100644 src/3rdparty/libucontext/README.md create mode 100644 src/3rdparty/libucontext/VERSION create mode 100644 src/3rdparty/libucontext/arch/aarch64/defs.h create mode 100644 src/3rdparty/libucontext/arch/aarch64/getcontext.S create mode 100644 src/3rdparty/libucontext/arch/aarch64/include/libucontext/bits.h create mode 100644 src/3rdparty/libucontext/arch/aarch64/makecontext.c create mode 100644 src/3rdparty/libucontext/arch/aarch64/setcontext.S create mode 100644 src/3rdparty/libucontext/arch/aarch64/swapcontext.S create mode 100644 src/3rdparty/libucontext/arch/aarch64/trampoline.c create mode 100644 src/3rdparty/libucontext/arch/arm/defs.h create mode 100644 src/3rdparty/libucontext/arch/arm/getcontext.S create mode 100644 src/3rdparty/libucontext/arch/arm/include/libucontext/bits.h create mode 100644 src/3rdparty/libucontext/arch/arm/makecontext.c create mode 100644 src/3rdparty/libucontext/arch/arm/setcontext.S create mode 100644 src/3rdparty/libucontext/arch/arm/swapcontext.S create mode 100644 src/3rdparty/libucontext/arch/arm/trampoline.c create mode 100644 src/3rdparty/libucontext/arch/common/common-defs.h create mode 100644 src/3rdparty/libucontext/arch/common/common-trampoline.c create mode 100644 src/3rdparty/libucontext/arch/common/include/libucontext/bits.h create mode 100644 src/3rdparty/libucontext/arch/loongarch64/defs.h create mode 100644 src/3rdparty/libucontext/arch/loongarch64/freestanding/bits.h create mode 100644 src/3rdparty/libucontext/arch/loongarch64/getcontext.S create mode 100644 src/3rdparty/libucontext/arch/loongarch64/makecontext.S create mode 100644 src/3rdparty/libucontext/arch/loongarch64/setcontext.S create mode 100644 src/3rdparty/libucontext/arch/loongarch64/startcontext.S create mode 100644 src/3rdparty/libucontext/arch/loongarch64/swapcontext.S create mode 100644 src/3rdparty/libucontext/arch/m68k/defs.h create mode 100644 src/3rdparty/libucontext/arch/m68k/getcontext.S create mode 100644 src/3rdparty/libucontext/arch/m68k/include/libucontext/bits.h create mode 100644 src/3rdparty/libucontext/arch/m68k/makecontext.c create mode 100644 src/3rdparty/libucontext/arch/m68k/setcontext.S create mode 100644 src/3rdparty/libucontext/arch/m68k/swapcontext.S create mode 100644 src/3rdparty/libucontext/arch/m68k/trampoline.c create mode 100644 src/3rdparty/libucontext/arch/mips/defs.h create mode 100644 src/3rdparty/libucontext/arch/mips/getcontext.S create mode 100644 src/3rdparty/libucontext/arch/mips/include/libucontext/bits.h create mode 100644 src/3rdparty/libucontext/arch/mips/makecontext.S create mode 100644 src/3rdparty/libucontext/arch/mips/setcontext.S create mode 100644 src/3rdparty/libucontext/arch/mips/startcontext.S create mode 100644 src/3rdparty/libucontext/arch/mips/swapcontext.S create mode 100644 src/3rdparty/libucontext/arch/mips64/defs.h create mode 100644 src/3rdparty/libucontext/arch/mips64/getcontext.S create mode 100644 src/3rdparty/libucontext/arch/mips64/include/libucontext/bits.h create mode 100644 src/3rdparty/libucontext/arch/mips64/makecontext.S create mode 100644 src/3rdparty/libucontext/arch/mips64/setcontext.S create mode 100644 src/3rdparty/libucontext/arch/mips64/startcontext.S create mode 100644 src/3rdparty/libucontext/arch/mips64/swapcontext.S create mode 100644 src/3rdparty/libucontext/arch/or1k/defs.h create mode 100644 src/3rdparty/libucontext/arch/or1k/getcontext.S create mode 100644 src/3rdparty/libucontext/arch/or1k/include/libucontext/bits.h create mode 100644 src/3rdparty/libucontext/arch/or1k/makecontext.c create mode 100644 src/3rdparty/libucontext/arch/or1k/setcontext.S create mode 100644 src/3rdparty/libucontext/arch/or1k/swapcontext.S create mode 100644 src/3rdparty/libucontext/arch/or1k/trampoline.c create mode 100644 src/3rdparty/libucontext/arch/ppc/defs.h create mode 100644 src/3rdparty/libucontext/arch/ppc/getcontext.S create mode 100644 src/3rdparty/libucontext/arch/ppc/makecontext.c create mode 100644 src/3rdparty/libucontext/arch/ppc/retfromsyscall.c create mode 100644 src/3rdparty/libucontext/arch/ppc/setcontext.S create mode 100644 src/3rdparty/libucontext/arch/ppc/startcontext.S create mode 100644 src/3rdparty/libucontext/arch/ppc/swapcontext.S create mode 100644 src/3rdparty/libucontext/arch/ppc64/defs.h create mode 100644 src/3rdparty/libucontext/arch/ppc64/getcontext.S create mode 100644 src/3rdparty/libucontext/arch/ppc64/makecontext.c create mode 100644 src/3rdparty/libucontext/arch/ppc64/retfromsyscall.c create mode 100644 src/3rdparty/libucontext/arch/ppc64/setcontext.S create mode 100644 src/3rdparty/libucontext/arch/ppc64/startcontext.S create mode 100644 src/3rdparty/libucontext/arch/ppc64/swapcontext.S create mode 100644 src/3rdparty/libucontext/arch/riscv32/defs.h create mode 100644 src/3rdparty/libucontext/arch/riscv32/getcontext.S create mode 100644 src/3rdparty/libucontext/arch/riscv32/include/libucontext/bits.h create mode 100644 src/3rdparty/libucontext/arch/riscv32/makecontext.c create mode 100644 src/3rdparty/libucontext/arch/riscv32/setcontext.S create mode 100644 src/3rdparty/libucontext/arch/riscv32/swapcontext.S create mode 100644 src/3rdparty/libucontext/arch/riscv32/trampoline.c create mode 100644 src/3rdparty/libucontext/arch/riscv64/defs.h create mode 100644 src/3rdparty/libucontext/arch/riscv64/getcontext.S create mode 100644 src/3rdparty/libucontext/arch/riscv64/include/libucontext/bits.h create mode 100644 src/3rdparty/libucontext/arch/riscv64/makecontext.c create mode 100644 src/3rdparty/libucontext/arch/riscv64/setcontext.S create mode 100644 src/3rdparty/libucontext/arch/riscv64/swapcontext.S create mode 100644 src/3rdparty/libucontext/arch/riscv64/trampoline.c create mode 100644 src/3rdparty/libucontext/arch/s390x/defs.h create mode 100644 src/3rdparty/libucontext/arch/s390x/getcontext.S create mode 100644 src/3rdparty/libucontext/arch/s390x/include/libucontext/bits.h create mode 100644 src/3rdparty/libucontext/arch/s390x/makecontext.c create mode 100644 src/3rdparty/libucontext/arch/s390x/setcontext.S create mode 100644 src/3rdparty/libucontext/arch/s390x/startcontext.S create mode 100644 src/3rdparty/libucontext/arch/s390x/swapcontext.S create mode 100644 src/3rdparty/libucontext/arch/sh/defs.h create mode 100644 src/3rdparty/libucontext/arch/sh/getcontext.S create mode 100644 src/3rdparty/libucontext/arch/sh/include/libucontext/bits.h create mode 100644 src/3rdparty/libucontext/arch/sh/makecontext.c create mode 100644 src/3rdparty/libucontext/arch/sh/setcontext.S create mode 100644 src/3rdparty/libucontext/arch/sh/swapcontext.S create mode 100644 src/3rdparty/libucontext/arch/sh/trampoline.c create mode 100644 src/3rdparty/libucontext/arch/x86/defs.h create mode 100644 src/3rdparty/libucontext/arch/x86/getcontext.S create mode 100644 src/3rdparty/libucontext/arch/x86/include/libucontext/bits.h create mode 100644 src/3rdparty/libucontext/arch/x86/makecontext.c create mode 100644 src/3rdparty/libucontext/arch/x86/setcontext.S create mode 100644 src/3rdparty/libucontext/arch/x86/swapcontext.S create mode 100644 src/3rdparty/libucontext/arch/x86/trampoline.c create mode 100644 src/3rdparty/libucontext/arch/x86_64/defs.h create mode 100644 src/3rdparty/libucontext/arch/x86_64/getcontext.S create mode 100644 src/3rdparty/libucontext/arch/x86_64/include/libucontext/bits.h create mode 100644 src/3rdparty/libucontext/arch/x86_64/makecontext.c create mode 100644 src/3rdparty/libucontext/arch/x86_64/setcontext.S create mode 100644 src/3rdparty/libucontext/arch/x86_64/swapcontext.S create mode 100644 src/3rdparty/libucontext/arch/x86_64/trampoline.c create mode 100644 src/3rdparty/libucontext/doc/libucontext.scd create mode 100644 src/3rdparty/libucontext/doc/meson.build create mode 100644 src/3rdparty/libucontext/examples/cooperative_threading.c create mode 100644 src/3rdparty/libucontext/include/libucontext/libucontext.h create mode 100644 src/3rdparty/libucontext/libucontext.pc.in create mode 100644 src/3rdparty/libucontext/libucontext_posix.c create mode 100644 src/3rdparty/libucontext/meson.build create mode 100644 src/3rdparty/libucontext/meson_options.txt create mode 100644 src/3rdparty/libucontext/test_libucontext.c create mode 100644 src/3rdparty/libucontext/test_libucontext_posix.c diff --git a/README.md b/README.md index 528561173..d5db95c5c 100644 --- a/README.md +++ b/README.md @@ -61,14 +61,6 @@ The build system will look for these libraries and enable/link if available. - Client libraries for either [MySQL](https://dev.mysql.com) or [MariaDB](https://mariadb.org) - [SQLite 3](http://sqlite.org) -> [!NOTE] -> -> On some systems, -> [libucontext](https://github.com/kaniini/libucontext) will be downloaded -> and built alongside Lwan. This will require a network connection, so keep -> this in mind when packaging Lwan for non-x86_64 or non-aarch64 -> architectures. - ### Common operating system package names #### Minimum to build diff --git a/src/3rdparty/libucontext/LICENSE b/src/3rdparty/libucontext/LICENSE new file mode 100644 index 000000000..9fbc5d306 --- /dev/null +++ b/src/3rdparty/libucontext/LICENSE @@ -0,0 +1,9 @@ +Copyright (c) 2018-2022 Ariadne Conill + +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. diff --git a/src/3rdparty/libucontext/Makefile b/src/3rdparty/libucontext/Makefile new file mode 100644 index 000000000..587729543 --- /dev/null +++ b/src/3rdparty/libucontext/Makefile @@ -0,0 +1,292 @@ +SCDOC := scdoc + +ARCH := $(shell uname -m) +ifeq ($(ARCH),$(filter $(ARCH),i386 i686)) + override ARCH = x86 +endif +ifeq ($(ARCH),$(filter $(ARCH),sh2 sh4)) + override ARCH = sh +endif +ifeq ($(ARCH),$(filter $(ARCH),ppc64le)) + override ARCH = ppc64 +endif +ifeq ($(ARCH),$(filter $(ARCH),armv7l)) + override ARCH = arm +endif +ifeq ($(ARCH),$(filter $(ARCH),arm64)) + override ARCH = aarch64 +endif + +prefix = /usr +libdir = ${prefix}/lib +shared_libdir = ${libdir} +static_libdir = ${libdir} +includedir = ${prefix}/include +pkgconfigdir = ${prefix}/lib/pkgconfig + +CFLAGS ?= -ggdb3 -O2 -Wall +CPPFLAGS := -Iinclude -Iarch/${ARCH} -Iarch/common +ifneq ($(shell uname),Darwin) + EXPORT_UNPREFIXED := yes +else + # Darwin does not support aliases + EXPORT_UNPREFIXED := no +endif +FREESTANDING := no + +ifeq ($(FREESTANDING),yes) + CPPFLAGS += -DFREESTANDING + EXPORT_UNPREFIXED = no +endif + +FORCE_SOFT_FLOAT := no + +ifeq ($(FORCE_SOFT_FLOAT),yes) + CPPFLAGS += -DFORCE_SOFT_FLOAT +endif + +FORCE_HARD_FLOAT := no + +ifeq ($(FORCE_HARD_FLOAT),yes) + CPPFLAGS += -DFORCE_HARD_FLOAT +endif + +ifeq ($(EXPORT_UNPREFIXED),yes) + CPPFLAGS += -DEXPORT_UNPREFIXED +endif + +LIBUCONTEXT_C_SRC = $(wildcard arch/${ARCH}/*.c) +LIBUCONTEXT_S_SRC = $(wildcard arch/${ARCH}/*.S) + +ifeq ($(shell test -d arch/${ARCH}/include; echo $?),0) + CPPFLAGS += -Iarch/${ARCH}/include +endif + +LIBUCONTEXT_VERSION := $(shell head -n 1 VERSION) +LIBUCONTEXT_OBJ = ${LIBUCONTEXT_C_SRC:.c=.o} ${LIBUCONTEXT_S_SRC:.S=.o} +LIBUCONTEXT_SOVERSION = 1 +ifeq ($(shell uname),Darwin) + LIBUCONTEXT_NAME = libucontext.dylib + LIBUCONTEXT_SONAME = libucontext.${LIBUCONTEXT_SOVERSION}.dylib + LIBUCONTEXT_POSIX_NAME = libucontext_posix.dylib + LIBUCONTEXT_POSIX_SONAME = libucontext_posix.${LIBUCONTEXT_SOVERSION}.dylib + LIBUCONTEXT_LINKER_FLAGS = -Wl,-dynamiclib,-install_name,${LIBUCONTEXT_SONAME},-current_version,${LIBUCONTEXT_SOVERSION},-compatibility_version,${LIBUCONTEXT_SOVERSION} + LIBUCONTEXT_POSIX_LINKER_FLAGS = -Wl,-dynamiclib,-install_name,${LIBUCONTEXT_POSIX_SONAME},-current_version,${LIBUCONTEXT_SOVERSION},-compatibility_version,${LIBUCONTEXT_SOVERSION} +else + LIBUCONTEXT_NAME = libucontext.so + LIBUCONTEXT_SONAME = libucontext.so.${LIBUCONTEXT_SOVERSION} + LIBUCONTEXT_POSIX_NAME = libucontext_posix.so + LIBUCONTEXT_POSIX_SONAME = libucontext_posix.so.${LIBUCONTEXT_SOVERSION} + LIBUCONTEXT_LINKER_FLAGS = -shared -Wl,-soname,${LIBUCONTEXT_SONAME} -Wl,-z,noexecstack + LIBUCONTEXT_POSIX_LINKER_FLAGS = -shared -Wl,-soname,${LIBUCONTEXT_POSIX_SONAME} -Wl,-z,noexecstack + ASFLAGS = -Wa,--noexecstack +endif +LIBUCONTEXT_STATIC_NAME = libucontext.a +LIBUCONTEXT_PC = libucontext.pc +LIBUCONTEXT_PATH = ${shared_libdir}/${LIBUCONTEXT_SONAME} +LIBUCONTEXT_STATIC_PATH = ${static_libdir}/${LIBUCONTEXT_STATIC_NAME} +LIBUCONTEXT_HEADERS = \ + include/libucontext/libucontext.h \ + include/libucontext/bits.h +LIBUCONTEXT_EXAMPLES = \ + examples/cooperative_threading +LIBUCONTEXT_POSIX_STATIC_NAME = libucontext_posix.a +LIBUCONTEXT_POSIX_C_SRC = libucontext_posix.c +LIBUCONTEXT_POSIX_OBJ = ${LIBUCONTEXT_POSIX_C_SRC:.c=.o} +LIBUCONTEXT_POSIX_PATH = ${shared_libdir}/${LIBUCONTEXT_POSIX_SONAME} +LIBUCONTEXT_POSIX_STATIC_PATH = ${static_libdir}/${LIBUCONTEXT_POSIX_STATIC_NAME} + +ifeq ($(FREESTANDING),yes) + LIBUCONTEXT_POSIX_NAME = + LIBUCONTEXT_POSIX_STATIC_NAME = +endif + +all: ${LIBUCONTEXT_SONAME} ${LIBUCONTEXT_STATIC_NAME} ${LIBUCONTEXT_POSIX_NAME} ${LIBUCONTEXT_POSIX_STATIC_NAME} ${LIBUCONTEXT_PC} + +${LIBUCONTEXT_POSIX_NAME}: ${LIBUCONTEXT_NAME} ${LIBUCONTEXT_POSIX_OBJ} + $(CC) -fPIC -o ${LIBUCONTEXT_POSIX_NAME} ${LIBUCONTEXT_POSIX_LINKER_FLAGS} ${LIBUCONTEXT_POSIX_OBJ} -L. -lucontext ${LDFLAGS} + +${LIBUCONTEXT_POSIX_STATIC_NAME}: ${LIBUCONTEXT_STATIC_NAME} ${LIBUCONTEXT_POSIX_OBJ} + $(AR) rcs ${LIBUCONTEXT_POSIX_STATIC_NAME} ${LIBUCONTEXT_POSIX_OBJ} + +${LIBUCONTEXT_POSIX_SONAME}: ${LIBUCONTEXT_POSIX_NAME} + ln -sf ${LIBUCONTEXT_POSIX_NAME} ${LIBUCONTEXT_POSIX_SONAME} + +${LIBUCONTEXT_STATIC_NAME}: ${LIBUCONTEXT_HEADERS} ${LIBUCONTEXT_OBJ} + $(AR) rcs ${LIBUCONTEXT_STATIC_NAME} ${LIBUCONTEXT_OBJ} + +${LIBUCONTEXT_NAME}: ${LIBUCONTEXT_HEADERS} ${LIBUCONTEXT_OBJ} + $(CC) -fPIC -o ${LIBUCONTEXT_NAME} ${LIBUCONTEXT_LINKER_FLAGS} ${LIBUCONTEXT_OBJ} ${LDFLAGS} + +${LIBUCONTEXT_SONAME}: ${LIBUCONTEXT_NAME} + ln -sf ${LIBUCONTEXT_NAME} ${LIBUCONTEXT_SONAME} + +${LIBUCONTEXT_PC}: libucontext.pc.in + sed -e s:@LIBUCONTEXT_VERSION@:${LIBUCONTEXT_VERSION}:g \ + -e s:@LIBUCONTEXT_SHARED_LIBDIR@:${shared_libdir}:g \ + -e s:@LIBUCONTEXT_STATIC_LIBDIR@:${static_libdir}:g \ + -e s:@LIBUCONTEXT_INCLUDEDIR@:${includedir}:g $< > $@ + +MANPAGES_SYMLINKS_3 = \ + libucontext_getcontext.3 \ + libucontext_makecontext.3 \ + libucontext_setcontext.3 \ + libucontext_swapcontext.3 +MANPAGES_3 = doc/libucontext.3 + +MANPAGES = ${MANPAGES_3} + +.scd.3: + ${SCDOC} < $< > $@ + +.SUFFIXES: .scd .3 + +docs: ${MANPAGES} + +.c.o: + $(CC) -std=gnu99 -D_DEFAULT_SOURCE -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} -c -o $@ $< + +.S.o: + $(CC) -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} ${ASFLAGS} -c -o $@ $< + +${LIBUCONTEXT_NAME}_clean: + rm -f ${LIBUCONTEXT_NAME} + +${LIBUCONTEXT_SONAME}_clean: + rm -f ${LIBUCONTEXT_SONAME} + +${LIBUCONTEXT_STATIC_NAME}_clean: + rm -f ${LIBUCONTEXT_STATIC_NAME} + +libucontext_obj_clean: + rm -f ${LIBUCONTEXT_OBJ} + +${LIBUCONTEXT_PC}_clean: + rm -f ${LIBUCONTEXT_PC} + +bits_clean: + rm -f include/libucontext/bits.h + +${LIBUCONTEXT_POSIX_NAME}_clean: + rm -f ${LIBUCONTEXT_POSIX_NAME} + +${LIBUCONTEXT_POSIX_SONAME}_clean: + rm -f ${LIBUCONTEXT_POSIX_SONAME} + +${LIBUCONTEXT_POSIX_STATIC_NAME}_clean: + rm -f ${LIBUCONTEXT_POSIX_STATIC_NAME} + +libucontext_posix_obj_clean: + rm -f ${LIBUCONTEXT_POSIX_OBJ} + +check_clean: check_bare_clean check_posix_clean check_bare_posixabi_clean + +check_bare_clean: + rm -f test_libucontext + +check_posix_clean: + rm -f test_libucontext_posix + +check_bare_posixabi_clean: + rm -f test_libucontext_bare_posixabi + +docs_clean: + rm -f ${MANPAGES} + +clean: ${LIBUCONTEXT_NAME}_clean +clean: ${LIBUCONTEXT_SONAME}_clean +clean: ${LIBUCONTEXT_STATIC_NAME}_clean +clean: ${LIBUCONTEXT_PC}_clean +clean: bits_clean +clean: ${LIBUCONTEXT_POSIX_NAME}_clean +clean: ${LIBUCONTEXT_POSIX_SONAME}_clean +clean: ${LIBUCONTEXT_POSIX_STATIC_NAME}_clean +clean: libucontext_posix_obj_clean +clean: libucontext_obj_clean +clean: check_clean +clean: docs_clean + +install-shared: ${LIBUCONTEXT_SONAME} + install -D -m755 ${LIBUCONTEXT_NAME} ${DESTDIR}${LIBUCONTEXT_PATH} + ln -sf ${LIBUCONTEXT_SONAME} ${DESTDIR}${shared_libdir}/${LIBUCONTEXT_NAME} + +install-static: ${LIBUCONTEXT_STATIC_NAME} + install -D -m664 ${LIBUCONTEXT_STATIC_NAME} ${DESTDIR}${LIBUCONTEXT_STATIC_PATH} + +install-pkgconf: + install -D -m644 ${LIBUCONTEXT_PC} ${DESTDIR}${pkgconfigdir}/${LIBUCONTEXT_PC} + if [ -n "${LIBUCONTEXT_POSIX_NAME}" ]; then \ + install -D -m755 ${LIBUCONTEXT_POSIX_NAME} ${DESTDIR}${LIBUCONTEXT_POSIX_PATH}; \ + install -D -m644 ${LIBUCONTEXT_POSIX_STATIC_NAME} ${DESTDIR}${LIBUCONTEXT_POSIX_STATIC_PATH}; \ + fi + +install-headers: + for i in ${LIBUCONTEXT_HEADERS}; do \ + destfn=$$(echo $$i | sed s:include/::g); \ + install -D -m644 $$i ${DESTDIR}${includedir}/$$destfn; \ + done + +install: all install-shared install-static install-pkgconf install-headers + +install_docs: docs + install -D -m644 doc/libucontext.3 ${DESTDIR}/usr/share/man/man3/libucontext.3 + for i in ${MANPAGES_SYMLINKS_3}; do \ + ln -s libucontext.3 ${DESTDIR}/usr/share/man/man3/$$i; \ + done + +ifneq (${FREESTANDING},yes) +check: check_libucontext_posix + +check_libucontext_posix: test_libucontext_posix ${LIBUCONTEXT_POSIX_SONAME} ${LIBUCONTEXT_SONAME} + env LD_LIBRARY_PATH=$(shell pwd) ./test_libucontext_posix + +test_libucontext_posix: test_libucontext_posix.c ${LIBUCONTEXT_POSIX_NAME} + $(CC) -std=gnu99 -D_DEFAULT_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext -lucontext_posix +endif + +ifeq ($(EXPORT_UNPREFIXED),yes) +check: check_libucontext_bare_posixabi + +check_libucontext_bare_posixabi: test_libucontext_bare_posixabi ${LIBUCONTEXT_SONAME} + env LD_LIBRARY_PATH=$(shell pwd) ./test_libucontext_bare_posixabi + +test_libucontext_bare_posixabi: test_libucontext_posix.c ${LIBUCONTEXT_NAME} + $(CC) -std=gnu99 -D_DEFAULT_SOURCE ${CFLAGS} ${CPPFLAGS} test_libucontext_posix.c -o $@ -L. -lucontext +endif + +check_libucontext: test_libucontext ${LIBUCONTEXT_SONAME} + env LD_LIBRARY_PATH=$(shell pwd) ./test_libucontext + +check: check_libucontext + +test_libucontext: test_libucontext.c ${LIBUCONTEXT_NAME} + $(CC) -std=gnu99 -D_DEFAULT_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext + +examples: ${LIBUCONTEXT_EXAMPLES} +examples/cooperative_threading: examples/cooperative_threading.c ${LIBUCONTEXT_NAME} + $(CC) -std=gnu99 -D_DEFAULT_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext + +ifeq ($(FREESTANDING),no) + +include/libucontext/bits.h: arch/common/include/libucontext/bits.h + cp $< $@ + +else + +include/libucontext/bits.h: arch/${ARCH}/include/libucontext/bits.h + cp $< $@ + +endif + +PACKAGE_NAME = libucontext +PACKAGE_VERSION = ${LIBUCONTEXT_VERSION} +DIST_NAME = ${PACKAGE_NAME}-${PACKAGE_VERSION} +DIST_TARBALL = ${DIST_NAME}.tar.xz + +distcheck: check dist +dist: ${DIST_TARBALL} +${DIST_TARBALL}: + git archive --format=tar --prefix=${DIST_NAME}/ -o ${DIST_NAME}.tar ${DIST_NAME} + xz ${DIST_NAME}.tar + +.PHONY: check dist diff --git a/src/3rdparty/libucontext/NEWS b/src/3rdparty/libucontext/NEWS new file mode 100644 index 000000000..af46a1021 --- /dev/null +++ b/src/3rdparty/libucontext/NEWS @@ -0,0 +1,133 @@ +Changes from 1.1 to 1.2 +----------------------- + +* Added Loongarch64 port. + +* Added OpenRISC (or1k) port. + +* Fixed various build system issues: + - libucontext_posix.so is no longer underlinked + - Executable stacks are now disabled when using GNU-like toolchains + - CPPFLAGS is used consistently + - Users may now build on Darwin without using Meson + +* aarch64 now implements the necessary SIMD register save/restore as + mandatory in AAPCS64. + Patches contributed by Richard Campbell. + +Changes from 1.0 to 1.1 +----------------------- + +* Added RISC-V RV32 port. + +* Cleaned up use of _GNU_SOURCE in C code. + Partially from patches contributed by osy. + +* Added automatic detection of armv7l architecture. + Patch contributed by Leandro Pereira. + +* Fixed installation path of libucontext_posix.a. + +* Work around deficiency in clang built-in assembler on AArch64 targets. + Patch contributed by osy. + +Changes from 0.13.1 to 1.0 +-------------------------- + +* Implement common libucontext_trampoline, written in C with inline + assembly. + +* Added Renesas / Hitachi SH-2/SH-4 port (sh). + +* Added Meson build system, primarily for the convenience of using + libucontext with qemu as a subproject. + +* Added support for Mach-O ABI. + +* Fixed deficiencies in libucontext ABI, SONAME has been bumped due + to the ABI regressions in 0.13. + +Changes from 0.13 to 0.13.1 +--------------------------- + +* Fix installation of libucontext.pc. + Patch contributed by Ömer Faruk IRMAK. + +Changes from 0.12 to 0.13 +------------------------- + +* Aligned RISC-V RV64 port's header usage with musl 1.2 to remove + warnings and ensure consistent register name usage. + +* Added Motorola 680X0 / NXP ColdFire port (m68k). + +* Added support for building for bare-metal targets with newlib via + make FREESTANDING=yes. Other OS are also supported (for example, + the m68k freestanding port was tested on AmigaOS), PowerPC requires + kernel assistance and cannot be built with FREESTANDING=yes. Not + all ports have support for FREESTANDING yet, patches welcome. + +Changes from 0.11 to 0.12 +------------------------- + +* Fixed compilation of RISC-V RV64 port with modern musl releases. + +Changes from 0.10 to 0.11 +------------------------- + +* Added RISC-V RV64 port. + +* Fixed compilation with clang. + Patch contributed by Khem Raj. + +* Add ${LIBDIR} variable to build system. + Patch contributed by Khem Raj. + +Changes from 0.9.0 to 0.10 +-------------------------- + +* Added MIPS O32 and MIPS N64 ports. + MIPS N32 ABI is theoretically supported by ARCH=mips64 with + a MIPS N32 toolchain, but this has not been tested. + +* Improved test program (test_libucontext) verbosity. + +* Modernized all architectures to use common assembly + macros, such as REG_OFFSET(reg), FUNC() and ALIAS(). + +* Added debugging hints to assembly functions for GDB. + +* Automatically alias i386/i686 to x86 in makefile. + Patch contributed by Gabriel Ivascu. + +Changes from 0.1.3 to 0.9.0 +--------------------------- + +* Pass ${LDFLAGS} when linking the libucontext library. + Patch contributed by Khem Raj. + +* Fix clobbering of the first stack argument on x86. + Patch contributed by A. Wilcox. + +* Add support for building a static libucontext. + Patches contributed by Gabriel Ivascu. + +* Rewrite ppc/ppc64 implementation to fully use the + swapcontext(3) syscall. + Patches contributed by Bobby Bingham. + +Changes from 0.1.1 to 0.1.3 +--------------------------- + +* Fix register clobbering on x86_64. + Patches contributed by A. Wilcox and Timo Teräs. + +Changes from 0.1.0 to 0.1.1 +--------------------------- + +* Added S390X port. + +* Cleaned up the ppc/ppc64 trampoline. + +* Fixed up GOT clobbering and removed a textrel from the x86 + trampoline. diff --git a/src/3rdparty/libucontext/README.md b/src/3rdparty/libucontext/README.md new file mode 100644 index 000000000..d9d5dbe89 --- /dev/null +++ b/src/3rdparty/libucontext/README.md @@ -0,0 +1,105 @@ +# `libucontext` + +`libucontext` is a library which provides the `ucontext.h` C API. Unlike other implementations, +it faithfully follows the kernel process ABI when doing context swaps. + +Notably, when combined with `gcompat`, it provides a fully compatible implementation of the ucontext +functions that are ABI compatible with glibc. + +Since version 0.13, for some architectures, you can deploy to bare metal using newlib via the +`FREESTANDING=yes` make option. Systems which use a syscall cannot work this way. The table +below shows which architecture ports have been adapted to build with `FREESTANDING=yes`. + +Adding support for new architectures is easy, but you need to know assembly language for the +target to do it. + + +## supported features + +| Architecture | Works on musl | Syscall | Supports FREESTANDING | Common trampoline | +|--------------|---------------|---------|-----------------------|-------------------| +| aarch64 | ✓ | | ✓ | ✓ | +| arm | ✓ | | ✓ | ✓ | +| loongarch64 | ✓ | | ✓ | | +| m68k | ✓ | | ✓ | ✓ | +| mips | ✓ | | ✓ | | +| mips64 | ✓ | | ✓ | | +| or1k | ✓ | | ✓ | ✓ | +| ppc | ✓ | ✓ | | | +| ppc64 | ✓ | ✓ | | | +| riscv32 | ✓ | | ✓ | ✓ | +| riscv64 | ✓ | | ✓ | ✓ | +| s390x | ✓ | | ✓ | | +| sh | ✓ | | ✓ | ✓ | +| x86 | ✓ | | ✓ | ✓ | +| x86_64 | ✓ | | ✓ | ✓ | + + +## building + +`libucontext` uses a simple makefile build system. You should define `ARCH=` at build time, otherwise +the build system will attempt to guess using `uname -m`. + +``` +$ make ARCH=x86_64 +$ make ARCH=x86_64 check +$ make ARCH=x86_64 DESTDIR=out install +``` + +There are a few options: + +* `ARCH`: The architecture libucontext is being built for. Must be set to one of the architectures + listed in the feature support table. If unset, the build system will attempt to guess based on what + architecture the host is running. Setting this option explicitly is highly recommended. + +* `FREESTANDING`: If this is set to `yes`, the system ucontext.h headers will not be used. Instead, + the headers in `arch/${ARCH}/freestanding` will be used for definitions where appropriate. + Default is `no`. + +* `EXPORT_UNPREFIXED`: If this is set to `yes`, the POSIX 2004 names `getcontext`, `setcontext`, + `swapcontext` and `makecontext` will be provided as weak symbols aliased against their `libucontext_` + namespaced equivalents. This is necessary for libucontext to provide these functions on musl + systems, but you may wish to disable this when using `FREESTANDING` mode to avoid conflicts with + the target's libc. Default is `yes`. + +* `DESTDIR`: If this variable is set, the installed files will be installed to the specified path instead + of the system root. + +If you have `scdoc` installed, you can build manpages and install them: + +``` +$ make docs +$ make DESTDIR=out install_docs +``` + + +## real-world use cases + +`libucontext` is used on almost all musl distributions to provide the legacy `ucontext.h` API. +Additionally, it is used by: + +* [UTM](https://getutm.app) -- friendly qemu distribution for macOS and iOS devices. UTM uses libucontext + as qemu's coroutine backend. + +* [Lwan](https://lwan.ws) -- a high-performance embeddable asynchronous web server. Lwan uses libucontext + to provide green threads when building on non-x86 architectures. + + +## caveats + +`libucontext`, while largely functionally equivalent does have some differences over traditional POSIX +ucontext functions: + +* Saving and restoring the signal mask is not implemented by default in order to avoid kernel syscall + overhead. Use `-lucontext_posix` if you actually need this functionality, which provides a POSIX + compliant implementation at the cost of performance. + +* Only basic GPR registers are saved and restored when context swapping. The glibc implementation uses + hardware capability detection to save/restore other register groups, such as the FPU registers or + vector processing (AltiVec/AVX/NEON) registers. Adding this capability detection would significantly + increase the complexity of the project and thus is not implemented. Support for compiling in code to + save/restore FPU registers or vector registers may be added in a later release as a build-time + setting -- for now, we assume a soft-float ABI with no optional processor features. In practice, this + does not really matter, code using these functions are unlikely to be impacted by this design + assumption. This is a work in progress, as newer compilers will spill even non-floating-point state + through floating point registers when allowed to do so. diff --git a/src/3rdparty/libucontext/VERSION b/src/3rdparty/libucontext/VERSION new file mode 100644 index 000000000..ea710abb9 --- /dev/null +++ b/src/3rdparty/libucontext/VERSION @@ -0,0 +1 @@ +1.2 \ No newline at end of file diff --git a/src/3rdparty/libucontext/arch/aarch64/defs.h b/src/3rdparty/libucontext/arch/aarch64/defs.h new file mode 100644 index 000000000..5398adcde --- /dev/null +++ b/src/3rdparty/libucontext/arch/aarch64/defs.h @@ -0,0 +1,27 @@ +#ifndef __ARCH_AARCH64_DEFS_H +#define __ARCH_AARCH64_DEFS_H + +#define REG_SZ (8) +#define MCONTEXT_GREGS (184) + +#define R0_OFFSET REG_OFFSET(0) + +#define SP_OFFSET 432 +#define PC_OFFSET 440 +#define PSTATE_OFFSET 448 +#define FPSIMD_CONTEXT_OFFSET 464 + +#ifndef FPSIMD_MAGIC +# define FPSIMD_MAGIC 0x46508001 +#endif + +#ifndef ESR_MAGIC +# define ESR_MAGIC 0x45535201 +#endif + +#define FETCH_LINKPTR(dest) \ + asm("mov %0, x19" : "=r" ((dest))) + +#include "common-defs.h" + +#endif diff --git a/src/3rdparty/libucontext/arch/aarch64/getcontext.S b/src/3rdparty/libucontext/arch/aarch64/getcontext.S new file mode 100644 index 000000000..37390a6bd --- /dev/null +++ b/src/3rdparty/libucontext/arch/aarch64/getcontext.S @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 2020 Ariadne Conill + * + * 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" + +ALIAS(getcontext, libucontext_getcontext) +ALIAS(__getcontext, libucontext_getcontext) + + .global PROC_NAME(libucontext_getcontext); + .align 2; + TYPE(libucontext_getcontext) + ENT(libucontext_getcontext) +PROC_NAME(libucontext_getcontext): + str xzr, [x0, #REG_OFFSET(0)] + + /* save GPRs */ + stp x0, x1, [x0, #REG_OFFSET(0)] + stp x2, x3, [x0, #REG_OFFSET(2)] + stp x4, x5, [x0, #REG_OFFSET(4)] + stp x6, x7, [x0, #REG_OFFSET(6)] + stp x8, x9, [x0, #REG_OFFSET(8)] + stp x10, x11, [x0, #REG_OFFSET(10)] + stp x12, x13, [x0, #REG_OFFSET(12)] + stp x14, x15, [x0, #REG_OFFSET(14)] + stp x16, x17, [x0, #REG_OFFSET(16)] + stp x18, x19, [x0, #REG_OFFSET(18)] + stp x20, x21, [x0, #REG_OFFSET(20)] + stp x22, x23, [x0, #REG_OFFSET(22)] + stp x24, x25, [x0, #REG_OFFSET(24)] + stp x26, x27, [x0, #REG_OFFSET(26)] + stp x28, x29, [x0, #REG_OFFSET(28)] + str x30, [x0, #REG_OFFSET(30)] + + /* 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] + + add x2, x0, #FPSIMD_CONTEXT_OFFSET + stp q8, q9, [x2, #144] + stp q10, q11, [x2, #176] + stp q12, q13, [x2, #208] + stp q14, q15, [x2, #240] + + mov x0, #0 + ret +END(libucontext_getcontext) diff --git a/src/3rdparty/libucontext/arch/aarch64/include/libucontext/bits.h b/src/3rdparty/libucontext/arch/aarch64/include/libucontext/bits.h new file mode 100644 index 000000000..e249448f9 --- /dev/null +++ b/src/3rdparty/libucontext/arch/aarch64/include/libucontext/bits.h @@ -0,0 +1,34 @@ +#ifndef LIBUCONTEXT_BITS_H +#define LIBUCONTEXT_BITS_H + +typedef unsigned long libucontext_greg_t; +typedef unsigned long libucontext_gregset_t[34]; + +typedef struct { + __uint128_t vregs[32]; + unsigned int fpsr; + unsigned int fpcr; +} libucontext_fpregset_t; + +typedef struct sigcontext { + unsigned long fault_address; + unsigned long regs[31]; + unsigned long sp, pc, pstate; + long double __reserved[256]; +} libucontext_mcontext_t; + +typedef struct { + void *ss_sp; + int ss_flags; + size_t ss_size; +} libucontext_stack_t; + +typedef struct libucontext_ucontext { + unsigned long uc_flags; + struct libucontext_ucontext *uc_link; + libucontext_stack_t uc_stack; + unsigned char __pad[136]; + libucontext_mcontext_t uc_mcontext; +} libucontext_ucontext_t; + +#endif diff --git a/src/3rdparty/libucontext/arch/aarch64/makecontext.c b/src/3rdparty/libucontext/arch/aarch64/makecontext.c new file mode 100644 index 000000000..f6823cf6c --- /dev/null +++ b/src/3rdparty/libucontext/arch/aarch64/makecontext.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018 Ariadne Conill + * + * 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 +#include +#include +#include +#include +#include "defs.h" +#include + + +extern void libucontext_trampoline(void); + +_Static_assert(offsetof(libucontext_ucontext_t, uc_mcontext.regs[0]) == R0_OFFSET, "R0_OFFSET is invalid"); +_Static_assert(offsetof(libucontext_ucontext_t, uc_mcontext.sp) == SP_OFFSET, "SP_OFFSET is invalid"); +_Static_assert(offsetof(libucontext_ucontext_t, uc_mcontext.pc) == PC_OFFSET, "PC_OFFSET is invalid"); +_Static_assert(offsetof(libucontext_ucontext_t, uc_mcontext.pstate) == PSTATE_OFFSET, "PSTATE_OFFSET is invalid"); + +void +libucontext_makecontext(libucontext_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) &libucontext_trampoline; + + 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); +} + +#ifdef EXPORT_UNPREFIXED +extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +#endif diff --git a/src/3rdparty/libucontext/arch/aarch64/setcontext.S b/src/3rdparty/libucontext/arch/aarch64/setcontext.S new file mode 100644 index 000000000..f34836026 --- /dev/null +++ b/src/3rdparty/libucontext/arch/aarch64/setcontext.S @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018, 2020 Ariadne Conill + * + * 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" + +ALIAS(setcontext, libucontext_setcontext) +ALIAS(__setcontext, libucontext_setcontext) + + .global PROC_NAME(libucontext_setcontext); + .align 2; + TYPE(libucontext_setcontext) + ENT(libucontext_setcontext) +PROC_NAME(libucontext_setcontext): + /* restore GPRs */ + ldp x18, x19, [x0, #REG_OFFSET(18)] + ldp x20, x21, [x0, #REG_OFFSET(20)] + ldp x22, x23, [x0, #REG_OFFSET(22)] + ldp x24, x25, [x0, #REG_OFFSET(24)] + ldp x26, x27, [x0, #REG_OFFSET(26)] + ldp x28, x29, [x0, #REG_OFFSET(28)] + ldr x30, [x0, #REG_OFFSET(30)] + + /* save current stack pointer */ + ldr x2, [x0, #SP_OFFSET] + mov sp, x2 + + add x2, x0, #FPSIMD_CONTEXT_OFFSET + ldp q8, q9, [x2, #144] + ldp q10, q11, [x2, #176] + ldp q12, q13, [x2, #208] + ldp q14, q15, [x2, #240] + + /* save current program counter in link register */ + ldr x16, [x0, #PC_OFFSET] + + /* restore args */ + ldp x2, x3, [x0, #REG_OFFSET(2)] + ldp x4, x5, [x0, #REG_OFFSET(4)] + ldp x6, x7, [x0, #REG_OFFSET(6)] + ldp x0, x1, [x0, #REG_OFFSET(0)] + + /* jump to new PC */ + br x16 +END(libucontext_setcontext) diff --git a/src/3rdparty/libucontext/arch/aarch64/swapcontext.S b/src/3rdparty/libucontext/arch/aarch64/swapcontext.S new file mode 100644 index 000000000..fc587e389 --- /dev/null +++ b/src/3rdparty/libucontext/arch/aarch64/swapcontext.S @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018 Ariadne Conill + * + * 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" + +ALIAS(swapcontext, libucontext_swapcontext) +ALIAS(__swapcontext, libucontext_swapcontext) + + .global PROC_NAME(libucontext_swapcontext); + .align 2; + TYPE(libucontext_swapcontext) + ENT(libucontext_swapcontext) +PROC_NAME(libucontext_swapcontext): + str xzr, [x0, #REG_OFFSET(0)] + + /* save GPRs */ + stp x2, x3, [x0, #REG_OFFSET(2)] + stp x4, x5, [x0, #REG_OFFSET(4)] + stp x6, x7, [x0, #REG_OFFSET(6)] + stp x8, x9, [x0, #REG_OFFSET(8)] + stp x10, x11, [x0, #REG_OFFSET(10)] + stp x12, x13, [x0, #REG_OFFSET(12)] + stp x14, x15, [x0, #REG_OFFSET(14)] + stp x16, x17, [x0, #REG_OFFSET(16)] + stp x18, x19, [x0, #REG_OFFSET(18)] + stp x20, x21, [x0, #REG_OFFSET(20)] + stp x22, x23, [x0, #REG_OFFSET(22)] + stp x24, x25, [x0, #REG_OFFSET(24)] + stp x26, x27, [x0, #REG_OFFSET(26)] + stp x28, x29, [x0, #REG_OFFSET(28)] + str x30, [x0, #REG_OFFSET(30)] + + /* 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] + + add x2, x0, #FPSIMD_CONTEXT_OFFSET + stp q8, q9, [x2, #144] + stp q10, q11, [x2, #176] + stp q12, q13, [x2, #208] + stp q14, q15, [x2, #240] + + /* 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 PROC_NAME(libucontext_setcontext) + + /* hmm, we came back here try to return */ + mov x30, x28 + ret +END(libucontext_swapcontext) diff --git a/src/3rdparty/libucontext/arch/aarch64/trampoline.c b/src/3rdparty/libucontext/arch/aarch64/trampoline.c new file mode 100644 index 000000000..699a0505d --- /dev/null +++ b/src/3rdparty/libucontext/arch/aarch64/trampoline.c @@ -0,0 +1,3 @@ +#include "defs.h" +#include +#include "common-trampoline.c" diff --git a/src/3rdparty/libucontext/arch/arm/defs.h b/src/3rdparty/libucontext/arch/arm/defs.h new file mode 100644 index 000000000..1c3b7ddea --- /dev/null +++ b/src/3rdparty/libucontext/arch/arm/defs.h @@ -0,0 +1,15 @@ +#ifndef __ARCH_ARM_DEFS_H + +#define REG_SZ (4) +#define MCONTEXT_GREGS (32) +#define VFP_MAGIC_OFFSET (232) +#define VFP_D8_OFFSET (304) + +#define TYPE(__proc) .type __proc, %function; + +#define FETCH_LINKPTR(dest) \ + asm("movs %0, r4" : "=r" ((dest))) + +#include "common-defs.h" + +#endif diff --git a/src/3rdparty/libucontext/arch/arm/getcontext.S b/src/3rdparty/libucontext/arch/arm/getcontext.S new file mode 100644 index 000000000..0afa1506b --- /dev/null +++ b/src/3rdparty/libucontext/arch/arm/getcontext.S @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018, 2020 Ariadne Conill + * + * 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" + +ALIAS(getcontext, libucontext_getcontext) +ALIAS(__getcontext, libucontext_getcontext) + +FUNC(libucontext_getcontext) + /* copy all of the current registers into the ucontext structure */ + add r1, r0, #REG_OFFSET(4) + stmia r1, {r4-r12} + str r13, [r0, #REG_OFFSET(13)] + str r14, [r0, #REG_OFFSET(15)] + +#ifndef FORCE_SOFT_FLOAT +#ifndef FORCE_HARD_FLOAT + /* test for vfp, set kernel-defined magic number in uc_regspace */ + push {r0-r1,fp,lr} + mov r0, #16 + bl getauxval + tst r0, #64 + pop {r0-r1,fp,lr} + moveq r2, #0 + ldrne r2, =#0x56465001 + str r2, [r0, #VFP_MAGIC_OFFSET] + beq 1f +#endif + /* if vfp detected, save d8-d15 */ + .fpu vfp + add r1, r0, #VFP_D8_OFFSET + vstmia r1, {d8-d15} + .fpu softvfp +1: +#endif + + /* return 0 */ + mov r0, #0 + mov pc, lr +END(libucontext_getcontext) diff --git a/src/3rdparty/libucontext/arch/arm/include/libucontext/bits.h b/src/3rdparty/libucontext/arch/arm/include/libucontext/bits.h new file mode 100644 index 000000000..caad8d4bd --- /dev/null +++ b/src/3rdparty/libucontext/arch/arm/include/libucontext/bits.h @@ -0,0 +1,30 @@ +#ifndef LIBUCONTEXT_BITS_H +#define LIBUCONTEXT_BITS_H + +typedef int libucontext_greg_t, libucontext_gregset_t[18]; + +typedef struct { + unsigned long trap_no, error_code, oldmask; + unsigned long arm_r0, arm_r1, arm_r2, arm_r3; + unsigned long arm_r4, arm_r5, arm_r6, arm_r7; + unsigned long arm_r8, arm_r9, arm_r10, arm_fp; + unsigned long arm_ip, arm_sp, arm_lr, arm_pc; + unsigned long arm_cpsr, fault_address; +} libucontext_mcontext_t; + +typedef struct { + void *ss_sp; + int ss_flags; + size_t ss_size; +} libucontext_stack_t; + +typedef struct libucontext_ucontext { + unsigned long uc_flags; + struct libucontext_ucontext *uc_link; + libucontext_stack_t uc_stack; + libucontext_mcontext_t uc_mcontext; + unsigned long uc_sigmask[128 / sizeof(long)]; + unsigned long long uc_regspace[64]; +} libucontext_ucontext_t; + +#endif diff --git a/src/3rdparty/libucontext/arch/arm/makecontext.c b/src/3rdparty/libucontext/arch/arm/makecontext.c new file mode 100644 index 000000000..b137a16f8 --- /dev/null +++ b/src/3rdparty/libucontext/arch/arm/makecontext.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, 2020 Ariadne Conill + * + * 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 +#include +#include +#include +#include + + +#include "defs.h" +#include + + +extern void libucontext_trampoline(void); + + +void +libucontext_makecontext(libucontext_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 = (unsigned long *) (((uintptr_t) sp & -16L) - 8); + + if (argc > 4) + sp -= (argc - 4); + + ucp->uc_mcontext.arm_sp = (uintptr_t) sp; + ucp->uc_mcontext.arm_pc = (uintptr_t) func; + ucp->uc_mcontext.arm_r4 = (uintptr_t) ucp->uc_link; + ucp->uc_mcontext.arm_lr = (uintptr_t) &libucontext_trampoline; + + va_start(va, argc); + + regp = &(ucp->uc_mcontext.arm_r0); + + for (i = 0; (i < argc && i < 4); i++) + *regp++ = va_arg (va, unsigned long); + + for (; i < argc; i++) + *sp++ = va_arg (va, unsigned long); + + va_end(va); +} + +#ifdef EXPORT_UNPREFIXED +extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +#endif diff --git a/src/3rdparty/libucontext/arch/arm/setcontext.S b/src/3rdparty/libucontext/arch/arm/setcontext.S new file mode 100644 index 000000000..792d8f272 --- /dev/null +++ b/src/3rdparty/libucontext/arch/arm/setcontext.S @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018, 2020 Ariadne Conill + * + * 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" + +ALIAS(setcontext, libucontext_setcontext) +ALIAS(__setcontext, libucontext_setcontext) + +FUNC(libucontext_setcontext) +#ifndef FORCE_SOFT_FLOAT +#ifndef FORCE_HARD_FLOAT + /* test for vfp magic number set by getcontext */ + ldr r2, [r0, #VFP_MAGIC_OFFSET] + ldr r3, =#0x56465001 + cmp r2, r3 + bne 1f +#endif + /* if vfp in use, restore d8-d15 from uc_regspace */ + .fpu vfp + add r14, r0, #VFP_D8_OFFSET + vldmia r14, {d8-d15} + .fpu softvfp +1: +#endif + + /* copy all of the current registers into the ucontext structure */ + add r14, r0, #REG_OFFSET(0) + ldmia r14, {r0-r12} + ldr r13, [r14, #52] + add r14, r14, #56 + + /* load link register and jump to new context */ + ldmia r14, {r14, pc} +END(libucontext_setcontext) diff --git a/src/3rdparty/libucontext/arch/arm/swapcontext.S b/src/3rdparty/libucontext/arch/arm/swapcontext.S new file mode 100644 index 000000000..f8411828f --- /dev/null +++ b/src/3rdparty/libucontext/arch/arm/swapcontext.S @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018, 2020 Ariadne Conill + * + * 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" + +ALIAS(swapcontext, libucontext_swapcontext) +ALIAS(__swapcontext, libucontext_swapcontext) + +FUNC(libucontext_swapcontext) + /* copy all of the current registers into the ucontext structure */ + add r2, r0, #REG_OFFSET(0) + stmia r2, {r0-r12} + str r13, [r0,#REG_OFFSET(13)] + str r14, [r0,#REG_OFFSET(15)] + +#ifndef FORCE_SOFT_FLOAT +#ifndef FORCE_HARD_FLOAT + /* test for vfp magic number, copy to other ucontext */ + ldr r3, [r1, #VFP_MAGIC_OFFSET] + ldr r4, =#0x56465001 + str r3, [r0, #VFP_MAGIC_OFFSET] + cmp r3, r4 + bne 1f +#endif + /* if vfp in use, save and restore d8-d15 */ + .fpu vfp + add r2, r0, #VFP_D8_OFFSET + vstmia r2, {d8-d15} + + add r14, r1, #VFP_D8_OFFSET + vldmia r14, {d8-d15} + .fpu softvfp +1: +#endif + + /* load new registers from the second ucontext structure */ + add r14, r1, #REG_OFFSET(0) + ldmia r14, {r0-r12} + ldr r13, [r14, #52] + add r14, r14, #56 + ldmia r14, {r14, pc} +END(libucontext_swapcontext) diff --git a/src/3rdparty/libucontext/arch/arm/trampoline.c b/src/3rdparty/libucontext/arch/arm/trampoline.c new file mode 100644 index 000000000..699a0505d --- /dev/null +++ b/src/3rdparty/libucontext/arch/arm/trampoline.c @@ -0,0 +1,3 @@ +#include "defs.h" +#include +#include "common-trampoline.c" diff --git a/src/3rdparty/libucontext/arch/common/common-defs.h b/src/3rdparty/libucontext/arch/common/common-defs.h new file mode 100644 index 000000000..8ba97bfd4 --- /dev/null +++ b/src/3rdparty/libucontext/arch/common/common-defs.h @@ -0,0 +1,61 @@ +#ifndef __ARCH_COMMON_COMMON_DEFS_H +#define __ARCH_COMMON_COMMON_DEFS_H + +#ifndef SETUP_FRAME +# define SETUP_FRAME(__proc) +#endif + +#ifndef PUSH_FRAME +# define PUSH_FRAME(__proc) +#endif + +#ifndef POP_FRAME +# define POP_FRAME(__proc) +#endif + +#ifndef ENT +# define ENT(__proc) +#endif + +#ifndef TYPE +# ifdef __clang__ +# define TYPE(__proc) // .type not supported +# else +# define TYPE(__proc) .type __proc, @function; +#endif +#endif + +#ifndef PROC_NAME +# ifdef __MACH__ +# define PROC_NAME(__proc) _ ## __proc +# else +# define PROC_NAME(__proc) __proc +# endif +#endif + +#define FUNC(__proc) \ + .global PROC_NAME(__proc); \ + .align 2; \ + TYPE(__proc) \ + ENT(__proc) \ +PROC_NAME(__proc): \ + SETUP_FRAME(__proc) +#ifdef __clang__ +#define END(__proc) +#else +#define END(__proc) \ + .end __proc; \ + .size __proc,.-__proc; +#endif + +#ifdef EXPORT_UNPREFIXED +#define ALIAS(__alias, __real) \ + .weak __alias; \ + __alias = __real; +#else +#define ALIAS(...) +#endif + +#define REG_OFFSET(__reg) (MCONTEXT_GREGS + ((__reg) * REG_SZ)) + +#endif diff --git a/src/3rdparty/libucontext/arch/common/common-trampoline.c b/src/3rdparty/libucontext/arch/common/common-trampoline.c new file mode 100644 index 000000000..5b5232760 --- /dev/null +++ b/src/3rdparty/libucontext/arch/common/common-trampoline.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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 +#include +#include + +__attribute__ ((visibility ("hidden"))) +void +libucontext_trampoline(void) +{ + register libucontext_ucontext_t *uc_link = NULL; + + FETCH_LINKPTR(uc_link); + + if (uc_link == NULL) + exit(0); + + libucontext_setcontext(uc_link); +} diff --git a/src/3rdparty/libucontext/arch/common/include/libucontext/bits.h b/src/3rdparty/libucontext/arch/common/include/libucontext/bits.h new file mode 100644 index 000000000..65a039f59 --- /dev/null +++ b/src/3rdparty/libucontext/arch/common/include/libucontext/bits.h @@ -0,0 +1,13 @@ +#ifndef LIBUCONTEXT_BITS_H +#define LIBUCONTEXT_BITS_H + +#ifndef FREESTANDING + +#include + +typedef greg_t libucontext_greg_t; +typedef ucontext_t libucontext_ucontext_t; + +#endif + +#endif diff --git a/src/3rdparty/libucontext/arch/loongarch64/defs.h b/src/3rdparty/libucontext/arch/loongarch64/defs.h new file mode 100644 index 000000000..94d014a8e --- /dev/null +++ b/src/3rdparty/libucontext/arch/loongarch64/defs.h @@ -0,0 +1,76 @@ +#ifndef __ARCH_LOONGARCH64_DEFS_H +#define __ARCH_LOONGARCH64_DEFS_H + +#define REG_SZ (8) + +#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) + +/* $a0 is $4 , also $v0, same as $5, $a1 and $v1*/ +#define REG_A0 (4) + +/* stack pointer is actually $3 */ +#define REG_SP (3) + +/* frame pointer is actually $22 */ +#define REG_FP (22) + +/* offset to mc_gregs in ucontext_t */ +#define MCONTEXT_GREGS (48) + +/* offset to PC in ucontext_t */ +#define MCONTEXT_PC (40) + +/* offset to uc_link in ucontext_t */ +#define UCONTEXT_UC_LINK (8) + +/* offset to uc_stack.ss_sp in ucontext_t */ +#define UCONTEXT_STACK_PTR (16) + +/* offset to uc_stack.ss_size in ucontext_t */ +#define UCONTEXT_STACK_SIZE (32) + +/* Stack alignment, from Kernel source */ +#define ALSZ 15 +#define ALMASK ~15 +#define FRAMESZ (((LOCALSZ * REG_SZ) + ALSZ) & ALMASK) + +#define PUSH_FRAME(__proc) \ + addi.d $sp, $sp, -FRAMESZ; + +#define POP_FRAME(__proc) \ + addi.d $sp, $sp, FRAMESZ; + +#include + +#endif diff --git a/src/3rdparty/libucontext/arch/loongarch64/freestanding/bits.h b/src/3rdparty/libucontext/arch/loongarch64/freestanding/bits.h new file mode 100644 index 000000000..b567678c5 --- /dev/null +++ b/src/3rdparty/libucontext/arch/loongarch64/freestanding/bits.h @@ -0,0 +1,43 @@ +#ifndef LIBUCONTEXT_BITS_H +#define LIBUCONTEXT_BITS_H + +typedef unsigned long long libucontext_greg_t, libucontext_gregset_t[32]; + +/* Container for all general registers. */ +typedef __loongarch_mc_gp_state gregset_t; + +/* Container for floating-point state. */ +typedef union __loongarch_mc_fp_state fpregset_t; + +union __loongarch_mc_fp_state { + unsigned int __val32[256 / 32]; + unsigned long long __val64[256 / 64]; +}; + +typedef struct mcontext_t { + unsigned long long __pc; + unsigned long long __gregs[32]; + unsigned int __flags; + + unsigned int __fcsr; + unsigned int __vcsr; + unsigned long long __fcc; + union __loongarch_mc_fp_state __fpregs[32] __attribute__((__aligned__ (32))); + + unsigned int __reserved; +} mcontext_t; + +typedef struct { + void *ss_sp; + int ss_flags; + size_t ss_size; +} libucontext_stack_t; + +typedef struct libucontext_ucontext { + unsigned long uc_flags; + struct libucontext_ucontext *uc_link; + libucontext_stack_t uc_stack; + libucontext_mcontext_t uc_mcontext; +} libucontext_ucontext_t; + +#endif diff --git a/src/3rdparty/libucontext/arch/loongarch64/getcontext.S b/src/3rdparty/libucontext/arch/loongarch64/getcontext.S new file mode 100644 index 000000000..49c90a9e8 --- /dev/null +++ b/src/3rdparty/libucontext/arch/loongarch64/getcontext.S @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Peng Fan + * + * 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 LOCALSZ (1) + +#include "defs.h" + +ALIAS(getcontext, libucontext_getcontext) + +FUNC(libucontext_getcontext) + /* copy $sp, $fp to temporary registers so we don't clobber them */ + move $a2, $sp + move $a3, $fp + + PUSH_FRAME(libucontext_getcontext) + + /* set registers */ + st.d $s0, $a0, REG_OFFSET(23) + st.d $s1, $a0, REG_OFFSET(24) + st.d $s2, $a0, REG_OFFSET(25) + st.d $s3, $a0, REG_OFFSET(26) + st.d $s4, $a0, REG_OFFSET(27) + st.d $s5, $a0, REG_OFFSET(28) + st.d $s6, $a0, REG_OFFSET(29) + st.d $s7, $a0, REG_OFFSET(30) + st.d $s8, $a0, REG_OFFSET(31) + + st.d $a2, $a0, REG_OFFSET(3) + st.d $a3, $a0, REG_OFFSET(22) + st.d $ra, $a0, REG_OFFSET(1) + + st.d $ra, $a0, (MCONTEXT_PC) + + POP_FRAME(libucontext_getcontext) + + jr $ra +END(libucontext_getcontext) diff --git a/src/3rdparty/libucontext/arch/loongarch64/makecontext.S b/src/3rdparty/libucontext/arch/loongarch64/makecontext.S new file mode 100644 index 000000000..44ec9a593 --- /dev/null +++ b/src/3rdparty/libucontext/arch/loongarch64/makecontext.S @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021 Peng Fan + * + * 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" + +#define LOCALSZ (6) + +#define A3_OFF (FRAMESZ - (5 * REG_SZ)) +#define A4_OFF (FRAMESZ - (4 * REG_SZ)) +#define A5_OFF (FRAMESZ - (3 * REG_SZ)) +#define A6_OFF (FRAMESZ - (2 * REG_SZ)) +#define A7_OFF (FRAMESZ - (1 * REG_SZ)) + +ALIAS(makecontext, libucontext_makecontext) + +FUNC(libucontext_makecontext) + PUSH_FRAME(libucontext_makecontext) + + move $t5, $a0 + move $t4, $a1 + + /* store $a3 through $a7 to the stack frame. */ + st.d $a3, $sp, A3_OFF + st.d $a4, $sp, A4_OFF + st.d $a5, $sp, A5_OFF + st.d $a6, $sp, A6_OFF + st.d $a7, $sp, A7_OFF + + /* set $zero in the mcontext to 1. */ + addi.d $v0, $zero, 1 + st.d $v0, $t5, REG_OFFSET(0) + + /* ensure the stack is aligned on a quad-word boundary. */ + ld.d $t0, $t5, UCONTEXT_STACK_PTR + ld.d $t2, $t5, UCONTEXT_STACK_SIZE + /* the third argument(from zero), that's the first argument of func() */ + addi.d $t1, $sp, A3_OFF + add.d $t0, $t0, $t2 + + addi.d $t7, $zero, ALMASK + and $t0, $t0, $t7 + + /* number of args */ + beq $a2, $zero, no_more_arguments + bltu $a2, $zero, no_more_arguments + + /* store register arguments. */ + addi.d $t2, $t5, MCONTEXT_GREGS + (4 * REG_SZ) + move $t3, $zero + +store_register_arg: + addi.d $t3, $t3, 1 + ld.d $v1, $t1, 0 + addi.d $t1, $t1, REG_SZ + st.d $v1, $t2, 0 + addi.d $t2, $t2, REG_SZ + addi.d $t6, $zero, 8 + bltu $t3, $t6, store_register_arg + bgeu $t3, $a2, no_more_arguments + + /* make room for stack arguments. */ + sub.d $t2, $a2, $t3 + + addi.d $t6, $zero, 3 + sll.d $t2, $t2, $t6 + + sub.d $t0, $t0, $t2 + + addi.d $t6, $zero, ALMASK + and $t0, $t0, $t6 + + /* store stack arguments. */ + move $t2, $t0 + +store_stack_arg: + addi.d $t3, $t3, 1 + ld.d $v1, $t1, 0 + addi.d $t1, $t1, REG_SZ + st.d $v1, $t2, 0 + addi.d $t2, $t2, REG_SZ + bltu $t3, $a2, store_stack_arg + +no_more_arguments: + /* trampoline setup. */ + la.got $t8, libucontext_trampoline + + ld.d $v1, $t5, UCONTEXT_UC_LINK + st.d $v1, $t5, REG_OFFSET(23) + + st.d $t0, $t5, REG_OFFSET(3) + + st.d $t8, $t5, REG_OFFSET(1) + + st.d $t4, $t5, MCONTEXT_PC + + POP_FRAME(libucontext_makecontext) + + jr $ra +END(libucontext_makecontext) diff --git a/src/3rdparty/libucontext/arch/loongarch64/setcontext.S b/src/3rdparty/libucontext/arch/loongarch64/setcontext.S new file mode 100644 index 000000000..9a0e0b7ea --- /dev/null +++ b/src/3rdparty/libucontext/arch/loongarch64/setcontext.S @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 Peng Fan + * + * 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 LOCALSZ (1) + +#include "defs.h" + +ALIAS(setcontext, libucontext_setcontext) + +FUNC(libucontext_setcontext) + PUSH_FRAME(libucontext_setcontext) + + /* move the context to $v0, in LA, $v0 = $a0 = $4 */ + move $t5, $a0 + + /* load the registers */ + ld.d $a0, $t5, REG_OFFSET(4) + ld.d $a1, $t5, REG_OFFSET(5) + ld.d $a2, $t5, REG_OFFSET(6) + ld.d $a3, $t5, REG_OFFSET(7) + ld.d $a4, $t5, REG_OFFSET(8) + ld.d $a5, $t5, REG_OFFSET(9) + ld.d $a6, $t5, REG_OFFSET(10) + ld.d $a7, $t5, REG_OFFSET(11) + + ld.d $s0, $t5, REG_OFFSET(23) + ld.d $s1, $t5, REG_OFFSET(24) + ld.d $s2, $t5, REG_OFFSET(25) + ld.d $s3, $t5, REG_OFFSET(26) + ld.d $s4, $t5, REG_OFFSET(27) + ld.d $s5, $t5, REG_OFFSET(28) + ld.d $s6, $t5, REG_OFFSET(29) + ld.d $s7, $t5, REG_OFFSET(30) + ld.d $s8, $t5, REG_OFFSET(31) + + ld.d $sp, $t5, REG_OFFSET(3) + ld.d $fp, $t5, REG_OFFSET(22) + ld.d $ra, $t5, REG_OFFSET(1) + + ld.d $t8, $t5, (MCONTEXT_PC) + + jr $t8 + move $v0, $zero + + POP_FRAME(libucontext_setcontext) +END(libucontext_setcontext) diff --git a/src/3rdparty/libucontext/arch/loongarch64/startcontext.S b/src/3rdparty/libucontext/arch/loongarch64/startcontext.S new file mode 100644 index 000000000..b26450c0c --- /dev/null +++ b/src/3rdparty/libucontext/arch/loongarch64/startcontext.S @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Peng Fan + * + * 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 LOCALSZ (4) + +#include "defs.h" + +FUNC(libucontext_trampoline) + + /* call setcontext */ + move $a0, $s0 + /* we receive our initial ucontext in $s0, so if $s0 is nil, bail */ + beqz $s0, no_linked_context + + la.got $t8, libucontext_setcontext + + jr $t8 + +no_linked_context: + move $a0, $zero + la.global $t8, exit + jr $t8 + +END(libucontext_trampoline) diff --git a/src/3rdparty/libucontext/arch/loongarch64/swapcontext.S b/src/3rdparty/libucontext/arch/loongarch64/swapcontext.S new file mode 100644 index 000000000..b5063f68b --- /dev/null +++ b/src/3rdparty/libucontext/arch/loongarch64/swapcontext.S @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021 Peng Fan + * + * 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 LOCALSZ (4) + +#include "defs.h" + +#define A1_OFFSET (FRAMESZ - (1 * REG_SZ)) + +ALIAS(swapcontext, libucontext_swapcontext) + +FUNC(libucontext_swapcontext) + /* copy $sp, $fp to temporary registers so we don't clobber them */ + move $a3, $sp + move $a4, $fp + + move $t5, $a0 + + PUSH_FRAME(libucontext_swapcontext) + + /* set registers */ + st.d $s0, $t5, REG_OFFSET(23) + st.d $s1, $t5, REG_OFFSET(24) + st.d $s2, $t5, REG_OFFSET(25) + st.d $s3, $t5, REG_OFFSET(26) + st.d $s4, $t5, REG_OFFSET(27) + st.d $s5, $t5, REG_OFFSET(28) + st.d $s6, $t5, REG_OFFSET(29) + st.d $s7, $t5, REG_OFFSET(30) + st.d $s8, $t5, REG_OFFSET(31) + + st.d $a3, $t5, REG_OFFSET(3) + st.d $a4, $t5, REG_OFFSET(22) + st.d $ra, $t5, REG_OFFSET(1) + + st.d $ra, $t5, (MCONTEXT_PC) + + /* copy new context address in $a1 to stack */ + st.d $a1, $sp, A1_OFFSET + + /* load new context address into $v0 */ + ld.d $t4, $sp, A1_OFFSET + + /* load the registers */ + ld.d $a0, $t4, REG_OFFSET(4) + ld.d $a1, $t4, REG_OFFSET(5) + ld.d $a2, $t4, REG_OFFSET(6) + ld.d $a3, $t4, REG_OFFSET(7) + ld.d $a4, $t4, REG_OFFSET(8) + ld.d $a5, $t4, REG_OFFSET(9) + ld.d $a6, $t4, REG_OFFSET(10) + ld.d $a7, $t4, REG_OFFSET(11) + + ld.d $s0, $t4, REG_OFFSET(23) + ld.d $s1, $t4, REG_OFFSET(24) + ld.d $s2, $t4, REG_OFFSET(25) + ld.d $s3, $t4, REG_OFFSET(26) + ld.d $s4, $t4, REG_OFFSET(27) + ld.d $s5, $t4, REG_OFFSET(28) + ld.d $s6, $t4, REG_OFFSET(29) + ld.d $s7, $t4, REG_OFFSET(30) + ld.d $s8, $t4, REG_OFFSET(31) + + ld.d $sp, $t4, REG_OFFSET(3) + ld.d $fp, $t4, REG_OFFSET(22) + ld.d $ra, $t4, REG_OFFSET(1) + + ld.d $t8, $t4, (MCONTEXT_PC) + + jr $t8 + move $v0, $zero + +fail: + la.global $t8, exit + + POP_FRAME(libucontext_swapcontext) + + jirl $ra, $t8, 0 + move $v0, $zero +END(libucontext_swapcontext) diff --git a/src/3rdparty/libucontext/arch/m68k/defs.h b/src/3rdparty/libucontext/arch/m68k/defs.h new file mode 100644 index 000000000..fc1925280 --- /dev/null +++ b/src/3rdparty/libucontext/arch/m68k/defs.h @@ -0,0 +1,34 @@ +#ifndef __ARCH_M68K_DEFS_H +#define __ARCH_M68K_DEFS_H + +#define REG_SZ (4) +#define MCONTEXT_GREGS (24) + +#define REG_D0 (0) +#define REG_D1 (1) +#define REG_D2 (2) +#define REG_D3 (3) +#define REG_D4 (4) +#define REG_D5 (5) +#define REG_D6 (6) +#define REG_D7 (7) +#define REG_A0 (8) +#define REG_A1 (9) +#define REG_A2 (10) +#define REG_A3 (11) +#define REG_A4 (12) +#define REG_A5 (13) +#define REG_A6 (14) +#define REG_A7 (15) +#define REG_SP (15) +#define REG_PC (16) +#define REG_PS (17) + +#define PC_OFFSET REG_OFFSET(REG_PC) + +#define FETCH_LINKPTR(dest) \ + asm("mov.l (%%sp, %%d7.l * 4), %0" :: "r" ((dest))) + +#include "common-defs.h" + +#endif diff --git a/src/3rdparty/libucontext/arch/m68k/getcontext.S b/src/3rdparty/libucontext/arch/m68k/getcontext.S new file mode 100644 index 000000000..40f2c1490 --- /dev/null +++ b/src/3rdparty/libucontext/arch/m68k/getcontext.S @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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" + +ALIAS(getcontext, libucontext_getcontext) +ALIAS(__getcontext, libucontext_getcontext) + +FUNC(libucontext_getcontext) + move.l 4(%sp), %a0 /* load ucontext_t pointer from stack */ + + movem.l %d2-%d7, REG_OFFSET(REG_D2)(%a0) /* preserve $d2 through $d7 */ + movem.l %a2-%a6, REG_OFFSET(REG_A2)(%a0) /* preserve $a2 through $a6 */ + + lea 4(%sp), %a1 /* load stack pointer into $a1 */ + move.l %a1, REG_OFFSET(REG_SP)(%a0) /* store $a1 in ucontext */ + move.l (%sp), REG_OFFSET(REG_PC)(%a0) /* store return address in ucontext's PC register */ + + clr.l %d0 /* return 0 */ + rts +END(libucontext_getcontext) diff --git a/src/3rdparty/libucontext/arch/m68k/include/libucontext/bits.h b/src/3rdparty/libucontext/arch/m68k/include/libucontext/bits.h new file mode 100644 index 000000000..17d3bf80b --- /dev/null +++ b/src/3rdparty/libucontext/arch/m68k/include/libucontext/bits.h @@ -0,0 +1,28 @@ +#ifndef LIBUCONTEXT_BITS_H +#define LIBUCONTEXT_BITS_H + +typedef struct sigaltstack { + void *ss_sp; + int ss_flags; + size_t ss_size; +} libucontext_stack_t; + +typedef int libucontext_greg_t, libucontext_gregset_t[18]; +typedef struct { + int f_pcr, f_psr, f_fpiaddr, f_fpregs[8][3]; +} libucontext_fpregset_t; + +typedef struct { + int version; + libucontext_gregset_t gregs; + libucontext_fpregset_t fpregs; +} libucontext_mcontext_t; + +typedef struct libucontext_ucontext { + unsigned long uc_flags; + struct libucontext_ucontext *uc_link; + libucontext_stack_t uc_stack; + libucontext_mcontext_t uc_mcontext; +} libucontext_ucontext_t; + +#endif diff --git a/src/3rdparty/libucontext/arch/m68k/makecontext.c b/src/3rdparty/libucontext/arch/m68k/makecontext.c new file mode 100644 index 000000000..c1a38e27c --- /dev/null +++ b/src/3rdparty/libucontext/arch/m68k/makecontext.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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 +#include +#include +#include +#include +#include "defs.h" +#include + + +extern void libucontext_trampoline(void); + + +void +libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(void), int argc, ...) +{ + libucontext_greg_t *sp; + va_list va; + int i; + + /* set up and align the stack. */ + sp = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); + sp -= (argc + 2); + sp = (libucontext_greg_t *) (((uintptr_t) sp & ~0x3)); + + /* set up the ucontext structure */ + ucp->uc_mcontext.gregs[REG_SP] = (libucontext_greg_t) sp; + ucp->uc_mcontext.gregs[REG_A6] = 0; + ucp->uc_mcontext.gregs[REG_D7] = argc; + ucp->uc_mcontext.gregs[REG_PC] = (libucontext_greg_t) func; + + /* return address */ + *sp++ = (libucontext_greg_t) libucontext_trampoline; + + va_start(va, argc); + + /* all arguments overflow into stack */ + for (i = 0; i < argc; i++) + *sp++ = va_arg (va, libucontext_greg_t); + + va_end(va); + + /* link pointer */ + *sp++ = (libucontext_greg_t) ucp->uc_link; +} + +#ifdef EXPORT_UNPREFIXED +extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +#endif diff --git a/src/3rdparty/libucontext/arch/m68k/setcontext.S b/src/3rdparty/libucontext/arch/m68k/setcontext.S new file mode 100644 index 000000000..994c37eae --- /dev/null +++ b/src/3rdparty/libucontext/arch/m68k/setcontext.S @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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" + +ALIAS(setcontext, libucontext_setcontext) +ALIAS(__setcontext, libucontext_setcontext) + +FUNC(libucontext_setcontext) + move.l 4(%sp), %a0 /* load ucontext_t pointer from stack */ + + move.l REG_OFFSET(REG_SP)(%a0), %sp /* load new stack pointer */ + + movem.l REG_OFFSET(REG_D2)(%a0), %d2-%d7 /* load $d2 through $d7 */ + movem.l REG_OFFSET(REG_A2)(%a0), %a2-%a6 /* load $a2 through $a6 */ + + clr.l %d0 /* clear $d0 */ + + move.l REG_OFFSET(REG_PC)(%a0), %a1 /* load jump target */ + + jmp (%a1) /* jump to *$a1 */ +END(libucontext_setcontext) diff --git a/src/3rdparty/libucontext/arch/m68k/swapcontext.S b/src/3rdparty/libucontext/arch/m68k/swapcontext.S new file mode 100644 index 000000000..e74eca5a7 --- /dev/null +++ b/src/3rdparty/libucontext/arch/m68k/swapcontext.S @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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" + +ALIAS(swapcontext, libucontext_swapcontext) +ALIAS(__swapcontext, libucontext_swapcontext) + +FUNC(libucontext_swapcontext) + move.l 4(%sp), %a0 /* load save ucontext_t pointer from stack */ + + movem.l %d2-%d7, REG_OFFSET(REG_D2)(%a0) /* preserve $d2 through $d7 */ + movem.l %a2-%a6, REG_OFFSET(REG_A2)(%a0) /* preserve $a2 through $a6 */ + + lea 4(%sp), %a1 /* load stack pointer into $a1 */ + move.l %a1, REG_OFFSET(REG_SP)(%a0) /* store $a1 in ucontext */ + move.l (%sp), REG_OFFSET(REG_PC)(%a0) /* store return address in ucontext's PC register */ + + move.l 8(%sp), %a0 /* load new ucontext_t pointer from stack */ + + move.l REG_OFFSET(REG_SP)(%a0), %sp /* load new stack pointer */ + + movem.l REG_OFFSET(REG_D2)(%a0), %d2-%d7 /* load $d2 through $d7 */ + movem.l REG_OFFSET(REG_A2)(%a0), %a2-%a6 /* load $a2 through $a6 */ + + clr.l %d0 /* clear $d0 */ + + move.l REG_OFFSET(REG_PC)(%a0), %a1 /* load jump target */ + + jmp (%a1) /* jump to *$a1 */ +END(libucontext_swapcontext) diff --git a/src/3rdparty/libucontext/arch/m68k/trampoline.c b/src/3rdparty/libucontext/arch/m68k/trampoline.c new file mode 100644 index 000000000..699a0505d --- /dev/null +++ b/src/3rdparty/libucontext/arch/m68k/trampoline.c @@ -0,0 +1,3 @@ +#include "defs.h" +#include +#include "common-trampoline.c" diff --git a/src/3rdparty/libucontext/arch/mips/defs.h b/src/3rdparty/libucontext/arch/mips/defs.h new file mode 100644 index 000000000..0d605dba1 --- /dev/null +++ b/src/3rdparty/libucontext/arch/mips/defs.h @@ -0,0 +1,94 @@ +#ifndef __ARCH_MIPS64_DEFS_H +#define __ARCH_MIPS64_DEFS_H + +#define REG_SZ (4) + +#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) + +/* $a0 is $4 */ +#define REG_A0 (4) + +/* stack pointer is actually $29 */ +#define REG_SP (29) + +/* frame pointer is actually $30 */ +#define REG_FP (30) + +/* $s0 ($16) is used as link register */ +#define REG_LNK (16) + +/* $t9 ($25) is used as entry */ +#define REG_ENTRY (25) + +/* offset to mc_gregs in ucontext_t */ +#define MCONTEXT_GREGS (40) + +/* offset to PC in ucontext_t */ +#define MCONTEXT_PC (32) + +/* offset to uc_link in ucontext_t */ +#define UCONTEXT_UC_LINK (4) + +/* offset to uc_stack.ss_sp in ucontext_t */ +#define UCONTEXT_STACK_PTR (8) + +/* offset to uc_stack.ss_size in ucontext_t */ +#define UCONTEXT_STACK_SIZE (12) + +/* setup frame, from MIPS N32/N64 calling convention manual */ +#define ALSZ 15 +#define ALMASK ~15 +#define FRAMESZ (((LOCALSZ * REG_SZ) + ALSZ) & ALMASK) // 16 +#define GPOFF (FRAMESZ - (LOCALSZ * REG_SZ)) // [16 - 16] + +#define SETUP_FRAME(__proc) \ + .frame $sp, FRAMESZ, $ra; \ + .mask 0x10000000, 0; \ + .fmask 0x00000000, 0; \ + .set noreorder; \ + .cpload $25; \ + .set reorder; + +#define PUSH_FRAME(__proc) \ + addiu $sp, -FRAMESZ; \ + .cprestore GPOFF; + +#define POP_FRAME(__proc) \ + addiu $sp, FRAMESZ + +#define ENT(__proc) .ent __proc, 0; + +#include + +#endif diff --git a/src/3rdparty/libucontext/arch/mips/getcontext.S b/src/3rdparty/libucontext/arch/mips/getcontext.S new file mode 100644 index 000000000..1655612be --- /dev/null +++ b/src/3rdparty/libucontext/arch/mips/getcontext.S @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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. + */ + +LOCALSZ = 1 + +#include "defs.h" + +ALIAS(getcontext, libucontext_getcontext) +ALIAS(__getcontext, libucontext_getcontext) + +FUNC(libucontext_getcontext) + /* copy $gp, $sp, $fp to temporary registers so we don't clobber them */ + move $a2, $gp + move $a3, $sp + move $a1, $fp + + PUSH_FRAME(libucontext_getcontext) + + /* set registers */ + sw $s0, REG_OFFSET(16)($a0) + sw $s1, REG_OFFSET(17)($a0) + sw $s2, REG_OFFSET(18)($a0) + sw $s3, REG_OFFSET(19)($a0) + sw $s4, REG_OFFSET(20)($a0) + sw $s5, REG_OFFSET(21)($a0) + sw $s6, REG_OFFSET(22)($a0) + sw $s7, REG_OFFSET(23)($a0) + + sw $a2, REG_OFFSET(28)($a0) + sw $a3, REG_OFFSET(29)($a0) + sw $a1, REG_OFFSET(30)($a0) + sw $ra, REG_OFFSET(31)($a0) + sw $ra, (MCONTEXT_PC)($a0) + + POP_FRAME(libucontext_getcontext) + + jr $ra +END(libucontext_getcontext) diff --git a/src/3rdparty/libucontext/arch/mips/include/libucontext/bits.h b/src/3rdparty/libucontext/arch/mips/include/libucontext/bits.h new file mode 100644 index 000000000..41a271a82 --- /dev/null +++ b/src/3rdparty/libucontext/arch/mips/include/libucontext/bits.h @@ -0,0 +1,27 @@ +#ifndef LIBUCONTEXT_BITS_H +#define LIBUCONTEXT_BITS_H + +typedef unsigned long long libucontext_greg_t, libucontext_gregset_t[32]; + +typedef struct { + unsigned regmask, status; + unsigned long long pc, gregs[32], fpregs[32]; + unsigned ownedfp, fpc_csr, fpc_eir, used_math, dsp; + unsigned long long mdhi, mdlo; + unsigned long hi1, lo1, hi2, lo2, hi3, lo3; +} libucontext_mcontext_t; + +typedef struct { + void *ss_sp; + size_t ss_size; + int ss_flags; +} libucontext_stack_t; + +typedef struct libucontext_ucontext { + unsigned long uc_flags; + struct libucontext_ucontext *uc_link; + libucontext_stack_t uc_stack; + libucontext_mcontext_t uc_mcontext; +} libucontext_ucontext_t; + +#endif diff --git a/src/3rdparty/libucontext/arch/mips/makecontext.S b/src/3rdparty/libucontext/arch/mips/makecontext.S new file mode 100644 index 000000000..bb841aed7 --- /dev/null +++ b/src/3rdparty/libucontext/arch/mips/makecontext.S @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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. + */ + +LOCALSZ = 2 + +#include "defs.h" + +A3_OFF = FRAMESZ + (3 * REG_SZ) + +/* + * Because we have to fiddle with $gp, we have to implement this in + * assembly rather than C. Annoying, that... + */ + +ALIAS(makecontext, libucontext_makecontext) +ALIAS(__makecontext, libucontext_makecontext) + +FUNC(libucontext_makecontext) + PUSH_FRAME(libucontext_makecontext) + + /* store $a3 through $a7 to the stack frame. */ + sw $a3, A3_OFF($sp) + + /* set $zero in the mcontext to 1. */ + li $v0, 1 + sw $v0, REG_OFFSET(0)($a0) + + /* ensure the stack is aligned on a quad-word boundary. */ + lw $t0, UCONTEXT_STACK_PTR($a0) + lw $t2, UCONTEXT_STACK_SIZE($a0) + addiu $t1, $sp, A3_OFF + addu $t0, $t2 + and $t0, ALMASK + blez $a2, no_more_arguments + + /* store register arguments. */ + addiu $t2, $a0, MCONTEXT_GREGS + (4 * REG_SZ) + move $t3, $zero + +store_register_arg: + addiu $t3, 1 + lw $v1, ($t1) + addiu $t1, REG_SZ + sw $v1, ($t2) + addiu $t2, REG_SZ + bgeu $t3, $a2, no_more_arguments + bltu $t3, 4, store_register_arg + + /* make room for stack arguments. */ + subu $t2, $a2, $t3 + sll $t2, 3 + subu $t0, $t2 + and $t0, ALMASK + + /* store stack arguments. */ + move $t2, $t0 + +store_stack_arg: + addiu $t3, 1 + lw $v1, ($t1) + addiu $t1, REG_SZ + sw $v1, ($t2) + addiu $t2, REG_SZ + bltu $t3, $a2, store_stack_arg + +no_more_arguments: + /* make room for $a0-$a3 storage */ + addiu $t0, -(4 * REG_SZ) + + /* trampoline setup. */ + la $t9, libucontext_trampoline + + /* copy link pointer as $s0... */ + lw $v1, UCONTEXT_UC_LINK($a0) + sw $v1, REG_OFFSET(16)($a0) + + /* set our $sp */ + sw $t0, REG_OFFSET(29)($a0) + + /* $gp is copied as $s1 */ + sw $gp, REG_OFFSET(17)($a0) + + /* set our $ra */ + sw $t9, REG_OFFSET(31)($a0) + + /* set our $pc */ + sw $a1, MCONTEXT_PC($a0) + + POP_FRAME(libucontext_makecontext) + + jr $ra +END(libucontext_makecontext) diff --git a/src/3rdparty/libucontext/arch/mips/setcontext.S b/src/3rdparty/libucontext/arch/mips/setcontext.S new file mode 100644 index 000000000..6017048f4 --- /dev/null +++ b/src/3rdparty/libucontext/arch/mips/setcontext.S @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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. + */ + +LOCALSZ = 1 + +#include "defs.h" + +ALIAS(setcontext, libucontext_setcontext) +ALIAS(__setcontext, libucontext_setcontext) + +FUNC(libucontext_setcontext) + PUSH_FRAME(libucontext_setcontext) + + /* move the context to $v0 */ + move $v0, $a0 + + /* load the registers */ + lw $a0, REG_OFFSET(4)($v0) + lw $a1, REG_OFFSET(5)($v0) + lw $a2, REG_OFFSET(6)($v0) + lw $a3, REG_OFFSET(7)($v0) + + lw $s0, REG_OFFSET(16)($v0) + lw $s1, REG_OFFSET(17)($v0) + lw $s2, REG_OFFSET(18)($v0) + lw $s3, REG_OFFSET(19)($v0) + lw $s4, REG_OFFSET(20)($v0) + lw $s5, REG_OFFSET(21)($v0) + lw $s6, REG_OFFSET(22)($v0) + lw $s7, REG_OFFSET(23)($v0) + + lw $gp, REG_OFFSET(28)($v0) + lw $sp, REG_OFFSET(29)($v0) + lw $fp, REG_OFFSET(30)($v0) + lw $ra, REG_OFFSET(31)($v0) + lw $t9, (MCONTEXT_PC)($v0) + + move $v0, $zero + jr $t9 + + POP_FRAME(libucontext_setcontext) +END(libucontext_setcontext) diff --git a/src/3rdparty/libucontext/arch/mips/startcontext.S b/src/3rdparty/libucontext/arch/mips/startcontext.S new file mode 100644 index 000000000..2ac79ec76 --- /dev/null +++ b/src/3rdparty/libucontext/arch/mips/startcontext.S @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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. + */ + +LOCALSZ = 1 + +#include "defs.h" + +.hidden libucontext_trampoline +FUNC(libucontext_trampoline) + move $gp, $s1 + + /* we receive our initial ucontext in $s0, so if $s0 is nil, bail */ + beqz $s0, no_linked_context + + /* call setcontext */ + move $a0, $s0 + la $t9, PROC_NAME(libucontext_setcontext) + + jr $t9 + +no_linked_context: + move $a0, $zero + la $t9, exit + jalr $t9 + nop +END(libucontext_trampoline) diff --git a/src/3rdparty/libucontext/arch/mips/swapcontext.S b/src/3rdparty/libucontext/arch/mips/swapcontext.S new file mode 100644 index 000000000..5e5647083 --- /dev/null +++ b/src/3rdparty/libucontext/arch/mips/swapcontext.S @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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. + */ + +LOCALSZ = 2 + +#include "defs.h" + +A1_OFFSET = FRAMESZ - (1 * REG_SZ) + +ALIAS(swapcontext, libucontext_swapcontext) +ALIAS(__swapcontext, libucontext_swapcontext) + +FUNC(libucontext_swapcontext) + /* copy $gp, $sp, $fp to temporary registers so we don't clobber them */ + move $a2, $gp + move $a3, $sp + + PUSH_FRAME(libucontext_swapcontext) + + /* set registers */ + sd $s0, REG_OFFSET(16)($a0) + sd $s1, REG_OFFSET(17)($a0) + sd $s2, REG_OFFSET(18)($a0) + sd $s3, REG_OFFSET(19)($a0) + sd $s4, REG_OFFSET(20)($a0) + sd $s5, REG_OFFSET(21)($a0) + sd $s6, REG_OFFSET(22)($a0) + sd $s7, REG_OFFSET(23)($a0) + + sd $a2, REG_OFFSET(28)($a0) + sd $a3, REG_OFFSET(29)($a0) + sd $fp, REG_OFFSET(30)($a0) + sd $ra, REG_OFFSET(31)($a0) + sd $ra, (MCONTEXT_PC)($a0) + + /* copy new context address in $a1 to stack */ + sd $a1, A1_OFFSET($sp) + + /* load new context address into $v0 */ + ld $v0, A1_OFFSET($sp) + + /* load the registers */ + ld $a0, REG_OFFSET(4)($v0) + ld $a1, REG_OFFSET(5)($v0) + ld $a2, REG_OFFSET(6)($v0) + ld $a3, REG_OFFSET(7)($v0) + + ld $s0, REG_OFFSET(16)($v0) + ld $s1, REG_OFFSET(17)($v0) + ld $s2, REG_OFFSET(18)($v0) + ld $s3, REG_OFFSET(19)($v0) + ld $s4, REG_OFFSET(20)($v0) + ld $s5, REG_OFFSET(21)($v0) + ld $s6, REG_OFFSET(22)($v0) + ld $s7, REG_OFFSET(23)($v0) + + ld $gp, REG_OFFSET(28)($v0) + ld $sp, REG_OFFSET(29)($v0) + ld $fp, REG_OFFSET(30)($v0) + ld $ra, REG_OFFSET(31)($v0) + ld $t9, (MCONTEXT_PC)($v0) + + move $v0, $zero + jr $t9 + +fail: + la $t9, exit + + POP_FRAME(libucontext_swapcontext) + + move $v0, $zero + jalr $t9 +END(libucontext_swapcontext) diff --git a/src/3rdparty/libucontext/arch/mips64/defs.h b/src/3rdparty/libucontext/arch/mips64/defs.h new file mode 100644 index 000000000..ade528842 --- /dev/null +++ b/src/3rdparty/libucontext/arch/mips64/defs.h @@ -0,0 +1,92 @@ +#ifndef __ARCH_MIPS64_DEFS_H +#define __ARCH_MIPS64_DEFS_H + +#define REG_SZ (8) + +#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) + +/* $a0 is $4 */ +#define REG_A0 (4) + +/* stack pointer is actually $29 */ +#define REG_SP (29) + +/* frame pointer is actually $30 */ +#define REG_FP (30) + +/* $s0 ($16) is used as link register */ +#define REG_LNK (16) + +/* $t9 ($25) is used as entry */ +#define REG_ENTRY (25) + +/* offset to mc_gregs in ucontext_t */ +#define MCONTEXT_GREGS (40) + +/* offset to PC in ucontext_t */ +#define MCONTEXT_PC (MCONTEXT_GREGS + 576) + +/* offset to uc_link in ucontext_t */ +#define UCONTEXT_UC_LINK (8) + +/* offset to uc_stack.ss_sp in ucontext_t */ +#define UCONTEXT_STACK_PTR (16) + +/* offset to uc_stack.ss_size in ucontext_t */ +#define UCONTEXT_STACK_SIZE (24) + +/* setup frame, from MIPS N32/N64 calling convention manual */ +#define ALSZ 15 +#define ALMASK ~15 +#define FRAMESZ (((LOCALSZ * REG_SZ) + ALSZ) & ALMASK) // 16 +#define GPOFF (FRAMESZ - (LOCALSZ * REG_SZ)) // [16 - 16] + +#define SETUP_FRAME(__proc) \ + .frame $sp, FRAMESZ, $ra; \ + .mask 0x10000000, 0; \ + .fmask 0x00000000, 0; + +#define PUSH_FRAME(__proc) \ + daddiu $sp, -FRAMESZ; \ + .cpsetup $25, GPOFF, __proc; + +#define POP_FRAME(__proc) \ + .cpreturn; \ + daddiu $sp, FRAMESZ + +#define ENT(__proc) .ent __proc, 0; + +#include + +#endif diff --git a/src/3rdparty/libucontext/arch/mips64/getcontext.S b/src/3rdparty/libucontext/arch/mips64/getcontext.S new file mode 100644 index 000000000..9912573cc --- /dev/null +++ b/src/3rdparty/libucontext/arch/mips64/getcontext.S @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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. + */ + +LOCALSZ = 1 + +#include "defs.h" + +ALIAS(getcontext, libucontext_getcontext) +ALIAS(__getcontext, libucontext_getcontext) + +FUNC(libucontext_getcontext) + /* copy $gp, $sp, $fp to temporary registers so we don't clobber them */ + move $a2, $gp + move $a3, $sp + move $a4, $fp + + PUSH_FRAME(libucontext_getcontext) + + /* set registers */ + sd $s0, REG_OFFSET(16)($a0) + sd $s1, REG_OFFSET(17)($a0) + sd $s2, REG_OFFSET(18)($a0) + sd $s3, REG_OFFSET(19)($a0) + sd $s4, REG_OFFSET(20)($a0) + sd $s5, REG_OFFSET(21)($a0) + sd $s6, REG_OFFSET(22)($a0) + sd $s7, REG_OFFSET(23)($a0) + + sd $a2, REG_OFFSET(28)($a0) + sd $a3, REG_OFFSET(29)($a0) + sd $a4, REG_OFFSET(30)($a0) + sd $ra, REG_OFFSET(31)($a0) + sd $ra, (MCONTEXT_PC)($a0) + + POP_FRAME(libucontext_getcontext) + + jr $ra +END(libucontext_getcontext) diff --git a/src/3rdparty/libucontext/arch/mips64/include/libucontext/bits.h b/src/3rdparty/libucontext/arch/mips64/include/libucontext/bits.h new file mode 100644 index 000000000..538dcd580 --- /dev/null +++ b/src/3rdparty/libucontext/arch/mips64/include/libucontext/bits.h @@ -0,0 +1,47 @@ +#ifndef LIBUCONTEXT_BITS_H +#define LIBUCONTEXT_BITS_H + +typedef unsigned long long libucontext_greg_t, libucontext_gregset_t[32]; + +typedef struct { + union { + double fp_dregs[32]; + struct { + float _fp_fregs; + unsigned _fp_pad; + } fp_fregs[32]; + } fp_r; +} libucontext_fpregset_t; + +typedef struct { + libucontext_gregset_t gregs; + libucontext_fpregset_t fpregs; + libucontext_greg_t mdhi; + libucontext_greg_t hi1; + libucontext_greg_t hi2; + libucontext_greg_t hi3; + libucontext_greg_t mdlo; + libucontext_greg_t lo1; + libucontext_greg_t lo2; + libucontext_greg_t lo3; + libucontext_greg_t pc; + unsigned int fpc_csr; + unsigned int used_math; + unsigned int dsp; + unsigned int reserved; +} libucontext_mcontext_t; + +typedef struct { + void *ss_sp; + size_t ss_size; + int ss_flags; +} libucontext_stack_t; + +typedef struct libucontext_ucontext { + unsigned long uc_flags; + struct libucontext_ucontext *uc_link; + libucontext_stack_t uc_stack; + libucontext_mcontext_t uc_mcontext; +} libucontext_ucontext_t; + +#endif diff --git a/src/3rdparty/libucontext/arch/mips64/makecontext.S b/src/3rdparty/libucontext/arch/mips64/makecontext.S new file mode 100644 index 000000000..98b4b514b --- /dev/null +++ b/src/3rdparty/libucontext/arch/mips64/makecontext.S @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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. + */ + +/* $gp + 5 args */ +LOCALSZ = 6 + +#include "defs.h" + +A3_OFF = FRAMESZ - (5 * REG_SZ) +A4_OFF = FRAMESZ - (4 * REG_SZ) +A5_OFF = FRAMESZ - (3 * REG_SZ) +A6_OFF = FRAMESZ - (2 * REG_SZ) +A7_OFF = FRAMESZ - (1 * REG_SZ) + +/* + * Because we have to fiddle with $gp, we have to implement this in + * assembly rather than C. Annoying, that... + */ + +ALIAS(makecontext, libucontext_makecontext) +ALIAS(__makecontext, libucontext_makecontext) + +FUNC(libucontext_makecontext) + PUSH_FRAME(libucontext_makecontext) + + /* store $a3 through $a7 to the stack frame. */ + sd $a3, A3_OFF($sp) + sd $a4, A4_OFF($sp) + sd $a5, A5_OFF($sp) + sd $a6, A6_OFF($sp) + sd $a7, A7_OFF($sp) + + /* set $zero in the mcontext to 1. */ + li $v0, 1 + sd $v0, REG_OFFSET(0)($a0) + + /* ensure the stack is aligned on a quad-word boundary. */ + ld $t0, UCONTEXT_STACK_PTR($a0) + ld $t2, UCONTEXT_STACK_SIZE($a0) + daddiu $t1, $sp, A3_OFF + daddu $t0, $t2 + and $t0, ALMASK + blez $a2, no_more_arguments + + /* store register arguments. */ + daddiu $t2, $a0, MCONTEXT_GREGS + (4 * REG_SZ) + move $t3, $zero + +store_register_arg: + daddiu $t3, 1 + ld $v1, ($t1) + daddiu $t1, REG_SZ + sd $v1, ($t2) + daddiu $t2, REG_SZ + bgeu $t3, $a2, no_more_arguments + bltu $t3, 8, store_register_arg + + /* make room for stack arguments. */ + dsubu $t2, $a2, $t3 + dsll $t2, 3 + dsubu $t0, $t2 + and $t0, ALMASK + + /* store stack arguments. */ + move $t2, $t0 + +store_stack_arg: + daddiu $t3, 1 + ld $v1, ($t1) + daddiu $t1, REG_SZ + sd $v1, ($t2) + daddiu $t2, REG_SZ + bltu $t3, $a2, store_stack_arg + +no_more_arguments: + /* trampoline setup. */ + dla $t9, libucontext_trampoline + + /* copy link pointer as $s0... */ + ld $v1, UCONTEXT_UC_LINK($a0) + sd $v1, REG_OFFSET(16)($a0) + + /* set our $sp */ + sd $t0, REG_OFFSET(29)($a0) + + /* $gp is copied as $s1 */ + sd $gp, REG_OFFSET(17)($a0) + + /* set our $ra */ + sd $t9, REG_OFFSET(31)($a0) + + /* set our $pc */ + sd $a1, MCONTEXT_PC($a0) + + POP_FRAME(libucontext_makecontext) + + jr $ra +END(libucontext_makecontext) diff --git a/src/3rdparty/libucontext/arch/mips64/setcontext.S b/src/3rdparty/libucontext/arch/mips64/setcontext.S new file mode 100644 index 000000000..17b9969fc --- /dev/null +++ b/src/3rdparty/libucontext/arch/mips64/setcontext.S @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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. + */ + +LOCALSZ = 1 + +#include "defs.h" + +ALIAS(setcontext, libucontext_setcontext) +ALIAS(__setcontext, libucontext_setcontext) + +FUNC(libucontext_setcontext) + PUSH_FRAME(libucontext_setcontext) + + /* move the context to $v0 */ + move $v0, $a0 + + /* load the registers */ + ld $a0, REG_OFFSET(4)($v0) + ld $a1, REG_OFFSET(5)($v0) + ld $a2, REG_OFFSET(6)($v0) + ld $a3, REG_OFFSET(7)($v0) + ld $a4, REG_OFFSET(8)($v0) + ld $a5, REG_OFFSET(9)($v0) + ld $a6, REG_OFFSET(10)($v0) + ld $a7, REG_OFFSET(11)($v0) + + ld $s0, REG_OFFSET(16)($v0) + ld $s1, REG_OFFSET(17)($v0) + ld $s2, REG_OFFSET(18)($v0) + ld $s3, REG_OFFSET(19)($v0) + ld $s4, REG_OFFSET(20)($v0) + ld $s5, REG_OFFSET(21)($v0) + ld $s6, REG_OFFSET(22)($v0) + ld $s7, REG_OFFSET(23)($v0) + + ld $gp, REG_OFFSET(28)($v0) + ld $sp, REG_OFFSET(29)($v0) + ld $fp, REG_OFFSET(30)($v0) + ld $ra, REG_OFFSET(31)($v0) + ld $t9, (MCONTEXT_PC)($v0) + + move $v0, $zero + jr $t9 + + POP_FRAME(libucontext_setcontext) +END(libucontext_setcontext) diff --git a/src/3rdparty/libucontext/arch/mips64/startcontext.S b/src/3rdparty/libucontext/arch/mips64/startcontext.S new file mode 100644 index 000000000..a96027957 --- /dev/null +++ b/src/3rdparty/libucontext/arch/mips64/startcontext.S @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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. + */ + +LOCALSZ = 1 + +#include "defs.h" + +.hidden libucontext_trampoline +FUNC(libucontext_trampoline) + move $gp, $s1 + + /* we receive our initial ucontext in $s0, so if $s0 is nil, bail */ + beqz $s0, no_linked_context + + /* call setcontext */ + move $a0, $s0 + dla $t9, PROC_NAME(libucontext_setcontext) + + jr $t9 + +no_linked_context: + move $a0, $zero + dla $t9, exit + jalr $t9 + nop +END(libucontext_trampoline) diff --git a/src/3rdparty/libucontext/arch/mips64/swapcontext.S b/src/3rdparty/libucontext/arch/mips64/swapcontext.S new file mode 100644 index 000000000..22846611f --- /dev/null +++ b/src/3rdparty/libucontext/arch/mips64/swapcontext.S @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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. + */ + +LOCALSZ = 2 + +#include "defs.h" + +A1_OFFSET = FRAMESZ - (1 * REG_SZ) + +ALIAS(swapcontext, libucontext_swapcontext) +ALIAS(__swapcontext, libucontext_swapcontext) + +FUNC(libucontext_swapcontext) + /* copy $gp, $sp, $fp to temporary registers so we don't clobber them */ + move $a2, $gp + move $a3, $sp + move $a4, $fp + + PUSH_FRAME(libucontext_swapcontext) + + /* set registers */ + sd $s0, REG_OFFSET(16)($a0) + sd $s1, REG_OFFSET(17)($a0) + sd $s2, REG_OFFSET(18)($a0) + sd $s3, REG_OFFSET(19)($a0) + sd $s4, REG_OFFSET(20)($a0) + sd $s5, REG_OFFSET(21)($a0) + sd $s6, REG_OFFSET(22)($a0) + sd $s7, REG_OFFSET(23)($a0) + + sd $a2, REG_OFFSET(28)($a0) + sd $a3, REG_OFFSET(29)($a0) + sd $a4, REG_OFFSET(30)($a0) + sd $ra, REG_OFFSET(31)($a0) + sd $ra, (MCONTEXT_PC)($a0) + + /* copy new context address in $a1 to stack */ + sd $a1, A1_OFFSET($sp) + + /* load new context address into $v0 */ + ld $v0, A1_OFFSET($sp) + + /* load the registers */ + ld $a0, REG_OFFSET(4)($v0) + ld $a1, REG_OFFSET(5)($v0) + ld $a2, REG_OFFSET(6)($v0) + ld $a3, REG_OFFSET(7)($v0) + ld $a4, REG_OFFSET(8)($v0) + ld $a5, REG_OFFSET(9)($v0) + ld $a6, REG_OFFSET(10)($v0) + ld $a7, REG_OFFSET(11)($v0) + + ld $s0, REG_OFFSET(16)($v0) + ld $s1, REG_OFFSET(17)($v0) + ld $s2, REG_OFFSET(18)($v0) + ld $s3, REG_OFFSET(19)($v0) + ld $s4, REG_OFFSET(20)($v0) + ld $s5, REG_OFFSET(21)($v0) + ld $s6, REG_OFFSET(22)($v0) + ld $s7, REG_OFFSET(23)($v0) + + ld $gp, REG_OFFSET(28)($v0) + ld $sp, REG_OFFSET(29)($v0) + ld $fp, REG_OFFSET(30)($v0) + ld $ra, REG_OFFSET(31)($v0) + ld $t9, (MCONTEXT_PC)($v0) + + move $v0, $zero + jr $t9 + +fail: + dla $t9, exit + + POP_FRAME(libucontext_swapcontext) + + move $v0, $zero + jalr $t9 +END(libucontext_swapcontext) diff --git a/src/3rdparty/libucontext/arch/or1k/defs.h b/src/3rdparty/libucontext/arch/or1k/defs.h new file mode 100644 index 000000000..fe2b31f91 --- /dev/null +++ b/src/3rdparty/libucontext/arch/or1k/defs.h @@ -0,0 +1,22 @@ +#ifndef __ARCH_OR1K_DEFS_H +#define __ARCH_OR1K_DEFS_H + +#define REG_SZ (4) +#define MCONTEXT_GREGS (20) + +#define REG_SP (1) +#define REG_FP (2) +#define REG_RA (9) +#define REG_SA (11) +#define REG_LR (14) +#define REG_PC (33) +#define REG_SR (34) + +#define PC_OFFSET REG_OFFSET(REG_PC) + +#define FETCH_LINKPTR(dest) \ + asm("l.ori %0, r14, 0" :: "r" ((dest))) + +#include "common-defs.h" + +#endif diff --git a/src/3rdparty/libucontext/arch/or1k/getcontext.S b/src/3rdparty/libucontext/arch/or1k/getcontext.S new file mode 100644 index 000000000..0d7e55c7a --- /dev/null +++ b/src/3rdparty/libucontext/arch/or1k/getcontext.S @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022 Ariadne Conill + * + * 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" + +ALIAS(getcontext, libucontext_getcontext) +ALIAS(__getcontext, libucontext_getcontext) + +FUNC(libucontext_getcontext) + l.sw REG_OFFSET(1)(r3), r1 /* store r1 and r2 */ + l.sw REG_OFFSET(2)(r3), r2 + + l.sw REG_OFFSET(9)(r3), r9 /* store r9 to both r9 and r11 in the context */ + l.sw REG_OFFSET(11)(r3), r9 + + l.sw REG_OFFSET(10)(r3), r10 /* store r10 for TLS */ + + l.sw REG_OFFSET(14)(r3), r14 /* store r14 through r30 even */ + l.sw REG_OFFSET(16)(r3), r16 + l.sw REG_OFFSET(18)(r3), r18 + l.sw REG_OFFSET(20)(r3), r20 + l.sw REG_OFFSET(22)(r3), r22 + l.sw REG_OFFSET(24)(r3), r24 + l.sw REG_OFFSET(26)(r3), r26 + l.sw REG_OFFSET(28)(r3), r28 + l.sw REG_OFFSET(30)(r3), r30 + + l.jr r9 + l.ori r11, r0, 0 +END(libucontext_getcontext) diff --git a/src/3rdparty/libucontext/arch/or1k/include/libucontext/bits.h b/src/3rdparty/libucontext/arch/or1k/include/libucontext/bits.h new file mode 100644 index 000000000..650351ec3 --- /dev/null +++ b/src/3rdparty/libucontext/arch/or1k/include/libucontext/bits.h @@ -0,0 +1,28 @@ +#ifndef LIBUCONTEXT_BITS_H +#define LIBUCONTEXT_BITS_H + +typedef struct sigaltstack { + void *ss_sp; + int ss_flags; + size_t ss_size; +} libucontext_stack_t; + +typedef int libucontext_greg_t, libucontext_gregset_t[32]; + +typedef struct { + struct { + libucontext_gregset_t gpr; + libucontext_greg_t pc; + libucontext_greg_t sr; + } regs; + unsigned long oldmask; +} libucontext_mcontext_t; + +typedef struct libucontext_ucontext { + unsigned long uc_flags; + struct libucontext_ucontext *uc_link; + libucontext_stack_t uc_stack; + libucontext_mcontext_t uc_mcontext; +} libucontext_ucontext_t; + +#endif diff --git a/src/3rdparty/libucontext/arch/or1k/makecontext.c b/src/3rdparty/libucontext/arch/or1k/makecontext.c new file mode 100644 index 000000000..863ba777c --- /dev/null +++ b/src/3rdparty/libucontext/arch/or1k/makecontext.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2022 Ariadne Conill + * + * 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 +#include +#include +#include +#include +#include "defs.h" +#include + + +extern void libucontext_trampoline(void); + + +void +libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(void), int argc, ...) +{ + libucontext_greg_t *sp; + va_list va; + int i; + + /* set up and align the stack. */ + sp = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); + sp -= argc < 6 ? 0 : (argc - 6); + sp = (libucontext_greg_t *) (((uintptr_t) sp & ~0x3)); + + /* set up the ucontext structure */ + ucp->uc_mcontext.regs.gpr[REG_SP] = (libucontext_greg_t) sp; + ucp->uc_mcontext.regs.gpr[REG_RA] = (libucontext_greg_t) &libucontext_trampoline; + ucp->uc_mcontext.regs.gpr[REG_FP] = 0; + ucp->uc_mcontext.regs.gpr[REG_SA] = (libucontext_greg_t) func; + ucp->uc_mcontext.regs.gpr[REG_LR] = (libucontext_greg_t) ucp->uc_link; + + va_start(va, argc); + + /* args less than argv[6] have dedicated registers, else they overflow onto stack */ + for (i = 0; i < argc; i++) + { + if (i < 6) + ucp->uc_mcontext.regs.gpr[i + 3] = va_arg (va, libucontext_greg_t); + else + sp[i - 6] = va_arg (va, libucontext_greg_t); + } + + va_end(va); +} + +#ifdef EXPORT_UNPREFIXED +extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +#endif diff --git a/src/3rdparty/libucontext/arch/or1k/setcontext.S b/src/3rdparty/libucontext/arch/or1k/setcontext.S new file mode 100644 index 000000000..d25c8009e --- /dev/null +++ b/src/3rdparty/libucontext/arch/or1k/setcontext.S @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022 Ariadne Conill + * + * 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" + +ALIAS(setcontext, libucontext_setcontext) +ALIAS(__setcontext, libucontext_setcontext) + +FUNC(libucontext_setcontext) + l.ori r30, r3, 0 /* avoid clobbering r3 by copying to r30 */ + + l.lwz r3, REG_OFFSET(3)(r30) /* restore r3-r8 (argument registers) */ + l.lwz r4, REG_OFFSET(4)(r30) + l.lwz r5, REG_OFFSET(5)(r30) + l.lwz r6, REG_OFFSET(6)(r30) + l.lwz r7, REG_OFFSET(7)(r30) + l.lwz r8, REG_OFFSET(8)(r30) + + l.lwz r1, REG_OFFSET(1)(r30) /* restore stack/frame pointers */ + l.lwz r2, REG_OFFSET(2)(r30) + + l.lwz r9, REG_OFFSET(9)(r30) /* restore link register and starting address register */ + l.lwz r11, REG_OFFSET(11)(r30) + + l.lwz r10, REG_OFFSET(10)(r30) /* restore TLS register */ + + l.lwz r14, REG_OFFSET(14)(r30) /* restore r14-r30, even only */ + l.lwz r16, REG_OFFSET(16)(r30) + l.lwz r18, REG_OFFSET(18)(r30) + l.lwz r20, REG_OFFSET(20)(r30) + l.lwz r22, REG_OFFSET(22)(r30) + l.lwz r24, REG_OFFSET(24)(r30) + l.lwz r26, REG_OFFSET(26)(r30) + l.lwz r28, REG_OFFSET(28)(r30) + l.lwz r30, REG_OFFSET(30)(r30) + + l.jr r11 /* jump to new starting address */ + l.ori r11, r0, 0 +END(libucontext_setcontext) diff --git a/src/3rdparty/libucontext/arch/or1k/swapcontext.S b/src/3rdparty/libucontext/arch/or1k/swapcontext.S new file mode 100644 index 000000000..07198e524 --- /dev/null +++ b/src/3rdparty/libucontext/arch/or1k/swapcontext.S @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022 Ariadne Conill + * + * 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" + +ALIAS(swapcontext, libucontext_swapcontext) +ALIAS(__swapcontext, libucontext_swapcontext) + +FUNC(libucontext_swapcontext) + /* copy context into r3 like getcontext */ + l.sw REG_OFFSET(1)(r3), r1 /* store r1 and r2 */ + l.sw REG_OFFSET(2)(r3), r2 + + l.sw REG_OFFSET(9)(r3), r9 /* store r9 to both r9 and r11 in the context */ + l.sw REG_OFFSET(11)(r3), r9 + + l.sw REG_OFFSET(10)(r3), r10 /* store r10 for TLS */ + + l.sw REG_OFFSET(14)(r3), r14 /* store r14 through r30 even */ + l.sw REG_OFFSET(16)(r3), r16 + l.sw REG_OFFSET(18)(r3), r18 + l.sw REG_OFFSET(20)(r3), r20 + l.sw REG_OFFSET(22)(r3), r22 + l.sw REG_OFFSET(24)(r3), r24 + l.sw REG_OFFSET(26)(r3), r26 + l.sw REG_OFFSET(28)(r3), r28 + l.sw REG_OFFSET(30)(r3), r30 + + /* set the new context from r4 */ + l.ori r30, r4, 0 /* copy r4 to r30 to avoid clobbering */ + + l.lwz r3, REG_OFFSET(3)(r30) /* restore r3-r8 (argument registers) */ + l.lwz r4, REG_OFFSET(4)(r30) + l.lwz r5, REG_OFFSET(5)(r30) + l.lwz r6, REG_OFFSET(6)(r30) + l.lwz r7, REG_OFFSET(7)(r30) + l.lwz r8, REG_OFFSET(8)(r30) + + l.lwz r1, REG_OFFSET(1)(r30) /* restore stack/frame pointers */ + l.lwz r2, REG_OFFSET(2)(r30) + + l.lwz r9, REG_OFFSET(9)(r30) /* restore link register and starting address register */ + l.lwz r11, REG_OFFSET(11)(r30) + + l.lwz r10, REG_OFFSET(10)(r30) /* restore TLS register */ + + l.lwz r14, REG_OFFSET(14)(r30) /* restore r14-r30, even only */ + l.lwz r16, REG_OFFSET(16)(r30) + l.lwz r18, REG_OFFSET(18)(r30) + l.lwz r20, REG_OFFSET(20)(r30) + l.lwz r22, REG_OFFSET(22)(r30) + l.lwz r24, REG_OFFSET(24)(r30) + l.lwz r26, REG_OFFSET(26)(r30) + l.lwz r28, REG_OFFSET(28)(r30) + l.lwz r30, REG_OFFSET(30)(r30) + + l.jr r11 /* jump to new starting address */ + l.ori r11, r0, 0 +END(libucontext_swapcontext) diff --git a/src/3rdparty/libucontext/arch/or1k/trampoline.c b/src/3rdparty/libucontext/arch/or1k/trampoline.c new file mode 100644 index 000000000..699a0505d --- /dev/null +++ b/src/3rdparty/libucontext/arch/or1k/trampoline.c @@ -0,0 +1,3 @@ +#include "defs.h" +#include +#include "common-trampoline.c" diff --git a/src/3rdparty/libucontext/arch/ppc/defs.h b/src/3rdparty/libucontext/arch/ppc/defs.h new file mode 100644 index 000000000..531e55120 --- /dev/null +++ b/src/3rdparty/libucontext/arch/ppc/defs.h @@ -0,0 +1,64 @@ +#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 + +#include "common-defs.h" + +#endif diff --git a/src/3rdparty/libucontext/arch/ppc/getcontext.S b/src/3rdparty/libucontext/arch/ppc/getcontext.S new file mode 100644 index 000000000..4920fd3c9 --- /dev/null +++ b/src/3rdparty/libucontext/arch/ppc/getcontext.S @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019 Bobby Bingham + * + * 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 "common-defs.h" + +ALIAS(getcontext, libucontext_getcontext) +ALIAS(__getcontext, libucontext_getcontext) + +.hidden __libucontext_swapcontext +FUNC(libucontext_getcontext) + li 4, 0 + b __libucontext_swapcontext@local +END(libucontext_getcontext) diff --git a/src/3rdparty/libucontext/arch/ppc/makecontext.c b/src/3rdparty/libucontext/arch/ppc/makecontext.c new file mode 100644 index 000000000..1b820384b --- /dev/null +++ b/src/3rdparty/libucontext/arch/ppc/makecontext.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018 Ariadne Conill + * Copyright (c) 2019 Bobby Bingham + * + * 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 +#include + + +#include "defs.h" +#include + + +extern void libucontext_trampoline(void); + + +void +libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(), int argc, ...) +{ + libucontext_greg_t *sp; + va_list va; + int i; + unsigned int stack_args; + + stack_args = argc > 8 ? argc - 8 : 0; + + sp = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); + sp -= stack_args + 2; + sp = (libucontext_greg_t *) ((uintptr_t) sp & -16L); + + ucp->uc_mcontext.gregs[REG_NIP] = (uintptr_t) func; + ucp->uc_mcontext.gregs[REG_LNK] = (uintptr_t) &libucontext_trampoline; + ucp->uc_mcontext.gregs[REG_R31] = (uintptr_t) ucp->uc_link; + ucp->uc_mcontext.gregs[REG_SP] = (uintptr_t) sp; + + sp[0] = 0; + + va_start(va, argc); + + for (i = 0; i < argc; i++) { + if (i < 8) + ucp->uc_mcontext.gregs[i + 3] = va_arg (va, libucontext_greg_t); + else + sp[i-8 + 2] = va_arg (va, libucontext_greg_t); + } + + va_end(va); +} + +#ifdef EXPORT_UNPREFIXED +extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +#endif diff --git a/src/3rdparty/libucontext/arch/ppc/retfromsyscall.c b/src/3rdparty/libucontext/arch/ppc/retfromsyscall.c new file mode 100644 index 000000000..150c13dcd --- /dev/null +++ b/src/3rdparty/libucontext/arch/ppc/retfromsyscall.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 Ariadne Conill + * Copyright (c) 2019 Bobby Bingham + * + * 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 + +__attribute__ ((visibility ("hidden"))) +int __retfromsyscall(long retval) +{ + if (retval < 0) { + errno = -retval; + return -1; + } + return 0; +} + diff --git a/src/3rdparty/libucontext/arch/ppc/setcontext.S b/src/3rdparty/libucontext/arch/ppc/setcontext.S new file mode 100644 index 000000000..d634e66f2 --- /dev/null +++ b/src/3rdparty/libucontext/arch/ppc/setcontext.S @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019 Bobby Bingham + * + * 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 "common-defs.h" + +ALIAS(setcontext, libucontext_setcontext) +ALIAS(__setcontext, libucontext_setcontext) + +.hidden __libucontext_swapcontext +FUNC(libucontext_setcontext) + mr 4, 3 + li 3, 0 + b __libucontext_swapcontext@local +END(libucontext_setcontext) diff --git a/src/3rdparty/libucontext/arch/ppc/startcontext.S b/src/3rdparty/libucontext/arch/ppc/startcontext.S new file mode 100644 index 000000000..783380871 --- /dev/null +++ b/src/3rdparty/libucontext/arch/ppc/startcontext.S @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Ariadne Conill + * + * 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 "common-defs.h" + +.hidden libucontext_trampoline +FUNC(libucontext_trampoline) + /* get the proper context into position and test for NULL */ + mr. 3,31 + + /* if we have no linked context, lets get out of here */ + beq no_linked_context + + /* jump to setcontext */ + bl libucontext_setcontext@local + +no_linked_context: + b exit@GOT +END(libucontext_trampoline) diff --git a/src/3rdparty/libucontext/arch/ppc/swapcontext.S b/src/3rdparty/libucontext/arch/ppc/swapcontext.S new file mode 100644 index 000000000..3d1efe016 --- /dev/null +++ b/src/3rdparty/libucontext/arch/ppc/swapcontext.S @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019 Bobby Bingham + * + * 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 "common-defs.h" + +ALIAS(swapcontext, __libucontext_swapcontext) +ALIAS(__swapcontext, __libucontext_swapcontext) + +/* make sure this is visible regardless of EXPORT_UNPREFIXED */ +.weak libucontext_swapcontext +libucontext_swapcontext = __libucontext_swapcontext + +FUNC(__libucontext_swapcontext) + li 0, 249 # SYS_swapcontext + li 5, 1184 # sizeof(ucontext_t) + sc + +.hidden __retfromsyscall + b __retfromsyscall@local +END(__libucontext_swapcontext) diff --git a/src/3rdparty/libucontext/arch/ppc64/defs.h b/src/3rdparty/libucontext/arch/ppc64/defs.h new file mode 100644 index 000000000..936591110 --- /dev/null +++ b/src/3rdparty/libucontext/arch/ppc64/defs.h @@ -0,0 +1,67 @@ +#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 + +/* entry register is actually %r12 */ +#define REG_ENTRY REG_R12 + +/* lnk register is actually %r36 */ +#define REG_LNK REG_R36 + +#include "common-defs.h" + +#endif diff --git a/src/3rdparty/libucontext/arch/ppc64/getcontext.S b/src/3rdparty/libucontext/arch/ppc64/getcontext.S new file mode 100644 index 000000000..1a67424e7 --- /dev/null +++ b/src/3rdparty/libucontext/arch/ppc64/getcontext.S @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019 Bobby Bingham + * + * 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 "common-defs.h" + +ALIAS(getcontext, libucontext_getcontext) +ALIAS(__getcontext, libucontext_getcontext) + +.hidden __libucontext_swapcontext +FUNC(libucontext_getcontext) + addis 2, 12, .TOC.-libucontext_getcontext@ha + addi 2, 12, .TOC.-libucontext_getcontext@l + + .localentry libucontext_getcontext,.-libucontext_getcontext + + li 4, 0 + b __libucontext_swapcontext +END(libucontext_getcontext) diff --git a/src/3rdparty/libucontext/arch/ppc64/makecontext.c b/src/3rdparty/libucontext/arch/ppc64/makecontext.c new file mode 100644 index 000000000..15ddbf9f8 --- /dev/null +++ b/src/3rdparty/libucontext/arch/ppc64/makecontext.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018 Ariadne Conill + * Copyright (c) 2019 Bobby Bingham + * + * 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 +#include + + +#include "defs.h" +#include + + +extern void libucontext_trampoline(void); + + +void +libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(), int argc, ...) +{ + libucontext_greg_t *sp; + va_list va; + int i; + unsigned int stack_args; + + stack_args = argc > 8 ? argc : 0; + + sp = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); + sp -= stack_args + 4; + sp = (libucontext_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) &libucontext_trampoline; + ucp->uc_mcontext.gp_regs[REG_SP] = (uintptr_t) sp; + ucp->uc_mcontext.gp_regs[REG_ENTRY] = (uintptr_t) func; + ucp->uc_mcontext.gp_regs[REG_R31] = (uintptr_t) ucp->uc_link; + + sp[0] = 0; + + va_start(va, argc); + + for (i = 0; i < argc; i++) { + if (i < 8) + ucp->uc_mcontext.gp_regs[i + 3] = va_arg (va, libucontext_greg_t); + else + sp[i + 4] = va_arg (va, libucontext_greg_t); + } + + va_end(va); +} + +#ifdef EXPORT_UNPREFIXED +extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +#endif diff --git a/src/3rdparty/libucontext/arch/ppc64/retfromsyscall.c b/src/3rdparty/libucontext/arch/ppc64/retfromsyscall.c new file mode 100644 index 000000000..150c13dcd --- /dev/null +++ b/src/3rdparty/libucontext/arch/ppc64/retfromsyscall.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 Ariadne Conill + * Copyright (c) 2019 Bobby Bingham + * + * 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 + +__attribute__ ((visibility ("hidden"))) +int __retfromsyscall(long retval) +{ + if (retval < 0) { + errno = -retval; + return -1; + } + return 0; +} + diff --git a/src/3rdparty/libucontext/arch/ppc64/setcontext.S b/src/3rdparty/libucontext/arch/ppc64/setcontext.S new file mode 100644 index 000000000..0cd918673 --- /dev/null +++ b/src/3rdparty/libucontext/arch/ppc64/setcontext.S @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019 Bobby Bingham + * + * 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 "common-defs.h" + +ALIAS(setcontext, libucontext_setcontext) +ALIAS(__setcontext, libucontext_setcontext) + +.hidden __libucontext_swapcontext +FUNC(libucontext_setcontext) + addis 2, 12, .TOC.-libucontext_setcontext@ha + addi 2, 12, .TOC.-libucontext_setcontext@l + + .localentry libucontext_setcontext,.-libucontext_setcontext + + mr 4, 3 + li 3, 0 + b __libucontext_swapcontext +END(libucontext_setcontext) diff --git a/src/3rdparty/libucontext/arch/ppc64/startcontext.S b/src/3rdparty/libucontext/arch/ppc64/startcontext.S new file mode 100644 index 000000000..367f99d2f --- /dev/null +++ b/src/3rdparty/libucontext/arch/ppc64/startcontext.S @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 Ariadne Conill + * + * 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 "common-defs.h" + +.hidden libucontext_trampoline +FUNC(libucontext_trampoline) + cmpdi 31,0 /* test if ucontext link pointer is null */ + beq no_linked_context /* if it is, exit */ + + /* now, call SYS_swapcontext */ + mr 4,31 /* ucp is in r31 */ + li 3,0 /* don't care about restoring, set oucp to NULL */ + li 5,1696 /* sizeof(ucontext_t) */ + li 0,249 /* SYS_swapcontext */ + sc + + /* we should not wind back up here, if we do, exit with -1 */ + li 3,-1 + +no_linked_context: + b exit@GOT + nop +END(libucontext_trampoline) diff --git a/src/3rdparty/libucontext/arch/ppc64/swapcontext.S b/src/3rdparty/libucontext/arch/ppc64/swapcontext.S new file mode 100644 index 000000000..facd491d1 --- /dev/null +++ b/src/3rdparty/libucontext/arch/ppc64/swapcontext.S @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019 Bobby Bingham + * + * 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 "common-defs.h" + +ALIAS(swapcontext, __libucontext_swapcontext) +ALIAS(__swapcontext, __libucontext_swapcontext) + +/* make sure this is visible regardless of EXPORT_UNPREFIXED */ +.weak libucontext_swapcontext +libucontext_swapcontext = __libucontext_swapcontext + +FUNC(__libucontext_swapcontext) + addis 2, 12, .TOC.-__libucontext_swapcontext@ha + addi 2, 12, .TOC.-__libucontext_swapcontext@l + + .localentry __libucontext_swapcontext,.-__libucontext_swapcontext + + li 0, 249 # SYS_swapcontext + li 5, 1696 # sizeof(ucontext_t) + sc + +.hidden __retfromsyscall + b __retfromsyscall +END(__libucontext_swapcontext) diff --git a/src/3rdparty/libucontext/arch/riscv32/defs.h b/src/3rdparty/libucontext/arch/riscv32/defs.h new file mode 100644 index 000000000..3f737116b --- /dev/null +++ b/src/3rdparty/libucontext/arch/riscv32/defs.h @@ -0,0 +1,55 @@ +#ifndef __ARCH_RISCV64_DEFS_H +#define __ARCH_RISCV64_DEFS_H + +#define REG_SZ (4) +#define MCONTEXT_GREGS (160) + +/* program counter is saved in x0 as well as x1, similar to mips */ +#ifndef REG_PC +#define REG_PC (0) +#endif + +#ifndef REG_RA +#define REG_RA (1) +#endif + +#ifndef REG_SP +#define REG_SP (2) +#endif + +#ifndef REG_S0 +#define REG_S0 (8) +#endif + +#define REG_S1 (9) + +#ifndef REG_A0 +#define REG_A0 (10) +#endif + +#define REG_A1 (11) +#define REG_A2 (12) +#define REG_A3 (13) +#define REG_A4 (14) +#define REG_A5 (15) +#define REG_A6 (16) +#define REG_A7 (17) +#define REG_S2 (18) +#define REG_S3 (19) +#define REG_S4 (20) +#define REG_S5 (21) +#define REG_S6 (22) +#define REG_S7 (23) +#define REG_S8 (24) +#define REG_S9 (25) +#define REG_S10 (26) +#define REG_S11 (27) + +#define PC_OFFSET REG_OFFSET(REG_PC) + +#define FETCH_LINKPTR(dest) \ + asm("mv %0, s1" : "=r" ((dest))) + +#include "common-defs.h" + +#endif diff --git a/src/3rdparty/libucontext/arch/riscv32/getcontext.S b/src/3rdparty/libucontext/arch/riscv32/getcontext.S new file mode 100644 index 000000000..888b6ab1e --- /dev/null +++ b/src/3rdparty/libucontext/arch/riscv32/getcontext.S @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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" + +ALIAS(getcontext, libucontext_getcontext) +ALIAS(__getcontext, libucontext_getcontext) + +FUNC(libucontext_getcontext) + sw ra, REG_OFFSET(REG_PC)(a0) + sw ra, REG_OFFSET(REG_RA)(a0) + sw sp, REG_OFFSET(REG_SP)(a0) + + /* first saved register block */ + sw s0, REG_OFFSET(REG_S0)(a0) + sw s1, REG_OFFSET(REG_S1)(a0) + + /* return register block */ + sw a0, REG_OFFSET(REG_A0)(a0) + sw a1, REG_OFFSET(REG_A1)(a0) + + /* second saved register block */ + sw s2, REG_OFFSET(REG_S2)(a0) + sw s3, REG_OFFSET(REG_S3)(a0) + sw s4, REG_OFFSET(REG_S4)(a0) + sw s5, REG_OFFSET(REG_S5)(a0) + sw s6, REG_OFFSET(REG_S6)(a0) + sw s7, REG_OFFSET(REG_S7)(a0) + sw s8, REG_OFFSET(REG_S8)(a0) + sw s9, REG_OFFSET(REG_S9)(a0) + sw s10, REG_OFFSET(REG_S10)(a0) + sw s11, REG_OFFSET(REG_S11)(a0) + + /* done saving, return */ + ret +END(libucontext_getcontext) diff --git a/src/3rdparty/libucontext/arch/riscv32/include/libucontext/bits.h b/src/3rdparty/libucontext/arch/riscv32/include/libucontext/bits.h new file mode 100644 index 000000000..8d7867608 --- /dev/null +++ b/src/3rdparty/libucontext/arch/riscv32/include/libucontext/bits.h @@ -0,0 +1,48 @@ +#ifndef LIBUCONTEXT_BITS_H +#define LIBUCONTEXT_BITS_H + +typedef unsigned long libucontext_greg_t; +typedef unsigned long libucontext__riscv_mc_gp_state[32]; + +struct libucontext__riscv_mc_f_ext_state { + unsigned int __f[32]; + unsigned int __fcsr; +}; + +struct libucontext__riscv_mc_d_ext_state { + unsigned long long __f[32]; + unsigned int __fcsr; +}; + +struct libucontext__riscv_mc_q_ext_state { + unsigned long long __f[64] __attribute__((aligned(16))); + unsigned int __fcsr; + unsigned int __reserved[3]; +}; + +union libucontext__riscv_mc_fp_state { + struct libucontext__riscv_mc_f_ext_state __f; + struct libucontext__riscv_mc_d_ext_state __d; + struct libucontext__riscv_mc_q_ext_state __q; +}; + +typedef struct libucontext_mcontext { + libucontext__riscv_mc_gp_state __gregs; + union libucontext__riscv_mc_fp_state __fpregs; +} libucontext_mcontext_t; + +typedef struct { + void *ss_sp; + int ss_flags; + size_t ss_size; +} libucontext_stack_t; + +typedef struct libucontext_ucontext { + unsigned long uc_flags; + struct libucontext_ucontext *uc_link; + libucontext_stack_t uc_stack; + unsigned char __pad[128]; + libucontext_mcontext_t uc_mcontext; +} libucontext_ucontext_t; + +#endif diff --git a/src/3rdparty/libucontext/arch/riscv32/makecontext.c b/src/3rdparty/libucontext/arch/riscv32/makecontext.c new file mode 100644 index 000000000..9a43ef4e9 --- /dev/null +++ b/src/3rdparty/libucontext/arch/riscv32/makecontext.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018 Ariadne Conill + * + * 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 +#include +#include +#include +#include +#include "defs.h" +#include + + +extern void libucontext_trampoline(void); + + +void +libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(void), int argc, ...) +{ + libucontext_greg_t *sp, *regp; + va_list va; + int i; + + /* set up and align the stack. */ + sp = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); + sp -= argc < 8 ? 0 : argc - 8; + sp = (libucontext_greg_t *) (((uintptr_t) sp & -16L)); + + /* set up the ucontext structure */ + ucp->uc_mcontext.__gregs[REG_RA] = (libucontext_greg_t) libucontext_trampoline; + ucp->uc_mcontext.__gregs[REG_S0] = 0; + ucp->uc_mcontext.__gregs[REG_S1] = (libucontext_greg_t) ucp->uc_link; + ucp->uc_mcontext.__gregs[REG_SP] = (libucontext_greg_t) sp; + ucp->uc_mcontext.__gregs[REG_PC] = (libucontext_greg_t) func; + + va_start(va, argc); + + /* first 8 args go in $a0 through $a7. */ + regp = &(ucp->uc_mcontext.__gregs[REG_A0]); + + for (i = 0; (i < argc && i < 8); i++) + *regp++ = va_arg (va, libucontext_greg_t); + + /* remainder overflows into stack */ + for (; i < argc; i++) + *sp++ = va_arg (va, libucontext_greg_t); + + va_end(va); +} + +#ifdef EXPORT_UNPREFIXED +extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +#endif diff --git a/src/3rdparty/libucontext/arch/riscv32/setcontext.S b/src/3rdparty/libucontext/arch/riscv32/setcontext.S new file mode 100644 index 000000000..06727851e --- /dev/null +++ b/src/3rdparty/libucontext/arch/riscv32/setcontext.S @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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" + +ALIAS(setcontext, libucontext_setcontext) +ALIAS(__setcontext, libucontext_setcontext) + +FUNC(libucontext_setcontext) + /* move $a0 to $t0 to avoid clobbering. */ + mv t0, a0 + + lw t1, PC_OFFSET(t0) + lw ra, REG_OFFSET(REG_RA)(t0) + lw sp, REG_OFFSET(REG_SP)(t0) + + /* first saved register block */ + lw s0, REG_OFFSET(REG_S0)(t0) + lw s1, REG_OFFSET(REG_S1)(t0) + + /* return register block */ + lw a0, REG_OFFSET(REG_A0)(t0) + lw a1, REG_OFFSET(REG_A1)(t0) + + /* argument register block */ + lw a2, REG_OFFSET(REG_A2)(t0) + lw a3, REG_OFFSET(REG_A3)(t0) + lw a4, REG_OFFSET(REG_A4)(t0) + lw a5, REG_OFFSET(REG_A5)(t0) + lw a6, REG_OFFSET(REG_A6)(t0) + lw a7, REG_OFFSET(REG_A7)(t0) + + /* second saved register block */ + lw s2, REG_OFFSET(REG_S2)(t0) + lw s3, REG_OFFSET(REG_S3)(t0) + lw s4, REG_OFFSET(REG_S4)(t0) + lw s5, REG_OFFSET(REG_S5)(t0) + lw s6, REG_OFFSET(REG_S6)(t0) + lw s7, REG_OFFSET(REG_S7)(t0) + lw s8, REG_OFFSET(REG_S8)(t0) + lw s9, REG_OFFSET(REG_S9)(t0) + lw s10, REG_OFFSET(REG_S10)(t0) + lw s11, REG_OFFSET(REG_S11)(t0) + + /* done restoring, jump to new pc in S1 */ + jr t1 +END(libucontext_setcontext) diff --git a/src/3rdparty/libucontext/arch/riscv32/swapcontext.S b/src/3rdparty/libucontext/arch/riscv32/swapcontext.S new file mode 100644 index 000000000..a4c7138a9 --- /dev/null +++ b/src/3rdparty/libucontext/arch/riscv32/swapcontext.S @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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" + +ALIAS(swapcontext, libucontext_swapcontext) +ALIAS(__swapcontext, libucontext_swapcontext) + +FUNC(libucontext_swapcontext) + /* move $a1 to $t0 to avoid clobbering. */ + mv t0, a1 + + sw ra, REG_OFFSET(REG_PC)(a0) + sw ra, REG_OFFSET(REG_RA)(a0) + sw sp, REG_OFFSET(REG_SP)(a0) + + /* first saved register block */ + sw s0, REG_OFFSET(REG_S0)(a0) + sw s1, REG_OFFSET(REG_S1)(a0) + + /* return register block */ + sw a0, REG_OFFSET(REG_A0)(a0) + sw a1, REG_OFFSET(REG_A1)(a0) + + /* second saved register block */ + sw s2, REG_OFFSET(REG_S2)(a0) + sw s3, REG_OFFSET(REG_S3)(a0) + sw s4, REG_OFFSET(REG_S4)(a0) + sw s5, REG_OFFSET(REG_S5)(a0) + sw s6, REG_OFFSET(REG_S6)(a0) + sw s7, REG_OFFSET(REG_S7)(a0) + sw s8, REG_OFFSET(REG_S8)(a0) + sw s9, REG_OFFSET(REG_S9)(a0) + sw s10, REG_OFFSET(REG_S10)(a0) + sw s11, REG_OFFSET(REG_S11)(a0) + + /* restore the other context from $t0. */ + lw t1, REG_OFFSET(REG_PC)(t0) + lw ra, REG_OFFSET(REG_RA)(t0) + lw sp, REG_OFFSET(REG_SP)(t0) + + /* first saved register block */ + lw s0, REG_OFFSET(REG_S0)(t0) + lw s1, REG_OFFSET(REG_S1)(t0) + + /* return register block */ + lw a0, REG_OFFSET(REG_A0)(t0) + lw a1, REG_OFFSET(REG_A1)(t0) + + /* argument register block */ + lw a2, REG_OFFSET(REG_A2)(t0) + lw a3, REG_OFFSET(REG_A3)(t0) + lw a4, REG_OFFSET(REG_A4)(t0) + lw a5, REG_OFFSET(REG_A5)(t0) + lw a6, REG_OFFSET(REG_A6)(t0) + lw a7, REG_OFFSET(REG_A7)(t0) + + /* second saved register block */ + lw s2, REG_OFFSET(REG_S2)(t0) + lw s3, REG_OFFSET(REG_S3)(t0) + lw s4, REG_OFFSET(REG_S4)(t0) + lw s5, REG_OFFSET(REG_S5)(t0) + lw s6, REG_OFFSET(REG_S6)(t0) + lw s7, REG_OFFSET(REG_S7)(t0) + lw s8, REG_OFFSET(REG_S8)(t0) + lw s9, REG_OFFSET(REG_S9)(t0) + lw s10, REG_OFFSET(REG_S10)(t0) + lw s11, REG_OFFSET(REG_S11)(t0) + + /* done swapping, jump to new PC in S1 */ + jr t1 +END(libucontext_swapcontext) diff --git a/src/3rdparty/libucontext/arch/riscv32/trampoline.c b/src/3rdparty/libucontext/arch/riscv32/trampoline.c new file mode 100644 index 000000000..699a0505d --- /dev/null +++ b/src/3rdparty/libucontext/arch/riscv32/trampoline.c @@ -0,0 +1,3 @@ +#include "defs.h" +#include +#include "common-trampoline.c" diff --git a/src/3rdparty/libucontext/arch/riscv64/defs.h b/src/3rdparty/libucontext/arch/riscv64/defs.h new file mode 100644 index 000000000..d9b764713 --- /dev/null +++ b/src/3rdparty/libucontext/arch/riscv64/defs.h @@ -0,0 +1,55 @@ +#ifndef __ARCH_RISCV64_DEFS_H +#define __ARCH_RISCV64_DEFS_H + +#define REG_SZ (8) +#define MCONTEXT_GREGS (176) + +/* program counter is saved in x0 as well as x1, similar to mips */ +#ifndef REG_PC +#define REG_PC (0) +#endif + +#ifndef REG_RA +#define REG_RA (1) +#endif + +#ifndef REG_SP +#define REG_SP (2) +#endif + +#ifndef REG_S0 +#define REG_S0 (8) +#endif + +#define REG_S1 (9) + +#ifndef REG_A0 +#define REG_A0 (10) +#endif + +#define REG_A1 (11) +#define REG_A2 (12) +#define REG_A3 (13) +#define REG_A4 (14) +#define REG_A5 (15) +#define REG_A6 (16) +#define REG_A7 (17) +#define REG_S2 (18) +#define REG_S3 (19) +#define REG_S4 (20) +#define REG_S5 (21) +#define REG_S6 (22) +#define REG_S7 (23) +#define REG_S8 (24) +#define REG_S9 (25) +#define REG_S10 (26) +#define REG_S11 (27) + +#define PC_OFFSET REG_OFFSET(REG_PC) + +#define FETCH_LINKPTR(dest) \ + asm("mv %0, s1" : "=r" ((dest))) + +#include "common-defs.h" + +#endif diff --git a/src/3rdparty/libucontext/arch/riscv64/getcontext.S b/src/3rdparty/libucontext/arch/riscv64/getcontext.S new file mode 100644 index 000000000..99a9c9ad9 --- /dev/null +++ b/src/3rdparty/libucontext/arch/riscv64/getcontext.S @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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" + +ALIAS(getcontext, libucontext_getcontext) +ALIAS(__getcontext, libucontext_getcontext) + +FUNC(libucontext_getcontext) + sd ra, REG_OFFSET(REG_PC)(a0) + sd ra, REG_OFFSET(REG_RA)(a0) + sd sp, REG_OFFSET(REG_SP)(a0) + + /* first saved register block */ + sd s0, REG_OFFSET(REG_S0)(a0) + sd s1, REG_OFFSET(REG_S1)(a0) + + /* return register block */ + sd a0, REG_OFFSET(REG_A0)(a0) + sd a1, REG_OFFSET(REG_A1)(a0) + + /* second saved register block */ + sd s2, REG_OFFSET(REG_S2)(a0) + sd s3, REG_OFFSET(REG_S3)(a0) + sd s4, REG_OFFSET(REG_S4)(a0) + sd s5, REG_OFFSET(REG_S5)(a0) + sd s6, REG_OFFSET(REG_S6)(a0) + sd s7, REG_OFFSET(REG_S7)(a0) + sd s8, REG_OFFSET(REG_S8)(a0) + sd s9, REG_OFFSET(REG_S9)(a0) + sd s10, REG_OFFSET(REG_S10)(a0) + sd s11, REG_OFFSET(REG_S11)(a0) + + /* done saving, return */ + ret +END(libucontext_getcontext) diff --git a/src/3rdparty/libucontext/arch/riscv64/include/libucontext/bits.h b/src/3rdparty/libucontext/arch/riscv64/include/libucontext/bits.h new file mode 100644 index 000000000..8d7867608 --- /dev/null +++ b/src/3rdparty/libucontext/arch/riscv64/include/libucontext/bits.h @@ -0,0 +1,48 @@ +#ifndef LIBUCONTEXT_BITS_H +#define LIBUCONTEXT_BITS_H + +typedef unsigned long libucontext_greg_t; +typedef unsigned long libucontext__riscv_mc_gp_state[32]; + +struct libucontext__riscv_mc_f_ext_state { + unsigned int __f[32]; + unsigned int __fcsr; +}; + +struct libucontext__riscv_mc_d_ext_state { + unsigned long long __f[32]; + unsigned int __fcsr; +}; + +struct libucontext__riscv_mc_q_ext_state { + unsigned long long __f[64] __attribute__((aligned(16))); + unsigned int __fcsr; + unsigned int __reserved[3]; +}; + +union libucontext__riscv_mc_fp_state { + struct libucontext__riscv_mc_f_ext_state __f; + struct libucontext__riscv_mc_d_ext_state __d; + struct libucontext__riscv_mc_q_ext_state __q; +}; + +typedef struct libucontext_mcontext { + libucontext__riscv_mc_gp_state __gregs; + union libucontext__riscv_mc_fp_state __fpregs; +} libucontext_mcontext_t; + +typedef struct { + void *ss_sp; + int ss_flags; + size_t ss_size; +} libucontext_stack_t; + +typedef struct libucontext_ucontext { + unsigned long uc_flags; + struct libucontext_ucontext *uc_link; + libucontext_stack_t uc_stack; + unsigned char __pad[128]; + libucontext_mcontext_t uc_mcontext; +} libucontext_ucontext_t; + +#endif diff --git a/src/3rdparty/libucontext/arch/riscv64/makecontext.c b/src/3rdparty/libucontext/arch/riscv64/makecontext.c new file mode 100644 index 000000000..9a43ef4e9 --- /dev/null +++ b/src/3rdparty/libucontext/arch/riscv64/makecontext.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018 Ariadne Conill + * + * 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 +#include +#include +#include +#include +#include "defs.h" +#include + + +extern void libucontext_trampoline(void); + + +void +libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(void), int argc, ...) +{ + libucontext_greg_t *sp, *regp; + va_list va; + int i; + + /* set up and align the stack. */ + sp = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); + sp -= argc < 8 ? 0 : argc - 8; + sp = (libucontext_greg_t *) (((uintptr_t) sp & -16L)); + + /* set up the ucontext structure */ + ucp->uc_mcontext.__gregs[REG_RA] = (libucontext_greg_t) libucontext_trampoline; + ucp->uc_mcontext.__gregs[REG_S0] = 0; + ucp->uc_mcontext.__gregs[REG_S1] = (libucontext_greg_t) ucp->uc_link; + ucp->uc_mcontext.__gregs[REG_SP] = (libucontext_greg_t) sp; + ucp->uc_mcontext.__gregs[REG_PC] = (libucontext_greg_t) func; + + va_start(va, argc); + + /* first 8 args go in $a0 through $a7. */ + regp = &(ucp->uc_mcontext.__gregs[REG_A0]); + + for (i = 0; (i < argc && i < 8); i++) + *regp++ = va_arg (va, libucontext_greg_t); + + /* remainder overflows into stack */ + for (; i < argc; i++) + *sp++ = va_arg (va, libucontext_greg_t); + + va_end(va); +} + +#ifdef EXPORT_UNPREFIXED +extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +#endif diff --git a/src/3rdparty/libucontext/arch/riscv64/setcontext.S b/src/3rdparty/libucontext/arch/riscv64/setcontext.S new file mode 100644 index 000000000..36704c91a --- /dev/null +++ b/src/3rdparty/libucontext/arch/riscv64/setcontext.S @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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" + +ALIAS(setcontext, libucontext_setcontext) +ALIAS(__setcontext, libucontext_setcontext) + +FUNC(libucontext_setcontext) + /* move $a0 to $t0 to avoid clobbering. */ + mv t0, a0 + + ld t1, PC_OFFSET(t0) + ld ra, REG_OFFSET(REG_RA)(t0) + ld sp, REG_OFFSET(REG_SP)(t0) + + /* first saved register block */ + ld s0, REG_OFFSET(REG_S0)(t0) + ld s1, REG_OFFSET(REG_S1)(t0) + + /* return register block */ + ld a0, REG_OFFSET(REG_A0)(t0) + ld a1, REG_OFFSET(REG_A1)(t0) + + /* argument register block */ + ld a2, REG_OFFSET(REG_A2)(t0) + ld a3, REG_OFFSET(REG_A3)(t0) + ld a4, REG_OFFSET(REG_A4)(t0) + ld a5, REG_OFFSET(REG_A5)(t0) + ld a6, REG_OFFSET(REG_A6)(t0) + ld a7, REG_OFFSET(REG_A7)(t0) + + /* second saved register block */ + ld s2, REG_OFFSET(REG_S2)(t0) + ld s3, REG_OFFSET(REG_S3)(t0) + ld s4, REG_OFFSET(REG_S4)(t0) + ld s5, REG_OFFSET(REG_S5)(t0) + ld s6, REG_OFFSET(REG_S6)(t0) + ld s7, REG_OFFSET(REG_S7)(t0) + ld s8, REG_OFFSET(REG_S8)(t0) + ld s9, REG_OFFSET(REG_S9)(t0) + ld s10, REG_OFFSET(REG_S10)(t0) + ld s11, REG_OFFSET(REG_S11)(t0) + + /* done restoring, jump to new pc in S1 */ + jr t1 +END(libucontext_setcontext) diff --git a/src/3rdparty/libucontext/arch/riscv64/swapcontext.S b/src/3rdparty/libucontext/arch/riscv64/swapcontext.S new file mode 100644 index 000000000..a2b013e1c --- /dev/null +++ b/src/3rdparty/libucontext/arch/riscv64/swapcontext.S @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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" + +ALIAS(swapcontext, libucontext_swapcontext) +ALIAS(__swapcontext, libucontext_swapcontext) + +FUNC(libucontext_swapcontext) + /* move $a1 to $t0 to avoid clobbering. */ + mv t0, a1 + + sd ra, REG_OFFSET(REG_PC)(a0) + sd ra, REG_OFFSET(REG_RA)(a0) + sd sp, REG_OFFSET(REG_SP)(a0) + + /* first saved register block */ + sd s0, REG_OFFSET(REG_S0)(a0) + sd s1, REG_OFFSET(REG_S1)(a0) + + /* return register block */ + sd a0, REG_OFFSET(REG_A0)(a0) + sd a1, REG_OFFSET(REG_A1)(a0) + + /* second saved register block */ + sd s2, REG_OFFSET(REG_S2)(a0) + sd s3, REG_OFFSET(REG_S3)(a0) + sd s4, REG_OFFSET(REG_S4)(a0) + sd s5, REG_OFFSET(REG_S5)(a0) + sd s6, REG_OFFSET(REG_S6)(a0) + sd s7, REG_OFFSET(REG_S7)(a0) + sd s8, REG_OFFSET(REG_S8)(a0) + sd s9, REG_OFFSET(REG_S9)(a0) + sd s10, REG_OFFSET(REG_S10)(a0) + sd s11, REG_OFFSET(REG_S11)(a0) + + /* restore the other context from $t0. */ + ld t1, REG_OFFSET(REG_PC)(t0) + ld ra, REG_OFFSET(REG_RA)(t0) + ld sp, REG_OFFSET(REG_SP)(t0) + + /* first saved register block */ + ld s0, REG_OFFSET(REG_S0)(t0) + ld s1, REG_OFFSET(REG_S1)(t0) + + /* return register block */ + ld a0, REG_OFFSET(REG_A0)(t0) + ld a1, REG_OFFSET(REG_A1)(t0) + + /* argument register block */ + ld a2, REG_OFFSET(REG_A2)(t0) + ld a3, REG_OFFSET(REG_A3)(t0) + ld a4, REG_OFFSET(REG_A4)(t0) + ld a5, REG_OFFSET(REG_A5)(t0) + ld a6, REG_OFFSET(REG_A6)(t0) + ld a7, REG_OFFSET(REG_A7)(t0) + + /* second saved register block */ + ld s2, REG_OFFSET(REG_S2)(t0) + ld s3, REG_OFFSET(REG_S3)(t0) + ld s4, REG_OFFSET(REG_S4)(t0) + ld s5, REG_OFFSET(REG_S5)(t0) + ld s6, REG_OFFSET(REG_S6)(t0) + ld s7, REG_OFFSET(REG_S7)(t0) + ld s8, REG_OFFSET(REG_S8)(t0) + ld s9, REG_OFFSET(REG_S9)(t0) + ld s10, REG_OFFSET(REG_S10)(t0) + ld s11, REG_OFFSET(REG_S11)(t0) + + /* done swapping, jump to new PC in S1 */ + jr t1 +END(libucontext_swapcontext) diff --git a/src/3rdparty/libucontext/arch/riscv64/trampoline.c b/src/3rdparty/libucontext/arch/riscv64/trampoline.c new file mode 100644 index 000000000..699a0505d --- /dev/null +++ b/src/3rdparty/libucontext/arch/riscv64/trampoline.c @@ -0,0 +1,3 @@ +#include "defs.h" +#include +#include "common-trampoline.c" diff --git a/src/3rdparty/libucontext/arch/s390x/defs.h b/src/3rdparty/libucontext/arch/s390x/defs.h new file mode 100644 index 000000000..cad21845f --- /dev/null +++ b/src/3rdparty/libucontext/arch/s390x/defs.h @@ -0,0 +1,15 @@ +#ifndef __ARCH_S390X_DEFS_H +#define __ARCH_S390X_DEFS_H + +#define REG_SZ (8) +#define AREG_SZ (4) + +#define MCONTEXT_GREGS (56) +#define MCONTEXT_AREGS (184) +#define MCONTEXT_FPREGS (248) + +#define AREG_OFFSET(__reg) (MCONTEXT_AREGS + ((__reg) * AREG_SZ)) + +#include "common-defs.h" + +#endif diff --git a/src/3rdparty/libucontext/arch/s390x/getcontext.S b/src/3rdparty/libucontext/arch/s390x/getcontext.S new file mode 100644 index 000000000..fd19d9b80 --- /dev/null +++ b/src/3rdparty/libucontext/arch/s390x/getcontext.S @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018, 2020 Ariadne Conill + * + * 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" + +ALIAS(getcontext, libucontext_getcontext) +ALIAS(__getcontext, libucontext_getcontext) + +FUNC(libucontext_getcontext) + lgr %r1, %r2 /* use %r1 as our working register */ + la %r2, 0 /* we will return 0 */ + + stam %a0, %a15, AREG_OFFSET(0)(%r1) /* store access registers */ + stmg %r0, %r15, REG_OFFSET(0)(%r1) /* store general-purpose registers */ + + br %r14 /* return to where we came from */ +END(libucontext_getcontext) diff --git a/src/3rdparty/libucontext/arch/s390x/include/libucontext/bits.h b/src/3rdparty/libucontext/arch/s390x/include/libucontext/bits.h new file mode 100644 index 000000000..bce841cbc --- /dev/null +++ b/src/3rdparty/libucontext/arch/s390x/include/libucontext/bits.h @@ -0,0 +1,41 @@ +#ifndef LIBUCONTEXT_BITS_H +#define LIBUCONTEXT_BITS_H + +typedef unsigned long libucontext_greg_t, libucontext_gregset_t[27]; + +typedef struct { + unsigned long mask; + unsigned long addr; +} libucontext_psw_t; + +typedef union { + double d; + float f; +} libucontext_fpreg_t; + +typedef struct { + unsigned fpc; + libucontext_fpreg_t fprs[16]; +} libucontext_fpregset_t; + +typedef struct { + libucontext_psw_t psw; + unsigned long gregs[16]; + unsigned aregs[16]; + libucontext_fpregset_t fpregs; +} libucontext_mcontext_t; + +typedef struct { + void *ss_sp; + int ss_flags; + size_t ss_size; +} libucontext_stack_t; + +typedef struct libucontext_ucontext { + unsigned long uc_flags; + struct libucontext_ucontext *uc_link; + libucontext_stack_t uc_stack; + libucontext_mcontext_t uc_mcontext; +} libucontext_ucontext_t; + +#endif diff --git a/src/3rdparty/libucontext/arch/s390x/makecontext.c b/src/3rdparty/libucontext/arch/s390x/makecontext.c new file mode 100644 index 000000000..22ce2527b --- /dev/null +++ b/src/3rdparty/libucontext/arch/s390x/makecontext.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 2020 Ariadne Conill + * + * 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 +#include +#include +#include + + +#include "defs.h" +#include + + +extern void libucontext_trampoline(void); +extern int libucontext_setcontext(const libucontext_ucontext_t *ucp); + + +void +libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(void), int argc, ...) +{ + libucontext_greg_t *sp; + va_list va; + int i; + + sp = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); + sp = (libucontext_greg_t *) (((uintptr_t) sp & -8L)); + + ucp->uc_mcontext.gregs[7] = (uintptr_t) func; + ucp->uc_mcontext.gregs[8] = (uintptr_t) ucp->uc_link; + ucp->uc_mcontext.gregs[9] = (uintptr_t) &libucontext_setcontext; + ucp->uc_mcontext.gregs[14] = (uintptr_t) &libucontext_trampoline; + + va_start(va, argc); + + for (i = 0; i < argc && i < 5; i++) + ucp->uc_mcontext.gregs[i + 2] = va_arg (va, libucontext_greg_t); + + if (argc > 5) + { + sp -= argc - 5; + + for (i = 5; i < argc; i++) + sp[i - 5] = va_arg (va, libucontext_greg_t); + } + + va_end(va); + + /* make room for backchain / register save area */ + sp -= 20; + *sp = 0; + + /* set up %r15 as sp */ + ucp->uc_mcontext.gregs[15] = (uintptr_t) sp; +} + +#ifdef EXPORT_UNPREFIXED +extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +#endif diff --git a/src/3rdparty/libucontext/arch/s390x/setcontext.S b/src/3rdparty/libucontext/arch/s390x/setcontext.S new file mode 100644 index 000000000..03fd4a175 --- /dev/null +++ b/src/3rdparty/libucontext/arch/s390x/setcontext.S @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018, 2020 Ariadne Conill + * + * 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" + +ALIAS(setcontext, libucontext_setcontext) +ALIAS(__setcontext, libucontext_setcontext) + +FUNC(libucontext_setcontext) + lgr %r1, %r2 /* use %r1 as our working register */ + + lam %a2, %a15, AREG_OFFSET(2)(%r1) /* load access registers, but skip %a0 and %a1 which are for TLS */ + lmg %r0, %r15, REG_OFFSET(0)(%r1) /* store general-purpose registers */ + + br %r14 /* return to new link register address */ +END(libucontext_setcontext) diff --git a/src/3rdparty/libucontext/arch/s390x/startcontext.S b/src/3rdparty/libucontext/arch/s390x/startcontext.S new file mode 100644 index 000000000..16569437d --- /dev/null +++ b/src/3rdparty/libucontext/arch/s390x/startcontext.S @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018, 2020 Ariadne Conill + * + * 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" + +.hidden libucontext_trampoline +FUNC(libucontext_trampoline) + basr %r14, %r7 /* run function pointer (%r7) and return here */ + ltgr %r8, %r8 /* check to see if uc_link (%r8) is null */ + + jz no_linked_context /* if we have no linked context, prepare to exit */ + + lgr %r2, %r8 /* copy the uc_link structure address to %r2 */ + br %r9 /* call setcontext */ + +no_linked_context: + la %r2, 0 /* return 0 */ + brasl %r14, exit@plt /* call exit */ + + j .+2 /* crash if exit returns */ +END(libucontext_trampoline) diff --git a/src/3rdparty/libucontext/arch/s390x/swapcontext.S b/src/3rdparty/libucontext/arch/s390x/swapcontext.S new file mode 100644 index 000000000..21a9b5ad6 --- /dev/null +++ b/src/3rdparty/libucontext/arch/s390x/swapcontext.S @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018, 2020 Ariadne Conill + * + * 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" + +ALIAS(swapcontext, libucontext_swapcontext) +ALIAS(__swapcontext, libucontext_swapcontext) + +FUNC(libucontext_swapcontext) + lgr %r1, %r2 /* use %r1 to save current context to */ + lgr %r0, %r3 /* use %r0 for source context */ + + stam %a0, %a15, AREG_OFFSET(0)(%r1) /* store access registers */ + stmg %r0, %r15, REG_OFFSET(0)(%r1) /* store general-purpose registers */ + + lgr %r2, %r0 /* swap %r0 to %r2 (XXX: figure out why it hates loading from %r0) */ + lam %a2, %a15, AREG_OFFSET(2)(%r2) /* load access registers, but skip %a0 and %a1 which are for TLS */ + lmg %r0, %r15, REG_OFFSET(0)(%r2) /* load general-purpose registers */ + + br %r14 /* return to new link register address */ +END(libucontext_swapcontext) diff --git a/src/3rdparty/libucontext/arch/sh/defs.h b/src/3rdparty/libucontext/arch/sh/defs.h new file mode 100644 index 000000000..7cddaeffd --- /dev/null +++ b/src/3rdparty/libucontext/arch/sh/defs.h @@ -0,0 +1,20 @@ +#ifndef __ARCH_SH4_DEFS_H +#define __ARCH_SH4_DEFS_H + +#define REG_SZ (4) +#define MCONTEXT_GREGS (24) + +#define REG_SP (15) +#define REG_PC (16) +#define REG_PR (17) +#define REG_SR (18) +#define REG_GBR (19) +#define REG_MACH (20) +#define REG_MACL (21) + +#define FETCH_LINKPTR(dest) \ + asm("mov r8, %0" : "=r" (dest)); + +#include "common-defs.h" + +#endif diff --git a/src/3rdparty/libucontext/arch/sh/getcontext.S b/src/3rdparty/libucontext/arch/sh/getcontext.S new file mode 100644 index 000000000..0978af610 --- /dev/null +++ b/src/3rdparty/libucontext/arch/sh/getcontext.S @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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" + +ALIAS(getcontext, libucontext_getcontext) +ALIAS(__getcontext, libucontext_getcontext) + +FUNC(libucontext_getcontext) + mov r4, r0 /* move r4 to r0, and increment by REG_OFFSET(REG_MACL) + REG_SZ. */ + add #(REG_OFFSET(REG_MACL + 1)), r0 + + sts.l macl, @-r0 /* save macl/mach registers */ + sts.l mach, @-r0 + + stc.l gbr, @-r0 /* save gbr register */ + + movt r1 /* load T-flag into r1 */ + mov.l r1, @-r0 /* save T-flag as SR register */ + + sts.l pr, @-r0 /* save current PR */ + sts.l pr, @-r0 /* save current PR as PC as well */ + + mov.l r15, @-r0 /* preserve registers backwards, from r15 to r1 */ + mov.l r14, @-r0 + mov.l r13, @-r0 + mov.l r12, @-r0 + mov.l r11, @-r0 + mov.l r10, @-r0 + mov.l r9, @-r0 + mov.l r8, @-r0 + mov.l r7, @-r0 + mov.l r6, @-r0 + mov.l r5, @-r0 + mov.l r4, @-r0 + mov.l r3, @-r0 + mov.l r2, @-r0 + mov.l r1, @-r0 + + mov r0, r1 + mov #0, r0 + + mov.l r0, @-r1 /* preserve r0 as explicit zero */ + + mov #0, r0 /* set return value as zero */ + rts +END(libucontext_getcontext) diff --git a/src/3rdparty/libucontext/arch/sh/include/libucontext/bits.h b/src/3rdparty/libucontext/arch/sh/include/libucontext/bits.h new file mode 100644 index 000000000..3db92add4 --- /dev/null +++ b/src/3rdparty/libucontext/arch/sh/include/libucontext/bits.h @@ -0,0 +1,29 @@ +#ifndef LIBUCONTEXT_BITS_H +#define LIBUCONTEXT_BITS_H + +typedef unsigned long libucontext_greg_t, libucontext_gregset_t[16]; +typedef unsigned long libucontext_freg_t, libucontext_fpregset_t[16]; +typedef struct sigcontext { + unsigned long oldmask; + unsigned long gregs[16]; + unsigned long pc, pr, sr; + unsigned long gbr, mach, macl; + unsigned long fpregs[16]; + unsigned long xfpregs[16]; + unsigned int fpscr, fpul, ownedfp; +} libucontext_mcontext_t; + +typedef struct { + void *ss_sp; + int ss_flags; + size_t ss_size; +} libucontext_stack_t; + +typedef struct libucontext_ucontext { + unsigned long uc_flags; + struct libucontext_ucontext *uc_link; + libucontext_stack_t uc_stack; + libucontext_mcontext_t uc_mcontext; +} libucontext_ucontext_t; + +#endif diff --git a/src/3rdparty/libucontext/arch/sh/makecontext.c b/src/3rdparty/libucontext/arch/sh/makecontext.c new file mode 100644 index 000000000..7e28e2aff --- /dev/null +++ b/src/3rdparty/libucontext/arch/sh/makecontext.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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 +#include +#include +#include +#include +#include "defs.h" +#include + + +extern void libucontext_trampoline(void); + + +void +libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(void), int argc, ...) +{ + libucontext_greg_t *sp, *regp; + va_list va; + int i; + + /* set up and align the stack */ + sp = (libucontext_greg_t *) (((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size) & -4L); + sp -= argc > 4 ? argc - 4 : 0; + + /* set up the context */ + ucp->uc_mcontext.gregs[REG_SP] = (libucontext_greg_t) sp; + ucp->uc_mcontext.pr = (libucontext_greg_t) libucontext_trampoline; + ucp->uc_mcontext.pc = (libucontext_greg_t) func; + ucp->uc_mcontext.gregs[8] = (libucontext_greg_t) ucp->uc_link; + + /* pass up to four args in r4-r7, rest on stack */ + va_start(va, argc); + + regp = &ucp->uc_mcontext.gregs[4]; + + for (i = 0; i < argc && i < 4; i++) + *regp++ = va_arg(va, libucontext_greg_t); + + for (; i < argc; i++) + *sp++ = va_arg(va, libucontext_greg_t); + + va_end(va); +} + +#ifdef EXPORT_UNPREFIXED +extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +#endif diff --git a/src/3rdparty/libucontext/arch/sh/setcontext.S b/src/3rdparty/libucontext/arch/sh/setcontext.S new file mode 100644 index 000000000..cee065c0f --- /dev/null +++ b/src/3rdparty/libucontext/arch/sh/setcontext.S @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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" + +ALIAS(setcontext, libucontext_setcontext) +ALIAS(__setcontext, libucontext_setcontext) + +FUNC(libucontext_setcontext) + mov r4, r0 + + add #(REG_OFFSET(5)), r0 /* restore GPRs r5-15 */ + mov.l @r0+, r5 + mov.l @r0+, r6 + mov.l @r0+, r7 + mov.l @r0+, r8 + mov.l @r0+, r9 + mov.l @r0+, r10 + mov.l @r0+, r11 + mov.l @r0+, r12 + mov.l @r0+, r13 + mov.l @r0+, r14 + mov.l @r0+, r15 + + mov.l @r0+, r2 /* restore PR */ + lds.l @r0+, pr + + mov.l @r0+, r1 /* restore T-flag */ + shlr r1 + + add #REG_SZ, r0 /* skip GBR (used for TLS) */ + + lds.l @r0+, mach /* load mach/macl registers */ + lds.l @r0+, macl + + mov r4, r0 /* bring r0 back to the top of the context */ + add #(REG_OFFSET(0)), r1 /* restore r0 into r1 (temporarily) */ + mov.l r1, @-r15 /* push to stack from r1 */ + mov.l r2, @-r15 /* push PC to stack */ + + mov.l @(REG_OFFSET(1), r0), r1 /* restore real r1 */ + mov.l @(REG_OFFSET(2), r0), r2 /* restore real r2 */ + mov.l @(REG_OFFSET(3), r0), r3 /* restore real r2 */ + mov.l @(REG_OFFSET(4), r0), r4 /* restore real r2 */ + + mov.l @r15+, r0 /* pop PC from stack */ + + jmp @r0 /* jump to new PC */ + + mov.l @r15+, r0 /* pop original r0 from stack */ +END(libucontext_setcontext) diff --git a/src/3rdparty/libucontext/arch/sh/swapcontext.S b/src/3rdparty/libucontext/arch/sh/swapcontext.S new file mode 100644 index 000000000..289061373 --- /dev/null +++ b/src/3rdparty/libucontext/arch/sh/swapcontext.S @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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" + +ALIAS(swapcontext, libucontext_swapcontext) +ALIAS(__swapcontext, libucontext_swapcontext) + +FUNC(libucontext_swapcontext) + mov r4, r0 /* move r4 to r0, and increment by REG_OFFSET(REG_MACL) + REG_SZ. */ + add #(REG_OFFSET(REG_MACL + 1)), r0 + + sts.l macl, @-r0 /* save macl/mach registers */ + sts.l mach, @-r0 + + stc.l gbr, @-r0 /* save gbr register */ + + movt r1 /* load T-flag into r1 */ + mov.l r1, @-r0 /* save T-flag as SR register */ + + sts.l pr, @-r0 /* save current PR */ + sts.l pr, @-r0 /* save current PR as PC as well */ + + mov.l r15, @-r0 /* preserve registers backwards, from r15 to r1 */ + mov.l r14, @-r0 + mov.l r13, @-r0 + mov.l r12, @-r0 + mov.l r11, @-r0 + mov.l r10, @-r0 + mov.l r9, @-r0 + mov.l r8, @-r0 + mov.l r7, @-r0 + mov.l r6, @-r0 + mov.l r5, @-r0 + mov.l r4, @-r0 + mov.l r3, @-r0 + mov.l r2, @-r0 + mov.l r1, @-r0 + + mov r0, r1 + mov #0, r0 + + mov.l r0, @-r1 /* preserve r0 as explicit zero */ + + mov r5, r0 /* now restore the new context */ + + add #(REG_OFFSET(6)), r0 /* restore GPRs r6-15 */ + mov.l @r0+, r6 + mov.l @r0+, r7 + mov.l @r0+, r8 + mov.l @r0+, r9 + mov.l @r0+, r10 + mov.l @r0+, r11 + mov.l @r0+, r12 + mov.l @r0+, r13 + mov.l @r0+, r14 + mov.l @r0+, r15 + + mov.l @r0+, r2 /* restore PR */ + lds.l @r0+, pr + + mov.l @r0+, r1 /* restore T-flag */ + shlr r1 + + add #REG_SZ, r0 /* skip GBR (used for TLS) */ + + lds.l @r0+, mach /* load mach/macl registers */ + lds.l @r0+, macl + + mov r5, r0 /* bring r0 back to the top of the context */ + add #(REG_OFFSET(0)), r1 /* restore r0 into r1 (temporarily) */ + mov.l r1, @-r15 /* push to stack from r1 */ + mov.l r2, @-r15 /* push PC to stack */ + + mov.l @(REG_OFFSET(1), r0), r1 /* restore real r1 */ + mov.l @(REG_OFFSET(2), r0), r2 /* restore real r2 */ + mov.l @(REG_OFFSET(3), r0), r3 /* restore real r3 */ + mov.l @(REG_OFFSET(4), r0), r4 /* restore real r4 */ + mov.l @(REG_OFFSET(5), r0), r5 /* restore real r5 */ + + mov.l @r15+, r0 /* pop PC from stack */ + + jmp @r0 /* jump to new PC */ + + mov.l @r15+, r0 /* pop original r0 from stack */ +END(libucontext_swapcontext) diff --git a/src/3rdparty/libucontext/arch/sh/trampoline.c b/src/3rdparty/libucontext/arch/sh/trampoline.c new file mode 100644 index 000000000..699a0505d --- /dev/null +++ b/src/3rdparty/libucontext/arch/sh/trampoline.c @@ -0,0 +1,3 @@ +#include "defs.h" +#include +#include "common-trampoline.c" diff --git a/src/3rdparty/libucontext/arch/x86/defs.h b/src/3rdparty/libucontext/arch/x86/defs.h new file mode 100644 index 000000000..9370869a3 --- /dev/null +++ b/src/3rdparty/libucontext/arch/x86/defs.h @@ -0,0 +1,65 @@ +#ifndef __ARCH_X86_DEFS_H +#define __ARCH_X86_DEFS_H + +#ifndef REG_GS +# define REG_GS (0) +#endif + +#ifndef REG_FS +# define REG_FS (1) +#endif + +#ifndef REG_ES +# define REG_ES (2) +#endif + +#ifndef REG_DS +# define REG_DS (3) +#endif + +#ifndef REG_EDI +# define REG_EDI (4) +#endif + +#ifndef REG_ESI +# define REG_ESI (5) +#endif + +#ifndef REG_EBP +# define REG_EBP (6) +#endif + +#ifndef REG_ESP +# define REG_ESP (7) +#endif + +#ifndef REG_EBX +# define REG_EBX (8) +#endif + +#ifndef REG_EDX +# define REG_EDX (9) +#endif + +#ifndef REG_ECX +# define REG_ECX (10) +#endif + +#ifndef REG_EAX +# define REG_EAX (11) +#endif + +#ifndef REG_EIP +# define REG_EIP (14) +#endif + +#define REG_SZ (4) + +#define MCONTEXT_GREGS (20) + +#define FETCH_LINKPTR(dest) \ + asm("movl (%%esp, %%ebx, 4), %0" : "=r" ((dest))); + +#include "common-defs.h" + +#endif diff --git a/src/3rdparty/libucontext/arch/x86/getcontext.S b/src/3rdparty/libucontext/arch/x86/getcontext.S new file mode 100644 index 000000000..4b9519786 --- /dev/null +++ b/src/3rdparty/libucontext/arch/x86/getcontext.S @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018, 2020 Ariadne Conill + * + * 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" + +ALIAS(getcontext, libucontext_getcontext) +ALIAS(__getcontext, libucontext_getcontext) + +FUNC(libucontext_getcontext) + /* load address of the ucontext structure */ + movl 4(%esp), %eax + + /* EAX is not a preserved register */ + movl $0, REG_OFFSET(REG_EAX)(%eax) + + /* copy all of the current registers into the ucontext structure */ + movl %ecx, REG_OFFSET(REG_ECX)(%eax) + movl %ebx, REG_OFFSET(REG_EBX)(%eax) + movl %edx, REG_OFFSET(REG_EDX)(%eax) + movl %edi, REG_OFFSET(REG_EDI)(%eax) + movl %esi, REG_OFFSET(REG_ESI)(%eax) + movl %ebp, REG_OFFSET(REG_EBP)(%eax) + + /* the first argument on the stack is the jump target (%eip), so we store it in the EIP + register in the ucontext structure. */ + movl (%esp), %ecx + movl %ecx, REG_OFFSET(REG_EIP)(%eax) + + /* take the stack pointer address (%esp) offsetting by 4 to skip over the jump target. */ + leal 4(%esp), %ecx + movl %ecx, REG_OFFSET(REG_ESP)(%eax) + + /* finally, save the FS segment register */ + xorl %ecx, %ecx + movw %fs, %cx + movl %ecx, REG_OFFSET(REG_FS)(%eax) + + /* we're all done here, return 0 */ + xorl %eax, %eax + ret +END(libucontext_getcontext) diff --git a/src/3rdparty/libucontext/arch/x86/include/libucontext/bits.h b/src/3rdparty/libucontext/arch/x86/include/libucontext/bits.h new file mode 100644 index 000000000..c4b28aa29 --- /dev/null +++ b/src/3rdparty/libucontext/arch/x86/include/libucontext/bits.h @@ -0,0 +1,48 @@ +#ifndef LIBUCONTEXT_BITS_H +#define LIBUCONTEXT_BITS_H + +#define REG_GS (0) +#define REG_FS (1) +#define REG_ES (2) +#define REG_DS (3) +#define REG_EDI (4) +#define REG_ESI (5) +#define REG_EBP (6) +#define REG_ESP (7) +#define REG_EBX (8) +#define REG_EDX (9) +#define REG_ECX (10) +#define REG_EAX (11) +#define REG_EIP (14) + +typedef int libucontext_greg_t, libucontext_gregset_t[19]; + +typedef struct libucontext_fpstate { + unsigned long cw, sw, tag, ipoff, cssel, dataoff, datasel; + struct { + unsigned short significand[4], exponent; + } _st[8]; + unsigned long status; +} *libucontext_fpregset_t; + +typedef struct { + libucontext_gregset_t gregs; + libucontext_fpregset_t fpregs; + unsigned long oldmask, cr2; +} libucontext_mcontext_t; + +typedef struct { + void *ss_sp; + int ss_flags; + size_t ss_size; +} libucontext_stack_t; + +typedef struct libucontext_ucontext { + unsigned long uc_flags; + struct libucontext_ucontext *uc_link; + libucontext_stack_t uc_stack; + libucontext_mcontext_t uc_mcontext; +} libucontext_ucontext_t; + +#endif + diff --git a/src/3rdparty/libucontext/arch/x86/makecontext.c b/src/3rdparty/libucontext/arch/x86/makecontext.c new file mode 100644 index 000000000..2f8138918 --- /dev/null +++ b/src/3rdparty/libucontext/arch/x86/makecontext.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018 Ariadne Conill + * Copyright (c) 2019 A. Wilcox + * + * 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 +#include +#include +#include +#include "defs.h" +#include + + +extern void libucontext_trampoline(void); + + +void +libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(void), int argc, ...) +{ + libucontext_greg_t *sp, *argp; + va_list va; + int i; + unsigned int uc_link; + + uc_link = (argc > 6 ? argc - 6 : 0) + 1; + + sp = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); + sp -= uc_link; + sp = (libucontext_greg_t *) (((uintptr_t) sp & -16L) - 8); + + ucp->uc_mcontext.gregs[REG_EIP] = (uintptr_t) func; + ucp->uc_mcontext.gregs[REG_EBX] = (uintptr_t) argc; + ucp->uc_mcontext.gregs[REG_ESP] = (uintptr_t) sp; + + argp = sp; + *argp++ = (uintptr_t) &libucontext_trampoline; + + va_start(va, argc); + + for (i = 0; i < argc; i++) + *argp++ = va_arg (va, libucontext_greg_t); + + va_end(va); + + *argp++ = (uintptr_t) ucp->uc_link; +} + +#ifdef EXPORT_UNPREFIXED +extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +#endif diff --git a/src/3rdparty/libucontext/arch/x86/setcontext.S b/src/3rdparty/libucontext/arch/x86/setcontext.S new file mode 100644 index 000000000..75d2108eb --- /dev/null +++ b/src/3rdparty/libucontext/arch/x86/setcontext.S @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018, 2020 Ariadne Conill + * + * 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" + +ALIAS(setcontext, libucontext_setcontext) +ALIAS(__setcontext, libucontext_setcontext) + +FUNC(libucontext_setcontext) + /* load address of the ucontext structure */ + movl 4(%esp), %eax + + /* set up the FS segment register */ + movl REG_OFFSET(REG_FS)(%eax), %ecx + movw %cx, %fs + + /* fetch the new EIP */ + movl REG_OFFSET(REG_EIP)(%eax), %ecx + + /* set up the new stack pointer */ + movl REG_OFFSET(REG_ESP)(%eax), %esp + + /* push the return address onto the stack */ + pushl %ecx + + /* set all of the registers */ + movl REG_OFFSET(REG_EBX)(%eax), %ebx + movl REG_OFFSET(REG_ECX)(%eax), %ecx + movl REG_OFFSET(REG_EDX)(%eax), %edx + movl REG_OFFSET(REG_EBP)(%eax), %ebp + movl REG_OFFSET(REG_EDI)(%eax), %edi + movl REG_OFFSET(REG_ESI)(%eax), %esi + movl REG_OFFSET(REG_EAX)(%eax), %eax + + ret +END(libucontext_setcontext) diff --git a/src/3rdparty/libucontext/arch/x86/swapcontext.S b/src/3rdparty/libucontext/arch/x86/swapcontext.S new file mode 100644 index 000000000..3594fc0e5 --- /dev/null +++ b/src/3rdparty/libucontext/arch/x86/swapcontext.S @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 2020 Ariadne Conill + * + * 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" + +ALIAS(swapcontext, libucontext_swapcontext) +ALIAS(__swapcontext, libucontext_swapcontext) + +FUNC(libucontext_swapcontext) + /* load address of the ucontext structure */ + movl 4(%esp), %eax + + /* EAX is not a preserved register */ + movl $0, REG_OFFSET(REG_EAX)(%eax) + + /* copy all of the current registers into the ucontext structure */ + movl %ecx, REG_OFFSET(REG_ECX)(%eax) + movl %ebx, REG_OFFSET(REG_EBX)(%eax) + movl %edx, REG_OFFSET(REG_EDX)(%eax) + movl %edi, REG_OFFSET(REG_EDI)(%eax) + movl %esi, REG_OFFSET(REG_ESI)(%eax) + movl %ebp, REG_OFFSET(REG_EBP)(%eax) + + /* the first argument on the stack is the jump target (%eip), so we store it in the EIP + register in the ucontext structure. */ + movl (%esp), %ecx + movl %ecx, REG_OFFSET(REG_EIP)(%eax) + + /* take the stack pointer address (%esp) offsetting by 4 to skip over the jump target. */ + leal 4(%esp), %ecx + movl %ecx, REG_OFFSET(REG_ESP)(%eax) + + /* finally, save the FS segment register */ + xorl %ecx, %ecx + movw %fs, %cx + movl %ecx, REG_OFFSET(REG_FS)(%eax) + + /* load address of the ucontext structure */ + movl 8(%esp), %eax + + /* set up the FS segment register */ + movl REG_OFFSET(REG_FS)(%eax), %ecx + movw %cx, %fs + + /* fetch the new EIP */ + movl REG_OFFSET(REG_EIP)(%eax), %ecx + + /* set up the new stack pointer */ + movl REG_OFFSET(REG_ESP)(%eax), %esp + + /* push the return address onto the stack */ + pushl %ecx + + /* set all of the registers */ + movl REG_OFFSET(REG_EBX)(%eax), %ebx + movl REG_OFFSET(REG_ECX)(%eax), %ecx + movl REG_OFFSET(REG_EDX)(%eax), %edx + movl REG_OFFSET(REG_EBP)(%eax), %ebp + movl REG_OFFSET(REG_EDI)(%eax), %edi + movl REG_OFFSET(REG_ESI)(%eax), %esi + movl REG_OFFSET(REG_EAX)(%eax), %eax + + ret +END(libucontext_swapcontext) diff --git a/src/3rdparty/libucontext/arch/x86/trampoline.c b/src/3rdparty/libucontext/arch/x86/trampoline.c new file mode 100644 index 000000000..699a0505d --- /dev/null +++ b/src/3rdparty/libucontext/arch/x86/trampoline.c @@ -0,0 +1,3 @@ +#include "defs.h" +#include +#include "common-trampoline.c" diff --git a/src/3rdparty/libucontext/arch/x86_64/defs.h b/src/3rdparty/libucontext/arch/x86_64/defs.h new file mode 100644 index 000000000..1ebf3a93f --- /dev/null +++ b/src/3rdparty/libucontext/arch/x86_64/defs.h @@ -0,0 +1,105 @@ +#ifndef __ARCH_X86_64_DEFS_H +#define __ARCH_X86_64_DEFS_H + +#ifndef REG_R8 +# define REG_R8 (0) +#endif + +#ifndef REG_R9 +# define REG_R9 (1) +#endif + +#ifndef REG_R10 +# define REG_R10 (2) +#endif + +#ifndef REG_R11 +# define REG_R11 (3) +#endif + +#ifndef REG_R12 +# define REG_R12 (4) +#endif + +#ifndef REG_R13 +# define REG_R13 (5) +#endif + +#ifndef REG_R14 +# define REG_R14 (6) +#endif + +#ifndef REG_R15 +# define REG_R15 (7) +#endif + +#ifndef REG_RDI +# define REG_RDI (8) +#endif + +#ifndef REG_RSI +# define REG_RSI (9) +#endif + +#ifndef REG_RBP +# define REG_RBP (10) +#endif + +#ifndef REG_RBX +# define REG_RBX (11) +#endif + +#ifndef REG_RDX +# define REG_RDX (12) +#endif + +#ifndef REG_RAX +# define REG_RAX (13) +#endif + +#ifndef REG_RCX +# define REG_RCX (14) +#endif + +#ifndef REG_RSP +# define REG_RSP (15) +#endif + +#ifndef REG_RIP +# define REG_RIP (16) +#endif + +#ifndef REG_EFL +# define REG_EFL (17) +#endif + +#ifndef REG_CSGSFS +# define REG_CSGSFS (18) +#endif + +#ifndef REG_ERR +# define REG_ERR (19) +#endif + +#ifndef REG_TRAPNO +# define REG_TRAPNO (20) +#endif + +#ifndef REG_OLDMASK +# define REG_OLDMASK (21) +#endif + +#ifndef REG_CR2 +# define REG_CR2 (22) +#endif + +#define MCONTEXT_GREGS (40) + +#define REG_SZ (8) + +#define FETCH_LINKPTR(dest) \ + asm("movq (%%rbx), %0" : "=r" ((dest))); + +#include "common-defs.h" + +#endif diff --git a/src/3rdparty/libucontext/arch/x86_64/getcontext.S b/src/3rdparty/libucontext/arch/x86_64/getcontext.S new file mode 100644 index 000000000..168fa473d --- /dev/null +++ b/src/3rdparty/libucontext/arch/x86_64/getcontext.S @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018, 2020 Ariadne Conill + * + * 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" + +ALIAS(getcontext, libucontext_getcontext) +ALIAS(__getcontext, libucontext_getcontext) + +FUNC(libucontext_getcontext) + /* copy all of the current registers into the ucontext structure */ + movq %r8, REG_OFFSET(REG_R8)(%rdi) + movq %r9, REG_OFFSET(REG_R9)(%rdi) + movq %r10, REG_OFFSET(REG_R10)(%rdi) + movq %r11, REG_OFFSET(REG_R11)(%rdi) + movq %r12, REG_OFFSET(REG_R12)(%rdi) + movq %r13, REG_OFFSET(REG_R13)(%rdi) + movq %r14, REG_OFFSET(REG_R14)(%rdi) + movq %r15, REG_OFFSET(REG_R15)(%rdi) + movq %rdi, REG_OFFSET(REG_RDI)(%rdi) + movq %rsi, REG_OFFSET(REG_RSI)(%rdi) + movq %rbp, REG_OFFSET(REG_RBP)(%rdi) + movq %rbx, REG_OFFSET(REG_RBX)(%rdi) + movq %rdx, REG_OFFSET(REG_RDX)(%rdi) + movq %rax, REG_OFFSET(REG_RAX)(%rdi) + movq %rcx, REG_OFFSET(REG_RCX)(%rdi) + + /* the first argument on the stack is the jump target (%rip), so we store it in the RIP + register in the ucontext structure. */ + movq (%rsp), %rcx + movq %rcx, REG_OFFSET(REG_RIP)(%rdi) + + /* finally take the stack pointer address (%rsp) offsetting by 8 to skip over the jump + target. */ + leaq 8(%rsp), %rcx + movq %rcx, REG_OFFSET(REG_RSP)(%rdi) + + /* we're all done here, return 0 */ + xorl %eax, %eax + ret +END(libucontext_getcontext) diff --git a/src/3rdparty/libucontext/arch/x86_64/include/libucontext/bits.h b/src/3rdparty/libucontext/arch/x86_64/include/libucontext/bits.h new file mode 100644 index 000000000..79567663b --- /dev/null +++ b/src/3rdparty/libucontext/arch/x86_64/include/libucontext/bits.h @@ -0,0 +1,64 @@ +#include + +#ifndef LIBUCONTEXT_BITS_H +#define LIBUCONTEXT_BITS_H + +#define REG_R8 (0) +#define REG_R9 (1) +#define REG_R10 (2) +#define REG_R11 (3) +#define REG_R12 (4) +#define REG_R13 (5) +#define REG_R14 (6) +#define REG_R15 (7) +#define REG_RDI (8) +#define REG_RSI (9) +#define REG_RBP (10) +#define REG_RBX (11) +#define REG_RDX (12) +#define REG_RAX (13) +#define REG_RCX (14) +#define REG_RSP (15) +#define REG_RIP (16) +#define REG_EFL (17) +#define REG_CSGSFS (18) +#define REG_ERR (19) +#define REG_TRAPNO (20) +#define REG_OLDMASK (21) +#define REG_CR2 (22) + +typedef long long libucontext_greg_t, libucontext_gregset_t[23]; + +typedef struct libucontext_fpstate { + unsigned short cwd, swd, ftw, fop; + unsigned long long rip, rdp; + unsigned mxcsr, mxcr_mask; + struct { + unsigned short significand[4], exponent, padding[3]; + } _st[8]; + struct { + unsigned element[4]; + } _xmm[16]; + unsigned padding[24]; +} *libucontext_fpregset_t; + +typedef struct { + libucontext_gregset_t gregs; + libucontext_fpregset_t fpregs; + unsigned long long __reserved1[8]; +} libucontext_mcontext_t; + +typedef struct { + void *ss_sp; + int ss_flags; + size_t ss_size; +} libucontext_stack_t; + +typedef struct libucontext_ucontext { + unsigned long uc_flags; + struct libucontext_ucontext *uc_link; + libucontext_stack_t uc_stack; + libucontext_mcontext_t uc_mcontext; +} libucontext_ucontext_t; + +#endif diff --git a/src/3rdparty/libucontext/arch/x86_64/makecontext.c b/src/3rdparty/libucontext/arch/x86_64/makecontext.c new file mode 100644 index 000000000..cba9cb1b4 --- /dev/null +++ b/src/3rdparty/libucontext/arch/x86_64/makecontext.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018 Ariadne Conill + * + * 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 +#include +#include +#include + +#include "defs.h" +#include + +extern void libucontext_trampoline(void); + +_Static_assert(offsetof(libucontext_ucontext_t, uc_mcontext.gregs) == MCONTEXT_GREGS, "MCONTEXT_GREGS is invalid"); + +void +libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(void), int argc, ...) +{ + libucontext_greg_t *sp; + va_list va; + int i; + unsigned int uc_link; + + uc_link = (argc > 6 ? argc - 6 : 0) + 1; + + sp = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); + sp -= uc_link; + sp = (libucontext_greg_t *) (((uintptr_t) sp & -16L) - 8); + + ucp->uc_mcontext.gregs[REG_RIP] = (uintptr_t) func; + ucp->uc_mcontext.gregs[REG_RBX] = (uintptr_t) &sp[uc_link]; + ucp->uc_mcontext.gregs[REG_RSP] = (uintptr_t) sp; + + sp[0] = (uintptr_t) &libucontext_trampoline; + sp[uc_link] = (uintptr_t) ucp->uc_link; + + va_start(va, argc); + + for (i = 0; i < argc; i++) + switch (i) + { + case 0: + ucp->uc_mcontext.gregs[REG_RDI] = va_arg (va, libucontext_greg_t); + break; + case 1: + ucp->uc_mcontext.gregs[REG_RSI] = va_arg (va, libucontext_greg_t); + break; + case 2: + ucp->uc_mcontext.gregs[REG_RDX] = va_arg (va, libucontext_greg_t); + break; + case 3: + ucp->uc_mcontext.gregs[REG_RCX] = va_arg (va, libucontext_greg_t); + break; + case 4: + ucp->uc_mcontext.gregs[REG_R8] = va_arg (va, libucontext_greg_t); + break; + case 5: + ucp->uc_mcontext.gregs[REG_R9] = va_arg (va, libucontext_greg_t); + break; + default: + sp[i - 5] = va_arg (va, libucontext_greg_t); + break; + } + + va_end(va); +} + +#ifdef EXPORT_UNPREFIXED +extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext"))); +#endif diff --git a/src/3rdparty/libucontext/arch/x86_64/setcontext.S b/src/3rdparty/libucontext/arch/x86_64/setcontext.S new file mode 100644 index 000000000..4dc270242 --- /dev/null +++ b/src/3rdparty/libucontext/arch/x86_64/setcontext.S @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018, 2020 Ariadne Conill + * + * 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" + +ALIAS(setcontext, libucontext_setcontext) +ALIAS(__setcontext, libucontext_setcontext) + +FUNC(libucontext_setcontext) + /* set all of the registers */ + movq REG_OFFSET(REG_R8)(%rdi), %r8 + movq REG_OFFSET(REG_R9)(%rdi), %r9 + movq REG_OFFSET(REG_R10)(%rdi), %r10 + movq REG_OFFSET(REG_R11)(%rdi), %r11 + movq REG_OFFSET(REG_R12)(%rdi), %r12 + movq REG_OFFSET(REG_R13)(%rdi), %r13 + movq REG_OFFSET(REG_R14)(%rdi), %r14 + movq REG_OFFSET(REG_R15)(%rdi), %r15 + movq REG_OFFSET(REG_RSI)(%rdi), %rsi + movq REG_OFFSET(REG_RBP)(%rdi), %rbp + movq REG_OFFSET(REG_RBX)(%rdi), %rbx + movq REG_OFFSET(REG_RDX)(%rdi), %rdx + movq REG_OFFSET(REG_RAX)(%rdi), %rax + movq REG_OFFSET(REG_RCX)(%rdi), %rcx + movq REG_OFFSET(REG_RSP)(%rdi), %rsp + + /* set the jump target by pushing it to the stack. + ret will pop the new %rip from the stack, causing us to jump there. */ + pushq REG_OFFSET(REG_RIP)(%rdi) + + /* finally, set %rdi correctly. */ + movq REG_OFFSET(REG_RDI)(%rdi), %rdi + + /* we're all done here, return 0 */ + xorl %eax, %eax + ret +END(libucontext_setcontext) diff --git a/src/3rdparty/libucontext/arch/x86_64/swapcontext.S b/src/3rdparty/libucontext/arch/x86_64/swapcontext.S new file mode 100644 index 000000000..43dafb594 --- /dev/null +++ b/src/3rdparty/libucontext/arch/x86_64/swapcontext.S @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 2020 Ariadne Conill + * + * 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" + +ALIAS(swapcontext, libucontext_swapcontext) +ALIAS(__swapcontext, libucontext_swapcontext) + +FUNC(libucontext_swapcontext) + /* copy all of the current registers into the ucontext structure pointed by + the first argument */ + movq %r8, REG_OFFSET(REG_R8)(%rdi) + movq %r9, REG_OFFSET(REG_R9)(%rdi) + movq %r10, REG_OFFSET(REG_R10)(%rdi) + movq %r11, REG_OFFSET(REG_R11)(%rdi) + movq %r12, REG_OFFSET(REG_R12)(%rdi) + movq %r13, REG_OFFSET(REG_R13)(%rdi) + movq %r14, REG_OFFSET(REG_R14)(%rdi) + movq %r15, REG_OFFSET(REG_R15)(%rdi) + movq %rdi, REG_OFFSET(REG_RDI)(%rdi) + movq %rsi, REG_OFFSET(REG_RSI)(%rdi) + movq %rbp, REG_OFFSET(REG_RBP)(%rdi) + movq %rbx, REG_OFFSET(REG_RBX)(%rdi) + movq %rdx, REG_OFFSET(REG_RDX)(%rdi) + movq %rax, REG_OFFSET(REG_RAX)(%rdi) + movq %rcx, REG_OFFSET(REG_RCX)(%rdi) + + /* the first argument on the stack is the jump target (%rip), so we store it in the RIP + register in the ucontext structure. */ + movq (%rsp), %rcx + movq %rcx, REG_OFFSET(REG_RIP)(%rdi) + + /* finally take the stack pointer address (%rsp) offsetting by 8 to skip over the jump + target. */ + leaq 8(%rsp), %rcx + movq %rcx, REG_OFFSET(REG_RSP)(%rdi) + + /* set all of the registers to their new states, stored in the second + ucontext structure */ + movq REG_OFFSET(REG_R8)(%rsi), %r8 + movq REG_OFFSET(REG_R9)(%rsi), %r9 + movq REG_OFFSET(REG_R10)(%rsi), %r10 + movq REG_OFFSET(REG_R11)(%rsi), %r11 + movq REG_OFFSET(REG_R12)(%rsi), %r12 + movq REG_OFFSET(REG_R13)(%rsi), %r13 + movq REG_OFFSET(REG_R14)(%rsi), %r14 + movq REG_OFFSET(REG_R15)(%rsi), %r15 + movq REG_OFFSET(REG_RDI)(%rsi), %rdi + movq REG_OFFSET(REG_RBP)(%rsi), %rbp + movq REG_OFFSET(REG_RBX)(%rsi), %rbx + movq REG_OFFSET(REG_RDX)(%rsi), %rdx + movq REG_OFFSET(REG_RAX)(%rsi), %rax + movq REG_OFFSET(REG_RCX)(%rsi), %rcx + movq REG_OFFSET(REG_RSP)(%rsi), %rsp + + /* set the jump target by pushing it to the stack. + ret will pop the new %rip from the stack, causing us to jump there. */ + pushq REG_OFFSET(REG_RIP)(%rsi) + + /* finally, set %rsi correctly since we do not need it anymore. */ + movq REG_OFFSET(REG_RSI)(%rsi), %rsi + + /* we're all done here, return 0 */ + xorl %eax, %eax + ret +END(libucontext_swapcontext) diff --git a/src/3rdparty/libucontext/arch/x86_64/trampoline.c b/src/3rdparty/libucontext/arch/x86_64/trampoline.c new file mode 100644 index 000000000..699a0505d --- /dev/null +++ b/src/3rdparty/libucontext/arch/x86_64/trampoline.c @@ -0,0 +1,3 @@ +#include "defs.h" +#include +#include "common-trampoline.c" diff --git a/src/3rdparty/libucontext/doc/libucontext.scd b/src/3rdparty/libucontext/doc/libucontext.scd new file mode 100644 index 000000000..1f6c07acb --- /dev/null +++ b/src/3rdparty/libucontext/doc/libucontext.scd @@ -0,0 +1,174 @@ +libucontext(3) + +# NAME + +libucontext - a library for userspace context swapping + +# SYNOPSIS + +*#include * + +``` +typedef struct { + /* depends on target architecture */ +} libucontext_mcontext_t; + +typedef struct { + void *ss_sp; + int ss_flags; + size_t ss_size; +} libucontext_stack_t; + +typedef struct libucontext_ucontext { + unsigned int uc_flags; + struct libucontext_ucontext *uc_link; + libucontext_stack_t uc_stack; + libucontext_mcontext_t uc_mcontext; +} libucontext_ucontext_t; +``` + +*int libucontext_getcontext(libucontext_ucontext_t* \*_ucp_*);* + +*int libucontext_setcontext(const libucontext_ucontext_t* \*_ucp_*);* + +*void libucontext_makecontext(libucontext_ucontext_t* \*_ucp_*, void* _(\*func)()_*, int* _argc_*,* _..._*);* + +*int libucontext_swapcontext(libucontext_ucontext_t* \*_oucp_*, const libucontext_ucontext_t* \*_ucp_*);* + +# DESCRIPTION + +The *libucontext* library provides an implementation of the SysV ucontext functions. These +are traditionally used to implement user-space context swapping. This is achieved by using +the *libucontext_getcontext*, *libucontext_setcontext*, *libucontext_makecontext* and +*libucontext_swapcontext* functions as appropriate. + +The *libucontext_getcontext* function initializes a structure pointed to by _ucp_ with the +current user context. + +The *libucontext_setcontext* function sets the current user context to the structure pointed +to by _ucp_. It discards the current user context. + +The *libucontext_swapcontext* function saves the current user context in a structure pointed +to by _oucp_ and then sets the current user context to the new context in a structure pointed +to by _ucp_. + +The *libucontext_makecontext* function modifies a user context in a structure pointed to by +_ucp_ to run a function pointed to by _func_ and sets up an argument list of _argc_ values. + +# CAVEATS + +In SysV, the ucontext functions save and restore signal masks. The *libucontext* library, +however, does not. In practice, this does not usually matter, as users of these functions +rarely change the signal mask between contexts. + +Other implementations may or may not save and restore additional processor registers that +this implementation does not. The *libucontext* library only saves and restores the general +purpose registers. In practice, this has proven sufficient. + +# EXAMPLE + +A practical example showing cooperative multithreading. This program is intended for +illustrative purpose only and has been written in a way favoring simplicity over performance +and robustness: + +``` +#include +#include +#include +#include +#include +#include +#include + +libucontext_ucontext_t mainctx = {}; +libucontext_ucontext_t *curthr = &mainctx; +libucontext_ucontext_t *threads = NULL; +size_t thrcount = 0; + +void +yieldto(libucontext_ucontext_t *target) +{ + libucontext_ucontext_t *oldthr = curthr; + curthr = target; + + libucontext_swapcontext(oldthr, curthr); +} + +void +yield(void) +{ + libucontext_ucontext_t *newthr; + + /* we set uc_flags to non-zero to signal thread completion. */ + do + newthr = &threads[random() % thrcount]; + while (newthr == curthr || newthr->uc_flags); + + srandom(time(NULL)); + + yieldto(newthr); +} + +void +worker(size_t multiple) +{ + size_t accum = 1; + + for (size_t i = 0; i < 10; i++) + { + accum += (multiple * i); + + printf("[%p] accumulated %zu\n", curthr, accum); + yield(); + } + + /* mark thread as completed, so we don't return here */ + curthr->uc_flags = 1; +} + +void +create(size_t multiple) +{ + libucontext_ucontext_t *cursor; + + thrcount += 1; + threads = realloc(threads, sizeof(*threads) * thrcount); + + cursor = &threads[thrcount - 1]; + memset(cursor, '\0', sizeof *cursor); + + /* initialize the new thread's values to our current context */ + libucontext_getcontext(cursor); + + /* set up uc_link */ + cursor->uc_link = thrcount > 1 ? &threads[thrcount - 2] : &mainctx; + + /* set up a stack */ + cursor->uc_stack.ss_size = 8192; + cursor->uc_stack.ss_sp = calloc(1, cursor->uc_stack.ss_size); + + /* set up the function call */ + libucontext_makecontext(cursor, worker, 1, multiple); +} + +int +main(int argc, const char *argv[]) +{ + srandom(time(NULL)); + + libucontext_getcontext(&mainctx); + + for (size_t i = 1; i < 4; i++) + create(i); + + /* start the threads off by yielding to the last one */ + yieldto(&threads[thrcount - 1]); + + return EXIT_SUCCESS; +} +``` + +# AUTHORS + +Ariadne Conill + diff --git a/src/3rdparty/libucontext/doc/meson.build b/src/3rdparty/libucontext/doc/meson.build new file mode 100644 index 000000000..8f5ac7964 --- /dev/null +++ b/src/3rdparty/libucontext/doc/meson.build @@ -0,0 +1,21 @@ +scdoc = find_program('scdoc', required: true) + +custom_target( + 'libucontext.3', + output: 'libucontext.3', + input: 'libucontext.scd', + command: [ scdoc ], + feed: true, + capture: true, + install: true, + install_dir: get_option('mandir') / 'man3' +) + +if meson.version().version_compare('>=0.61.0') + foreach link : [ 'get', 'make', 'set', 'swap' ] + install_symlink('libucontext_' + link + 'context.3', + pointing_to: 'libucontext.3', + install_dir: get_option('mandir') / 'man3' + ) + endforeach +endif diff --git a/src/3rdparty/libucontext/examples/cooperative_threading.c b/src/3rdparty/libucontext/examples/cooperative_threading.c new file mode 100644 index 000000000..123e9eaa6 --- /dev/null +++ b/src/3rdparty/libucontext/examples/cooperative_threading.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include +#include + +libucontext_ucontext_t mainctx = {}; +libucontext_ucontext_t *curthr = &mainctx; +libucontext_ucontext_t *threads = NULL; +size_t thrcount = 0; + +void +yieldto(libucontext_ucontext_t *target) +{ + libucontext_ucontext_t *oldthr = curthr; + curthr = target; + + libucontext_swapcontext(oldthr, curthr); +} + +void +yield(void) +{ + libucontext_ucontext_t *newthr; + + /* we set uc_flags to non-zero to signal thread completion. */ + do + newthr = &threads[random() % thrcount]; + while (newthr == curthr || newthr->uc_flags); + + srandom(time(NULL)); + + yieldto(newthr); +} + +void +worker(size_t multiple) +{ + size_t accum = 1; + + for (size_t i = 0; i < 10; i++) + { + accum += (multiple * i); + + printf("[%p] accumulated %zu\n", curthr, accum); + yield(); + } + + /* mark thread as completed, so we don't return here */ + curthr->uc_flags = 1; +} + +void +create(size_t multiple) +{ + libucontext_ucontext_t *cursor; + + thrcount += 1; + threads = realloc(threads, sizeof(*threads) * thrcount); + + cursor = &threads[thrcount - 1]; + memset(cursor, '\0', sizeof *cursor); + + /* initialize the new thread's values to our current context */ + libucontext_getcontext(cursor); + + /* set up uc_link */ + cursor->uc_link = thrcount > 1 ? &threads[thrcount - 2] : &mainctx; + + /* set up a stack */ + cursor->uc_stack.ss_size = 8192; + cursor->uc_stack.ss_sp = calloc(1, cursor->uc_stack.ss_size); + + /* set up the function call */ + libucontext_makecontext(cursor, worker, 1, multiple); +} + +int +main(int argc, const char *argv[]) +{ + srandom(time(NULL)); + + libucontext_getcontext(&mainctx); + + for (size_t i = 1; i < 4; i++) + create(i); + + /* start the threads off by yielding to the last one */ + yieldto(&threads[thrcount - 1]); + + return EXIT_SUCCESS; +} diff --git a/src/3rdparty/libucontext/include/libucontext/libucontext.h b/src/3rdparty/libucontext/include/libucontext/libucontext.h new file mode 100644 index 000000000..aac33f6ac --- /dev/null +++ b/src/3rdparty/libucontext/include/libucontext/libucontext.h @@ -0,0 +1,20 @@ +#ifndef LIBUCONTEXT_LIBUCONTEXT_H +#define LIBUCONTEXT_LIBUCONTEXT_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int libucontext_getcontext(libucontext_ucontext_t *); +void libucontext_makecontext(libucontext_ucontext_t *, void (*)(), int, ...); +int libucontext_setcontext(const libucontext_ucontext_t *); +int libucontext_swapcontext(libucontext_ucontext_t *, const libucontext_ucontext_t *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/3rdparty/libucontext/libucontext.pc.in b/src/3rdparty/libucontext/libucontext.pc.in new file mode 100644 index 000000000..10962d859 --- /dev/null +++ b/src/3rdparty/libucontext/libucontext.pc.in @@ -0,0 +1,9 @@ +libdir=@LIBUCONTEXT_SHARED_LIBDIR@ +static_libdir=@LIBUCONTEXT_STATIC_LIBDIR@ +includedir=@LIBUCONTEXT_INCLUDEDIR@ + +Name: libucontext +Version: @LIBUCONTEXT_VERSION@ +Description: ucontext library implementation (standalone) +Libs: -L${libdir} -L${static_libdir} -lucontext +Cflags: -I${includedir} diff --git a/src/3rdparty/libucontext/libucontext_posix.c b/src/3rdparty/libucontext/libucontext_posix.c new file mode 100644 index 000000000..859b40767 --- /dev/null +++ b/src/3rdparty/libucontext/libucontext_posix.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020 Ariadne Conill + * + * 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 +#include +#include +#include + +#ifdef FREESTANDING +# error libucontext_posix cannot be built in FREESTANDING mode. +#endif + +#ifdef DEBUG +# define TRACE(...) fprintf(stderr, "TRACE: " __VA_ARGS__) +#else +# define TRACE(...) +#endif + +int +getcontext(libucontext_ucontext_t *ucp) +{ + TRACE("getcontext(%p)\n", ucp); + + if (sigprocmask(SIG_SETMASK, NULL, &ucp->uc_sigmask)) + return -1; + + return libucontext_getcontext(ucp); +} + +int +setcontext(const libucontext_ucontext_t *ucp) +{ + TRACE("setcontext(%p)\n", ucp); + + if (sigprocmask(SIG_SETMASK, &ucp->uc_sigmask, NULL)) + return -1; + + return libucontext_setcontext(ucp); +} + +int +swapcontext(libucontext_ucontext_t *oucp, const libucontext_ucontext_t *ucp) +{ + TRACE("swapcontext(%p, %p)\n", oucp, ucp); + + if (sigprocmask(SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask)) + return -1; + + return libucontext_swapcontext(oucp, ucp); +} diff --git a/src/3rdparty/libucontext/meson.build b/src/3rdparty/libucontext/meson.build new file mode 100644 index 000000000..7dc9f8be2 --- /dev/null +++ b/src/3rdparty/libucontext/meson.build @@ -0,0 +1,172 @@ +project( + 'libucontext', + 'c', + meson_version : '>=0.59.0', + default_options: ['c_std=gnu11', 'default_library=both'], + version : run_command('head', files('VERSION')).stdout() +) + +cpu = get_option('cpu') +if cpu == '' + cpu = host_machine.cpu_family() +endif + +if cpu == 'sh4' + cpu = 'sh' +endif + +project_description = 'Portable implementation of ucontext' + +project_headers = [ + 'include/libucontext/libucontext.h' +] + +project_source_files = [ + 'arch' / cpu / 'getcontext.S', + 'arch' / cpu / 'setcontext.S', + 'arch' / cpu / 'swapcontext.S', +] +if cpu in ['mips', 'mips64'] + project_source_files += [ + 'arch' / cpu / 'makecontext.S' + ] +else + project_source_files += [ + 'arch' / cpu / 'makecontext.c' + ] +endif +if cpu in ['ppc', 'ppc64'] + project_source_files += [ + 'arch' / cpu / 'retfromsyscall.c' + ] +endif +if cpu not in ['mips', 'mips64', 'ppc', 'ppc64', 's390x'] + project_source_files += [ + 'arch' / cpu / 'trampoline.c' + ] +else + project_source_files += [ + 'arch' / cpu / 'startcontext.S' + ] +endif + +project_includes = [ + 'include', + 'arch/common' +] + +build_args = [ + '-D_BSD_SOURCE' +] + + +# =================================================================== + +# ====== +# Options +# ====== + +freestanding = get_option('freestanding') +export_unprefixed = get_option('export_unprefixed') +build_posix = true + +if freestanding + build_args += '-DFREESTANDING' + build_posix = false + export_unprefixed = false + project_headers += ['arch' / cpu / 'include/libucontext/bits.h'] + project_includes += ['arch' / cpu / 'include'] +else + project_headers += ['arch/common/include/libucontext/bits.h'] + project_includes += ['arch/common/include'] +endif + +if export_unprefixed + build_args += '-DEXPORT_UNPREFIXED' +endif + +# ====== +# Target +# ====== + +headers = include_directories(project_includes) + +libucontext_target = library( + 'ucontext', + project_source_files, + version: '1', + install : not meson.is_subproject(), + c_args : build_args, + pic: true, + include_directories : headers, +) +libucontext_dep = declare_dependency( + include_directories: headers, + link_with : libucontext_target +) + +if build_posix + libucontext_posix_target = library( + 'ucontext_posix', + project_source_files + ['libucontext_posix.c'], + version: '1', + install : not meson.is_subproject(), + c_args : build_args, + pic: true, + include_directories : headers, + ) + libucontext_posix_dep = declare_dependency( + include_directories: headers, + link_with : libucontext_posix_target + ) +endif + +# ======= +# Project +# ======= + +if not meson.is_subproject() + # Make this library usable from the system's + # package manager. + install_headers(project_headers, subdir : meson.project_name()) + + pkg_mod = import('pkgconfig') + pkg_mod.generate( + name : meson.project_name(), + filebase : meson.project_name(), + description : project_description, + subdirs : meson.project_name(), + libraries : libucontext_target, + ) +endif + +# ==== +# Docs +# ==== + +if not meson.is_subproject() and get_option('docs') + subdir('doc') +endif + +# ========== +# Unit Tests +# ========== + +test('test_libucontext', + executable( + 'test_libucontext', + files('test_libucontext.c'), + dependencies : libucontext_dep, + install : false + ) +) +if build_posix + test('test_libucontext_posix', + executable( + 'test_libucontext_posix', + files('test_libucontext_posix.c'), + dependencies : [libucontext_dep, libucontext_posix_dep], + install : false + ) + ) +endif diff --git a/src/3rdparty/libucontext/meson_options.txt b/src/3rdparty/libucontext/meson_options.txt new file mode 100644 index 000000000..e37217df4 --- /dev/null +++ b/src/3rdparty/libucontext/meson_options.txt @@ -0,0 +1,8 @@ +option('freestanding', type : 'boolean', value : false, + description: 'Do not use system headers') +option('export_unprefixed', type : 'boolean', value : true, + description: 'Export POSIX 2004 ucontext names as alises') +option('cpu', type : 'string', value : '', + description: 'Target CPU architecture for cross compile') +option('docs', type : 'boolean', value : false, + description: 'Build and install man pages') diff --git a/src/3rdparty/libucontext/test_libucontext.c b/src/3rdparty/libucontext/test_libucontext.c new file mode 100644 index 000000000..72b000e6f --- /dev/null +++ b/src/3rdparty/libucontext/test_libucontext.c @@ -0,0 +1,102 @@ +/* + * libucontext test program based on POSIX example program. + * Public domain. + */ + +#include +#include +#include +#include +#include + +static libucontext_ucontext_t ctx[3]; + + +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) { + printf("start f1\n"); + + printf("checking provided arguments to function f1\n"); + 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("looks like all arguments are passed correctly\n"); + + printf("swap back to f2\n"); + libucontext_swapcontext(&ctx[1], &ctx[2]); + printf("finish f1\n"); +} + + +static void f2 (void) { + printf("start f2\n"); + printf("swap to f1\n"); + libucontext_swapcontext(&ctx[2], &ctx[1]); + printf("finish f2, should swap to f1\n"); +} + + +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 */ + memset(st1, 'A', sizeof st1); + memset(st2, 'B', sizeof st2); + + + printf("setting up context 1\n"); + + + libucontext_getcontext(&ctx[1]); + ctx[1].uc_stack.ss_sp = st1; + ctx[1].uc_stack.ss_size = sizeof st1; + ctx[1].uc_link = &ctx[0]; + libucontext_makecontext(&ctx[1], f1, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + + + printf("setting up context 2\n"); + + + libucontext_getcontext(&ctx[2]); + ctx[2].uc_stack.ss_sp = st2; + ctx[2].uc_stack.ss_size = sizeof st2; + ctx[2].uc_link = &ctx[1]; + libucontext_makecontext(&ctx[2], f2, 0); + + + printf("doing initial swapcontext\n"); + + + libucontext_swapcontext(&ctx[0], &ctx[2]); + + + printf("returned from initial swapcontext\n"); + + + /* test ability to use getcontext/setcontext without makecontext */ + libucontext_getcontext(&ctx[1]); + printf("done = %d\n", done); + if (done++ == 0) libucontext_setcontext(&ctx[1]); + if (done != 2) { + fprintf(stderr, "wrong value for done. got %d, expected 2\n", done); + abort(); + } + + return 0; +} diff --git a/src/3rdparty/libucontext/test_libucontext_posix.c b/src/3rdparty/libucontext/test_libucontext_posix.c new file mode 100644 index 000000000..9b8c01d52 --- /dev/null +++ b/src/3rdparty/libucontext/test_libucontext_posix.c @@ -0,0 +1,102 @@ +/* + * libucontext test program based on POSIX example program. + * Public domain. + */ + +#include +#include +#include +#include +#include + +static ucontext_t ctx[3]; + + +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) { + printf("start f1\n"); + + printf("checking provided arguments to function f1\n"); + 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("looks like all arguments are passed correctly\n"); + + printf("swap back to f2\n"); + swapcontext(&ctx[1], &ctx[2]); + printf("finish f1\n"); +} + + +static void f2 (void) { + printf("start f2\n"); + printf("swap to f1\n"); + swapcontext(&ctx[2], &ctx[1]); + printf("finish f2, should swap to f1\n"); +} + + +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 */ + memset(st1, 'A', sizeof st1); + memset(st2, 'B', sizeof st2); + + + printf("setting up context 1\n"); + + + getcontext(&ctx[1]); + 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, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + + + printf("setting up context 2\n"); + + + getcontext(&ctx[2]); + ctx[2].uc_stack.ss_sp = st2; + ctx[2].uc_stack.ss_size = sizeof st2; + ctx[2].uc_link = &ctx[1]; + makecontext(&ctx[2], f2, 0); + + + printf("doing initial swapcontext\n"); + + + swapcontext(&ctx[0], &ctx[2]); + + + printf("returned from initial swapcontext\n"); + + + /* 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; +} diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index e9fccf9e0..07ebcf432 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -147,13 +147,13 @@ if (LWAN_HAVE_LIBUCONTEXT) include(ExternalProject) ExternalProject_Add(libucontext - GIT_REPOSITORY https://github.com/kaniini/libucontext + SOURCE_DIR ${CMAKE_SOURCE_DIR}/src/3rdparty/libucontext BUILD_IN_SOURCE ON CONFIGURE_COMMAND "" - BUILD_COMMAND make - INSTALL_COMMAND make install DESTDIR=${CMAKE_BINARY_DIR} + BUILD_COMMAND make libucontext.a FREESTANDING=yes + INSTALL_COMMAND make install-static install-headers DESTDIR=${CMAKE_BINARY_DIR} FREESTANDING=yes BUILD_BYPRODUCTS ${CMAKE_BINARY_DIR}/lib/libucontext.a @@ -162,7 +162,7 @@ if (LWAN_HAVE_LIBUCONTEXT) ) add_dependencies(lwan-static libucontext) - set(ADDITIONAL_LIBRARIES ${CMAKE_BINARY_DIR}/lib/libucontext.a ${ADDITIONAL_LIBRARIES} PARENT_SCOPE) + set(ADDITIONAL_LIBRARIES ${CMAKE_BINARY_DIR}/usr/lib/libucontext.a ${ADDITIONAL_LIBRARIES} PARENT_SCOPE) include_directories(${CMAKE_BINARY_DIR}/usr/include) else () message(STATUS "Using built-in context switching routines for ${CMAKE_SYSTEM_PROCESSOR} processors")