Compare commits
264 Commits
libucontex
...
master
Author | SHA1 | Date |
---|---|---|
Ariadne Conill | a0323579ac | |
Volker Christian | 302fbd7452 | |
Ariadne Conill | d64402737b | |
Ariadne Conill | c3d26b7940 | |
Ariadne Conill | e07c8d0ac5 | |
Ariadne Conill | ed663cf0e5 | |
Ariadne Conill | f593205e95 | |
Ariadne Conill | a65049c8d4 | |
Ariadne Conill | 828fc9e950 | |
Ariadne Conill | 3e5059e8a1 | |
Ariadne Conill | 570c0c8b32 | |
Ariadne Conill | 998ae99d61 | |
Ariadne Conill | c2a8b0a9d5 | |
Ariadne Conill | e603fd7239 | |
Ariadne Conill | c468c50b7b | |
Ariadne Conill | c1ecb0ea59 | |
Ariadne Conill | 5445f70157 | |
Ariadne Conill | 1a2dff93e7 | |
L. Pereira | 7badd2d5b2 | |
Jim Hauxwell | 4975ba9051 | |
Jim Hauxwell | b3cbfd9c1a | |
Sören Tempel | d0b03541bf | |
Volker Christian | 124a962b39 | |
Volker Christian | 9e5de65076 | |
Volker Christian | 076e69c9c1 | |
matoro | be80075e95 | |
Ariadne Conill | 4c2cfc54ac | |
L. Pereira | 0f625a86ee | |
Ismael Luceno | 8e1397f5a2 | |
Ariadne Conill | 33ff253d52 | |
Richard Campbell | 3044c2b908 | |
Ariadne Conill | 128e4fdc4b | |
Richard Campbell | 5244775fb9 | |
Richard Campbell | 9abcd8afe0 | |
Richard Campbell | 7bc3e90984 | |
Ariadne Conill | 4dde3417b4 | |
Ariadne Conill | 6ec3e63877 | |
Ariadne Conill | 69ebc5e51b | |
Ariadne Conill | 0a72eff002 | |
Ariadne Conill | 973e61441a | |
Ariadne Conill | 00128f7575 | |
Ariadne Conill | 7fc08a6dc6 | |
Ariadne Conill | e26a93806e | |
Ariadne Conill | 5d2f30f96a | |
Ariadne Conill | a51dce6e2c | |
Ariadne Conill | a5ed584aa8 | |
Ariadne Conill | 9943d4f5fc | |
Ariadne Conill | 9403b481bc | |
Ariadne Conill | 2c0c0e5d29 | |
Ariadne Conill | c8fe721e69 | |
Ariadne Conill | c50182d98c | |
Ariadne Conill | 55c91428ba | |
Ariadne Conill | 18aa732212 | |
Ariadne Conill | 8215aedb56 | |
Ariadne Conill | 8efa9e8b85 | |
Torrekie Gen | 6ddefbbbb4 | |
Ariadne Conill | b1b4fe9665 | |
Richard Campbell | 1e37bf30f9 | |
Ariadne Conill | 14d9859c00 | |
Richard Campbell | 06303df1cd | |
Ariadne Conill | ae058b1f38 | |
Peng Fan | a182fee66a | |
Ariadne Conill | 0108623531 | |
Khem Raj | a530eed9e7 | |
Ariadne Conill | 335ee864ef | |
Ariadne Conill | 4d8abf9b3b | |
Ariadne Conill | 7b8f3f6d04 | |
Ariadne Conill | fb1d203677 | |
Ariadne Conill | 1ad20e03e5 | |
Ariadne Conill | 464f98a01b | |
osy | 9b1d8f01a6 | |
osy | 5d66c194a7 | |
osy | f3e1b876c7 | |
Ariadne Conill | f04d423e63 | |
Leandro Pereira | 7823593b6f | |
Ariadne Conill | 7df60a2504 | |
Ariadne Conill | b757e1268c | |
Ariadne Conill | c4b5fedc1d | |
Ariadne Conill | 63b15f130a | |
Ariadne Conill | 98d7493b2a | |
Ariadne Conill | 9affe94dee | |
Daniel Kolesa | f3e0033a06 | |
Daniel Kolesa | 4801f0bdd8 | |
Daniel Kolesa | 739894e9a7 | |
Daniel Kolesa | efa6464e41 | |
osy | d592961b1a | |
Ariadne Conill | b1902729f7 | |
Ariadne Conill | 5546fde1e5 | |
Ariadne Conill | 09f78ddc28 | |
osy | fffb55011b | |
osy | f7eed30132 | |
Ariadne Conill | 3064ad6dbc | |
osy | 9983d136af | |
osy | d31c95a11a | |
Ariadne Conill | e4233715f3 | |
osy | 163c11d989 | |
osy | b6e60b5d64 | |
osy | 73d5e101ad | |
Ariadne Conill | e45956896a | |
osy | e1e6508af2 | |
Ariadne Conill | 638770cfd0 | |
Ariadne Conill | 78e880a29f | |
Ariadne Conill | 39a2958561 | |
Ariadne Conill | 5e6e421c54 | |
Ariadne Conill | 91c8837c93 | |
Daniel Kolesa | cf05112306 | |
Daniel Kolesa | 6026980cac | |
Daniel Kolesa | 03927d4c4c | |
Ariadne Conill | d81154a61c | |
Ariadne Conill | 11a40293be | |
Ariadne Conill | 6763b5ba1e | |
Ariadne Conill | c986ba340e | |
Ariadne Conill | 22b91690bc | |
Ariadne Conill | afcca79d7b | |
Ariadne Conill | a6a64b0711 | |
Ariadne Conill | 388edbe121 | |
Ariadne Conill | 3123bfdd9b | |
Ariadne Conill | b6542e1a6a | |
Ariadne Conill | b62ecd476c | |
Ariadne Conill | 09d3f81dcf | |
Ariadne Conill | 2d51d7bfa4 | |
Ariadne Conill | 71cbb6a3d3 | |
Ariadne Conill | 5c3ca5a7e1 | |
Ariadne Conill | 8d58adb3ba | |
Ariadne Conill | dd7ef8a806 | |
Ariadne Conill | f9a3f65f5b | |
Ariadne Conill | 82f734ab47 | |
Ariadne Conill | da3c8d170f | |
Ariadne Conill | a42fb86da0 | |
Ariadne Conill | 00261d70e8 | |
Ariadne Conill | fd06f42bc3 | |
Ariadne Conill | 2692ecf74a | |
Ariadne Conill | 42a4fbe9d1 | |
Ariadne Conill | de399ebdbf | |
Ariadne Conill | 4ea37b1877 | |
Ariadne Conill | 634145cc40 | |
Ariadne Conill | 04b5520a61 | |
Ariadne Conill | 2688747f8a | |
Ariadne Conill | ed1e5752fc | |
Ariadne Conill | 27d8a515e1 | |
Ariadne Conill | 045e622971 | |
Ariadne Conill | 4a91eacd41 | |
Ömer Faruk IRMAK | f2f46569e7 | |
Ariadne Conill | f0b5c0f7e1 | |
Ariadne Conill | 5cf38aeae8 | |
Ariadne Conill | bced874113 | |
Ariadne Conill | d64931ad4f | |
Ariadne Conill | cc2b4da24a | |
Ariadne Conill | a52354e640 | |
Ariadne Conill | be5b4c0cac | |
Ariadne Conill | 22bd490272 | |
Ariadne Conill | c10cde83da | |
Ariadne Conill | a04dc12d72 | |
Ariadne Conill | f3f52fc17c | |
Ariadne Conill | 7d149e6358 | |
Ariadne Conill | 20fd2b6f52 | |
Ariadne Conill | 0c6077854a | |
Ariadne Conill | 50bb9432c8 | |
Ariadne Conill | b33c7df219 | |
Ariadne Conill | da736b6add | |
Ariadne Conill | 131e825f50 | |
Ariadne Conill | 9c0ffd8fbb | |
Ariadne Conill | 83a109c2a7 | |
Ariadne Conill | 0566e66d2d | |
Ariadne Conill | 13f396f743 | |
Ariadne Conill | 9aef11752f | |
Ariadne Conill | 794b4f92aa | |
Ariadne Conill | 74121dfe75 | |
Ariadne Conill | e715cd2679 | |
Ariadne Conill | 1966a6b349 | |
Ariadne Conill | a8415a0c4e | |
Ariadne Conill | c31decc3d4 | |
Ariadne Conill | 40c8016144 | |
Ariadne Conill | ef632da18f | |
Ariadne Conill | e2636d542b | |
Ariadne Conill | 0953d71ed1 | |
Ariadne Conill | 2979186379 | |
Ariadne Conill | 11468c3e54 | |
Ariadne Conill | d44eba0b22 | |
Ariadne Conill | e65e485630 | |
Ariadne Conill | 37fe7afd5f | |
Ariadne Conill | 99ed5bbe12 | |
Ariadne Conill | 2f31efaa95 | |
Ariadne Conill | c693dc663c | |
Ariadne Conill | fe19127c66 | |
Ariadne Conill | 8b7cefd98d | |
Ariadne Conill | 0863bd891d | |
Ariadne Conill | 15ba7b039c | |
Ariadne Conill | 5f6135c0f9 | |
Ariadne Conill | 22520be2de | |
Ariadne Conill | 89536b198d | |
Ariadne Conill | c462af8a3c | |
Ariadne Conill | 76f1fd75b8 | |
Ariadne Conill | 5ee9c4e8a5 | |
Ariadne Conill | a6e76834d7 | |
Drew DeVault | 5928947223 | |
Ariadne Conill | ff858d8bdd | |
Ariadne Conill | b1ea2ae83b | |
Ariadne Conill | 34472b8884 | |
Ariadne Conill | 02470ccdd8 | |
Ariadne Conill | 938d0d5771 | |
Ariadne Conill | c3393695d2 | |
Ariadne Conill | e11fa34822 | |
Ariadne Conill | e9308ef58f | |
Ariadne Conill | e32eb6ef59 | |
Ariadne Conill | 4d42f482dc | |
Ariadne Conill | 19fa1bbfc2 | |
Khem Raj | b6732f6884 | |
Ariadne Conill | 272d682103 | |
A. Wilcox | 467ee2916d | |
Khem Raj | e2178de76a | |
Ariadne Conill | e040915105 | |
Ariadne Conill | 136ebdffd9 | |
Ariadne Conill | b784d75440 | |
A. Wilcox | d7688a41df | |
Ariadne Conill | e786bc9409 | |
Ariadne Conill | 1ee8d2f360 | |
Ariadne Conill | d7d746f44e | |
Ariadne Conill | ef42ad682a | |
Ariadne Conill | f708c95659 | |
Ariadne Conill | fb27ad693b | |
Ariadne Conill | b04da78fb8 | |
Ariadne Conill | 08e8a41d6c | |
Ariadne Conill | 3d40ad902a | |
Ariadne Conill | add34ddac7 | |
Ariadne Conill | 01432abb3e | |
Ariadne Conill | d0ccf2f96f | |
Ariadne Conill | d8cfe83e34 | |
Ariadne Conill | 8631580fbb | |
Ariadne Conill | e00902b5b1 | |
Ariadne Conill | 2411cdfb54 | |
Ariadne Conill | c385d69aa9 | |
Ariadne Conill | fd32a2fa8c | |
Ariadne Conill | 2f4eb16f38 | |
Ariadne Conill | 8536f1fa3b | |
Ariadne Conill | 87f58af294 | |
Ariadne Conill | 7c60f4576c | |
Ariadne Conill | e8115eb013 | |
Ariadne Conill | 80a6ca3854 | |
Ariadne Conill | f3a873e6e6 | |
Ariadne Conill | d696a0b692 | |
Ariadne Conill | d31eaabbaf | |
Ariadne Conill | 5f137a1fe4 | |
Khem Raj | 6cfab025e0 | |
Gabriel Ivașcu | acff6c83eb | |
William Pitcock | 0b4f9ecf33 | |
Gabriel Ivașcu | 2e15b38327 | |
William Pitcock | 05cb8ecbee | |
Gabriel Ivașcu | 9cc1a2c0e6 | |
William Pitcock | 7599fe5ff2 | |
Bobby Bingham | 2610c7faa7 | |
Bobby Bingham | 90ff6330e6 | |
Bobby Bingham | 29eac4259a | |
Bobby Bingham | edf69879ea | |
Bobby Bingham | 40d07758a5 | |
Bobby Bingham | a00a05ce29 | |
Bobby Bingham | 8ea5f548b9 | |
Bobby Bingham | 55168fcb18 | |
Bobby Bingham | b500b054c7 | |
Bobby Bingham | b9bd4045fb | |
Bobby Bingham | b6a9b5e279 | |
Bobby Bingham | cb59e7ee95 | |
Bobby Bingham | 94216c60c4 | |
A. Wilcox | 6046eb47e4 |
|
@ -1,38 +1,15 @@
|
||||||
# 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
|
|
||||||
|
|
||||||
*.o
|
*.o
|
||||||
|
examples/cooperative_threading
|
||||||
test_libucontext
|
test_libucontext
|
||||||
|
test_libucontext_posix
|
||||||
|
test_libucontext_bare_posixabi
|
||||||
|
libucontext.a
|
||||||
libucontext.so
|
libucontext.so
|
||||||
libucontext.so.*
|
libucontext.so.*
|
||||||
|
libucontext_posix.a
|
||||||
|
libucontext_posix.so
|
||||||
|
libucontext_posix.so.*
|
||||||
|
libucontext.pc
|
||||||
|
*.tar.xz
|
||||||
|
core
|
||||||
|
*.core
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Ariadne Conill <ariadne@dereferenced.org> <nenolod@dereferenced.org>
|
|
@ -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
|
2
LICENSE
2
LICENSE
|
@ -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
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
|
278
Makefile
278
Makefile
|
@ -1,48 +1,276 @@
|
||||||
|
SCDOC := scdoc
|
||||||
|
|
||||||
ARCH := $(shell uname -m)
|
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 = \
|
CFLAGS ?= -ggdb3 -O2 -Wall
|
||||||
arch/${ARCH}/makecontext.c
|
CPPFLAGS := -Iinclude -Iarch/${ARCH} -Iarch/common
|
||||||
|
ifneq ($(shell uname),Darwin)
|
||||||
|
EXPORT_UNPREFIXED := yes
|
||||||
|
else
|
||||||
|
# Darwin does not support aliases
|
||||||
|
EXPORT_UNPREFIXED := no
|
||||||
|
CPPFLAGS += -D_XOPEN_SOURCE
|
||||||
|
endif
|
||||||
|
FREESTANDING := no
|
||||||
|
|
||||||
LIBUCONTEXT_S_SRC = \
|
ifeq ($(FREESTANDING),yes)
|
||||||
arch/${ARCH}/getcontext.S \
|
CPPFLAGS += -DFREESTANDING
|
||||||
arch/${ARCH}/setcontext.S \
|
EXPORT_UNPREFIXED = no -Iarch/${ARCH}/include
|
||||||
arch/${ARCH}/swapcontext.S \
|
else
|
||||||
arch/${ARCH}/startcontext.S
|
CPPFLAGS += -Iarch/common/include
|
||||||
|
endif
|
||||||
|
|
||||||
|
# ARM hard float support is presently broken.
|
||||||
|
FORCE_SOFT_FLOAT := yes
|
||||||
|
|
||||||
|
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_OBJ = ${LIBUCONTEXT_C_SRC:.c=.o} ${LIBUCONTEXT_S_SRC:.S=.o}
|
||||||
LIBUCONTEXT_SOVERSION = 0
|
LIBUCONTEXT_SOVERSION = 1
|
||||||
LIBUCONTEXT_NAME = libucontext.so
|
ifeq ($(shell uname),Darwin)
|
||||||
LIBUCONTEXT_SONAME = libucontext.so.${LIBUCONTEXT_SOVERSION}
|
LIBUCONTEXT_NAME = libucontext.dylib
|
||||||
LIBUCONTEXT_PATH = /lib/${LIBUCONTEXT_SONAME}
|
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
|
||||||
|
ifeq ($(FREESTANDING),yes)
|
||||||
|
LIBUCONTEXT_HEADERS += arch/${ARCH}/include/libucontext/bits.h
|
||||||
|
else
|
||||||
|
LIBUCONTEXT_HEADERS += arch/common/include/libucontext/bits.h
|
||||||
|
endif
|
||||||
|
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
|
||||||
|
|
||||||
|
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_OBJ}
|
||||||
|
$(AR) rcs ${LIBUCONTEXT_STATIC_NAME} ${LIBUCONTEXT_OBJ}
|
||||||
|
|
||||||
${LIBUCONTEXT_NAME}: ${LIBUCONTEXT_OBJ}
|
${LIBUCONTEXT_NAME}: ${LIBUCONTEXT_OBJ}
|
||||||
$(CC) -o ${LIBUCONTEXT_NAME} -Wl,-soname,${LIBUCONTEXT_SONAME} \
|
$(CC) -fPIC -o ${LIBUCONTEXT_NAME} ${LIBUCONTEXT_LINKER_FLAGS} ${LIBUCONTEXT_OBJ} ${LDFLAGS}
|
||||||
-shared ${LIBUCONTEXT_OBJ}
|
|
||||||
|
|
||||||
${LIBUCONTEXT_SONAME}: ${LIBUCONTEXT_NAME}
|
${LIBUCONTEXT_SONAME}: ${LIBUCONTEXT_NAME}
|
||||||
ln -sf ${LIBUCONTEXT_NAME} ${LIBUCONTEXT_SONAME}
|
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:
|
.c.o:
|
||||||
$(CC) -std=c99 -D_BSD_SOURCE -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} -c -o $@ $<
|
$(CC) -std=gnu99 -D_DEFAULT_SOURCE -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} -c -o $@ $<
|
||||||
|
|
||||||
.S.o:
|
.S.o:
|
||||||
$(CC) -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} -c -o $@ $<
|
$(CC) -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} ${ASFLAGS} -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
${LIBUCONTEXT_NAME}_clean:
|
||||||
rm -f ${LIBUCONTEXT_NAME} ${LIBUCONTEXT_SONAME} ${LIBUCONTEXT_OBJ} test_libucontext
|
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}
|
||||||
|
|
||||||
|
${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: ${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: all
|
||||||
install -D -m755 ${LIBUCONTEXT_NAME} ${DESTDIR}/${LIBUCONTEXT_PATH}
|
install -D -m755 ${LIBUCONTEXT_NAME} ${DESTDIR}${LIBUCONTEXT_PATH}
|
||||||
ln -sf ${LIBUCONTEXT_SONAME} ${DESTDIR}/lib/${LIBUCONTEXT_NAME}
|
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_DEFAULT_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext -lucontext_posix
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(EXPORT_UNPREFIXED),yes)
|
||||||
|
check: check_libucontext_bare_posixabi
|
||||||
|
|
||||||
|
check_libucontext_bare_posixabi: test_libucontext_bare_posixabi ${LIBUCONTEXT_SONAME}
|
||||||
|
env LD_LIBRARY_PATH=$(shell pwd) ./test_libucontext_bare_posixabi
|
||||||
|
|
||||||
|
test_libucontext_bare_posixabi: test_libucontext_posix.c ${LIBUCONTEXT_NAME}
|
||||||
|
$(CC) -std=gnu99 -D_DEFAULT_SOURCE ${CFLAGS} ${CPPFLAGS} test_libucontext_posix.c -o $@ -L. -lucontext
|
||||||
|
endif
|
||||||
|
|
||||||
|
check_libucontext: test_libucontext ${LIBUCONTEXT_SONAME}
|
||||||
env LD_LIBRARY_PATH=$(shell pwd) ./test_libucontext
|
env LD_LIBRARY_PATH=$(shell pwd) ./test_libucontext
|
||||||
|
|
||||||
test_libucontext: test_libucontext.c ${LIBUCONTEXT_NAME}
|
check: check_libucontext
|
||||||
$(CC) -std=c99 -D_BSD_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext
|
|
||||||
|
|
||||||
.PHONY: check
|
test_libucontext: test_libucontext.c ${LIBUCONTEXT_NAME}
|
||||||
|
$(CC) -std=gnu99 -D_DEFAULT_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext
|
||||||
|
|
||||||
|
examples: ${LIBUCONTEXT_EXAMPLES}
|
||||||
|
examples/cooperative_threading: examples/cooperative_threading.c ${LIBUCONTEXT_NAME}
|
||||||
|
$(CC) -std=gnu99 -D_DEFAULT_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext
|
||||||
|
|
||||||
|
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
|
||||||
|
|
|
@ -0,0 +1,176 @@
|
||||||
|
Changes from 1.3.1 to 1.3.2
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
* Rewrite makecontext in C on LoongArch.
|
||||||
|
|
||||||
|
* Fix building x86 and loongarch64 variants on Meson.
|
||||||
|
Patch by Volker Christian.
|
||||||
|
|
||||||
|
Changes from 1.3 to 1.3.1
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
* Disable hard-float support on ARM by default.
|
||||||
|
|
||||||
|
* Fix up getcontext/swapcontext return values on LoongArch.
|
||||||
|
|
||||||
|
* Fix assembler warnings when building on LoongArch.
|
||||||
|
|
||||||
|
Changes from 1.2 to 1.3
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
* Fix up getcontext/swapcontext return values across a few ports.
|
||||||
|
Patches contributed for ARM and test suite by Volker Christian.
|
||||||
|
|
||||||
|
* Add support for hard-float on ARM.
|
||||||
|
Patches contributed by Richard Campbell.
|
||||||
|
|
||||||
|
* Align build system variables with those used by Automake.
|
||||||
|
Patch contributed by Ismael Luceno.
|
||||||
|
|
||||||
|
* Fix sporadic parallel build failures.
|
||||||
|
Patches contributed by Jim Hauxwell.
|
||||||
|
|
||||||
|
* Ensure frame pointers are omitted when using the C trampoline.
|
||||||
|
Patch contributed by Sören Tempel.
|
||||||
|
|
||||||
|
* Define _XOPEN_SOURCE when building on Darwin.
|
||||||
|
Patch contributed by L. Pereira.
|
||||||
|
|
||||||
|
* Add support for building the manpages with Meson.
|
||||||
|
Patch contributed by matoro.
|
||||||
|
|
||||||
|
* Migrate build from _BSD_SOURCE to _DEFAULT_SOURCE.
|
||||||
|
|
||||||
|
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.
|
94
README.md
94
README.md
|
@ -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
|
Notably, when combined with `gcompat`, it provides a fully compatible implementation of the ucontext
|
||||||
functions that are ABI compatible with glibc.
|
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
|
| Architecture | Works on musl | Syscall | Supports FREESTANDING | Common trampoline |
|
||||||
* x86_64
|
|--------------|---------------|---------|-----------------------|-------------------|
|
||||||
* armv6+ (`arm`)
|
| aarch64 | ✓ | | ✓ | ✓ |
|
||||||
* aarch64
|
| arm | ✓ | | ✓ | ✓ |
|
||||||
* s390x
|
| loongarch64 | ✓ | | ✓ | |
|
||||||
|
| m68k | ✓ | | ✓ | ✓ |
|
||||||
These archs require kernel assistance and use a syscall (the only assembly is the trampoline):
|
| mips | ✓ | | ✓ | |
|
||||||
|
| mips64 | ✓ | | ✓ | |
|
||||||
* ppc
|
| or1k | ✓ | | ✓ | ✓ |
|
||||||
* ppc64 (ELFv2 ABI spec only, ELFv1 not supported)
|
| ppc | ✓ | ✓ | | |
|
||||||
|
| ppc64 | ✓ | ✓ | | |
|
||||||
|
| riscv32 | ✓ | | ✓ | ✓ |
|
||||||
|
| riscv64 | ✓ | | ✓ | ✓ |
|
||||||
|
| s390x | ✓ | | ✓ | |
|
||||||
|
| sh | ✓ | | ✓ | ✓ |
|
||||||
|
| x86 | ✓ | | ✓ | |
|
||||||
|
| x86_64 | ✓ | | ✓ | ✓ |
|
||||||
|
|
||||||
|
|
||||||
## building
|
## building
|
||||||
|
@ -36,8 +46,60 @@ $ make ARCH=x86_64 check
|
||||||
$ make ARCH=x86_64 DESTDIR=out install
|
$ 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
|
* `FREESTANDING`: If this is set to `yes`, the system ucontext.h headers will not be used. Instead,
|
||||||
and bug reports to gcompat@lists.adelielinux.org.
|
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,11 +1,15 @@
|
||||||
#ifndef __ARCH_AARCH64_DEFS_H
|
#ifndef __ARCH_AARCH64_DEFS_H
|
||||||
#define __ARCH_AARCH64_DEFS_H
|
#define __ARCH_AARCH64_DEFS_H
|
||||||
|
|
||||||
#define REGSZ 8
|
#define REG_SZ (8)
|
||||||
#define R0_OFFSET 184
|
#define MCONTEXT_GREGS (184)
|
||||||
|
|
||||||
|
#define R0_OFFSET REG_OFFSET(0)
|
||||||
|
|
||||||
#define SP_OFFSET 432
|
#define SP_OFFSET 432
|
||||||
#define PC_OFFSET 440
|
#define PC_OFFSET 440
|
||||||
#define PSTATE_OFFSET 448
|
#define PSTATE_OFFSET 448
|
||||||
|
#define FPSIMD_CONTEXT_OFFSET 464
|
||||||
|
|
||||||
#ifndef FPSIMD_MAGIC
|
#ifndef FPSIMD_MAGIC
|
||||||
# define FPSIMD_MAGIC 0x46508001
|
# define FPSIMD_MAGIC 0x46508001
|
||||||
|
@ -15,4 +19,9 @@
|
||||||
# define ESR_MAGIC 0x45535201
|
# define ESR_MAGIC 0x45535201
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define FETCH_LINKPTR(dest) \
|
||||||
|
asm("mov %0, x19" : "=r" ((dest)))
|
||||||
|
|
||||||
|
#include "common-defs.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -12,27 +12,18 @@
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
.globl __getcontext;
|
ALIAS(getcontext, libucontext_getcontext)
|
||||||
__getcontext:
|
ALIAS(__getcontext, libucontext_getcontext)
|
||||||
str xzr, [x0, #R0_OFFSET + (0 * REGSZ)]
|
|
||||||
|
|
||||||
/* save GPRs */
|
.global PROC_NAME(libucontext_getcontext);
|
||||||
stp x0, x1, [x0, #R0_OFFSET + (0 * REGSZ)]
|
.align 2;
|
||||||
stp x2, x3, [x0, #R0_OFFSET + (2 * REGSZ)]
|
TYPE(libucontext_getcontext)
|
||||||
stp x4, x5, [x0, #R0_OFFSET + (4 * REGSZ)]
|
ENT(libucontext_getcontext)
|
||||||
stp x6, x7, [x0, #R0_OFFSET + (6 * REGSZ)]
|
PROC_NAME(libucontext_getcontext):
|
||||||
stp x8, x9, [x0, #R0_OFFSET + (8 * REGSZ)]
|
str xzr, [x0, #REG_OFFSET(0)]
|
||||||
stp x10, x11, [x0, #R0_OFFSET + (10 * REGSZ)]
|
|
||||||
stp x12, x13, [x0, #R0_OFFSET + (12 * REGSZ)]
|
/* save x2 and x3 for reuse */
|
||||||
stp x14, x15, [x0, #R0_OFFSET + (14 * REGSZ)]
|
stp x2, x3, [x0, #REG_OFFSET(2)]
|
||||||
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)]
|
|
||||||
|
|
||||||
/* save current program counter in link register */
|
/* save current program counter in link register */
|
||||||
str x30, [x0, #PC_OFFSET]
|
str x30, [x0, #PC_OFFSET]
|
||||||
|
@ -44,11 +35,32 @@ __getcontext:
|
||||||
/* save pstate */
|
/* save pstate */
|
||||||
str xzr, [x0, #PSTATE_OFFSET]
|
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]
|
||||||
|
|
||||||
|
/* save GPRs and return value 0 */
|
||||||
|
mov x2, x0
|
||||||
mov x0, #0
|
mov x0, #0
|
||||||
|
|
||||||
|
stp x0, x1, [x2, #REG_OFFSET(0)]
|
||||||
|
/* x2 and x3 have already been saved */
|
||||||
|
stp x4, x5, [x2, #REG_OFFSET(4)]
|
||||||
|
stp x6, x7, [x2, #REG_OFFSET(6)]
|
||||||
|
stp x8, x9, [x2, #REG_OFFSET(8)]
|
||||||
|
stp x10, x11, [x2, #REG_OFFSET(10)]
|
||||||
|
stp x12, x13, [x2, #REG_OFFSET(12)]
|
||||||
|
stp x14, x15, [x2, #REG_OFFSET(14)]
|
||||||
|
stp x16, x17, [x2, #REG_OFFSET(16)]
|
||||||
|
stp x18, x19, [x2, #REG_OFFSET(18)]
|
||||||
|
stp x20, x21, [x2, #REG_OFFSET(20)]
|
||||||
|
stp x22, x23, [x2, #REG_OFFSET(22)]
|
||||||
|
stp x24, x25, [x2, #REG_OFFSET(24)]
|
||||||
|
stp x26, x27, [x2, #REG_OFFSET(26)]
|
||||||
|
stp x28, x29, [x2, #REG_OFFSET(28)]
|
||||||
|
str x30, [x2, #REG_OFFSET(30)]
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
END(libucontext_getcontext)
|
||||||
|
|
||||||
.weak getcontext;
|
|
||||||
getcontext = __getcontext;
|
|
||||||
|
|
|
@ -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
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -10,21 +10,24 @@
|
||||||
* from the use of this software.
|
* from the use of this software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "defs.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
|
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 *sp;
|
||||||
unsigned long *regp;
|
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.sp = (uintptr_t) sp;
|
||||||
ucp->uc_mcontext.pc = (uintptr_t) func;
|
ucp->uc_mcontext.pc = (uintptr_t) func;
|
||||||
ucp->uc_mcontext.regs[19] = (uintptr_t) ucp->uc_link;
|
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);
|
va_start(va, argc);
|
||||||
|
|
||||||
|
@ -53,5 +56,7 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
|
||||||
va_end(va);
|
va_end(va);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EXPORT_UNPREFIXED
|
||||||
extern __typeof(__makecontext) makecontext __attribute__((weak, __alias__("__makecontext")));
|
extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
|
||||||
|
extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
|
||||||
|
#endif
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -12,36 +12,42 @@
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
.globl __setcontext;
|
ALIAS(setcontext, libucontext_setcontext)
|
||||||
__setcontext:
|
ALIAS(__setcontext, libucontext_setcontext)
|
||||||
|
|
||||||
|
.global PROC_NAME(libucontext_setcontext);
|
||||||
|
.align 2;
|
||||||
|
TYPE(libucontext_setcontext)
|
||||||
|
ENT(libucontext_setcontext)
|
||||||
|
PROC_NAME(libucontext_setcontext):
|
||||||
/* restore GPRs */
|
/* restore GPRs */
|
||||||
ldp x18, x19, [x0, #R0_OFFSET + (18 * REGSZ)]
|
ldp x18, x19, [x0, #REG_OFFSET(18)]
|
||||||
ldp x20, x21, [x0, #R0_OFFSET + (20 * REGSZ)]
|
ldp x20, x21, [x0, #REG_OFFSET(20)]
|
||||||
ldp x22, x23, [x0, #R0_OFFSET + (22 * REGSZ)]
|
ldp x22, x23, [x0, #REG_OFFSET(22)]
|
||||||
ldp x24, x25, [x0, #R0_OFFSET + (24 * REGSZ)]
|
ldp x24, x25, [x0, #REG_OFFSET(24)]
|
||||||
ldp x26, x27, [x0, #R0_OFFSET + (26 * REGSZ)]
|
ldp x26, x27, [x0, #REG_OFFSET(26)]
|
||||||
ldp x28, x29, [x0, #R0_OFFSET + (28 * REGSZ)]
|
ldp x28, x29, [x0, #REG_OFFSET(28)]
|
||||||
ldr x30, [x0, #R0_OFFSET + (30 * REGSZ)]
|
ldr x30, [x0, #REG_OFFSET(30)]
|
||||||
|
|
||||||
/* save current stack pointer */
|
/* save current stack pointer */
|
||||||
ldr x2, [x0, #SP_OFFSET]
|
ldr x2, [x0, #SP_OFFSET]
|
||||||
mov sp, x2
|
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 */
|
/* save current program counter in link register */
|
||||||
ldr x16, [x0, #PC_OFFSET]
|
ldr x16, [x0, #PC_OFFSET]
|
||||||
|
|
||||||
/* restore args */
|
/* restore args */
|
||||||
ldp x2, x3, [x0, #R0_OFFSET + (2 * REGSZ)]
|
ldp x2, x3, [x0, #REG_OFFSET(2)]
|
||||||
ldp x4, x5, [x0, #R0_OFFSET + (4 * REGSZ)]
|
ldp x4, x5, [x0, #REG_OFFSET(4)]
|
||||||
ldp x6, x7, [x0, #R0_OFFSET + (6 * REGSZ)]
|
ldp x6, x7, [x0, #REG_OFFSET(6)]
|
||||||
ldp x0, x1, [x0, #R0_OFFSET + (0 * REGSZ)]
|
ldp x0, x1, [x0, #REG_OFFSET(0)]
|
||||||
|
|
||||||
/* jump to new PC */
|
/* jump to new PC */
|
||||||
br x16
|
br x16
|
||||||
|
END(libucontext_setcontext)
|
||||||
|
|
||||||
.weak setcontext;
|
|
||||||
setcontext = __setcontext;
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -12,26 +12,32 @@
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
.globl __swapcontext;
|
ALIAS(swapcontext, libucontext_swapcontext)
|
||||||
__swapcontext:
|
ALIAS(__swapcontext, libucontext_swapcontext)
|
||||||
str xzr, [x0, #R0_OFFSET + (0 * REGSZ)]
|
|
||||||
|
.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 */
|
/* save GPRs */
|
||||||
stp x2, x3, [x0, #R0_OFFSET + (2 * REGSZ)]
|
stp x2, x3, [x0, #REG_OFFSET(2)]
|
||||||
stp x4, x5, [x0, #R0_OFFSET + (4 * REGSZ)]
|
stp x4, x5, [x0, #REG_OFFSET(4)]
|
||||||
stp x6, x7, [x0, #R0_OFFSET + (6 * REGSZ)]
|
stp x6, x7, [x0, #REG_OFFSET(6)]
|
||||||
stp x8, x9, [x0, #R0_OFFSET + (8 * REGSZ)]
|
stp x8, x9, [x0, #REG_OFFSET(8)]
|
||||||
stp x10, x11, [x0, #R0_OFFSET + (10 * REGSZ)]
|
stp x10, x11, [x0, #REG_OFFSET(10)]
|
||||||
stp x12, x13, [x0, #R0_OFFSET + (12 * REGSZ)]
|
stp x12, x13, [x0, #REG_OFFSET(12)]
|
||||||
stp x14, x15, [x0, #R0_OFFSET + (14 * REGSZ)]
|
stp x14, x15, [x0, #REG_OFFSET(14)]
|
||||||
stp x16, x17, [x0, #R0_OFFSET + (16 * REGSZ)]
|
stp x16, x17, [x0, #REG_OFFSET(16)]
|
||||||
stp x18, x19, [x0, #R0_OFFSET + (18 * REGSZ)]
|
stp x18, x19, [x0, #REG_OFFSET(18)]
|
||||||
stp x20, x21, [x0, #R0_OFFSET + (20 * REGSZ)]
|
stp x20, x21, [x0, #REG_OFFSET(20)]
|
||||||
stp x22, x23, [x0, #R0_OFFSET + (22 * REGSZ)]
|
stp x22, x23, [x0, #REG_OFFSET(22)]
|
||||||
stp x24, x25, [x0, #R0_OFFSET + (24 * REGSZ)]
|
stp x24, x25, [x0, #REG_OFFSET(24)]
|
||||||
stp x26, x27, [x0, #R0_OFFSET + (26 * REGSZ)]
|
stp x26, x27, [x0, #REG_OFFSET(26)]
|
||||||
stp x28, x29, [x0, #R0_OFFSET + (28 * REGSZ)]
|
stp x28, x29, [x0, #REG_OFFSET(28)]
|
||||||
str x30, [x0, #R0_OFFSET + (30 * REGSZ)]
|
str x30, [x0, #REG_OFFSET(30)]
|
||||||
|
|
||||||
/* save current program counter in link register */
|
/* save current program counter in link register */
|
||||||
str x30, [x0, #PC_OFFSET]
|
str x30, [x0, #PC_OFFSET]
|
||||||
|
@ -43,19 +49,21 @@ __swapcontext:
|
||||||
/* save pstate */
|
/* save pstate */
|
||||||
str xzr, [x0, #PSTATE_OFFSET]
|
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 */
|
/* context to swap to is in x1 so... we move to x0 and call setcontext */
|
||||||
/* store our link register in x28 */
|
/* store our link register in x28 */
|
||||||
mov x28, x30
|
mov x28, x30
|
||||||
|
|
||||||
/* move x1 to x0 and call setcontext */
|
/* move x1 to x0 and call setcontext */
|
||||||
mov x0, x1
|
mov x0, x1
|
||||||
bl __setcontext
|
bl PROC_NAME(libucontext_setcontext)
|
||||||
|
|
||||||
/* hmm, we came back here try to return */
|
/* hmm, we came back here try to return */
|
||||||
mov x30, x28
|
mov x30, x28
|
||||||
ret
|
ret
|
||||||
|
END(libucontext_swapcontext)
|
||||||
|
|
||||||
|
|
||||||
.weak swapcontext;
|
|
||||||
swapcontext = __swapcontext;
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
#include "defs.h"
|
||||||
|
#include <libucontext/libucontext.h>
|
||||||
|
#include "common-trampoline.c"
|
|
@ -0,0 +1,16 @@
|
||||||
|
#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 END(__proc)
|
||||||
|
|
||||||
|
#define FETCH_LINKPTR(dest) \
|
||||||
|
asm("movs %0, r4" : "=r" ((dest)))
|
||||||
|
|
||||||
|
#include "common-defs.h"
|
||||||
|
|
||||||
|
#endif
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -10,18 +10,40 @@
|
||||||
* from the use of this software.
|
* from the use of this software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.globl __getcontext;
|
#include "defs.h"
|
||||||
__getcontext:
|
|
||||||
|
ALIAS(getcontext, libucontext_getcontext)
|
||||||
|
ALIAS(__getcontext, libucontext_getcontext)
|
||||||
|
|
||||||
|
FUNC(libucontext_getcontext)
|
||||||
/* copy all of the current registers into the ucontext structure */
|
/* copy all of the current registers into the ucontext structure */
|
||||||
add r1, r0, #48
|
add r1, r0, #REG_OFFSET(4)
|
||||||
stmia r1, {r4-r12}
|
stmia r1, {r4-r12}
|
||||||
str r13, [r0,#84]
|
str r13, [r0, #REG_OFFSET(13)]
|
||||||
str r14, [r0,#92]
|
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 */
|
/* return 0 */
|
||||||
mov r0, #0
|
mov r0, #0
|
||||||
mov pc, lr
|
mov pc, lr
|
||||||
|
END(libucontext_getcontext)
|
||||||
|
|
||||||
.weak getcontext;
|
|
||||||
getcontext = __getcontext;
|
|
||||||
|
|
|
@ -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
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -10,20 +10,22 @@
|
||||||
* from the use of this software.
|
* from the use of this software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
extern void __start_context(void);
|
#include "defs.h"
|
||||||
|
#include <libucontext/libucontext.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern void libucontext_trampoline(void);
|
||||||
|
|
||||||
|
|
||||||
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 *sp;
|
||||||
unsigned long *regp;
|
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_sp = (uintptr_t) sp;
|
||||||
ucp->uc_mcontext.arm_pc = (uintptr_t) func;
|
ucp->uc_mcontext.arm_pc = (uintptr_t) func;
|
||||||
ucp->uc_mcontext.arm_r4 = (uintptr_t) ucp->uc_link;
|
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);
|
va_start(va, argc);
|
||||||
|
|
||||||
|
@ -52,14 +54,9 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
|
||||||
*sp++ = va_arg (va, unsigned long);
|
*sp++ = va_arg (va, unsigned long);
|
||||||
|
|
||||||
va_end(va);
|
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));
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EXPORT_UNPREFIXED
|
||||||
extern __typeof(__makecontext) makecontext __attribute__((weak, __alias__("__makecontext")));
|
extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
|
||||||
|
extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
|
||||||
|
#endif
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -10,17 +10,34 @@
|
||||||
* from the use of this software.
|
* from the use of this software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.globl __setcontext;
|
#include "defs.h"
|
||||||
__setcontext:
|
|
||||||
|
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 */
|
/* copy all of the current registers into the ucontext structure */
|
||||||
add r14, r0, #32
|
add r14, r0, #REG_OFFSET(0)
|
||||||
ldmia r14, {r0-r12}
|
ldmia r14, {r0-r12}
|
||||||
ldr r13, [r14, #52]
|
ldr r13, [r14, #52]
|
||||||
add r14, r14, #56
|
add r14, r14, #56
|
||||||
|
|
||||||
/* load link register and jump to new context */
|
/* load link register and jump to new context */
|
||||||
ldmia r14, {r14, pc}
|
ldmia r14, {r14, pc}
|
||||||
|
END(libucontext_setcontext)
|
||||||
|
|
||||||
.weak setcontext;
|
|
||||||
setcontext = __setcontext;
|
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -10,21 +10,44 @@
|
||||||
* from the use of this software.
|
* from the use of this software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.globl __swapcontext;
|
#include "defs.h"
|
||||||
__swapcontext:
|
|
||||||
/* copy all of the current registers into the ucontext structure */
|
ALIAS(swapcontext, libucontext_swapcontext)
|
||||||
add r2, r0, #32
|
ALIAS(__swapcontext, libucontext_swapcontext)
|
||||||
|
|
||||||
|
FUNC(libucontext_swapcontext)
|
||||||
|
#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
|
||||||
|
|
||||||
|
/* copy all of the current registers into the ucontext structure */
|
||||||
|
str r13, [r0,#REG_OFFSET(13)]
|
||||||
|
str r14, [r0,#REG_OFFSET(15)]
|
||||||
|
add r2, r0, #REG_OFFSET(0)
|
||||||
|
/* copy r0 with value 0 to indicate success (return value 0) */
|
||||||
|
mov r0, #0
|
||||||
stmia r2, {r0-r12}
|
stmia r2, {r0-r12}
|
||||||
str r13, [r0,#84]
|
|
||||||
str r14, [r0,#92]
|
|
||||||
|
|
||||||
/* load new registers from the second ucontext structure */
|
/* load new registers from the second ucontext structure */
|
||||||
add r14, r1, #32
|
add r14, r1, #REG_OFFSET(0)
|
||||||
ldmia r14, {r0-r12}
|
ldmia r14, {r0-r12}
|
||||||
ldr r13, [r14, #52]
|
ldr r13, [r14, #52]
|
||||||
add r14, r14, #56
|
add r14, r14, #56
|
||||||
ldmia r14, {r14, pc}
|
ldmia r14, {r14, pc}
|
||||||
|
END(libucontext_swapcontext)
|
||||||
|
|
||||||
.weak swapcontext;
|
|
||||||
swapcontext = __swapcontext;
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
#include "defs.h"
|
||||||
|
#include <libucontext/libucontext.h>
|
||||||
|
#include "common-trampoline.c"
|
|
@ -0,0 +1,64 @@
|
||||||
|
#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)
|
||||||
|
|
||||||
|
#ifndef END
|
||||||
|
#ifdef __clang__
|
||||||
|
#define END(__proc)
|
||||||
|
#else
|
||||||
|
#define END(__proc) \
|
||||||
|
.end __proc; \
|
||||||
|
.size __proc,.-__proc;
|
||||||
|
#endif
|
||||||
|
#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
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
|
||||||
|
/* We need to make sure that the C compiler doesn't push any
|
||||||
|
* additional data to the stack frame. Otherwise, assumptions
|
||||||
|
* made by the architecture-specific implementation of the
|
||||||
|
* FETCH_LINKPTR() macro about the location of the linkptr,
|
||||||
|
* relative to the stack pointer, will not hold.
|
||||||
|
*
|
||||||
|
* Hence, we compile this function with -fomit-frame-pointer
|
||||||
|
* and use the register storage-class specifier for all local
|
||||||
|
* vars. Note that the latter is just a "suggestion" (see C99).
|
||||||
|
*/
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("hidden")))
|
||||||
|
__attribute__ ((optimize ("omit-frame-pointer")))
|
||||||
|
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);
|
||||||
|
}
|
|
@ -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
|
|
@ -0,0 +1,82 @@
|
||||||
|
#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)
|
||||||
|
|
||||||
|
/* $s0 is $23 */
|
||||||
|
#define REG_S0 (23)
|
||||||
|
|
||||||
|
/* $ra is $1 */
|
||||||
|
#define REG_RA (1)
|
||||||
|
|
||||||
|
/* offset to mc_gregs in ucontext_t */
|
||||||
|
#define MCONTEXT_GREGS (184)
|
||||||
|
|
||||||
|
/* offset to PC in ucontext_t */
|
||||||
|
#define MCONTEXT_PC (176)
|
||||||
|
|
||||||
|
/* 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
|
|
@ -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
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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 $zero, $a0, REG_OFFSET(4)
|
||||||
|
st.d $a3, $a0, REG_OFFSET(22)
|
||||||
|
st.d $ra, $a0, REG_OFFSET(1)
|
||||||
|
|
||||||
|
st.d $ra, $a0, (MCONTEXT_PC)
|
||||||
|
|
||||||
|
move $a0, $zero
|
||||||
|
|
||||||
|
POP_FRAME(libucontext_getcontext)
|
||||||
|
|
||||||
|
jr $ra
|
||||||
|
END(libucontext_getcontext)
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 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] = (libucontext_greg_t) ucp->uc_link;
|
||||||
|
ucp->uc_mcontext.__gregs[REG_SP] = (libucontext_greg_t) sp;
|
||||||
|
ucp->uc_mcontext.__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
|
|
@ -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 $a0, $zero
|
||||||
|
|
||||||
|
POP_FRAME(libucontext_setcontext)
|
||||||
|
END(libucontext_setcontext)
|
|
@ -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)
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* 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 $zero, $t5, REG_OFFSET(4)
|
||||||
|
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 $a0, $zero
|
||||||
|
|
||||||
|
fail:
|
||||||
|
la.global $t8, exit
|
||||||
|
|
||||||
|
POP_FRAME(libucontext_swapcontext)
|
||||||
|
|
||||||
|
jirl $ra, $t8, 0
|
||||||
|
move $a0, $zero
|
||||||
|
END(libucontext_swapcontext)
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -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)
|
|
@ -0,0 +1,3 @@
|
||||||
|
#include "defs.h"
|
||||||
|
#include <libucontext/libucontext.h>
|
||||||
|
#include "common-trampoline.c"
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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
|
|
@ -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 /* link register */
|
||||||
|
l.sw REG_OFFSET(11)(r3), r0 /* return value is 0 */
|
||||||
|
|
||||||
|
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.ori r11, r0, 0
|
||||||
|
l.jr r9
|
||||||
|
END(libucontext_getcontext)
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -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 /* link register */
|
||||||
|
l.sw REG_OFFSET(11)(r3), r0 /* return value is zero */
|
||||||
|
|
||||||
|
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.ori r11, r0, 0
|
||||||
|
l.jr r9 /* jump to new starting address */
|
||||||
|
END(libucontext_swapcontext)
|
|
@ -0,0 +1,3 @@
|
||||||
|
#include "defs.h"
|
||||||
|
#include <libucontext/libucontext.h>
|
||||||
|
#include "common-trampoline.c"
|
|
@ -59,4 +59,6 @@
|
||||||
/* lnk register is actually r32 */
|
/* lnk register is actually r32 */
|
||||||
#define REG_LNK REG_R36
|
#define REG_LNK REG_R36
|
||||||
|
|
||||||
|
#include "common-defs.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -10,14 +10,13 @@
|
||||||
* from the use of this software.
|
* from the use of this software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.globl __start_context;
|
#include "common-defs.h"
|
||||||
.fnstart
|
|
||||||
.cantunwind
|
|
||||||
nop
|
|
||||||
__start_context:
|
|
||||||
/* get the proper context into position and test for NULL */
|
|
||||||
movs r0, r4
|
|
||||||
bne __setcontext@plt
|
|
||||||
|
|
||||||
/* we are returning into a null context, it seems, so maybe we should exit */
|
ALIAS(getcontext, libucontext_getcontext)
|
||||||
b exit@plt
|
ALIAS(__getcontext, libucontext_getcontext)
|
||||||
|
|
||||||
|
.hidden __libucontext_swapcontext
|
||||||
|
FUNC(libucontext_getcontext)
|
||||||
|
li 4, 0
|
||||||
|
b __libucontext_swapcontext@local
|
||||||
|
END(libucontext_getcontext)
|
|
@ -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")));
|
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -10,66 +11,51 @@
|
||||||
* from the use of this software.
|
* from the use of this software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
#include <libucontext/libucontext.h>
|
||||||
|
|
||||||
|
|
||||||
extern void __start_context(void);
|
extern void libucontext_trampoline(void);
|
||||||
|
|
||||||
|
|
||||||
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;
|
va_list va;
|
||||||
int i;
|
int i;
|
||||||
unsigned int uc_link, stack_args;
|
unsigned int stack_args;
|
||||||
|
|
||||||
stack_args = argc > 8 ? argc - 8 : 0;
|
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 = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
|
||||||
sp -= (uc_link + 1);
|
sp -= stack_args + 2;
|
||||||
sp = (greg_t *) (((uintptr_t) sp & -16L) - 8);
|
sp = (libucontext_greg_t *) ((uintptr_t) sp & -16L);
|
||||||
|
|
||||||
ucp->uc_mcontext.gregs[REG_NIP] = (uintptr_t) func;
|
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_R31] = (uintptr_t) ucp->uc_link;
|
||||||
ucp->uc_mcontext.gregs[REG_SP] = (uintptr_t) sp;
|
ucp->uc_mcontext.gregs[REG_SP] = (uintptr_t) sp;
|
||||||
|
|
||||||
sp[0] = (uintptr_t) &__start_context;
|
sp[0] = 0;
|
||||||
sp[uc_link] = (uintptr_t) ucp->uc_link;
|
|
||||||
argp = &sp[2];
|
|
||||||
|
|
||||||
va_start(va, argc);
|
va_start(va, argc);
|
||||||
|
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++) {
|
||||||
switch (i)
|
if (i < 8)
|
||||||
{
|
ucp->uc_mcontext.gregs[i + 3] = va_arg (va, libucontext_greg_t);
|
||||||
case 0:
|
else
|
||||||
case 1:
|
sp[i-8 + 2] = va_arg (va, libucontext_greg_t);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
va_end(va);
|
va_end(va);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EXPORT_UNPREFIXED
|
||||||
extern __typeof(__makecontext) makecontext __attribute__((weak, __alias__("__makecontext")));
|
extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
|
||||||
|
extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
|
||||||
|
#endif
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -10,11 +11,15 @@
|
||||||
* from the use of this software.
|
* from the use of this software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.globl __start_context;
|
#include <errno.h>
|
||||||
__start_context:
|
|
||||||
/* get the proper context into position and test for NULL */
|
__attribute__ ((visibility ("hidden")))
|
||||||
mov x0, x19
|
int __retfromsyscall(long retval)
|
||||||
cbnz x0, __setcontext
|
{
|
||||||
|
if (retval < 0) {
|
||||||
|
errno = -retval;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* something went wrong, exit */
|
|
||||||
b exit
|
|
|
@ -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)
|
|
@ -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")));
|
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -10,8 +10,10 @@
|
||||||
* from the use of this software.
|
* from the use of this software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.globl __start_context;
|
#include "common-defs.h"
|
||||||
__start_context:
|
|
||||||
|
.hidden libucontext_trampoline
|
||||||
|
FUNC(libucontext_trampoline)
|
||||||
/* get the proper context into position and test for NULL */
|
/* get the proper context into position and test for NULL */
|
||||||
mr. 3,31
|
mr. 3,31
|
||||||
|
|
||||||
|
@ -19,7 +21,8 @@ __start_context:
|
||||||
beq no_linked_context
|
beq no_linked_context
|
||||||
|
|
||||||
/* jump to setcontext */
|
/* jump to setcontext */
|
||||||
bl __setcontext@local
|
bl libucontext_setcontext@local
|
||||||
|
|
||||||
no_linked_context:
|
no_linked_context:
|
||||||
b exit@GOT
|
b exit@GOT
|
||||||
|
END(libucontext_trampoline)
|
||||||
|
|
|
@ -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)
|
|
@ -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")));
|
|
|
@ -62,4 +62,6 @@
|
||||||
/* lnk register is actually %r36 */
|
/* lnk register is actually %r36 */
|
||||||
#define REG_LNK REG_R36
|
#define REG_LNK REG_R36
|
||||||
|
|
||||||
|
#include "common-defs.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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)
|
|
@ -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")));
|
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -10,67 +11,52 @@
|
||||||
* from the use of this software.
|
* from the use of this software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
#include <libucontext/libucontext.h>
|
||||||
|
|
||||||
|
|
||||||
extern void __start_context(void);
|
extern void libucontext_trampoline(void);
|
||||||
|
|
||||||
|
|
||||||
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;
|
va_list va;
|
||||||
int i;
|
int i;
|
||||||
unsigned int uc_link, stack_args;
|
unsigned int stack_args;
|
||||||
|
|
||||||
stack_args = argc > 8 ? argc - 8 : 0;
|
stack_args = argc > 8 ? argc : 0;
|
||||||
uc_link = stack_args + 1;
|
|
||||||
|
|
||||||
sp = (greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
|
sp = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
|
||||||
sp -= (uc_link + 1);
|
sp -= stack_args + 4;
|
||||||
sp = (greg_t *) (((uintptr_t) sp & -16L));
|
sp = (libucontext_greg_t *) ((uintptr_t) sp & -16L);
|
||||||
|
|
||||||
ucp->uc_mcontext.gp_regs[REG_NIP] = (uintptr_t) func;
|
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_SP] = (uintptr_t) sp;
|
||||||
ucp->uc_mcontext.gp_regs[REG_ENTRY] = (uintptr_t) func;
|
ucp->uc_mcontext.gp_regs[REG_ENTRY] = (uintptr_t) func;
|
||||||
ucp->uc_mcontext.gp_regs[REG_R31] = (uintptr_t) ucp->uc_link;
|
ucp->uc_mcontext.gp_regs[REG_R31] = (uintptr_t) ucp->uc_link;
|
||||||
|
|
||||||
sp[0] = (uintptr_t) &__start_context;
|
sp[0] = 0;
|
||||||
sp[uc_link] = (uintptr_t) ucp->uc_link;
|
|
||||||
argp = &sp[2];
|
|
||||||
|
|
||||||
va_start(va, argc);
|
va_start(va, argc);
|
||||||
|
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++) {
|
||||||
switch (i)
|
if (i < 8)
|
||||||
{
|
ucp->uc_mcontext.gp_regs[i + 3] = va_arg (va, libucontext_greg_t);
|
||||||
case 0:
|
else
|
||||||
case 1:
|
sp[i + 4] = va_arg (va, libucontext_greg_t);
|
||||||
case 2:
|
}
|
||||||
case 3:
|
|
||||||
case 4:
|
|
||||||
case 5:
|
|
||||||
case 6:
|
|
||||||
case 7:
|
|
||||||
ucp->uc_mcontext.gp_regs[i + 3] = va_arg (va, greg_t);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*argp++ = va_arg (va, greg_t);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
va_end(va);
|
va_end(va);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EXPORT_UNPREFIXED
|
||||||
extern __typeof(__makecontext) makecontext __attribute__((weak, __alias__("__makecontext")));
|
extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
|
||||||
|
extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
|
||||||
|
#endif
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
|
@ -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")));
|
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -10,9 +10,10 @@
|
||||||
* from the use of this software.
|
* from the use of this software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.globl __start_context;
|
#include "common-defs.h"
|
||||||
.hidden __start_context;
|
|
||||||
__start_context:
|
.hidden libucontext_trampoline
|
||||||
|
FUNC(libucontext_trampoline)
|
||||||
cmpdi 31,0 /* test if ucontext link pointer is null */
|
cmpdi 31,0 /* test if ucontext link pointer is null */
|
||||||
beq no_linked_context /* if it is, exit */
|
beq no_linked_context /* if it is, exit */
|
||||||
|
|
||||||
|
@ -29,3 +30,4 @@ __start_context:
|
||||||
no_linked_context:
|
no_linked_context:
|
||||||
b exit@GOT
|
b exit@GOT
|
||||||
nop
|
nop
|
||||||
|
END(libucontext_trampoline)
|
||||||
|
|
|
@ -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)
|
|
@ -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")));
|
|
|
@ -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
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* 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 x0, REG_OFFSET(REG_A0)(a0)
|
||||||
|
sw x0, 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 */
|
||||||
|
mv a0, x0
|
||||||
|
ret
|
||||||
|
END(libucontext_getcontext)
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -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 x0, REG_OFFSET(REG_A0)(a0)
|
||||||
|
sw x0, 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)
|
|
@ -0,0 +1,3 @@
|
||||||
|
#include "defs.h"
|
||||||
|
#include <libucontext/libucontext.h>
|
||||||
|
#include "common-trampoline.c"
|
|
@ -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
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* 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 x0, REG_OFFSET(REG_A0)(a0)
|
||||||
|
sd x0, 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 */
|
||||||
|
mv a0, x0
|
||||||
|
ret
|
||||||
|
END(libucontext_getcontext)
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -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 x0, REG_OFFSET(REG_A0)(a0)
|
||||||
|
sd x0, 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)
|
|
@ -0,0 +1,3 @@
|
||||||
|
#include "defs.h"
|
||||||
|
#include <libucontext/libucontext.h>
|
||||||
|
#include "common-trampoline.c"
|
|
@ -1,8 +1,15 @@
|
||||||
#ifndef __ARCH_S390X_DEFS_H
|
#ifndef __ARCH_S390X_DEFS_H
|
||||||
#define __ARCH_S390X_DEFS_H
|
#define __ARCH_S390X_DEFS_H
|
||||||
|
|
||||||
#define OFFSET_GREGS (56)
|
#define REG_SZ (8)
|
||||||
#define OFFSET_AREGS (184)
|
#define AREG_SZ (4)
|
||||||
#define OFFSET_FPREGS (248)
|
|
||||||
|
#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
|
#endif
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -12,17 +12,15 @@
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
|
ALIAS(getcontext, libucontext_getcontext)
|
||||||
|
ALIAS(__getcontext, libucontext_getcontext)
|
||||||
|
|
||||||
.globl __getcontext;
|
FUNC(libucontext_getcontext)
|
||||||
__getcontext:
|
|
||||||
lgr %r1, %r2 /* use %r1 as our working register */
|
lgr %r1, %r2 /* use %r1 as our working register */
|
||||||
la %r2, 0 /* we will return 0 */
|
la %r2, 0 /* we will return 0 */
|
||||||
|
|
||||||
stam %a0, %a15, OFFSET_AREGS(%r1) /* store access registers */
|
stam %a0, %a15, AREG_OFFSET(0)(%r1) /* store access registers */
|
||||||
stmg %r0, %r15, OFFSET_GREGS(%r1) /* store general-purpose registers */
|
stmg %r0, %r15, REG_OFFSET(0)(%r1) /* store general-purpose registers */
|
||||||
|
|
||||||
br %r14 /* return to where we came from */
|
br %r14 /* return to where we came from */
|
||||||
|
END(libucontext_getcontext)
|
||||||
|
|
||||||
.weak getcontext;
|
|
||||||
getcontext = __getcontext;
|
|
||||||
|
|
|
@ -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
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -10,59 +10,47 @@
|
||||||
* from the use of this software.
|
* from the use of this software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
#include <libucontext/libucontext.h>
|
||||||
|
|
||||||
|
|
||||||
extern void __start_context(void);
|
extern void libucontext_trampoline(void);
|
||||||
extern int __setcontext(const ucontext_t *ucp);
|
extern int libucontext_setcontext(const libucontext_ucontext_t *ucp);
|
||||||
|
|
||||||
|
|
||||||
void
|
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;
|
va_list va;
|
||||||
int i;
|
int i;
|
||||||
unsigned int stack_args;
|
|
||||||
|
|
||||||
stack_args = argc > 5 ? argc - 5 : 0;
|
sp = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
|
||||||
|
sp = (libucontext_greg_t *) (((uintptr_t) sp & -8L));
|
||||||
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));
|
|
||||||
|
|
||||||
ucp->uc_mcontext.gregs[7] = (uintptr_t) func;
|
ucp->uc_mcontext.gregs[7] = (uintptr_t) func;
|
||||||
ucp->uc_mcontext.gregs[8] = (uintptr_t) ucp->uc_link;
|
ucp->uc_mcontext.gregs[8] = (uintptr_t) ucp->uc_link;
|
||||||
ucp->uc_mcontext.gregs[9] = (uintptr_t) &__setcontext;
|
ucp->uc_mcontext.gregs[9] = (uintptr_t) &libucontext_setcontext;
|
||||||
ucp->uc_mcontext.gregs[14] = (uintptr_t) &__start_context;
|
ucp->uc_mcontext.gregs[14] = (uintptr_t) &libucontext_trampoline;
|
||||||
|
|
||||||
argp = sp;
|
|
||||||
|
|
||||||
va_start(va, argc);
|
va_start(va, argc);
|
||||||
|
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc && i < 5; i++)
|
||||||
switch (i)
|
ucp->uc_mcontext.gregs[i + 2] = va_arg (va, libucontext_greg_t);
|
||||||
{
|
|
||||||
case 0:
|
if (argc > 5)
|
||||||
case 1:
|
{
|
||||||
case 2:
|
sp -= argc - 5;
|
||||||
case 3:
|
|
||||||
case 4:
|
for (i = 5; i < argc; i++)
|
||||||
case 5:
|
sp[i - 5] = va_arg (va, libucontext_greg_t);
|
||||||
ucp->uc_mcontext.gregs[i + 2] = va_arg (va, greg_t);
|
}
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*argp++ = va_arg (va, greg_t);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
|
||||||
|
@ -74,5 +62,7 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
|
||||||
ucp->uc_mcontext.gregs[15] = (uintptr_t) sp;
|
ucp->uc_mcontext.gregs[15] = (uintptr_t) sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EXPORT_UNPREFIXED
|
||||||
extern __typeof(__makecontext) makecontext __attribute__((weak, __alias__("__makecontext")));
|
extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
|
||||||
|
extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
|
||||||
|
#endif
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -12,16 +12,14 @@
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
|
ALIAS(setcontext, libucontext_setcontext)
|
||||||
|
ALIAS(__setcontext, libucontext_setcontext)
|
||||||
|
|
||||||
.globl __setcontext;
|
FUNC(libucontext_setcontext)
|
||||||
__setcontext:
|
|
||||||
lgr %r1, %r2 /* use %r1 as our working register */
|
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 */
|
lam %a2, %a15, AREG_OFFSET(2)(%r1) /* load access registers, but skip %a0 and %a1 which are for TLS */
|
||||||
lmg %r0, %r15, OFFSET_GREGS(%r1) /* store general-purpose registers */
|
lmg %r0, %r15, REG_OFFSET(0)(%r1) /* store general-purpose registers */
|
||||||
|
|
||||||
br %r14 /* return to new link register address */
|
br %r14 /* return to new link register address */
|
||||||
|
END(libucontext_setcontext)
|
||||||
|
|
||||||
.weak setcontext;
|
|
||||||
setcontext = __setcontext;
|
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -12,9 +12,8 @@
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
|
.hidden libucontext_trampoline
|
||||||
.globl __start_context;
|
FUNC(libucontext_trampoline)
|
||||||
__start_context:
|
|
||||||
basr %r14, %r7 /* run function pointer (%r7) and return here */
|
basr %r14, %r7 /* run function pointer (%r7) and return here */
|
||||||
ltgr %r8, %r8 /* check to see if uc_link (%r8) is null */
|
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 */
|
brasl %r14, exit@plt /* call exit */
|
||||||
|
|
||||||
j .+2 /* crash if exit returns */
|
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
Loading…
Reference in New Issue