[RFC PATCH kvm-unit-tests] x86: add ioregionfd fast PIO test

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Signed-off-by: Elena Afanasova <eafanasova@xxxxxxxxx>
---
 scripts/common.bash   | 12 +++++--
 scripts/runtime.bash  |  9 +++++
 x86/Makefile.common   |  5 ++-
 x86/Makefile.x86_64   |  2 ++
 x86/ioregionfd-test.c | 84 +++++++++++++++++++++++++++++++++++++++++++
 x86/ioregionfd_pio.c  | 24 +++++++++++++
 x86/unittests.cfg     |  7 ++++
 7 files changed, 140 insertions(+), 3 deletions(-)
 create mode 100644 x86/ioregionfd-test.c
 create mode 100644 x86/ioregionfd_pio.c

diff --git a/scripts/common.bash b/scripts/common.bash
index 7b983f7..d9f8556 100644
--- a/scripts/common.bash
+++ b/scripts/common.bash
@@ -14,6 +14,8 @@ function for_each_unittest()
 	local accel
 	local timeout
 	local rematch
+	local helper_cmd
+	local fifo
 
 	exec {fd}<"$unittests"
 
@@ -21,7 +23,7 @@ function for_each_unittest()
 		if [[ "$line" =~ ^\[(.*)\]$ ]]; then
 			rematch=${BASH_REMATCH[1]}
 			if [ -n "${testname}" ]; then
-				$(arch_cmd) "$cmd" "$testname" "$groups" "$smp" "$kernel" "$opts" "$arch" "$check" "$accel" "$timeout"
+				$(arch_cmd) "$cmd" "$testname" "$groups" "$smp" "$kernel" "$opts" "$arch" "$check" "$accel" "$timeout" "$helper_cmd" "$fifo"
 			fi
 			testname=$rematch
 			smp=1
@@ -32,6 +34,8 @@ function for_each_unittest()
 			check=""
 			accel=""
 			timeout=""
+			helper_cmd=""
+			fifo=""
 		elif [[ $line =~ ^file\ *=\ *(.*)$ ]]; then
 			kernel=$TEST_DIR/${BASH_REMATCH[1]}
 		elif [[ $line =~ ^smp\ *=\ *(.*)$ ]]; then
@@ -48,10 +52,14 @@ function for_each_unittest()
 			accel=${BASH_REMATCH[1]}
 		elif [[ $line =~ ^timeout\ *=\ *(.*)$ ]]; then
 			timeout=${BASH_REMATCH[1]}
+		elif [[ $line =~ ^helper_cmd\ *=\ *(.*)$ ]]; then
+			helper_cmd=$TEST_DIR/${BASH_REMATCH[1]}
+		elif [[ $line =~ ^fifo\ *=\ *(.*)$ ]]; then
+			fifo=${BASH_REMATCH[1]}
 		fi
 	done
 	if [ -n "${testname}" ]; then
-		$(arch_cmd) "$cmd" "$testname" "$groups" "$smp" "$kernel" "$opts" "$arch" "$check" "$accel" "$timeout"
+		$(arch_cmd) "$cmd" "$testname" "$groups" "$smp" "$kernel" "$opts" "$arch" "$check" "$accel" "$timeout" "$helper_cmd" "$fifo"
 	fi
 	exec {fd}<&-
 }
diff --git a/scripts/runtime.bash b/scripts/runtime.bash
index 132389c..ba94ee5 100644
--- a/scripts/runtime.bash
+++ b/scripts/runtime.bash
@@ -81,6 +81,8 @@ function run()
     local check="${CHECK:-$7}"
     local accel="$8"
     local timeout="${9:-$TIMEOUT}" # unittests.cfg overrides the default
+    local helper_cmd="${10}"
+    local fifo="${11}"
 
     if [ -z "$testname" ]; then
         return
@@ -139,6 +141,11 @@ function run()
         echo $cmdline
     fi
 
+    if [ -n "${helper_cmd}" ] && [ -n "${fifo}" ]; then
+        mkfifo $fifo
+        $helper_cmd $fifo &
+    fi
+
     # extra_params in the config file may contain backticks that need to be
     # expanded, so use eval to start qemu.  Use "> >(foo)" instead of a pipe to
     # preserve the exit status.
@@ -159,6 +166,8 @@ function run()
         print_result "FAIL" $testname "$summary"
     fi
 
+    [ -n "${fifo}" ] && rm -rf $fifo
+
     return $ret
 }
 
diff --git a/x86/Makefile.common b/x86/Makefile.common
index 55f7f28..a5cd1d2 100644
--- a/x86/Makefile.common
+++ b/x86/Makefile.common
@@ -82,6 +82,9 @@ $(TEST_DIR)/hyperv_stimer.elf: $(TEST_DIR)/hyperv.o
 
 $(TEST_DIR)/hyperv_connections.elf: $(TEST_DIR)/hyperv.o
 
+$(TEST_DIR)/ioregionfd-test:
+	$(CC) -o $@ $(TEST_DIR)/ioregionfd-test.c
+
 arch_clean:
-	$(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
+	$(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf $(TEST_DIR)/ioregionfd-test \
 	$(TEST_DIR)/.*.d lib/x86/.*.d \
diff --git a/x86/Makefile.x86_64 b/x86/Makefile.x86_64
index 8134952..1a7a6b1 100644
--- a/x86/Makefile.x86_64
+++ b/x86/Makefile.x86_64
@@ -24,6 +24,8 @@ tests += $(TEST_DIR)/vmware_backdoors.flat
 tests += $(TEST_DIR)/rdpru.flat
 tests += $(TEST_DIR)/pks.flat
 tests += $(TEST_DIR)/pmu_lbr.flat
+tests += $(TEST_DIR)/ioregionfd_pio.flat
+tests += $(TEST_DIR)/ioregionfd-test
 
 ifneq ($(fcf_protection_full),)
 tests += $(TEST_DIR)/cet.flat
diff --git a/x86/ioregionfd-test.c b/x86/ioregionfd-test.c
new file mode 100644
index 0000000..5ea5e57
--- /dev/null
+++ b/x86/ioregionfd-test.c
@@ -0,0 +1,84 @@
+#include <linux/ioregion.h>
+#include <string.h>
+#include <poll.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+void err_exit(const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	vfprintf(stderr, fmt, args);
+	va_end(args);
+	exit(EXIT_FAILURE);
+}
+
+int main(int argc, char *argv[])
+{
+	struct ioregionfd_cmd cmd;
+	struct ioregionfd_resp resp;
+	struct pollfd pollfd;
+	int read_fd, write_fd = -1;
+	unsigned long cdata = 0;
+	int ret;
+
+	if (argc < 2)
+		err_exit("Usage: %s <read_fifo> <write_fifo>\n", argv[0]);
+
+	read_fd = open(argv[1], O_RDONLY);
+	if (read_fd < 0)
+		err_exit("failed to open read fifo %s\n", argv[1]);
+
+	if (argc == 3) {
+		write_fd = open(argv[2], O_WRONLY);
+		if (write_fd < 0) {
+			close(read_fd);
+			err_exit("failed to open write fifo %s\n", argv[2]);
+		}
+	}
+
+	pollfd.fd = read_fd;
+	pollfd.events = POLLIN;
+
+	for (;;) {
+		ret = poll(&pollfd, 1, -1);
+		if (ret < 0) {
+			close(read_fd);
+			if (write_fd > 0)
+				close(write_fd);
+			err_exit("poll\n");
+		}
+
+		if (pollfd.revents & POLLIN) {
+			ret = read(read_fd, &cmd, sizeof(cmd));
+
+			switch (cmd.cmd) {
+			case IOREGIONFD_CMD_READ:
+				memset(&resp, 0, sizeof(resp));
+				memcpy(&resp.data, &cdata, 1 << cmd.size_exponent);
+				ret = write(write_fd, &resp, sizeof(resp));
+				break;
+			case IOREGIONFD_CMD_WRITE:
+				memcpy(&cdata, &cmd.data, 1 << cmd.size_exponent);
+				if (cmd.resp) {
+					memset(&resp, 0, sizeof(resp));
+					ret = write(write_fd, &resp, sizeof(resp));
+				}
+				break;
+			default:
+				break;
+			}
+		} else
+			break;
+	}
+
+	close(read_fd);
+	if (write_fd > 0)
+		close(write_fd);
+
+	return 0;
+}
diff --git a/x86/ioregionfd_pio.c b/x86/ioregionfd_pio.c
new file mode 100644
index 0000000..eaf8aad
--- /dev/null
+++ b/x86/ioregionfd_pio.c
@@ -0,0 +1,24 @@
+#include "x86/vm.h"
+
+int main(int ac, char **av)
+{
+	u32 expected = 0x11223344;
+	u32 val = 0;
+	u32 write_addr = 0x1234;
+	u32 read_addr = 0x1238;
+
+	outb(expected, write_addr);
+	val = inb(read_addr);
+	report(val == (u8)expected, "%x\n", val);
+
+	outw(expected, write_addr);
+	val = inw(read_addr);
+	report(val == (u16)expected, "%x\n", val);
+
+	outl(expected, write_addr);
+	val = inl(read_addr);
+	report(val == expected, "%x\n", val);
+
+	return report_summary();
+}
+
diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index 0698d15..8001808 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -389,3 +389,10 @@ file = cet.flat
 arch = x86_64
 smp = 2
 extra_params = -enable-kvm -m 2048 -cpu host
+
+[ioregion-pio]
+file = ioregionfd_pio.flat
+helper_cmd = ioregionfd-test
+fifo = /tmp/test1 /tmp/test2
+extra_params = -device pc-testdev,addr=0x1234,size=8,rfifo=/tmp/test2,wfifo=/tmp/test1,pio=true
+arch = x86_64
-- 
2.25.1




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux