aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-08-30 18:56:49 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-08-30 18:56:49 +0300
commit1a2e1fff7ce4b8fd8db46549d81e71e76b842da3 (patch)
treee33fa259bf9de49e589dd1e75a95dcd09ad3bc97
parentec30538a81c0e900797f4d88c1ee059afa7d9617 (diff)
downloadkmi-1a2e1fff7ce4b8fd8db46549d81e71e76b842da3.tar.gz
kmi-1a2e1fff7ce4b8fd8db46549d81e71e76b842da3.zip
add some basic benchmarks
-rw-r--r--Makefile12
-rw-r--r--benchmarks/Makefile16
-rw-r--r--benchmarks/benchmarks.mk52
l---------benchmarks/common1
-rw-r--r--benchmarks/create/init.c27
-rw-r--r--benchmarks/create/source.mk1
-rw-r--r--benchmarks/fork/init.c27
-rw-r--r--benchmarks/fork/source.mk1
-rw-r--r--benchmarks/ipc-req/init.c24
-rw-r--r--benchmarks/ipc-req/source.mk1
-rw-r--r--benchmarks/malloc/init.c22
-rw-r--r--benchmarks/malloc/source.mk1
-rwxr-xr-xbenchmarks/scripts/gen-benchmark32
-rw-r--r--benchmarks/scripts/makefile47
-rw-r--r--tests/common/benchmark.h17
-rw-r--r--tests/common/printf.c5
-rw-r--r--tests/common/printf.h8
-rw-r--r--tests/common/start.h9
-rw-r--r--tests/common/sys.h320
-rw-r--r--tests/common/test.h323
20 files changed, 625 insertions, 321 deletions
diff --git a/Makefile b/Makefile
index 0eae957..d2f6325 100644
--- a/Makefile
+++ b/Makefile
@@ -6,6 +6,10 @@ all: setup
check: all
$(MAKE) -C tests check
+.PHONY: benchmark
+benchmark: all
+ $(MAKE) -C benchmarks benchmark
+
# this kicks all unrecognised targets to the client script.
# note that trying to compile individual files, e.g.
#
@@ -58,6 +62,14 @@ clean:
$(MAKE) -C tests clean
$(RM) -rf $(CLEANUP)
+.PHONY: clean_tests
+clean_tests:
+ $(MAKE) -C tests clean
+
+.PHONY: clean_benchmarks
+clean_benchmarks:
+ $(MAKE) -C benchmarks clean
+
.PHONY: clean_run
clean_run:
$(CLEANUP_CMD)
diff --git a/benchmarks/Makefile b/benchmarks/Makefile
new file mode 100644
index 0000000..79e1afd
--- /dev/null
+++ b/benchmarks/Makefile
@@ -0,0 +1,16 @@
+.PHONY: benchmark
+benchmark:
+ $(MAKE) -f scripts/makefile benchmark
+
+.DEFAULT:
+ $(MAKE) -f scripts/makefile $<
+
+SOURCES != echo */source.mk
+DO != echo -n > benchmarks.mk
+include $(SOURCES)
+
+RM ?= rm
+
+.PHONY: clean
+clean:
+ $(RM) -rf build
diff --git a/benchmarks/benchmarks.mk b/benchmarks/benchmarks.mk
new file mode 100644
index 0000000..6b29504
--- /dev/null
+++ b/benchmarks/benchmarks.mk
@@ -0,0 +1,52 @@
+build/create/init.o.d:
+-include build/create/init.o.d
+build/create/init.o: create/
+ mkdir -p build/create
+ $(COMPILE_BENCHMARK) -c create/init.c -o build/create/init.o
+build/create/initrd: build/create/init.o $(COMMON)
+ $(COMPILE_BENCHMARK) build/create/init.o $(COMMON) -o build/create/init
+ echo build/create/init | $(GEN_INITRD) build/create/initrd
+BENCHMARKS += create
+.PHONY: create
+create: build/create/initrd
+ mkdir -p reports/create
+ timeout --foreground 30s $(QEMU) build/create/initrd > reports/create/log
+build/fork/init.o.d:
+-include build/fork/init.o.d
+build/fork/init.o: fork/
+ mkdir -p build/fork
+ $(COMPILE_BENCHMARK) -c fork/init.c -o build/fork/init.o
+build/fork/initrd: build/fork/init.o $(COMMON)
+ $(COMPILE_BENCHMARK) build/fork/init.o $(COMMON) -o build/fork/init
+ echo build/fork/init | $(GEN_INITRD) build/fork/initrd
+BENCHMARKS += fork
+.PHONY: fork
+fork: build/fork/initrd
+ mkdir -p reports/fork
+ timeout --foreground 30s $(QEMU) build/fork/initrd > reports/fork/log
+build/ipc-req/init.o.d:
+-include build/ipc-req/init.o.d
+build/ipc-req/init.o: ipc-req/
+ mkdir -p build/ipc-req
+ $(COMPILE_BENCHMARK) -c ipc-req/init.c -o build/ipc-req/init.o
+build/ipc-req/initrd: build/ipc-req/init.o $(COMMON)
+ $(COMPILE_BENCHMARK) build/ipc-req/init.o $(COMMON) -o build/ipc-req/init
+ echo build/ipc-req/init | $(GEN_INITRD) build/ipc-req/initrd
+BENCHMARKS += ipc-req
+.PHONY: ipc-req
+ipc-req: build/ipc-req/initrd
+ mkdir -p reports/ipc-req
+ timeout --foreground 30s $(QEMU) build/ipc-req/initrd > reports/ipc-req/log
+build/malloc/init.o.d:
+-include build/malloc/init.o.d
+build/malloc/init.o: malloc/
+ mkdir -p build/malloc
+ $(COMPILE_BENCHMARK) -c malloc/init.c -o build/malloc/init.o
+build/malloc/initrd: build/malloc/init.o $(COMMON)
+ $(COMPILE_BENCHMARK) build/malloc/init.o $(COMMON) -o build/malloc/init
+ echo build/malloc/init | $(GEN_INITRD) build/malloc/initrd
+BENCHMARKS += malloc
+.PHONY: malloc
+malloc: build/malloc/initrd
+ mkdir -p reports/malloc
+ timeout --foreground 30s $(QEMU) build/malloc/initrd > reports/malloc/log
diff --git a/benchmarks/common b/benchmarks/common
new file mode 120000
index 0000000..7d2aca5
--- /dev/null
+++ b/benchmarks/common
@@ -0,0 +1 @@
+../tests/common \ No newline at end of file
diff --git a/benchmarks/create/init.c b/benchmarks/create/init.c
new file mode 100644
index 0000000..7254296
--- /dev/null
+++ b/benchmarks/create/init.c
@@ -0,0 +1,27 @@
+#include <common/benchmark.h>
+
+void callback()
+{
+ sys_exit(1);
+}
+
+START(pid, tid, d0, d1, d2, d3)
+{
+ UNUSED(pid);
+ UNUSED(tid);
+ UNUSED(d0);
+ UNUSED(d1);
+ UNUSED(d2);
+ UNUSED(d3);
+
+ uint64_t timebase = sys_timebase();
+ uint64_t start = sys_ticks();
+
+ for (size_t i = 0; i < 1000; ++i) {
+ id_t new_id = sys_create((uintptr_t)callback, 0, 0, 0, 0);
+ sys_swap(new_id);
+ }
+
+ uint64_t end = sys_ticks();
+ report(start, end, timebase);
+}
diff --git a/benchmarks/create/source.mk b/benchmarks/create/source.mk
new file mode 100644
index 0000000..0377337
--- /dev/null
+++ b/benchmarks/create/source.mk
@@ -0,0 +1 @@
+DO != ./scripts/gen-benchmark -n create
diff --git a/benchmarks/fork/init.c b/benchmarks/fork/init.c
new file mode 100644
index 0000000..95f6466
--- /dev/null
+++ b/benchmarks/fork/init.c
@@ -0,0 +1,27 @@
+#include <common/benchmark.h>
+
+START(pid, tid, d0, d1, d2, d3)
+{
+ UNUSED(pid);
+ UNUSED(tid);
+ UNUSED(d0);
+ UNUSED(d1);
+ UNUSED(d2);
+ UNUSED(d3);
+
+ uint64_t timebase = sys_timebase();
+ uint64_t start = sys_ticks();
+
+ for (size_t i = 0; i < 1000; ++i) {
+ id_t our_tid = 0;
+ id_t new_id = sys_fork(&our_tid);
+ if (new_id == 0) {
+ /* child instantly dies */
+ sys_exit(1);
+ }
+ sys_swap(new_id);
+ }
+
+ uint64_t end = sys_ticks();
+ report(start, end, timebase);
+}
diff --git a/benchmarks/fork/source.mk b/benchmarks/fork/source.mk
new file mode 100644
index 0000000..46bde60
--- /dev/null
+++ b/benchmarks/fork/source.mk
@@ -0,0 +1 @@
+DO != ./scripts/gen-benchmark -n fork
diff --git a/benchmarks/ipc-req/init.c b/benchmarks/ipc-req/init.c
new file mode 100644
index 0000000..02064a6
--- /dev/null
+++ b/benchmarks/ipc-req/init.c
@@ -0,0 +1,24 @@
+#include <common/benchmark.h>
+
+START(pid, tid, d0, d1, d2, d3)
+{
+ UNUSED(tid);
+ UNUSED(d0);
+ UNUSED(d1);
+ UNUSED(d2);
+ UNUSED(d3);
+
+ if (pid == 0) {
+ uint64_t timebase = sys_timebase();
+ uint64_t start = sys_ticks();
+
+ for (size_t i = 0; i < 1000; ++i)
+ sys_ipc_req0(1);
+
+ uint64_t end = sys_ticks();
+ report(start, end, timebase);
+ }
+ else if (pid == 1) {
+ sys_ipc_resp0();
+ }
+}
diff --git a/benchmarks/ipc-req/source.mk b/benchmarks/ipc-req/source.mk
new file mode 100644
index 0000000..21dc0e0
--- /dev/null
+++ b/benchmarks/ipc-req/source.mk
@@ -0,0 +1 @@
+DO != ./scripts/gen-benchmark -n ipc-req
diff --git a/benchmarks/malloc/init.c b/benchmarks/malloc/init.c
new file mode 100644
index 0000000..d58eeb2
--- /dev/null
+++ b/benchmarks/malloc/init.c
@@ -0,0 +1,22 @@
+#include <common/benchmark.h>
+
+START(pid, tid, d0, d1, d2, d3)
+{
+ UNUSED(pid);
+ UNUSED(tid);
+ UNUSED(d0);
+ UNUSED(d1);
+ UNUSED(d2);
+ UNUSED(d3);
+
+ uint64_t timebase = sys_timebase();
+ uint64_t start = sys_ticks();
+
+ for (size_t i = 0; i < 1000; ++i) {
+ void *p = sys_req_mem(1, VM_R | VM_W);
+ sys_free_mem((uintptr_t)p);
+ }
+
+ uint64_t end = sys_ticks();
+ report(start, end, timebase);
+}
diff --git a/benchmarks/malloc/source.mk b/benchmarks/malloc/source.mk
new file mode 100644
index 0000000..3367314
--- /dev/null
+++ b/benchmarks/malloc/source.mk
@@ -0,0 +1 @@
+DO != ./scripts/gen-benchmark -n malloc
diff --git a/benchmarks/scripts/gen-benchmark b/benchmarks/scripts/gen-benchmark
new file mode 100755
index 0000000..459040d
--- /dev/null
+++ b/benchmarks/scripts/gen-benchmark
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+NAME=
+while getopts "n:p:" opt; do
+ case "$opt" in
+ n) NAME="$OPTARG";;
+ *) echo "unrecognised options -$OPTARG" >&2; exit 1;
+ esac
+done
+
+obj="build/${NAME}/init.o"
+dep="${obj}.d"
+
+echo "${dep}:" >> benchmarks.mk
+echo "-include ${dep}" >> benchmarks.mk
+echo "${obj}: $NAME/${s}" >> benchmarks.mk
+echo " mkdir -p build/$NAME" >> benchmarks.mk
+echo " \$(COMPILE_BENCHMARK) -c $NAME/init.c -o ${obj}" >> benchmarks.mk
+
+echo "build/${NAME}/initrd: ${obj} \$(COMMON)" >> benchmarks.mk
+echo " \$(COMPILE_BENCHMARK) ${obj} \
+ \$(COMMON) -o build/${NAME}/init" >> benchmarks.mk
+
+echo " echo build/${NAME}/init | \
+ \$(GEN_INITRD) build/${NAME}/initrd" >> benchmarks.mk
+
+echo "BENCHMARKS += ${NAME}" >> benchmarks.mk
+echo ".PHONY: ${NAME}" >> benchmarks.mk
+echo "${NAME}: build/${NAME}/initrd" >> benchmarks.mk
+echo " mkdir -p reports/${NAME}" >> benchmarks.mk
+echo " timeout --foreground 30s \
+ \$(QEMU) build/${NAME}/initrd > reports/${NAME}/log" >> benchmarks.mk
diff --git a/benchmarks/scripts/makefile b/benchmarks/scripts/makefile
new file mode 100644
index 0000000..7140c05
--- /dev/null
+++ b/benchmarks/scripts/makefile
@@ -0,0 +1,47 @@
+.PHONY: all
+all: benchmark
+
+ARCH ?= riscv64
+CROSS_COMPILE ?= $(ARCH)-unknown-elf-
+
+LLVM ?= 0
+COMPILER != [ "$(LLVM)" != "0" ] \
+ && echo clang --target="$(CROSS_COMPILE)" \
+ || echo $(CROSS_COMPILE)gcc
+
+include common/arch/$(ARCH)/source.mk
+
+OBFLAGS := -ffreestanding -nostdlib -std=c17 -g -O2
+INCLUDEFLAGS := -I ../include -I.
+WARNFLAGS := -Wall -Wextra
+DEPFLAGS = -MT $@ -MMD -MP -MF $@.d
+COMPILE_BENCHMARK = $(COMPILER) $(WARNFLAGS) $(INCLUDEFLAGS) \
+ $(DEPFLAGS) $(OBFLAGS) $(ARCH_FLAGS)
+
+GEN_INITRD := cpio -H newc -o >
+
+# icount gives a rough approximation of how many instructions are executed, but
+# *actual* performance would still have to be measured on real systems
+QEMU := qemu-system-$(ARCH) -machine virt -kernel ../kmi.bin \
+ -serial stdio \
+ -monitor none \
+ -nographic \
+ -no-reboot \
+ -m 128M \
+ -icount 0 \
+ -initrd
+
+KMI := ../kmi.bin
+COMMON := build/printf.o
+
+build/printf.o: common/printf.c $(KMI)
+ $(COMPILE_BENCHMARK) -c common/printf.c -o build/printf.o
+
+BENCHMARKS :=
+include benchmarks.mk
+
+.PHONY: benchmark
+benchmark: $(BENCHMARKS)
+ @cd reports; for d in * ; do \
+ printf "%8s: " "$$d"; tail -n 1 $$d/log | tr -d '\r' | bc -l; \
+ done
diff --git a/tests/common/benchmark.h b/tests/common/benchmark.h
new file mode 100644
index 0000000..d3ed6eb
--- /dev/null
+++ b/tests/common/benchmark.h
@@ -0,0 +1,17 @@
+#ifndef KMI_BENCHMARK_H
+#define KMI_BENCHMARK_H
+
+#include "sys.h"
+#include "start.h"
+#include "printf.h"
+
+#define exit() sys_poweroff(SYS_SHUTDOWN)
+#define report(start, end, timebase)\
+ do {\
+ printf("%lld / %lld\n", \
+ (long long unsigned)((end) - (start)), \
+ (long long unsigned)(timebase)); \
+ exit();\
+ } while (0)
+
+#endif /* KMI_BENCHMARK_H */
diff --git a/tests/common/printf.c b/tests/common/printf.c
index 0ad084b..7e7451a 100644
--- a/tests/common/printf.c
+++ b/tests/common/printf.c
@@ -1,5 +1,8 @@
#include <stdarg.h>
-#include "test.h"
+#include <kmi/types.h>
+
+#include "printf.h"
+#include "sys.h"
/* Directly copied from src/debug.c, which was copied from
* https://github.com/mpaland/printf/blob/master/printf.c
diff --git a/tests/common/printf.h b/tests/common/printf.h
new file mode 100644
index 0000000..b6e50e5
--- /dev/null
+++ b/tests/common/printf.h
@@ -0,0 +1,8 @@
+#ifndef KMI_PRINTF_H
+#define KMI_PRINTF_H
+
+#include <kmi/attrs.h>
+
+int printf(const char *fmt, ...) __printf;
+
+#endif /* KMI_PRINTF_H */
diff --git a/tests/common/start.h b/tests/common/start.h
new file mode 100644
index 0000000..3a49686
--- /dev/null
+++ b/tests/common/start.h
@@ -0,0 +1,9 @@
+#ifndef KMI_START_H
+#define KMI_START_H
+
+#define UNUSED(x) (void)x
+#define START(pid, tid, d0, d1, d2, d3)\
+void _start(sys_arg_t pid, sys_arg_t tid,\
+ sys_arg_t d0, sys_arg_t d1, sys_arg_t d2, sys_arg_t d3)
+
+#endif /* KMI_START_H */
diff --git a/tests/common/sys.h b/tests/common/sys.h
new file mode 100644
index 0000000..6d5e493
--- /dev/null
+++ b/tests/common/sys.h
@@ -0,0 +1,320 @@
+#ifndef KMI_SYS_H
+#define KMI_SYS_H
+
+#include <kmi/types.h>
+
+#if defined(__riscv)
+# if __riscv_xlen == 64
+#include "arch/riscv64/syscall.h"
+# endif
+#endif
+
+#define syscall0(op) syscall(1, op, 0, 0, 0, 0, 0)
+#define syscall1(op, a0) syscall(2, op, a0, 0, 0, 0, 0)
+#define syscall2(op, a0, a1) syscall(3, op, a0, a1, 0, 0, 0)
+#define syscall3(op, a0, a1, a2) syscall(4, op, a0, a1, a2, 0, 0)
+#define syscall4(op, a0, a1, a2, a3) syscall(5, op, a0, a1, a2, a3, 0)
+#define syscall5(op, a0, a1, a2, a3, a4) syscall(6, op, a0, a1, a2, a3, a4)
+
+static inline void sys_noop()
+{
+ syscall0(SYS_NOOP);
+}
+
+static inline void sys_putch(char c)
+{
+ syscall1(SYS_PUTCH, c);
+}
+
+static inline void *sys_req_mem(size_t size, vmflags_t flags)
+{
+ struct sys_ret r = syscall2(SYS_REQ_MEM, size, flags);
+ if (r.s)
+ return NULL;
+
+ return (void *)r.a0;
+}
+
+static inline void *sys_req_fixmem(uintptr_t fixed, size_t size, vmflags_t flags)
+{
+ struct sys_ret r = syscall3(SYS_REQ_FIXMEM, fixed, size, flags);
+ if (r.s)
+ return NULL;
+
+ return (void *)r.a0;
+}
+
+static inline void *sys_req_pmem(uintptr_t addr, size_t size, vmflags_t flags)
+{
+ struct sys_ret r = syscall3(SYS_REQ_PMEM, addr, size, flags);
+ if (r.s)
+ return NULL;
+
+ return (void *)r.a0;
+}
+
+static inline void *sys_req_page(size_t size, vmflags_t flags, uintptr_t *addr, size_t *asize)
+{
+ struct sys_ret r = syscall2(SYS_REQ_PAGE, size, flags);
+ if (r.s)
+ return NULL;
+
+ if (addr)
+ *addr = r.a1;
+
+ if (asize)
+ *asize = r.a2;
+
+ return (void *)r.a0;
+}
+
+static inline void *sys_req_sharedmem(size_t size, vmflags_t flags)
+{
+ struct sys_ret r = syscall2(SYS_REQ_SHAREDMEM, size, flags);
+ if (r.s)
+ return NULL;
+
+ return (void *)r.a0;
+}
+
+static inline void *sys_ref_sharedmem(id_t tid, uintptr_t addr, vmflags_t flags)
+{
+ struct sys_ret r = syscall3(SYS_REF_SHAREDMEM, tid, addr, flags);
+ if (r.s)
+ return NULL;
+
+ return (void *)r.a0;
+}
+
+static inline void sys_free_mem(uintptr_t start)
+{
+ syscall1(SYS_FREE_MEM, start);
+}
+
+static inline uint64_t sys_timebase()
+{
+ struct sys_ret r = syscall0(SYS_TIMEBASE);
+ if (r.s)
+ return 0;
+
+#if defined(_LP64)
+ return r.a0;
+#else
+ return ((uint64_t)r.a1 << 32) | r.a0
+#endif
+}
+
+static inline uint64_t sys_ticks()
+{
+ struct sys_ret r = syscall0(SYS_TICKS);
+ if (r.s)
+ return 0;
+
+#if defined(_LP64)
+ return r.a0;
+#else
+ return ((uint64_t)r.a1 << 32) | r.a0;
+#endif
+}
+
+static inline id_t sys_req_rel_timer(uint64_t ticks)
+{
+ struct sys_ret r;
+#if defined(_LP64)
+ r = syscall2(SYS_REQ_REL_TIMER, ticks >> 32, ticks);
+#else
+ r = syscall1(SYS_REQ_REL_TIMER, ticks);
+#endif
+
+ if (r.s)
+ return -1;
+
+ return r.a0;
+}
+
+static inline id_t sys_req_abs_timer(uint64_t ticks)
+{
+ struct sys_ret r;
+#if defined(_LP64)
+ r = syscall2(SYS_REQ_ABS_TIMER, ticks >> 32, ticks);
+#else
+ r = syscall1(SYS_REQ_ABS_TIMER, ticks);
+#endif
+
+ if (r.s)
+ return -1;
+
+ return r.a0;
+}
+
+#define sys_ipc_req0(pid) syscall1(SYS_IPC_REQ, pid)
+#define sys_ipc_req1(pid, d0) syscall2(SYS_IPC_REQ, pid, d0)
+#define sys_ipc_req2(pid, d0, d1) syscall3(SYS_IPC_REQ, pid, d0, d1)
+#define sys_ipc_req3(pid, d0, d1, d2) syscall4(SYS_IPC_REQ, pid, d0, d1, d2)
+#define sys_ipc_req4(pid, d0, d1, d2, d3) syscall5(SYS_IPC_REQ, pid, d0, d1, d2, d3)
+
+#define sys_ipc_fwd0(pid) syscall1(SYS_IPC_FWD, pid)
+#define sys_ipc_fwd1(pid, d0) syscall2(SYS_IPC_FWD, pid, d0)
+#define sys_ipc_fwd2(pid, d0, d1) syscall3(SYS_IPC_FWD, pid, d0, d1)
+#define sys_ipc_fwd3(pid, d0, d1, d2) syscall4(SYS_IPC_FWD, pid, d0, d1, d2)
+#define sys_ipc_fwd4(pid, d0, d1, d2, d3) syscall5(SYS_IPC_FWD, pid, d0, d1, d2, d3)
+
+#define sys_ipc_tail0(pid) syscall1(SYS_IPC_TAIL, pid)
+#define sys_ipc_tail1(pid, d0) syscall2(SYS_IPC_TAIL, pid, d0)
+#define sys_ipc_tail2(pid, d0, d1) syscall3(SYS_IPC_TAIL, pid, d0, d1)
+#define sys_ipc_tail3(pid, d0, d1, d2) syscall4(SYS_IPC_TAIL, pid, d0, d1, d2)
+#define sys_ipc_tail4(pid, d0, d1, d2, d3) syscall5(SYS_IPC_TAIL, pid, d0, d1, d2, d3)
+
+#define sys_ipc_kick0(pid) syscall1(SYS_IPC_KICK, pid)
+#define sys_ipc_kick1(pid, d0) syscall2(SYS_IPC_KICK, pid, d0)
+#define sys_ipc_kick2(pid, d0, d1) syscall3(SYS_IPC_KICK, pid, d0, d1)
+#define sys_ipc_kick3(pid, d0, d1, d2) syscall4(SYS_IPC_KICK, pid, d0, d1, d2)
+#define sys_ipc_kick4(pid, d0, d1, d2, d3) syscall5(SYS_IPC_KICK, pid, d0, d1, d2, d3)
+
+static inline enum sys_status sys_set_handler(id_t tid, id_t pid)
+{
+ struct sys_ret r = syscall2(SYS_SET_HANDLER, tid, pid);
+ return r.s;
+}
+
+static inline enum sys_status sys_ipc_notify(id_t tid)
+{
+ struct sys_ret r = syscall1(SYS_IPC_NOTIFY, tid);
+ return r.s;
+}
+
+static inline enum sys_status sys_ipc_resp0()
+{
+ struct sys_ret r = syscall0(SYS_IPC_RESP);
+ return r.s;
+}
+
+static inline enum sys_status sys_ipc_resp1(sys_arg_t a)
+{
+ struct sys_ret r = syscall1(SYS_IPC_RESP, a);
+ return r.s;
+}
+
+static inline enum sys_status sys_ipc_resp2(sys_arg_t a, sys_arg_t b)
+{
+ struct sys_ret r = syscall2(SYS_IPC_RESP, a, b);
+ return r.s;
+}
+
+static inline enum sys_status sys_ipc_resp3(sys_arg_t a, sys_arg_t b, sys_arg_t c)
+{
+ struct sys_ret r = syscall3(SYS_IPC_RESP, a, b, c);
+ return r.s;
+}
+
+static inline enum sys_status sys_ipc_resp4(sys_arg_t a, sys_arg_t b, sys_arg_t c, sys_arg_t d)
+{
+ struct sys_ret r = syscall4(SYS_IPC_RESP, a, b, c, d);
+ return r.s;
+}
+
+static inline id_t sys_create(uintptr_t func, long d0, long d1, long d2, long d3)
+{
+ struct sys_ret r = syscall5(SYS_CREATE, func, d0, d1, d2, d3);
+ return r.s;
+}
+
+/* note that negative IDs are error values */
+static inline id_t sys_fork(id_t *new_id)
+{
+ struct sys_ret r = syscall0(SYS_FORK);
+ if (new_id)
+ *new_id = r.a0;
+
+ return r.s;
+}
+
+static inline enum sys_status sys_exec(uintptr_t bin, uintptr_t interp)
+{
+ struct sys_ret r = syscall2(SYS_EXEC, bin, interp);
+ /* if we reach this point, something's gone wrong */
+ return r.s;
+}
+
+/* negative IDs mean errors */
+static inline id_t sys_spawn(uintptr_t bin, uintptr_t interp)
+{
+ struct sys_ret r = syscall2(SYS_EXEC, bin, interp);
+ return r.s;
+}
+
+static inline enum sys_status sys_swap(id_t tid)
+{
+ struct sys_ret r = syscall1(SYS_SWAP, tid);
+ return r.s;
+}
+
+static inline enum sys_status sys_conf_set(enum conf_param param, long arg)
+{
+ struct sys_ret r = syscall2(SYS_SET_CONF, param, arg);
+ return r.s;
+}
+
+static inline long sys_conf_get(enum conf_param param, long arg)
+{
+ struct sys_ret r = syscall2(SYS_GET_CONF, param, arg);
+ return r.a0;
+}
+
+static inline enum sys_status sys_set_cap(id_t tid, enum sys_cap cap)
+{
+ struct sys_ret r = syscall2(SYS_SET_CAP, tid, cap);
+ return r.s;
+}
+
+static inline enum sys_status sys_get_cap(id_t tid, enum sys_cap *cap)
+{
+ struct sys_ret r = syscall1(SYS_GET_CAP, tid);
+ *cap = r.a0;
+ return r.s;
+}
+
+static inline enum sys_status sys_clear_cap(id_t tid, enum sys_cap cap)
+{
+ struct sys_ret r = syscall2(SYS_CLEAR_CAP, tid, cap);
+ return r.s;
+}
+
+static inline enum sys_status sys_poweroff(enum poweroff_type type)
+{
+ struct sys_ret r = syscall1(SYS_POWEROFF, type);
+ return r.s;
+}
+
+static inline enum sys_status sys_sleep()
+{
+ struct sys_ret r = syscall0(SYS_SLEEP);
+ return r.s;
+}
+
+/** note that negative IDs mean errors */
+static inline id_t sys_irq_req(long irq)
+{
+ struct sys_ret r = syscall1(SYS_IRQ_REQ, irq);
+ return r.s;
+}
+
+static inline enum sys_status sys_free_irq(long irq)
+{
+ struct sys_ret r = syscall1(SYS_FREE_IRQ, irq);
+ return r.s;
+}
+
+static inline enum sys_status sys_detach(id_t tid)
+{
+ struct sys_ret r = syscall1(SYS_DETACH, tid);
+ return r.s;
+}
+
+static inline enum sys_status sys_exit(id_t tid)
+{
+ struct sys_ret r = syscall1(SYS_EXIT, tid);
+ return r.s;
+}
+
+#endif /* KMI_SYS_H */
diff --git a/tests/common/test.h b/tests/common/test.h
index 0b53b52..1476fdf 100644
--- a/tests/common/test.h
+++ b/tests/common/test.h
@@ -4,326 +4,9 @@
#include <kmi/attrs.h>
#include <kmi/types.h>
-#if defined(__riscv)
-# if __riscv_xlen == 64
-#include "arch/riscv64/syscall.h"
-# endif
-#endif
-
-#define syscall0(op) syscall(1, op, 0, 0, 0, 0, 0)
-#define syscall1(op, a0) syscall(2, op, a0, 0, 0, 0, 0)
-#define syscall2(op, a0, a1) syscall(3, op, a0, a1, 0, 0, 0)
-#define syscall3(op, a0, a1, a2) syscall(4, op, a0, a1, a2, 0, 0)
-#define syscall4(op, a0, a1, a2, a3) syscall(5, op, a0, a1, a2, a3, 0)
-#define syscall5(op, a0, a1, a2, a3, a4) syscall(6, op, a0, a1, a2, a3, a4)
-
-#define UNUSED(x) (void)x
-#define START(pid, tid, d0, d1, d2, d3)\
-void _start(sys_arg_t pid, sys_arg_t tid,\
- sys_arg_t d0, sys_arg_t d1, sys_arg_t d2, sys_arg_t d3)
-
-static inline void sys_noop()
-{
- syscall0(SYS_NOOP);
-}
-
-static inline void sys_putch(char c)
-{
- syscall1(SYS_PUTCH, c);
-}
-
-static inline void *sys_req_mem(size_t size, vmflags_t flags)
-{
- struct sys_ret r = syscall2(SYS_REQ_MEM, size, flags);
- if (r.s)
- return NULL;
-
- return (void *)r.a0;
-}
-
-static inline void *sys_req_fixmem(uintptr_t fixed, size_t size, vmflags_t flags)
-{
- struct sys_ret r = syscall3(SYS_REQ_FIXMEM, fixed, size, flags);
- if (r.s)
- return NULL;
-
- return (void *)r.a0;
-}
-
-static inline void *sys_req_pmem(uintptr_t addr, size_t size, vmflags_t flags)
-{
- struct sys_ret r = syscall3(SYS_REQ_PMEM, addr, size, flags);
- if (r.s)
- return NULL;
-
- return (void *)r.a0;
-}
-
-static inline void *sys_req_page(size_t size, vmflags_t flags, uintptr_t *addr, size_t *asize)
-{
- struct sys_ret r = syscall2(SYS_REQ_PAGE, size, flags);
- if (r.s)
- return NULL;
-
- if (addr)
- *addr = r.a1;
-
- if (asize)
- *asize = r.a2;
-
- return (void *)r.a0;
-}
-
-static inline void *sys_req_sharedmem(size_t size, vmflags_t flags)
-{
- struct sys_ret r = syscall2(SYS_REQ_SHAREDMEM, size, flags);
- if (r.s)
- return NULL;
-
- return (void *)r.a0;
-}
-
-static inline void *sys_ref_sharedmem(id_t tid, uintptr_t addr, vmflags_t flags)
-{
- struct sys_ret r = syscall3(SYS_REF_SHAREDMEM, tid, addr, flags);
- if (r.s)
- return NULL;
-
- return (void *)r.a0;
-}
-
-static inline void sys_free_mem(uintptr_t start)
-{
- syscall1(SYS_FREE_MEM, start);
-}
-
-static inline uint64_t sys_timebase()
-{
- struct sys_ret r = syscall0(SYS_TIMEBASE);
- if (r.s)
- return 0;
-
-#if defined(_LP64)
- return r.a0;
-#else
- return ((uint64_t)r.a1 << 32) | r.a0
-#endif
-}
-
-static inline uint64_t sys_ticks()
-{
- struct sys_ret r = syscall0(SYS_TICKS);
- if (r.s)
- return 0;
-
-#if defined(_LP64)
- return r.a0;
-#else
- return ((uint64_t)r.a1 << 32) | r.a0;
-#endif
-}
-
-static inline id_t sys_req_rel_timer(uint64_t ticks)
-{
- struct sys_ret r;
-#if defined(_LP64)
- r = syscall2(SYS_REQ_REL_TIMER, ticks >> 32, ticks);
-#else
- r = syscall1(SYS_REQ_REL_TIMER, ticks);
-#endif
-
- if (r.s)
- return -1;
-
- return r.a0;
-}
-
-static inline id_t sys_req_abs_timer(uint64_t ticks)
-{
- struct sys_ret r;
-#if defined(_LP64)
- r = syscall2(SYS_REQ_ABS_TIMER, ticks >> 32, ticks);
-#else
- r = syscall1(SYS_REQ_ABS_TIMER, ticks);
-#endif
-
- if (r.s)
- return -1;
-
- return r.a0;
-}
-
-#define sys_ipc_req0(pid) syscall1(SYS_IPC_REQ, pid)
-#define sys_ipc_req1(pid, d0) syscall2(SYS_IPC_REQ, pid, d0)
-#define sys_ipc_req2(pid, d0, d1) syscall3(SYS_IPC_REQ, pid, d0, d1)
-#define sys_ipc_req3(pid, d0, d1, d2) syscall4(SYS_IPC_REQ, pid, d0, d1, d2)
-#define sys_ipc_req4(pid, d0, d1, d2, d3) syscall5(SYS_IPC_REQ, pid, d0, d1, d2, d3)
-
-#define sys_ipc_fwd0(pid) syscall1(SYS_IPC_FWD, pid)
-#define sys_ipc_fwd1(pid, d0) syscall2(SYS_IPC_FWD, pid, d0)
-#define sys_ipc_fwd2(pid, d0, d1) syscall3(SYS_IPC_FWD, pid, d0, d1)
-#define sys_ipc_fwd3(pid, d0, d1, d2) syscall4(SYS_IPC_FWD, pid, d0, d1, d2)
-#define sys_ipc_fwd4(pid, d0, d1, d2, d3) syscall5(SYS_IPC_FWD, pid, d0, d1, d2, d3)
-
-#define sys_ipc_tail0(pid) syscall1(SYS_IPC_TAIL, pid)
-#define sys_ipc_tail1(pid, d0) syscall2(SYS_IPC_TAIL, pid, d0)
-#define sys_ipc_tail2(pid, d0, d1) syscall3(SYS_IPC_TAIL, pid, d0, d1)
-#define sys_ipc_tail3(pid, d0, d1, d2) syscall4(SYS_IPC_TAIL, pid, d0, d1, d2)
-#define sys_ipc_tail4(pid, d0, d1, d2, d3) syscall5(SYS_IPC_TAIL, pid, d0, d1, d2, d3)
-
-#define sys_ipc_kick0(pid) syscall1(SYS_IPC_KICK, pid)
-#define sys_ipc_kick1(pid, d0) syscall2(SYS_IPC_KICK, pid, d0)
-#define sys_ipc_kick2(pid, d0, d1) syscall3(SYS_IPC_KICK, pid, d0, d1)
-#define sys_ipc_kick3(pid, d0, d1, d2) syscall4(SYS_IPC_KICK, pid, d0, d1, d2)
-#define sys_ipc_kick4(pid, d0, d1, d2, d3) syscall5(SYS_IPC_KICK, pid, d0, d1, d2, d3)
-
-static inline enum sys_status sys_set_handler(id_t tid, id_t pid)
-{
- struct sys_ret r = syscall2(SYS_SET_HANDLER, tid, pid);
- return r.s;
-}
-
-static inline enum sys_status sys_ipc_notify(id_t tid)
-{
- struct sys_ret r = syscall1(SYS_IPC_NOTIFY, tid);
- return r.s;
-}
-
-static inline enum sys_status sys_ipc_resp0()
-{
- struct sys_ret r = syscall0(SYS_IPC_RESP);
- return r.s;
-}
-
-static inline enum sys_status sys_ipc_resp1(sys_arg_t a)
-{
- struct sys_ret r = syscall1(SYS_IPC_RESP, a);
- return r.s;
-}
-
-static inline enum sys_status sys_ipc_resp2(sys_arg_t a, sys_arg_t b)
-{
- struct sys_ret r = syscall2(SYS_IPC_RESP, a, b);
- return r.s;
-}
-
-static inline enum sys_status sys_ipc_resp3(sys_arg_t a, sys_arg_t b, sys_arg_t c)
-{
- struct sys_ret r = syscall3(SYS_IPC_RESP, a, b, c);
- return r.s;
-}
-
-static inline enum sys_status sys_ipc_resp4(sys_arg_t a, sys_arg_t b, sys_arg_t c, sys_arg_t d)
-{
- struct sys_ret r = syscall4(SYS_IPC_RESP, a, b, c, d);
- return r.s;
-}
-
-static inline id_t sys_create(uintptr_t func, long d0, long d1, long d2, long d3)
-{
- struct sys_ret r = syscall5(SYS_CREATE, func, d0, d1, d2, d3);
- return r.s;
-}
-
-/* note that negative IDs are error values */
-static inline id_t sys_fork(id_t *new_id)
-{
- struct sys_ret r = syscall0(SYS_FORK);
- if (new_id)
- *new_id = r.a0;
-
- return r.s;
-}
-
-static inline enum sys_status sys_exec(uintptr_t bin, uintptr_t interp)
-{
- struct sys_ret r = syscall2(SYS_EXEC, bin, interp);
- /* if we reach this point, something's gone wrong */
- return r.s;
-}
-
-/* negative IDs mean errors */
-static inline id_t sys_spawn(uintptr_t bin, uintptr_t interp)
-{
- struct sys_ret r = syscall2(SYS_EXEC, bin, interp);
- return r.s;
-}
-
-static inline enum sys_status sys_swap(id_t tid)
-{
- struct sys_ret r = syscall1(SYS_SWAP, tid);
- return r.s;
-}
-
-static inline enum sys_status sys_conf_set(enum conf_param param, long arg)
-{
- struct sys_ret r = syscall2(SYS_SET_CONF, param, arg);
- return r.s;
-}
-
-static inline long sys_conf_get(enum conf_param param, long arg)
-{
- struct sys_ret r = syscall2(SYS_GET_CONF, param, arg);
- return r.a0;
-}
-
-static inline enum sys_status sys_set_cap(id_t tid, enum sys_cap cap)
-{
- struct sys_ret r = syscall2(SYS_SET_CAP, tid, cap);
- return r.s;
-}
-
-static inline enum sys_status sys_get_cap(id_t tid, enum sys_cap *cap)
-{
- struct sys_ret r = syscall1(SYS_GET_CAP, tid);
- *cap = r.a0;
- return r.s;
-}
-
-static inline enum sys_status sys_clear_cap(id_t tid, enum sys_cap cap)
-{
- struct sys_ret r = syscall2(SYS_CLEAR_CAP, tid, cap);
- return r.s;
-}
-
-static inline enum sys_status sys_poweroff(enum poweroff_type type)
-{
- struct sys_ret r = syscall1(SYS_POWEROFF, type);
- return r.s;
-}
-
-static inline enum sys_status sys_sleep()
-{
- struct sys_ret r = syscall0(SYS_SLEEP);
- return r.s;
-}
-
-/** note that negative IDs mean errors */
-static inline id_t sys_irq_req(long irq)
-{
- struct sys_ret r = syscall1(SYS_IRQ_REQ, irq);
- return r.s;
-}
-
-static inline enum sys_status sys_free_irq(long irq)
-{
- struct sys_ret r = syscall1(SYS_FREE_IRQ, irq);
- return r.s;
-}
-
-static inline enum sys_status sys_detach(id_t tid)
-{
- struct sys_ret r = syscall1(SYS_DETACH, tid);
- return r.s;
-}
-
-static inline enum sys_status sys_exit(id_t tid)
-{
- struct sys_ret r = syscall1(SYS_EXIT, tid);
- return r.s;
-}
-
-int printf(const char *fmt, ...) __printf;
+#include "sys.h"
+#include "start.h"
+#include "printf.h"
#define error(x, ...)\
printf("ERROR: " x, ## __VA_ARGS__)