Compare commits

...

238 Commits

Author SHA1 Message Date
matoro be80075e95 meson: support building docs
ci/woodpecker/push/woodpecker Pipeline was successful Details
Toggleable with -Ddocs=(true|false), defaults to false.

Requires bumping minimum meson version to 0.59.0, or 0.61.0 to also
include symlinks.
2023-05-18 18:12:55 -07:00
Ariadne Conill 4c2cfc54ac libucontext.h: add C++ externs 2023-05-18 18:11:50 -07:00
L. Pereira 0f625a86ee Fix FREESTANDING install target
When installing a FREESTANDING build, the check for an empty variable
was not being honored because the empty string would evaluate to
nothing.  Put the variable expansion in quotes so that we have an empty
string instead.
2023-05-18 18:10:01 -07:00
Ismael Luceno 8e1397f5a2 Makefile: Make variables Automake-compatible
Also split libdir into shared and static variants to enable installing to
different locations.

Signed-off-by: Ismael Luceno <ismael@iodev.co.uk>
2023-05-18 18:08:07 -07:00
Ariadne Conill 33ff253d52 Merge pull request 'Fixed empty TYPE(__proc) causing linker issues on 32-bit arm' (#36) from rlcamp/libucontext:arm_linker_fix into master
Reviewed-on: #36
2022-03-24 08:57:53 +00:00
Richard Campbell 3044c2b908 Fixed empty TYPE(__proc) causing linker issues on 32-bit arm 2022-03-23 15:18:39 -07:00
Ariadne Conill 128e4fdc4b Merge pull request 'arm_hard_float' (#35) from rlcamp/libucontext:arm_hard_float into master
Reviewed-on: #35
2022-03-23 20:15:32 +00:00
Richard Campbell 5244775fb9 Added note to readme about floating point WIP 2022-03-04 10:41:54 -08:00
Richard Campbell 9abcd8afe0 Added passthrough of FORCE_SOFT_FLOAT and FORCE_HARD_FLOAT Makefile options 2022-03-04 10:40:30 -08:00
Richard Campbell 7bc3e90984 Added arm conditional vfp save/restore 2022-03-04 10:35:25 -08:00
Ariadne Conill 4dde3417b4 libucontext 1.2
continuous-integration/woodpecker the build was successful Details
2022-02-13 09:17:12 +00:00
Ariadne Conill 6ec3e63877 NEWS: mention or1k port
continuous-integration/woodpecker the build was successful Details
2022-02-13 09:08:46 +00:00
Ariadne Conill 69ebc5e51b README: add or1k
continuous-integration/woodpecker the build was successful Details
2022-02-13 09:07:36 +00:00
Ariadne Conill 0a72eff002 or1k: add freestanding bits 2022-02-13 09:06:58 +00:00
Ariadne Conill 973e61441a or1k: add getcontext/setcontext/swapcontext 2022-02-13 08:58:38 +00:00
Ariadne Conill 00128f7575 or1k: add makecontext and trampoline 2022-02-13 08:58:03 +00:00
Ariadne Conill 7fc08a6dc6 or1k: add definitions 2022-02-13 08:57:36 +00:00
Ariadne Conill e26a93806e build: allow check_libucontext program to be run on its own like the other check steps
continuous-integration/woodpecker the build was successful Details
2022-02-13 08:54:34 +00:00
Ariadne Conill 5d2f30f96a build: check_libucontext_posix must depend on ${LIBUCONTEXT_SONAME} 2022-02-13 08:53:45 +00:00
Ariadne Conill a51dce6e2c common-trampoline: initialize link pointer to NULL
continuous-integration/woodpecker the build was successful Details
2022-02-13 07:35:23 +00:00
Ariadne Conill a5ed584aa8 build: ensure libucontext_posix.so.1 is cleaned up
continuous-integration/woodpecker the build was successful Details
2022-02-13 07:18:19 +00:00
Ariadne Conill 9943d4f5fc NEWS: prepare for 1.2
continuous-integration/woodpecker the build was successful Details
2022-02-13 06:38:00 +00:00
Ariadne Conill 9403b481bc build: use CPPFLAGS instead of CFLAGS for FREESTANDING/EXPORT_UNPREFIXED 2022-02-13 06:25:47 +00:00
Ariadne Conill 2c0c0e5d29 build: only set default CFLAGS if there are none already set 2022-02-13 06:25:11 +00:00
Ariadne Conill c8fe721e69 build: fix linking of libucontext_posix against libucontext 2022-02-13 06:19:47 +00:00
Ariadne Conill c50182d98c build: disable executable stacks 2022-02-13 06:11:37 +00:00
Ariadne Conill 55c91428ba build: use -shared correctly instead of as linker flag
continuous-integration/woodpecker the build was successful Details
2021-12-18 16:54:17 +00:00
Ariadne Conill 18aa732212 CI: also build armv7
continuous-integration/woodpecker the build was successful Details
2021-12-01 09:36:20 -06:00
Ariadne Conill 8215aedb56 add woodpecker pipeline 2021-12-01 09:33:12 -06:00
Ariadne Conill 8efa9e8b85
Merge pull request #34 from Torrekie/master
Allow building on Darwin/arm64
2021-11-14 21:27:26 -06:00
Torrekie Gen 6ddefbbbb4
Allow building on Darwin/arm64
Changes:
1. `-soname` should be `-install_name` on Darwin
2. Version suffix should placed before extension suffix (libucontext.so.1 -> libucontext.1.dylib)
3. Check for architecture specific include directory, and include it while building
4. `EXPORT_UNPREFIXED` macro shouldn't be set since Darwin don't support aliases
5. Choose correct subdir for arm64
6. Use `-dynamiclib` instead of `-shared` on Darwin for adding version info (`-current_version` and `-compatibility_version`)
2021-11-13 19:10:25 +08:00
Ariadne Conill b1b4fe9665
Merge pull request #32 from rlcamp/master
Adjusted location within ucontext of saved/restored FP regs for compat
2021-07-31 13:38:54 -05:00
Richard Campbell 1e37bf30f9 Adjusted location within ucontext of saved/restored FP regs for compatibility 2021-07-30 12:45:12 -07:00
Ariadne Conill 14d9859c00
Merge pull request #31 from rlcamp/master
Added saving/restoring of bottom 64 bits of d8-d15 per AAPCS64
2021-07-29 20:49:13 -05:00
Richard Campbell 06303df1cd Added saving/restoring of bottom 64 bits of d8-d15 per AAPCS64 2021-07-29 18:45:48 -07:00
Ariadne Conill ae058b1f38 add loongarch64 to the supported arch list 2021-06-04 09:07:38 -06:00
Peng Fan a182fee66a Add support for Loongarch64
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
2021-06-04 09:07:38 -06:00
Ariadne Conill 0108623531
Merge pull request #28 from kraj/master
meson: Add option to pass cpu
2021-05-30 11:00:18 -05:00
Khem Raj a530eed9e7 meson: Add option to pass cpu
This helps with cross compile setups, where host_cpu != target_cpu
therefore detecting it on the fly will end up with wrong cpu to build
for

Signed-off-by: Khem Raj <raj.khem@gmail.com>
2021-05-30 08:38:54 -07:00
Ariadne Conill 335ee864ef libucontext 1.1. 2021-03-09 00:46:31 -07:00
Ariadne Conill 4d8abf9b3b update README a bit 2021-03-09 00:42:26 -07:00
Ariadne Conill 7b8f3f6d04 NEWS for 1.1. 2021-03-09 00:33:41 -07:00
Ariadne Conill fb1d203677 everywhere: drop _GNU_SOURCE requirement 2021-03-09 00:25:13 -07:00
Ariadne Conill 1ad20e03e5 add riscv32 port 2021-03-09 00:00:26 -07:00
Ariadne Conill 464f98a01b
Merge pull request #27 from utmapp/qemu-support-v2
Remaining fixes for Apple Silicon and QEMU
2021-03-08 20:48:30 -06:00
osy 9b1d8f01a6 aarch64: remove usage of FUNC macro for clang
Clang's arm64 assembler does not support multiple directives on a single
line. C macros ALWAYS expand to a single line.
2021-03-08 15:13:34 -08:00
osy 5d66c194a7 x86_64: define reg names if not defined
_GNU_SOURCE can be defined without defining REG_X macros so it is not a
good indicator. (QEMU for example defines it in the build system.) x86
and x86_64 should have consistant looking defs.h so ifndef guards are
added to each REG_X definition.
2021-03-08 14:02:58 -08:00
osy f3e1b876c7 project: move freestanding include headers
This is needed because in libucontext.h we include "libucontext/bits.h".
We therefore need to have bits.h in somepath/libucontext/bits.h. In the
Makefile, somepath/freestanding/bits.h was copied to the right path but
in the meson build system, the include copy happens at the end.
2021-03-08 13:02:27 -08:00
Ariadne Conill f04d423e63
Merge pull request #26 from lpereira/armv7l-makefile-fix
Fix ARCH deduction on armv7l when using Makefiles
2021-02-05 11:46:37 -07:00
Leandro Pereira 7823593b6f Fix ARCH deduction on armv7l when using Makefiles
The Makefile on ARMv7l devices (e.g. Raspberry Pi 400 running the
stock Raspbian distro) was failing to deduct the architecture and
empty libraries were being built as a result.  Building with Meson
works fine; only building with make generated empty libraries.

Add an override for armv7l -> arm in the Makefile to address this.
2021-02-05 08:46:38 -08:00
Ariadne Conill 7df60a2504 build: fix install of libucontext_posix.a 2021-01-09 01:00:05 -07:00
Ariadne Conill b757e1268c libucontext 1.0. 2021-01-09 00:57:00 -07:00
Ariadne Conill c4b5fedc1d add NEWS for libucontext 1.0 2021-01-09 00:56:37 -07:00
Ariadne Conill 63b15f130a set SOVERSION to 1 where appropriate 2021-01-09 00:55:58 -07:00
Ariadne Conill 98d7493b2a meson: bump std level to gnu11, since we use static_assert 2021-01-08 16:29:37 -07:00
Ariadne Conill 9affe94dee
Merge pull request #25 from q66/ppc-no-alias
fix ALIAS usage in ppc, fix meson build, hide libucontext_trampoline
2021-01-08 09:59:47 -05:00
Daniel Kolesa f3e0033a06 meson: remove the subproject-based library checking
this is not idiomatic, and should not be done (and it did not even
work in the first place); meson is capable of building both
libraries via library() and then you can choose on commandline

it defaults to only shared, but we want both out of box, so specify
that
2021-01-08 15:56:42 +01:00
Daniel Kolesa 4801f0bdd8 all: mark the trampoline symbol hidden
this should not be a part of the public ABI
2021-01-08 15:17:13 +01:00
Daniel Kolesa 739894e9a7 meson: fix build 2021-01-08 15:17:13 +01:00
Daniel Kolesa efa6464e41 ppc, ppc64: do not use ALIAS for libucontext_swapcontext 2021-01-08 15:17:11 +01:00
osy d592961b1a build: add meson build 2021-01-08 04:25:56 -07:00
Ariadne Conill b1902729f7 aarch64: fix freestanding structure layout when building with clang 2021-01-08 11:19:01 +00:00
Ariadne Conill 5546fde1e5 aarch64: add static asserts for struct layout 2021-01-08 10:39:47 +00:00
Ariadne Conill 09f78ddc28 alias __makecontext too 2021-01-08 10:37:27 +00:00
osy fffb55011b arm: fix broken FETCH_LINKPTR 2021-01-08 03:20:14 -07:00
osy f7eed30132 build: guard _GNU_SOURCE define if build system defines it 2021-01-08 03:16:05 -07:00
Ariadne Conill 3064ad6dbc build: use head -n1 when reading VERSION 2021-01-08 03:12:33 -07:00
osy 9983d136af build: move version number to file 2021-01-08 03:11:47 -07:00
osy d31c95a11a build: remove -DLIBUCONTEXT_ASSEMBLY
Meson does not support separate defines for .S compile.
2021-01-08 03:11:25 -07:00
Ariadne Conill e4233715f3 mips: use PROC_NAME where appropriate 2021-01-08 03:10:10 -07:00
osy 163c11d989 build: support mach-o ABI 2021-01-08 03:05:06 -07:00
osy b6e60b5d64 include: missing stddef.h include for size_t 2021-01-08 03:04:01 -07:00
osy 73d5e101ad build: respect EXPORT_UNPREFIXED for libucontext_makecontext 2021-01-08 03:02:43 -07:00
Ariadne Conill e45956896a common-trampoline: use register keyword to force register allocation 2021-01-08 03:00:37 -07:00
osy e1e6508af2 defs: use register output only for FETCH_LINKPTR 2021-01-08 02:59:43 -07:00
Ariadne Conill 638770cfd0 x86_64: add static assert verifying memory layout 2021-01-08 02:56:45 -07:00
Ariadne Conill 78e880a29f test POSIX ABI compatibility in libucontext itself, too 2021-01-08 02:37:47 -07:00
Ariadne Conill 39a2958561 add previous ABI symbols 2021-01-08 02:30:50 -07:00
Ariadne Conill 5e6e421c54
Merge pull request #23 from q66/static-only-fix
build: depend on headers for the static target
2021-01-08 04:24:13 -05:00
Ariadne Conill 91c8837c93
Merge pull request #24 from q66/ppc-fixes
ppc, ppc64: tag global symbols as functions
2021-01-08 04:23:59 -05:00
Daniel Kolesa cf05112306 ppc, ppc64: use common ALIAS/FUNC/END macros 2021-01-08 04:52:46 +01:00
Daniel Kolesa 6026980cac ppc, ppc64: tag global symbols as functions
it is necessary to tag these symbols as functions otherwise the
linker gets confused; this previously manifested as the internal
functions (pre-rename) like __getcontext leaking into the symbol
table of things linked against libucontext that used the ucontext
POSIX API through the weak aliases

it also had another bad effect and that is if you tried to use
libucontext's API (post-rename), the linker would warn you during
compile time that the type is unknown, and the resulting program
would crash at runtime

after properly tagging everything, I no longer notice any leakage,
i.e. there don't seem to be any references to the aliased symbols
in the resulting symbol table when using the aliases, and using
the libucontext prefixed symbols directly also works
2021-01-08 04:27:27 +01:00
Daniel Kolesa 03927d4c4c build: depend on headers for the static target
this fixes static-only build, i.e. "make libucontext.a"
2021-01-08 03:01:32 +01:00
Ariadne Conill d81154a61c riscv64: port to C trampoline 2020-12-12 00:08:48 -07:00
Ariadne Conill 11a40293be riscv64: simplify the context swapping 2020-12-12 07:05:09 +00:00
Ariadne Conill 6763b5ba1e README: note which archs support C trampoline 2020-12-11 23:53:09 -07:00
Ariadne Conill c986ba340e build: use ARCH=ppc64 by default on ppc64le 2020-12-12 06:46:08 +00:00
Ariadne Conill 22b91690bc aarch64: move to C trampoline 2020-12-12 06:43:58 +00:00
Ariadne Conill afcca79d7b arm: move to C trampoline 2020-12-12 06:40:27 +00:00
Ariadne Conill a6a64b0711 build: fix test_libucontext_posix linkage 2020-12-12 06:37:31 +00:00
Ariadne Conill 388edbe121 x86: port to use common trampoline 2020-12-12 06:32:01 +00:00
Ariadne Conill 3123bfdd9b gitignore: add a bunch of stuff 2020-12-11 23:23:08 -07:00
Ariadne Conill b6542e1a6a m68k: port to use common trampoline 2020-12-12 00:17:26 -06:00
Ariadne Conill b62ecd476c start NEWS for 1.0 2020-12-11 23:09:58 -07:00
Ariadne Conill 09d3f81dcf sh: use new common trampoline 2020-12-12 06:08:33 +00:00
Ariadne Conill 2d51d7bfa4 x86_64: add common trampoline code written in C, port to it 2020-12-11 23:04:47 -07:00
Ariadne Conill 71cbb6a3d3 README: note sh architecture is supported 2020-12-11 23:03:45 -07:00
Ariadne Conill 5c3ca5a7e1 sh: add freestanding bits 2020-12-12 06:02:47 +00:00
Ariadne Conill 8d58adb3ba sh: fix up setcontext/swapcontext 2020-12-12 05:57:58 +00:00
Ariadne Conill dd7ef8a806 sh: makecontext: fix stack alignment 2020-12-12 05:04:39 +00:00
Ariadne Conill f9a3f65f5b sh: fix getcontext implementation 2020-12-12 05:04:17 +00:00
Ariadne Conill 82f734ab47 sh: makecontext: set up stack pointer in r15 2020-12-12 04:53:50 +00:00
Ariadne Conill da3c8d170f sh: add remaining port files 2020-12-11 23:18:04 +00:00
Ariadne Conill a42fb86da0 sh: add plausible swapcontext implementation 2020-12-11 22:37:21 +00:00
Ariadne Conill 00261d70e8 sh: add plausible setcontext implementation 2020-12-11 22:25:23 +00:00
Ariadne Conill fd06f42bc3 sh: add first attempt at a getcontext implementation 2020-12-11 21:58:56 +00:00
Ariadne Conill 2692ecf74a sh: defs: define REG_GBR, REG_MACH, REG_MACL 2020-12-11 21:35:12 +00:00
Ariadne Conill 42a4fbe9d1 sh: add makecontext 2020-12-11 21:13:20 +00:00
Ariadne Conill de399ebdbf build: override ARCH to sh on sh4 systems 2020-12-11 12:09:59 +00:00
Ariadne Conill 4ea37b1877 libucontext_posix: fix build under glibc 2020-12-11 11:12:47 +00:00
Ariadne Conill 634145cc40 add libucontext_posix test program 2020-12-09 01:40:12 +00:00
Ariadne Conill 04b5520a61 build: build test_libucontext_posix program 2020-12-09 01:39:54 +00:00
Ariadne Conill 2688747f8a build: make and install libucontext_posix 2020-12-08 18:29:21 -07:00
Ariadne Conill ed1e5752fc libucontext_posix: add some tracing 2020-12-08 18:28:35 -07:00
Ariadne Conill 27d8a515e1 libucontext_posix: add posixly-correct wrapper around libucontext 2020-12-08 17:06:09 -07:00
Ariadne Conill 045e622971 libucontext 0.13.1. 2020-12-08 03:49:52 -07:00
Ariadne Conill 4a91eacd41
Merge pull request #21 from omerfirmak/master
.pc file should be installed under PKGCONFIGDIR
2020-12-08 03:25:48 -07:00
Ömer Faruk IRMAK f2f46569e7 .pc file should be installed under PKGCONFIGDIR 2020-12-08 12:18:01 +03:00
Ariadne Conill f0b5c0f7e1 libucontext 0.13. 2020-12-07 18:29:54 -07:00
Ariadne Conill 5cf38aeae8 build: add dist/distcheck 2020-12-07 18:28:02 -07:00
Ariadne Conill bced874113 README: discuss docs/install_docs and DESTDIR 2020-12-07 18:21:58 -07:00
Ariadne Conill d64931ad4f build: add install_docs target 2020-12-07 18:19:37 -07:00
Ariadne Conill cc2b4da24a add cooperative threading example 2020-12-07 18:15:18 -07:00
Ariadne Conill a52354e640 build: add docs target 2020-12-07 18:14:51 -07:00
Ariadne Conill be5b4c0cac add manual page 2020-12-07 18:14:35 -07:00
Ariadne Conill 22bd490272 libucontext: expand README 2020-12-07 14:39:07 -07:00
Ariadne Conill c10cde83da ppc: fix build with libucontext_ namespacing changes 2020-12-06 14:04:22 +00:00
Ariadne Conill a04dc12d72 aarch64: add freestanding port 2020-12-06 13:50:50 +00:00
Ariadne Conill f3f52fc17c arm: add freestanding port 2020-12-06 13:43:04 +00:00
Ariadne Conill 7d149e6358 mips: add freestanding port 2020-12-06 06:34:56 -07:00
Ariadne Conill 20fd2b6f52 mips64: add freestanding port 2020-12-06 06:24:50 -07:00
Ariadne Conill 0c6077854a riscv64: add freestanding port 2020-12-06 06:10:00 -07:00
Ariadne Conill 50bb9432c8 s390x: add freestanding port 2020-12-06 12:37:08 +00:00
Ariadne Conill b33c7df219 s390x: update makecontext prototype 2020-12-06 12:30:44 +00:00
Ariadne Conill da736b6add ppc64: chase API changes related to freestanding stuff
freestanding is however NOT supported here
2020-12-06 12:23:09 +00:00
Ariadne Conill 131e825f50 x86: add freestanding port 2020-12-06 11:37:19 +00:00
Ariadne Conill 9c0ffd8fbb x86: fix conflicts with musl headers + freestanding adaptations 2020-12-06 11:24:23 +00:00
Ariadne Conill 83a109c2a7 update README with status table 2020-12-06 03:54:19 -07:00
Ariadne Conill 0566e66d2d NEWS: not all ports have freestanding yet 2020-12-06 03:45:05 -07:00
Ariadne Conill 13f396f743 note freestanding build support (closes #6, #7) 2020-12-06 03:30:13 -07:00
Ariadne Conill 9aef11752f x86_64: add freestanding port 2020-12-06 03:22:27 -07:00
Ariadne Conill 794b4f92aa build: generate libucontext pkg-config file 2020-12-06 04:10:14 -06:00
Ariadne Conill 74121dfe75 build: install generated headers 2020-12-06 04:01:26 -06:00
Ariadne Conill e715cd2679 gitignore: add include/libucontext/bits.h 2020-12-06 03:54:22 -06:00
Ariadne Conill 1966a6b349 include: add public libucontext/libucontext.h header 2020-12-06 03:53:58 -06:00
Ariadne Conill a8415a0c4e m68k: add freestanding bits.h file 2020-12-06 03:53:45 -06:00
Ariadne Conill c31decc3d4 build: use internal definitions to replace things pulled in from ucontext.h 2020-12-06 03:44:45 -06:00
Ariadne Conill 40c8016144 bits: alias greg_t as libucontext_greg_t in non-freestanding builds 2020-12-06 03:40:55 -06:00
Ariadne Conill ef632da18f build: regenerate libucontext/bits.h as needed 2020-12-06 03:40:27 -06:00
Ariadne Conill e2636d542b test program: use libucontext-prefixed symbols 2020-12-06 03:32:09 -06:00
Ariadne Conill 0953d71ed1 build: fill in more details for freestanding builds 2020-12-06 03:31:48 -06:00
Ariadne Conill 2979186379 common: define libucontext_ucontext_t for non-freestanding case 2020-12-06 03:18:41 -06:00
Ariadne Conill 11468c3e54 build: assemble with -DLIBUCONTEXT_ASSEMBLY 2020-12-06 03:17:36 -06:00
Ariadne Conill d44eba0b22 build: add support for freestanding builds 2020-12-06 03:10:04 -06:00
Ariadne Conill e65e485630 everywhere: rename __swapcontext to libucontext_swapcontext 2020-12-06 03:04:22 -06:00
Ariadne Conill 37fe7afd5f everywhere: rename __setcontext to libucontext_setcontext 2020-12-06 03:03:07 -06:00
Ariadne Conill 99ed5bbe12 everywhere: rename __getcontext to libucontext_getcontext 2020-12-06 03:02:25 -06:00
Ariadne Conill 2f31efaa95 everywhere: rename __start_context to better descriptive libucontext_trampoline 2020-12-06 02:59:59 -06:00
Ariadne Conill c693dc663c rename __makecontext to libucontext_makecontext 2020-12-06 02:56:59 -06:00
Ariadne Conill fe19127c66 build: add support for EXPORT_UNPREFIXED=no
In an EXPORT_UNPREFIXED=no build, getcontext/makecontext/setcontext/swapcontext
symbols are not provided.
2020-12-06 02:54:01 -06:00
Ariadne Conill 8b7cefd98d begin NEWS for 0.13 2020-12-06 02:42:37 -06:00
Ariadne Conill 0863bd891d README: note m68k support 2020-12-06 02:25:53 -06:00
Ariadne Conill 15ba7b039c m68k: add startcontext trampoline 2020-12-06 02:24:49 -06:00
Ariadne Conill 5f6135c0f9 m68k: fixups for makecontext 2020-12-06 02:24:05 -06:00
Ariadne Conill 22520be2de m68k: fix register layout off by one 2020-12-06 00:52:05 -06:00
Ariadne Conill 89536b198d m68k: add swapcontext 2020-12-06 00:04:50 -06:00
Ariadne Conill c462af8a3c m68k: implement getcontext and setcontext 2020-12-05 23:54:36 -06:00
Ariadne Conill 76f1fd75b8 m68k: add makecontext() implementation 2020-12-05 23:30:39 -06:00
Ariadne Conill 5ee9c4e8a5 m68k: add register definitions 2020-12-05 23:22:40 -06:00
Ariadne Conill a6e76834d7 riscv64: align ucontext register access with musl 1.2 headers 2020-12-05 20:07:34 -07:00
Drew DeVault 5928947223 riscv64: fix PIC-incompatible assembly 2020-12-05 18:53:49 -07:00
Ariadne Conill ff858d8bdd NEWS: add 0.12 changes (forgot to do so earlier) 2020-12-04 11:23:34 -07:00
Ariadne Conill b1ea2ae83b everywhere: use ucontext.h instead of signal.h for pulling in ucontext definitions
This allows building libucontext against newlib.
2020-12-04 11:19:02 -07:00
Ariadne Conill 34472b8884 riscv64: chase musl ab3eb89a8b83353cdaab12ed017a67a7730f90e9 changes 2020-12-03 18:25:04 -07:00
Ariadne Conill 02470ccdd8 build: split CFLAGS/CPPFLAGS correctly 2020-12-03 18:24:08 -07:00
Ariadne Conill 938d0d5771 README: note riscv64 support 2020-05-18 03:28:21 +00:00
Ariadne Conill c3393695d2 NEWS: prepare for 0.11 release 2020-05-18 03:26:37 +00:00
Ariadne Conill e11fa34822 riscv64: add makecontext() and __start_context() trampoline 2020-05-18 03:19:22 +00:00
Ariadne Conill e9308ef58f riscv64: add swapcontext 2020-05-18 02:48:28 +00:00
Ariadne Conill e32eb6ef59 riscv64: implement getcontext/setcontext 2020-05-18 02:43:27 +00:00
Ariadne Conill 4d42f482dc riscv64: add architectural defines 2020-05-18 02:19:14 +00:00
Ariadne Conill 19fa1bbfc2
Merge pull request #20 from kraj/master
Remove using .end directive with clang
2020-04-12 13:21:28 -05:00
Khem Raj b6732f6884 Remove using .end directive with clang
Clang does not support this asm directive
Fixes Issue #19

Signed-off-by: Khem Raj <raj.khem@gmail.com>
2020-04-10 11:23:39 -07:00
Ariadne Conill 272d682103
Merge pull request #18 from awilfox/master
x86: Update copyright statement
2020-03-31 04:13:22 -06:00
A. Wilcox 467ee2916d
x86: Update copyright statement
Commit d0ccf2f96f contains the makecontext
fix from Adélie commit aaeb73ea701388e55b7640e32509a5f6a57f6350[1], as
seen at AdelieLinux/libucontext@aaeb73ea – but it didn't include the
addition of my author line.

The full commit text, for future documentation/reference, was:

```
x86: Write link pointer at correct stack offset

It must come *after* the parameters, not *before*.
```

Fixes: d0ccf2f96f ("x86: modernize")
Signed-off-by: A. Wilcox <AWilcox@Wilcox-Tech.com>

[1]: aaeb73ea70
2020-03-30 17:25:30 -05:00
Khem Raj e2178de76a Makefile: Add LIBDIR variable
This ensures that it can be installed into custom location and also

Upstream-Status: Submitted
Signed-off-by: Khem Raj <raj.khem@gmail.com>
2020-03-30 08:21:52 +00:00
Ariadne Conill e040915105
Merge pull request #17 from awilfox/master
README: Remove support section
2020-03-30 02:11:55 -06:00
Ariadne Conill 136ebdffd9
Merge branch 'master' into master 2020-03-30 02:11:45 -06:00
Ariadne Conill b784d75440 README: drop gcompat mailing list mention 2020-03-30 08:10:19 +00:00
A. Wilcox d7688a41df
README: Remove support section
This is no longer a member of the gcompat family of projects;
remove the mention of that and the gcompat mailing list link.
2020-03-30 02:22:43 -05:00
Ariadne Conill e786bc9409 README: ARCH=mips64 does support N32 ABI in theory 2020-03-30 06:38:23 +00:00
Ariadne Conill 1ee8d2f360 add NEWS for pending 0.10 release 2020-03-30 06:36:08 +00:00
Ariadne Conill d7d746f44e s390x: modernize assembly code 2020-03-30 01:12:07 -05:00
Ariadne Conill ef42ad682a s390x: fix makecontext(3) implementation for passing arguments via stack 2020-03-30 01:04:16 -05:00
Ariadne Conill f708c95659 arm: modernize 2020-03-30 05:04:18 +00:00
Ariadne Conill fb27ad693b aarch64: modernize 2020-03-30 04:38:53 +00:00
Ariadne Conill b04da78fb8 mips: use REG_OFFSET 2020-03-30 04:07:41 +00:00
Ariadne Conill 08e8a41d6c mips64: use REG_OFFSET 2020-03-30 04:05:00 +00:00
Ariadne Conill 3d40ad902a readme: note mips support 2020-03-29 15:59:18 +00:00
Ariadne Conill add34ddac7 mips: add MIPS O32 ABI implementation (closes #2) 2020-03-29 15:54:32 +00:00
Ariadne Conill 01432abb3e test: swaps to f1 not main 2020-03-29 15:10:17 +00:00
Ariadne Conill d0ccf2f96f x86: modernize 2020-03-29 15:04:03 +00:00
Ariadne Conill d8cfe83e34 common: use REG_SZ, not SZ_REG in line with mips64 port for REG_OFFSET macro 2020-03-29 14:50:38 +00:00
Ariadne Conill 8631580fbb mips64: use ALIAS() macro for aliases 2020-03-29 14:37:13 +00:00
Ariadne Conill e00902b5b1 x86_64: modernize implementation 2020-03-29 14:27:40 +00:00
Ariadne Conill 2411cdfb54 common: add REG_OFFSET accesso 2020-03-29 14:27:19 +00:00
Ariadne Conill c385d69aa9 common: add ALIAS() macro 2020-03-29 14:12:23 +00:00
Ariadne Conill fd32a2fa8c common: factor out .ent handling 2020-03-29 14:03:18 +00:00
Ariadne Conill 2f4eb16f38 mips64: factor out frame management macros into arch/common/common-defs.h 2020-03-29 13:49:57 +00:00
Ariadne Conill 8536f1fa3b makefile: add include path for arch/common 2020-03-29 13:46:19 +00:00
Ariadne Conill 87f58af294 remove pointless gitignore entries 2020-03-29 13:44:06 +00:00
Ariadne Conill 7c60f4576c mips64: elide emulation of the magic flag crap glibc does 2020-03-29 13:40:32 +00:00
Ariadne Conill e8115eb013 test: add additional verbosity 2020-03-29 12:37:01 +00:00
Ariadne Conill 80a6ca3854 add mips64 implementation 2020-03-29 12:05:52 +00:00
Ariadne Conill f3a873e6e6 test: add additional verbosity 2020-03-29 12:05:00 +00:00
Ariadne Conill d696a0b692 tests: add additional verbosity 2020-03-27 12:43:09 +00:00
Ariadne Conill d31eaabbaf update copyright statements, add mailmap 2020-03-27 09:23:49 +00:00
Ariadne Conill 5f137a1fe4
Merge pull request #16 from gabrielivascu/master
Makefile: i386, i686 -> x86
2020-03-27 03:09:32 -06:00
Khem Raj 6cfab025e0 pass LDFLAGS to link step
This helps to use OE specific linker flags and fixes

do_package_qa: QA Issue: No GNU_HASH in the ELF binary

Upstream-Status: Pending
Signed-off-by: Khem Raj <raj.khem@gmail.com>
2020-03-27 08:54:56 +00:00
Gabriel Ivașcu acff6c83eb Makefile: i386, i686 -> x86 2019-10-22 18:08:47 +03:00
William Pitcock 0b4f9ecf33
Merge pull request #14 from gabrielivascu/master
Makefile: Handle static library at clean/install
2019-04-14 19:33:06 -05:00
Gabriel Ivașcu 2e15b38327 Makefile: Handle static library at clean/install 2019-04-12 10:48:24 +03:00
William Pitcock 05cb8ecbee
Merge pull request #13 from gabrielivascu/master
Build static library too
2019-04-11 13:17:18 -05:00
Gabriel Ivașcu 9cc1a2c0e6 Build static library too 2019-04-09 16:07:39 +03:00
William Pitcock 7599fe5ff2
Merge pull request #11 from koorogi/ppc-fixes
Ppc fixes
2019-04-06 10:30:37 -04:00
Bobby Bingham 2610c7faa7 ppc32/64: rewrite get/set/swapcontext in assembly
getcontext cannot be correctly implemented in C.

If this calls another function, as it does to call syscall, it needs to
first spill its return address to the stack.  If, after getcontext returns,
its caller then calls other functions, this saved return address can be
clobbered.  When the context saved by getcontext is later restored, the
(now clobbered) return address will be reloaded from the stack, and the
second return from getcontext will return to the wrong location.

Because the powerpc swapcontext syscall allows either the old context or
new context pointers to be null, it is usable for implementing all of
get/set/swapcontext.

We therefore rewrite swapcontext in assembly, and get/setcontext as simple
assembly function wrappers around swapcontext.

The one piece we keep in C is the code to check the return value of the
system call and to set errno.  This code was actually unnecessary before --
libc does this within syscall.  However, now that the system call is made
directly in assembly, bypassing libc, it is truly necessary.  Because errno
is thread-local and the details of how to set it can vary by libc, this
code remains written in C.
2019-04-05 14:44:54 -05:00
Bobby Bingham 90ff6330e6 ppc32/64: update copyright 2019-04-05 14:18:20 -05:00
Bobby Bingham 29eac4259a ppc32/64: remove unused includes 2019-04-05 14:18:20 -05:00
Bobby Bingham edf69879ea ppc64: remove unnecessary parentheses 2019-04-05 14:18:20 -05:00
Bobby Bingham 40d07758a5 ppc32/64: correct signature of function parameter to makecontext
Because makecontext can pass a set of integer arguments to the provided
function, it is incorrect to require that this function accept no
parameters.
2019-04-05 14:18:20 -05:00
Bobby Bingham a00a05ce29 ppc64: fix incorrect position of parameters within stack frame
On PPC64, there are 4 register-sized stack slots below the parameter save
area, which is different from the 2 stack slots on PPC32.
2019-04-05 14:18:20 -05:00
Bobby Bingham 8ea5f548b9 ppc64: fix makecontext with more than 8 parameters
The ELFv2 ABI used on PPC64 differs from the ELFv1 ABI used on PPC32 here.
On PPC64, once there are any parameters that need to be passed on the
stack, space needs to be reserved on the stack to pass all parameters.
Parameters 0-7 are still only passed by register, but if the callee needs
to spill them, it can use the stack space reserved for the corresponding
parameter to do so.
2019-04-05 14:18:20 -05:00
Bobby Bingham 55168fcb18 ppc32/64: simplify storage of stack parameters
The switch statement is simpler as an if/else, and removing the argp
variable makes the code more symmetric between the register and stack
parameter cases.
2019-04-05 14:18:20 -05:00
Bobby Bingham b500b054c7 ppc32/64: don't store uc_link on the stack
This was previously stored either in the CR (ppc64) or LR (ppc32) save
area of the stack, or to one of the parameter save slots.

In either case, the saved value was unused.  This value is also passed
to __start_context via r31, so there's no need to pass it on the stack.
2019-04-05 14:15:49 -05:00
Bobby Bingham b9bd4045fb ppc32/64: fix back chain pointer
The ABI states that sp[0] should point to the previous stack frame, or be
zero if there is no previous stack frame.  makecontext previously set this
slot to point to the __start_context function, rather than to a valid
stack frame.
2019-04-05 14:15:49 -05:00
Bobby Bingham b6a9b5e279 ppc32: fix stack alignment
The stack should be 16-byte aligned, not 8 mod 16.
2019-04-05 14:15:44 -05:00
Bobby Bingham cb59e7ee95 test calls to getcontext without makecontext 2019-04-05 13:28:36 -05:00
Bobby Bingham 94216c60c4 test ability to pass 10 args through makecontext 2019-04-05 13:28:36 -05:00
134 changed files with 5349 additions and 918 deletions

46
.gitignore vendored
View File

@ -1,38 +1,16 @@
# http://www.gnu.org/software/automake
Makefile.in
/ar-lib
/mdate-sh
/py-compile
/test-driver
/ylwrap
# http://www.gnu.org/software/autoconf
/autom4te.cache
/autoscan.log
/autoscan-*.log
/aclocal.m4
/compile
/config.guess
/config.h.in
/config.sub
/configure
/configure.scan
/depcomp
/install-sh
/missing
/stamp-h1
# https://www.gnu.org/software/libtool/
/ltmain.sh
# http://www.gnu.org/software/texinfo
/texinfo.tex
include/libucontext/bits.h
*.o
examples/cooperative_threading
test_libucontext
test_libucontext_posix
test_libucontext_bare_posixabi
libucontext.a
libucontext.so
libucontext.so.*
libucontext_posix.a
libucontext_posix.so
libucontext_posix.so.*
libucontext.pc
*.tar.xz
core
*.core

1
.mailmap Normal file
View File

@ -0,0 +1 @@
Ariadne Conill <ariadne@dereferenced.org> <nenolod@dereferenced.org>

40
.woodpecker.yml Normal file
View File

@ -0,0 +1,40 @@
pipeline:
build-x86_64:
image: alpine
commands:
- apk add --no-cache build-base
- make check ARCH=x86_64
when:
platform: linux/amd64
build-s390x:
image: alpine
commands:
- apk add --no-cache build-base
- make check ARCH=s390x
when:
platform: linux/s390x
build-ppc64le:
image: alpine
commands:
- apk add --no-cache build-base
- make check ARCH=ppc64le
when:
platform: linux/ppc64le
build-armv7:
image: alpine
commands:
- apk add --no-cache build-base
- make check ARCH=arm
when:
platform: linux/arm
build-aarch64:
image: alpine
commands:
- apk add --no-cache build-base
- make check ARCH=aarch64
when:
platform: linux/arm64

View File

@ -1,4 +1,4 @@
Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
Copyright (c) 2018-2022 Ariadne Conill <ariadne@dereferenced.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above

288
Makefile
View File

@ -1,48 +1,284 @@
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
CFLAGS = -ggdb3 -O2 -Wall -Iarch/${ARCH}
prefix = /usr
libdir = ${prefix}/lib
shared_libdir = ${libdir}
static_libdir = ${libdir}
includedir = ${prefix}/include
pkgconfigdir = ${prefix}/lib/pkgconfig
LIBUCONTEXT_C_SRC = \
arch/${ARCH}/makecontext.c
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
LIBUCONTEXT_S_SRC = \
arch/${ARCH}/getcontext.S \
arch/${ARCH}/setcontext.S \
arch/${ARCH}/swapcontext.S \
arch/${ARCH}/startcontext.S
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 = 0
LIBUCONTEXT_NAME = libucontext.so
LIBUCONTEXT_SONAME = libucontext.so.${LIBUCONTEXT_SOVERSION}
LIBUCONTEXT_PATH = /lib/${LIBUCONTEXT_SONAME}
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}
all: ${LIBUCONTEXT_SONAME}
ifeq ($(FREESTANDING),yes)
LIBUCONTEXT_POSIX_NAME =
LIBUCONTEXT_POSIX_STATIC_NAME =
endif
${LIBUCONTEXT_NAME}: ${LIBUCONTEXT_OBJ}
$(CC) -o ${LIBUCONTEXT_NAME} -Wl,-soname,${LIBUCONTEXT_SONAME} \
-shared ${LIBUCONTEXT_OBJ}
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=c99 -D_BSD_SOURCE -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} -c -o $@ $<
$(CC) -std=gnu99 -D_BSD_SOURCE -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} -c -o $@ $<
.S.o:
$(CC) -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} -c -o $@ $<
$(CC) -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} ${ASFLAGS} -c -o $@ $<
clean:
rm -f ${LIBUCONTEXT_NAME} ${LIBUCONTEXT_SONAME} ${LIBUCONTEXT_OBJ} test_libucontext
${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: all
install -D -m755 ${LIBUCONTEXT_NAME} ${DESTDIR}/${LIBUCONTEXT_PATH}
ln -sf ${LIBUCONTEXT_SONAME} ${DESTDIR}/lib/${LIBUCONTEXT_NAME}
install -D -m755 ${LIBUCONTEXT_NAME} ${DESTDIR}${LIBUCONTEXT_PATH}
install -D -m664 ${LIBUCONTEXT_STATIC_NAME} ${DESTDIR}${LIBUCONTEXT_STATIC_PATH}
ln -sf ${LIBUCONTEXT_SONAME} ${DESTDIR}${shared_libdir}/${LIBUCONTEXT_NAME}
for i in ${LIBUCONTEXT_HEADERS}; do \
destfn=$$(echo $$i | sed s:include/::g); \
install -D -m644 $$i ${DESTDIR}${includedir}/$$destfn; \
done
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
check: test_libucontext ${LIBUCONTEXT_SONAME}
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_BSD_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_BSD_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
test_libucontext: test_libucontext.c ${LIBUCONTEXT_NAME}
$(CC) -std=c99 -D_BSD_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext
check: check_libucontext
.PHONY: check
test_libucontext: test_libucontext.c ${LIBUCONTEXT_NAME}
$(CC) -std=gnu99 -D_BSD_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext
examples: ${LIBUCONTEXT_EXAMPLES}
examples/cooperative_threading: examples/cooperative_threading.c ${LIBUCONTEXT_NAME}
$(CC) -std=gnu99 -D_BSD_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

133
NEWS Normal file
View File

@ -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.

View File

@ -6,23 +6,33 @@ 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`.
## supported architectures
Adding support for new architectures is easy, but you need to know assembly language for the
target to do it.
Adding support for new architectures is easy, but you need to know assembly language to do it.
Right now these archs are supported and should work on bare metal:
## supported features
* x86
* x86_64
* armv6+ (`arm`)
* aarch64
* s390x
These archs require kernel assistance and use a syscall (the only assembly is the trampoline):
* ppc
* ppc64 (ELFv2 ABI spec only, ELFv1 not supported)
| 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
@ -36,8 +46,60 @@ $ make ARCH=x86_64 check
$ make ARCH=x86_64 DESTDIR=out install
```
There are a few options:
## support
* `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.
`libucontext` is offered as part of the `gcompat` project. Accordingly, please address all questions
and bug reports to gcompat@lists.adelielinux.org.
* `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.

1
VERSION Normal file
View File

@ -0,0 +1 @@
1.2

View File

@ -1,11 +1,15 @@
#ifndef __ARCH_AARCH64_DEFS_H
#define __ARCH_AARCH64_DEFS_H
#define REGSZ 8
#define R0_OFFSET 184
#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
@ -15,4 +19,9 @@
# define ESR_MAGIC 0x45535201
#endif
#define FETCH_LINKPTR(dest) \
asm("mov %0, x19" : "=r" ((dest)))
#include "common-defs.h"
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2018, 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -12,27 +12,33 @@
#include "defs.h"
.globl __getcontext;
__getcontext:
str xzr, [x0, #R0_OFFSET + (0 * REGSZ)]
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, #R0_OFFSET + (0 * REGSZ)]
stp x2, x3, [x0, #R0_OFFSET + (2 * REGSZ)]
stp x4, x5, [x0, #R0_OFFSET + (4 * REGSZ)]
stp x6, x7, [x0, #R0_OFFSET + (6 * REGSZ)]
stp x8, x9, [x0, #R0_OFFSET + (8 * REGSZ)]
stp x10, x11, [x0, #R0_OFFSET + (10 * REGSZ)]
stp x12, x13, [x0, #R0_OFFSET + (12 * REGSZ)]
stp x14, x15, [x0, #R0_OFFSET + (14 * REGSZ)]
stp x16, x17, [x0, #R0_OFFSET + (16 * REGSZ)]
stp x18, x19, [x0, #R0_OFFSET + (18 * REGSZ)]
stp x20, x21, [x0, #R0_OFFSET + (20 * REGSZ)]
stp x22, x23, [x0, #R0_OFFSET + (22 * REGSZ)]
stp x24, x25, [x0, #R0_OFFSET + (24 * REGSZ)]
stp x26, x27, [x0, #R0_OFFSET + (26 * REGSZ)]
stp x28, x29, [x0, #R0_OFFSET + (28 * REGSZ)]
str x30, [x0, #R0_OFFSET + (30 * REGSZ)]
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]
@ -44,11 +50,12 @@ __getcontext:
/* save pstate */
str xzr, [x0, #PSTATE_OFFSET]
/* TODO: SIMD / FPRs */
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
.weak getcontext;
getcontext = __getcontext;
END(libucontext_getcontext)

View File

@ -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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2018 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -10,21 +10,24 @@
* from the use of this software.
*/
#define _GNU_SOURCE
#include <stddef.h>
#include <stdarg.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include "defs.h"
#include <libucontext/libucontext.h>
extern void __start_context(void);
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
__makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(void), int argc, ...)
{
unsigned long *sp;
unsigned long *regp;
@ -38,7 +41,7 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
ucp->uc_mcontext.sp = (uintptr_t) sp;
ucp->uc_mcontext.pc = (uintptr_t) func;
ucp->uc_mcontext.regs[19] = (uintptr_t) ucp->uc_link;
ucp->uc_mcontext.regs[30] = (uintptr_t) &__start_context;
ucp->uc_mcontext.regs[30] = (uintptr_t) &libucontext_trampoline;
va_start(va, argc);
@ -53,5 +56,7 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
va_end(va);
}
extern __typeof(__makecontext) makecontext __attribute__((weak, __alias__("__makecontext")));
#ifdef EXPORT_UNPREFIXED
extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2018, 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -12,36 +12,42 @@
#include "defs.h"
.globl __setcontext;
__setcontext:
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, #R0_OFFSET + (18 * REGSZ)]
ldp x20, x21, [x0, #R0_OFFSET + (20 * REGSZ)]
ldp x22, x23, [x0, #R0_OFFSET + (22 * REGSZ)]
ldp x24, x25, [x0, #R0_OFFSET + (24 * REGSZ)]
ldp x26, x27, [x0, #R0_OFFSET + (26 * REGSZ)]
ldp x28, x29, [x0, #R0_OFFSET + (28 * REGSZ)]
ldr x30, [x0, #R0_OFFSET + (30 * REGSZ)]
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
/* TODO: SIMD / FPRs */
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, #R0_OFFSET + (2 * REGSZ)]
ldp x4, x5, [x0, #R0_OFFSET + (4 * REGSZ)]
ldp x6, x7, [x0, #R0_OFFSET + (6 * REGSZ)]
ldp x0, x1, [x0, #R0_OFFSET + (0 * REGSZ)]
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
.weak setcontext;
setcontext = __setcontext;
END(libucontext_setcontext)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2018 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -12,26 +12,32 @@
#include "defs.h"
.globl __swapcontext;
__swapcontext:
str xzr, [x0, #R0_OFFSET + (0 * REGSZ)]
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, #R0_OFFSET + (2 * REGSZ)]
stp x4, x5, [x0, #R0_OFFSET + (4 * REGSZ)]
stp x6, x7, [x0, #R0_OFFSET + (6 * REGSZ)]
stp x8, x9, [x0, #R0_OFFSET + (8 * REGSZ)]
stp x10, x11, [x0, #R0_OFFSET + (10 * REGSZ)]
stp x12, x13, [x0, #R0_OFFSET + (12 * REGSZ)]
stp x14, x15, [x0, #R0_OFFSET + (14 * REGSZ)]
stp x16, x17, [x0, #R0_OFFSET + (16 * REGSZ)]
stp x18, x19, [x0, #R0_OFFSET + (18 * REGSZ)]
stp x20, x21, [x0, #R0_OFFSET + (20 * REGSZ)]
stp x22, x23, [x0, #R0_OFFSET + (22 * REGSZ)]
stp x24, x25, [x0, #R0_OFFSET + (24 * REGSZ)]
stp x26, x27, [x0, #R0_OFFSET + (26 * REGSZ)]
stp x28, x29, [x0, #R0_OFFSET + (28 * REGSZ)]
str x30, [x0, #R0_OFFSET + (30 * REGSZ)]
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]
@ -43,19 +49,21 @@ __swapcontext:
/* 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 __setcontext
bl PROC_NAME(libucontext_setcontext)
/* hmm, we came back here try to return */
mov x30, x28
ret
.weak swapcontext;
swapcontext = __swapcontext;
END(libucontext_swapcontext)

View File

@ -0,0 +1,3 @@
#include "defs.h"
#include <libucontext/libucontext.h>
#include "common-trampoline.c"

15
arch/arm/defs.h Normal file
View File

@ -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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2018, 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -10,18 +10,40 @@
* from the use of this software.
*/
.globl __getcontext;
__getcontext:
#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, #48
add r1, r0, #REG_OFFSET(4)
stmia r1, {r4-r12}
str r13, [r0,#84]
str r14, [r0,#92]
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
.weak getcontext;
getcontext = __getcontext;
END(libucontext_getcontext)

View File

@ -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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2018, 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -10,20 +10,22 @@
* from the use of this software.
*/
#define _GNU_SOURCE
#include <stddef.h>
#include <stdarg.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
extern void __start_context(void);
#include "defs.h"
#include <libucontext/libucontext.h>
extern void libucontext_trampoline(void);
void
__makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(void), int argc, ...)
{
unsigned long *sp;
unsigned long *regp;
@ -39,7 +41,7 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
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) &__start_context;
ucp->uc_mcontext.arm_lr = (uintptr_t) &libucontext_trampoline;
va_start(va, argc);
@ -52,14 +54,9 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
*sp++ = va_arg (va, unsigned long);
va_end(va);
/*
printf("R4 offset = %d\n", offsetof(ucontext_t, uc_mcontext.arm_r4));
printf("SP offset = %d\n", offsetof(ucontext_t, uc_mcontext.arm_sp));
printf("LR offset = %d\n", offsetof(ucontext_t, uc_mcontext.arm_lr));
printf("PC offset = %d\n", offsetof(ucontext_t, uc_mcontext.arm_pc));
*/
}
extern __typeof(__makecontext) makecontext __attribute__((weak, __alias__("__makecontext")));
#ifdef EXPORT_UNPREFIXED
extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2018, 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -10,17 +10,34 @@
* from the use of this software.
*/
.globl __setcontext;
__setcontext:
#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, #32
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}
.weak setcontext;
setcontext = __setcontext;
END(libucontext_setcontext)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2018, 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -10,21 +10,42 @@
* from the use of this software.
*/
.globl __swapcontext;
__swapcontext:
#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, #32
add r2, r0, #REG_OFFSET(0)
stmia r2, {r0-r12}
str r13, [r0,#84]
str r14, [r0,#92]
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, #32
add r14, r1, #REG_OFFSET(0)
ldmia r14, {r0-r12}
ldr r13, [r14, #52]
add r14, r14, #56
ldmia r14, {r14, pc}
.weak swapcontext;
swapcontext = __swapcontext;
END(libucontext_swapcontext)

3
arch/arm/trampoline.c Normal file
View File

@ -0,0 +1,3 @@
#include "defs.h"
#include <libucontext/libucontext.h>
#include "common-trampoline.c"

61
arch/common/common-defs.h Normal file
View File

@ -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

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
__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);
}

View File

@ -0,0 +1,13 @@
#ifndef LIBUCONTEXT_BITS_H
#define LIBUCONTEXT_BITS_H
#ifndef FREESTANDING
#include <ucontext.h>
typedef greg_t libucontext_greg_t;
typedef ucontext_t libucontext_ucontext_t;
#endif
#endif

76
arch/loongarch64/defs.h Normal file
View File

@ -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 <common-defs.h>
#endif

View File

@ -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

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2021 Peng Fan <fanpeng@loongson.cn>
*
* 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)

View File

@ -0,0 +1,108 @@
/*
* Copyright (c) 2021 Peng Fan <fanpeng@loongson.cn>
*
* 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)

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2021 Peng Fan <fanpeng@loongson.cn>
*
* 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)

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2021 Peng Fan <fanpeng@loongson.cn>
*
* 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)

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2021 Peng Fan <fanpeng@loongson.cn>
*
* 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)

34
arch/m68k/defs.h Normal file
View File

@ -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

30
arch/m68k/getcontext.S Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#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)

View File

@ -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

61
arch/m68k/makecontext.c Normal file
View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include "defs.h"
#include <libucontext/libucontext.h>
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

31
arch/m68k/setcontext.S Normal file
View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#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)

40
arch/m68k/swapcontext.S Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#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)

3
arch/m68k/trampoline.c Normal file
View File

@ -0,0 +1,3 @@
#include "defs.h"
#include <libucontext/libucontext.h>
#include "common-trampoline.c"

94
arch/mips/defs.h Normal file
View File

@ -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 <common-defs.h>
#endif

47
arch/mips/getcontext.S Normal file
View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
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)

View File

@ -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

101
arch/mips/makecontext.S Normal file
View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
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)

51
arch/mips/setcontext.S Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
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)

35
arch/mips/startcontext.S Normal file
View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
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)

82
arch/mips/swapcontext.S Normal file
View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
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)

92
arch/mips64/defs.h Normal file
View File

@ -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 <common-defs.h>
#endif

47
arch/mips64/getcontext.S Normal file
View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
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)

View File

@ -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

107
arch/mips64/makecontext.S Normal file
View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
/* $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)

55
arch/mips64/setcontext.S Normal file
View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
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)

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
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)

87
arch/mips64/swapcontext.S Normal file
View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
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)

22
arch/or1k/defs.h Normal file
View File

@ -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

39
arch/or1k/getcontext.S Normal file
View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2022 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#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)

View File

@ -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

61
arch/or1k/makecontext.c Normal file
View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2022 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include "defs.h"
#include <libucontext/libucontext.h>
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

48
arch/or1k/setcontext.S Normal file
View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2022 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#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)

68
arch/or1k/swapcontext.S Normal file
View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2022 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#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)

3
arch/or1k/trampoline.c Normal file
View File

@ -0,0 +1,3 @@
#include "defs.h"
#include <libucontext/libucontext.h>
#include "common-trampoline.c"

View File

@ -59,4 +59,6 @@
/* lnk register is actually r32 */
#define REG_LNK REG_R36
#include "common-defs.h"
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -10,14 +10,13 @@
* from the use of this software.
*/
.globl __start_context;
.fnstart
.cantunwind
nop
__start_context:
/* get the proper context into position and test for NULL */
movs r0, r4
bne __setcontext@plt
#include "common-defs.h"
/* we are returning into a null context, it seems, so maybe we should exit */
b exit@plt
ALIAS(getcontext, libucontext_getcontext)
ALIAS(__getcontext, libucontext_getcontext)
.hidden __libucontext_swapcontext
FUNC(libucontext_getcontext)
li 4, 0
b __libucontext_swapcontext@local
END(libucontext_getcontext)

View File

@ -1,45 +0,0 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#define _GNU_SOURCE
#include <stddef.h>
#include <stdarg.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <sys/syscall.h>
int
__getcontext(ucontext_t *ucp)
{
#ifdef SYS_swapcontext
int r;
r = syscall(SYS_swapcontext, ucp, NULL, sizeof(ucontext_t));
if (r < 0)
{
errno = -r;
return -1;
}
return 0;
#else
errno = ENOSYS;
return -1;
#endif
}
extern __typeof(__getcontext) getcontext __attribute__((weak, __alias__("__getcontext")));

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2018 Ariadne Conill <ariadne@dereferenced.org>
* Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -10,66 +11,51 @@
* from the use of this software.
*/
#define _GNU_SOURCE
#include <stddef.h>
#include <stdarg.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>
#include "defs.h"
#include <libucontext/libucontext.h>
extern void __start_context(void);
extern void libucontext_trampoline(void);
void
__makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(), int argc, ...)
{
greg_t *sp, *argp;
libucontext_greg_t *sp;
va_list va;
int i;
unsigned int uc_link, stack_args;
unsigned int stack_args;
stack_args = argc > 8 ? argc - 8 : 0;
uc_link = stack_args + 1;
sp = (greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
sp -= (uc_link + 1);
sp = (greg_t *) (((uintptr_t) sp & -16L) - 8);
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) &__start_context;
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] = (uintptr_t) &__start_context;
sp[uc_link] = (uintptr_t) ucp->uc_link;
argp = &sp[2];
sp[0] = 0;
va_start(va, argc);
for (i = 0; i < argc; i++)
switch (i)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
ucp->uc_mcontext.gregs[i + 3] = va_arg (va, greg_t);
break;
default:
*argp++ = va_arg (va, greg_t);
break;
}
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);
}
extern __typeof(__makecontext) makecontext __attribute__((weak, __alias__("__makecontext")));
#ifdef EXPORT_UNPREFIXED
extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
#endif

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2018 Ariadne Conill <ariadne@dereferenced.org>
* Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -10,11 +11,15 @@
* from the use of this software.
*/
.globl __start_context;
__start_context:
/* get the proper context into position and test for NULL */
mov x0, x19
cbnz x0, __setcontext
#include <errno.h>
__attribute__ ((visibility ("hidden")))
int __retfromsyscall(long retval)
{
if (retval < 0) {
errno = -retval;
return -1;
}
return 0;
}
/* something went wrong, exit */
b exit

23
arch/ppc/setcontext.S Normal file
View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#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)

View File

@ -1,45 +0,0 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#define _GNU_SOURCE
#include <stddef.h>
#include <stdarg.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <sys/syscall.h>
int
__setcontext(const ucontext_t *ucp)
{
#ifdef SYS_swapcontext
int r;
r = syscall(SYS_swapcontext, NULL, (void *) ucp, sizeof(ucontext_t));
if (r < 0)
{
errno = -r;
return -1;
}
return r;
#else
errno = ENOSYS;
return -1;
#endif
}
extern __typeof(__setcontext) setcontext __attribute__((weak, __alias__("__setcontext")));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2018 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -10,8 +10,10 @@
* from the use of this software.
*/
.globl __start_context;
__start_context:
#include "common-defs.h"
.hidden libucontext_trampoline
FUNC(libucontext_trampoline)
/* get the proper context into position and test for NULL */
mr. 3,31
@ -19,7 +21,8 @@ __start_context:
beq no_linked_context
/* jump to setcontext */
bl __setcontext@local
bl libucontext_setcontext@local
no_linked_context:
b exit@GOT
END(libucontext_trampoline)

29
arch/ppc/swapcontext.S Normal file
View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#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)

View File

@ -1,45 +0,0 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#define _GNU_SOURCE
#include <stddef.h>
#include <stdarg.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <sys/syscall.h>
int
__swapcontext(ucontext_t *oucp, const ucontext_t *ucp)
{
#ifdef SYS_swapcontext
int r;
r = syscall(SYS_swapcontext, oucp, ucp, sizeof(ucontext_t));
if (r < 0)
{
errno = -r;
return -1;
}
return r;
#else
errno = ENOSYS;
return -1;
#endif
}
extern __typeof(__swapcontext) swapcontext __attribute__((weak, __alias__("__swapcontext")));

View File

@ -62,4 +62,6 @@
/* lnk register is actually %r36 */
#define REG_LNK REG_R36
#include "common-defs.h"
#endif

27
arch/ppc64/getcontext.S Normal file
View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#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)

View File

@ -1,45 +0,0 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#define _GNU_SOURCE
#include <stddef.h>
#include <stdarg.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <sys/syscall.h>
int
__getcontext(ucontext_t *ucp)
{
#ifdef SYS_swapcontext
int r;
r = syscall(SYS_swapcontext, ucp, NULL, sizeof(ucontext_t));
if (r < 0)
{
errno = -r;
return -1;
}
return 0;
#else
errno = ENOSYS;
return -1;
#endif
}
extern __typeof(__getcontext) getcontext __attribute__((weak, __alias__("__getcontext")));

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2018 Ariadne Conill <ariadne@dereferenced.org>
* Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -10,67 +11,52 @@
* from the use of this software.
*/
#define _GNU_SOURCE
#include <stddef.h>
#include <stdarg.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>
#include "defs.h"
#include <libucontext/libucontext.h>
extern void __start_context(void);
extern void libucontext_trampoline(void);
void
__makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(), int argc, ...)
{
greg_t *sp, *argp;
libucontext_greg_t *sp;
va_list va;
int i;
unsigned int uc_link, stack_args;
unsigned int stack_args;
stack_args = argc > 8 ? argc - 8 : 0;
uc_link = stack_args + 1;
stack_args = argc > 8 ? argc : 0;
sp = (greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
sp -= (uc_link + 1);
sp = (greg_t *) (((uintptr_t) sp & -16L));
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) &__start_context;
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] = (uintptr_t) &__start_context;
sp[uc_link] = (uintptr_t) ucp->uc_link;
argp = &sp[2];
sp[0] = 0;
va_start(va, argc);
for (i = 0; i < argc; i++)
switch (i)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
ucp->uc_mcontext.gp_regs[i + 3] = va_arg (va, greg_t);
break;
default:
*argp++ = va_arg (va, greg_t);
break;
}
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);
}
extern __typeof(__makecontext) makecontext __attribute__((weak, __alias__("__makecontext")));
#ifdef EXPORT_UNPREFIXED
extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
#endif

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2018 Ariadne Conill <ariadne@dereferenced.org>
* Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* 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 <errno.h>
__attribute__ ((visibility ("hidden")))
int __retfromsyscall(long retval)
{
if (retval < 0) {
errno = -retval;
return -1;
}
return 0;
}

28
arch/ppc64/setcontext.S Normal file
View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#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)

View File

@ -1,45 +0,0 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#define _GNU_SOURCE
#include <stddef.h>
#include <stdarg.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <sys/syscall.h>
int
__setcontext(const ucontext_t *ucp)
{
#ifdef SYS_swapcontext
int r;
r = syscall(SYS_swapcontext, NULL, (void *) ucp, sizeof(ucontext_t));
if (r < 0)
{
errno = -r;
return -1;
}
return r;
#else
errno = ENOSYS;
return -1;
#endif
}
extern __typeof(__setcontext) setcontext __attribute__((weak, __alias__("__setcontext")));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2018 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -10,9 +10,10 @@
* from the use of this software.
*/
.globl __start_context;
.hidden __start_context;
__start_context:
#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 */
@ -29,3 +30,4 @@ __start_context:
no_linked_context:
b exit@GOT
nop
END(libucontext_trampoline)

34
arch/ppc64/swapcontext.S Normal file
View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#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)

View File

@ -1,45 +0,0 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#define _GNU_SOURCE
#include <stddef.h>
#include <stdarg.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <sys/syscall.h>
int
__swapcontext(ucontext_t *oucp, const ucontext_t *ucp)
{
#ifdef SYS_swapcontext
int r;
r = syscall(SYS_swapcontext, oucp, ucp, sizeof(ucontext_t));
if (r < 0)
{
errno = -r;
return -1;
}
return r;
#else
errno = ENOSYS;
return -1;
#endif
}
extern __typeof(__swapcontext) swapcontext __attribute__((weak, __alias__("__swapcontext")));

55
arch/riscv32/defs.h Normal file
View File

@ -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

45
arch/riscv32/getcontext.S Normal file
View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#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)

View File

@ -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

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2018 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include "defs.h"
#include <libucontext/libucontext.h>
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

56
arch/riscv32/setcontext.S Normal file
View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#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)

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#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)

View File

@ -0,0 +1,3 @@
#include "defs.h"
#include <libucontext/libucontext.h>
#include "common-trampoline.c"

55
arch/riscv64/defs.h Normal file
View File

@ -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

45
arch/riscv64/getcontext.S Normal file
View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#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)

View File

@ -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

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2018 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include "defs.h"
#include <libucontext/libucontext.h>
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

56
arch/riscv64/setcontext.S Normal file
View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#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)

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#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)

View File

@ -0,0 +1,3 @@
#include "defs.h"
#include <libucontext/libucontext.h>
#include "common-trampoline.c"

View File

@ -1,8 +1,15 @@
#ifndef __ARCH_S390X_DEFS_H
#define __ARCH_S390X_DEFS_H
#define OFFSET_GREGS (56)
#define OFFSET_AREGS (184)
#define OFFSET_FPREGS (248)
#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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2018, 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -12,17 +12,15 @@
#include "defs.h"
ALIAS(getcontext, libucontext_getcontext)
ALIAS(__getcontext, libucontext_getcontext)
.globl __getcontext;
__getcontext:
FUNC(libucontext_getcontext)
lgr %r1, %r2 /* use %r1 as our working register */
la %r2, 0 /* we will return 0 */
stam %a0, %a15, OFFSET_AREGS(%r1) /* store access registers */
stmg %r0, %r15, OFFSET_GREGS(%r1) /* store general-purpose registers */
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 */
.weak getcontext;
getcontext = __getcontext;
END(libucontext_getcontext)

View File

@ -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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2018, 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -10,59 +10,47 @@
* from the use of this software.
*/
#define _GNU_SOURCE
#include <stddef.h>
#include <stdarg.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>
#include "defs.h"
#include <libucontext/libucontext.h>
extern void __start_context(void);
extern int __setcontext(const ucontext_t *ucp);
extern void libucontext_trampoline(void);
extern int libucontext_setcontext(const libucontext_ucontext_t *ucp);
void
__makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(void), int argc, ...)
{
greg_t *sp, *argp;
libucontext_greg_t *sp;
va_list va;
int i;
unsigned int stack_args;
stack_args = argc > 5 ? argc - 5 : 0;
sp = (greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
sp -= stack_args; // maybe +1
sp = (greg_t *) (((uintptr_t) sp & -16L));
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) &__setcontext;
ucp->uc_mcontext.gregs[14] = (uintptr_t) &__start_context;
argp = sp;
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++)
switch (i)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
ucp->uc_mcontext.gregs[i + 2] = va_arg (va, greg_t);
break;
default:
*argp++ = va_arg (va, greg_t);
break;
}
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);
@ -74,5 +62,7 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
ucp->uc_mcontext.gregs[15] = (uintptr_t) sp;
}
extern __typeof(__makecontext) makecontext __attribute__((weak, __alias__("__makecontext")));
#ifdef EXPORT_UNPREFIXED
extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2018, 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -12,16 +12,14 @@
#include "defs.h"
ALIAS(setcontext, libucontext_setcontext)
ALIAS(__setcontext, libucontext_setcontext)
.globl __setcontext;
__setcontext:
FUNC(libucontext_setcontext)
lgr %r1, %r2 /* use %r1 as our working register */
lam %a2, %a15, OFFSET_AREGS+8(%r1) /* load access registers, but skip %a0 and %a1 which are for TLS */
lmg %r0, %r15, OFFSET_GREGS(%r1) /* store general-purpose registers */
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 */
.weak setcontext;
setcontext = __setcontext;
END(libucontext_setcontext)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org>
* Copyright (c) 2018, 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -12,9 +12,8 @@
#include "defs.h"
.globl __start_context;
__start_context:
.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 */
@ -28,3 +27,4 @@ no_linked_context:
brasl %r14, exit@plt /* call exit */
j .+2 /* crash if exit returns */
END(libucontext_trampoline)

Some files were not shown because too many files have changed in this diff Show More