aboutsummaryrefslogtreecommitdiff
path: root/tests/user-qemu.mk
diff options
context:
space:
mode:
Diffstat (limited to 'tests/user-qemu.mk')
-rw-r--r--tests/user-qemu.mk212
1 files changed, 212 insertions, 0 deletions
diff --git a/tests/user-qemu.mk b/tests/user-qemu.mk
new file mode 100644
index 00000000..78775938
--- /dev/null
+++ b/tests/user-qemu.mk
@@ -0,0 +1,212 @@
+# Copyright (C) 2024 Free Software Foundation
+
+# This program is free software ; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation ; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY ; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with the program ; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#
+# MIG stubs generation for user-space tests
+#
+
+MACH_TESTINSTALL = $(builddir)/tests/include-mach
+MACH_TESTINCLUDE = $(MACH_TESTINSTALL)/$(prefix)/include
+
+MIGCOMUSER = $(USER_MIG) -n -cc cat - /dev/null
+MIG_OUTDIR = $(builddir)/tests/mig-out
+MIG_CPPFLAGS = -x c -nostdinc -I$(MACH_TESTINCLUDE)
+
+# FIXME: how can we reliably detect a change on any header and reinstall them?
+$(MACH_TESTINSTALL):
+ mkdir -p $@
+ $(MAKE) install-data DESTDIR=$@
+
+prepare-test: $(MACH_TESTINSTALL)
+
+$(MIG_OUTDIR):
+ mkdir -p $@
+
+define generate_mig_client
+$(MIG_OUTDIR)/$(2).user.c: prepare-test $(MIG_OUTDIR) $(MACH_TESTINCLUDE)/$(1)/$(2).defs
+ $(USER_CPP) $(USER_CPPFLAGS) $(MIG_CPPFLAGS) \
+ -o $(MIG_OUTDIR)/$(2).user.defs \
+ $(MACH_TESTINCLUDE)/$(1)/$(2).defs
+ $(MIGCOMUSER) $(MIGCOMFLAGS) $(MIGCOMUFLAGS) \
+ -user $(MIG_OUTDIR)/$(2).user.c \
+ -header $(MIG_OUTDIR)/$(2).user.h \
+ -list $(MIG_OUTDIR)/$(2).user.msgids \
+ < $(MIG_OUTDIR)/$(2).user.defs
+endef
+
+define generate_mig_server
+$(MIG_OUTDIR)/$(2).server.c: prepare-test $(MIG_OUTDIR) $(srcdir)/include/$(1)/$(2).defs
+ $(USER_CPP) $(USER_CPPFLAGS) $(MIG_CPPFLAGS) \
+ -o $(MIG_OUTDIR)/$(2).server.defs \
+ $(srcdir)/include/$(1)/$(2).defs
+ $(MIGCOMUSER) $(MIGCOMFLAGS) $(MIGCOMUFLAGS) \
+ -server $(MIG_OUTDIR)/$(2).server.c \
+ -header $(MIG_OUTDIR)/$(2).server.h \
+ -list $(MIG_OUTDIR)/$(2).server.msgids \
+ < $(MIG_OUTDIR)/$(2).server.defs
+endef
+
+# These are all the IPC implemented in the kernel, both as a server or as a client.
+# Files are sorted as in
+# find builddir/tests/include-mach/ -name *.defs | grep -v types | sort
+# eval->info for debug of generated rules
+$(eval $(call generate_mig_client,device,device))
+$(eval $(call generate_mig_client,device,device_reply))
+$(eval $(call generate_mig_client,device,device_request))
+$(eval $(call generate_mig_client,mach_debug,mach_debug))
+# default_pager.defs?
+$(eval $(call generate_mig_server,mach,exc))
+# experimental.defs?
+$(eval $(call generate_mig_client,mach,gnumach))
+$(eval $(call generate_mig_client,mach,mach4))
+$(eval $(call generate_mig_client,mach,mach))
+$(eval $(call generate_mig_client,mach,mach_host))
+$(eval $(call generate_mig_client,mach,mach_port))
+# memory_object{_default}.defs?
+# notify.defs?
+$(eval $(call generate_mig_server,mach,task_notify))
+if HOST_ix86
+$(eval $(call generate_mig_client,mach/i386,mach_i386))
+endif
+if HOST_x86_64
+$(eval $(call generate_mig_client,mach/x86_64,mach_i386))
+endif
+
+# NOTE: keep in sync with the rules above
+MIG_GEN_CC = \
+ $(MIG_OUTDIR)/device.user.c \
+ $(MIG_OUTDIR)/device_reply.user.c \
+ $(MIG_OUTDIR)/device_request.user.c \
+ $(MIG_OUTDIR)/mach_debug.user.c \
+ $(MIG_OUTDIR)/exc.server.c \
+ $(MIG_OUTDIR)/gnumach.user.c \
+ $(MIG_OUTDIR)/mach4.user.c \
+ $(MIG_OUTDIR)/mach.user.c \
+ $(MIG_OUTDIR)/mach_host.user.c \
+ $(MIG_OUTDIR)/mach_port.user.c \
+ $(MIG_OUTDIR)/task_notify.server.c \
+ $(MIG_OUTDIR)/mach_i386.user.c
+
+#
+# compilation of user space tests and utilities
+#
+
+TEST_START_MARKER = booting-start-of-test
+TEST_SUCCESS_MARKER = gnumach-test-success-and-reboot
+TEST_FAILURE_MARKER = gnumach-test-failure
+
+TESTCFLAGS = -static -nostartfiles -nolibc \
+ -ffreestanding \
+ -ftrivial-auto-var-init=pattern \
+ -I$(srcdir)/tests/include \
+ -I$(MACH_TESTINCLUDE) \
+ -I$(MIG_OUTDIR) \
+ -ggdb3 \
+ -DMIG_EOPNOTSUPP
+
+SRC_TESTLIB= \
+ $(srcdir)/i386/i386/strings.c \
+ $(srcdir)/kern/printf.c \
+ $(srcdir)/kern/strings.c \
+ $(srcdir)/util/atoi.c \
+ $(srcdir)/tests/syscalls.S \
+ $(srcdir)/tests/start.S \
+ $(srcdir)/tests/testlib.c \
+ $(builddir)/tests/errlist.c \
+ $(MIG_GEN_CC)
+
+tests/errlist.c: $(addprefix $(srcdir)/include/mach/,message.h kern_return.h mig_errors.h)
+ echo "/* autogenerated file */" >$@
+ echo "#include <mach/message.h>" >>$@
+ echo "#include <mach/kern_return.h>" >>$@
+ echo "#include <mach/mig_errors.h>" >>$@
+ echo "#include <testlib.h>" >>$@
+ echo "#include <stddef.h>" >>$@
+ echo "const char* TEST_SUCCESS_MARKER = \"$(TEST_SUCCESS_MARKER)\";" >>$@
+ echo "const char* TEST_FAILURE_MARKER = \"$(TEST_FAILURE_MARKER)\";" >>$@
+ echo "const char* e2s_gnumach(int err) { switch (err) {" >>$@
+ grep "define[[:space:]]MIG" $(srcdir)/include/mach/mig_errors.h | \
+ awk '{printf " case %s: return \"%s\";\n", $$2, $$2}' >>$@
+ grep "define[[:space:]]KERN" $(srcdir)/include/mach/kern_return.h | \
+ awk '{printf " case %s: return \"%s\";\n", $$2, $$2}' >>$@
+ awk 'f;/MACH_MSG_SUCCESS/{f=1}' $(srcdir)/include/mach/message.h | \
+ grep "define[[:space:]]MACH" | \
+ awk '{printf " case %s: return \"%s\";\n", $$2, $$2}' >>$@
+ echo " default: return NULL;" >>$@
+ echo "}}" >>$@
+
+tests/module-%: $(srcdir)/tests/test-%.c $(SRC_TESTLIB) $(MACH_TESTINSTALL)
+ $(USER_CC) $(USER_CFLAGS) $(TESTCFLAGS) $< $(SRC_TESTLIB) -o $@
+
+#
+# packaging of qemu bootable image and test runner
+#
+
+GNUMACH_ARGS = console=com0
+QEMU_OPTS = -m 2048 -nographic -no-reboot -boot d
+QEMU_GDB_PORT ?= 1234
+
+if HOST_ix86
+QEMU_BIN = qemu-system-i386
+QEMU_OPTS += -cpu pentium3-v1
+endif
+if HOST_x86_64
+QEMU_BIN = qemu-system-x86_64
+QEMU_OPTS += -cpu core2duo-v1
+endif
+
+tests/test-%.iso: tests/module-% gnumach $(srcdir)/tests/grub.cfg.single.template
+ rm -rf $(builddir)/tests/isofiles
+ mkdir -p $(builddir)/tests/isofiles/boot/grub/
+ < $(srcdir)/tests/grub.cfg.single.template \
+ sed -e "s|BOOTMODULE|$(notdir $<)|g" \
+ -e "s/GNUMACHARGS/$(GNUMACH_ARGS)/g" \
+ -e "s/TEST_START_MARKER/$(TEST_START_MARKER)/g" \
+ >$(builddir)/tests/isofiles/boot/grub/grub.cfg
+ cp gnumach $< $(builddir)/tests/isofiles/boot/
+ grub-mkrescue -o $@ $(builddir)/tests/isofiles
+
+tests/test-%: tests/test-%.iso $(srcdir)/tests/run-qemu.sh.template
+ < $(srcdir)/tests/run-qemu.sh.template \
+ sed -e "s|TESTNAME|$(subst tests/test-,,$@)|g" \
+ -e "s/QEMU_OPTS/$(QEMU_OPTS)/g" \
+ -e "s/QEMU_BIN/$(QEMU_BIN)/g" \
+ -e "s/TEST_START_MARKER/$(TEST_START_MARKER)/g" \
+ -e "s/TEST_SUCCESS_MARKER/$(TEST_SUCCESS_MARKER)/g" \
+ -e "s/TEST_FAILURE_MARKER/$(TEST_FAILURE_MARKER)/g" \
+ >$@
+ chmod +x $@
+
+clean-test-%:
+ rm -f tests/test-$*.iso tests/module-$* tests/test-$**
+
+
+USER_TESTS := \
+ tests/test-hello
+
+USER_TESTS_CLEAN = $(subst tests/,clean-,$(USER_TESTS))
+
+#
+# helpers for interactive test run and debug
+#
+
+run-%: tests/test-%
+ $^
+
+# don't reuse the launcher script as the timeout would kill the debug session
+debug-%: tests/test-%.iso
+ $(QEMU_BIN) $(QEMU_OPTS) -cdrom $< -gdb tcp::$(QEMU_GDB_PORT) -S \
+ | sed -n "/$(TEST_START_MARKER)/"',$$p'