* [PATCH 0/9 v2] kvm-unit-tests/arm: initial drop
@ 2013-12-04 16:42 Andrew Jones
2013-12-04 16:42 ` [PATCH 1/9] remove unused files Andrew Jones
` (8 more replies)
0 siblings, 9 replies; 44+ messages in thread
From: Andrew Jones @ 2013-12-04 16:42 UTC (permalink / raw)
To: kvmarm, kvm
This is a v2 of a series that introduces arm to kvm-unit-tests.
First, it does some tidying up of the repo. Then, it adds support
for virtio-testdev, which a v2 of was just posted to qemu-devel[1].
Next, it adds the basic infrastructure for booting a test case
(guest), and adds a single simple test.
The v1 of this series also added support for vectors. This time
I'm posting the initial drop without it, but will be sending the
vector support separately soon.
This initial drop doesn't require kvmarm. Only qemu-system-arm,
with the most recent mach-virt patches[2] and the previously
mentioned virtio-testdev, is required.
[1] http://lists.nongnu.org/archive/html/qemu-devel/2013-12/msg00690.html
[2] http://lists.nongnu.org/archive/html/qemu-devel/2013-11/msg02912.html
These patches are also available from a git repo here
https://github.com/rhdrjones/kvm-unit-tests/commits/arm-branch/master
Andrew Jones (9):
remove unused files
makefile and run_tests tweaks
clean root dir of all x86-ness
move x86's simple heap management to common code
Introduce libio to common code for io read/write
Introduce a simple iomap structure
Add halt() and some error codes
Introduce virtio-testdev
arm: initial drop
Makefile | 19 +-
README | 56 ++--
arm/boot.c | 17 +
arm/cstart.S | 38 +++
arm/flat.lds | 18 ++
arm/run | 19 ++
arm/unittests.cfg | 11 +
config-i386.mak | 13 -
config-ia64.mak | 7 -
config-powerpc-440.mak | 15 -
config-powerpc.mak | 39 ---
config-x86-common.mak | 122 --------
config-x86_64.mak | 14 -
config/config-arm.mak | 73 +++++
config/config-i386.mak | 12 +
config/config-x86-common.mak | 121 ++++++++
config/config-x86_64.mak | 13 +
configure | 27 +-
docs/testdev.txt | 11 +
flat.lds | 21 --
formats | 31 --
iotable.c | 53 ----
iotable.h | 40 ---
kvmtrace.c | 706 ------------------------------------------
kvmtrace_format | 532 -------------------------------
lib/arm/eabi_compat.c | 20 ++
lib/arm/io.c | 31 ++
lib/arm/io.h | 24 ++
lib/arm/setup.c | 85 +++++
lib/arm/sysinfo.h | 19 ++
lib/errno.h | 22 ++
lib/fwcfg.c | 58 ----
lib/heap.c | 43 +++
lib/heap.h | 8 +
lib/iomaps.c | 31 ++
lib/iomaps.h | 14 +
lib/libcflat.h | 8 +-
lib/libio.c | 67 ++++
lib/libio.h | 180 +++++++++++
lib/panic.c | 13 -
lib/powerpc/44x/map.c | 51 ---
lib/powerpc/44x/timebase.S | 28 --
lib/powerpc/44x/timebase.h | 25 --
lib/powerpc/44x/tlbwe.S | 29 --
lib/powerpc/io.c | 35 ---
lib/test_util.c | 34 ++
lib/test_util.h | 13 +
lib/virtio-testdev.c | 139 +++++++++
lib/virtio-testdev.h | 9 +
lib/virtio.c | 70 +++++
lib/virtio.h | 74 +++++
lib/x86/vm.c | 33 +-
main-ppc.c | 383 -----------------------
powerpc/44x/tlbsx.S | 33 --
powerpc/44x/tlbwe.S | 27 --
powerpc/44x/tlbwe_16KB.S | 35 ---
powerpc/44x/tlbwe_hole.S | 27 --
powerpc/cstart.S | 38 ---
powerpc/exit.c | 23 --
powerpc/helloworld.c | 27 --
powerpc/io.S | 32 --
powerpc/spin.S | 4 -
powerpc/sprg.S | 7 -
run_tests.sh | 19 +-
scripts/gen-devtree-iomaps.pl | 105 +++++++
testdev.txt | 14 -
x86-run | 41 ---
x86/README | 60 +++-
x86/flat.lds | 21 ++
x86/print.h | 19 --
x86/run | 41 +++
x86/run-kvm-unit-tests | 6 -
72 files changed, 1502 insertions(+), 2651 deletions(-)
create mode 100644 arm/boot.c
create mode 100644 arm/cstart.S
create mode 100644 arm/flat.lds
create mode 100755 arm/run
create mode 100644 arm/unittests.cfg
delete mode 100644 config-i386.mak
delete mode 100644 config-ia64.mak
delete mode 100644 config-powerpc-440.mak
delete mode 100644 config-powerpc.mak
delete mode 100644 config-x86-common.mak
delete mode 100644 config-x86_64.mak
create mode 100644 config/config-arm.mak
create mode 100644 config/config-i386.mak
create mode 100644 config/config-x86-common.mak
create mode 100644 config/config-x86_64.mak
create mode 100644 docs/testdev.txt
delete mode 100644 flat.lds
delete mode 100644 formats
delete mode 100644 iotable.c
delete mode 100644 iotable.h
delete mode 100644 kvmtrace.c
delete mode 100755 kvmtrace_format
create mode 100644 lib/arm/eabi_compat.c
create mode 100644 lib/arm/io.c
create mode 100644 lib/arm/io.h
create mode 100644 lib/arm/setup.c
create mode 100644 lib/arm/sysinfo.h
create mode 100644 lib/errno.h
delete mode 100644 lib/fwcfg.c
create mode 100644 lib/heap.c
create mode 100644 lib/heap.h
create mode 100644 lib/iomaps.c
create mode 100644 lib/iomaps.h
create mode 100644 lib/libio.c
create mode 100644 lib/libio.h
delete mode 100644 lib/panic.c
delete mode 100644 lib/powerpc/44x/map.c
delete mode 100644 lib/powerpc/44x/timebase.S
delete mode 100644 lib/powerpc/44x/timebase.h
delete mode 100644 lib/powerpc/44x/tlbwe.S
delete mode 100644 lib/powerpc/io.c
create mode 100644 lib/test_util.c
create mode 100644 lib/test_util.h
create mode 100644 lib/virtio-testdev.c
create mode 100644 lib/virtio-testdev.h
create mode 100644 lib/virtio.c
create mode 100644 lib/virtio.h
delete mode 100644 main-ppc.c
delete mode 100644 powerpc/44x/tlbsx.S
delete mode 100644 powerpc/44x/tlbwe.S
delete mode 100644 powerpc/44x/tlbwe_16KB.S
delete mode 100644 powerpc/44x/tlbwe_hole.S
delete mode 100644 powerpc/cstart.S
delete mode 100644 powerpc/exit.c
delete mode 100644 powerpc/helloworld.c
delete mode 100644 powerpc/io.S
delete mode 100644 powerpc/spin.S
delete mode 100644 powerpc/sprg.S
create mode 100755 scripts/gen-devtree-iomaps.pl
delete mode 100644 testdev.txt
delete mode 100755 x86-run
create mode 100644 x86/flat.lds
delete mode 100644 x86/print.h
create mode 100755 x86/run
delete mode 100644 x86/run-kvm-unit-tests
--
1.8.1.4
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 1/9] remove unused files
2013-12-04 16:42 [PATCH 0/9 v2] kvm-unit-tests/arm: initial drop Andrew Jones
@ 2013-12-04 16:42 ` Andrew Jones
2013-12-04 16:42 ` [PATCH 2/9] makefile and run_tests tweaks Andrew Jones
` (7 subsequent siblings)
8 siblings, 0 replies; 44+ messages in thread
From: Andrew Jones @ 2013-12-04 16:42 UTC (permalink / raw)
To: kvmarm, kvm
There are several unused files, primarily because powerpc is an unused
arch. The exceptions are config-ia64.mak, which is also an unused arch
file, lib/fwcfg.c, lib/panic.c, x86/print.h and x86/run-kvm-unit-tests,
which are just unused. Remove them all in order to tidy things up.
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
Makefile | 8 +-
config-ia64.mak | 7 -
config-powerpc-440.mak | 15 -
config-powerpc.mak | 39 ---
formats | 31 --
iotable.c | 53 ----
iotable.h | 40 ---
kvmtrace.c | 706 ---------------------------------------------
kvmtrace_format | 532 ----------------------------------
lib/fwcfg.c | 58 ----
lib/libcflat.h | 1 -
lib/panic.c | 13 -
lib/powerpc/44x/map.c | 51 ----
lib/powerpc/44x/timebase.S | 28 --
lib/powerpc/44x/timebase.h | 25 --
lib/powerpc/44x/tlbwe.S | 29 --
lib/powerpc/io.c | 35 ---
main-ppc.c | 383 ------------------------
powerpc/44x/tlbsx.S | 33 ---
powerpc/44x/tlbwe.S | 27 --
powerpc/44x/tlbwe_16KB.S | 35 ---
powerpc/44x/tlbwe_hole.S | 27 --
powerpc/cstart.S | 38 ---
powerpc/exit.c | 23 --
powerpc/helloworld.c | 27 --
powerpc/io.S | 32 --
powerpc/spin.S | 4 -
powerpc/sprg.S | 7 -
x86/print.h | 19 --
x86/run-kvm-unit-tests | 6 -
30 files changed, 1 insertion(+), 2331 deletions(-)
delete mode 100644 config-ia64.mak
delete mode 100644 config-powerpc-440.mak
delete mode 100644 config-powerpc.mak
delete mode 100644 formats
delete mode 100644 iotable.c
delete mode 100644 iotable.h
delete mode 100644 kvmtrace.c
delete mode 100755 kvmtrace_format
delete mode 100644 lib/fwcfg.c
delete mode 100644 lib/panic.c
delete mode 100644 lib/powerpc/44x/map.c
delete mode 100644 lib/powerpc/44x/timebase.S
delete mode 100644 lib/powerpc/44x/timebase.h
delete mode 100644 lib/powerpc/44x/tlbwe.S
delete mode 100644 lib/powerpc/io.c
delete mode 100644 main-ppc.c
delete mode 100644 powerpc/44x/tlbsx.S
delete mode 100644 powerpc/44x/tlbwe.S
delete mode 100644 powerpc/44x/tlbwe_16KB.S
delete mode 100644 powerpc/44x/tlbwe_hole.S
delete mode 100644 powerpc/cstart.S
delete mode 100644 powerpc/exit.c
delete mode 100644 powerpc/helloworld.c
delete mode 100644 powerpc/io.S
delete mode 100644 powerpc/spin.S
delete mode 100644 powerpc/sprg.S
delete mode 100644 x86/print.h
delete mode 100644 x86/run-kvm-unit-tests
diff --git a/Makefile b/Makefile
index b6e87598721a6..278791dbbef23 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,6 @@ libgcc := $(shell $(CC) --print-libgcc-file-name)
libcflat := lib/libcflat.a
cflatobjs := \
- lib/panic.o \
lib/printf.o \
lib/string.o
cflatobjs += lib/argv.o
@@ -39,11 +38,6 @@ autodepend-flags = -MMD -MF $(dir $*).$(notdir $*).d
LDFLAGS += $(CFLAGS)
LDFLAGS += -pthread -lrt
-kvmtrace_objs= kvmtrace.o
-
-kvmtrace: $(kvmtrace_objs)
- $(CC) $(LDFLAGS) $^ -o $@
-
$(libcflat): $(cflatobjs)
$(AR) rcs $@ $^
@@ -57,4 +51,4 @@ install:
install $(tests_and_config) $(DESTDIR)
clean: arch_clean
- $(RM) kvmtrace *.o *.a .*.d $(libcflat) $(cflatobjs)
+ $(RM) *.o *.a .*.d $(libcflat) $(cflatobjs)
diff --git a/config-ia64.mak b/config-ia64.mak
deleted file mode 100644
index d9350fcc5a9ec..0000000000000
--- a/config-ia64.mak
+++ /dev/null
@@ -1,7 +0,0 @@
-bits = 64
-CFLAGS += -m64
-CFLAGS += -D__ia64__
-CFLAGS += -I../include/ia64
-
-all:
-
diff --git a/config-powerpc-440.mak b/config-powerpc-440.mak
deleted file mode 100644
index bb8597153b30e..0000000000000
--- a/config-powerpc-440.mak
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-# for some reason binutils hates tlbsx unless we say we're 405 :(
-CFLAGS += -Wa,-m405 -I lib/powerpc/44x
-
-cflatobjs += \
- lib/powerpc/44x/map.o \
- lib/powerpc/44x/tlbwe.o \
- lib/powerpc/44x/timebase.o
-
-simpletests += \
- powerpc/44x/tlbsx.bin \
- powerpc/44x/tlbwe_16KB.bin \
- powerpc/44x/tlbwe_hole.bin \
- powerpc/44x/tlbwe.bin
diff --git a/config-powerpc.mak b/config-powerpc.mak
deleted file mode 100644
index d053569b8aa3c..0000000000000
--- a/config-powerpc.mak
+++ /dev/null
@@ -1,39 +0,0 @@
-CFLAGS += -I../include/powerpc
-CFLAGS += -Wa,-mregnames -I lib
-CFLAGS += -ffreestanding
-
-cstart := powerpc/cstart.o
-
-cflatobjs += \
- lib/powerpc/io.o
-
-$(libcflat): LDFLAGS += -nostdlib
-
-# these tests do not use libcflat
-simpletests := \
- powerpc/spin.bin \
- powerpc/io.bin \
- powerpc/sprg.bin
-
-# theses tests use cstart.o, libcflat, and libgcc
-tests := \
- powerpc/exit.bin \
- powerpc/helloworld.bin
-
-include config-powerpc-$(PROCESSOR).mak
-
-
-all: kvmtrace kvmctl $(libcflat) $(simpletests) $(tests)
-
-$(simpletests): %.bin: %.o
- $(CC) -nostdlib $^ -Wl,-T,flat.lds -o $@
-
-$(tests): %.bin: $(cstart) %.o $(libcflat)
- $(CC) -nostdlib $^ $(libgcc) -Wl,-T,flat.lds -o $@
-
-kvmctl_objs = main-ppc.o iotable.o ../libkvm/libkvm.a
-
-arch_clean:
- $(RM) $(simpletests) $(tests) $(cstart)
- $(RM) $(patsubst %.bin, %.elf, $(simpletests) $(tests))
- $(RM) $(patsubst %.bin, %.o, $(simpletests) $(tests))
diff --git a/formats b/formats
deleted file mode 100644
index 7f4ebdbcedaa2..0000000000000
--- a/formats
+++ /dev/null
@@ -1,31 +0,0 @@
-0x00000000 %(ts)d (+%(relts)12d) unknown (0x%(event)016x) vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ 0x%(1)08x 0x%(2)08x 0x%(3)08x 0x%(4)08x 0x%(5)08x ]
-
-0x00010001 %(ts)d (+%(relts)12d) VMENTRY vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x
-0x00010002 %(ts)d (+%(relts)12d) VMEXIT vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ exitcode = 0x%(1)08x, rip = 0x%(3)08x %(2)08x ]
-0x00020001 %(ts)d (+%(relts)12d) PAGE_FAULT vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ errorcode = 0x%(1)08x, virt = 0x%(3)08x %(2)08x ]
-0x00020002 %(ts)d (+%(relts)12d) INJ_VIRQ vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ vector = 0x%(1)02x ]
-0x00020003 %(ts)d (+%(relts)12d) REDELIVER_EVT vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ vector = 0x%(1)02x ]
-0x00020004 %(ts)d (+%(relts)12d) PEND_INTR vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ vector = 0x%(1)02x ]
-0x00020005 %(ts)d (+%(relts)12d) IO_READ vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ port = 0x%(1)04x, size = %(2)d ]
-0x00020006 %(ts)d (+%(relts)12d) IO_WRITE vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ port = 0x%(1)04x, size = %(2)d ]
-0x00020007 %(ts)d (+%(relts)12d) CR_READ vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ CR# = %(1)d, value = 0x%(3)08x %(2)08x ]
-0x00020008 %(ts)d (+%(relts)12d) CR_WRITE vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ CR# = %(1)d, value = 0x%(3)08x %(2)08x ]
-0x00020009 %(ts)d (+%(relts)12d) DR_READ vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ DR# = %(1)d, value = 0x%(2)08x ]
-0x0002000A %(ts)d (+%(relts)12d) DR_WRITE vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ DR# = %(1)d, value = 0x%(2)08x ]
-0x0002000B %(ts)d (+%(relts)12d) MSR_READ vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ MSR# = 0x%(1)08x, data = 0x%(3)08x %(2)08x ]
-0x0002000C %(ts)d (+%(relts)12d) MSR_WRITE vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ MSR# = 0x%(1)08x, data = 0x%(3)08x %(2)08x ]
-0x0002000D %(ts)d (+%(relts)12d) CPUID vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ func = 0x%(1)08x, eax = 0x%(2)08x, ebx = 0x%(3)08x, ecx = 0x%(4)08x edx = 0x%(5)08x]
-0x0002000E %(ts)d (+%(relts)12d) INTR vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ vector = 0x%(1)02x ]
-0x0002000F %(ts)d (+%(relts)12d) NMI vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x
-0x00020010 %(ts)d (+%(relts)12d) VMMCALL vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ func = 0x%(1)08x ]
-0x00020011 %(ts)d (+%(relts)12d) HLT vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x
-0x00020012 %(ts)d (+%(relts)12d) CLTS vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x
-0x00020013 %(ts)d (+%(relts)12d) LMSW vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ value = 0x%(1)08x ]
-0x00020014 %(ts)d (+%(relts)12d) APIC_ACCESS vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ offset = 0x%(1)08x ]
-0x00020015 %(ts)d (+%(relts)12d) TDP_FAULT vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ errorcode = 0x%(1)08x, virt = 0x%(3)08x %(2)08x ]
-# ppc: tlb traces
-0x00020016 GTLB_WRITE vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ index = 0x%(1)08x, tid = 0x%(2)08x, word1=0x%(3)08x, word2=0x%(4)08x, word3=0x%(5)08x ]
-0x00020017 STLB_WRITE vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ index = 0x%(1)08x, tid = 0x%(2)08x, word1=0x%(3)08x, word2=0x%(4)08x, word3=0x%(5)08x ]
-0x00020018 STLB_INVAL vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ index = 0x%(1)08x, tid = 0x%(2)08x, word1=0x%(3)08x, word2=0x%(4)08x, word3=0x%(5)08x ]
-# ppc: instruction emulation - this type is handled more complex in kvmtrace_format, but listed to show the eventid and transported data
-#0x00020019 %(ts)d (+%(relts)12d) PPC_INSTR vcpu = 0x%(vcpu)08x pid = 0x%(pid)08x [ instr = 0x%(1)08x, pc = 0x%(2)08x, emul = 0x%(3)08x, nsec = %(4)08d ]
diff --git a/iotable.c b/iotable.c
deleted file mode 100644
index 91a5016c42005..0000000000000
--- a/iotable.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Kernel-based Virtual Machine test driver
- *
- * This test driver provides a simple way of testing kvm, without a full
- * device model.
- *
- * Copyright (C) 2006 Qumranet
- *
- * Authors:
- *
- * Avi Kivity <avi@qumranet.com>
- * Yaniv Kamay <yaniv@qumranet.com>
- *
- * This work is licensed under the GNU LGPL license, version 2.
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <errno.h>
-
-#include "iotable.h"
-
-struct io_table_entry *io_table_lookup(struct io_table *io_table, uint64_t addr)
-{
- int i;
-
- for (i = 0; i < io_table->nr_entries; i++) {
- if (io_table->entries[i].start <= addr &&
- addr < io_table->entries[i].end)
- return &io_table->entries[i];
- }
-
- return NULL;
-}
-
-int io_table_register(struct io_table *io_table, uint64_t start, uint64_t size,
- io_table_handler_t *handler, void *opaque)
-{
- struct io_table_entry *entry;
-
- if (io_table->nr_entries == MAX_IO_TABLE)
- return -ENOSPC;
-
- entry = &io_table->entries[io_table->nr_entries];
- io_table->nr_entries++;
-
- entry->start = start;
- entry->end = start + size;
- entry->handler = handler;
- entry->opaque = opaque;
-
- return 0;
-}
diff --git a/iotable.h b/iotable.h
deleted file mode 100644
index cb18f23789be1..0000000000000
--- a/iotable.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Kernel-based Virtual Machine test driver
- *
- * This test driver provides a simple way of testing kvm, without a full
- * device model.
- *
- * Copyright (C) 2006 Qumranet
- *
- * Authors:
- *
- * Avi Kivity <avi@qumranet.com>
- * Yaniv Kamay <yaniv@qumranet.com>
- *
- * This work is licensed under the GNU LGPL license, version 2.
- */
-
-#include <stdint.h>
-
-#define MAX_IO_TABLE 50
-
-typedef int (io_table_handler_t)(void *, int, int, uint64_t, uint64_t *);
-
-struct io_table_entry
-{
- uint64_t start;
- uint64_t end;
- io_table_handler_t *handler;
- void *opaque;
-};
-
-struct io_table
-{
- int nr_entries;
- struct io_table_entry entries[MAX_IO_TABLE];
-};
-
-struct io_table_entry *io_table_lookup(struct io_table *io_table,
- uint64_t addr);
-int io_table_register(struct io_table *io_table, uint64_t start, uint64_t size,
- io_table_handler_t *handler, void *opaque);
diff --git a/kvmtrace.c b/kvmtrace.c
deleted file mode 100644
index de3c1897f4660..0000000000000
--- a/kvmtrace.c
+++ /dev/null
@@ -1,706 +0,0 @@
-/*
- * kvm tracing application
- *
- * This tool is used for collecting trace buffer data
- * for kvm trace.
- *
- * Based on blktrace 0.99.3
- *
- * Copyright (C) 2005 Jens Axboe <axboe@suse.de>
- * Copyright (C) 2006 Jens Axboe <axboe@kernel.dk>
- * Copyright (C) 2008 Eric Liu <eric.e.liu@intel.com>
- *
- * This work is licensed under the GNU LGPL license, version 2.
- */
-
-#define _GNU_SOURCE
-
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/param.h>
-#include <sys/statfs.h>
-#include <sys/poll.h>
-#include <sys/mman.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <getopt.h>
-#include <errno.h>
-#include <sched.h>
-
-#ifndef __user
-#define __user
-#endif
-#include <linux/kvm.h>
-
-static char kvmtrace_version[] = "0.1";
-
-/*
- * You may want to increase this even more, if you are logging at a high
- * rate and see skipped/missed events
- */
-#define BUF_SIZE (512 * 1024)
-#define BUF_NR (8)
-
-#define OFILE_BUF (128 * 1024)
-
-#define DEBUGFS_TYPE 0x64626720
-
-#define max(a, b) ((a) > (b) ? (a) : (b))
-
-#define S_OPTS "r:o:w:?Vb:n:D:"
-static struct option l_opts[] = {
- {
- .name = "relay",
- .has_arg = required_argument,
- .flag = NULL,
- .val = 'r'
- },
- {
- .name = "output",
- .has_arg = required_argument,
- .flag = NULL,
- .val = 'o'
- },
- {
- .name = "stopwatch",
- .has_arg = required_argument,
- .flag = NULL,
- .val = 'w'
- },
- {
- .name = "version",
- .has_arg = no_argument,
- .flag = NULL,
- .val = 'V'
- },
- {
- .name = "buffer-size",
- .has_arg = required_argument,
- .flag = NULL,
- .val = 'b'
- },
- {
- .name = "num-sub-buffers",
- .has_arg = required_argument,
- .flag = NULL,
- .val = 'n'
- },
- {
- .name = "output-dir",
- .has_arg = required_argument,
- .flag = NULL,
- .val = 'D'
- },
- {
- .name = NULL,
- }
-};
-
-struct thread_information {
- int cpu;
- pthread_t thread;
-
- int fd;
- char fn[MAXPATHLEN + 64];
-
- FILE *ofile;
- char *ofile_buffer;
-
- int (*get_subbuf)(struct thread_information *, unsigned int);
- int (*read_data)(struct thread_information *, void *, unsigned int);
-
- unsigned long long data_read;
-
- struct kvm_trace_information *trace_info;
-
- int exited;
-
- /*
- * mmap controlled output files
- */
- unsigned long long fs_size;
- unsigned long long fs_max_size;
- unsigned long fs_off;
- void *fs_buf;
- unsigned long fs_buf_len;
-
-};
-
-struct kvm_trace_information {
- int fd;
- volatile int trace_started;
- unsigned long lost_records;
- struct thread_information *threads;
- unsigned long buf_size;
- unsigned long buf_nr;
-};
-
-static struct kvm_trace_information trace_information;
-
-static int ncpus;
-static char default_debugfs_path[] = "/sys/kernel/debug";
-
-/* command line option globals */
-static char *debugfs_path;
-static char *output_name;
-static char *output_dir;
-static int stop_watch;
-static unsigned long buf_size = BUF_SIZE;
-static unsigned long buf_nr = BUF_NR;
-static unsigned int page_size;
-
-#define for_each_cpu_online(cpu) \
- for (cpu = 0; cpu < ncpus; cpu++)
-#define for_each_tip(tip, i) \
- for (i = 0, tip = trace_information.threads; i < ncpus; i++, tip++)
-
-#define is_done() (*(volatile int *)(&done))
-static volatile int done;
-
-#define is_trace_stopped() (*(volatile int *)(&trace_stopped))
-static volatile int trace_stopped;
-
-static void exit_trace(int status);
-
-static void handle_sigint(__attribute__((__unused__)) int sig)
-{
- ioctl(trace_information.fd, KVM_TRACE_PAUSE);
- done = 1;
-}
-
-static int get_lost_records()
-{
- int fd;
- char tmp[MAXPATHLEN + 64];
-
- snprintf(tmp, sizeof(tmp), "%s/kvm/lost_records", debugfs_path);
- fd = open(tmp, O_RDONLY);
- if (fd < 0) {
- /*
- * this may be ok, if the kernel doesn't support dropped counts
- */
- if (errno == ENOENT)
- return 0;
-
- fprintf(stderr, "Couldn't open dropped file %s\n", tmp);
- return -1;
- }
-
- if (read(fd, tmp, sizeof(tmp)) < 0) {
- perror(tmp);
- close(fd);
- return -1;
- }
- close(fd);
-
- return atoi(tmp);
-}
-
-static void wait_for_data(struct thread_information *tip, int timeout)
-{
- struct pollfd pfd = { .fd = tip->fd, .events = POLLIN };
-
- while (!is_done()) {
- if (poll(&pfd, 1, timeout) < 0) {
- perror("poll");
- break;
- }
- if (pfd.revents & POLLIN)
- break;
- }
-}
-
-static int read_data(struct thread_information *tip, void *buf,
- unsigned int len)
-{
- int ret = 0;
-
- do {
- wait_for_data(tip, 100);
-
- ret = read(tip->fd, buf, len);
-
- if (!ret)
- continue;
- else if (ret > 0)
- return ret;
- else {
- if (errno != EAGAIN) {
- perror(tip->fn);
- fprintf(stderr, "Thread %d failed read of %s\n",
- tip->cpu, tip->fn);
- break;
- }
- continue;
- }
- } while (!is_done());
-
- return ret;
-
-}
-
-/*
- * For file output, truncate and mmap the file appropriately
- */
-static int mmap_subbuf(struct thread_information *tip, unsigned int maxlen)
-{
- int ofd = fileno(tip->ofile);
- int ret;
- unsigned long nr;
- unsigned long size;
-
- /*
- * extend file, if we have to. use chunks of 16 subbuffers.
- */
- if (tip->fs_off + maxlen > tip->fs_buf_len) {
- if (tip->fs_buf) {
- munlock(tip->fs_buf, tip->fs_buf_len);
- munmap(tip->fs_buf, tip->fs_buf_len);
- tip->fs_buf = NULL;
- }
-
- tip->fs_off = tip->fs_size & (page_size - 1);
- nr = max(16, tip->trace_info->buf_nr);
- size = tip->trace_info->buf_size;
- tip->fs_buf_len = (nr * size) - tip->fs_off;
- tip->fs_max_size += tip->fs_buf_len;
-
- if (ftruncate(ofd, tip->fs_max_size) < 0) {
- perror("ftruncate");
- return -1;
- }
-
- tip->fs_buf = mmap(NULL, tip->fs_buf_len, PROT_WRITE,
- MAP_SHARED, ofd, tip->fs_size - tip->fs_off);
- if (tip->fs_buf == MAP_FAILED) {
- perror("mmap");
- return -1;
- }
- mlock(tip->fs_buf, tip->fs_buf_len);
- }
-
- ret = tip->read_data(tip, tip->fs_buf + tip->fs_off, maxlen);
- if (ret >= 0) {
- tip->data_read += ret;
- tip->fs_size += ret;
- tip->fs_off += ret;
- return 0;
- }
-
- return -1;
-}
-
-static void tip_ftrunc_final(struct thread_information *tip)
-{
- /*
- * truncate to right size and cleanup mmap
- */
- if (tip->ofile) {
- int ofd = fileno(tip->ofile);
-
- if (tip->fs_buf)
- munmap(tip->fs_buf, tip->fs_buf_len);
-
- ftruncate(ofd, tip->fs_size);
- }
-}
-
-static void *thread_main(void *arg)
-{
- struct thread_information *tip = arg;
- pid_t pid = getpid();
- cpu_set_t cpu_mask;
-
- CPU_ZERO(&cpu_mask);
- CPU_SET((tip->cpu), &cpu_mask);
-
- if (sched_setaffinity(pid, sizeof(cpu_mask), &cpu_mask) == -1) {
- perror("sched_setaffinity");
- exit_trace(1);
- }
-
- snprintf(tip->fn, sizeof(tip->fn), "%s/kvm/trace%d",
- debugfs_path, tip->cpu);
- tip->fd = open(tip->fn, O_RDONLY);
- if (tip->fd < 0) {
- perror(tip->fn);
- fprintf(stderr, "Thread %d failed open of %s\n", tip->cpu,
- tip->fn);
- exit_trace(1);
- }
- while (!is_done()) {
- if (tip->get_subbuf(tip, tip->trace_info->buf_size) < 0)
- break;
- }
-
- /*
- * trace is stopped, pull data until we get a short read
- */
- while (tip->get_subbuf(tip, tip->trace_info->buf_size) > 0)
- ;
-
- tip_ftrunc_final(tip);
- tip->exited = 1;
- return NULL;
-}
-
-static int fill_ofname(struct thread_information *tip, char *dst)
-{
- struct stat sb;
- int len = 0;
-
- if (output_dir)
- len = sprintf(dst, "%s/", output_dir);
- else
- len = sprintf(dst, "./");
-
- if (stat(dst, &sb) < 0) {
- if (errno != ENOENT) {
- perror("stat");
- return 1;
- }
- if (mkdir(dst, 0755) < 0) {
- perror(dst);
- fprintf(stderr, "Can't make output dir\n");
- return 1;
- }
- }
-
- sprintf(dst + len, "%s.kvmtrace.%d", output_name, tip->cpu);
-
- return 0;
-}
-
-static void fill_ops(struct thread_information *tip)
-{
- tip->get_subbuf = mmap_subbuf;
- tip->read_data = read_data;
-}
-
-static void close_thread(struct thread_information *tip)
-{
- if (tip->fd != -1)
- close(tip->fd);
- if (tip->ofile)
- fclose(tip->ofile);
- if (tip->ofile_buffer)
- free(tip->ofile_buffer);
-
- tip->fd = -1;
- tip->ofile = NULL;
- tip->ofile_buffer = NULL;
-}
-
-static int tip_open_output(struct thread_information *tip)
-{
- int mode, vbuf_size;
- char op[NAME_MAX];
-
- if (fill_ofname(tip, op))
- return 1;
-
- tip->ofile = fopen(op, "w+");
- mode = _IOFBF;
- vbuf_size = OFILE_BUF;
-
- if (tip->ofile == NULL) {
- perror(op);
- return 1;
- }
-
- tip->ofile_buffer = malloc(vbuf_size);
- if (setvbuf(tip->ofile, tip->ofile_buffer, mode, vbuf_size)) {
- perror("setvbuf");
- close_thread(tip);
- return 1;
- }
-
- fill_ops(tip);
- return 0;
-}
-
-static int start_threads(int cpu)
-{
- struct thread_information *tip;
-
- tip = trace_information.threads + cpu;
- tip->cpu = cpu;
- tip->trace_info = &trace_information;
- tip->fd = -1;
-
- if (tip_open_output(tip))
- return 1;
-
- if (pthread_create(&tip->thread, NULL, thread_main, tip)) {
- perror("pthread_create");
- close_thread(tip);
- return 1;
- }
-
- return 0;
-}
-
-static void stop_threads()
-{
- struct thread_information *tip;
- unsigned long ret;
- int i;
-
- for_each_tip(tip, i) {
- if (tip->thread)
- (void) pthread_join(tip->thread, (void *) &ret);
- close_thread(tip);
- }
-}
-
-static int start_trace(void)
-{
- int fd;
- struct kvm_user_trace_setup kuts;
-
- fd = trace_information.fd = open("/dev/kvm", O_RDWR);
- if (fd == -1) {
- perror("/dev/kvm");
- return 1;
- }
-
- memset(&kuts, 0, sizeof(kuts));
- kuts.buf_size = trace_information.buf_size = buf_size;
- kuts.buf_nr = trace_information.buf_nr = buf_nr;
-
- if (ioctl(trace_information.fd , KVM_TRACE_ENABLE, &kuts) < 0) {
- perror("KVM_TRACE_ENABLE");
- close(fd);
- return 1;
- }
- trace_information.trace_started = 1;
-
- return 0;
-}
-
-static void cleanup_trace(void)
-{
- if (trace_information.fd == -1)
- return;
-
- trace_information.lost_records = get_lost_records();
-
- if (trace_information.trace_started) {
- trace_information.trace_started = 0;
- if (ioctl(trace_information.fd, KVM_TRACE_DISABLE) < 0)
- perror("KVM_TRACE_DISABLE");
- }
-
- close(trace_information.fd);
- trace_information.fd = -1;
-}
-
-static void stop_all_traces(void)
-{
- if (!is_trace_stopped()) {
- trace_stopped = 1;
- stop_threads();
- cleanup_trace();
- }
-}
-
-static void exit_trace(int status)
-{
- stop_all_traces();
- exit(status);
-}
-
-static int start_kvm_trace(void)
-{
- int i, size;
- struct thread_information *tip;
-
- size = ncpus * sizeof(struct thread_information);
- tip = malloc(size);
- if (!tip) {
- fprintf(stderr, "Out of memory, threads (%d)\n", size);
- return 1;
- }
- memset(tip, 0, size);
- trace_information.threads = tip;
-
- if (start_trace())
- return 1;
-
- for_each_cpu_online(i) {
- if (start_threads(i)) {
- fprintf(stderr, "Failed to start worker threads\n");
- break;
- }
- }
-
- if (i != ncpus) {
- stop_threads();
- cleanup_trace();
- return 1;
- }
-
- return 0;
-}
-
-static void wait_for_threads(void)
-{
- struct thread_information *tip;
- int i, tips_running;
-
- do {
- tips_running = 0;
- usleep(100000);
-
- for_each_tip(tip, i)
- tips_running += !tip->exited;
-
- } while (tips_running);
-}
-
-static void show_stats(void)
-{
- struct thread_information *tip;
- unsigned long long data_read;
- int i;
-
- data_read = 0;
- for_each_tip(tip, i) {
- printf(" CPU%3d: %8llu KiB data\n",
- tip->cpu, (tip->data_read + 1023) >> 10);
- data_read += tip->data_read;
- }
-
- printf(" Total: lost %lu, %8llu KiB data\n",
- trace_information.lost_records, (data_read + 1023) >> 10);
-
- if (trace_information.lost_records)
- fprintf(stderr, "You have lost records, "
- "consider using a larger buffer size (-b)\n");
-}
-
-static char usage_str[] = \
- "[ -r debugfs path ] [ -D output dir ] [ -b buffer size ]\n" \
- "[ -n number of buffers] [ -o <output file> ] [ -w time ] [ -V ]\n\n" \
- "\t-r Path to mounted debugfs, defaults to /sys/kernel/debug\n" \
- "\t-o File(s) to send output to\n" \
- "\t-D Directory to prepend to output file names\n" \
- "\t-w Stop after defined time, in seconds\n" \
- "\t-b Sub buffer size in KiB\n" \
- "\t-n Number of sub buffers\n" \
- "\t-V Print program version info\n\n";
-
-static void show_usage(char *prog)
-{
- fprintf(stderr, "Usage: %s %s %s", prog, kvmtrace_version, usage_str);
- exit(EXIT_FAILURE);
-}
-
-void parse_args(int argc, char **argv)
-{
- int c;
-
- while ((c = getopt_long(argc, argv, S_OPTS, l_opts, NULL)) >= 0) {
- switch (c) {
- case 'r':
- debugfs_path = optarg;
- break;
- case 'o':
- output_name = optarg;
- break;
- case 'w':
- stop_watch = atoi(optarg);
- if (stop_watch <= 0) {
- fprintf(stderr,
- "Invalid stopwatch value (%d secs)\n",
- stop_watch);
- exit(EXIT_FAILURE);
- }
- break;
- case 'V':
- printf("%s version %s\n", argv[0], kvmtrace_version);
- exit(EXIT_SUCCESS);
- case 'b':
- buf_size = strtoul(optarg, NULL, 10);
- if (buf_size <= 0 || buf_size > 16*1024) {
- fprintf(stderr,
- "Invalid buffer size (%lu)\n",
- buf_size);
- exit(EXIT_FAILURE);
- }
- buf_size <<= 10;
- break;
- case 'n':
- buf_nr = strtoul(optarg, NULL, 10);
- if (buf_nr <= 0) {
- fprintf(stderr,
- "Invalid buffer nr (%lu)\n", buf_nr);
- exit(EXIT_FAILURE);
- }
- break;
- case 'D':
- output_dir = optarg;
- break;
- default:
- show_usage(argv[0]);
- }
- }
-
- if (optind < argc || output_name == NULL)
- show_usage(argv[0]);
-}
-
-int main(int argc, char *argv[])
-{
- struct statfs st;
-
- parse_args(argc, argv);
-
- if (!debugfs_path)
- debugfs_path = default_debugfs_path;
-
- if (statfs(debugfs_path, &st) < 0) {
- perror("statfs");
- fprintf(stderr, "%s does not appear to be a valid path\n",
- debugfs_path);
- return 1;
- } else if (st.f_type != (long) DEBUGFS_TYPE) {
- fprintf(stderr, "%s does not appear to be a debug filesystem,"
- " please mount debugfs.\n",
- debugfs_path);
- return 1;
- }
-
- page_size = getpagesize();
-
- ncpus = sysconf(_SC_NPROCESSORS_ONLN);
- if (ncpus < 0) {
- fprintf(stderr, "sysconf(_SC_NPROCESSORS_ONLN) failed\n");
- return 1;
- }
-
- signal(SIGINT, handle_sigint);
- signal(SIGHUP, handle_sigint);
- signal(SIGTERM, handle_sigint);
- signal(SIGALRM, handle_sigint);
- signal(SIGPIPE, SIG_IGN);
-
- if (start_kvm_trace() != 0)
- return 1;
-
- if (stop_watch)
- alarm(stop_watch);
-
- wait_for_threads();
- stop_all_traces();
- show_stats();
-
- return 0;
-}
diff --git a/kvmtrace_format b/kvmtrace_format
deleted file mode 100755
index 6556475f726c4..0000000000000
--- a/kvmtrace_format
+++ /dev/null
@@ -1,532 +0,0 @@
-#!/usr/bin/env python
-
-# by Mark Williamson, (C) 2004 Intel Research Cambridge
-
-# Program for reformatting trace buffer output according to user-supplied rules
-
-import re, sys, string, signal, struct, os, getopt, operator
-
-PREFIX = '/usr'
-DATADIR = os.path.join(PREFIX, 'share')
-KVMDIR = os.path.join(DATADIR, 'kvm')
-FORMATS_FILE = os.path.join(KVMDIR, 'formats')
-
-def usage():
- print >> sys.stderr, \
- "Usage: " + sys.argv[0] + """ defs-file
- Parses trace data in binary format, as output by kvmtrace and
- reformats it according to the rules in a file of definitions. The
- rules in this file should have the format ({ and } show grouping
- and are not part of the syntax):
-
- {event_id}{whitespace}{text format string}
-
- The textual format string may include format specifiers, such as:
- %(ts)d, %(event)d, %(pid)d %(vcpu)d %(1)d, %(2)d,
- %(3)d, %(4)d, %(5)d
- [ the 'd' format specifier outputs in decimal, alternatively 'x'
- will output in hexadecimal and 'o' will output in octal ]
-
- Which correspond to the event ID, timestamp counter, pid
- , vcpu and the 5 data fields from the trace record. There should be
- one such rule for each type of event.
- Depending on your system and the volume of trace buffer data,
- this script may not be able to keep up with the output of kvmtrace
- if it is piped directly. In these circumstances you should have
- kvmtrace output to a file for processing off-line.
-
- kvmtrace_format has the following additional switches
- -s - if this switch is set additional trace statistics are
- created and printed at the end of the output
- """
- sys.exit(1)
-
-def read_defs(defs_file):
- defs = {}
-
- fd = open(defs_file)
-
- reg = re.compile('(\S+)\s+(\S.*)')
-
- while True:
- line = fd.readline()
- if not line:
- break
-
- if line[0] == '#' or line[0] == '\n':
- continue
-
- m = reg.match(line)
-
- if not m: print >> sys.stderr, "Bad format file" ; sys.exit(1)
-
- defs[str(eval(m.group(1)))] = m.group(2)
-
- return defs
-
-def sighand(x,y):
- global interrupted
- interrupted = 1
-
-# ppc instruction decoding for event type 0x00020019 (PPC_INSTR)
-# some globals for statistic summaries
-stat_ppc_instr_mnemonic = {};
-stat_ppc_instr_spr = {};
-stat_ppc_instr_dcr = {};
-stat_ppc_instr_tlb = {};
-
-def ppc_instr_print_summary(sortedlist, colname):
- print "\n\n%14s + %10s" % (colname, "count")
- print "%s" % (15*"-"+"+"+11*"-")
- sum = 0
- for value, key in sortedlist:
- sum += key
- print "%14s | %10d" % (value, key)
- print "%14s = %10d" % ("sum", sum)
-
-
-def ppc_instr_summary():
- # don't print empty statistics
- if stat_ppc_instr_mnemonic:
- ppc_instr_print_summary(sorted(stat_ppc_instr_mnemonic.iteritems(), key=operator.itemgetter(1), reverse=True), "mnemonic")
- if stat_ppc_instr_spr:
- ppc_instr_print_summary(sorted(stat_ppc_instr_spr.iteritems(), key=operator.itemgetter(1), reverse=True), "mnemonic-spr")
- if stat_ppc_instr_dcr:
- ppc_instr_print_summary(sorted(stat_ppc_instr_dcr.iteritems(), key=operator.itemgetter(1), reverse=True), "mnemonic-dcr")
- if stat_ppc_instr_tlb:
- ppc_instr_print_summary(sorted(stat_ppc_instr_tlb.iteritems(), key=operator.itemgetter(1), reverse=True), "mnemonic-tlb")
-
-def get_op(instr):
- return (instr >> 26);
-
-def get_xop(instr):
- return (instr >> 1) & 0x3ff;
-
-def get_sprn(instr):
- return ((instr >> 16) & 0x1f) | ((instr >> 6) & 0x3e0)
-
-def get_dcrn(instr):
- return ((instr >> 16) & 0x1f) | ((instr >> 6) & 0x3e0);
-
-def get_tlbwe_type(instr):
- ws = (instr >> 11) & 0x1f;
- if ws == 0:
- return "PAGEID"
- elif ws == 1:
- return "XLAT"
- elif ws == 2:
- return "ATTRIB"
- else:
- return "UNKNOWN"
-
-def get_name(instr):
- if get_op(instr)==3:
- return "trap"
- elif get_op(instr)==19:
- if get_xop(instr) == 50:
- return "rfi"
- else:
- return "unknown"
- elif get_op(instr)==31:
- if get_xop(instr) == 83:
- return "mfmsr"
-
- elif get_xop(instr) == 87:
- return "lbzx"
-
- elif get_xop(instr) == 131:
- return "wrtee"
-
- elif get_xop(instr) == 146:
- return "mtmsr"
-
- elif get_xop(instr) == 163:
- return "wrteei"
-
- elif get_xop(instr) == 215:
- return "stbx"
-
- elif get_xop(instr) == 247:
- return "stbux"
-
- elif get_xop(instr) == 279:
- return "lhzx"
-
- elif get_xop(instr) == 311:
- return "lhzux"
-
- elif get_xop(instr) == 323:
- return "mfdcr"
-
- elif get_xop(instr) == 339:
- return "mfspr"
-
- elif get_xop(instr) == 407:
- return "sthx"
-
- elif get_xop(instr) == 439:
- return "sthux"
-
- elif get_xop(instr) == 451:
- return "mtdcr"
-
- elif get_xop(instr) == 467:
- return "mtspr"
-
- elif get_xop(instr) == 470:
- return "dcbi"
-
- elif get_xop(instr) == 534:
- return "lwbrx"
-
- elif get_xop(instr) == 566:
- return "tlbsync"
-
- elif get_xop(instr) == 662:
- return "stwbrx"
-
- elif get_xop(instr) == 978:
- return "tlbwe"
-
- elif get_xop(instr) == 914:
- return "tlbsx"
-
- elif get_xop(instr) == 790:
- return "lhbrx"
-
- elif get_xop(instr) == 918:
- return "sthbrx"
-
- elif get_xop(instr) == 966:
- return "iccci"
-
- else:
- return "unknown"
-
- elif get_op(instr) == 32:
- return "lwz"
-
- elif get_op(instr) == 33:
- return "lwzu"
-
- elif get_op(instr) == 34:
- return "lbz"
-
- elif get_op(instr) == 35:
- return "lbzu"
-
- elif get_op(instr) == 36:
- return "stw"
-
- elif get_op(instr) == 37:
- return "stwu"
-
- elif get_op(instr) == 38:
- return "stb"
-
- elif get_op(instr) == 39:
- return "stbu"
-
- elif get_op(instr) == 40:
- return "lhz"
-
- elif get_op(instr) == 41:
- return "lhzu"
-
- elif get_op(instr) == 44:
- return "sth"
-
- elif get_op(instr) == 45:
- return "sthu"
-
- else:
- return "unknown"
-
-def get_sprn_name(sprn):
- if sprn == 0x01a:
- return "SRR0"
- elif sprn == 0x01b:
- return "SRR1"
- elif sprn == 0x3b2:
- return "MMUCR"
- elif sprn == 0x030:
- return "PID"
- elif sprn == 0x03f:
- return "IVPR"
- elif sprn == 0x3b3:
- return "CCR0"
- elif sprn == 0x378:
- return "CCR1"
- elif sprn == 0x11f:
- return "PVR"
- elif sprn == 0x03d:
- return "DEAR"
- elif sprn == 0x03e:
- return "ESR"
- elif sprn == 0x134:
- return "DBCR0"
- elif sprn == 0x135:
- return "DBCR1"
- elif sprn == 0x11c:
- return "TBWL"
- elif sprn == 0x11d:
- return "TBWU"
- elif sprn == 0x016:
- return "DEC"
- elif sprn == 0x150:
- return "TSR"
- elif sprn == 0x154:
- return "TCR"
- elif sprn == 0x110:
- return "SPRG0"
- elif sprn == 0x111:
- return "SPRG1"
- elif sprn == 0x112:
- return "SPRG2"
- elif sprn == 0x113:
- return "SPRG3"
- elif sprn == 0x114:
- return "SPRG4"
- elif sprn == 0x115:
- return "SPRG5"
- elif sprn == 0x116:
- return "SPRG6"
- elif sprn == 0x117:
- return "SPRG7"
- elif sprn == 0x190:
- return "IVOR0"
- elif sprn == 0x191:
- return "IVOR1"
- elif sprn == 0x192:
- return "IVOR2"
- elif sprn == 0x193:
- return "IVOR3"
- elif sprn == 0x194:
- return "IVOR4"
- elif sprn == 0x195:
- return "IVOR5"
- elif sprn == 0x196:
- return "IVOR6"
- elif sprn == 0x197:
- return "IVOR7"
- elif sprn == 0x198:
- return "IVOR8"
- elif sprn == 0x199:
- return "IVOR9"
- elif sprn == 0x19a:
- return "IVOR10"
- elif sprn == 0x19b:
- return "IVOR11"
- elif sprn == 0x19c:
- return "IVOR12"
- elif sprn == 0x19d:
- return "IVOR13"
- elif sprn == 0x19e:
- return "IVOR14"
- elif sprn == 0x19f:
- return "IVOR15"
- else:
- return "UNKNOWN"
-
-def get_special(instr):
- name = get_name(instr);
- if stat_ppc_instr_mnemonic.has_key(name):
- stat_ppc_instr_mnemonic[name] += 1
- else:
- stat_ppc_instr_mnemonic[name] = 1
-
- if get_op(instr) == 31:
- if (get_xop(instr) == 339) or (get_xop(instr) == 467):
- sprn = get_sprn(instr);
- sprn_name = get_sprn_name(sprn);
- stat_idx = name+"-"+sprn_name
- if stat_ppc_instr_spr.has_key(stat_idx):
- stat_ppc_instr_spr[stat_idx] += 1
- else:
- stat_ppc_instr_spr[stat_idx] = 1
- return ("- sprn 0x%03x %8s" % (sprn, sprn_name))
- elif (get_xop(instr) == 323 ) or (get_xop(instr) == 451):
- dcrn = get_dcrn(instr);
- stat_idx = name+"-"+("%04X"%dcrn)
- if stat_ppc_instr_dcr.has_key(stat_idx):
- stat_ppc_instr_dcr[stat_idx] += 1
- else:
- stat_ppc_instr_dcr[stat_idx] = 1
- return ("- dcrn 0x%03x" % dcrn)
- elif (get_xop(instr) == 978 ) or (get_xop(instr) == 451):
- tlbwe_type = get_tlbwe_type(instr)
- stat_idx = name+"-"+tlbwe_type
- if stat_ppc_instr_tlb.has_key(stat_idx):
- stat_ppc_instr_tlb[stat_idx] += 1
- else:
- stat_ppc_instr_tlb[stat_idx] = 1
- return ("- ws -> %8s" % tlbwe_type)
- return ""
-
-##### Main code
-
-summary = False
-
-try:
- opts, arg = getopt.getopt(sys.argv[1:], "sc:" )
- for opt in opts:
- if opt[0] == '-s' : summary = True
-
-except getopt.GetoptError:
- usage()
-
-signal.signal(signal.SIGTERM, sighand)
-signal.signal(signal.SIGHUP, sighand)
-signal.signal(signal.SIGINT, sighand)
-
-interrupted = 0
-
-if len(arg) > 0:
- defs = read_defs(arg[0])
-else:
- defs = read_defs(FORMATS_FILE)
-
-# structure of trace record (as output by kvmtrace):
-# HDR(I) {TSC(Q)} D1(I) D2(I) D3(I) D4(I) D5(I)
-#
-# HDR consists of EVENT:28:, n_data:3:, ts_in:1:
-# pid:32, vcpu_id:32
-# EVENT means Event ID
-# n_data means number of data (like D1, D2, ...)
-# ts_in means Timestamp data exists(1) or not(0).
-# if ts_in == 0, TSC(Q) does not exists.
-#
-HDRREC = "<III"
-TSCREC = "<Q"
-D1REC = "<I"
-D2REC = "<II"
-D3REC = "<III"
-D4REC = "<IIII"
-D5REC = "<IIIII"
-KMAGIC = "<I"
-
-last_ts = 0
-
-i=0
-
-while not interrupted:
- try:
- i=i+1
-
- if i == 1:
- line = sys.stdin.read(struct.calcsize(KMAGIC))
- if not line:
- break
- kmgc = struct.unpack(KMAGIC, line)[0]
-
- #firstly try to parse data file as little endian
- # if "kvmtrace-metadata".kmagic != kmagic
- # then data file must be big endian"
- if kmgc != 0x12345678:
- if kmgc != 0x78563412:
- print >> sys.stderr, "Bad data file: magic number error."
- break;
- else:
- HDRREC = ">III"
- TSCREC = ">Q"
- D1REC = ">I"
- D2REC = ">II"
- D3REC = ">III"
- D4REC = ">IIII"
- D5REC = ">IIIII"
- continue
-
- line = sys.stdin.read(struct.calcsize(HDRREC))
- if not line:
- break
- (event, pid, vcpu_id) = struct.unpack(HDRREC, line)
-
- n_data = event >> 28 & 0x7
- ts_in = event >> 31
-
- d1 = 0
- d2 = 0
- d3 = 0
- d4 = 0
- d5 = 0
-
- ts = 0
-
- if ts_in == 1:
- line = sys.stdin.read(struct.calcsize(TSCREC))
- if not line:
- break
- ts = struct.unpack(TSCREC, line)[0]
- if n_data == 1:
- line = sys.stdin.read(struct.calcsize(D1REC))
- if not line:
- break
- d1 = struct.unpack(D1REC, line)[0]
- if n_data == 2:
- line = sys.stdin.read(struct.calcsize(D2REC))
- if not line:
- break
- (d1, d2) = struct.unpack(D2REC, line)
- if n_data == 3:
- line = sys.stdin.read(struct.calcsize(D3REC))
- if not line:
- break
- (d1, d2, d3) = struct.unpack(D3REC, line)
- if n_data == 4:
- line = sys.stdin.read(struct.calcsize(D4REC))
- if not line:
- break
- (d1, d2, d3, d4) = struct.unpack(D4REC, line)
- if n_data == 5:
- line = sys.stdin.read(struct.calcsize(D5REC))
- if not line:
- break
- (d1, d2, d3, d4, d5) = struct.unpack(D5REC, line)
-
- event &= 0x0fffffff
-
- # provide relative TSC
-
- if last_ts > 0 and ts_in == 1:
- relts = ts - last_ts
- else:
- relts = 0
-
- if ts_in == 1:
- last_ts = ts
-
- args = {'ts' : ts,
- 'event' : event,
- 'relts': relts,
- 'pid' : pid,
- 'vcpu' : vcpu_id,
- '1' : d1,
- '2' : d2,
- '3' : d3,
- '4' : d4,
- '5' : d5 }
-
- # some event types need more than just formats mapping they are if/elif
- # chained here and the last default else is the mapping via formats
- if event == 0x00020019:
- pdata = (ts, relts, vcpu_id, pid, d1, d2, d3, get_name(d1), get_special(d1))
- print "%d (+%12d) PPC_INSTR vcpu = 0x%08x pid = 0x%08x [ instr = 0x%08x, pc = 0x%08x, emul = %01d, mnemonic = %8s %s" % pdata
- else:
- try:
- if defs.has_key(str(event)):
- print defs[str(event)] % args
- else:
- if defs.has_key(str(0)): print defs[str(0)] % args
- except TypeError:
- if defs.has_key(str(event)):
- print defs[str(event)]
- print args
- else:
- if defs.has_key(str(0)):
- print defs[str(0)]
- print args
-
- except IOError, struct.error: sys.exit()
-
-if summary:
- ppc_instr_summary()
diff --git a/lib/fwcfg.c b/lib/fwcfg.c
deleted file mode 100644
index dc34d299df766..0000000000000
--- a/lib/fwcfg.c
+++ /dev/null
@@ -1,58 +0,0 @@
-
-void qemu_cfg_select(int f)
-{
- outw(QEMU_CFG_CTL_PORT, f);
-}
-
-int qemu_cfg_port_probe()
-{
- char *sig = "QEMU";
- int i;
-
- qemu_cfg_select(QEMU_CFG_SIGNATURE);
-
- for (i = 0; i < 4; i++)
- if (inb(QEMU_CFG_DATA_PORT) != sig[i])
- return 0;
-
- return 1;
-}
-
-void qemu_cfg_read(uint8_t *buf, int len)
-{
- while (len--)
- *(buf++) = inb(QEMU_CFG_DATA_PORT);
-}
-
-uint8_t qemu_cfg_get8(void)
-{
- uint8_t ret;
-
- qemu_cfg_read(&ret, 1);
- return ret;
-}
-
-uint16_t qemu_cfg_get16(void)
-{
- uint16_t ret;
-
- qemu_cfg_read((uint8_t*)&ret, 2);
- return le16_to_cpu(ret);
-}
-
-uint64_t qemu_cfg_get32(void)
-{
- uint32_t ret;
-
- qemu_cfg_read((uint8_t*)&ret, 4);
- return le32_to_cpu(ret);
-}
-
-uint64_t qemu_cfg_get64(void)
-{
- uint64_t ret;
-
- qemu_cfg_read((uint8_t*)&ret, 8);
- return le64_to_cpu(ret);
-}
-
diff --git a/lib/libcflat.h b/lib/libcflat.h
index fadc33d30f85b..140c172e77d54 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -38,7 +38,6 @@ typedef _Bool bool;
#define false 0
extern void exit(int code);
-extern void panic(char *fmt, ...);
extern unsigned long strlen(const char *buf);
extern char *strcat(char *dest, const char *src);
diff --git a/lib/panic.c b/lib/panic.c
deleted file mode 100644
index 6e0b29ebed503..0000000000000
--- a/lib/panic.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "libcflat.h"
-
-void panic(char *fmt, ...)
-{
- va_list va;
- char buf[2000];
-
- va_start(va, fmt);
- vsnprintf(buf, sizeof(buf), fmt, va);
- va_end(va);
- puts(buf);
- exit(-1);
-}
diff --git a/lib/powerpc/44x/map.c b/lib/powerpc/44x/map.c
deleted file mode 100644
index 113434d2f1b4d..0000000000000
--- a/lib/powerpc/44x/map.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * 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 this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Copyright IBM Corp. 2008
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-#include "libcflat.h"
-
-#define TLB_SIZE 64
-
-extern void tlbwe(unsigned int index,
- unsigned char tid,
- unsigned int word0,
- unsigned int word1,
- unsigned int word2);
-
-unsigned int next_free_index;
-
-#define PAGE_SHIFT 12
-#define PAGE_MASK (~((1<<PAGE_SHIFT)-1))
-
-#define V (1<<9)
-
-void map(unsigned long vaddr, unsigned long paddr)
-{
- unsigned int w0, w1, w2;
-
- /* We don't install exception handlers, so we can't handle TLB misses,
- * so we can't loop around and overwrite entry 0. */
- if (next_free_index++ >= TLB_SIZE)
- panic("TLB overflow");
-
- w0 = (vaddr & PAGE_MASK) | V;
- w1 = paddr & PAGE_MASK;
- w2 = 0x3;
-
- tlbwe(next_free_index, 0, w0, w1, w2);
-}
diff --git a/lib/powerpc/44x/timebase.S b/lib/powerpc/44x/timebase.S
deleted file mode 100644
index 385904da3c161..0000000000000
--- a/lib/powerpc/44x/timebase.S
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * 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 this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Copyright IBM Corp. 2008
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-/* unsigned long long mftb(void); */
-.global mftb
-mftb:
- mftbu r5
- mftbl r4
- mftbu r3
- cmpw r3, r5
- bne mftb
- blr
diff --git a/lib/powerpc/44x/timebase.h b/lib/powerpc/44x/timebase.h
deleted file mode 100644
index ce85347bd17c5..0000000000000
--- a/lib/powerpc/44x/timebase.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * 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 this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Copyright IBM Corp. 2008
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-#ifndef __TIMEBASE_H__
-#define __TIMEBASE_H__
-
-unsigned long long mftb(void);
-
-#endif /* __TIMEBASE_H__ */
diff --git a/lib/powerpc/44x/tlbwe.S b/lib/powerpc/44x/tlbwe.S
deleted file mode 100644
index 3790374eb5c61..0000000000000
--- a/lib/powerpc/44x/tlbwe.S
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * 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 this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Copyright IBM Corp. 2008
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-#define SPRN_MMUCR 0x3b2
-
-/* tlbwe(uint index, uint8_t tid, uint word0, uint word1, uint word2) */
-.global tlbwe
-tlbwe:
- mtspr SPRN_MMUCR, r4
- tlbwe r5, r3, 0
- tlbwe r6, r3, 1
- tlbwe r7, r3, 2
- blr
diff --git a/lib/powerpc/io.c b/lib/powerpc/io.c
deleted file mode 100644
index 8bd239521f25f..0000000000000
--- a/lib/powerpc/io.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * 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 this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Copyright IBM Corp. 2008
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-#include "libcflat.h"
-
-#define BASE 0xf0000000
-#define _putc ((volatile char *)(BASE))
-#define _exit ((volatile char *)(BASE+1))
-
-void puts(const char *s)
-{
- while (*s != '\0')
- *_putc = *s++;
-}
-
-void exit(int code)
-{
- *_exit = code;
-}
diff --git a/main-ppc.c b/main-ppc.c
deleted file mode 100644
index 5af59f846ef07..0000000000000
--- a/main-ppc.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Kernel-based Virtual Machine test driver
- *
- * This test driver provides a simple way of testing kvm, without a full
- * device model.
- *
- * Copyright (C) 2006 Qumranet
- * Copyright IBM Corp. 2008
- *
- * Authors:
- *
- * Avi Kivity <avi@qumranet.com>
- * Yaniv Kamay <yaniv@qumranet.com>
- * Hollis Blanchard <hollisb@us.ibm.com>
- *
- * This work is licensed under the GNU LGPL license, version 2.
- */
-
-#define _GNU_SOURCE
-
-#include <libkvm.h>
-
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <semaphore.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <pthread.h>
-#include <signal.h>
-#include <pthread.h>
-#include <sys/syscall.h>
-#include <linux/unistd.h>
-#include <getopt.h>
-#include <stdbool.h>
-#include <inttypes.h>
-
-#include "iotable.h"
-
-static int gettid(void)
-{
- return syscall(__NR_gettid);
-}
-
-kvm_context_t kvm;
-
-#define IPI_SIGNAL (SIGRTMIN + 4)
-
-struct io_table mmio_table;
-
-static int ncpus = 1;
-static sem_t exited_sem;
-static __thread int vcpu;
-static sigset_t kernel_sigmask;
-static sigset_t ipi_sigmask;
-static uint64_t memory_size = 128 * 1024 * 1024;
-
-struct vcpu_info {
- pid_t tid;
-};
-
-struct vcpu_info *vcpus;
-
-/* Must match flat.lds linker script */
-#define VM_TEST_LOAD_ADDRESS 0x100000
-
-static int test_debug(void *opaque, void *vcpu)
-{
- printf("test_debug\n");
- return 0;
-}
-
-static int test_halt(void *opaque, int vcpu)
-{
- int n;
-
- sigwait(&ipi_sigmask, &n);
- return 0;
-}
-
-static int test_io_window(void *opaque)
-{
- return 0;
-}
-
-static int test_try_push_interrupts(void *opaque)
-{
- return 0;
-}
-
-static void test_post_kvm_run(void *opaque, void *vcpu)
-{
-}
-
-static int test_pre_kvm_run(void *opaque, void *vcpu)
-{
- return 0;
-}
-
-static int mmio_handler(void *opaque, int len, int is_write, uint64_t offset,
- uint64_t *data)
-{
- int r = 0;
-
- switch (offset) {
- case 0: /* putc */
- putc(*(char *)data, stdout);
- fflush(stdout);
- break;
- case 1: /* exit */
- r = *(char *)data;
- break;
- default:
- printf("%s: offset %"PRIx64" len %d data %"PRIx64"\n",
- __func__, offset, len, *(uint64_t *)data);
- r = -EINVAL;
- }
-
- return r;
-}
-
-static int test_mem_read(void *opaque, uint64_t addr, uint8_t *data, int len)
-{
- struct io_table_entry *iodev;
-
-#if 0
- printf("%s: addr %"PRIx64" len %d\n", __func__, addr, len);
-#endif
-
- iodev = io_table_lookup(&mmio_table, addr);
- if (!iodev) {
- printf("couldn't find device\n");
- return -ENODEV;
- }
-
- return iodev->handler(iodev->opaque, len, 0, addr - iodev->start,
- (uint64_t *)data);
-}
-
-static int test_mem_write(void *opaque, uint64_t addr, uint8_t *data, int len)
-{
- struct io_table_entry *iodev;
-
-#if 0
- printf("%s: addr %"PRIx64" len %d data %"PRIx64"\n",
- __func__, addr, len, *(uint64_t *)data);
-#endif
-
- iodev = io_table_lookup(&mmio_table, addr);
- if (!iodev) {
- printf("couldn't find device\n");
- return -ENODEV;
- }
-
- return iodev->handler(iodev->opaque, len, 1, addr - iodev->start,
- (uint64_t *)data);
-}
-
-static int test_dcr_read(int vcpu, uint32_t dcrn, uint32_t *data)
-{
- printf("%s: dcrn %04X\n", __func__, dcrn);
- *data = 0;
- return 0;
-}
-
-static int test_dcr_write(int vcpu, uint32_t dcrn, uint32_t data)
-{
- printf("%s: dcrn %04X data %04X\n", __func__, dcrn, data);
- return 0;
-}
-
-static struct kvm_callbacks test_callbacks = {
- .mmio_read = test_mem_read,
- .mmio_write = test_mem_write,
- .debug = test_debug,
- .halt = test_halt,
- .io_window = test_io_window,
- .try_push_interrupts = test_try_push_interrupts,
- .post_kvm_run = test_post_kvm_run,
- .pre_kvm_run = test_pre_kvm_run,
- .powerpc_dcr_read = test_dcr_read,
- .powerpc_dcr_write = test_dcr_write,
-};
-
-static unsigned long load_file(void *mem, const char *fname, int inval_icache)
-{
- ssize_t r;
- int fd;
- unsigned long bytes = 0;
-
- fd = open(fname, O_RDONLY);
- if (fd == -1) {
- perror("open");
- exit(1);
- }
-
- while ((r = read(fd, mem, 4096)) != -1 && r != 0) {
- mem += r;
- bytes += r;
- }
-
- if (r == -1) {
- perror("read");
- printf("read %d bytes\n", bytes);
- exit(1);
- }
-
- return bytes;
-}
-
-#define ICACHE_LINE_SIZE 32
-
-void sync_caches(void *mem, unsigned long len)
-{
- unsigned long i;
-
- for (i = 0; i < len; i += ICACHE_LINE_SIZE)
- asm volatile ("dcbst %0, %1" : : "g"(mem), "r"(i));
- asm volatile ("sync");
- for (i = 0; i < len; i += ICACHE_LINE_SIZE)
- asm volatile ("icbi %0, %1" : : "g"(mem), "r"(i));
- asm volatile ("sync; isync");
-}
-
-static void init_vcpu(int n)
-{
- sigemptyset(&ipi_sigmask);
- sigaddset(&ipi_sigmask, IPI_SIGNAL);
- sigprocmask(SIG_UNBLOCK, &ipi_sigmask, NULL);
- sigprocmask(SIG_BLOCK, &ipi_sigmask, &kernel_sigmask);
- vcpus[n].tid = gettid();
- vcpu = n;
- kvm_set_signal_mask(kvm, n, &kernel_sigmask);
-}
-
-static void *do_create_vcpu(void *_n)
-{
- struct kvm_regs regs;
- int n = (long)_n;
-
- kvm_create_vcpu(kvm, n);
- init_vcpu(n);
-
- kvm_get_regs(kvm, n, ®s);
- regs.pc = VM_TEST_LOAD_ADDRESS;
- kvm_set_regs(kvm, n, ®s);
-
- kvm_run(kvm, n, &vcpus[n]);
- sem_post(&exited_sem);
- return NULL;
-}
-
-static void start_vcpu(int n)
-{
- pthread_t thread;
-
- pthread_create(&thread, NULL, do_create_vcpu, (void *)(long)n);
-}
-
-static void usage(const char *progname)
-{
- fprintf(stderr,
-"Usage: %s [OPTIONS] [bootstrap] flatfile\n"
-"KVM test harness.\n"
-"\n"
-" -s, --smp=NUM create a VM with NUM virtual CPUs\n"
-" -m, --memory=NUM[GMKB] allocate NUM memory for virtual machine. A suffix\n"
-" can be used to change the unit (default: `M')\n"
-" -h, --help display this help screen and exit\n"
-"\n"
-"Report bugs to <kvm-ppc@vger.kernel.org>.\n"
- , progname);
-}
-
-static void sig_ignore(int sig)
-{
- write(1, "boo\n", 4);
-}
-
-int main(int argc, char **argv)
-{
- void *vm_mem;
- unsigned long len;
- int i;
- const char *sopts = "s:phm:";
- struct option lopts[] = {
- { "smp", 1, 0, 's' },
- { "memory", 1, 0, 'm' },
- { "help", 0, 0, 'h' },
- { 0 },
- };
- int opt_ind, ch;
- int nb_args;
- char *endptr;
-
- while ((ch = getopt_long(argc, argv, sopts, lopts, &opt_ind)) != -1) {
- switch (ch) {
- case 's':
- ncpus = atoi(optarg);
- break;
- case 'm':
- memory_size = strtoull(optarg, &endptr, 0);
- switch (*endptr) {
- case 'G': case 'g':
- memory_size <<= 30;
- break;
- case '\0':
- case 'M': case 'm':
- memory_size <<= 20;
- break;
- case 'K': case 'k':
- memory_size <<= 10;
- break;
- default:
- fprintf(stderr,
- "Unrecongized memory suffix: %c\n",
- *endptr);
- exit(1);
- }
- if (memory_size == 0) {
- fprintf(stderr,
- "Invalid memory size: 0\n");
- exit(1);
- }
- break;
- case 'h':
- usage(argv[0]);
- exit(0);
- case '?':
- default:
- fprintf(stderr,
- "Try `%s --help' for more information.\n",
- argv[0]);
- exit(1);
- }
- }
-
- nb_args = argc - optind;
- if (nb_args < 1 || nb_args > 2) {
- fprintf(stderr,
- "Incorrect number of arguments.\n"
- "Try `%s --help' for more information.\n",
- argv[0]);
- exit(1);
- }
-
- signal(IPI_SIGNAL, sig_ignore);
-
- vcpus = calloc(ncpus, sizeof *vcpus);
- if (!vcpus) {
- fprintf(stderr, "calloc failed\n");
- return 1;
- }
-
- kvm = kvm_init(&test_callbacks, 0);
- if (!kvm) {
- fprintf(stderr, "kvm_init failed\n");
- return 1;
- }
- if (kvm_create(kvm, memory_size, &vm_mem) < 0) {
- kvm_finalize(kvm);
- fprintf(stderr, "kvm_create failed\n");
- return 1;
- }
-
- vm_mem = kvm_create_phys_mem(kvm, 0, memory_size, 0, 1);
-
- len = load_file(vm_mem + VM_TEST_LOAD_ADDRESS, argv[optind], 1);
- sync_caches(vm_mem + VM_TEST_LOAD_ADDRESS, len);
-
- io_table_register(&mmio_table, 0xf0000000, 64, mmio_handler, NULL);
-
- sem_init(&exited_sem, 0, 0);
- for (i = 0; i < ncpus; ++i)
- start_vcpu(i);
- /* Wait for all vcpus to exit. */
- for (i = 0; i < ncpus; ++i)
- sem_wait(&exited_sem);
-
- return 0;
-}
diff --git a/powerpc/44x/tlbsx.S b/powerpc/44x/tlbsx.S
deleted file mode 100644
index b15874b18b74c..0000000000000
--- a/powerpc/44x/tlbsx.S
+++ /dev/null
@@ -1,33 +0,0 @@
-#define SPRN_MMUCR 0x3b2
-
-#define TLBWORD0 0x10000210
-#define TLBWORD1 0x10000000
-#define TLBWORD2 0x00000003
-
-.global _start
-_start:
- li r4, 0
- mtspr SPRN_MMUCR, r4
-
- li r3, 23
-
- lis r4, TLBWORD0@h
- ori r4, r4, TLBWORD0@l
- tlbwe r4, r3, 0
-
- lis r4, TLBWORD1@h
- ori r4, r4, TLBWORD1@l
- tlbwe r4, r3, 1
-
- lis r4, TLBWORD2@h
- ori r4, r4, TLBWORD2@l
- tlbwe r4, r3, 2
-
- lis r4, 0x1000
- tlbsx r5, r4, r0
- cmpwi r5, 23
- beq good
- trap
-
-good:
- b .
diff --git a/powerpc/44x/tlbwe.S b/powerpc/44x/tlbwe.S
deleted file mode 100644
index ec6ef5c57fc47..0000000000000
--- a/powerpc/44x/tlbwe.S
+++ /dev/null
@@ -1,27 +0,0 @@
-#define SPRN_MMUCR 0x3b2
-
-/* Create a mapping at 4MB */
-#define TLBWORD0 0x00400210
-#define TLBWORD1 0x00400000
-#define TLBWORD2 0x00000003
-
-.global _start
-_start:
- li r4, 0
- mtspr SPRN_MMUCR, r4
-
- li r3, 23
-
- lis r4, TLBWORD0@h
- ori r4, r4, TLBWORD0@l
- tlbwe r4, r3, 0
-
- lis r4, TLBWORD1@h
- ori r4, r4, TLBWORD1@l
- tlbwe r4, r3, 1
-
- lis r4, TLBWORD2@h
- ori r4, r4, TLBWORD2@l
- tlbwe r4, r3, 2
-
- b .
diff --git a/powerpc/44x/tlbwe_16KB.S b/powerpc/44x/tlbwe_16KB.S
deleted file mode 100644
index 1bd10bf17a187..0000000000000
--- a/powerpc/44x/tlbwe_16KB.S
+++ /dev/null
@@ -1,35 +0,0 @@
-#define SPRN_MMUCR 0x3b2
-
-/* 16KB mapping at 4MB */
-#define TLBWORD0 0x00400220
-#define TLBWORD1 0x00400000
-#define TLBWORD2 0x00000003
-
-.global _start
-_start:
- li r4, 0
- mtspr SPRN_MMUCR, r4
-
- li r3, 5
-
- lis r4, TLBWORD0@h
- ori r4, r4, TLBWORD0@l
- tlbwe r4, r3, 0
-
- lis r4, TLBWORD1@h
- ori r4, r4, TLBWORD1@l
- tlbwe r4, r3, 1
-
- lis r4, TLBWORD2@h
- ori r4, r4, TLBWORD2@l
- tlbwe r4, r3, 2
-
- /* load from 4MB */
- lis r3, 0x0040
- lwz r4, 0(r3)
-
- /* load from 4MB+8KB */
- ori r3, r3, 0x2000
- lwz r4, 0(r3)
-
- b .
diff --git a/powerpc/44x/tlbwe_hole.S b/powerpc/44x/tlbwe_hole.S
deleted file mode 100644
index 5efd30357daa9..0000000000000
--- a/powerpc/44x/tlbwe_hole.S
+++ /dev/null
@@ -1,27 +0,0 @@
-#define SPRN_MMUCR 0x3b2
-
-/* Try to map real address 1GB. */
-#define TLBWORD0 0x40000210
-#define TLBWORD1 0x40000000
-#define TLBWORD2 0x00000003
-
-.global _start
-_start:
- li r4, 0
- mtspr SPRN_MMUCR, r4
-
- li r3, 23
-
- lis r4, TLBWORD0@h
- ori r4, r4, TLBWORD0@l
- tlbwe r4, r3, 0
-
- lis r4, TLBWORD1@h
- ori r4, r4, TLBWORD1@l
- tlbwe r4, r3, 1
-
- lis r4, TLBWORD2@h
- ori r4, r4, TLBWORD2@l
- tlbwe r4, r3, 2
-
- b .
diff --git a/powerpc/cstart.S b/powerpc/cstart.S
deleted file mode 100644
index 70a0e9fcd47c9..0000000000000
--- a/powerpc/cstart.S
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation;
- *
- * 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 this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Copyright IBM Corp. 2008
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-#define OUTPUT_VADDR 0xf0000000
-#define OUTPUT_PADDR 0xf0000000
-
-.globl _start
-_start:
- /* In the future we might need to assign a stack and zero BSS here. */
-
- /* Map the debug page 1:1. */
- lis r3, OUTPUT_VADDR@h
- ori r3, r3, OUTPUT_VADDR@l
- lis r4, OUTPUT_PADDR@h
- ori r4, r4, OUTPUT_PADDR@l
- bl map
-
- /* Call main() and pass return code to exit(). */
- bl main
- bl exit
-
- b .
diff --git a/powerpc/exit.c b/powerpc/exit.c
deleted file mode 100644
index 804ee04d9f88e..0000000000000
--- a/powerpc/exit.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation;
- *
- * 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 this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Copyright IBM Corp. 2008
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-int main(void)
-{
- return 1;
-}
diff --git a/powerpc/helloworld.c b/powerpc/helloworld.c
deleted file mode 100644
index f8630f7c5381f..0000000000000
--- a/powerpc/helloworld.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation;
- *
- * 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 this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Copyright IBM Corp. 2008
- *
- * Authors: Deepa Srinivasan <deepas@us.ibm.com>
- */
-
-#include "libcflat.h"
-
-int main()
-{
- printf("Hello World\n");
-
- return 1;
-}
diff --git a/powerpc/io.S b/powerpc/io.S
deleted file mode 100644
index 97567cb6c73f2..0000000000000
--- a/powerpc/io.S
+++ /dev/null
@@ -1,32 +0,0 @@
-#define SPRN_MMUCR 0x3b2
-
-#define TLBWORD0 0xf0000210
-#define TLBWORD1 0xf0000000
-#define TLBWORD2 0x00000003
-
-.global _start
-_start:
- li r4, 0
- mtspr SPRN_MMUCR, r4
-
- li r3, 2
-
- lis r4, TLBWORD0@h
- ori r4, r4, TLBWORD0@l
- tlbwe r4, r3, 0
-
- lis r4, TLBWORD1@h
- ori r4, r4, TLBWORD1@l
- tlbwe r4, r3, 1
-
- lis r4, TLBWORD2@h
- ori r4, r4, TLBWORD2@l
- tlbwe r4, r3, 2
-
- lis r3, 0xf000
- lis r4, 0x1234
- ori r4, r4, 0x5678
- stb r4, 0(r3)
- lbz r5, 0(r3)
-
- b .
diff --git a/powerpc/spin.S b/powerpc/spin.S
deleted file mode 100644
index 4406641c2711c..0000000000000
--- a/powerpc/spin.S
+++ /dev/null
@@ -1,4 +0,0 @@
-
-.global _start
-_start:
- b .
diff --git a/powerpc/sprg.S b/powerpc/sprg.S
deleted file mode 100644
index d0414a480342a..0000000000000
--- a/powerpc/sprg.S
+++ /dev/null
@@ -1,7 +0,0 @@
-
-.global _start
-_start:
- li r3, 42
- mtsprg 0, r3
- mfsprg r4, 0
- b .
diff --git a/x86/print.h b/x86/print.h
deleted file mode 100644
index d5bd2f9978dc4..0000000000000
--- a/x86/print.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef PRINT_H
-#define PRINT_H
-
-.macro PRINT text
-
-.data
-
-333: .asciz "\text\n"
-
-.previous
-
- push %rdi
- lea 333b, %rdi
- call print
- pop %rdi
-
-.endm
-
-#endif
diff --git a/x86/run-kvm-unit-tests b/x86/run-kvm-unit-tests
deleted file mode 100644
index fed925a3d70fe..0000000000000
--- a/x86/run-kvm-unit-tests
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/python
-
-import sys, os, os.path
-
-prog = sys.argv[0]
-dir = os.path.dirname(prog)
--
1.8.1.4
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH 2/9] makefile and run_tests tweaks
2013-12-04 16:42 [PATCH 0/9 v2] kvm-unit-tests/arm: initial drop Andrew Jones
2013-12-04 16:42 ` [PATCH 1/9] remove unused files Andrew Jones
@ 2013-12-04 16:42 ` Andrew Jones
2013-12-29 6:30 ` Christoffer Dall
2013-12-04 16:42 ` [PATCH 3/9] clean root dir of all x86-ness Andrew Jones
` (6 subsequent siblings)
8 siblings, 1 reply; 44+ messages in thread
From: Andrew Jones @ 2013-12-04 16:42 UTC (permalink / raw)
To: kvmarm, kvm
- remove a redundant '-display none'
- remove a redundant -g from CFLAGS
- remove a useless -I../include/x86 from CFLAGS
- remove lib autodep files on make clean
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
Makefile | 8 ++++----
config-x86-common.mak | 16 +++++++---------
run_tests.sh | 2 +-
3 files changed, 12 insertions(+), 14 deletions(-)
diff --git a/Makefile b/Makefile
index 278791dbbef23..697fc2a766966 100644
--- a/Makefile
+++ b/Makefile
@@ -12,9 +12,9 @@ libgcc := $(shell $(CC) --print-libgcc-file-name)
libcflat := lib/libcflat.a
cflatobjs := \
+ lib/argv.o \
lib/printf.o \
lib/string.o
-cflatobjs += lib/argv.o
#include architecure specific make rules
include config-$(ARCH).mak
@@ -25,8 +25,8 @@ include config-$(ARCH).mak
cc-option = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null \
> /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
-CFLAGS += -O1
-CFLAGS += $(autodepend-flags) -g -fomit-frame-pointer -Wall
+CFLAGS += $(autodepend-flags) -Wall
+CFLAGS += $(call cc-option, -fomit-frame-pointer, "")
CFLAGS += $(call cc-option, -fno-stack-protector, "")
CFLAGS += $(call cc-option, -fno-stack-protector-all, "")
CFLAGS += -I.
@@ -51,4 +51,4 @@ install:
install $(tests_and_config) $(DESTDIR)
clean: arch_clean
- $(RM) *.o *.a .*.d $(libcflat) $(cflatobjs)
+ $(RM) *.o *.a .*.d lib/.*.d $(libcflat) $(cflatobjs)
diff --git a/config-x86-common.mak b/config-x86-common.mak
index bf88c672de472..7e481192a0737 100644
--- a/config-x86-common.mak
+++ b/config-x86-common.mak
@@ -1,13 +1,9 @@
#This is a make file with common rules for both x86 & x86-64
-CFLAGS += -I../include/x86
-
all: test_cases
-cflatobjs += \
- lib/x86/io.o \
- lib/x86/smp.o
-
+cflatobjs += lib/x86/io.o
+cflatobjs += lib/x86/smp.o
cflatobjs += lib/x86/vm.o
cflatobjs += lib/x86/fwcfg.o
cflatobjs += lib/x86/apic.o
@@ -20,15 +16,17 @@ $(libcflat): LDFLAGS += -nostdlib
$(libcflat): CFLAGS += -ffreestanding -I lib
CFLAGS += -m$(bits)
+CFLAGS += -O1
libgcc := $(shell $(CC) -m$(bits) --print-libgcc-file-name)
FLATLIBS = lib/libcflat.a $(libgcc)
%.elf: %.o $(FLATLIBS) flat.lds
- $(CC) $(CFLAGS) -nostdlib -o $@ -Wl,-T,flat.lds $(filter %.o, $^) $(FLATLIBS)
+ $(CC) $(CFLAGS) -nostdlib -o $@ -Wl,-T,flat.lds \
+ $(filter %.o, $^) $(FLATLIBS)
%.flat: %.elf
- objcopy -O elf32-i386 $^ $@
+ $(OBJCOPY) -O elf32-i386 $^ $@
tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \
$(TEST_DIR)/smptest.flat $(TEST_DIR)/port80.flat \
@@ -105,7 +103,7 @@ $(TEST_DIR)/vmx.elf: $(cstart.o) $(TEST_DIR)/vmx.o $(TEST_DIR)/vmx_tests.o
arch_clean:
$(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
- $(TEST_DIR)/.*.d $(TEST_DIR)/lib/.*.d $(TEST_DIR)/lib/*.o
+ $(TEST_DIR)/.*.d lib/x86/.*.d
api/%.o: CFLAGS += -m32
diff --git a/run_tests.sh b/run_tests.sh
index 55ecac5bed3a4..f373c533b75b2 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -27,7 +27,7 @@ function run()
return
fi
- cmdline="./x86-run $kernel -smp $smp -display none $opts"
+ cmdline="./x86-run $kernel -smp $smp $opts"
if [ $verbose != 0 ]; then
echo $cmdline
fi
--
1.8.1.4
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH 3/9] clean root dir of all x86-ness
2013-12-04 16:42 [PATCH 0/9 v2] kvm-unit-tests/arm: initial drop Andrew Jones
2013-12-04 16:42 ` [PATCH 1/9] remove unused files Andrew Jones
2013-12-04 16:42 ` [PATCH 2/9] makefile and run_tests tweaks Andrew Jones
@ 2013-12-04 16:42 ` Andrew Jones
2013-12-29 6:30 ` Christoffer Dall
2013-12-04 16:42 ` [PATCH 4/9] move x86's simple heap management to common code Andrew Jones
` (5 subsequent siblings)
8 siblings, 1 reply; 44+ messages in thread
From: Andrew Jones @ 2013-12-04 16:42 UTC (permalink / raw)
To: kvmarm, kvm
Remove all references to x86 from the root dir (except from in
configure). Also remove references from the root dir README
by moving that documentation to the x86/README, and touch up
the READMEs at the same time.
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v2:
- tests' images => test images [Christoffer Dall]
TODO:
- more documentation is still needed, we should add
* an overview of the framework
* improve the quickstart guide for running the tests
* add a quickstart guide for developing tests
---
Makefile | 7 ++-
README | 55 +++++++++-----------
config-i386.mak | 13 -----
config-x86-common.mak | 120 -------------------------------------------
config-x86_64.mak | 14 -----
config/config-i386.mak | 12 +++++
config/config-x86-common.mak | 120 +++++++++++++++++++++++++++++++++++++++++++
config/config-x86_64.mak | 13 +++++
configure | 17 ++++++
docs/testdev.txt | 11 ++++
flat.lds | 21 --------
run_tests.sh | 19 ++++---
testdev.txt | 14 -----
x86-run | 41 ---------------
x86/README | 60 +++++++++++++++++-----
x86/flat.lds | 21 ++++++++
x86/run | 41 +++++++++++++++
17 files changed, 316 insertions(+), 283 deletions(-)
delete mode 100644 config-i386.mak
delete mode 100644 config-x86-common.mak
delete mode 100644 config-x86_64.mak
create mode 100644 config/config-i386.mak
create mode 100644 config/config-x86-common.mak
create mode 100644 config/config-x86_64.mak
create mode 100644 docs/testdev.txt
delete mode 100644 flat.lds
delete mode 100644 testdev.txt
delete mode 100755 x86-run
create mode 100644 x86/flat.lds
create mode 100755 x86/run
diff --git a/Makefile b/Makefile
index 697fc2a766966..7a5ec8e6348bf 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ cflatobjs := \
lib/string.o
#include architecure specific make rules
-include config-$(ARCH).mak
+include config/config-$(ARCH).mak
# cc-option
# Usage: OP_CFLAGS+=$(call cc-option, -falign-functions=0, -malign-functions=0)
@@ -29,7 +29,6 @@ CFLAGS += $(autodepend-flags) -Wall
CFLAGS += $(call cc-option, -fomit-frame-pointer, "")
CFLAGS += $(call cc-option, -fno-stack-protector, "")
CFLAGS += $(call cc-option, -fno-stack-protector-all, "")
-CFLAGS += -I.
CXXFLAGS += $(CFLAGS)
@@ -44,11 +43,11 @@ $(libcflat): $(cflatobjs)
%.o: %.S
$(CC) $(CFLAGS) -c -nostdlib -o $@ $<
--include .*.d */.*.d */*/.*.d
+-include */.*.d */*/.*.d
install:
mkdir -p $(DESTDIR)
install $(tests_and_config) $(DESTDIR)
clean: arch_clean
- $(RM) *.o *.a .*.d lib/.*.d $(libcflat) $(cflatobjs)
+ $(RM) lib/.*.d $(libcflat) $(cflatobjs)
diff --git a/README b/README
index db525e3bbb79d..0174679c05021 100644
--- a/README
+++ b/README
@@ -1,36 +1,27 @@
This directory contains sources for a kvm test suite.
-Tests for x86 architecture are run as kernel images for qemu that supports multiboot format.
-Tests uses an infrastructure called from the bios code. The infrastructure initialize the system/cpu's,
-switch to long-mode and calls the 'main' function of the individual test.
-Tests uses a qemu's virtual test device, named testdev, for services like printing, exiting, query memory size etc.
-See file testdev.txt for more details.
-
-To create the tests' images just type 'make' in this directory.
-Tests' images created in ./<ARCH>/*.flat
-
-An example of a test invocation:
-Using qemu-kvm:
-
-qemu-kvm -device testdev,chardev=testlog -chardev file,id=testlog,path=msr.out -serial stdio -kernel ./x86/msr.flat
-This invocation runs the msr test case. The test outputs to stdio.
-
-Using qemu (supported since qemu 1.3):
-qemu-system-x86_64 -enable-kvm -device pc-testdev -serial stdio -device isa-debug-exit,iobase=0xf4,iosize=0x4 -kernel ./x86/msr.flat
-
-Or use a runner script to detect the correct invocation:
-./x86-run ./x86/msr.flat
-To select a specific qemu binary, specify the QEMU=<path> environment:
-QEMU=/tmp/qemu/x86_64-softmmu/qemu-system-x86_64 ./x86-run ./x86/msr.flat
-
-The exit status of the binary (and the script) is inconsistent: with
-qemu-system, after the unittest is done, the exit status of qemu is 1,
-different from the 'old style' qemu-kvm, whose exit status in successful
-completion is 0.
+To create the test images do
+ ./configure
+ make
+in this directory. Test images are created in ./<ARCH>/*.flat
+
+Then use the runner script to detect the correct invocation and
+invoke the test, e.g.
+ ./x86-run ./x86/msr.flat
+or
+ ./run_tests.sh
+to run them all.
+
+To select a specific qemu binary, specify the QEMU=<path>
+environment, e.g.
+ QEMU=/tmp/qemu/x86_64-softmmu/qemu-system-x86_64 ./x86-run ./x86/msr.flat
Directory structure:
-.: Makefile and config files for the tests
-./lib: general services for the tests
-./lib/<ARCH>: architecture dependent services for the tests
-./<ARCH>: the sources of the tests and the created objects/images
-
+.: Makefile and config files for the tests
+./config: config files for the tests
+./docs: documentation files
+./lib: general services for the tests
+./lib/<ARCH>: architecture dependent services for the tests
+./<ARCH>: the sources of the tests and the created objects/images
+
+See <ARCH>/README for arch specific documentation.
diff --git a/config-i386.mak b/config-i386.mak
deleted file mode 100644
index de52f3d53cff8..0000000000000
--- a/config-i386.mak
+++ /dev/null
@@ -1,13 +0,0 @@
-TEST_DIR=x86
-cstart.o = $(TEST_DIR)/cstart.o
-bits = 32
-ldarch = elf32-i386
-CFLAGS += -D__i386__
-CFLAGS += -I $(KERNELDIR)/include
-
-tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat
-
-include config-x86-common.mak
-
-$(TEST_DIR)/taskswitch.elf: $(cstart.o) $(TEST_DIR)/taskswitch.o
-$(TEST_DIR)/taskswitch2.elf: $(cstart.o) $(TEST_DIR)/taskswitch2.o
diff --git a/config-x86-common.mak b/config-x86-common.mak
deleted file mode 100644
index 7e481192a0737..0000000000000
--- a/config-x86-common.mak
+++ /dev/null
@@ -1,120 +0,0 @@
-#This is a make file with common rules for both x86 & x86-64
-
-all: test_cases
-
-cflatobjs += lib/x86/io.o
-cflatobjs += lib/x86/smp.o
-cflatobjs += lib/x86/vm.o
-cflatobjs += lib/x86/fwcfg.o
-cflatobjs += lib/x86/apic.o
-cflatobjs += lib/x86/atomic.o
-cflatobjs += lib/x86/desc.o
-cflatobjs += lib/x86/isr.o
-cflatobjs += lib/x86/pci.o
-
-$(libcflat): LDFLAGS += -nostdlib
-$(libcflat): CFLAGS += -ffreestanding -I lib
-
-CFLAGS += -m$(bits)
-CFLAGS += -O1
-
-libgcc := $(shell $(CC) -m$(bits) --print-libgcc-file-name)
-
-FLATLIBS = lib/libcflat.a $(libgcc)
-%.elf: %.o $(FLATLIBS) flat.lds
- $(CC) $(CFLAGS) -nostdlib -o $@ -Wl,-T,flat.lds \
- $(filter %.o, $^) $(FLATLIBS)
-
-%.flat: %.elf
- $(OBJCOPY) -O elf32-i386 $^ $@
-
-tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \
- $(TEST_DIR)/smptest.flat $(TEST_DIR)/port80.flat \
- $(TEST_DIR)/realmode.flat $(TEST_DIR)/msr.flat \
- $(TEST_DIR)/hypercall.flat $(TEST_DIR)/sieve.flat \
- $(TEST_DIR)/kvmclock_test.flat $(TEST_DIR)/eventinj.flat \
- $(TEST_DIR)/s3.flat $(TEST_DIR)/pmu.flat \
- $(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \
- $(TEST_DIR)/init.flat
-
-ifdef API
-tests-common += api/api-sample
-tests-common += api/dirty-log
-tests-common += api/dirty-log-perf
-endif
-
-tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg
-
-test_cases: $(tests-common) $(tests)
-
-$(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I lib -I lib/x86
-
-$(TEST_DIR)/access.elf: $(cstart.o) $(TEST_DIR)/access.o
-
-$(TEST_DIR)/hypercall.elf: $(cstart.o) $(TEST_DIR)/hypercall.o
-
-$(TEST_DIR)/sieve.elf: $(cstart.o) $(TEST_DIR)/sieve.o
-
-$(TEST_DIR)/vmexit.elf: $(cstart.o) $(TEST_DIR)/vmexit.o
-
-$(TEST_DIR)/smptest.elf: $(cstart.o) $(TEST_DIR)/smptest.o
-
-$(TEST_DIR)/emulator.elf: $(cstart.o) $(TEST_DIR)/emulator.o
-
-$(TEST_DIR)/port80.elf: $(cstart.o) $(TEST_DIR)/port80.o
-
-$(TEST_DIR)/tsc.elf: $(cstart.o) $(TEST_DIR)/tsc.o
-
-$(TEST_DIR)/tsc_adjust.elf: $(cstart.o) $(TEST_DIR)/tsc_adjust.o
-
-$(TEST_DIR)/apic.elf: $(cstart.o) $(TEST_DIR)/apic.o
-
-$(TEST_DIR)/init.elf: $(cstart.o) $(TEST_DIR)/init.o
-
-$(TEST_DIR)/realmode.elf: $(TEST_DIR)/realmode.o
- $(CC) -m32 -nostdlib -o $@ -Wl,-T,$(TEST_DIR)/realmode.lds $^
-
-$(TEST_DIR)/realmode.o: bits = 32
-
-$(TEST_DIR)/msr.elf: $(cstart.o) $(TEST_DIR)/msr.o
-
-$(TEST_DIR)/idt_test.elf: $(cstart.o) $(TEST_DIR)/idt_test.o
-
-$(TEST_DIR)/xsave.elf: $(cstart.o) $(TEST_DIR)/xsave.o
-
-$(TEST_DIR)/rmap_chain.elf: $(cstart.o) $(TEST_DIR)/rmap_chain.o
-
-$(TEST_DIR)/svm.elf: $(cstart.o)
-
-$(TEST_DIR)/kvmclock_test.elf: $(cstart.o) $(TEST_DIR)/kvmclock.o \
- $(TEST_DIR)/kvmclock_test.o
-
-$(TEST_DIR)/eventinj.elf: $(cstart.o) $(TEST_DIR)/eventinj.o
-
-$(TEST_DIR)/s3.elf: $(cstart.o) $(TEST_DIR)/s3.o
-
-$(TEST_DIR)/pmu.elf: $(cstart.o) $(TEST_DIR)/pmu.o
-
-$(TEST_DIR)/asyncpf.elf: $(cstart.o) $(TEST_DIR)/asyncpf.o
-
-$(TEST_DIR)/pcid.elf: $(cstart.o) $(TEST_DIR)/pcid.o
-
-$(TEST_DIR)/vmx.elf: $(cstart.o) $(TEST_DIR)/vmx.o $(TEST_DIR)/vmx_tests.o
-
-arch_clean:
- $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
- $(TEST_DIR)/.*.d lib/x86/.*.d
-
-api/%.o: CFLAGS += -m32
-
-api/%: LDLIBS += -lstdc++ -lboost_thread-mt -lpthread -lrt
-api/%: LDFLAGS += -m32
-
-api/libapi.a: api/kvmxx.o api/identity.o api/exception.o api/memmap.o
- $(AR) rcs $@ $^
-
-api/api-sample: api/api-sample.o api/libapi.a
-
-api/dirty-log: api/dirty-log.o api/libapi.a
-
-api/dirty-log-perf: api/dirty-log-perf.o api/libapi.a
diff --git a/config-x86_64.mak b/config-x86_64.mak
deleted file mode 100644
index bb8ee89713abd..0000000000000
--- a/config-x86_64.mak
+++ /dev/null
@@ -1,14 +0,0 @@
-TEST_DIR=x86
-cstart.o = $(TEST_DIR)/cstart64.o
-bits = 64
-ldarch = elf64-x86-64
-CFLAGS += -D__x86_64__
-
-tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \
- $(TEST_DIR)/emulator.flat $(TEST_DIR)/idt_test.flat \
- $(TEST_DIR)/xsave.flat $(TEST_DIR)/rmap_chain.flat \
- $(TEST_DIR)/pcid.flat
-tests += $(TEST_DIR)/svm.flat
-tests += $(TEST_DIR)/vmx.flat
-
-include config-x86-common.mak
diff --git a/config/config-i386.mak b/config/config-i386.mak
new file mode 100644
index 0000000000000..82fed0f5a48b0
--- /dev/null
+++ b/config/config-i386.mak
@@ -0,0 +1,12 @@
+cstart.o = $(TEST_DIR)/cstart.o
+bits = 32
+ldarch = elf32-i386
+CFLAGS += -D__i386__
+CFLAGS += -I $(KERNELDIR)/include
+
+tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat
+
+include config/config-x86-common.mak
+
+$(TEST_DIR)/taskswitch.elf: $(cstart.o) $(TEST_DIR)/taskswitch.o
+$(TEST_DIR)/taskswitch2.elf: $(cstart.o) $(TEST_DIR)/taskswitch2.o
diff --git a/config/config-x86-common.mak b/config/config-x86-common.mak
new file mode 100644
index 0000000000000..917cbbf801a65
--- /dev/null
+++ b/config/config-x86-common.mak
@@ -0,0 +1,120 @@
+#This is a make file with common rules for both x86 & x86-64
+
+all: test_cases
+
+cflatobjs += lib/x86/io.o
+cflatobjs += lib/x86/smp.o
+cflatobjs += lib/x86/vm.o
+cflatobjs += lib/x86/fwcfg.o
+cflatobjs += lib/x86/apic.o
+cflatobjs += lib/x86/atomic.o
+cflatobjs += lib/x86/desc.o
+cflatobjs += lib/x86/isr.o
+cflatobjs += lib/x86/pci.o
+
+$(libcflat): LDFLAGS += -nostdlib
+$(libcflat): CFLAGS += -ffreestanding -I lib
+
+CFLAGS += -m$(bits)
+CFLAGS += -O1
+
+libgcc := $(shell $(CC) -m$(bits) --print-libgcc-file-name)
+
+FLATLIBS = lib/libcflat.a $(libgcc)
+%.elf: %.o $(FLATLIBS) x86/flat.lds
+ $(CC) $(CFLAGS) -nostdlib -o $@ -Wl,-T,x86/flat.lds \
+ $(filter %.o, $^) $(FLATLIBS)
+
+%.flat: %.elf
+ $(OBJCOPY) -O elf32-i386 $^ $@
+
+tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \
+ $(TEST_DIR)/smptest.flat $(TEST_DIR)/port80.flat \
+ $(TEST_DIR)/realmode.flat $(TEST_DIR)/msr.flat \
+ $(TEST_DIR)/hypercall.flat $(TEST_DIR)/sieve.flat \
+ $(TEST_DIR)/kvmclock_test.flat $(TEST_DIR)/eventinj.flat \
+ $(TEST_DIR)/s3.flat $(TEST_DIR)/pmu.flat \
+ $(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \
+ $(TEST_DIR)/init.flat
+
+ifdef API
+tests-common += api/api-sample
+tests-common += api/dirty-log
+tests-common += api/dirty-log-perf
+endif
+
+tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg
+
+test_cases: $(tests-common) $(tests)
+
+$(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I lib -I lib/x86
+
+$(TEST_DIR)/access.elf: $(cstart.o) $(TEST_DIR)/access.o
+
+$(TEST_DIR)/hypercall.elf: $(cstart.o) $(TEST_DIR)/hypercall.o
+
+$(TEST_DIR)/sieve.elf: $(cstart.o) $(TEST_DIR)/sieve.o
+
+$(TEST_DIR)/vmexit.elf: $(cstart.o) $(TEST_DIR)/vmexit.o
+
+$(TEST_DIR)/smptest.elf: $(cstart.o) $(TEST_DIR)/smptest.o
+
+$(TEST_DIR)/emulator.elf: $(cstart.o) $(TEST_DIR)/emulator.o
+
+$(TEST_DIR)/port80.elf: $(cstart.o) $(TEST_DIR)/port80.o
+
+$(TEST_DIR)/tsc.elf: $(cstart.o) $(TEST_DIR)/tsc.o
+
+$(TEST_DIR)/tsc_adjust.elf: $(cstart.o) $(TEST_DIR)/tsc_adjust.o
+
+$(TEST_DIR)/apic.elf: $(cstart.o) $(TEST_DIR)/apic.o
+
+$(TEST_DIR)/init.elf: $(cstart.o) $(TEST_DIR)/init.o
+
+$(TEST_DIR)/realmode.elf: $(TEST_DIR)/realmode.o
+ $(CC) -m32 -nostdlib -o $@ -Wl,-T,$(TEST_DIR)/realmode.lds $^
+
+$(TEST_DIR)/realmode.o: bits = 32
+
+$(TEST_DIR)/msr.elf: $(cstart.o) $(TEST_DIR)/msr.o
+
+$(TEST_DIR)/idt_test.elf: $(cstart.o) $(TEST_DIR)/idt_test.o
+
+$(TEST_DIR)/xsave.elf: $(cstart.o) $(TEST_DIR)/xsave.o
+
+$(TEST_DIR)/rmap_chain.elf: $(cstart.o) $(TEST_DIR)/rmap_chain.o
+
+$(TEST_DIR)/svm.elf: $(cstart.o)
+
+$(TEST_DIR)/kvmclock_test.elf: $(cstart.o) $(TEST_DIR)/kvmclock.o \
+ $(TEST_DIR)/kvmclock_test.o
+
+$(TEST_DIR)/eventinj.elf: $(cstart.o) $(TEST_DIR)/eventinj.o
+
+$(TEST_DIR)/s3.elf: $(cstart.o) $(TEST_DIR)/s3.o
+
+$(TEST_DIR)/pmu.elf: $(cstart.o) $(TEST_DIR)/pmu.o
+
+$(TEST_DIR)/asyncpf.elf: $(cstart.o) $(TEST_DIR)/asyncpf.o
+
+$(TEST_DIR)/pcid.elf: $(cstart.o) $(TEST_DIR)/pcid.o
+
+$(TEST_DIR)/vmx.elf: $(cstart.o) $(TEST_DIR)/vmx.o $(TEST_DIR)/vmx_tests.o
+
+arch_clean:
+ $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
+ $(TEST_DIR)/.*.d lib/x86/.*.d
+
+api/%.o: CFLAGS += -m32
+
+api/%: LDLIBS += -lstdc++ -lboost_thread-mt -lpthread -lrt
+api/%: LDFLAGS += -m32
+
+api/libapi.a: api/kvmxx.o api/identity.o api/exception.o api/memmap.o
+ $(AR) rcs $@ $^
+
+api/api-sample: api/api-sample.o api/libapi.a
+
+api/dirty-log: api/dirty-log.o api/libapi.a
+
+api/dirty-log-perf: api/dirty-log-perf.o api/libapi.a
diff --git a/config/config-x86_64.mak b/config/config-x86_64.mak
new file mode 100644
index 0000000000000..f089b05a178c3
--- /dev/null
+++ b/config/config-x86_64.mak
@@ -0,0 +1,13 @@
+cstart.o = $(TEST_DIR)/cstart64.o
+bits = 64
+ldarch = elf64-x86-64
+CFLAGS += -D__x86_64__
+
+tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \
+ $(TEST_DIR)/emulator.flat $(TEST_DIR)/idt_test.flat \
+ $(TEST_DIR)/xsave.flat $(TEST_DIR)/rmap_chain.flat \
+ $(TEST_DIR)/pcid.flat
+tests += $(TEST_DIR)/svm.flat
+tests += $(TEST_DIR)/vmx.flat
+
+include config/config-x86-common.mak
diff --git a/configure b/configure
index d0c62e24dd1d2..6cfc64943f6e6 100755
--- a/configure
+++ b/configure
@@ -15,6 +15,7 @@ usage() {
Usage: $0 [options]
Options include:
+ --test-dir=DIR the main directory for tests ($arch)
--arch=ARCH architecture to compile for ($arch)
--cross-prefix=PREFIX cross compiler prefix
--cc=CC c compiler to use ($cc)
@@ -33,6 +34,9 @@ while [[ "$1" = -* ]]; do
opt="${opt%%=*}"
fi
case "$opt" in
+ --test-dir)
+ testdir="$arg"
+ ;;
--prefix)
prefix="$arg"
;;
@@ -62,6 +66,18 @@ while [[ "$1" = -* ]]; do
;;
esac
done
+if [ -z "$testdir" -a \( "$arch" = "i386" -o "$arch" = "x86_64" \) ]; then
+ testdir=x86
+elif [ -z "$testdir" ]; then
+ testdir=$arch
+fi
+if [ ! -d $testdir ]; then
+ echo "$testdir does not exist!"
+ exit 1
+fi
+if [ -f $testdir/run ]; then
+ ln -fs $testdir/run $testdir-run
+fi
# check for dependent 32 bit libraries
cat << EOF > lib_test.c
@@ -89,4 +105,5 @@ LD=$cross_prefix$ld
OBJCOPY=$cross_prefix$objcopy
AR=$cross_prefix$ar
API=$api
+TEST_DIR=$testdir
EOF
diff --git a/docs/testdev.txt b/docs/testdev.txt
new file mode 100644
index 0000000000000..854b5c774b60c
--- /dev/null
+++ b/docs/testdev.txt
@@ -0,0 +1,11 @@
+This file describes the virtual device of qemu for supporting this test suite.
+
+Services supplied by the testdev device:
+
+serial output: write only, on io port 0xf1
+exit process: write only, on io port 0xf4, value used as exit code
+ram size: read-only, on io port 0xd1, 4 bytes' size
+irq line setting: write only, on io ports 0x2000 - 0x2018, value to set/clear
+simple io: read/write, on io port 0xe0, 1/2/4 bytes
+
+Test device used a char device for actual output
diff --git a/flat.lds b/flat.lds
deleted file mode 100644
index a278b56c9a4e3..0000000000000
--- a/flat.lds
+++ /dev/null
@@ -1,21 +0,0 @@
-SECTIONS
-{
- . = 4M + SIZEOF_HEADERS;
- stext = .;
- .text : { *(.init) *(.text) *(.text.*) }
- . = ALIGN(4K);
- .data : {
- *(.data)
- exception_table_start = .;
- *(.data.ex)
- exception_table_end = .;
- }
- . = ALIGN(16);
- .rodata : { *(.rodata) }
- . = ALIGN(16);
- .bss : { *(.bss) }
- . = ALIGN(4K);
- edata = .;
-}
-
-ENTRY(start)
diff --git a/run_tests.sh b/run_tests.sh
index f373c533b75b2..400c62458ae18 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -1,8 +1,10 @@
#!/bin/bash
-testroot=x86
-config=$testroot/unittests.cfg
-qemu=${qemu:-qemu-system-x86_64}
+# As it happens, config.mak is valid shell script code, too :-)
+source config.mak
+
+config=$TEST_DIR/unittests.cfg
+qemu=${QEMU:-qemu-system-$ARCH}
verbose=0
function run()
@@ -27,7 +29,7 @@ function run()
return
fi
- cmdline="./x86-run $kernel -smp $smp $opts"
+ cmdline="./$TEST_DIR-run $kernel -smp $smp $opts"
if [ $verbose != 0 ]; then
echo $cmdline
fi
@@ -65,7 +67,7 @@ function run_all()
groups=""
arch=""
elif [[ $line =~ ^file\ *=\ *(.*)$ ]]; then
- kernel=$testroot/${BASH_REMATCH[1]}
+ kernel=$TEST_DIR/${BASH_REMATCH[1]}
elif [[ $line =~ ^smp\ *=\ *(.*)$ ]]; then
smp=${BASH_REMATCH[1]}
elif [[ $line =~ ^extra_params\ *=\ *(.*)$ ]]; then
@@ -92,15 +94,12 @@ Usage: $0 [-g group] [-h] [-v]
-h: Output this help text
-v: Enables verbose mode
-Set the environment variable QEMU=/path/to/qemu-system-x86_64 to allow the
-internally used x86-run to pick up the right qemu binary.
+Set the environment variable QEMU=/path/to/qemu-system-ARCH to allow the
+internally used ARCH-run to pick up the right qemu binary.
EOF
}
-# As it happens, config.mak is valid shell script code, too :-)
-source config.mak
-
echo > test.log
while getopts "g:hv" opt; do
case $opt in
diff --git a/testdev.txt b/testdev.txt
deleted file mode 100644
index ac436efadb633..0000000000000
--- a/testdev.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-This file describes the virtual device of qemu for supporting this test suite.
-
-Services supplied by the testdev device:
-
-serial output: write only, on io port 0xf1
-exit process: write only, on io port 0xf4, value used as exit code
-ram size: read-only, on io port 0xd1, 4 bytes' size
-irq line setting: write only, on io ports 0x2000 - 0x2018, value to set/clear
-simple io: read/write, on io port 0xe0, 1/2/4 bytes
-
-Test device used a char device for actual output
-
-
-
diff --git a/x86-run b/x86-run
deleted file mode 100755
index 646c5770ed03f..0000000000000
--- a/x86-run
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/bash
-
-qemukvm="${QEMU:-qemu-kvm}"
-qemusystem="${QEMU:-qemu-system-x86_64}"
-if
- ${qemukvm} -device '?' 2>&1 | grep -F -e \"testdev\" -e \"pc-testdev\" > /dev/null;
-then
- qemu="${qemukvm}"
-else
- if
- ${qemusystem} -device '?' 2>&1 | grep -F -e \"testdev\" -e \"pc-testdev\" > /dev/null;
- then
- qemu="${qemusystem}"
- else
- echo QEMU binary ${QEMU} has no support for test device. Exiting.
- exit 2
- fi
-fi
-
-if
- ${qemu} -device '?' 2>&1 | grep -F "pci-testdev" > /dev/null;
-then
- pci_testdev="-device pci-testdev"
-else
- pci_testdev=""
-fi
-
-if
- ${qemu} -device '?' 2>&1 | grep -F "pc-testdev" > /dev/null;
-then
- pc_testdev="-device pc-testdev -device isa-debug-exit,iobase=0xf4,iosize=0x4"
-else
- pc_testdev="-device testdev,chardev=testlog -chardev file,id=testlog,path=msr.out"
-fi
-
-command="${qemu} -enable-kvm $pc_testdev -display none -serial stdio $pci_testdev -kernel"
-echo ${command} "$@"
-${command} "$@"
-ret=$?
-echo Return value from qemu: $ret
-exit $ret
diff --git a/x86/README b/x86/README
index d644abdf31708..2f4baa46c6ed1 100644
--- a/x86/README
+++ b/x86/README
@@ -1,16 +1,48 @@
+
+Tests for x86 architecture are run as kernel images for qemu that supports
+multiboot format. Tests uses an infrastructure called from the bios code.
+The infrastructure initialize the system/cpu's, switch to long-mode and calls
+the 'main' function of the individual test. Tests uses a qemu's virtual test
+device, named testdev, for services like printing, exiting, query memory
+size etc. See file docs/testdev.txt for more details.
+
+An example of a test invocation:
+Using qemu-kvm:
+
+qemu-kvm -device testdev,chardev=testlog \
+ -chardev file,id=testlog,path=msr.out \
+ -serial stdio -kernel ./x86/msr.flat
+This invocation runs the msr test case. The test outputs to stdio.
+
+Using qemu (supported since qemu 1.3):
+qemu-system-x86_64 -enable-kvm -device pc-testdev -serial stdio \
+ -device isa-debug-exit,iobase=0xf4,iosize=0x4 \
+ -kernel ./x86/msr.flat
+
Tests in this directory and what they do:
-access: lots of page table related access (pte/pde) (read/write)
-apic: enable x2apic, self ipi, ioapic intr, ioapic simultaneous
-emulator: move to/from regs, cmps, push, pop, to/from cr8, smsw and lmsw
-hypercall: intel and amd hypercall insn
-msr: write to msr (only KERNEL_GS_BASE for now)
-port80: lots of out to port 80
-realmode: goes back to realmode, shld, push/pop, mov immediate, cmp immediate, add immediate,
- io, eflags instructions (clc, cli, etc.), jcc short, jcc near, call, long jmp, xchg
-sieve: heavy memory access with no paging and with paging static and with paging vmalloc'ed
-smptest: run smp_id() on every cpu and compares return value to number
-tsc: write to tsc(0) and write to tsc(100000000000) and read it back
-vmexit: long loops for each: cpuid, vmcall, mov_from_cr8, mov_to_cr8, inl_pmtimer, ipi, ipi+halt
-kvmclock_test: test of wallclock, monotonic cycle and performance of kvmclock
-pcid: basic functionality test of PCID/INVPCID feature
\ No newline at end of file
+ access: lots of page table related access (pte/pde) (read/write)
+ apic: enable x2apic, self ipi, ioapic intr, ioapic simultaneous
+ emulator: move to/from regs, cmps, push, pop, to/from cr8, smsw and lmsw
+ hypercall: intel and amd hypercall insn
+ msr: write to msr (only KERNEL_GS_BASE for now)
+ port80: lots of out to port 80
+ realmode: goes back to realmode, shld, push/pop, mov immediate,
+ cmp immediate, add immediate, io, eflags instructions
+ (clc, cli, etc.), jcc short, jcc near, call, long jmp, xchg
+ sieve: heavy memory access with no paging and with paging static and
+ with paging vmalloc'ed
+ smptest: run smp_id() on every cpu and compares return value to number
+ tsc: write to tsc(0) and write to tsc(100000000000) and read it back
+ vmexit: long loops for each: cpuid, vmcall, mov_from_cr8, mov_to_cr8,
+ inl_pmtimer, ipi, ipi+halt
+ kvmclock_test: test of wallclock, monotonic cycle and performance of kvmclock
+ pcid: basic functionality test of PCID/INVPCID featureThis directory
+ contains sources for a kvm test suite.
+
+Legacy notes:
+
+ The exit status of the binary (and the script) is inconsistent: with
+ qemu-system, after the unittest is done, the exit status of qemu is 1,
+ different from the 'old style' qemu-kvm, whose exit status in successful
+ completion is 0.
diff --git a/x86/flat.lds b/x86/flat.lds
new file mode 100644
index 0000000000000..a278b56c9a4e3
--- /dev/null
+++ b/x86/flat.lds
@@ -0,0 +1,21 @@
+SECTIONS
+{
+ . = 4M + SIZEOF_HEADERS;
+ stext = .;
+ .text : { *(.init) *(.text) *(.text.*) }
+ . = ALIGN(4K);
+ .data : {
+ *(.data)
+ exception_table_start = .;
+ *(.data.ex)
+ exception_table_end = .;
+ }
+ . = ALIGN(16);
+ .rodata : { *(.rodata) }
+ . = ALIGN(16);
+ .bss : { *(.bss) }
+ . = ALIGN(4K);
+ edata = .;
+}
+
+ENTRY(start)
diff --git a/x86/run b/x86/run
new file mode 100755
index 0000000000000..646c5770ed03f
--- /dev/null
+++ b/x86/run
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+qemukvm="${QEMU:-qemu-kvm}"
+qemusystem="${QEMU:-qemu-system-x86_64}"
+if
+ ${qemukvm} -device '?' 2>&1 | grep -F -e \"testdev\" -e \"pc-testdev\" > /dev/null;
+then
+ qemu="${qemukvm}"
+else
+ if
+ ${qemusystem} -device '?' 2>&1 | grep -F -e \"testdev\" -e \"pc-testdev\" > /dev/null;
+ then
+ qemu="${qemusystem}"
+ else
+ echo QEMU binary ${QEMU} has no support for test device. Exiting.
+ exit 2
+ fi
+fi
+
+if
+ ${qemu} -device '?' 2>&1 | grep -F "pci-testdev" > /dev/null;
+then
+ pci_testdev="-device pci-testdev"
+else
+ pci_testdev=""
+fi
+
+if
+ ${qemu} -device '?' 2>&1 | grep -F "pc-testdev" > /dev/null;
+then
+ pc_testdev="-device pc-testdev -device isa-debug-exit,iobase=0xf4,iosize=0x4"
+else
+ pc_testdev="-device testdev,chardev=testlog -chardev file,id=testlog,path=msr.out"
+fi
+
+command="${qemu} -enable-kvm $pc_testdev -display none -serial stdio $pci_testdev -kernel"
+echo ${command} "$@"
+${command} "$@"
+ret=$?
+echo Return value from qemu: $ret
+exit $ret
--
1.8.1.4
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH 4/9] move x86's simple heap management to common code
2013-12-04 16:42 [PATCH 0/9 v2] kvm-unit-tests/arm: initial drop Andrew Jones
` (2 preceding siblings ...)
2013-12-04 16:42 ` [PATCH 3/9] clean root dir of all x86-ness Andrew Jones
@ 2013-12-04 16:42 ` Andrew Jones
2013-12-29 6:30 ` Christoffer Dall
2013-12-04 16:42 ` [PATCH 5/9] Introduce libio to common code for io read/write Andrew Jones
` (4 subsequent siblings)
8 siblings, 1 reply; 44+ messages in thread
From: Andrew Jones @ 2013-12-04 16:42 UTC (permalink / raw)
To: kvmarm, kvm
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
config/config-x86-common.mak | 1 +
lib/heap.c | 43 +++++++++++++++++++++++++++++++++++++++++++
lib/heap.h | 8 ++++++++
lib/x86/vm.c | 33 ++-------------------------------
4 files changed, 54 insertions(+), 31 deletions(-)
create mode 100644 lib/heap.c
create mode 100644 lib/heap.h
diff --git a/config/config-x86-common.mak b/config/config-x86-common.mak
index 917cbbf801a65..8a78f7a6c8849 100644
--- a/config/config-x86-common.mak
+++ b/config/config-x86-common.mak
@@ -2,6 +2,7 @@
all: test_cases
+cflatobjs += lib/heap.o
cflatobjs += lib/x86/io.o
cflatobjs += lib/x86/smp.o
cflatobjs += lib/x86/vm.o
diff --git a/lib/heap.c b/lib/heap.c
new file mode 100644
index 0000000000000..e52ee0edba163
--- /dev/null
+++ b/lib/heap.c
@@ -0,0 +1,43 @@
+#include "libcflat.h"
+
+static size_t pagesize;
+static void *free_head;
+
+void heap_init(void *start, size_t size, size_t page_size)
+{
+ unsigned long s = (unsigned long)start;
+ void *p = start;
+
+ pagesize = page_size;
+
+ if (s != (s & ~(pagesize - 1))) {
+ s += pagesize;
+ s &= ~(pagesize - 1);
+ p = (void *)s;
+ }
+
+ while (size >= pagesize) {
+ *(void **)p = free_head;
+ free_head = p;
+ p += pagesize;
+ size -= pagesize;
+ }
+}
+
+void *alloc_page(void)
+{
+ void *p;
+
+ if (!free_head)
+ return NULL;
+
+ p = free_head;
+ free_head = *(void **)free_head;
+ return p;
+}
+
+void free_page(void *page)
+{
+ *(void **)page = free_head;
+ free_head = page;
+}
diff --git a/lib/heap.h b/lib/heap.h
new file mode 100644
index 0000000000000..78b893021ae92
--- /dev/null
+++ b/lib/heap.h
@@ -0,0 +1,8 @@
+#ifndef _HEAP_H_
+#define _HEAP_H_
+#include "libcflat.h"
+
+extern void heap_init(void *start, size_t size, size_t page_size);
+extern void *alloc_page(void);
+extern void free_page(void *page);
+#endif
diff --git a/lib/x86/vm.c b/lib/x86/vm.c
index 188bf57587aa7..725cfe33259c2 100644
--- a/lib/x86/vm.c
+++ b/lib/x86/vm.c
@@ -1,6 +1,7 @@
#include "fwcfg.h"
#include "vm.h"
#include "libcflat.h"
+#include "heap.h"
#define PAGE_SIZE 4096ul
#ifdef __x86_64__
@@ -9,38 +10,8 @@
#define LARGE_PAGE_SIZE (1024 * PAGE_SIZE)
#endif
-static void *free = 0;
static void *vfree_top = 0;
-static void free_memory(void *mem, unsigned long size)
-{
- while (size >= PAGE_SIZE) {
- *(void **)mem = free;
- free = mem;
- mem += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
-}
-
-void *alloc_page()
-{
- void *p;
-
- if (!free)
- return 0;
-
- p = free;
- free = *(void **)free;
-
- return p;
-}
-
-void free_page(void *page)
-{
- *(void **)page = free;
- free = page;
-}
-
extern char edata;
static unsigned long end_of_memory;
@@ -185,7 +156,7 @@ static void setup_mmu(unsigned long len)
void setup_vm()
{
end_of_memory = fwcfg_get_u64(FW_CFG_RAM_SIZE);
- free_memory(&edata, end_of_memory - (unsigned long)&edata);
+ heap_init(&edata, end_of_memory - (unsigned long)&edata, PAGE_SIZE);
setup_mmu(end_of_memory);
}
--
1.8.1.4
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH 5/9] Introduce libio to common code for io read/write
2013-12-04 16:42 [PATCH 0/9 v2] kvm-unit-tests/arm: initial drop Andrew Jones
` (3 preceding siblings ...)
2013-12-04 16:42 ` [PATCH 4/9] move x86's simple heap management to common code Andrew Jones
@ 2013-12-04 16:42 ` Andrew Jones
2013-12-29 6:30 ` Christoffer Dall
2013-12-04 16:42 ` [PATCH 6/9] Introduce a simple iomap structure Andrew Jones
` (3 subsequent siblings)
8 siblings, 1 reply; 44+ messages in thread
From: Andrew Jones @ 2013-12-04 16:42 UTC (permalink / raw)
To: kvmarm, kvm
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
lib/libio.c | 67 +++++++++++++++++++++++
lib/libio.h | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 243 insertions(+)
create mode 100644 lib/libio.c
create mode 100644 lib/libio.h
diff --git a/lib/libio.c b/lib/libio.c
new file mode 100644
index 0000000000000..e450e984fefb1
--- /dev/null
+++ b/lib/libio.c
@@ -0,0 +1,67 @@
+#include "libcflat.h"
+#include "libio.h"
+
+void read_len(const volatile void *addr, void *buf, unsigned len)
+{
+ unsigned long val;
+
+ switch (len) {
+ case 1:
+ val = readb(addr);
+ break;
+ case 2:
+ val = readw(addr);
+ break;
+ case 4:
+ val = readl(addr);
+ break;
+#ifdef CONFIG_64BIT
+ case 8:
+ val = readq(addr);
+ break;
+#endif
+ default:
+ {
+ u8 *p = buf;
+ unsigned i;
+
+ for (i = 0; i < len; ++i)
+ p[i] = readb(addr + i);
+ return;
+ }
+ }
+ memcpy(buf, &val, len);
+}
+
+void write_len(volatile void *addr, const void *buf, unsigned len)
+{
+ unsigned long val;
+
+ if (len <= sizeof(unsigned long))
+ memcpy(&val, buf, len);
+
+ switch (len) {
+ case 1:
+ writeb(val, addr);
+ break;
+ case 2:
+ writew(val, addr);
+ break;
+ case 4:
+ writel(val, addr);
+ break;
+#ifdef CONFIG_64BIT
+ case 8:
+ writeq(val, addr);
+ break;
+#endif
+ default:
+ {
+ const u8 *p = buf;
+ unsigned i;
+
+ for (i = 0; i < len; ++i)
+ writeb(p[i], addr + i);
+ }
+ }
+}
diff --git a/lib/libio.h b/lib/libio.h
new file mode 100644
index 0000000000000..210b8d78af43f
--- /dev/null
+++ b/lib/libio.h
@@ -0,0 +1,176 @@
+#ifndef _LIBIO_H_
+#define _LIBIO_H_
+/*
+ * Adapted from the Linux kernel's include/asm-generic/io.h and
+ * arch/arm/include/asm/io.h
+ */
+#include "libcflat.h"
+
+typedef u32 compat_ptr_t;
+
+static inline void *compat_ptr(compat_ptr_t ptr)
+{
+ return (void *)(unsigned long)ptr;
+}
+
+static inline compat_ptr_t ptr_to_compat(void *ptr)
+{
+ return (u32)(unsigned long)ptr;
+}
+
+#ifndef __raw_readb
+static inline u8 __raw_readb(const volatile void *addr)
+{
+ return *(const volatile u8 *)addr;
+}
+#endif
+
+#ifndef __raw_readw
+static inline u16 __raw_readw(const volatile void *addr)
+{
+ return *(const volatile u16 *)addr;
+}
+#endif
+
+#ifndef __raw_readl
+static inline u32 __raw_readl(const volatile void *addr)
+{
+ return *(const volatile u32 *)addr;
+}
+#endif
+
+#ifdef CONFIG_64BIT
+#ifndef __raw_readq
+static inline u64 __raw_readq(const volatile void *addr)
+{
+ return *(const volatile u64 *)addr;
+}
+#endif
+#endif
+
+#ifndef __raw_writeb
+static inline void __raw_writeb(u8 b, volatile void *addr)
+{
+ *(volatile u8 *)addr = b;
+}
+#endif
+
+#ifndef __raw_writew
+static inline void __raw_writew(u16 b, volatile void *addr)
+{
+ *(volatile u16 *)addr = b;
+}
+#endif
+
+#ifndef __raw_writel
+static inline void __raw_writel(u32 b, volatile void *addr)
+{
+ *(volatile u32 *)addr = b;
+}
+#endif
+
+#ifdef CONFIG_64BIT
+#ifndef __raw_writeq
+static inline void __raw_writeq(u64 b, volatile void *addr)
+{
+ *(volatile u64 *)addr = b;
+}
+#endif
+#endif
+
+#ifndef __bswap16
+static inline u16 __bswap16(u16 x)
+{
+ return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
+}
+#endif
+
+#ifndef __bswap32
+static inline u32 __bswap32(u32 x)
+{
+ return ((x & 0xff000000) >> 24) | ((x & 0x00ff0000) >> 8) |
+ ((x & 0x0000ff00) << 8) | ((x & 0x000000ff) << 24);
+}
+#endif
+
+#ifdef CONFIG_64BIT
+#ifndef __bswap64
+static inline u64 __bswap64(u64 x)
+{
+ return ((x & 0x00000000000000ffULL) << 56) |
+ ((x & 0x000000000000ff00ULL) << 40) |
+ ((x & 0x0000000000ff0000ULL) << 24) |
+ ((x & 0x00000000ff000000ULL) << 8) |
+ ((x & 0x000000ff00000000ULL) >> 8) |
+ ((x & 0x0000ff0000000000ULL) >> 24) |
+ ((x & 0x00ff000000000000ULL) >> 40) |
+ ((x & 0xff00000000000000ULL) >> 56);
+}
+#endif
+#endif
+
+#ifndef cpu_is_be
+#define cpu_is_be 0
+#endif
+
+#define le16_to_cpu(x) \
+ ({ u16 __r = cpu_is_be ? __bswap16(x) : (x); __r; })
+#define cpu_to_le16 le16_to_cpu
+
+#define le32_to_cpu(x) \
+ ({ u32 __r = cpu_is_be ? __bswap32(x) : (x); __r; })
+#define cpu_to_le32 le32_to_cpu
+
+#ifdef CONFIG_64BIT
+#define le64_to_cpu \
+ ({ u64 __r = cpu_is_be ? __bswap64(x) : (x); __r; })
+#define cpu_to_le64 le64_to_cpu
+#endif
+
+#define be16_to_cpu(x) \
+ ({ u16 __r = !cpu_is_be ? __bswap16(x) : (x); __r; })
+#define cpu_to_be16 be16_to_cpu
+
+#define be32_to_cpu(x) \
+ ({ u32 __r = !cpu_is_be ? __bswap32(x) : (x); __r; })
+#define cpu_to_be32 be32_to_cpu
+
+#ifdef CONFIG_64BIT
+#define be64_to_cpu \
+ ({ u64 __r = !cpu_is_be ? __bswap64(x) : (x); __r; })
+#define cpu_to_be64 be64_to_cpu
+#endif
+
+#ifndef rmb
+#define rmb() do { } while (0)
+#endif
+#ifndef wmb
+#define wmb() do { } while (0)
+#endif
+
+#define readb(addr) \
+ ({ u8 __r = __raw_readb(addr); rmb(); __r; })
+#define readw(addr) \
+ ({ u16 __r = le16_to_cpu(__raw_readw(addr)); rmb(); __r; })
+#define readl(addr) \
+ ({ u32 __r = le32_to_cpu(__raw_readl(addr)); rmb(); __r; })
+#ifdef CONFIG_64BIT
+#define readq(addr) \
+ ({ u64 __r = le64_to_cpu(__raw_readq(addr)); rmb(); __r; })
+#endif
+
+#define writeb(b, addr) \
+ ({ wmb(); __raw_writeb(b, addr); })
+#define writew(b, addr) \
+ ({ wmb(); __raw_writew(cpu_to_le16(b), addr); })
+#define writel(b, addr) \
+ ({ wmb(); __raw_writel(cpu_to_le32(b), addr); })
+#ifdef CONFIG_64BIT
+#define writeq(b, addr) \
+ ({ wmb(); __raw_writeq(cpu_to_le64(b), addr); })
+#endif
+
+extern void read_len(const volatile void *addr, void *buf, unsigned len);
+extern void write_len(volatile void *addr, const void *buf, unsigned len);
+
+#endif
--
1.8.1.4
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH 6/9] Introduce a simple iomap structure
2013-12-04 16:42 [PATCH 0/9 v2] kvm-unit-tests/arm: initial drop Andrew Jones
` (4 preceding siblings ...)
2013-12-04 16:42 ` [PATCH 5/9] Introduce libio to common code for io read/write Andrew Jones
@ 2013-12-04 16:42 ` Andrew Jones
2013-12-29 6:30 ` Christoffer Dall
2013-12-04 16:42 ` [PATCH 7/9] Add halt() and some error codes Andrew Jones
` (2 subsequent siblings)
8 siblings, 1 reply; 44+ messages in thread
From: Andrew Jones @ 2013-12-04 16:42 UTC (permalink / raw)
To: kvmarm, kvm
Add a simple structure and search function to the common code that
can be used for looking up a set of addresses by type. The user
must supply the iomaps[] table, e.g.
struct iomap iomaps[] = {
{
.type = "virtio_mmio",
.nr = 4,
.addrs = { 0x2000000, 0x2000200, 0x2000400, 0x2000600, },
},
{
.type = NULL,
},
};
Also add a script scripts/gen-devtree-iomaps.pl that can generate
the iomaps table from an fdt, e.g.
fdtdump dtb | scripts/gen-devtree-iomaps.pl - virtio_mmio
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v2:
- switch to kernel coding style
- rework fdt parsing to enable extraction of properties. Extract
the 'compatible' property.
- add iomaps_find_compatible() to allow searching for iomaps by
its 'compatible' property.
---
README | 1 +
lib/iomaps.c | 31 +++++++++++++
lib/iomaps.h | 14 ++++++
scripts/gen-devtree-iomaps.pl | 105 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 151 insertions(+)
create mode 100644 lib/iomaps.c
create mode 100644 lib/iomaps.h
create mode 100755 scripts/gen-devtree-iomaps.pl
diff --git a/README b/README
index 0174679c05021..f834c61dc6112 100644
--- a/README
+++ b/README
@@ -20,6 +20,7 @@ Directory structure:
.: Makefile and config files for the tests
./config: config files for the tests
./docs: documentation files
+./scripts: misc helper scripts
./lib: general services for the tests
./lib/<ARCH>: architecture dependent services for the tests
./<ARCH>: the sources of the tests and the created objects/images
diff --git a/lib/iomaps.c b/lib/iomaps.c
new file mode 100644
index 0000000000000..f2263b79dce96
--- /dev/null
+++ b/lib/iomaps.c
@@ -0,0 +1,31 @@
+#include "libcflat.h"
+#include "iomaps.h"
+
+extern const struct iomap iomaps[];
+
+const struct iomap *iomaps_find_type(const char *type)
+{
+ const struct iomap *m = &iomaps[0];
+
+ while (m->type) {
+ if (strcmp(m->type, type) == 0)
+ return m;
+ ++m;
+ }
+ return NULL;
+}
+
+const struct iomap *iomaps_find_compatible(const char *compat)
+{
+ const struct iomap *m = &iomaps[0];
+ const char *c;
+ int i;
+
+ while (m->type) {
+ for (i = 0, c = m->compats[0]; c != NULL; c = m->compats[++i])
+ if (strcmp(c, compat) == 0)
+ return m;
+ ++m;
+ }
+ return NULL;
+}
diff --git a/lib/iomaps.h b/lib/iomaps.h
new file mode 100644
index 0000000000000..76a1aa4720337
--- /dev/null
+++ b/lib/iomaps.h
@@ -0,0 +1,14 @@
+#ifndef _IOMAPS_H_
+#define _IOMAPS_H_
+#include "libcflat.h"
+
+struct iomap {
+ const char *type;
+ const char *compats[5];
+ u32 nr;
+ u32 addrs[64];
+};
+
+const struct iomap *iomaps_find_type(const char *type);
+const struct iomap *iomaps_find_compatible(const char *compat);
+#endif
diff --git a/scripts/gen-devtree-iomaps.pl b/scripts/gen-devtree-iomaps.pl
new file mode 100755
index 0000000000000..b48e85e48ab34
--- /dev/null
+++ b/scripts/gen-devtree-iomaps.pl
@@ -0,0 +1,105 @@
+#!/usr/bin/perl -w
+use strict;
+use File::Temp qw/:POSIX/;
+
+my $dts = shift @ARGV;
+my @types = @ARGV;
+my $max_nr_addrs = 64;
+my $max_nr_compats = 4;
+
+if (!defined $dts || $#types < 0) {
+ print STDERR "Usage: gen-devtree-iomaps ".
+ "<dts-file|-> <addr-type> [addr-types...]\n";
+ exit 1;
+}
+
+my $dtb = tmpnam();
+system "dtc -I dts -O dtb $dts -o $dtb";
+
+my $g = join '|', map { $_ . '@' } @types;
+my @devs = grep { /$g/ } `fdtget -l $dtb / 2>/dev/null`;
+
+my %iomaps;
+foreach my $dev (@devs) {
+
+ chomp($dev);
+ my ($type, $addr) = split /@/, $dev;
+
+ if (!exists $iomaps{$type}) {
+
+ my $compatible = `fdtget $dtb /$dev compatible 2>/dev/null`;
+ chomp($compatible);
+ my @compats = split ' ', $compatible;
+
+ $iomaps{$type}{compats} = \@compats;
+ $iomaps{$type}{addrs} = [$addr];
+ } else {
+ push @{ $iomaps{$type}{addrs} }, $addr;
+ }
+}
+unlink $dtb;
+
+print <<EOF;
+/*
+ * Generated file. See gen-devtree-iomaps.pl
+ */
+#include "iomaps.h"
+EOF
+print "\nconst struct iomap iomaps[] = {\n";
+foreach my $type (keys %iomaps) {
+
+ my $compats = $iomaps{$type}{compats};
+ my $addrs = $iomaps{$type}{addrs};
+
+ my $nr_compats = $#{ $compats } + 1;
+ if ($nr_compats > $max_nr_compats) {
+ print STDERR "$type has $nr_compats compats, but iomaps can ".
+ "only support up to $max_nr_compats.\n";
+ splice @{ $compats }, $max_nr_compats;
+ }
+
+ @{ $addrs } = sort @{ $addrs };
+
+ my $nr = $#{ $addrs } + 1;
+ if ($nr > $max_nr_addrs) {
+ print STDERR "$type has $nr addrs, but iomaps can ".
+ "only support up to $max_nr_addrs.\n";
+ $nr = $max_nr_addrs;
+ splice @{ $addrs }, $nr;
+ }
+
+ @{ $addrs } = map { $_ = sprintf '0x%.8x', hex($_) } @{ $addrs };
+
+ print "{\n";
+ print "\t.type = \"$type\",\n";
+
+ print "\t.compats = {";
+ foreach my $compat (@{ $compats }) {
+ print " \"$compat\",";
+ }
+ print " NULL, },\n";
+
+ print "\t.nr = $nr,\n";
+ print "\t.addrs = {";
+ if ($nr < 5) {
+ print ' ';
+ print join ', ', @{ $addrs };
+ print ", },\n";
+ } else {
+ print "\n";
+ for (my $i = 0; $i < $nr; $i += 5) {
+ print "\t\t";
+ my $j = $i;
+ while ($j < $i + 4 && $j < $nr - 1) {
+ print $addrs->[$j] . ", ";
+ ++$j;
+ }
+ print $addrs->[$j] . ",\n";
+ }
+ print "\t},\n";
+ }
+ print "},\n";
+}
+print "{\n\t.type = NULL,\n},\n";
+print "};\n";
+exit 0;
--
1.8.1.4
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH 7/9] Add halt() and some error codes
2013-12-04 16:42 [PATCH 0/9 v2] kvm-unit-tests/arm: initial drop Andrew Jones
` (5 preceding siblings ...)
2013-12-04 16:42 ` [PATCH 6/9] Introduce a simple iomap structure Andrew Jones
@ 2013-12-04 16:42 ` Andrew Jones
2013-12-29 6:31 ` Christoffer Dall
2013-12-04 16:42 ` [PATCH 8/9] Introduce virtio-testdev Andrew Jones
2013-12-04 16:42 ` [PATCH 9/9] arm: initial drop Andrew Jones
8 siblings, 1 reply; 44+ messages in thread
From: Andrew Jones @ 2013-12-04 16:42 UTC (permalink / raw)
To: kvmarm, kvm
Define a halt function that can be implemented by the test framework
for use on error paths before exit() works. Also add some error codes
that can be passed to halt() in case the serial isn't working either.
Then, on register inspection of the halted guest we may be able to
quickly determine the problem without having to find the halt()
call-site. The error codes may of course also be used with exit().
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v2:
- keep the error numbers more consistent with the standard numbers
---
lib/errno.h | 22 ++++++++++++++++++++++
lib/libcflat.h | 2 ++
2 files changed, 24 insertions(+)
create mode 100644 lib/errno.h
diff --git a/lib/errno.h b/lib/errno.h
new file mode 100644
index 0000000000000..f60845cdc61f6
--- /dev/null
+++ b/lib/errno.h
@@ -0,0 +1,22 @@
+#ifndef _ERRNO_H_
+#define _ERRNO_H_
+/*
+ * Define some error codes for the test framework's use. qemu
+ * exits with ((code << 1) | 1) when this framework calls
+ * exit(code), so we reserve codes 64 to 126. 127 is left
+ * for exit(-1).
+ *
+ * (Ab)use the standard E* names for syntax highlighting...
+ * The errno descriptions in [] are for non-standard semantics.
+ */
+#define EINTR (64 + 4) /* [unhandled exception] */
+#define EIO (64 + 5) /* I/O error */
+#define ENXIO (64 + 6) /* No such device or address [no serial] */
+#define ENOEXEC (64 + 8) /* Exec format error [bad flat file] */
+#define ENOMEM (64 + 12) /* Out of memory */
+#define ENODEV (64 + 19) /* No such device */
+#define EINVAL (64 + 22) /* Invalid argument */
+#define ENOSPC (64 + 28) /* No space left on device */
+#define ERANGE (64 + 34) /* Math result not representable
+ [divide by zero] */
+#endif
diff --git a/lib/libcflat.h b/lib/libcflat.h
index 140c172e77d54..a1be635ab4ee9 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -37,6 +37,7 @@ typedef _Bool bool;
#define true 1
#define false 0
+extern void halt(int code);
extern void exit(int code);
extern unsigned long strlen(const char *buf);
@@ -57,4 +58,5 @@ extern long atol(const char *ptr);
#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
#define NULL ((void *)0UL)
+#include "errno.h"
#endif
--
1.8.1.4
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH 8/9] Introduce virtio-testdev
2013-12-04 16:42 [PATCH 0/9 v2] kvm-unit-tests/arm: initial drop Andrew Jones
` (6 preceding siblings ...)
2013-12-04 16:42 ` [PATCH 7/9] Add halt() and some error codes Andrew Jones
@ 2013-12-04 16:42 ` Andrew Jones
2013-12-29 6:31 ` Christoffer Dall
2013-12-04 16:42 ` [PATCH 9/9] arm: initial drop Andrew Jones
8 siblings, 1 reply; 44+ messages in thread
From: Andrew Jones @ 2013-12-04 16:42 UTC (permalink / raw)
To: kvmarm, kvm
virtio-testdev is a communication channel to qemu through virtio that
can be used by test code to send commands. The only command currently
implemented is EXIT, which allows the test code to exit with a given
status code.
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v2:
- use readl/writel framework (libio) [Christoffer Dall]
- keep the virtio abstraction in virtio-testdev [Alexander Graf]
---
lib/libcflat.h | 3 ++
lib/virtio-testdev.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++
lib/virtio-testdev.h | 9 ++++
lib/virtio.c | 70 ++++++++++++++++++++++++++
lib/virtio.h | 74 +++++++++++++++++++++++++++
5 files changed, 295 insertions(+)
create mode 100644 lib/virtio-testdev.c
create mode 100644 lib/virtio-testdev.h
create mode 100644 lib/virtio.c
create mode 100644 lib/virtio.h
diff --git a/lib/libcflat.h b/lib/libcflat.h
index a1be635ab4ee9..197b703e53b46 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -56,6 +56,9 @@ extern long atol(const char *ptr);
#define ARRAY_SIZE(_a) (sizeof(_a)/sizeof((_a)[0]))
#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
#define NULL ((void *)0UL)
#include "errno.h"
diff --git a/lib/virtio-testdev.c b/lib/virtio-testdev.c
new file mode 100644
index 0000000000000..93731a3565b81
--- /dev/null
+++ b/lib/virtio-testdev.c
@@ -0,0 +1,139 @@
+#include "libcflat.h"
+#include "virtio.h"
+
+#define TESTDEV_MAJOR_VER 1
+#define TESTDEV_MINOR_VER 1
+
+#define VIRTIO_ID_TESTDEV 0xffff
+
+#define CONFIG_SIZE 64
+
+enum {
+ VERSION = 1,
+ CLEAR,
+ EXIT,
+};
+
+#define TOKEN_OFFSET 0x0
+#define NARGS_OFFSET 0x4
+#define NRETS_OFFSET 0x8
+#define ARG_OFFSET(n) (0xc + (n) * 4)
+#define __RET_OFFSET(nargs, n) (ARG_OFFSET(nargs) + (n) * 4)
+
+static struct virtio_dev *testdev;
+
+static u32 testdev_readl(unsigned offset)
+{
+ if (offset > (CONFIG_SIZE - 4)) {
+ printf("%s: offset 0x%x to big!\n", __func__, offset);
+ exit(EINVAL);
+ }
+
+ return virtio_config_readl(testdev, offset);
+}
+
+static void testdev_writel(unsigned offset, u32 val)
+{
+ if (offset > (CONFIG_SIZE - 4)) {
+ printf("%s: offset 0x%x to big!\n", __func__, offset);
+ exit(EINVAL);
+ }
+
+ virtio_config_writel(testdev, offset, val);
+}
+
+/*
+ * We have to write all args; nargs, nrets, ... first to
+ * avoid executing token's operation until all args are in
+ * place. Then issue the op, and then read the rets. Reading
+ * the rets (or just sanity checking by reading token) will
+ * read a zero into qemu's copy of the token, which allows us
+ * to prepare additional ops without re-executing the last one.
+ */
+void virtio_testdev(u32 token, u32 nargs, u32 nrets, ...)
+{
+ va_list va;
+ unsigned off;
+ u32 n;
+
+ if (!testdev)
+ return;
+
+ testdev_writel(NARGS_OFFSET, nargs);
+ testdev_writel(NRETS_OFFSET, nrets);
+
+ va_start(va, nrets);
+
+ off = ARG_OFFSET(0);
+ n = nargs;
+ while (n--) {
+ testdev_writel(off, va_arg(va, unsigned));
+ off += 4;
+ }
+
+ /* this runs the op, but then resets token to zero */
+ testdev_writel(TOKEN_OFFSET, token);
+
+ /* sanity check */
+ if (testdev_readl(TOKEN_OFFSET) != 0) {
+ printf("virtio-testdev token should always read as zero!\n");
+ halt(EIO);
+ }
+
+ off = __RET_OFFSET(nargs, 0);
+ n = nrets;
+ while (n--) {
+ u32 *r = va_arg(va, unsigned *);
+ *r = testdev_readl(off);
+ off += 4;
+ }
+
+ va_end(va);
+}
+
+void virtio_testdev_version(u32 *version)
+{
+ virtio_testdev(VERSION, 0, 1, version);
+}
+
+void virtio_testdev_clear(void)
+{
+ virtio_testdev(CLEAR, 0, 0);
+}
+
+void virtio_testdev_exit(int code)
+{
+ virtio_testdev(EXIT, 1, 0, code);
+}
+
+void virtio_testdev_init(void)
+{
+ u16 major, minor;
+ u32 version;
+
+ testdev = virtio_bind(VIRTIO_ID_TESTDEV);
+ if (testdev == NULL) {
+ printf("Can't find virtio-testdev. "
+ "Is '-device virtio-testdev' "
+ "on the qemu command line?\n");
+ halt(ENODEV);
+ }
+
+ virtio_testdev_version(&version);
+ major = version >> 16;
+ minor = version & 0xffff;
+
+ if (major != TESTDEV_MAJOR_VER || minor < TESTDEV_MINOR_VER) {
+ char *u = "qemu";
+ if (major > TESTDEV_MAJOR_VER)
+ u = "kvm-unit-tests";
+ printf("Incompatible version of virtio-testdev: major = %d, "
+ "minor = %d\n", major, minor);
+ printf("Update %s.\n", u);
+ exit(ENODEV);
+ }
+
+ if (minor > TESTDEV_MINOR_VER)
+ printf("testdev has new features. "
+ "An update of kvm-unit-tests may be possible.\n");
+}
diff --git a/lib/virtio-testdev.h b/lib/virtio-testdev.h
new file mode 100644
index 0000000000000..c10bbfb591d0b
--- /dev/null
+++ b/lib/virtio-testdev.h
@@ -0,0 +1,9 @@
+#ifndef _VIRTIO_TESTDEV_H_
+#define _VIRTIO_TESTDEV_H_
+#include "libcflat.h"
+
+extern void virtio_testdev_init(void);
+extern void virtio_testdev_version(u32 *version);
+extern void virtio_testdev_clear(void);
+extern void virtio_testdev_exit(int code);
+#endif
diff --git a/lib/virtio.c b/lib/virtio.c
new file mode 100644
index 0000000000000..c5ad1c85ff9a1
--- /dev/null
+++ b/lib/virtio.c
@@ -0,0 +1,70 @@
+#include "libcflat.h"
+#include "libio.h"
+#include "iomaps.h"
+#include "heap.h"
+#include "virtio.h"
+
+#define to_virtio_mmio_dev(vdev) \
+ container_of(vdev, struct virtio_mmio_dev, vdev)
+
+static void vm_get(struct virtio_dev *vdev, unsigned offset,
+ void *buf, unsigned len)
+{
+ struct virtio_mmio_dev *vmdev = to_virtio_mmio_dev(vdev);
+ void *addr = vmdev->base + VIRTIO_MMIO_CONFIG + offset;
+ read_len(addr, buf, len);
+}
+
+static void vm_set(struct virtio_dev *vdev, unsigned offset,
+ const void *buf, unsigned len)
+{
+ struct virtio_mmio_dev *vmdev = to_virtio_mmio_dev(vdev);
+ void *addr = vmdev->base + VIRTIO_MMIO_CONFIG + offset;
+ write_len(addr, buf, len);
+}
+
+static struct virtio_dev *virtio_mmio_bind(const struct iomap *m, u32 device)
+{
+ struct virtio_mmio_dev *vmdev;
+ void *page;
+ u32 devid, i;
+
+ page = alloc_page();
+ vmdev = page;
+ vmdev->vdev.config = page + sizeof(struct virtio_mmio_dev);
+
+ vmdev->vdev.id.device = device;
+ vmdev->vdev.id.vendor = -1;
+ vmdev->vdev.config->get = vm_get;
+ vmdev->vdev.config->set = vm_set;
+
+ device &= 0xffff;
+
+ for (i = 0; i < m->nr; ++i) {
+ vmdev->base = compat_ptr(m->addrs[i]);
+ devid = readl(vmdev->base + VIRTIO_MMIO_DEVICE_ID);
+ if ((devid & 0xffff) == device)
+ break;
+ }
+
+ if (i >= m->nr) {
+ printf("%s: Can't find device 0x%x.\n", __func__, device);
+ free_page(page);
+ return NULL;
+ }
+
+ return &vmdev->vdev;
+}
+
+struct virtio_dev *virtio_bind(u32 device)
+{
+ const struct iomap *m;
+
+ /* currently we only support virtio-mmio */
+ m = iomaps_find_compatible("virtio,mmio");
+ if (!m) {
+ printf("%s: No virtio-mmio transports found!\n", __func__);
+ return NULL;
+ }
+ return virtio_mmio_bind(m, device);
+}
diff --git a/lib/virtio.h b/lib/virtio.h
new file mode 100644
index 0000000000000..c30a8dcd105cd
--- /dev/null
+++ b/lib/virtio.h
@@ -0,0 +1,74 @@
+#ifndef _VIRTIO_H_
+#define _VIRTIO_H_
+#include "libcflat.h"
+
+#define VIRTIO_MMIO_DEVICE_ID 0x008
+#define VIRTIO_MMIO_CONFIG 0x100
+
+struct virtio_devid {
+ u32 device;
+ u32 vendor;
+};
+
+struct virtio_dev {
+ struct virtio_devid id;
+ struct virtio_conf_ops *config;
+};
+
+struct virtio_conf_ops {
+ void (*get)(struct virtio_dev *vdev, unsigned offset,
+ void *buf, unsigned len);
+ void (*set)(struct virtio_dev *vdev, unsigned offset,
+ const void *buf, unsigned len);
+};
+
+struct virtio_mmio_dev {
+ struct virtio_dev vdev;
+ void *base;
+};
+
+static inline u8
+virtio_config_readb(struct virtio_dev *vdev, unsigned offset)
+{
+ u8 val;
+ vdev->config->get(vdev, offset, &val, 1);
+ return val;
+}
+
+static inline u16
+virtio_config_readw(struct virtio_dev *vdev, unsigned offset)
+{
+ u16 val;
+ vdev->config->get(vdev, offset, &val, 2);
+ return val;
+}
+
+static inline u32
+virtio_config_readl(struct virtio_dev *vdev, unsigned offset)
+{
+ u32 val;
+ vdev->config->get(vdev, offset, &val, 4);
+ return val;
+}
+
+static inline void
+virtio_config_writeb(struct virtio_dev *vdev, unsigned offset, u8 val)
+{
+ vdev->config->set(vdev, offset, &val, 1);
+}
+
+static inline void
+virtio_config_writew(struct virtio_dev *vdev, unsigned offset, u16 val)
+{
+ vdev->config->set(vdev, offset, &val, 2);
+}
+
+static inline void
+virtio_config_writel(struct virtio_dev *vdev, unsigned offset, u32 val)
+{
+ vdev->config->set(vdev, offset, &val, 4);
+}
+
+extern struct virtio_dev *virtio_bind(u32 device);
+
+#endif
--
1.8.1.4
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH 9/9] arm: initial drop
2013-12-04 16:42 [PATCH 0/9 v2] kvm-unit-tests/arm: initial drop Andrew Jones
` (7 preceding siblings ...)
2013-12-04 16:42 ` [PATCH 8/9] Introduce virtio-testdev Andrew Jones
@ 2013-12-04 16:42 ` Andrew Jones
2013-12-29 6:31 ` Christoffer Dall
8 siblings, 1 reply; 44+ messages in thread
From: Andrew Jones @ 2013-12-04 16:42 UTC (permalink / raw)
To: kvmarm, kvm
This is the initial arm test framework and a first simple test that
checks some bootinfo. kvm isn't needed to run this test. This patch
also adds a common build environment variable, $QEMU_BIN, which
allows makefiles to call on qemu when needed.
Try it out with
yum install gcc-arm-linux-gnu dtc
export QEMU=[qemu with mach-virt and virtio-testdev]
./configure --cross-prefix=arm-linux-gnu- --arch=arm
make
./run_tests.sh
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v2:
- add eabi utility functions needed for some toolchains, this
allows us to drop the divmod hacks that were in v1
- switch to kernel coding style
- some refactoring of setup code for heap init
- some refactoring of the simple bootinfo test for clarity
and reuse opportunity
- update base addr for the new mach-virt version
---
arm/boot.c | 17 +++++++++++
arm/cstart.S | 38 +++++++++++++++++++++++
arm/flat.lds | 18 +++++++++++
arm/run | 19 ++++++++++++
arm/unittests.cfg | 11 +++++++
config/config-arm.mak | 73 +++++++++++++++++++++++++++++++++++++++++++
configure | 10 ++++--
lib/arm/eabi_compat.c | 20 ++++++++++++
lib/arm/io.c | 31 +++++++++++++++++++
lib/arm/io.h | 24 +++++++++++++++
lib/arm/setup.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++
lib/arm/sysinfo.h | 19 ++++++++++++
lib/libcflat.h | 2 ++
lib/libio.h | 4 +++
lib/test_util.c | 34 +++++++++++++++++++++
lib/test_util.h | 13 ++++++++
16 files changed, 416 insertions(+), 2 deletions(-)
create mode 100644 arm/boot.c
create mode 100644 arm/cstart.S
create mode 100644 arm/flat.lds
create mode 100755 arm/run
create mode 100644 arm/unittests.cfg
create mode 100644 config/config-arm.mak
create mode 100644 lib/arm/eabi_compat.c
create mode 100644 lib/arm/io.c
create mode 100644 lib/arm/io.h
create mode 100644 lib/arm/setup.c
create mode 100644 lib/arm/sysinfo.h
create mode 100644 lib/test_util.c
create mode 100644 lib/test_util.h
diff --git a/arm/boot.c b/arm/boot.c
new file mode 100644
index 0000000000000..dc42dfc232366
--- /dev/null
+++ b/arm/boot.c
@@ -0,0 +1,17 @@
+#include "libcflat.h"
+#include "test_util.h"
+#include "arm/sysinfo.h"
+
+int main(int argc, char **argv)
+{
+ int ret = FAIL;
+
+ if (argc >= 1) {
+ --argc;
+ if (!strcmp(argv[0], "mem") && enough_args(argc, 1)) {
+ if (check_u32(mem32.size/1024/1024, 10, argv[1]))
+ ret = PASS;
+ }
+ }
+ return ret;
+}
diff --git a/arm/cstart.S b/arm/cstart.S
new file mode 100644
index 0000000000000..05d4bb5becaa0
--- /dev/null
+++ b/arm/cstart.S
@@ -0,0 +1,38 @@
+
+#define CR_B (1 << 7) /* Big endian */
+
+.arm
+
+.section .init
+
+.globl start
+start:
+ /* bootloader params are in r0-r2 */
+ ldr sp, =stacktop
+
+ mrc p15, 0, r8, c1, c0, 0 @r8 = sctrl
+ ands r3, r8, #CR_B @set BE, if necessary
+ ldrne r3, =cpu_is_be
+ movne r4, #1
+ strne r4, [r3]
+ bl setup @complete setup
+
+ /* start the test */
+ ldr r0, =__argc
+ ldr r0, [r0]
+ ldr r1, =__argv
+ bl main
+ bl exit
+ b halt
+
+.text
+
+.globl halt
+halt:
+1: wfi
+ b 1b
+
+.data
+
+.globl cpu_is_be
+cpu_is_be: .word 0
diff --git a/arm/flat.lds b/arm/flat.lds
new file mode 100644
index 0000000000000..3e5d72e24989b
--- /dev/null
+++ b/arm/flat.lds
@@ -0,0 +1,18 @@
+
+SECTIONS
+{
+ .text : { *(.init) *(.text) *(.text.*) }
+ . = ALIGN(4K);
+ .data : { *(.data) }
+ . = ALIGN(16);
+ .rodata : { *(.rodata) }
+ . = ALIGN(16);
+ .bss : { *(.bss) }
+ . = ALIGN(4K);
+ edata = .;
+ . += 8K;
+ . = ALIGN(4K);
+ stacktop = .;
+}
+
+ENTRY(start)
diff --git a/arm/run b/arm/run
new file mode 100755
index 0000000000000..64446e8907564
--- /dev/null
+++ b/arm/run
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+qemu="${QEMU:-qemu-system-arm}"
+testdev='virtio-testdev'
+
+if ! $qemu -device '?' 2>&1 | grep $testdev > /dev/null; then
+ echo \"$qemu\" has no support for the virtio test device. Exiting.
+ exit 2
+fi
+
+command="$qemu -device $testdev -display none -serial stdio "
+command+="-M virt -cpu cortex-a15 "
+#command+="-enable-kvm "
+command+="-kernel"
+echo $command "$@"
+$command "$@"
+ret=$?
+echo Return value from qemu: $ret
+exit $ret
diff --git a/arm/unittests.cfg b/arm/unittests.cfg
new file mode 100644
index 0000000000000..c328657b7944a
--- /dev/null
+++ b/arm/unittests.cfg
@@ -0,0 +1,11 @@
+# Define your new unittest following the convention:
+# [unittest_name]
+# file = foo.flat # Name of the flat file to be used
+# smp = 2 # Number of processors the VM will use during this test
+# extra_params = -append <params...> # Additional parameters used
+# arch = arm/arm64 # Only if the test case works only on one of them
+# groups = group1 group2 # Used to identify test cases with run_tests -g ...
+
+[boot_info]
+file = boot.flat
+extra_params = -m 256 -append 'mem 256'
diff --git a/config/config-arm.mak b/config/config-arm.mak
new file mode 100644
index 0000000000000..d0814186b279c
--- /dev/null
+++ b/config/config-arm.mak
@@ -0,0 +1,73 @@
+mach = mach-virt
+iodevs = pl011 virtio_mmio
+phys_base = 0x40000000
+
+cstart.o = $(TEST_DIR)/cstart.o
+bits = 32
+ldarch = elf32-littlearm
+kernel_offset = 0x10000
+CFLAGS += -D__arm__
+
+all: test_cases
+
+cflatobjs += \
+ lib/$(TEST_DIR)/iomaps.gen.o \
+ lib/heap.o \
+ lib/iomaps.o \
+ lib/libio.o \
+ lib/virtio.o \
+ lib/virtio-testdev.o \
+ lib/test_util.o \
+ lib/arm/io.o \
+ lib/arm/setup.o
+
+libeabi := lib/arm/libeabi.a
+eabiobjs += \
+ lib/arm/eabi_compat.o
+
+$(libcflat) $(libeabi): LDFLAGS += -nostdlib
+$(libcflat) $(libeabi): CFLAGS += -ffreestanding -I lib
+
+CFLAGS += -Wextra
+CFLAGS += -marm
+#CFLAGS += -mcpu=$(PROCESSOR)
+CFLAGS += -mcpu=cortex-a15
+CFLAGS += -O2
+
+libgcc := $(shell $(CC) -m$(ARCH) --print-libgcc-file-name)
+start_addr := $(shell printf "%x\n" $$(( $(phys_base) + $(kernel_offset) )))
+
+FLATLIBS = $(libcflat) $(libgcc) $(libeabi)
+%.elf: %.o $(FLATLIBS) arm/flat.lds
+ $(CC) $(CFLAGS) -nostdlib -o $@ \
+ -Wl,-T,arm/flat.lds,--build-id=none,-Ttext=$(start_addr) \
+ $(filter %.o, $^) $(FLATLIBS)
+
+$(libeabi): $(eabiobjs)
+ $(AR) rcs $@ $^
+
+%.flat: %.elf
+ $(OBJCOPY) -O binary $^ $@
+
+tests-common = $(TEST_DIR)/boot.flat
+
+tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg
+
+test_cases: $(tests-common) $(tests)
+
+$(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I lib
+
+$(TEST_DIR)/boot.elf: $(cstart.o) $(TEST_DIR)/boot.o
+
+lib/$(TEST_DIR)/iomaps.gen.c: lib/$(TEST_DIR)/$(mach).dts
+ scripts/gen-devtree-iomaps.pl $^ $(iodevs) > $@
+
+lib/$(TEST_DIR)/mach-virt.dts: dtb = $(subst .dts,.dtb,$@)
+lib/$(TEST_DIR)/mach-virt.dts:
+ $(QEMU_BIN) -kernel /dev/null -M virt -machine dumpdtb=$(dtb)
+ fdtdump $(dtb) > $@
+
+arch_clean:
+ $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
+ $(libeabi) $(eabiobjs) $(TEST_DIR)/.*.d lib/arm/.*.d \
+ lib/$(TEST_DIR)/iomaps.gen.c lib/$(TEST_DIR)/mach-virt.*
diff --git a/configure b/configure
index 6cfc64943f6e6..296c70182ea1d 100755
--- a/configure
+++ b/configure
@@ -6,8 +6,7 @@ cc=gcc
ld=ld
objcopy=objcopy
ar=ar
-arch=`uname -m | sed -e s/i.86/i386/`
-processor="$arch"
+arch=`uname -m | sed -e s/i.86/i386/ | sed -e 's/arm.*/arm/'`
cross_prefix=
usage() {
@@ -17,6 +16,7 @@ usage() {
Options include:
--test-dir=DIR the main directory for tests ($arch)
--arch=ARCH architecture to compile for ($arch)
+ --processor=PROCESSOR processor to compile for ($arch)
--cross-prefix=PREFIX cross compiler prefix
--cc=CC c compiler to use ($cc)
--ld=LD ld linker to use ($ld)
@@ -66,6 +66,9 @@ while [[ "$1" = -* ]]; do
;;
esac
done
+[ -z "$processor" ] && processor="$arch"
+qemu="${QEMU:-qemu-system-$arch}"
+
if [ -z "$testdir" -a \( "$arch" = "i386" -o "$arch" = "x86_64" \) ]; then
testdir=x86
elif [ -z "$testdir" ]; then
@@ -80,6 +83,7 @@ if [ -f $testdir/run ]; then
fi
# check for dependent 32 bit libraries
+if [ "$arch" = "i386" -o "$arch" = "x86_64" ]; then
cat << EOF > lib_test.c
#include <stdc++.h>
#include <boost_thread-mt.h>
@@ -94,6 +98,7 @@ if [ $exit -eq 0 ]; then
api=true
fi
rm -f lib_test.c
+fi
cat <<EOF > config.mak
PREFIX=$prefix
@@ -106,4 +111,5 @@ OBJCOPY=$cross_prefix$objcopy
AR=$cross_prefix$ar
API=$api
TEST_DIR=$testdir
+QEMU_BIN=$qemu
EOF
diff --git a/lib/arm/eabi_compat.c b/lib/arm/eabi_compat.c
new file mode 100644
index 0000000000000..76e04f5543ee1
--- /dev/null
+++ b/lib/arm/eabi_compat.c
@@ -0,0 +1,20 @@
+/*
+ * Adapted from u-boot's arch/arm/lib/eabi_compat.c
+ */
+#include "libcflat.h"
+
+int raise(int signum __unused)
+{
+ printf("Divide by zero!\n");
+ exit(ERANGE);
+ return 0;
+}
+
+/* Dummy functions to avoid linker complaints */
+void __aeabi_unwind_cpp_pr0(void)
+{
+}
+
+void __aeabi_unwind_cpp_pr1(void)
+{
+}
diff --git a/lib/arm/io.c b/lib/arm/io.c
new file mode 100644
index 0000000000000..32c896c29450a
--- /dev/null
+++ b/lib/arm/io.c
@@ -0,0 +1,31 @@
+#include "libcflat.h"
+#include "libio.h"
+#include "iomaps.h"
+#include "virtio-testdev.h"
+
+static volatile u8 *uart0_base;
+
+void puts(const char *s)
+{
+ while (*s)
+ *uart0_base = *s++;
+}
+
+void exit(int code)
+{
+ virtio_testdev_exit(code);
+ halt(code);
+}
+
+void io_init_early(void)
+{
+ const struct iomap *m = iomaps_find_compatible("arm,pl011");
+ if (!m)
+ halt(ENXIO);
+ uart0_base = (u8 *)compat_ptr(m->addrs[0]);
+}
+
+void io_init(void)
+{
+ virtio_testdev_init();
+}
diff --git a/lib/arm/io.h b/lib/arm/io.h
new file mode 100644
index 0000000000000..f058f7e54d4a7
--- /dev/null
+++ b/lib/arm/io.h
@@ -0,0 +1,24 @@
+#ifndef _ARM_IO_H_
+#define _ARM_IO_H_
+
+#define cpu_is_be cpu_is_be
+extern bool cpu_is_be;
+
+#define __bswap16 bswap16
+static inline u16 bswap16(u16 val)
+{
+ u16 ret;
+ asm volatile("rev16 %0, %1" : "=r" (ret) : "r" (val));
+ return ret;
+}
+
+#define __bswap32 bswap32
+static inline u32 bswap32(u32 val)
+{
+ u32 ret;
+ asm volatile("rev %0, %1" : "=r" (ret) : "r" (val));
+ return ret;
+}
+
+#include "libio.h"
+#endif
diff --git a/lib/arm/setup.c b/lib/arm/setup.c
new file mode 100644
index 0000000000000..32fa84bd0bb5b
--- /dev/null
+++ b/lib/arm/setup.c
@@ -0,0 +1,85 @@
+#include "libcflat.h"
+#include "libio.h"
+#include "heap.h"
+#include "arm/sysinfo.h"
+
+#define FDT_SIG 0xd00dfeed
+
+#define KERNEL_OFFSET 0x00010000
+#define ATAG_OFFSET 0x00000100
+
+#define ATAG_CORE 0x54410001
+#define ATAG_MEM 0x54410002
+#define ATAG_CMDLINE 0x54410009
+
+extern void start(void);
+extern unsigned long stacktop;
+extern char *__args;
+
+extern void io_init_early(void);
+extern void io_init(void);
+extern void __setup_args(void);
+
+u32 mach_type_id;
+struct tag_core core;
+struct tag_mem32 mem32;
+
+static void read_atags(u32 id, u32 *info)
+{
+ u32 *p = info;
+
+ if (!p) {
+ printf("Can't find bootinfo. mach-type = %x\n", id);
+ exit(ENOEXEC);
+ }
+
+ /*
+ * p[0] count of words for the tag
+ * p[1] tag id
+ * p[2..] tag data
+ */
+ for (; p[0] != 0; p += p[0])
+ switch (p[1]) {
+ case ATAG_CORE:
+ core.flags = p[2];
+ core.pagesize = p[3];
+ core.rootdev = p[4];
+ break;
+ case ATAG_MEM:
+ mem32.size = p[2];
+ mem32.start = p[3];
+ break;
+ case ATAG_CMDLINE:
+ __args = (char *)&p[2];
+ break;
+ }
+}
+
+static void read_bootinfo(u32 id, u32 *info)
+{
+ u32 *atags = NULL;
+
+ mach_type_id = id;
+
+ if (info[0] == be32_to_cpu(FDT_SIG)) {
+ /*
+ * fdt reading is not [yet?] implemented. So calculate
+ * the ATAGS addr to read that instead.
+ */
+ atags = (u32 *)(start - KERNEL_OFFSET + ATAG_OFFSET);
+ } else if (info[1] == ATAG_CORE)
+ atags = info;
+
+ read_atags(id, atags);
+}
+
+void setup(u32 arg __unused, u32 id, u32 *info)
+{
+ io_init_early();
+ read_bootinfo(id, info);
+ __setup_args();
+ heap_init(&stacktop,
+ mem32.size - (ptr_to_compat(&stacktop) - mem32.start),
+ core.pagesize);
+ io_init();
+}
diff --git a/lib/arm/sysinfo.h b/lib/arm/sysinfo.h
new file mode 100644
index 0000000000000..f3b076e1a34c4
--- /dev/null
+++ b/lib/arm/sysinfo.h
@@ -0,0 +1,19 @@
+#ifndef _ARM_SYSINFO_H_
+#define _ARM_SYSINFO_H_
+#include "libcflat.h"
+
+struct tag_core {
+ u32 flags; /* bit 0 = read-only */
+ u32 pagesize;
+ u32 rootdev;
+};
+
+struct tag_mem32 {
+ u32 size;
+ u32 start; /* physical start address */
+};
+
+extern u32 mach_type_id;
+extern struct tag_core core;
+extern struct tag_mem32 mem32;
+#endif
diff --git a/lib/libcflat.h b/lib/libcflat.h
index 197b703e53b46..8c6cf1f0735ba 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -45,6 +45,7 @@ extern char *strcat(char *dest, const char *src);
extern int strcmp(const char *a, const char *b);
extern int printf(const char *fmt, ...);
+extern int snprintf(char *buf, int size, const char *fmt, ...);
extern int vsnprintf(char *buf, int size, const char *fmt, va_list va);
extern void puts(const char *s);
@@ -60,6 +61,7 @@ extern long atol(const char *ptr);
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
+#define __unused __attribute__((__unused__))
#define NULL ((void *)0UL)
#include "errno.h"
#endif
diff --git a/lib/libio.h b/lib/libio.h
index 210b8d78af43f..5ac1056e7002f 100644
--- a/lib/libio.h
+++ b/lib/libio.h
@@ -6,6 +6,10 @@
*/
#include "libcflat.h"
+#ifdef __arm__
+#include "arm/io.h"
+#endif
+
typedef u32 compat_ptr_t;
static inline void *compat_ptr(compat_ptr_t ptr)
diff --git a/lib/test_util.c b/lib/test_util.c
new file mode 100644
index 0000000000000..3de1f74f83455
--- /dev/null
+++ b/lib/test_util.c
@@ -0,0 +1,34 @@
+#include "libcflat.h"
+#include "test_util.h"
+
+bool enough_args(int nargs, int needed)
+{
+ if (nargs >= needed)
+ return true;
+
+ fail("Not enough arguments.\n");
+ return false;
+}
+
+/*
+ * Typically one would compare val == strtoul(expected, endp, base),
+ * but we don't have, nor at this point really need, strtoul, so we
+ * convert val to a string instead. base can only be 10 or 16.
+ */
+bool check_u32(u32 val, int base, char *expected)
+{
+ char *fmt = base == 10 ? "%d" : "%x";
+ char val_str[16];
+
+ snprintf(val_str, 16, fmt, val);
+
+ if (base == 16)
+ while (*expected == '0' || *expected == 'x')
+ ++expected;
+
+ if (strcmp(val_str, expected) == 0)
+ return true;
+
+ fail("expected %s, but have %s\n", expected, val_str);
+ return false;
+}
diff --git a/lib/test_util.h b/lib/test_util.h
new file mode 100644
index 0000000000000..0e3e6c4a80d51
--- /dev/null
+++ b/lib/test_util.h
@@ -0,0 +1,13 @@
+#ifndef _TEST_UTIL_H_
+#define _TEST_UTIL_H_
+#include "libcflat.h"
+
+#define PASS 0
+#define FAIL 1
+
+#define pass(fmt...) printf("PASS: " fmt)
+#define fail(fmt...) printf("FAIL: " fmt)
+
+bool enough_args(int nargs, int needed);
+bool check_u32(u32 val, int base, char *expected);
+#endif
--
1.8.1.4
^ permalink raw reply related [flat|nested] 44+ messages in thread
* Re: [PATCH 2/9] makefile and run_tests tweaks
2013-12-04 16:42 ` [PATCH 2/9] makefile and run_tests tweaks Andrew Jones
@ 2013-12-29 6:30 ` Christoffer Dall
2014-01-02 14:30 ` Andrew Jones
0 siblings, 1 reply; 44+ messages in thread
From: Christoffer Dall @ 2013-12-29 6:30 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvmarm, kvm
On Wed, Dec 04, 2013 at 05:42:50PM +0100, Andrew Jones wrote:
This is a really short commit message, for anyone not super-familiar
with the make system in this toolset, it makes it quite hard to
understand the change. See some examples below:
> - remove a redundant '-display none'
> - remove a redundant -g from CFLAGS
> - remove a useless -I../include/x86 from CFLAGS
why is this include useless?
> - remove lib autodep files on make clean
why?
>
> Signed-off-by: Andrew Jones <drjones@redhat.com>
> ---
> Makefile | 8 ++++----
> config-x86-common.mak | 16 +++++++---------
> run_tests.sh | 2 +-
> 3 files changed, 12 insertions(+), 14 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index 278791dbbef23..697fc2a766966 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -12,9 +12,9 @@ libgcc := $(shell $(CC) --print-libgcc-file-name)
>
> libcflat := lib/libcflat.a
> cflatobjs := \
> + lib/argv.o \
> lib/printf.o \
> lib/string.o
> -cflatobjs += lib/argv.o
>
> #include architecure specific make rules
> include config-$(ARCH).mak
> @@ -25,8 +25,8 @@ include config-$(ARCH).mak
> cc-option = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null \
> > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
>
> -CFLAGS += -O1
seems like a good idea to compile test code without optimizations, is
that what you're trying to achieve here? Seems to me this should be a
separate change or at least motivated in the commit text.
> -CFLAGS += $(autodepend-flags) -g -fomit-frame-pointer -Wall
I like removing the redundant -g but wouldn't it be cleaner to set the
CFLAGS to an empty string in the beginning of the file and then have a
seprate line for -g where all the CFLAGS are set?
> +CFLAGS += $(autodepend-flags) -Wall
> +CFLAGS += $(call cc-option, -fomit-frame-pointer, "")
> CFLAGS += $(call cc-option, -fno-stack-protector, "")
> CFLAGS += $(call cc-option, -fno-stack-protector-all, "")
> CFLAGS += -I.
> @@ -51,4 +51,4 @@ install:
> install $(tests_and_config) $(DESTDIR)
>
> clean: arch_clean
> - $(RM) *.o *.a .*.d $(libcflat) $(cflatobjs)
> + $(RM) *.o *.a .*.d lib/.*.d $(libcflat) $(cflatobjs)
> diff --git a/config-x86-common.mak b/config-x86-common.mak
> index bf88c672de472..7e481192a0737 100644
> --- a/config-x86-common.mak
> +++ b/config-x86-common.mak
> @@ -1,13 +1,9 @@
> #This is a make file with common rules for both x86 & x86-64
>
> -CFLAGS += -I../include/x86
> -
> all: test_cases
>
> -cflatobjs += \
> - lib/x86/io.o \
> - lib/x86/smp.o
> -
> +cflatobjs += lib/x86/io.o
> +cflatobjs += lib/x86/smp.o
> cflatobjs += lib/x86/vm.o
> cflatobjs += lib/x86/fwcfg.o
> cflatobjs += lib/x86/apic.o
> @@ -20,15 +16,17 @@ $(libcflat): LDFLAGS += -nostdlib
> $(libcflat): CFLAGS += -ffreestanding -I lib
>
> CFLAGS += -m$(bits)
> +CFLAGS += -O1
>
> libgcc := $(shell $(CC) -m$(bits) --print-libgcc-file-name)
>
> FLATLIBS = lib/libcflat.a $(libgcc)
> %.elf: %.o $(FLATLIBS) flat.lds
> - $(CC) $(CFLAGS) -nostdlib -o $@ -Wl,-T,flat.lds $(filter %.o, $^) $(FLATLIBS)
> + $(CC) $(CFLAGS) -nostdlib -o $@ -Wl,-T,flat.lds \
> + $(filter %.o, $^) $(FLATLIBS)
>
> %.flat: %.elf
> - objcopy -O elf32-i386 $^ $@
> + $(OBJCOPY) -O elf32-i386 $^ $@
>
> tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \
> $(TEST_DIR)/smptest.flat $(TEST_DIR)/port80.flat \
> @@ -105,7 +103,7 @@ $(TEST_DIR)/vmx.elf: $(cstart.o) $(TEST_DIR)/vmx.o $(TEST_DIR)/vmx_tests.o
>
> arch_clean:
> $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
> - $(TEST_DIR)/.*.d $(TEST_DIR)/lib/.*.d $(TEST_DIR)/lib/*.o
> + $(TEST_DIR)/.*.d lib/x86/.*.d
>
> api/%.o: CFLAGS += -m32
>
> diff --git a/run_tests.sh b/run_tests.sh
> index 55ecac5bed3a4..f373c533b75b2 100755
> --- a/run_tests.sh
> +++ b/run_tests.sh
> @@ -27,7 +27,7 @@ function run()
> return
> fi
>
> - cmdline="./x86-run $kernel -smp $smp -display none $opts"
> + cmdline="./x86-run $kernel -smp $smp $opts"
> if [ $verbose != 0 ]; then
> echo $cmdline
> fi
> --
> 1.8.1.4
>
> _______________________________________________
> kvmarm mailing list
> kvmarm@lists.cs.columbia.edu
> https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
--
Christoffer
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 3/9] clean root dir of all x86-ness
2013-12-04 16:42 ` [PATCH 3/9] clean root dir of all x86-ness Andrew Jones
@ 2013-12-29 6:30 ` Christoffer Dall
2014-01-02 15:00 ` Andrew Jones
0 siblings, 1 reply; 44+ messages in thread
From: Christoffer Dall @ 2013-12-29 6:30 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvmarm, kvm
On Wed, Dec 04, 2013 at 05:42:51PM +0100, Andrew Jones wrote:
> Remove all references to x86 from the root dir (except from in
> configure). Also remove references from the root dir README
> by moving that documentation to the x86/README, and touch up
> the READMEs at the same time.
>
> Signed-off-by: Andrew Jones <drjones@redhat.com>
>
> ---
> v2:
> - tests' images => test images [Christoffer Dall]
>
> TODO:
> - more documentation is still needed, we should add
> * an overview of the framework
> * improve the quickstart guide for running the tests
> * add a quickstart guide for developing tests
> ---
> Makefile | 7 ++-
> README | 55 +++++++++-----------
> config-i386.mak | 13 -----
> config-x86-common.mak | 120 -------------------------------------------
> config-x86_64.mak | 14 -----
> config/config-i386.mak | 12 +++++
> config/config-x86-common.mak | 120 +++++++++++++++++++++++++++++++++++++++++++
> config/config-x86_64.mak | 13 +++++
> configure | 17 ++++++
> docs/testdev.txt | 11 ++++
> flat.lds | 21 --------
> run_tests.sh | 19 ++++---
> testdev.txt | 14 -----
> x86-run | 41 ---------------
> x86/README | 60 +++++++++++++++++-----
> x86/flat.lds | 21 ++++++++
> x86/run | 41 +++++++++++++++
> 17 files changed, 316 insertions(+), 283 deletions(-)
> delete mode 100644 config-i386.mak
> delete mode 100644 config-x86-common.mak
> delete mode 100644 config-x86_64.mak
> create mode 100644 config/config-i386.mak
> create mode 100644 config/config-x86-common.mak
> create mode 100644 config/config-x86_64.mak
> create mode 100644 docs/testdev.txt
> delete mode 100644 flat.lds
> delete mode 100644 testdev.txt
> delete mode 100755 x86-run
> create mode 100644 x86/flat.lds
> create mode 100755 x86/run
>
> diff --git a/Makefile b/Makefile
> index 697fc2a766966..7a5ec8e6348bf 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -17,7 +17,7 @@ cflatobjs := \
> lib/string.o
>
> #include architecure specific make rules
> -include config-$(ARCH).mak
> +include config/config-$(ARCH).mak
>
> # cc-option
> # Usage: OP_CFLAGS+=$(call cc-option, -falign-functions=0, -malign-functions=0)
> @@ -29,7 +29,6 @@ CFLAGS += $(autodepend-flags) -Wall
> CFLAGS += $(call cc-option, -fomit-frame-pointer, "")
> CFLAGS += $(call cc-option, -fno-stack-protector, "")
> CFLAGS += $(call cc-option, -fno-stack-protector-all, "")
> -CFLAGS += -I.
>
> CXXFLAGS += $(CFLAGS)
>
> @@ -44,11 +43,11 @@ $(libcflat): $(cflatobjs)
> %.o: %.S
> $(CC) $(CFLAGS) -c -nostdlib -o $@ $<
>
> --include .*.d */.*.d */*/.*.d
> +-include */.*.d */*/.*.d
>
> install:
> mkdir -p $(DESTDIR)
> install $(tests_and_config) $(DESTDIR)
>
> clean: arch_clean
> - $(RM) *.o *.a .*.d lib/.*.d $(libcflat) $(cflatobjs)
> + $(RM) lib/.*.d $(libcflat) $(cflatobjs)
so above you're referencing */.*.d and */*/.*.d but in make arch_clean
we're only removing lib/.*.d ?
> diff --git a/README b/README
> index db525e3bbb79d..0174679c05021 100644
> --- a/README
> +++ b/README
> @@ -1,36 +1,27 @@
> This directory contains sources for a kvm test suite.
>
> -Tests for x86 architecture are run as kernel images for qemu that supports multiboot format.
> -Tests uses an infrastructure called from the bios code. The infrastructure initialize the system/cpu's,
> -switch to long-mode and calls the 'main' function of the individual test.
> -Tests uses a qemu's virtual test device, named testdev, for services like printing, exiting, query memory size etc.
> -See file testdev.txt for more details.
> -
> -To create the tests' images just type 'make' in this directory.
> -Tests' images created in ./<ARCH>/*.flat
> -
> -An example of a test invocation:
> -Using qemu-kvm:
> -
> -qemu-kvm -device testdev,chardev=testlog -chardev file,id=testlog,path=msr.out -serial stdio -kernel ./x86/msr.flat
> -This invocation runs the msr test case. The test outputs to stdio.
> -
> -Using qemu (supported since qemu 1.3):
> -qemu-system-x86_64 -enable-kvm -device pc-testdev -serial stdio -device isa-debug-exit,iobase=0xf4,iosize=0x4 -kernel ./x86/msr.flat
> -
> -Or use a runner script to detect the correct invocation:
> -./x86-run ./x86/msr.flat
> -To select a specific qemu binary, specify the QEMU=<path> environment:
> -QEMU=/tmp/qemu/x86_64-softmmu/qemu-system-x86_64 ./x86-run ./x86/msr.flat
> -
> -The exit status of the binary (and the script) is inconsistent: with
> -qemu-system, after the unittest is done, the exit status of qemu is 1,
> -different from the 'old style' qemu-kvm, whose exit status in successful
> -completion is 0.
> +To create the test images do
> + ./configure
> + make
> +in this directory. Test images are created in ./<ARCH>/*.flat
> +
> +Then use the runner script to detect the correct invocation and
> +invoke the test, e.g.
> + ./x86-run ./x86/msr.flat
> +or
> + ./run_tests.sh
> +to run them all.
> +
> +To select a specific qemu binary, specify the QEMU=<path>
> +environment, e.g.
> + QEMU=/tmp/qemu/x86_64-softmmu/qemu-system-x86_64 ./x86-run ./x86/msr.flat
>
> Directory structure:
> -.: Makefile and config files for the tests
> -./lib: general services for the tests
> -./lib/<ARCH>: architecture dependent services for the tests
> -./<ARCH>: the sources of the tests and the created objects/images
> -
> +.: Makefile and config files for the tests
> +./config: config files for the tests
> +./docs: documentation files
> +./lib: general services for the tests
> +./lib/<ARCH>: architecture dependent services for the tests
> +./<ARCH>: the sources of the tests and the created objects/images
> +
> +See <ARCH>/README for arch specific documentation.
> diff --git a/config-i386.mak b/config-i386.mak
> deleted file mode 100644
> index de52f3d53cff8..0000000000000
> --- a/config-i386.mak
> +++ /dev/null
> @@ -1,13 +0,0 @@
> -TEST_DIR=x86
> -cstart.o = $(TEST_DIR)/cstart.o
> -bits = 32
> -ldarch = elf32-i386
> -CFLAGS += -D__i386__
> -CFLAGS += -I $(KERNELDIR)/include
> -
> -tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat
> -
> -include config-x86-common.mak
> -
> -$(TEST_DIR)/taskswitch.elf: $(cstart.o) $(TEST_DIR)/taskswitch.o
> -$(TEST_DIR)/taskswitch2.elf: $(cstart.o) $(TEST_DIR)/taskswitch2.o
> diff --git a/config-x86-common.mak b/config-x86-common.mak
> deleted file mode 100644
> index 7e481192a0737..0000000000000
> --- a/config-x86-common.mak
> +++ /dev/null
> @@ -1,120 +0,0 @@
> -#This is a make file with common rules for both x86 & x86-64
> -
> -all: test_cases
> -
> -cflatobjs += lib/x86/io.o
> -cflatobjs += lib/x86/smp.o
> -cflatobjs += lib/x86/vm.o
> -cflatobjs += lib/x86/fwcfg.o
> -cflatobjs += lib/x86/apic.o
> -cflatobjs += lib/x86/atomic.o
> -cflatobjs += lib/x86/desc.o
> -cflatobjs += lib/x86/isr.o
> -cflatobjs += lib/x86/pci.o
> -
> -$(libcflat): LDFLAGS += -nostdlib
> -$(libcflat): CFLAGS += -ffreestanding -I lib
> -
> -CFLAGS += -m$(bits)
> -CFLAGS += -O1
> -
> -libgcc := $(shell $(CC) -m$(bits) --print-libgcc-file-name)
> -
> -FLATLIBS = lib/libcflat.a $(libgcc)
> -%.elf: %.o $(FLATLIBS) flat.lds
> - $(CC) $(CFLAGS) -nostdlib -o $@ -Wl,-T,flat.lds \
> - $(filter %.o, $^) $(FLATLIBS)
> -
> -%.flat: %.elf
> - $(OBJCOPY) -O elf32-i386 $^ $@
> -
> -tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \
> - $(TEST_DIR)/smptest.flat $(TEST_DIR)/port80.flat \
> - $(TEST_DIR)/realmode.flat $(TEST_DIR)/msr.flat \
> - $(TEST_DIR)/hypercall.flat $(TEST_DIR)/sieve.flat \
> - $(TEST_DIR)/kvmclock_test.flat $(TEST_DIR)/eventinj.flat \
> - $(TEST_DIR)/s3.flat $(TEST_DIR)/pmu.flat \
> - $(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \
> - $(TEST_DIR)/init.flat
> -
> -ifdef API
> -tests-common += api/api-sample
> -tests-common += api/dirty-log
> -tests-common += api/dirty-log-perf
> -endif
> -
> -tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg
> -
> -test_cases: $(tests-common) $(tests)
> -
> -$(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I lib -I lib/x86
> -
> -$(TEST_DIR)/access.elf: $(cstart.o) $(TEST_DIR)/access.o
> -
> -$(TEST_DIR)/hypercall.elf: $(cstart.o) $(TEST_DIR)/hypercall.o
> -
> -$(TEST_DIR)/sieve.elf: $(cstart.o) $(TEST_DIR)/sieve.o
> -
> -$(TEST_DIR)/vmexit.elf: $(cstart.o) $(TEST_DIR)/vmexit.o
> -
> -$(TEST_DIR)/smptest.elf: $(cstart.o) $(TEST_DIR)/smptest.o
> -
> -$(TEST_DIR)/emulator.elf: $(cstart.o) $(TEST_DIR)/emulator.o
> -
> -$(TEST_DIR)/port80.elf: $(cstart.o) $(TEST_DIR)/port80.o
> -
> -$(TEST_DIR)/tsc.elf: $(cstart.o) $(TEST_DIR)/tsc.o
> -
> -$(TEST_DIR)/tsc_adjust.elf: $(cstart.o) $(TEST_DIR)/tsc_adjust.o
> -
> -$(TEST_DIR)/apic.elf: $(cstart.o) $(TEST_DIR)/apic.o
> -
> -$(TEST_DIR)/init.elf: $(cstart.o) $(TEST_DIR)/init.o
> -
> -$(TEST_DIR)/realmode.elf: $(TEST_DIR)/realmode.o
> - $(CC) -m32 -nostdlib -o $@ -Wl,-T,$(TEST_DIR)/realmode.lds $^
> -
> -$(TEST_DIR)/realmode.o: bits = 32
> -
> -$(TEST_DIR)/msr.elf: $(cstart.o) $(TEST_DIR)/msr.o
> -
> -$(TEST_DIR)/idt_test.elf: $(cstart.o) $(TEST_DIR)/idt_test.o
> -
> -$(TEST_DIR)/xsave.elf: $(cstart.o) $(TEST_DIR)/xsave.o
> -
> -$(TEST_DIR)/rmap_chain.elf: $(cstart.o) $(TEST_DIR)/rmap_chain.o
> -
> -$(TEST_DIR)/svm.elf: $(cstart.o)
> -
> -$(TEST_DIR)/kvmclock_test.elf: $(cstart.o) $(TEST_DIR)/kvmclock.o \
> - $(TEST_DIR)/kvmclock_test.o
> -
> -$(TEST_DIR)/eventinj.elf: $(cstart.o) $(TEST_DIR)/eventinj.o
> -
> -$(TEST_DIR)/s3.elf: $(cstart.o) $(TEST_DIR)/s3.o
> -
> -$(TEST_DIR)/pmu.elf: $(cstart.o) $(TEST_DIR)/pmu.o
> -
> -$(TEST_DIR)/asyncpf.elf: $(cstart.o) $(TEST_DIR)/asyncpf.o
> -
> -$(TEST_DIR)/pcid.elf: $(cstart.o) $(TEST_DIR)/pcid.o
> -
> -$(TEST_DIR)/vmx.elf: $(cstart.o) $(TEST_DIR)/vmx.o $(TEST_DIR)/vmx_tests.o
> -
> -arch_clean:
> - $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
> - $(TEST_DIR)/.*.d lib/x86/.*.d
> -
> -api/%.o: CFLAGS += -m32
> -
> -api/%: LDLIBS += -lstdc++ -lboost_thread-mt -lpthread -lrt
> -api/%: LDFLAGS += -m32
> -
> -api/libapi.a: api/kvmxx.o api/identity.o api/exception.o api/memmap.o
> - $(AR) rcs $@ $^
> -
> -api/api-sample: api/api-sample.o api/libapi.a
> -
> -api/dirty-log: api/dirty-log.o api/libapi.a
> -
> -api/dirty-log-perf: api/dirty-log-perf.o api/libapi.a
> diff --git a/config-x86_64.mak b/config-x86_64.mak
> deleted file mode 100644
> index bb8ee89713abd..0000000000000
> --- a/config-x86_64.mak
> +++ /dev/null
> @@ -1,14 +0,0 @@
> -TEST_DIR=x86
> -cstart.o = $(TEST_DIR)/cstart64.o
> -bits = 64
> -ldarch = elf64-x86-64
> -CFLAGS += -D__x86_64__
> -
> -tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \
> - $(TEST_DIR)/emulator.flat $(TEST_DIR)/idt_test.flat \
> - $(TEST_DIR)/xsave.flat $(TEST_DIR)/rmap_chain.flat \
> - $(TEST_DIR)/pcid.flat
> -tests += $(TEST_DIR)/svm.flat
> -tests += $(TEST_DIR)/vmx.flat
> -
> -include config-x86-common.mak
> diff --git a/config/config-i386.mak b/config/config-i386.mak
> new file mode 100644
> index 0000000000000..82fed0f5a48b0
> --- /dev/null
> +++ b/config/config-i386.mak
> @@ -0,0 +1,12 @@
> +cstart.o = $(TEST_DIR)/cstart.o
> +bits = 32
> +ldarch = elf32-i386
> +CFLAGS += -D__i386__
> +CFLAGS += -I $(KERNELDIR)/include
> +
> +tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat
> +
> +include config/config-x86-common.mak
> +
> +$(TEST_DIR)/taskswitch.elf: $(cstart.o) $(TEST_DIR)/taskswitch.o
> +$(TEST_DIR)/taskswitch2.elf: $(cstart.o) $(TEST_DIR)/taskswitch2.o
> diff --git a/config/config-x86-common.mak b/config/config-x86-common.mak
> new file mode 100644
> index 0000000000000..917cbbf801a65
> --- /dev/null
> +++ b/config/config-x86-common.mak
> @@ -0,0 +1,120 @@
> +#This is a make file with common rules for both x86 & x86-64
> +
> +all: test_cases
> +
> +cflatobjs += lib/x86/io.o
> +cflatobjs += lib/x86/smp.o
> +cflatobjs += lib/x86/vm.o
> +cflatobjs += lib/x86/fwcfg.o
> +cflatobjs += lib/x86/apic.o
> +cflatobjs += lib/x86/atomic.o
> +cflatobjs += lib/x86/desc.o
> +cflatobjs += lib/x86/isr.o
> +cflatobjs += lib/x86/pci.o
> +
> +$(libcflat): LDFLAGS += -nostdlib
> +$(libcflat): CFLAGS += -ffreestanding -I lib
> +
> +CFLAGS += -m$(bits)
> +CFLAGS += -O1
> +
> +libgcc := $(shell $(CC) -m$(bits) --print-libgcc-file-name)
> +
> +FLATLIBS = lib/libcflat.a $(libgcc)
> +%.elf: %.o $(FLATLIBS) x86/flat.lds
> + $(CC) $(CFLAGS) -nostdlib -o $@ -Wl,-T,x86/flat.lds \
> + $(filter %.o, $^) $(FLATLIBS)
> +
> +%.flat: %.elf
> + $(OBJCOPY) -O elf32-i386 $^ $@
> +
> +tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \
> + $(TEST_DIR)/smptest.flat $(TEST_DIR)/port80.flat \
> + $(TEST_DIR)/realmode.flat $(TEST_DIR)/msr.flat \
> + $(TEST_DIR)/hypercall.flat $(TEST_DIR)/sieve.flat \
> + $(TEST_DIR)/kvmclock_test.flat $(TEST_DIR)/eventinj.flat \
> + $(TEST_DIR)/s3.flat $(TEST_DIR)/pmu.flat \
> + $(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \
> + $(TEST_DIR)/init.flat
> +
> +ifdef API
> +tests-common += api/api-sample
> +tests-common += api/dirty-log
> +tests-common += api/dirty-log-perf
> +endif
> +
> +tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg
> +
> +test_cases: $(tests-common) $(tests)
> +
> +$(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I lib -I lib/x86
> +
> +$(TEST_DIR)/access.elf: $(cstart.o) $(TEST_DIR)/access.o
> +
> +$(TEST_DIR)/hypercall.elf: $(cstart.o) $(TEST_DIR)/hypercall.o
> +
> +$(TEST_DIR)/sieve.elf: $(cstart.o) $(TEST_DIR)/sieve.o
> +
> +$(TEST_DIR)/vmexit.elf: $(cstart.o) $(TEST_DIR)/vmexit.o
> +
> +$(TEST_DIR)/smptest.elf: $(cstart.o) $(TEST_DIR)/smptest.o
> +
> +$(TEST_DIR)/emulator.elf: $(cstart.o) $(TEST_DIR)/emulator.o
> +
> +$(TEST_DIR)/port80.elf: $(cstart.o) $(TEST_DIR)/port80.o
> +
> +$(TEST_DIR)/tsc.elf: $(cstart.o) $(TEST_DIR)/tsc.o
> +
> +$(TEST_DIR)/tsc_adjust.elf: $(cstart.o) $(TEST_DIR)/tsc_adjust.o
> +
> +$(TEST_DIR)/apic.elf: $(cstart.o) $(TEST_DIR)/apic.o
> +
> +$(TEST_DIR)/init.elf: $(cstart.o) $(TEST_DIR)/init.o
> +
> +$(TEST_DIR)/realmode.elf: $(TEST_DIR)/realmode.o
> + $(CC) -m32 -nostdlib -o $@ -Wl,-T,$(TEST_DIR)/realmode.lds $^
> +
> +$(TEST_DIR)/realmode.o: bits = 32
> +
> +$(TEST_DIR)/msr.elf: $(cstart.o) $(TEST_DIR)/msr.o
> +
> +$(TEST_DIR)/idt_test.elf: $(cstart.o) $(TEST_DIR)/idt_test.o
> +
> +$(TEST_DIR)/xsave.elf: $(cstart.o) $(TEST_DIR)/xsave.o
> +
> +$(TEST_DIR)/rmap_chain.elf: $(cstart.o) $(TEST_DIR)/rmap_chain.o
> +
> +$(TEST_DIR)/svm.elf: $(cstart.o)
> +
> +$(TEST_DIR)/kvmclock_test.elf: $(cstart.o) $(TEST_DIR)/kvmclock.o \
> + $(TEST_DIR)/kvmclock_test.o
> +
> +$(TEST_DIR)/eventinj.elf: $(cstart.o) $(TEST_DIR)/eventinj.o
> +
> +$(TEST_DIR)/s3.elf: $(cstart.o) $(TEST_DIR)/s3.o
> +
> +$(TEST_DIR)/pmu.elf: $(cstart.o) $(TEST_DIR)/pmu.o
> +
> +$(TEST_DIR)/asyncpf.elf: $(cstart.o) $(TEST_DIR)/asyncpf.o
> +
> +$(TEST_DIR)/pcid.elf: $(cstart.o) $(TEST_DIR)/pcid.o
> +
> +$(TEST_DIR)/vmx.elf: $(cstart.o) $(TEST_DIR)/vmx.o $(TEST_DIR)/vmx_tests.o
> +
> +arch_clean:
> + $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
> + $(TEST_DIR)/.*.d lib/x86/.*.d
> +
> +api/%.o: CFLAGS += -m32
> +
> +api/%: LDLIBS += -lstdc++ -lboost_thread-mt -lpthread -lrt
> +api/%: LDFLAGS += -m32
> +
> +api/libapi.a: api/kvmxx.o api/identity.o api/exception.o api/memmap.o
> + $(AR) rcs $@ $^
> +
> +api/api-sample: api/api-sample.o api/libapi.a
> +
> +api/dirty-log: api/dirty-log.o api/libapi.a
> +
> +api/dirty-log-perf: api/dirty-log-perf.o api/libapi.a
> diff --git a/config/config-x86_64.mak b/config/config-x86_64.mak
> new file mode 100644
> index 0000000000000..f089b05a178c3
> --- /dev/null
> +++ b/config/config-x86_64.mak
> @@ -0,0 +1,13 @@
> +cstart.o = $(TEST_DIR)/cstart64.o
> +bits = 64
> +ldarch = elf64-x86-64
> +CFLAGS += -D__x86_64__
> +
> +tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \
> + $(TEST_DIR)/emulator.flat $(TEST_DIR)/idt_test.flat \
> + $(TEST_DIR)/xsave.flat $(TEST_DIR)/rmap_chain.flat \
> + $(TEST_DIR)/pcid.flat
> +tests += $(TEST_DIR)/svm.flat
> +tests += $(TEST_DIR)/vmx.flat
> +
> +include config/config-x86-common.mak
> diff --git a/configure b/configure
> index d0c62e24dd1d2..6cfc64943f6e6 100755
> --- a/configure
> +++ b/configure
> @@ -15,6 +15,7 @@ usage() {
> Usage: $0 [options]
>
> Options include:
> + --test-dir=DIR the main directory for tests ($arch)
huh? why would you want to specify something different from arch here?
> --arch=ARCH architecture to compile for ($arch)
> --cross-prefix=PREFIX cross compiler prefix
> --cc=CC c compiler to use ($cc)
> @@ -33,6 +34,9 @@ while [[ "$1" = -* ]]; do
> opt="${opt%%=*}"
> fi
> case "$opt" in
> + --test-dir)
> + testdir="$arg"
> + ;;
> --prefix)
> prefix="$arg"
> ;;
> @@ -62,6 +66,18 @@ while [[ "$1" = -* ]]; do
> ;;
> esac
> done
> +if [ -z "$testdir" -a \( "$arch" = "i386" -o "$arch" = "x86_64" \) ]; then
> + testdir=x86
> +elif [ -z "$testdir" ]; then
> + testdir=$arch
> +fi
> +if [ ! -d $testdir ]; then
> + echo "$testdir does not exist!"
> + exit 1
> +fi
> +if [ -f $testdir/run ]; then
> + ln -fs $testdir/run $testdir-run
> +fi
>
> # check for dependent 32 bit libraries
> cat << EOF > lib_test.c
> @@ -89,4 +105,5 @@ LD=$cross_prefix$ld
> OBJCOPY=$cross_prefix$objcopy
> AR=$cross_prefix$ar
> API=$api
> +TEST_DIR=$testdir
> EOF
> diff --git a/docs/testdev.txt b/docs/testdev.txt
> new file mode 100644
> index 0000000000000..854b5c774b60c
> --- /dev/null
> +++ b/docs/testdev.txt
> @@ -0,0 +1,11 @@
> +This file describes the virtual device of qemu for supporting this test suite.
> +
> +Services supplied by the testdev device:
> +
> +serial output: write only, on io port 0xf1
> +exit process: write only, on io port 0xf4, value used as exit code
> +ram size: read-only, on io port 0xd1, 4 bytes' size
> +irq line setting: write only, on io ports 0x2000 - 0x2018, value to set/clear
> +simple io: read/write, on io port 0xe0, 1/2/4 bytes
> +
> +Test device used a char device for actual output
what do you mean by this last sentence?
> diff --git a/flat.lds b/flat.lds
> deleted file mode 100644
> index a278b56c9a4e3..0000000000000
> --- a/flat.lds
> +++ /dev/null
> @@ -1,21 +0,0 @@
> -SECTIONS
> -{
> - . = 4M + SIZEOF_HEADERS;
> - stext = .;
> - .text : { *(.init) *(.text) *(.text.*) }
> - . = ALIGN(4K);
> - .data : {
> - *(.data)
> - exception_table_start = .;
> - *(.data.ex)
> - exception_table_end = .;
> - }
> - . = ALIGN(16);
> - .rodata : { *(.rodata) }
> - . = ALIGN(16);
> - .bss : { *(.bss) }
> - . = ALIGN(4K);
> - edata = .;
> -}
> -
> -ENTRY(start)
> diff --git a/run_tests.sh b/run_tests.sh
> index f373c533b75b2..400c62458ae18 100755
> --- a/run_tests.sh
> +++ b/run_tests.sh
> @@ -1,8 +1,10 @@
> #!/bin/bash
>
> -testroot=x86
> -config=$testroot/unittests.cfg
> -qemu=${qemu:-qemu-system-x86_64}
> +# As it happens, config.mak is valid shell script code, too :-)
> +source config.mak
is this a well-established method of doing things or a hack? If the
latter, sems like something that could quickly come and bite us.
> +
> +config=$TEST_DIR/unittests.cfg
> +qemu=${QEMU:-qemu-system-$ARCH}
> verbose=0
>
> function run()
> @@ -27,7 +29,7 @@ function run()
> return
> fi
>
> - cmdline="./x86-run $kernel -smp $smp $opts"
> + cmdline="./$TEST_DIR-run $kernel -smp $smp $opts"
> if [ $verbose != 0 ]; then
> echo $cmdline
> fi
> @@ -65,7 +67,7 @@ function run_all()
> groups=""
> arch=""
> elif [[ $line =~ ^file\ *=\ *(.*)$ ]]; then
> - kernel=$testroot/${BASH_REMATCH[1]}
> + kernel=$TEST_DIR/${BASH_REMATCH[1]}
> elif [[ $line =~ ^smp\ *=\ *(.*)$ ]]; then
> smp=${BASH_REMATCH[1]}
> elif [[ $line =~ ^extra_params\ *=\ *(.*)$ ]]; then
> @@ -92,15 +94,12 @@ Usage: $0 [-g group] [-h] [-v]
> -h: Output this help text
> -v: Enables verbose mode
>
> -Set the environment variable QEMU=/path/to/qemu-system-x86_64 to allow the
> -internally used x86-run to pick up the right qemu binary.
> +Set the environment variable QEMU=/path/to/qemu-system-ARCH to allow the
> +internally used ARCH-run to pick up the right qemu binary.
this message may not make a lot of sense to non kvm-unit-test
devevelopers, why not say that it allows the user to specify which QEMU
binary to use?
>
> EOF
> }
>
> -# As it happens, config.mak is valid shell script code, too :-)
> -source config.mak
> -
ah, I see, this hack/method was used before too, still relevant to
consider if it's a good approach though...
> echo > test.log
> while getopts "g:hv" opt; do
> case $opt in
> diff --git a/testdev.txt b/testdev.txt
> deleted file mode 100644
> index ac436efadb633..0000000000000
> --- a/testdev.txt
> +++ /dev/null
> @@ -1,14 +0,0 @@
> -This file describes the virtual device of qemu for supporting this test suite.
> -
> -Services supplied by the testdev device:
> -
> -serial output: write only, on io port 0xf1
> -exit process: write only, on io port 0xf4, value used as exit code
> -ram size: read-only, on io port 0xd1, 4 bytes' size
> -irq line setting: write only, on io ports 0x2000 - 0x2018, value to set/clear
> -simple io: read/write, on io port 0xe0, 1/2/4 bytes
> -
> -Test device used a char device for actual output
> -
> -
> -
> diff --git a/x86-run b/x86-run
> deleted file mode 100755
> index 646c5770ed03f..0000000000000
> --- a/x86-run
> +++ /dev/null
> @@ -1,41 +0,0 @@
> -#!/bin/bash
> -
> -qemukvm="${QEMU:-qemu-kvm}"
> -qemusystem="${QEMU:-qemu-system-x86_64}"
> -if
> - ${qemukvm} -device '?' 2>&1 | grep -F -e \"testdev\" -e \"pc-testdev\" > /dev/null;
> -then
> - qemu="${qemukvm}"
> -else
> - if
> - ${qemusystem} -device '?' 2>&1 | grep -F -e \"testdev\" -e \"pc-testdev\" > /dev/null;
> - then
> - qemu="${qemusystem}"
> - else
> - echo QEMU binary ${QEMU} has no support for test device. Exiting.
> - exit 2
> - fi
> -fi
> -
> -if
> - ${qemu} -device '?' 2>&1 | grep -F "pci-testdev" > /dev/null;
> -then
> - pci_testdev="-device pci-testdev"
> -else
> - pci_testdev=""
> -fi
> -
> -if
> - ${qemu} -device '?' 2>&1 | grep -F "pc-testdev" > /dev/null;
> -then
> - pc_testdev="-device pc-testdev -device isa-debug-exit,iobase=0xf4,iosize=0x4"
> -else
> - pc_testdev="-device testdev,chardev=testlog -chardev file,id=testlog,path=msr.out"
> -fi
> -
> -command="${qemu} -enable-kvm $pc_testdev -display none -serial stdio $pci_testdev -kernel"
> -echo ${command} "$@"
> -${command} "$@"
> -ret=$?
> -echo Return value from qemu: $ret
> -exit $ret
> diff --git a/x86/README b/x86/README
> index d644abdf31708..2f4baa46c6ed1 100644
> --- a/x86/README
> +++ b/x86/README
> @@ -1,16 +1,48 @@
> +
> +Tests for x86 architecture are run as kernel images for qemu that supports
> +multiboot format. Tests uses an infrastructure called from the bios code.
> +The infrastructure initialize the system/cpu's, switch to long-mode and calls
> +the 'main' function of the individual test. Tests uses a qemu's virtual test
Tests use
> +device, named testdev, for services like printing, exiting, query memory
> +size etc. See file docs/testdev.txt for more details.
> +
> +An example of a test invocation:
> +Using qemu-kvm:
> +
> +qemu-kvm -device testdev,chardev=testlog \
> + -chardev file,id=testlog,path=msr.out \
> + -serial stdio -kernel ./x86/msr.flat
> +This invocation runs the msr test case. The test outputs to stdio.
> +
> +Using qemu (supported since qemu 1.3):
> +qemu-system-x86_64 -enable-kvm -device pc-testdev -serial stdio \
> + -device isa-debug-exit,iobase=0xf4,iosize=0x4 \
> + -kernel ./x86/msr.flat
> +
> Tests in this directory and what they do:
>
> -access: lots of page table related access (pte/pde) (read/write)
> -apic: enable x2apic, self ipi, ioapic intr, ioapic simultaneous
> -emulator: move to/from regs, cmps, push, pop, to/from cr8, smsw and lmsw
> -hypercall: intel and amd hypercall insn
> -msr: write to msr (only KERNEL_GS_BASE for now)
> -port80: lots of out to port 80
> -realmode: goes back to realmode, shld, push/pop, mov immediate, cmp immediate, add immediate,
> - io, eflags instructions (clc, cli, etc.), jcc short, jcc near, call, long jmp, xchg
> -sieve: heavy memory access with no paging and with paging static and with paging vmalloc'ed
> -smptest: run smp_id() on every cpu and compares return value to number
> -tsc: write to tsc(0) and write to tsc(100000000000) and read it back
> -vmexit: long loops for each: cpuid, vmcall, mov_from_cr8, mov_to_cr8, inl_pmtimer, ipi, ipi+halt
> -kvmclock_test: test of wallclock, monotonic cycle and performance of kvmclock
> -pcid: basic functionality test of PCID/INVPCID feature
> \ No newline at end of file
> + access: lots of page table related access (pte/pde) (read/write)
> + apic: enable x2apic, self ipi, ioapic intr, ioapic simultaneous
> + emulator: move to/from regs, cmps, push, pop, to/from cr8, smsw and lmsw
> + hypercall: intel and amd hypercall insn
> + msr: write to msr (only KERNEL_GS_BASE for now)
> + port80: lots of out to port 80
> + realmode: goes back to realmode, shld, push/pop, mov immediate,
> + cmp immediate, add immediate, io, eflags instructions
> + (clc, cli, etc.), jcc short, jcc near, call, long jmp, xchg
> + sieve: heavy memory access with no paging and with paging static and
> + with paging vmalloc'ed
> + smptest: run smp_id() on every cpu and compares return value to number
> + tsc: write to tsc(0) and write to tsc(100000000000) and read it back
> + vmexit: long loops for each: cpuid, vmcall, mov_from_cr8, mov_to_cr8,
> + inl_pmtimer, ipi, ipi+halt
> + kvmclock_test: test of wallclock, monotonic cycle and performance of kvmclock
> + pcid: basic functionality test of PCID/INVPCID featureThis directory
> + contains sources for a kvm test suite.
> +
> +Legacy notes:
> +
> + The exit status of the binary (and the script) is inconsistent: with
> + qemu-system, after the unittest is done, the exit status of qemu is 1,
> + different from the 'old style' qemu-kvm, whose exit status in successful
> + completion is 0.
> diff --git a/x86/flat.lds b/x86/flat.lds
> new file mode 100644
> index 0000000000000..a278b56c9a4e3
> --- /dev/null
> +++ b/x86/flat.lds
> @@ -0,0 +1,21 @@
> +SECTIONS
> +{
> + . = 4M + SIZEOF_HEADERS;
> + stext = .;
> + .text : { *(.init) *(.text) *(.text.*) }
> + . = ALIGN(4K);
> + .data : {
> + *(.data)
> + exception_table_start = .;
> + *(.data.ex)
> + exception_table_end = .;
> + }
> + . = ALIGN(16);
> + .rodata : { *(.rodata) }
> + . = ALIGN(16);
> + .bss : { *(.bss) }
> + . = ALIGN(4K);
> + edata = .;
> +}
> +
> +ENTRY(start)
> diff --git a/x86/run b/x86/run
> new file mode 100755
> index 0000000000000..646c5770ed03f
> --- /dev/null
> +++ b/x86/run
> @@ -0,0 +1,41 @@
> +#!/bin/bash
> +
> +qemukvm="${QEMU:-qemu-kvm}"
> +qemusystem="${QEMU:-qemu-system-x86_64}"
> +if
> + ${qemukvm} -device '?' 2>&1 | grep -F -e \"testdev\" -e \"pc-testdev\" > /dev/null;
> +then
> + qemu="${qemukvm}"
> +else
> + if
> + ${qemusystem} -device '?' 2>&1 | grep -F -e \"testdev\" -e \"pc-testdev\" > /dev/null;
> + then
> + qemu="${qemusystem}"
> + else
> + echo QEMU binary ${QEMU} has no support for test device. Exiting.
> + exit 2
> + fi
> +fi
> +
> +if
> + ${qemu} -device '?' 2>&1 | grep -F "pci-testdev" > /dev/null;
> +then
> + pci_testdev="-device pci-testdev"
> +else
> + pci_testdev=""
> +fi
> +
> +if
> + ${qemu} -device '?' 2>&1 | grep -F "pc-testdev" > /dev/null;
> +then
> + pc_testdev="-device pc-testdev -device isa-debug-exit,iobase=0xf4,iosize=0x4"
> +else
> + pc_testdev="-device testdev,chardev=testlog -chardev file,id=testlog,path=msr.out"
> +fi
> +
> +command="${qemu} -enable-kvm $pc_testdev -display none -serial stdio $pci_testdev -kernel"
> +echo ${command} "$@"
> +${command} "$@"
> +ret=$?
> +echo Return value from qemu: $ret
> +exit $ret
> --
> 1.8.1.4
>
> _______________________________________________
> kvmarm mailing list
> kvmarm@lists.cs.columbia.edu
> https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
--
Christoffer
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 4/9] move x86's simple heap management to common code
2013-12-04 16:42 ` [PATCH 4/9] move x86's simple heap management to common code Andrew Jones
@ 2013-12-29 6:30 ` Christoffer Dall
2014-01-02 15:17 ` Andrew Jones
0 siblings, 1 reply; 44+ messages in thread
From: Christoffer Dall @ 2013-12-29 6:30 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvmarm, kvm
On Wed, Dec 04, 2013 at 05:42:52PM +0100, Andrew Jones wrote:
> Signed-off-by: Andrew Jones <drjones@redhat.com>
> ---
> config/config-x86-common.mak | 1 +
> lib/heap.c | 43 +++++++++++++++++++++++++++++++++++++++++++
> lib/heap.h | 8 ++++++++
> lib/x86/vm.c | 33 ++-------------------------------
> 4 files changed, 54 insertions(+), 31 deletions(-)
> create mode 100644 lib/heap.c
> create mode 100644 lib/heap.h
>
> diff --git a/config/config-x86-common.mak b/config/config-x86-common.mak
> index 917cbbf801a65..8a78f7a6c8849 100644
> --- a/config/config-x86-common.mak
> +++ b/config/config-x86-common.mak
> @@ -2,6 +2,7 @@
>
> all: test_cases
>
> +cflatobjs += lib/heap.o
> cflatobjs += lib/x86/io.o
> cflatobjs += lib/x86/smp.o
> cflatobjs += lib/x86/vm.o
> diff --git a/lib/heap.c b/lib/heap.c
> new file mode 100644
> index 0000000000000..e52ee0edba163
> --- /dev/null
> +++ b/lib/heap.c
> @@ -0,0 +1,43 @@
> +#include "libcflat.h"
> +
> +static size_t pagesize;
> +static void *free_head;
> +
> +void heap_init(void *start, size_t size, size_t page_size)
> +{
> + unsigned long s = (unsigned long)start;
> + void *p = start;
> +
> + pagesize = page_size;
> +
> + if (s != (s & ~(pagesize - 1))) {
you're just testing 'if (s & (pagesize -1))' right?
> + s += pagesize;
> + s &= ~(pagesize - 1);
> + p = (void *)s;
> + }
a one-line comment on this block saying 'page-align start of heap would
be nice.
> +
> + while (size >= pagesize) {
> + *(void **)p = free_head;
> + free_head = p;
> + p += pagesize;
> + size -= pagesize;
> + }
you could also be nice and comment this block of code, saying something
like "set up linked list of free pages using the pages themselves as the
data structure" if you should feel so inclined.
why are you not trusting start to be page aligned but you are trusting
size to be? If size is smaller than pagesize then this loop will go
nuts won't it?
> +}
> +
> +void *alloc_page(void)
> +{
> + void *p;
> +
> + if (!free_head)
> + return NULL;
> +
> + p = free_head;
> + free_head = *(void **)free_head;
> + return p;
> +}
> +
> +void free_page(void *page)
> +{
> + *(void **)page = free_head;
> + free_head = page;
> +}
> diff --git a/lib/heap.h b/lib/heap.h
> new file mode 100644
> index 0000000000000..78b893021ae92
> --- /dev/null
> +++ b/lib/heap.h
> @@ -0,0 +1,8 @@
> +#ifndef _HEAP_H_
> +#define _HEAP_H_
> +#include "libcflat.h"
> +
> +extern void heap_init(void *start, size_t size, size_t page_size);
> +extern void *alloc_page(void);
> +extern void free_page(void *page);
> +#endif
> diff --git a/lib/x86/vm.c b/lib/x86/vm.c
> index 188bf57587aa7..725cfe33259c2 100644
> --- a/lib/x86/vm.c
> +++ b/lib/x86/vm.c
> @@ -1,6 +1,7 @@
> #include "fwcfg.h"
> #include "vm.h"
> #include "libcflat.h"
> +#include "heap.h"
>
> #define PAGE_SIZE 4096ul
> #ifdef __x86_64__
> @@ -9,38 +10,8 @@
> #define LARGE_PAGE_SIZE (1024 * PAGE_SIZE)
> #endif
>
> -static void *free = 0;
> static void *vfree_top = 0;
>
> -static void free_memory(void *mem, unsigned long size)
> -{
> - while (size >= PAGE_SIZE) {
> - *(void **)mem = free;
> - free = mem;
> - mem += PAGE_SIZE;
> - size -= PAGE_SIZE;
> - }
> -}
> -
> -void *alloc_page()
> -{
> - void *p;
> -
> - if (!free)
> - return 0;
> -
> - p = free;
> - free = *(void **)free;
> -
> - return p;
> -}
> -
> -void free_page(void *page)
> -{
> - *(void **)page = free;
> - free = page;
> -}
> -
> extern char edata;
> static unsigned long end_of_memory;
>
> @@ -185,7 +156,7 @@ static void setup_mmu(unsigned long len)
> void setup_vm()
> {
> end_of_memory = fwcfg_get_u64(FW_CFG_RAM_SIZE);
> - free_memory(&edata, end_of_memory - (unsigned long)&edata);
> + heap_init(&edata, end_of_memory - (unsigned long)&edata, PAGE_SIZE);
> setup_mmu(end_of_memory);
> }
>
> --
> 1.8.1.4
>
> _______________________________________________
> kvmarm mailing list
> kvmarm@lists.cs.columbia.edu
> https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
--
Christoffer
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 5/9] Introduce libio to common code for io read/write
2013-12-04 16:42 ` [PATCH 5/9] Introduce libio to common code for io read/write Andrew Jones
@ 2013-12-29 6:30 ` Christoffer Dall
2014-01-02 15:47 ` Andrew Jones
0 siblings, 1 reply; 44+ messages in thread
From: Christoffer Dall @ 2013-12-29 6:30 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvmarm, kvm
On Wed, Dec 04, 2013 at 05:42:53PM +0100, Andrew Jones wrote:
Wow, are you being charged extra taxes per commit message keystroke over
there? ;)
> Signed-off-by: Andrew Jones <drjones@redhat.com>
> ---
> lib/libio.c | 67 +++++++++++++++++++++++
> lib/libio.h | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 243 insertions(+)
> create mode 100644 lib/libio.c
> create mode 100644 lib/libio.h
>
> diff --git a/lib/libio.c b/lib/libio.c
> new file mode 100644
> index 0000000000000..e450e984fefb1
> --- /dev/null
> +++ b/lib/libio.c
> @@ -0,0 +1,67 @@
> +#include "libcflat.h"
> +#include "libio.h"
> +
> +void read_len(const volatile void *addr, void *buf, unsigned len)
> +{
> + unsigned long val;
> +
> + switch (len) {
> + case 1:
> + val = readb(addr);
> + break;
> + case 2:
> + val = readw(addr);
> + break;
> + case 4:
> + val = readl(addr);
> + break;
> +#ifdef CONFIG_64BIT
> + case 8:
> + val = readq(addr);
> + break;
> +#endif
> + default:
> + {
> + u8 *p = buf;
> + unsigned i;
> +
> + for (i = 0; i < len; ++i)
> + p[i] = readb(addr + i);
> + return;
are you taking proper care of endianness in the common case?
> + }
> + }
> + memcpy(buf, &val, len);
> +}
> +
> +void write_len(volatile void *addr, const void *buf, unsigned len)
> +{
> + unsigned long val;
> +
> + if (len <= sizeof(unsigned long))
> + memcpy(&val, buf, len);
Does this work with big-endian for sizes smaller than sizeof(unsigned
long)?
Take a look at arch/arm/kvm/mmio.c and see how Marc uses a union to
solve this issue.
> +
> + switch (len) {
> + case 1:
> + writeb(val, addr);
> + break;
> + case 2:
> + writew(val, addr);
> + break;
> + case 4:
> + writel(val, addr);
> + break;
> +#ifdef CONFIG_64BIT
> + case 8:
> + writeq(val, addr);
> + break;
> +#endif
> + default:
> + {
> + const u8 *p = buf;
> + unsigned i;
> +
> + for (i = 0; i < len; ++i)
> + writeb(p[i], addr + i);
same as above?
> + }
> + }
> +}
> diff --git a/lib/libio.h b/lib/libio.h
> new file mode 100644
> index 0000000000000..210b8d78af43f
> --- /dev/null
> +++ b/lib/libio.h
> @@ -0,0 +1,176 @@
> +#ifndef _LIBIO_H_
> +#define _LIBIO_H_
> +/*
> + * Adapted from the Linux kernel's include/asm-generic/io.h and
> + * arch/arm/include/asm/io.h
> + */
> +#include "libcflat.h"
> +
> +typedef u32 compat_ptr_t;
How is this going to be used here? The compat ptr stuff in the kernel
deals with user space pointer iirc, but I'm not an expert on the
details. Does typedef'ing a pointer to a u32 in generic code work on a
64-bit platform?
> +
> +static inline void *compat_ptr(compat_ptr_t ptr)
> +{
> + return (void *)(unsigned long)ptr;
> +}
> +
> +static inline compat_ptr_t ptr_to_compat(void *ptr)
> +{
> + return (u32)(unsigned long)ptr;
> +}
> +
> +#ifndef __raw_readb
> +static inline u8 __raw_readb(const volatile void *addr)
> +{
> + return *(const volatile u8 *)addr;
> +}
> +#endif
> +
> +#ifndef __raw_readw
> +static inline u16 __raw_readw(const volatile void *addr)
> +{
> + return *(const volatile u16 *)addr;
> +}
> +#endif
> +
> +#ifndef __raw_readl
> +static inline u32 __raw_readl(const volatile void *addr)
> +{
> + return *(const volatile u32 *)addr;
> +}
> +#endif
> +
> +#ifdef CONFIG_64BIT
> +#ifndef __raw_readq
> +static inline u64 __raw_readq(const volatile void *addr)
> +{
> + return *(const volatile u64 *)addr;
> +}
> +#endif
> +#endif
> +
> +#ifndef __raw_writeb
> +static inline void __raw_writeb(u8 b, volatile void *addr)
> +{
> + *(volatile u8 *)addr = b;
> +}
> +#endif
> +
> +#ifndef __raw_writew
> +static inline void __raw_writew(u16 b, volatile void *addr)
> +{
> + *(volatile u16 *)addr = b;
> +}
> +#endif
> +
> +#ifndef __raw_writel
> +static inline void __raw_writel(u32 b, volatile void *addr)
> +{
> + *(volatile u32 *)addr = b;
> +}
> +#endif
> +
> +#ifdef CONFIG_64BIT
> +#ifndef __raw_writeq
> +static inline void __raw_writeq(u64 b, volatile void *addr)
> +{
> + *(volatile u64 *)addr = b;
> +}
> +#endif
> +#endif
> +
> +#ifndef __bswap16
> +static inline u16 __bswap16(u16 x)
> +{
> + return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
> +}
> +#endif
> +
> +#ifndef __bswap32
> +static inline u32 __bswap32(u32 x)
> +{
> + return ((x & 0xff000000) >> 24) | ((x & 0x00ff0000) >> 8) |
> + ((x & 0x0000ff00) << 8) | ((x & 0x000000ff) << 24);
> +}
> +#endif
> +
> +#ifdef CONFIG_64BIT
> +#ifndef __bswap64
> +static inline u64 __bswap64(u64 x)
> +{
> + return ((x & 0x00000000000000ffULL) << 56) |
> + ((x & 0x000000000000ff00ULL) << 40) |
> + ((x & 0x0000000000ff0000ULL) << 24) |
> + ((x & 0x00000000ff000000ULL) << 8) |
> + ((x & 0x000000ff00000000ULL) >> 8) |
> + ((x & 0x0000ff0000000000ULL) >> 24) |
> + ((x & 0x00ff000000000000ULL) >> 40) |
> + ((x & 0xff00000000000000ULL) >> 56);
> +}
> +#endif
> +#endif
> +
> +#ifndef cpu_is_be
> +#define cpu_is_be 0
> +#endif
> +
> +#define le16_to_cpu(x) \
> + ({ u16 __r = cpu_is_be ? __bswap16(x) : (x); __r; })
> +#define cpu_to_le16 le16_to_cpu
> +
> +#define le32_to_cpu(x) \
> + ({ u32 __r = cpu_is_be ? __bswap32(x) : (x); __r; })
> +#define cpu_to_le32 le32_to_cpu
> +
> +#ifdef CONFIG_64BIT
> +#define le64_to_cpu \
> + ({ u64 __r = cpu_is_be ? __bswap64(x) : (x); __r; })
> +#define cpu_to_le64 le64_to_cpu
> +#endif
> +
> +#define be16_to_cpu(x) \
> + ({ u16 __r = !cpu_is_be ? __bswap16(x) : (x); __r; })
> +#define cpu_to_be16 be16_to_cpu
> +
> +#define be32_to_cpu(x) \
> + ({ u32 __r = !cpu_is_be ? __bswap32(x) : (x); __r; })
> +#define cpu_to_be32 be32_to_cpu
> +
> +#ifdef CONFIG_64BIT
> +#define be64_to_cpu \
> + ({ u64 __r = !cpu_is_be ? __bswap64(x) : (x); __r; })
> +#define cpu_to_be64 be64_to_cpu
> +#endif
> +
> +#ifndef rmb
> +#define rmb() do { } while (0)
> +#endif
> +#ifndef wmb
> +#define wmb() do { } while (0)
> +#endif
> +
> +#define readb(addr) \
> + ({ u8 __r = __raw_readb(addr); rmb(); __r; })
> +#define readw(addr) \
> + ({ u16 __r = le16_to_cpu(__raw_readw(addr)); rmb(); __r; })
> +#define readl(addr) \
> + ({ u32 __r = le32_to_cpu(__raw_readl(addr)); rmb(); __r; })
> +#ifdef CONFIG_64BIT
> +#define readq(addr) \
> + ({ u64 __r = le64_to_cpu(__raw_readq(addr)); rmb(); __r; })
> +#endif
> +
> +#define writeb(b, addr) \
> + ({ wmb(); __raw_writeb(b, addr); })
> +#define writew(b, addr) \
> + ({ wmb(); __raw_writew(cpu_to_le16(b), addr); })
> +#define writel(b, addr) \
> + ({ wmb(); __raw_writel(cpu_to_le32(b), addr); })
> +#ifdef CONFIG_64BIT
> +#define writeq(b, addr) \
> + ({ wmb(); __raw_writeq(cpu_to_le64(b), addr); })
> +#endif
> +
> +extern void read_len(const volatile void *addr, void *buf, unsigned len);
> +extern void write_len(volatile void *addr, const void *buf, unsigned len);
> +
> +#endif
> --
> 1.8.1.4
I didn't review all these defines and raw_ functions carefully as I
assume the individual functions and defines are copied verbatim from the
kernel?
--
Christoffer
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 6/9] Introduce a simple iomap structure
2013-12-04 16:42 ` [PATCH 6/9] Introduce a simple iomap structure Andrew Jones
@ 2013-12-29 6:30 ` Christoffer Dall
2014-01-02 16:04 ` Andrew Jones
0 siblings, 1 reply; 44+ messages in thread
From: Christoffer Dall @ 2013-12-29 6:30 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvmarm, kvm
On Wed, Dec 04, 2013 at 05:42:54PM +0100, Andrew Jones wrote:
> Add a simple structure and search function to the common code that
> can be used for looking up a set of addresses by type. The user
> must supply the iomaps[] table, e.g.
>
> struct iomap iomaps[] = {
> {
> .type = "virtio_mmio",
> .nr = 4,
> .addrs = { 0x2000000, 0x2000200, 0x2000400, 0x2000600, },
> },
> {
> .type = NULL,
> },
> };
>
> Also add a script scripts/gen-devtree-iomaps.pl that can generate
> the iomaps table from an fdt, e.g.
>
> fdtdump dtb | scripts/gen-devtree-iomaps.pl - virtio_mmio
>
> Signed-off-by: Andrew Jones <drjones@redhat.com>
>
> ---
> v2:
> - switch to kernel coding style
> - rework fdt parsing to enable extraction of properties. Extract
> the 'compatible' property.
> - add iomaps_find_compatible() to allow searching for iomaps by
> its 'compatible' property.
> ---
> README | 1 +
> lib/iomaps.c | 31 +++++++++++++
> lib/iomaps.h | 14 ++++++
> scripts/gen-devtree-iomaps.pl | 105 ++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 151 insertions(+)
> create mode 100644 lib/iomaps.c
> create mode 100644 lib/iomaps.h
> create mode 100755 scripts/gen-devtree-iomaps.pl
>
> diff --git a/README b/README
> index 0174679c05021..f834c61dc6112 100644
> --- a/README
> +++ b/README
> @@ -20,6 +20,7 @@ Directory structure:
> .: Makefile and config files for the tests
> ./config: config files for the tests
> ./docs: documentation files
> +./scripts: misc helper scripts
> ./lib: general services for the tests
> ./lib/<ARCH>: architecture dependent services for the tests
> ./<ARCH>: the sources of the tests and the created objects/images
> diff --git a/lib/iomaps.c b/lib/iomaps.c
> new file mode 100644
> index 0000000000000..f2263b79dce96
> --- /dev/null
> +++ b/lib/iomaps.c
> @@ -0,0 +1,31 @@
> +#include "libcflat.h"
> +#include "iomaps.h"
> +
> +extern const struct iomap iomaps[];
> +
> +const struct iomap *iomaps_find_type(const char *type)
> +{
> + const struct iomap *m = &iomaps[0];
> +
> + while (m->type) {
> + if (strcmp(m->type, type) == 0)
> + return m;
> + ++m;
> + }
> + return NULL;
> +}
> +
> +const struct iomap *iomaps_find_compatible(const char *compat)
> +{
> + const struct iomap *m = &iomaps[0];
> + const char *c;
> + int i;
> +
> + while (m->type) {
> + for (i = 0, c = m->compats[0]; c != NULL; c = m->compats[++i])
> + if (strcmp(c, compat) == 0)
> + return m;
> + ++m;
> + }
> + return NULL;
> +}
> diff --git a/lib/iomaps.h b/lib/iomaps.h
> new file mode 100644
> index 0000000000000..76a1aa4720337
> --- /dev/null
> +++ b/lib/iomaps.h
> @@ -0,0 +1,14 @@
> +#ifndef _IOMAPS_H_
> +#define _IOMAPS_H_
> +#include "libcflat.h"
> +
> +struct iomap {
> + const char *type;
> + const char *compats[5];
I would name the field compatible to be more in-line with the
DT-representation, but OK.
it looks from the above like the array must be null terminated?
how about #define IOMAP_MAX_COMPATS 5
and then turn your loop above into:
for (i = 0; i < IOMAP_MAX_COMPATS; i++, m++) {
if (!m->compats[i])
break;
if (strcmp(m->compats[i], compat) == 0)
return m;
}
> + u32 nr;
> + u32 addrs[64];
why are we limiting ourselves to a 32 bit physical address space?
> +};
> +
> +const struct iomap *iomaps_find_type(const char *type);
> +const struct iomap *iomaps_find_compatible(const char *compat);
> +#endif
> diff --git a/scripts/gen-devtree-iomaps.pl b/scripts/gen-devtree-iomaps.pl
> new file mode 100755
> index 0000000000000..b48e85e48ab34
> --- /dev/null
> +++ b/scripts/gen-devtree-iomaps.pl
> @@ -0,0 +1,105 @@
> +#!/usr/bin/perl -w
> +use strict;
> +use File::Temp qw/:POSIX/;
> +
> +my $dts = shift @ARGV;
> +my @types = @ARGV;
> +my $max_nr_addrs = 64;
> +my $max_nr_compats = 4;
> +
> +if (!defined $dts || $#types < 0) {
> + print STDERR "Usage: gen-devtree-iomaps ".
> + "<dts-file|-> <addr-type> [addr-types...]\n";
> + exit 1;
> +}
> +
> +my $dtb = tmpnam();
> +system "dtc -I dts -O dtb $dts -o $dtb";
> +
> +my $g = join '|', map { $_ . '@' } @types;
> +my @devs = grep { /$g/ } `fdtget -l $dtb / 2>/dev/null`;
> +
> +my %iomaps;
> +foreach my $dev (@devs) {
> +
> + chomp($dev);
> + my ($type, $addr) = split /@/, $dev;
> +
> + if (!exists $iomaps{$type}) {
> +
> + my $compatible = `fdtget $dtb /$dev compatible 2>/dev/null`;
> + chomp($compatible);
> + my @compats = split ' ', $compatible;
> +
> + $iomaps{$type}{compats} = \@compats;
> + $iomaps{$type}{addrs} = [$addr];
> + } else {
> + push @{ $iomaps{$type}{addrs} }, $addr;
> + }
> +}
> +unlink $dtb;
> +
> +print <<EOF;
> +/*
> + * Generated file. See gen-devtree-iomaps.pl
> + */
> +#include "iomaps.h"
> +EOF
> +print "\nconst struct iomap iomaps[] = {\n";
> +foreach my $type (keys %iomaps) {
> +
> + my $compats = $iomaps{$type}{compats};
> + my $addrs = $iomaps{$type}{addrs};
> +
> + my $nr_compats = $#{ $compats } + 1;
> + if ($nr_compats > $max_nr_compats) {
> + print STDERR "$type has $nr_compats compats, but iomaps can ".
> + "only support up to $max_nr_compats.\n";
> + splice @{ $compats }, $max_nr_compats;
> + }
> +
> + @{ $addrs } = sort @{ $addrs };
> +
> + my $nr = $#{ $addrs } + 1;
> + if ($nr > $max_nr_addrs) {
> + print STDERR "$type has $nr addrs, but iomaps can ".
> + "only support up to $max_nr_addrs.\n";
> + $nr = $max_nr_addrs;
> + splice @{ $addrs }, $nr;
> + }
> +
> + @{ $addrs } = map { $_ = sprintf '0x%.8x', hex($_) } @{ $addrs };
> +
> + print "{\n";
> + print "\t.type = \"$type\",\n";
> +
> + print "\t.compats = {";
> + foreach my $compat (@{ $compats }) {
> + print " \"$compat\",";
> + }
> + print " NULL, },\n";
> +
> + print "\t.nr = $nr,\n";
> + print "\t.addrs = {";
> + if ($nr < 5) {
> + print ' ';
> + print join ', ', @{ $addrs };
> + print ", },\n";
> + } else {
> + print "\n";
> + for (my $i = 0; $i < $nr; $i += 5) {
> + print "\t\t";
> + my $j = $i;
> + while ($j < $i + 4 && $j < $nr - 1) {
> + print $addrs->[$j] . ", ";
> + ++$j;
> + }
> + print $addrs->[$j] . ",\n";
> + }
> + print "\t},\n";
> + }
> + print "},\n";
> +}
> +print "{\n\t.type = NULL,\n},\n";
> +print "};\n";
> +exit 0;
This script doesn't work on either of the Ubuntu distros I run. The
reasons are that the dumpfdt tool is not processing the multi-compatible
strings output from the dtb correctly and the fdtget utility included
does not yet have the -l option to list subnodes.
I spent a fair amount of time trying to fix this, changing dumpfdt to
'dtc -I dtb -O dts', and I tried it on the newest Ubuntu distro, tried
compiling fdtget from the kernel sources etc. and failed miserably.
I think at the very least we need to check the tools available on the
build machine as part of the configure script or test it a little
broader.
Thanks,
--
Christoffer
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 7/9] Add halt() and some error codes
2013-12-04 16:42 ` [PATCH 7/9] Add halt() and some error codes Andrew Jones
@ 2013-12-29 6:31 ` Christoffer Dall
0 siblings, 0 replies; 44+ messages in thread
From: Christoffer Dall @ 2013-12-29 6:31 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvmarm, kvm
On Wed, Dec 04, 2013 at 05:42:55PM +0100, Andrew Jones wrote:
> Define a halt function that can be implemented by the test framework
> for use on error paths before exit() works. Also add some error codes
> that can be passed to halt() in case the serial isn't working either.
> Then, on register inspection of the halted guest we may be able to
> quickly determine the problem without having to find the halt()
> call-site. The error codes may of course also be used with exit().
Looks good to me.
-Christoffer
>
> Signed-off-by: Andrew Jones <drjones@redhat.com>
>
> ---
> v2:
> - keep the error numbers more consistent with the standard numbers
> ---
> lib/errno.h | 22 ++++++++++++++++++++++
> lib/libcflat.h | 2 ++
> 2 files changed, 24 insertions(+)
> create mode 100644 lib/errno.h
>
> diff --git a/lib/errno.h b/lib/errno.h
> new file mode 100644
> index 0000000000000..f60845cdc61f6
> --- /dev/null
> +++ b/lib/errno.h
> @@ -0,0 +1,22 @@
> +#ifndef _ERRNO_H_
> +#define _ERRNO_H_
> +/*
> + * Define some error codes for the test framework's use. qemu
> + * exits with ((code << 1) | 1) when this framework calls
> + * exit(code), so we reserve codes 64 to 126. 127 is left
> + * for exit(-1).
> + *
> + * (Ab)use the standard E* names for syntax highlighting...
> + * The errno descriptions in [] are for non-standard semantics.
> + */
> +#define EINTR (64 + 4) /* [unhandled exception] */
> +#define EIO (64 + 5) /* I/O error */
> +#define ENXIO (64 + 6) /* No such device or address [no serial] */
> +#define ENOEXEC (64 + 8) /* Exec format error [bad flat file] */
> +#define ENOMEM (64 + 12) /* Out of memory */
> +#define ENODEV (64 + 19) /* No such device */
> +#define EINVAL (64 + 22) /* Invalid argument */
> +#define ENOSPC (64 + 28) /* No space left on device */
> +#define ERANGE (64 + 34) /* Math result not representable
> + [divide by zero] */
> +#endif
> diff --git a/lib/libcflat.h b/lib/libcflat.h
> index 140c172e77d54..a1be635ab4ee9 100644
> --- a/lib/libcflat.h
> +++ b/lib/libcflat.h
> @@ -37,6 +37,7 @@ typedef _Bool bool;
> #define true 1
> #define false 0
>
> +extern void halt(int code);
> extern void exit(int code);
>
> extern unsigned long strlen(const char *buf);
> @@ -57,4 +58,5 @@ extern long atol(const char *ptr);
> #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
>
> #define NULL ((void *)0UL)
> +#include "errno.h"
> #endif
> --
> 1.8.1.4
>
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 8/9] Introduce virtio-testdev
2013-12-04 16:42 ` [PATCH 8/9] Introduce virtio-testdev Andrew Jones
@ 2013-12-29 6:31 ` Christoffer Dall
2014-01-02 16:16 ` Andrew Jones
0 siblings, 1 reply; 44+ messages in thread
From: Christoffer Dall @ 2013-12-29 6:31 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvmarm, kvm
On Wed, Dec 04, 2013 at 05:42:56PM +0100, Andrew Jones wrote:
> virtio-testdev is a communication channel to qemu through virtio that
> can be used by test code to send commands. The only command currently
> implemented is EXIT, which allows the test code to exit with a given
> status code.
>
> Signed-off-by: Andrew Jones <drjones@redhat.com>
>
> ---
> v2:
> - use readl/writel framework (libio) [Christoffer Dall]
> - keep the virtio abstraction in virtio-testdev [Alexander Graf]
> ---
> lib/libcflat.h | 3 ++
> lib/virtio-testdev.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++
> lib/virtio-testdev.h | 9 ++++
> lib/virtio.c | 70 ++++++++++++++++++++++++++
> lib/virtio.h | 74 +++++++++++++++++++++++++++
> 5 files changed, 295 insertions(+)
> create mode 100644 lib/virtio-testdev.c
> create mode 100644 lib/virtio-testdev.h
> create mode 100644 lib/virtio.c
> create mode 100644 lib/virtio.h
>
> diff --git a/lib/libcflat.h b/lib/libcflat.h
> index a1be635ab4ee9..197b703e53b46 100644
> --- a/lib/libcflat.h
> +++ b/lib/libcflat.h
> @@ -56,6 +56,9 @@ extern long atol(const char *ptr);
> #define ARRAY_SIZE(_a) (sizeof(_a)/sizeof((_a)[0]))
>
> #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
> +#define container_of(ptr, type, member) ({ \
> + const typeof( ((type *)0)->member ) *__mptr = (ptr); \
> + (type *)( (char *)__mptr - offsetof(type,member) );})
>
> #define NULL ((void *)0UL)
> #include "errno.h"
> diff --git a/lib/virtio-testdev.c b/lib/virtio-testdev.c
> new file mode 100644
> index 0000000000000..93731a3565b81
> --- /dev/null
> +++ b/lib/virtio-testdev.c
> @@ -0,0 +1,139 @@
> +#include "libcflat.h"
> +#include "virtio.h"
> +
> +#define TESTDEV_MAJOR_VER 1
> +#define TESTDEV_MINOR_VER 1
> +
> +#define VIRTIO_ID_TESTDEV 0xffff
> +
> +#define CONFIG_SIZE 64
> +
> +enum {
> + VERSION = 1,
> + CLEAR,
> + EXIT,
> +};
> +
> +#define TOKEN_OFFSET 0x0
> +#define NARGS_OFFSET 0x4
> +#define NRETS_OFFSET 0x8
> +#define ARG_OFFSET(n) (0xc + (n) * 4)
> +#define __RET_OFFSET(nargs, n) (ARG_OFFSET(nargs) + (n) * 4)
> +
> +static struct virtio_dev *testdev;
> +
> +static u32 testdev_readl(unsigned offset)
> +{
> + if (offset > (CONFIG_SIZE - 4)) {
> + printf("%s: offset 0x%x to big!\n", __func__, offset);
> + exit(EINVAL);
> + }
> +
> + return virtio_config_readl(testdev, offset);
> +}
> +
> +static void testdev_writel(unsigned offset, u32 val)
> +{
> + if (offset > (CONFIG_SIZE - 4)) {
> + printf("%s: offset 0x%x to big!\n", __func__, offset);
> + exit(EINVAL);
> + }
> +
> + virtio_config_writel(testdev, offset, val);
> +}
> +
> +/*
> + * We have to write all args; nargs, nrets, ... first to
> + * avoid executing token's operation until all args are in
the token's ?
> + * place. Then issue the op, and then read the rets. Reading
rets? return values?
> + * the rets (or just sanity checking by reading token) will
> + * read a zero into qemu's copy of the token, which allows us
> + * to prepare additional ops without re-executing the last one.
> + */
> +void virtio_testdev(u32 token, u32 nargs, u32 nrets, ...)
> +{
> + va_list va;
> + unsigned off;
> + u32 n;
> +
> + if (!testdev)
> + return;
> +
> + testdev_writel(NARGS_OFFSET, nargs);
> + testdev_writel(NRETS_OFFSET, nrets);
> +
> + va_start(va, nrets);
> +
> + off = ARG_OFFSET(0);
> + n = nargs;
> + while (n--) {
> + testdev_writel(off, va_arg(va, unsigned));
> + off += 4;
> + }
> +
> + /* this runs the op, but then resets token to zero */
> + testdev_writel(TOKEN_OFFSET, token);
> +
> + /* sanity check */
> + if (testdev_readl(TOKEN_OFFSET) != 0) {
> + printf("virtio-testdev token should always read as zero!\n");
> + halt(EIO);
> + }
> +
> + off = __RET_OFFSET(nargs, 0);
> + n = nrets;
> + while (n--) {
> + u32 *r = va_arg(va, unsigned *);
> + *r = testdev_readl(off);
> + off += 4;
> + }
> +
> + va_end(va);
> +}
> +
> +void virtio_testdev_version(u32 *version)
> +{
> + virtio_testdev(VERSION, 0, 1, version);
> +}
> +
> +void virtio_testdev_clear(void)
> +{
> + virtio_testdev(CLEAR, 0, 0);
> +}
> +
> +void virtio_testdev_exit(int code)
> +{
> + virtio_testdev(EXIT, 1, 0, code);
> +}
> +
> +void virtio_testdev_init(void)
> +{
> + u16 major, minor;
> + u32 version;
> +
> + testdev = virtio_bind(VIRTIO_ID_TESTDEV);
> + if (testdev == NULL) {
> + printf("Can't find virtio-testdev. "
> + "Is '-device virtio-testdev' "
> + "on the qemu command line?\n");
> + halt(ENODEV);
> + }
> +
> + virtio_testdev_version(&version);
> + major = version >> 16;
> + minor = version & 0xffff;
> +
> + if (major != TESTDEV_MAJOR_VER || minor < TESTDEV_MINOR_VER) {
> + char *u = "qemu";
> + if (major > TESTDEV_MAJOR_VER)
> + u = "kvm-unit-tests";
> + printf("Incompatible version of virtio-testdev: major = %d, "
> + "minor = %d\n", major, minor);
> + printf("Update %s.\n", u);
> + exit(ENODEV);
> + }
> +
> + if (minor > TESTDEV_MINOR_VER)
> + printf("testdev has new features. "
> + "An update of kvm-unit-tests may be possible.\n");
> +}
> diff --git a/lib/virtio-testdev.h b/lib/virtio-testdev.h
> new file mode 100644
> index 0000000000000..c10bbfb591d0b
> --- /dev/null
> +++ b/lib/virtio-testdev.h
> @@ -0,0 +1,9 @@
> +#ifndef _VIRTIO_TESTDEV_H_
> +#define _VIRTIO_TESTDEV_H_
> +#include "libcflat.h"
> +
> +extern void virtio_testdev_init(void);
> +extern void virtio_testdev_version(u32 *version);
> +extern void virtio_testdev_clear(void);
> +extern void virtio_testdev_exit(int code);
> +#endif
> diff --git a/lib/virtio.c b/lib/virtio.c
> new file mode 100644
> index 0000000000000..c5ad1c85ff9a1
> --- /dev/null
> +++ b/lib/virtio.c
> @@ -0,0 +1,70 @@
> +#include "libcflat.h"
> +#include "libio.h"
> +#include "iomaps.h"
> +#include "heap.h"
> +#include "virtio.h"
> +
> +#define to_virtio_mmio_dev(vdev) \
> + container_of(vdev, struct virtio_mmio_dev, vdev)
argh, macro pain, can you rename the parameter to _vdev or vdev_ptr or
something like that?
> +
> +static void vm_get(struct virtio_dev *vdev, unsigned offset,
> + void *buf, unsigned len)
> +{
> + struct virtio_mmio_dev *vmdev = to_virtio_mmio_dev(vdev);
> + void *addr = vmdev->base + VIRTIO_MMIO_CONFIG + offset;
> + read_len(addr, buf, len);
> +}
> +
> +static void vm_set(struct virtio_dev *vdev, unsigned offset,
> + const void *buf, unsigned len)
> +{
> + struct virtio_mmio_dev *vmdev = to_virtio_mmio_dev(vdev);
> + void *addr = vmdev->base + VIRTIO_MMIO_CONFIG + offset;
> + write_len(addr, buf, len);
> +}
> +
> +static struct virtio_dev *virtio_mmio_bind(const struct iomap *m, u32 device)
> +{
> + struct virtio_mmio_dev *vmdev;
> + void *page;
> + u32 devid, i;
> +
> + page = alloc_page();
> + vmdev = page;
> + vmdev->vdev.config = page + sizeof(struct virtio_mmio_dev);
> +
> + vmdev->vdev.id.device = device;
> + vmdev->vdev.id.vendor = -1;
> + vmdev->vdev.config->get = vm_get;
> + vmdev->vdev.config->set = vm_set;
> +
> + device &= 0xffff;
what is this mask again? Is this to correspond to the virtio PCI device
ID specs, but then shouldn't we also check the range, seems strange to
me to just ignore upper-bits garbage?
> +
> + for (i = 0; i < m->nr; ++i) {
> + vmdev->base = compat_ptr(m->addrs[i]);
> + devid = readl(vmdev->base + VIRTIO_MMIO_DEVICE_ID);
> + if ((devid & 0xffff) == device)
> + break;
> + }
> +
> + if (i >= m->nr) {
this can just be 'if (i == m->nr)' right?
> + printf("%s: Can't find device 0x%x.\n", __func__, device);
I would ditch the '.'
> + free_page(page);
> + return NULL;
> + }
> +
> + return &vmdev->vdev;
> +}
> +
> +struct virtio_dev *virtio_bind(u32 device)
> +{
> + const struct iomap *m;
> +
> + /* currently we only support virtio-mmio */
> + m = iomaps_find_compatible("virtio,mmio");
> + if (!m) {
> + printf("%s: No virtio-mmio transports found!\n", __func__);
> + return NULL;
> + }
> + return virtio_mmio_bind(m, device);
> +}
> diff --git a/lib/virtio.h b/lib/virtio.h
> new file mode 100644
> index 0000000000000..c30a8dcd105cd
> --- /dev/null
> +++ b/lib/virtio.h
> @@ -0,0 +1,74 @@
> +#ifndef _VIRTIO_H_
> +#define _VIRTIO_H_
> +#include "libcflat.h"
> +
> +#define VIRTIO_MMIO_DEVICE_ID 0x008
> +#define VIRTIO_MMIO_CONFIG 0x100
> +
> +struct virtio_devid {
> + u32 device;
> + u32 vendor;
> +};
> +
> +struct virtio_dev {
> + struct virtio_devid id;
> + struct virtio_conf_ops *config;
> +};
> +
> +struct virtio_conf_ops {
> + void (*get)(struct virtio_dev *vdev, unsigned offset,
> + void *buf, unsigned len);
> + void (*set)(struct virtio_dev *vdev, unsigned offset,
> + const void *buf, unsigned len);
> +};
> +
> +struct virtio_mmio_dev {
> + struct virtio_dev vdev;
> + void *base;
> +};
> +
> +static inline u8
> +virtio_config_readb(struct virtio_dev *vdev, unsigned offset)
> +{
> + u8 val;
> + vdev->config->get(vdev, offset, &val, 1);
> + return val;
> +}
> +
> +static inline u16
> +virtio_config_readw(struct virtio_dev *vdev, unsigned offset)
> +{
> + u16 val;
> + vdev->config->get(vdev, offset, &val, 2);
> + return val;
> +}
> +
> +static inline u32
> +virtio_config_readl(struct virtio_dev *vdev, unsigned offset)
> +{
> + u32 val;
> + vdev->config->get(vdev, offset, &val, 4);
> + return val;
> +}
> +
> +static inline void
> +virtio_config_writeb(struct virtio_dev *vdev, unsigned offset, u8 val)
> +{
> + vdev->config->set(vdev, offset, &val, 1);
> +}
> +
> +static inline void
> +virtio_config_writew(struct virtio_dev *vdev, unsigned offset, u16 val)
> +{
> + vdev->config->set(vdev, offset, &val, 2);
> +}
> +
> +static inline void
> +virtio_config_writel(struct virtio_dev *vdev, unsigned offset, u32 val)
> +{
> + vdev->config->set(vdev, offset, &val, 4);
> +}
> +
> +extern struct virtio_dev *virtio_bind(u32 device);
> +
> +#endif
> --
> 1.8.1.4
>
> _______________________________________________
> kvmarm mailing list
> kvmarm@lists.cs.columbia.edu
> https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
--
Christoffer
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 9/9] arm: initial drop
2013-12-04 16:42 ` [PATCH 9/9] arm: initial drop Andrew Jones
@ 2013-12-29 6:31 ` Christoffer Dall
2013-12-29 9:18 ` Peter Maydell
2014-01-02 16:54 ` Andrew Jones
0 siblings, 2 replies; 44+ messages in thread
From: Christoffer Dall @ 2013-12-29 6:31 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvmarm, kvm
On Wed, Dec 04, 2013 at 05:42:57PM +0100, Andrew Jones wrote:
> This is the initial arm test framework and a first simple test that
> checks some bootinfo. kvm isn't needed to run this test. This patch
> also adds a common build environment variable, $QEMU_BIN, which
> allows makefiles to call on qemu when needed.
>
> Try it out with
> yum install gcc-arm-linux-gnu dtc
> export QEMU=[qemu with mach-virt and virtio-testdev]
> ./configure --cross-prefix=arm-linux-gnu- --arch=arm
> make
> ./run_tests.sh
You refer to QEMU_BIN but your example uses QEMU= ?
It's getting to be a pretty heavy chunk this patch, it would have been
slightly easier to review if it was broken up into multiple patches, but
ok.
>
> Signed-off-by: Andrew Jones <drjones@redhat.com>
>
> ---
> v2:
> - add eabi utility functions needed for some toolchains, this
> allows us to drop the divmod hacks that were in v1
> - switch to kernel coding style
> - some refactoring of setup code for heap init
> - some refactoring of the simple bootinfo test for clarity
> and reuse opportunity
> - update base addr for the new mach-virt version
> ---
> arm/boot.c | 17 +++++++++++
> arm/cstart.S | 38 +++++++++++++++++++++++
> arm/flat.lds | 18 +++++++++++
> arm/run | 19 ++++++++++++
> arm/unittests.cfg | 11 +++++++
> config/config-arm.mak | 73 +++++++++++++++++++++++++++++++++++++++++++
> configure | 10 ++++--
> lib/arm/eabi_compat.c | 20 ++++++++++++
> lib/arm/io.c | 31 +++++++++++++++++++
> lib/arm/io.h | 24 +++++++++++++++
> lib/arm/setup.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++
> lib/arm/sysinfo.h | 19 ++++++++++++
> lib/libcflat.h | 2 ++
> lib/libio.h | 4 +++
> lib/test_util.c | 34 +++++++++++++++++++++
> lib/test_util.h | 13 ++++++++
> 16 files changed, 416 insertions(+), 2 deletions(-)
> create mode 100644 arm/boot.c
> create mode 100644 arm/cstart.S
> create mode 100644 arm/flat.lds
> create mode 100755 arm/run
> create mode 100644 arm/unittests.cfg
> create mode 100644 config/config-arm.mak
> create mode 100644 lib/arm/eabi_compat.c
> create mode 100644 lib/arm/io.c
> create mode 100644 lib/arm/io.h
> create mode 100644 lib/arm/setup.c
> create mode 100644 lib/arm/sysinfo.h
> create mode 100644 lib/test_util.c
> create mode 100644 lib/test_util.h
>
> diff --git a/arm/boot.c b/arm/boot.c
> new file mode 100644
> index 0000000000000..dc42dfc232366
> --- /dev/null
> +++ b/arm/boot.c
> @@ -0,0 +1,17 @@
> +#include "libcflat.h"
> +#include "test_util.h"
> +#include "arm/sysinfo.h"
> +
> +int main(int argc, char **argv)
> +{
> + int ret = FAIL;
> +
> + if (argc >= 1) {
> + --argc;
> + if (!strcmp(argv[0], "mem") && enough_args(argc, 1)) {
> + if (check_u32(mem32.size/1024/1024, 10, argv[1]))
> + ret = PASS;
> + }
> + }
> + return ret;
> +}
consider renaming this file to boottest.c to avoid the confusion that
this file is needed to boot anything that runs tests...
> diff --git a/arm/cstart.S b/arm/cstart.S
> new file mode 100644
> index 0000000000000..05d4bb5becaa0
> --- /dev/null
> +++ b/arm/cstart.S
> @@ -0,0 +1,38 @@
> +
> +#define CR_B (1 << 7) /* Big endian */
> +
> +.arm
> +
> +.section .init
> +
> +.globl start
> +start:
> + /* bootloader params are in r0-r2 */
which bootlaoder params are they? What boot protocol is used, what are
you expecting to be in the various registers?
I assume this tool expects r0-r2 to follow the definitions in
Documentation/arm/Booting in the kernel?
> + ldr sp, =stacktop
> +
> + mrc p15, 0, r8, c1, c0, 0 @r8 = sctrl
that's sctlr, not sctrl.
> + ands r3, r8, #CR_B @set BE, if necessary
> + ldrne r3, =cpu_is_be
> + movne r4, #1
This is deprecated for ARMv7 according to the ARM ARM. What is the
intention here? Does qemu support running this test tool with the
system configured for big-endian? If so, I think this is a build option
for this binary or you need to come up with some other
architecture-compliant method of detecting the endian-state.
> + strne r4, [r3]
> + bl setup @complete setup
> +
> + /* start the test */
> + ldr r0, =__argc
> + ldr r0, [r0]
> + ldr r1, =__argv
> + bl main
> + bl exit
> + b halt
> +
> +.text
> +
> +.globl halt
> +halt:
> +1: wfi
> + b 1b
> +
> +.data
> +
> +.globl cpu_is_be
> +cpu_is_be: .word 0
> diff --git a/arm/flat.lds b/arm/flat.lds
> new file mode 100644
> index 0000000000000..3e5d72e24989b
> --- /dev/null
> +++ b/arm/flat.lds
> @@ -0,0 +1,18 @@
> +
> +SECTIONS
> +{
> + .text : { *(.init) *(.text) *(.text.*) }
> + . = ALIGN(4K);
> + .data : { *(.data) }
> + . = ALIGN(16);
> + .rodata : { *(.rodata) }
> + . = ALIGN(16);
> + .bss : { *(.bss) }
> + . = ALIGN(4K);
> + edata = .;
> + . += 8K;
> + . = ALIGN(4K);
> + stacktop = .;
> +}
> +
> +ENTRY(start)
> diff --git a/arm/run b/arm/run
> new file mode 100755
> index 0000000000000..64446e8907564
> --- /dev/null
> +++ b/arm/run
> @@ -0,0 +1,19 @@
> +#!/bin/bash
> +
> +qemu="${QEMU:-qemu-system-arm}"
> +testdev='virtio-testdev'
> +
> +if ! $qemu -device '?' 2>&1 | grep $testdev > /dev/null; then
> + echo \"$qemu\" has no support for the virtio test device. Exiting.
> + exit 2
> +fi
> +
> +command="$qemu -device $testdev -display none -serial stdio "
> +command+="-M virt -cpu cortex-a15 "
> +#command+="-enable-kvm "
> +command+="-kernel"
> +echo $command "$@"
> +$command "$@"
> +ret=$?
> +echo Return value from qemu: $ret
> +exit $ret
> diff --git a/arm/unittests.cfg b/arm/unittests.cfg
> new file mode 100644
> index 0000000000000..c328657b7944a
> --- /dev/null
> +++ b/arm/unittests.cfg
> @@ -0,0 +1,11 @@
> +# Define your new unittest following the convention:
> +# [unittest_name]
> +# file = foo.flat # Name of the flat file to be used
> +# smp = 2 # Number of processors the VM will use during this test
> +# extra_params = -append <params...> # Additional parameters used
used to QEMU I presume?
> +# arch = arm/arm64 # Only if the test case works only on one of them
Do we have any verified support for arm64 yet?
> +# groups = group1 group2 # Used to identify test cases with run_tests -g ...
> +
> +[boot_info]
> +file = boot.flat
> +extra_params = -m 256 -append 'mem 256'
> diff --git a/config/config-arm.mak b/config/config-arm.mak
> new file mode 100644
> index 0000000000000..d0814186b279c
> --- /dev/null
> +++ b/config/config-arm.mak
> @@ -0,0 +1,73 @@
> +mach = mach-virt
> +iodevs = pl011 virtio_mmio
> +phys_base = 0x40000000
> +
> +cstart.o = $(TEST_DIR)/cstart.o
> +bits = 32
> +ldarch = elf32-littlearm
> +kernel_offset = 0x10000
> +CFLAGS += -D__arm__
> +
> +all: test_cases
> +
> +cflatobjs += \
> + lib/$(TEST_DIR)/iomaps.gen.o \
> + lib/heap.o \
> + lib/iomaps.o \
> + lib/libio.o \
> + lib/virtio.o \
> + lib/virtio-testdev.o \
> + lib/test_util.o \
> + lib/arm/io.o \
> + lib/arm/setup.o
> +
> +libeabi := lib/arm/libeabi.a
> +eabiobjs += \
> + lib/arm/eabi_compat.o
> +
> +$(libcflat) $(libeabi): LDFLAGS += -nostdlib
> +$(libcflat) $(libeabi): CFLAGS += -ffreestanding -I lib
> +
> +CFLAGS += -Wextra
> +CFLAGS += -marm
> +#CFLAGS += -mcpu=$(PROCESSOR)
This looks weird, should it not be $(PROCESSOR) and default to
cortex-a15 if it's not set?
(also note that you can now use -cpu host with mach-virt which may make
your life easier).
> +CFLAGS += -mcpu=cortex-a15
> +CFLAGS += -O2
Why do we choose this particular optimzation-level in the arch-specific
config?
> +
> +libgcc := $(shell $(CC) -m$(ARCH) --print-libgcc-file-name)
> +start_addr := $(shell printf "%x\n" $$(( $(phys_base) + $(kernel_offset) )))
> +
> +FLATLIBS = $(libcflat) $(libgcc) $(libeabi)
> +%.elf: %.o $(FLATLIBS) arm/flat.lds
> + $(CC) $(CFLAGS) -nostdlib -o $@ \
> + -Wl,-T,arm/flat.lds,--build-id=none,-Ttext=$(start_addr) \
> + $(filter %.o, $^) $(FLATLIBS)
I have no idea what the above rules are doing :-(
> +
> +$(libeabi): $(eabiobjs)
> + $(AR) rcs $@ $^
> +
> +%.flat: %.elf
> + $(OBJCOPY) -O binary $^ $@
> +
> +tests-common = $(TEST_DIR)/boot.flat
> +
> +tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg
> +
> +test_cases: $(tests-common) $(tests)
what's the distinction between tests-common and tests? arm/arm64 vs.
one or the other, or?
> +
> +$(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I lib
> +
> +$(TEST_DIR)/boot.elf: $(cstart.o) $(TEST_DIR)/boot.o
> +
> +lib/$(TEST_DIR)/iomaps.gen.c: lib/$(TEST_DIR)/$(mach).dts
> + scripts/gen-devtree-iomaps.pl $^ $(iodevs) > $@
> +
> +lib/$(TEST_DIR)/mach-virt.dts: dtb = $(subst .dts,.dtb,$@)
> +lib/$(TEST_DIR)/mach-virt.dts:
> + $(QEMU_BIN) -kernel /dev/null -M virt -machine dumpdtb=$(dtb)
> + fdtdump $(dtb) > $@
> +
> +arch_clean:
> + $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
> + $(libeabi) $(eabiobjs) $(TEST_DIR)/.*.d lib/arm/.*.d \
> + lib/$(TEST_DIR)/iomaps.gen.c lib/$(TEST_DIR)/mach-virt.*
> diff --git a/configure b/configure
> index 6cfc64943f6e6..296c70182ea1d 100755
> --- a/configure
> +++ b/configure
> @@ -6,8 +6,7 @@ cc=gcc
> ld=ld
> objcopy=objcopy
> ar=ar
> -arch=`uname -m | sed -e s/i.86/i386/`
> -processor="$arch"
> +arch=`uname -m | sed -e s/i.86/i386/ | sed -e 's/arm.*/arm/'`
> cross_prefix=
>
> usage() {
> @@ -17,6 +16,7 @@ usage() {
> Options include:
> --test-dir=DIR the main directory for tests ($arch)
> --arch=ARCH architecture to compile for ($arch)
> + --processor=PROCESSOR processor to compile for ($arch)
> --cross-prefix=PREFIX cross compiler prefix
> --cc=CC c compiler to use ($cc)
> --ld=LD ld linker to use ($ld)
> @@ -66,6 +66,9 @@ while [[ "$1" = -* ]]; do
> ;;
> esac
> done
> +[ -z "$processor" ] && processor="$arch"
> +qemu="${QEMU:-qemu-system-$arch}"
> +
> if [ -z "$testdir" -a \( "$arch" = "i386" -o "$arch" = "x86_64" \) ]; then
> testdir=x86
> elif [ -z "$testdir" ]; then
> @@ -80,6 +83,7 @@ if [ -f $testdir/run ]; then
> fi
>
> # check for dependent 32 bit libraries
> +if [ "$arch" = "i386" -o "$arch" = "x86_64" ]; then
> cat << EOF > lib_test.c
> #include <stdc++.h>
> #include <boost_thread-mt.h>
> @@ -94,6 +98,7 @@ if [ $exit -eq 0 ]; then
> api=true
> fi
> rm -f lib_test.c
> +fi
>
> cat <<EOF > config.mak
> PREFIX=$prefix
> @@ -106,4 +111,5 @@ OBJCOPY=$cross_prefix$objcopy
> AR=$cross_prefix$ar
> API=$api
> TEST_DIR=$testdir
> +QEMU_BIN=$qemu
> EOF
> diff --git a/lib/arm/eabi_compat.c b/lib/arm/eabi_compat.c
> new file mode 100644
> index 0000000000000..76e04f5543ee1
> --- /dev/null
> +++ b/lib/arm/eabi_compat.c
> @@ -0,0 +1,20 @@
> +/*
> + * Adapted from u-boot's arch/arm/lib/eabi_compat.c
> + */
> +#include "libcflat.h"
> +
> +int raise(int signum __unused)
> +{
> + printf("Divide by zero!\n");
> + exit(ERANGE);
> + return 0;
> +}
> +
> +/* Dummy functions to avoid linker complaints */
> +void __aeabi_unwind_cpp_pr0(void)
> +{
> +}
> +
> +void __aeabi_unwind_cpp_pr1(void)
> +{
> +}
> diff --git a/lib/arm/io.c b/lib/arm/io.c
> new file mode 100644
> index 0000000000000..32c896c29450a
> --- /dev/null
> +++ b/lib/arm/io.c
> @@ -0,0 +1,31 @@
> +#include "libcflat.h"
> +#include "libio.h"
> +#include "iomaps.h"
> +#include "virtio-testdev.h"
> +
> +static volatile u8 *uart0_base;
> +
> +void puts(const char *s)
> +{
> + while (*s)
> + *uart0_base = *s++;
> +}
> +
> +void exit(int code)
> +{
> + virtio_testdev_exit(code);
> + halt(code);
> +}
> +
> +void io_init_early(void)
> +{
> + const struct iomap *m = iomaps_find_compatible("arm,pl011");
> + if (!m)
> + halt(ENXIO);
> + uart0_base = (u8 *)compat_ptr(m->addrs[0]);
> +}
is io_init_early going to do something else later on or is it just
early_console_init? If the latter, then name the function as such.
> +
> +void io_init(void)
> +{
> + virtio_testdev_init();
> +}
> diff --git a/lib/arm/io.h b/lib/arm/io.h
> new file mode 100644
> index 0000000000000..f058f7e54d4a7
> --- /dev/null
> +++ b/lib/arm/io.h
> @@ -0,0 +1,24 @@
> +#ifndef _ARM_IO_H_
> +#define _ARM_IO_H_
> +
> +#define cpu_is_be cpu_is_be
huh?
> +extern bool cpu_is_be;
> +
> +#define __bswap16 bswap16
> +static inline u16 bswap16(u16 val)
> +{
> + u16 ret;
> + asm volatile("rev16 %0, %1" : "=r" (ret) : "r" (val));
> + return ret;
> +}
> +
> +#define __bswap32 bswap32
> +static inline u32 bswap32(u32 val)
> +{
> + u32 ret;
> + asm volatile("rev %0, %1" : "=r" (ret) : "r" (val));
> + return ret;
> +}
> +
> +#include "libio.h"
> +#endif
> diff --git a/lib/arm/setup.c b/lib/arm/setup.c
> new file mode 100644
> index 0000000000000..32fa84bd0bb5b
> --- /dev/null
> +++ b/lib/arm/setup.c
> @@ -0,0 +1,85 @@
> +#include "libcflat.h"
> +#include "libio.h"
> +#include "heap.h"
> +#include "arm/sysinfo.h"
> +
> +#define FDT_SIG 0xd00dfeed
> +
> +#define KERNEL_OFFSET 0x00010000
> +#define ATAG_OFFSET 0x00000100
> +
> +#define ATAG_CORE 0x54410001
> +#define ATAG_MEM 0x54410002
> +#define ATAG_CMDLINE 0x54410009
> +
> +extern void start(void);
> +extern unsigned long stacktop;
> +extern char *__args;
> +
> +extern void io_init_early(void);
> +extern void io_init(void);
> +extern void __setup_args(void);
> +
> +u32 mach_type_id;
> +struct tag_core core;
> +struct tag_mem32 mem32;
> +
> +static void read_atags(u32 id, u32 *info)
> +{
> + u32 *p = info;
> +
> + if (!p) {
> + printf("Can't find bootinfo. mach-type = %x\n", id);
> + exit(ENOEXEC);
> + }
> +
> + /*
> + * p[0] count of words for the tag
> + * p[1] tag id
> + * p[2..] tag data
> + */
> + for (; p[0] != 0; p += p[0])
braces, please.
> + switch (p[1]) {
> + case ATAG_CORE:
> + core.flags = p[2];
> + core.pagesize = p[3];
> + core.rootdev = p[4];
> + break;
> + case ATAG_MEM:
> + mem32.size = p[2];
> + mem32.start = p[3];
> + break;
> + case ATAG_CMDLINE:
> + __args = (char *)&p[2];
> + break;
> + }
> +}
> +
> +static void read_bootinfo(u32 id, u32 *info)
> +{
> + u32 *atags = NULL;
> +
> + mach_type_id = id;
> +
> + if (info[0] == be32_to_cpu(FDT_SIG)) {
> + /*
> + * fdt reading is not [yet?] implemented. So calculate
> + * the ATAGS addr to read that instead.
> + */
> + atags = (u32 *)(start - KERNEL_OFFSET + ATAG_OFFSET);
are the atags always supposed to be loaded even for device-tree booting?
I could not find this in any ARM booting documents, and QEMU does seem
to do this, but only for auto-generated device trees, which could just
be a bug in do_cpu_reset?
> + } else if (info[1] == ATAG_CORE)
> + atags = info;
> +
> + read_atags(id, atags);
> +}
> +
> +void setup(u32 arg __unused, u32 id, u32 *info)
> +{
> + io_init_early();
> + read_bootinfo(id, info);
> + __setup_args();
> + heap_init(&stacktop,
> + mem32.size - (ptr_to_compat(&stacktop) - mem32.start),
> + core.pagesize);
> + io_init();
> +}
> diff --git a/lib/arm/sysinfo.h b/lib/arm/sysinfo.h
> new file mode 100644
> index 0000000000000..f3b076e1a34c4
> --- /dev/null
> +++ b/lib/arm/sysinfo.h
> @@ -0,0 +1,19 @@
> +#ifndef _ARM_SYSINFO_H_
> +#define _ARM_SYSINFO_H_
> +#include "libcflat.h"
> +
> +struct tag_core {
> + u32 flags; /* bit 0 = read-only */
> + u32 pagesize;
> + u32 rootdev;
> +};
> +
> +struct tag_mem32 {
> + u32 size;
> + u32 start; /* physical start address */
> +};
> +
> +extern u32 mach_type_id;
> +extern struct tag_core core;
> +extern struct tag_mem32 mem32;
> +#endif
> diff --git a/lib/libcflat.h b/lib/libcflat.h
> index 197b703e53b46..8c6cf1f0735ba 100644
> --- a/lib/libcflat.h
> +++ b/lib/libcflat.h
> @@ -45,6 +45,7 @@ extern char *strcat(char *dest, const char *src);
> extern int strcmp(const char *a, const char *b);
>
> extern int printf(const char *fmt, ...);
> +extern int snprintf(char *buf, int size, const char *fmt, ...);
> extern int vsnprintf(char *buf, int size, const char *fmt, va_list va);
>
> extern void puts(const char *s);
> @@ -60,6 +61,7 @@ extern long atol(const char *ptr);
> const typeof( ((type *)0)->member ) *__mptr = (ptr); \
> (type *)( (char *)__mptr - offsetof(type,member) );})
>
> +#define __unused __attribute__((__unused__))
> #define NULL ((void *)0UL)
> #include "errno.h"
> #endif
> diff --git a/lib/libio.h b/lib/libio.h
> index 210b8d78af43f..5ac1056e7002f 100644
> --- a/lib/libio.h
> +++ b/lib/libio.h
> @@ -6,6 +6,10 @@
> */
> #include "libcflat.h"
>
> +#ifdef __arm__
> +#include "arm/io.h"
> +#endif
> +
> typedef u32 compat_ptr_t;
>
> static inline void *compat_ptr(compat_ptr_t ptr)
> diff --git a/lib/test_util.c b/lib/test_util.c
> new file mode 100644
> index 0000000000000..3de1f74f83455
> --- /dev/null
> +++ b/lib/test_util.c
> @@ -0,0 +1,34 @@
> +#include "libcflat.h"
> +#include "test_util.h"
> +
> +bool enough_args(int nargs, int needed)
> +{
> + if (nargs >= needed)
> + return true;
> +
> + fail("Not enough arguments.\n");
> + return false;
> +}
> +
> +/*
> + * Typically one would compare val == strtoul(expected, endp, base),
> + * but we don't have, nor at this point really need, strtoul, so we
> + * convert val to a string instead. base can only be 10 or 16.
> + */
> +bool check_u32(u32 val, int base, char *expected)
> +{
> + char *fmt = base == 10 ? "%d" : "%x";
> + char val_str[16];
> +
> + snprintf(val_str, 16, fmt, val);
> +
> + if (base == 16)
> + while (*expected == '0' || *expected == 'x')
> + ++expected;
> +
> + if (strcmp(val_str, expected) == 0)
> + return true;
> +
> + fail("expected %s, but have %s\n", expected, val_str);
> + return false;
> +}
> diff --git a/lib/test_util.h b/lib/test_util.h
> new file mode 100644
> index 0000000000000..0e3e6c4a80d51
> --- /dev/null
> +++ b/lib/test_util.h
> @@ -0,0 +1,13 @@
> +#ifndef _TEST_UTIL_H_
> +#define _TEST_UTIL_H_
> +#include "libcflat.h"
> +
> +#define PASS 0
> +#define FAIL 1
> +
> +#define pass(fmt...) printf("PASS: " fmt)
> +#define fail(fmt...) printf("FAIL: " fmt)
> +
> +bool enough_args(int nargs, int needed);
> +bool check_u32(u32 val, int base, char *expected);
> +#endif
> --
> 1.8.1.4
>
I was expecting to see a __raw_... IO accessor definitions for ARM here,
specifically so we avoid the register-writeback versions that are not
supported on ARM.
See arch/arm/include/asm/io.h in the kernel.
--
Christoffer
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 9/9] arm: initial drop
2013-12-29 6:31 ` Christoffer Dall
@ 2013-12-29 9:18 ` Peter Maydell
2014-01-02 16:54 ` Andrew Jones
1 sibling, 0 replies; 44+ messages in thread
From: Peter Maydell @ 2013-12-29 9:18 UTC (permalink / raw)
To: Christoffer Dall; +Cc: Andrew Jones, kvmarm@lists.cs.columbia.edu, kvm-devel
On 29 December 2013 06:31, Christoffer Dall <christoffer.dall@linaro.org> wrote:
> are the atags always supposed to be loaded even for device-tree booting?
> I could not find this in any ARM booting documents, and QEMU does seem
> to do this, but only for auto-generated device trees, which could just
> be a bug in do_cpu_reset?
Heh, yes, that's just a bug in QEMU -- I didn't notice when I added the
support for autogenerated device trees that we were using "is there a
dtb filename?" to trigger whether to write ATAGS info in reset. I'll fix
that at some point soon...
thanks
-- PMM
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 2/9] makefile and run_tests tweaks
2013-12-29 6:30 ` Christoffer Dall
@ 2014-01-02 14:30 ` Andrew Jones
0 siblings, 0 replies; 44+ messages in thread
From: Andrew Jones @ 2014-01-02 14:30 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvmarm, kvm
On Sat, Dec 28, 2013 at 10:30:03PM -0800, Christoffer Dall wrote:
> On Wed, Dec 04, 2013 at 05:42:50PM +0100, Andrew Jones wrote:
>
> This is a really short commit message, for anyone not super-familiar
> with the make system in this toolset, it makes it quite hard to
> understand the change. See some examples below:
>
> > - remove a redundant '-display none'
> > - remove a redundant -g from CFLAGS
> > - remove a useless -I../include/x86 from CFLAGS
>
> why is this include useless?
The directory doesn't exist.
>
> > - remove lib autodep files on make clean
>
> why?
There should be a way to get rid of them. Maybe add a 'realclean'
target? I think that would be overkill though, as 'make clean'
isn't something I expect people to run all that frequently anyway.
>
> >
> > Signed-off-by: Andrew Jones <drjones@redhat.com>
> > ---
> > Makefile | 8 ++++----
> > config-x86-common.mak | 16 +++++++---------
> > run_tests.sh | 2 +-
> > 3 files changed, 12 insertions(+), 14 deletions(-)
> >
> > diff --git a/Makefile b/Makefile
> > index 278791dbbef23..697fc2a766966 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -12,9 +12,9 @@ libgcc := $(shell $(CC) --print-libgcc-file-name)
> >
> > libcflat := lib/libcflat.a
> > cflatobjs := \
> > + lib/argv.o \
> > lib/printf.o \
> > lib/string.o
> > -cflatobjs += lib/argv.o
> >
> > #include architecure specific make rules
> > include config-$(ARCH).mak
> > @@ -25,8 +25,8 @@ include config-$(ARCH).mak
> > cc-option = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null \
> > > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
> >
> > -CFLAGS += -O1
>
> seems like a good idea to compile test code without optimizations, is
> that what you're trying to achieve here? Seems to me this should be a
> separate change or at least motivated in the commit text.
No, I keep the -O1, but it gets moved to an x86 specific file in order
to give each arch their own choice.
>
> > -CFLAGS += $(autodepend-flags) -g -fomit-frame-pointer -Wall
>
> I like removing the redundant -g but wouldn't it be cleaner to set the
> CFLAGS to an empty string in the beginning of the file and then have a
> seprate line for -g where all the CFLAGS are set?
OK, done for v3.
drew
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 3/9] clean root dir of all x86-ness
2013-12-29 6:30 ` Christoffer Dall
@ 2014-01-02 15:00 ` Andrew Jones
2014-01-02 17:16 ` Christoffer Dall
0 siblings, 1 reply; 44+ messages in thread
From: Andrew Jones @ 2014-01-02 15:00 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvmarm, kvm
On Sat, Dec 28, 2013 at 10:30:12PM -0800, Christoffer Dall wrote:
> >
> > clean: arch_clean
> > - $(RM) *.o *.a .*.d lib/.*.d $(libcflat) $(cflatobjs)
> > + $(RM) lib/.*.d $(libcflat) $(cflatobjs)
>
> so above you're referencing */.*.d and */*/.*.d but in make arch_clean
> we're only removing lib/.*.d ?
There are no longer any source files in the root dir, allowing us to
remove the 'rm *.o *.a .*.d' from this top-level makefile. arch_clean
doesn't remove lib/.*.d. It only removes its arch-specific files, e.g.
$(TEST_DIR)/* and lib/$(ARCH)/*.
> >
> > Options include:
> > + --test-dir=DIR the main directory for tests ($arch)
>
> huh? why would you want to specify something different from arch here?
$(TEST_DIR) isn't new with this patch, only the ability to specify it
is. As a separate tidyup patch we could s/r TEST_DIR with ARCH to get
rid of it, but it wouldn't gain us much, and would lose the ability to
have a second testdir for the same arch (for what I don't know - maybe
just for a scratch dir?)
> > +Services supplied by the testdev device:
> > +
> > +serial output: write only, on io port 0xf1
> > +exit process: write only, on io port 0xf4, value used as exit code
> > +ram size: read-only, on io port 0xd1, 4 bytes' size
> > +irq line setting: write only, on io ports 0x2000 - 0x2018, value to set/clear
> > +simple io: read/write, on io port 0xe0, 1/2/4 bytes
> > +
> > +Test device used a char device for actual output
>
> what do you mean by this last sentence?
Don't shoot the file-mover :-) I didn't write it, but it looks like
it's referring to how testdev (as opposed to pc-testdev) works, i.e.
'-device testdev,chardev=testlog -chardev file,id=testlog,path=msr.out'
> > +# As it happens, config.mak is valid shell script code, too :-)
> > +source config.mak
>
> is this a well-established method of doing things or a hack? If the
> latter, sems like something that could quickly come and bite us.
As long as config.mak is only ever a list of 'key=value's, then I
guess we're pretty safe.
> >
> > -Set the environment variable QEMU=/path/to/qemu-system-x86_64 to allow the
> > -internally used x86-run to pick up the right qemu binary.
> > +Set the environment variable QEMU=/path/to/qemu-system-ARCH to allow the
> > +internally used ARCH-run to pick up the right qemu binary.
>
> this message may not make a lot of sense to non kvm-unit-test
> devevelopers, why not say that it allows the user to specify which QEMU
> binary to use?
OK, tweaked it to
Set the environment variable QEMU=/path/to/qemu-system-ARCH to specify
the appropriate qemu binary for ARCH-run.
>
> >
> > EOF
> > }
> >
> > -# As it happens, config.mak is valid shell script code, too :-)
> > -source config.mak
> > -
>
> ah, I see, this hack/method was used before too, still relevant to
> consider if it's a good approach though...
yup, I think it's OK.
> > +
> > +Tests for x86 architecture are run as kernel images for qemu that supports
> > +multiboot format. Tests uses an infrastructure called from the bios code.
> > +The infrastructure initialize the system/cpu's, switch to long-mode and calls
> > +the 'main' function of the individual test. Tests uses a qemu's virtual test
>
> Tests use
fixed
drew
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 4/9] move x86's simple heap management to common code
2013-12-29 6:30 ` Christoffer Dall
@ 2014-01-02 15:17 ` Andrew Jones
2014-01-02 17:17 ` Christoffer Dall
0 siblings, 1 reply; 44+ messages in thread
From: Andrew Jones @ 2014-01-02 15:17 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvmarm, kvm
On Sat, Dec 28, 2013 at 10:30:24PM -0800, Christoffer Dall wrote:
> > +
> > + if (s != (s & ~(pagesize - 1))) {
>
> you're just testing 'if (s & (pagesize -1))' right?
yeah, I'll simplify that.
>
> > + s += pagesize;
> > + s &= ~(pagesize - 1);
> > + p = (void *)s;
> > + }
>
> a one-line comment on this block saying 'page-align start of heap would
> be nice.
added
>
> > +
> > + while (size >= pagesize) {
> > + *(void **)p = free_head;
> > + free_head = p;
> > + p += pagesize;
> > + size -= pagesize;
> > + }
>
> you could also be nice and comment this block of code, saying something
> like "set up linked list of free pages using the pages themselves as the
> data structure" if you should feel so inclined.
added "link free pages"
>
> why are you not trusting start to be page aligned but you are trusting
> size to be? If size is smaller than pagesize then this loop will go
> nuts won't it?
I don't see how. As soon as size is less than pagesize we won't
[re]enter the loop, and thus it can never go negative (big positive).
drew
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 5/9] Introduce libio to common code for io read/write
2013-12-29 6:30 ` Christoffer Dall
@ 2014-01-02 15:47 ` Andrew Jones
2014-01-02 17:19 ` Christoffer Dall
0 siblings, 1 reply; 44+ messages in thread
From: Andrew Jones @ 2014-01-02 15:47 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvmarm, kvm
On Sat, Dec 28, 2013 at 10:30:35PM -0800, Christoffer Dall wrote:
> > diff --git a/lib/libio.c b/lib/libio.c
> > new file mode 100644
> > index 0000000000000..e450e984fefb1
> > --- /dev/null
> > +++ b/lib/libio.c
> > @@ -0,0 +1,67 @@
> > +#include "libcflat.h"
> > +#include "libio.h"
> > +
> > +void read_len(const volatile void *addr, void *buf, unsigned len)
> > +{
> > + unsigned long val;
> > +
> > + switch (len) {
> > + case 1:
> > + val = readb(addr);
> > + break;
> > + case 2:
> > + val = readw(addr);
> > + break;
> > + case 4:
> > + val = readl(addr);
> > + break;
> > +#ifdef CONFIG_64BIT
> > + case 8:
> > + val = readq(addr);
> > + break;
> > +#endif
> > + default:
> > + {
> > + u8 *p = buf;
> > + unsigned i;
> > +
> > + for (i = 0; i < len; ++i)
> > + p[i] = readb(addr + i);
> > + return;
>
> are you taking proper care of endianness in the common case?
Nope, and on second thought I'll change the default to be an error
instead. Something like this doesn't really belong in an io lib.
>
> > + }
> > + }
> > + memcpy(buf, &val, len);
> > +}
> > +
> > +void write_len(volatile void *addr, const void *buf, unsigned len)
> > +{
> > + unsigned long val;
> > +
> > + if (len <= sizeof(unsigned long))
> > + memcpy(&val, buf, len);
>
> Does this work with big-endian for sizes smaller than sizeof(unsigned
> long)?
Dunno. I didn't test it. Looking at Marc's code makes me suspect
is does not though...
>
> Take a look at arch/arm/kvm/mmio.c and see how Marc uses a union to
> solve this issue.
I'll rework this with some shameless theft from Marc.
> > +/*
> > + * Adapted from the Linux kernel's include/asm-generic/io.h and
> > + * arch/arm/include/asm/io.h
> > + */
> > +#include "libcflat.h"
> > +
> > +typedef u32 compat_ptr_t;
>
> How is this going to be used here? The compat ptr stuff in the kernel
> deals with user space pointer iirc, but I'm not an expert on the
> details. Does typedef'ing a pointer to a u32 in generic code work on a
> 64-bit platform?
This is necessary to eliminate compiler warnings when casting 64-bit
pointers to u32s.
>
> > +
> > +static inline void *compat_ptr(compat_ptr_t ptr)
> > +{
> > + return (void *)(unsigned long)ptr;
> > +}
> > +
> > +static inline compat_ptr_t ptr_to_compat(void *ptr)
> > +{
> > + return (u32)(unsigned long)ptr;
> > +}
> > +
> > +#ifndef __raw_readb
> > +static inline u8 __raw_readb(const volatile void *addr)
> > +{
> > + return *(const volatile u8 *)addr;
> > +}
> > +#endif
> > +
> > +#ifndef __raw_readw
> > +static inline u16 __raw_readw(const volatile void *addr)
> > +{
> > + return *(const volatile u16 *)addr;
> > +}
> > +#endif
> > +
> > +#ifndef __raw_readl
> > +static inline u32 __raw_readl(const volatile void *addr)
> > +{
> > + return *(const volatile u32 *)addr;
> > +}
> > +#endif
> > +
> > +#ifdef CONFIG_64BIT
> > +#ifndef __raw_readq
> > +static inline u64 __raw_readq(const volatile void *addr)
> > +{
> > + return *(const volatile u64 *)addr;
> > +}
> > +#endif
> > +#endif
> > +
> > +#ifndef __raw_writeb
> > +static inline void __raw_writeb(u8 b, volatile void *addr)
> > +{
> > + *(volatile u8 *)addr = b;
> > +}
> > +#endif
> > +
> > +#ifndef __raw_writew
> > +static inline void __raw_writew(u16 b, volatile void *addr)
> > +{
> > + *(volatile u16 *)addr = b;
> > +}
> > +#endif
> > +
> > +#ifndef __raw_writel
> > +static inline void __raw_writel(u32 b, volatile void *addr)
> > +{
> > + *(volatile u32 *)addr = b;
> > +}
> > +#endif
> > +
> > +#ifdef CONFIG_64BIT
> > +#ifndef __raw_writeq
> > +static inline void __raw_writeq(u64 b, volatile void *addr)
> > +{
> > + *(volatile u64 *)addr = b;
> > +}
> > +#endif
> > +#endif
> > +
> > +#ifndef __bswap16
> > +static inline u16 __bswap16(u16 x)
> > +{
> > + return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
> > +}
> > +#endif
> > +
> > +#ifndef __bswap32
> > +static inline u32 __bswap32(u32 x)
> > +{
> > + return ((x & 0xff000000) >> 24) | ((x & 0x00ff0000) >> 8) |
> > + ((x & 0x0000ff00) << 8) | ((x & 0x000000ff) << 24);
> > +}
> > +#endif
> > +
> > +#ifdef CONFIG_64BIT
> > +#ifndef __bswap64
> > +static inline u64 __bswap64(u64 x)
> > +{
> > + return ((x & 0x00000000000000ffULL) << 56) |
> > + ((x & 0x000000000000ff00ULL) << 40) |
> > + ((x & 0x0000000000ff0000ULL) << 24) |
> > + ((x & 0x00000000ff000000ULL) << 8) |
> > + ((x & 0x000000ff00000000ULL) >> 8) |
> > + ((x & 0x0000ff0000000000ULL) >> 24) |
> > + ((x & 0x00ff000000000000ULL) >> 40) |
> > + ((x & 0xff00000000000000ULL) >> 56);
> > +}
> > +#endif
> > +#endif
> > +
> > +#ifndef cpu_is_be
> > +#define cpu_is_be 0
> > +#endif
> > +
> > +#define le16_to_cpu(x) \
> > + ({ u16 __r = cpu_is_be ? __bswap16(x) : (x); __r; })
> > +#define cpu_to_le16 le16_to_cpu
> > +
> > +#define le32_to_cpu(x) \
> > + ({ u32 __r = cpu_is_be ? __bswap32(x) : (x); __r; })
> > +#define cpu_to_le32 le32_to_cpu
> > +
> > +#ifdef CONFIG_64BIT
> > +#define le64_to_cpu \
> > + ({ u64 __r = cpu_is_be ? __bswap64(x) : (x); __r; })
> > +#define cpu_to_le64 le64_to_cpu
> > +#endif
> > +
> > +#define be16_to_cpu(x) \
> > + ({ u16 __r = !cpu_is_be ? __bswap16(x) : (x); __r; })
> > +#define cpu_to_be16 be16_to_cpu
> > +
> > +#define be32_to_cpu(x) \
> > + ({ u32 __r = !cpu_is_be ? __bswap32(x) : (x); __r; })
> > +#define cpu_to_be32 be32_to_cpu
> > +
> > +#ifdef CONFIG_64BIT
> > +#define be64_to_cpu \
> > + ({ u64 __r = !cpu_is_be ? __bswap64(x) : (x); __r; })
> > +#define cpu_to_be64 be64_to_cpu
> > +#endif
> > +
> > +#ifndef rmb
> > +#define rmb() do { } while (0)
> > +#endif
> > +#ifndef wmb
> > +#define wmb() do { } while (0)
> > +#endif
> > +
> > +#define readb(addr) \
> > + ({ u8 __r = __raw_readb(addr); rmb(); __r; })
> > +#define readw(addr) \
> > + ({ u16 __r = le16_to_cpu(__raw_readw(addr)); rmb(); __r; })
> > +#define readl(addr) \
> > + ({ u32 __r = le32_to_cpu(__raw_readl(addr)); rmb(); __r; })
> > +#ifdef CONFIG_64BIT
> > +#define readq(addr) \
> > + ({ u64 __r = le64_to_cpu(__raw_readq(addr)); rmb(); __r; })
> > +#endif
> > +
> > +#define writeb(b, addr) \
> > + ({ wmb(); __raw_writeb(b, addr); })
> > +#define writew(b, addr) \
> > + ({ wmb(); __raw_writew(cpu_to_le16(b), addr); })
> > +#define writel(b, addr) \
> > + ({ wmb(); __raw_writel(cpu_to_le32(b), addr); })
> > +#ifdef CONFIG_64BIT
> > +#define writeq(b, addr) \
> > + ({ wmb(); __raw_writeq(cpu_to_le64(b), addr); })
> > +#endif
> > +
> > +extern void read_len(const volatile void *addr, void *buf, unsigned len);
> > +extern void write_len(volatile void *addr, const void *buf, unsigned len);
> > +
> > +#endif
> > --
> > 1.8.1.4
>
> I didn't review all these defines and raw_ functions carefully as I
> assume the individual functions and defines are copied verbatim from the
> kernel?
>
You should take a look, as they're not verbatim - although almost. I can't
recall where I might have diverged, I just know I didn't copy+paste :-)
drew
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 6/9] Introduce a simple iomap structure
2013-12-29 6:30 ` Christoffer Dall
@ 2014-01-02 16:04 ` Andrew Jones
2014-01-02 17:23 ` Christoffer Dall
2014-01-02 17:32 ` Peter Maydell
0 siblings, 2 replies; 44+ messages in thread
From: Andrew Jones @ 2014-01-02 16:04 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvmarm, kvm
On Sat, Dec 28, 2013 at 10:30:54PM -0800, Christoffer Dall wrote:
> > +struct iomap {
> > + const char *type;
> > + const char *compats[5];
>
> I would name the field compatible to be more in-line with the
> DT-representation, but OK.
>
> it looks from the above like the array must be null terminated?
>
> how about #define IOMAP_MAX_COMPATS 5
defines are good.
> and then turn your loop above into:
>
> for (i = 0; i < IOMAP_MAX_COMPATS; i++, m++) {
> if (!m->compats[i])
> break;
Doesn't improve the loop conditions much, IMO.
> if (strcmp(m->compats[i], compat) == 0)
> return m;
> }
>
> > + u32 nr;
> > + u32 addrs[64];
>
> why are we limiting ourselves to a 32 bit physical address space?
I have had this mentally noted from the beginning as something I'll
need to deal with when getting aarch64 going. Anyway, I think a lot
of this is going to change as I teach kvm-unit-tests more and more
about DT.
<snip>
> > +print "{\n\t.type = NULL,\n},\n";
> > +print "};\n";
> > +exit 0;
>
> This script doesn't work on either of the Ubuntu distros I run. The
> reasons are that the dumpfdt tool is not processing the multi-compatible
> strings output from the dtb correctly and the fdtget utility included
> does not yet have the -l option to list subnodes.
>
> I spent a fair amount of time trying to fix this, changing dumpfdt to
> 'dtc -I dtb -O dts', and I tried it on the newest Ubuntu distro, tried
> compiling fdtget from the kernel sources etc. and failed miserably.
>
> I think at the very least we need to check the tools available on the
> build machine as part of the configure script or test it a little
> broader.
>
Drat. I've preferred the idea of using the tools to parse the DT during
the build - avoiding the need for [cross-compiled] libfdt as a dep, but
I guess as we need more and more from the DT, or when particular tests
want to look at the DT itself, and there are already dependency problems,
then it's looking more and more like we should just use libfdt.
drew
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 8/9] Introduce virtio-testdev
2013-12-29 6:31 ` Christoffer Dall
@ 2014-01-02 16:16 ` Andrew Jones
2014-01-02 17:27 ` Christoffer Dall
0 siblings, 1 reply; 44+ messages in thread
From: Andrew Jones @ 2014-01-02 16:16 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvmarm, kvm
On Sat, Dec 28, 2013 at 10:31:17PM -0800, Christoffer Dall wrote:
> > +
> > +/*
> > + * We have to write all args; nargs, nrets, ... first to
> > + * avoid executing token's operation until all args are in
>
> the token's ?
ok
>
> > + * place. Then issue the op, and then read the rets. Reading
>
> rets? return values?
ok
> > +
> > +#define to_virtio_mmio_dev(vdev) \
> > + container_of(vdev, struct virtio_mmio_dev, vdev)
>
> argh, macro pain, can you rename the parameter to _vdev or vdev_ptr or
> something like that?
ok
> > +static struct virtio_dev *virtio_mmio_bind(const struct iomap *m, u32 device)
> > +{
> > + struct virtio_mmio_dev *vmdev;
> > + void *page;
> > + u32 devid, i;
> > +
> > + page = alloc_page();
> > + vmdev = page;
> > + vmdev->vdev.config = page + sizeof(struct virtio_mmio_dev);
> > +
> > + vmdev->vdev.id.device = device;
> > + vmdev->vdev.id.vendor = -1;
> > + vmdev->vdev.config->get = vm_get;
> > + vmdev->vdev.config->set = vm_set;
> > +
> > + device &= 0xffff;
>
> what is this mask again? Is this to correspond to the virtio PCI device
> ID specs, but then shouldn't we also check the range, seems strange to
> me to just ignore upper-bits garbage?
Right, we're ignoring the upper bits to comply with the spec (and to
actually find the device if the upper bits weren't zero). Strangely, at
least to me, struct virtio_device_id in the kernel has device as a u32,
even though the spec has it as a u16. So I allow u32 devices to be put in
the device id, but then throw out the upper bits before searching.
>
> > +
> > + for (i = 0; i < m->nr; ++i) {
> > + vmdev->base = compat_ptr(m->addrs[i]);
> > + devid = readl(vmdev->base + VIRTIO_MMIO_DEVICE_ID);
> > + if ((devid & 0xffff) == device)
> > + break;
> > + }
> > +
> > + if (i >= m->nr) {
>
> this can just be 'if (i == m->nr)' right?
yeah, I just prefer to choose the broader condition when possible.
>
> > + printf("%s: Can't find device 0x%x.\n", __func__, device);
>
> I would ditch the '.'
ditched
drew
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 9/9] arm: initial drop
2013-12-29 6:31 ` Christoffer Dall
2013-12-29 9:18 ` Peter Maydell
@ 2014-01-02 16:54 ` Andrew Jones
2014-01-02 17:40 ` Peter Maydell
2014-01-02 17:44 ` Christoffer Dall
1 sibling, 2 replies; 44+ messages in thread
From: Andrew Jones @ 2014-01-02 16:54 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvmarm, kvm
On Sat, Dec 28, 2013 at 10:31:35PM -0800, Christoffer Dall wrote:
> On Wed, Dec 04, 2013 at 05:42:57PM +0100, Andrew Jones wrote:
> > This is the initial arm test framework and a first simple test that
> > checks some bootinfo. kvm isn't needed to run this test. This patch
> > also adds a common build environment variable, $QEMU_BIN, which
> > allows makefiles to call on qemu when needed.
> >
> > Try it out with
> > yum install gcc-arm-linux-gnu dtc
> > export QEMU=[qemu with mach-virt and virtio-testdev]
> > ./configure --cross-prefix=arm-linux-gnu- --arch=arm
> > make
> > ./run_tests.sh
>
> You refer to QEMU_BIN but your example uses QEMU= ?
Two different vars. QEMU_BIN is an internal makefile var set in
config.mak. QEMU is an ENV. Hmm, I guess I could reuse the QEMU
name in the makefiles too...
<snip>
> > + return ret;
> > +}
>
> consider renaming this file to boottest.c to avoid the confusion that
> this file is needed to boot anything that runs tests...
I think I'll rename it to selftest.c, as it's really just a test
framework selftest.
>
> > diff --git a/arm/cstart.S b/arm/cstart.S
> > new file mode 100644
> > index 0000000000000..05d4bb5becaa0
> > --- /dev/null
> > +++ b/arm/cstart.S
> > @@ -0,0 +1,38 @@
> > +
> > +#define CR_B (1 << 7) /* Big endian */
> > +
> > +.arm
> > +
> > +.section .init
> > +
> > +.globl start
> > +start:
> > + /* bootloader params are in r0-r2 */
>
> which bootlaoder params are they? What boot protocol is used, what are
> you expecting to be in the various registers?
>
> I assume this tool expects r0-r2 to follow the definitions in
> Documentation/arm/Booting in the kernel?
Correct. I guess I can add a 'see Documentation/arm/Booting comment'
>
> > + ldr sp, =stacktop
> > +
> > + mrc p15, 0, r8, c1, c0, 0 @r8 = sctrl
>
> that's sctlr, not sctrl.
fixed
>
> > + ands r3, r8, #CR_B @set BE, if necessary
> > + ldrne r3, =cpu_is_be
> > + movne r4, #1
>
> This is deprecated for ARMv7 according to the ARM ARM. What is the
> intention here? Does qemu support running this test tool with the
> system configured for big-endian? If so, I think this is a build option
> for this binary or you need to come up with some other
> architecture-compliant method of detecting the endian-state.
Yes, qemu allows big-endian. I haven't tested it though, but suspect
someday we will want big-endian guests tested as well. I'll fix the
detection.
> > +++ b/arm/unittests.cfg
> > @@ -0,0 +1,11 @@
> > +# Define your new unittest following the convention:
> > +# [unittest_name]
> > +# file = foo.flat # Name of the flat file to be used
> > +# smp = 2 # Number of processors the VM will use during this test
> > +# extra_params = -append <params...> # Additional parameters used
>
> used to QEMU I presume?
correct
>
> > +# arch = arm/arm64 # Only if the test case works only on one of them
>
> Do we have any verified support for arm64 yet?
not yet, high on my TODO list though.
> > +
> > +CFLAGS += -Wextra
> > +CFLAGS += -marm
> > +#CFLAGS += -mcpu=$(PROCESSOR)
>
> This looks weird, should it not be $(PROCESSOR) and default to
> cortex-a15 if it's not set?
Agreed.
>
> (also note that you can now use -cpu host with mach-virt which may make
> your life easier).
I'll think about how we might/must use '-cpu host'.
>
> > +CFLAGS += -mcpu=cortex-a15
> > +CFLAGS += -O2
>
> Why do we choose this particular optimzation-level in the arch-specific
> config?
My cross-compiler was generating broken code with anything less. I
haven't checked later compilers yet to see if it's fixed or not.
>
> > +
> > +libgcc := $(shell $(CC) -m$(ARCH) --print-libgcc-file-name)
> > +start_addr := $(shell printf "%x\n" $$(( $(phys_base) + $(kernel_offset) )))
> > +
> > +FLATLIBS = $(libcflat) $(libgcc) $(libeabi)
> > +%.elf: %.o $(FLATLIBS) arm/flat.lds
> > + $(CC) $(CFLAGS) -nostdlib -o $@ \
> > + -Wl,-T,arm/flat.lds,--build-id=none,-Ttext=$(start_addr) \
> > + $(filter %.o, $^) $(FLATLIBS)
>
> I have no idea what the above rules are doing :-(
Calls the linker on the *.o files with the supplied linker script, and
a .text addr of $(start_addr). Also gets rid of the build-id section, which
messes up the start address. And supplies libs to link with, which need to
be in a particular order (defined in FLATLIBS).
>
> > +
> > +$(libeabi): $(eabiobjs)
> > + $(AR) rcs $@ $^
> > +
> > +%.flat: %.elf
> > + $(OBJCOPY) -O binary $^ $@
> > +
> > +tests-common = $(TEST_DIR)/boot.flat
> > +
> > +tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg
> > +
> > +test_cases: $(tests-common) $(tests)
>
> what's the distinction between tests-common and tests? arm/arm64 vs.
> one or the other, or?
Correct. Eventually we'll have tests-common, which will be the majority
and apply to both, and also tests which are specific to one.
> > +void io_init_early(void)
> > +{
> > + const struct iomap *m = iomaps_find_compatible("arm,pl011");
> > + if (!m)
> > + halt(ENXIO);
> > + uart0_base = (u8 *)compat_ptr(m->addrs[0]);
> > +}
>
> is io_init_early going to do something else later on or is it just
> early_console_init? If the latter, then name the function as such.
I'll rename for now, as I don't know if it will do something else
yet. I guess we can rename it again if it ever does.
>
> > +
> > +void io_init(void)
> > +{
> > + virtio_testdev_init();
> > +}
> > diff --git a/lib/arm/io.h b/lib/arm/io.h
> > new file mode 100644
> > index 0000000000000..f058f7e54d4a7
> > --- /dev/null
> > +++ b/lib/arm/io.h
> > @@ -0,0 +1,24 @@
> > +#ifndef _ARM_IO_H_
> > +#define _ARM_IO_H_
> > +
> > +#define cpu_is_be cpu_is_be
>
> huh?
>
> > +extern bool cpu_is_be;
See lib/libio.h, it has
#ifndef cpu_is_be
#define cpu_is_be 0
#endif
> > +static void read_atags(u32 id, u32 *info)
> > +{
> > + u32 *p = info;
> > +
> > + if (!p) {
> > + printf("Can't find bootinfo. mach-type = %x\n", id);
> > + exit(ENOEXEC);
> > + }
> > +
> > + /*
> > + * p[0] count of words for the tag
> > + * p[1] tag id
> > + * p[2..] tag data
> > + */
> > + for (; p[0] != 0; p += p[0])
>
> braces, please.
added.
>
> > + switch (p[1]) {
> > + case ATAG_CORE:
> > + core.flags = p[2];
> > + core.pagesize = p[3];
> > + core.rootdev = p[4];
> > + break;
> > + case ATAG_MEM:
> > + mem32.size = p[2];
> > + mem32.start = p[3];
> > + break;
> > + case ATAG_CMDLINE:
> > + __args = (char *)&p[2];
> > + break;
> > + }
> > +}
> > +
> > +static void read_bootinfo(u32 id, u32 *info)
> > +{
> > + u32 *atags = NULL;
> > +
> > + mach_type_id = id;
> > +
> > + if (info[0] == be32_to_cpu(FDT_SIG)) {
> > + /*
> > + * fdt reading is not [yet?] implemented. So calculate
> > + * the ATAGS addr to read that instead.
> > + */
> > + atags = (u32 *)(start - KERNEL_OFFSET + ATAG_OFFSET);
>
> are the atags always supposed to be loaded even for device-tree booting?
> I could not find this in any ARM booting documents, and QEMU does seem
> to do this, but only for auto-generated device trees, which could just
> be a bug in do_cpu_reset?
Looks like Peter confirms I can't rely on this anymore. I guess it's
time to just be one with libfdt.
> > diff --git a/lib/test_util.c b/lib/test_util.c
> > new file mode 100644
> > index 0000000000000..3de1f74f83455
> > --- /dev/null
> > +++ b/lib/test_util.c
> > @@ -0,0 +1,34 @@
> > +#include "libcflat.h"
> > +#include "test_util.h"
> > +
> > +bool enough_args(int nargs, int needed)
> > +{
> > + if (nargs >= needed)
> > + return true;
> > +
> > + fail("Not enough arguments.\n");
> > + return false;
> > +}
> > +
> > +/*
> > + * Typically one would compare val == strtoul(expected, endp, base),
> > + * but we don't have, nor at this point really need, strtoul, so we
> > + * convert val to a string instead. base can only be 10 or 16.
> > + */
> > +bool check_u32(u32 val, int base, char *expected)
> > +{
> > + char *fmt = base == 10 ? "%d" : "%x";
> > + char val_str[16];
> > +
> > + snprintf(val_str, 16, fmt, val);
> > +
> > + if (base == 16)
> > + while (*expected == '0' || *expected == 'x')
> > + ++expected;
> > +
> > + if (strcmp(val_str, expected) == 0)
> > + return true;
> > +
> > + fail("expected %s, but have %s\n", expected, val_str);
> > + return false;
> > +}
> > diff --git a/lib/test_util.h b/lib/test_util.h
> > new file mode 100644
> > index 0000000000000..0e3e6c4a80d51
> > --- /dev/null
> > +++ b/lib/test_util.h
> > @@ -0,0 +1,13 @@
> > +#ifndef _TEST_UTIL_H_
> > +#define _TEST_UTIL_H_
> > +#include "libcflat.h"
> > +
> > +#define PASS 0
> > +#define FAIL 1
> > +
> > +#define pass(fmt...) printf("PASS: " fmt)
> > +#define fail(fmt...) printf("FAIL: " fmt)
> > +
> > +bool enough_args(int nargs, int needed);
> > +bool check_u32(u32 val, int base, char *expected);
> > +#endif
> > --
> > 1.8.1.4
> >
>
> I was expecting to see a __raw_... IO accessor definitions for ARM here,
> specifically so we avoid the register-writeback versions that are not
> supported on ARM.
>
> See arch/arm/include/asm/io.h in the kernel.
k, I'll grab them, but they'll go in lib/arm/io.h. I think I'll drop
these lib/test_util.* in v3, so far they're fairly useless cruft. We
can bring them back if they have enough purpose later.
drew
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 3/9] clean root dir of all x86-ness
2014-01-02 15:00 ` Andrew Jones
@ 2014-01-02 17:16 ` Christoffer Dall
0 siblings, 0 replies; 44+ messages in thread
From: Christoffer Dall @ 2014-01-02 17:16 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvmarm, kvm
On Thu, Jan 02, 2014 at 04:00:17PM +0100, Andrew Jones wrote:
> On Sat, Dec 28, 2013 at 10:30:12PM -0800, Christoffer Dall wrote:
> > >
> > > clean: arch_clean
> > > - $(RM) *.o *.a .*.d lib/.*.d $(libcflat) $(cflatobjs)
> > > + $(RM) lib/.*.d $(libcflat) $(cflatobjs)
> >
> > so above you're referencing */.*.d and */*/.*.d but in make arch_clean
> > we're only removing lib/.*.d ?
>
> There are no longer any source files in the root dir, allowing us to
> remove the 'rm *.o *.a .*.d' from this top-level makefile. arch_clean
> doesn't remove lib/.*.d. It only removes its arch-specific files, e.g.
> $(TEST_DIR)/* and lib/$(ARCH)/*.
>
ah ok.
> > >
> > > Options include:
> > > + --test-dir=DIR the main directory for tests ($arch)
> >
> > huh? why would you want to specify something different from arch here?
>
> $(TEST_DIR) isn't new with this patch, only the ability to specify it
> is. As a separate tidyup patch we could s/r TEST_DIR with ARCH to get
> rid of it, but it wouldn't gain us much, and would lose the ability to
> have a second testdir for the same arch (for what I don't know - maybe
> just for a scratch dir?)
>
hmm, ok, I don't know what the original intention with this patch was
then.
> > > +Services supplied by the testdev device:
> > > +
> > > +serial output: write only, on io port 0xf1
> > > +exit process: write only, on io port 0xf4, value used as exit code
> > > +ram size: read-only, on io port 0xd1, 4 bytes' size
> > > +irq line setting: write only, on io ports 0x2000 - 0x2018, value to set/clear
> > > +simple io: read/write, on io port 0xe0, 1/2/4 bytes
> > > +
> > > +Test device used a char device for actual output
> >
> > what do you mean by this last sentence?
>
> Don't shoot the file-mover :-) I didn't write it, but it looks like
> it's referring to how testdev (as opposed to pc-testdev) works, i.e.
> '-device testdev,chardev=testlog -chardev file,id=testlog,path=msr.out'
>
ok, I'll let you off on that one then :)
> > > +# As it happens, config.mak is valid shell script code, too :-)
> > > +source config.mak
> >
> > is this a well-established method of doing things or a hack? If the
> > latter, sems like something that could quickly come and bite us.
>
> As long as config.mak is only ever a list of 'key=value's, then I
> guess we're pretty safe.
>
> > >
> > > -Set the environment variable QEMU=/path/to/qemu-system-x86_64 to allow the
> > > -internally used x86-run to pick up the right qemu binary.
> > > +Set the environment variable QEMU=/path/to/qemu-system-ARCH to allow the
> > > +internally used ARCH-run to pick up the right qemu binary.
> >
> > this message may not make a lot of sense to non kvm-unit-test
> > devevelopers, why not say that it allows the user to specify which QEMU
> > binary to use?
>
> OK, tweaked it to
> Set the environment variable QEMU=/path/to/qemu-system-ARCH to specify
> the appropriate qemu binary for ARCH-run.
thanks!
>
> >
> > >
> > > EOF
> > > }
> > >
> > > -# As it happens, config.mak is valid shell script code, too :-)
> > > -source config.mak
> > > -
> >
> > ah, I see, this hack/method was used before too, still relevant to
> > consider if it's a good approach though...
>
> yup, I think it's OK.
>
> > > +
> > > +Tests for x86 architecture are run as kernel images for qemu that supports
> > > +multiboot format. Tests uses an infrastructure called from the bios code.
> > > +The infrastructure initialize the system/cpu's, switch to long-mode and calls
> > > +the 'main' function of the individual test. Tests uses a qemu's virtual test
> >
> > Tests use
>
> fixed
>
> drew
--
Christoffer
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 4/9] move x86's simple heap management to common code
2014-01-02 15:17 ` Andrew Jones
@ 2014-01-02 17:17 ` Christoffer Dall
0 siblings, 0 replies; 44+ messages in thread
From: Christoffer Dall @ 2014-01-02 17:17 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvmarm, kvm
On Thu, Jan 02, 2014 at 04:17:08PM +0100, Andrew Jones wrote:
> On Sat, Dec 28, 2013 at 10:30:24PM -0800, Christoffer Dall wrote:
> > > +
> > > + if (s != (s & ~(pagesize - 1))) {
> >
> > you're just testing 'if (s & (pagesize -1))' right?
>
> yeah, I'll simplify that.
>
> >
> > > + s += pagesize;
> > > + s &= ~(pagesize - 1);
> > > + p = (void *)s;
> > > + }
> >
> > a one-line comment on this block saying 'page-align start of heap would
> > be nice.
>
> added
>
> >
> > > +
> > > + while (size >= pagesize) {
> > > + *(void **)p = free_head;
> > > + free_head = p;
> > > + p += pagesize;
> > > + size -= pagesize;
> > > + }
> >
> > you could also be nice and comment this block of code, saying something
> > like "set up linked list of free pages using the pages themselves as the
> > data structure" if you should feel so inclined.
>
> added "link free pages"
>
> >
> > why are you not trusting start to be page aligned but you are trusting
> > size to be? If size is smaller than pagesize then this loop will go
> > nuts won't it?
>
> I don't see how. As soon as size is less than pagesize we won't
> [re]enter the loop, and thus it can never go negative (big positive).
>
yeah you're right. duh.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 5/9] Introduce libio to common code for io read/write
2014-01-02 15:47 ` Andrew Jones
@ 2014-01-02 17:19 ` Christoffer Dall
2014-01-02 18:38 ` Andrew Jones
0 siblings, 1 reply; 44+ messages in thread
From: Christoffer Dall @ 2014-01-02 17:19 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvmarm, kvm
On Thu, Jan 02, 2014 at 04:47:22PM +0100, Andrew Jones wrote:
> On Sat, Dec 28, 2013 at 10:30:35PM -0800, Christoffer Dall wrote:
> > > diff --git a/lib/libio.c b/lib/libio.c
> > > new file mode 100644
> > > index 0000000000000..e450e984fefb1
> > > --- /dev/null
> > > +++ b/lib/libio.c
> > > @@ -0,0 +1,67 @@
> > > +#include "libcflat.h"
> > > +#include "libio.h"
> > > +
> > > +void read_len(const volatile void *addr, void *buf, unsigned len)
> > > +{
> > > + unsigned long val;
> > > +
> > > + switch (len) {
> > > + case 1:
> > > + val = readb(addr);
> > > + break;
> > > + case 2:
> > > + val = readw(addr);
> > > + break;
> > > + case 4:
> > > + val = readl(addr);
> > > + break;
> > > +#ifdef CONFIG_64BIT
> > > + case 8:
> > > + val = readq(addr);
> > > + break;
> > > +#endif
> > > + default:
> > > + {
> > > + u8 *p = buf;
> > > + unsigned i;
> > > +
> > > + for (i = 0; i < len; ++i)
> > > + p[i] = readb(addr + i);
> > > + return;
> >
> > are you taking proper care of endianness in the common case?
>
> Nope, and on second thought I'll change the default to be an error
> instead. Something like this doesn't really belong in an io lib.
>
> >
> > > + }
> > > + }
> > > + memcpy(buf, &val, len);
> > > +}
> > > +
> > > +void write_len(volatile void *addr, const void *buf, unsigned len)
> > > +{
> > > + unsigned long val;
> > > +
> > > + if (len <= sizeof(unsigned long))
> > > + memcpy(&val, buf, len);
> >
> > Does this work with big-endian for sizes smaller than sizeof(unsigned
> > long)?
>
> Dunno. I didn't test it. Looking at Marc's code makes me suspect
> is does not though...
>
> >
> > Take a look at arch/arm/kvm/mmio.c and see how Marc uses a union to
> > solve this issue.
>
> I'll rework this with some shameless theft from Marc.
>
> > > +/*
> > > + * Adapted from the Linux kernel's include/asm-generic/io.h and
> > > + * arch/arm/include/asm/io.h
> > > + */
> > > +#include "libcflat.h"
> > > +
> > > +typedef u32 compat_ptr_t;
> >
> > How is this going to be used here? The compat ptr stuff in the kernel
> > deals with user space pointer iirc, but I'm not an expert on the
> > details. Does typedef'ing a pointer to a u32 in generic code work on a
> > 64-bit platform?
>
> This is necessary to eliminate compiler warnings when casting 64-bit
> pointers to u32s.
>
ah, ok, a comment to that effect would be nice for us neandertals still
mostly stuck in the 32-bit worlds.
> >
> > > +
> > > +static inline void *compat_ptr(compat_ptr_t ptr)
> > > +{
> > > + return (void *)(unsigned long)ptr;
> > > +}
> > > +
> > > +static inline compat_ptr_t ptr_to_compat(void *ptr)
> > > +{
> > > + return (u32)(unsigned long)ptr;
> > > +}
> > > +
> > > +#ifndef __raw_readb
> > > +static inline u8 __raw_readb(const volatile void *addr)
> > > +{
> > > + return *(const volatile u8 *)addr;
> > > +}
> > > +#endif
> > > +
> > > +#ifndef __raw_readw
> > > +static inline u16 __raw_readw(const volatile void *addr)
> > > +{
> > > + return *(const volatile u16 *)addr;
> > > +}
> > > +#endif
> > > +
> > > +#ifndef __raw_readl
> > > +static inline u32 __raw_readl(const volatile void *addr)
> > > +{
> > > + return *(const volatile u32 *)addr;
> > > +}
> > > +#endif
> > > +
> > > +#ifdef CONFIG_64BIT
> > > +#ifndef __raw_readq
> > > +static inline u64 __raw_readq(const volatile void *addr)
> > > +{
> > > + return *(const volatile u64 *)addr;
> > > +}
> > > +#endif
> > > +#endif
> > > +
> > > +#ifndef __raw_writeb
> > > +static inline void __raw_writeb(u8 b, volatile void *addr)
> > > +{
> > > + *(volatile u8 *)addr = b;
> > > +}
> > > +#endif
> > > +
> > > +#ifndef __raw_writew
> > > +static inline void __raw_writew(u16 b, volatile void *addr)
> > > +{
> > > + *(volatile u16 *)addr = b;
> > > +}
> > > +#endif
> > > +
> > > +#ifndef __raw_writel
> > > +static inline void __raw_writel(u32 b, volatile void *addr)
> > > +{
> > > + *(volatile u32 *)addr = b;
> > > +}
> > > +#endif
> > > +
> > > +#ifdef CONFIG_64BIT
> > > +#ifndef __raw_writeq
> > > +static inline void __raw_writeq(u64 b, volatile void *addr)
> > > +{
> > > + *(volatile u64 *)addr = b;
> > > +}
> > > +#endif
> > > +#endif
> > > +
> > > +#ifndef __bswap16
> > > +static inline u16 __bswap16(u16 x)
> > > +{
> > > + return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
> > > +}
> > > +#endif
> > > +
> > > +#ifndef __bswap32
> > > +static inline u32 __bswap32(u32 x)
> > > +{
> > > + return ((x & 0xff000000) >> 24) | ((x & 0x00ff0000) >> 8) |
> > > + ((x & 0x0000ff00) << 8) | ((x & 0x000000ff) << 24);
> > > +}
> > > +#endif
> > > +
> > > +#ifdef CONFIG_64BIT
> > > +#ifndef __bswap64
> > > +static inline u64 __bswap64(u64 x)
> > > +{
> > > + return ((x & 0x00000000000000ffULL) << 56) |
> > > + ((x & 0x000000000000ff00ULL) << 40) |
> > > + ((x & 0x0000000000ff0000ULL) << 24) |
> > > + ((x & 0x00000000ff000000ULL) << 8) |
> > > + ((x & 0x000000ff00000000ULL) >> 8) |
> > > + ((x & 0x0000ff0000000000ULL) >> 24) |
> > > + ((x & 0x00ff000000000000ULL) >> 40) |
> > > + ((x & 0xff00000000000000ULL) >> 56);
> > > +}
> > > +#endif
> > > +#endif
> > > +
> > > +#ifndef cpu_is_be
> > > +#define cpu_is_be 0
> > > +#endif
> > > +
> > > +#define le16_to_cpu(x) \
> > > + ({ u16 __r = cpu_is_be ? __bswap16(x) : (x); __r; })
> > > +#define cpu_to_le16 le16_to_cpu
> > > +
> > > +#define le32_to_cpu(x) \
> > > + ({ u32 __r = cpu_is_be ? __bswap32(x) : (x); __r; })
> > > +#define cpu_to_le32 le32_to_cpu
> > > +
> > > +#ifdef CONFIG_64BIT
> > > +#define le64_to_cpu \
> > > + ({ u64 __r = cpu_is_be ? __bswap64(x) : (x); __r; })
> > > +#define cpu_to_le64 le64_to_cpu
> > > +#endif
> > > +
> > > +#define be16_to_cpu(x) \
> > > + ({ u16 __r = !cpu_is_be ? __bswap16(x) : (x); __r; })
> > > +#define cpu_to_be16 be16_to_cpu
> > > +
> > > +#define be32_to_cpu(x) \
> > > + ({ u32 __r = !cpu_is_be ? __bswap32(x) : (x); __r; })
> > > +#define cpu_to_be32 be32_to_cpu
> > > +
> > > +#ifdef CONFIG_64BIT
> > > +#define be64_to_cpu \
> > > + ({ u64 __r = !cpu_is_be ? __bswap64(x) : (x); __r; })
> > > +#define cpu_to_be64 be64_to_cpu
> > > +#endif
> > > +
> > > +#ifndef rmb
> > > +#define rmb() do { } while (0)
> > > +#endif
> > > +#ifndef wmb
> > > +#define wmb() do { } while (0)
> > > +#endif
> > > +
> > > +#define readb(addr) \
> > > + ({ u8 __r = __raw_readb(addr); rmb(); __r; })
> > > +#define readw(addr) \
> > > + ({ u16 __r = le16_to_cpu(__raw_readw(addr)); rmb(); __r; })
> > > +#define readl(addr) \
> > > + ({ u32 __r = le32_to_cpu(__raw_readl(addr)); rmb(); __r; })
> > > +#ifdef CONFIG_64BIT
> > > +#define readq(addr) \
> > > + ({ u64 __r = le64_to_cpu(__raw_readq(addr)); rmb(); __r; })
> > > +#endif
> > > +
> > > +#define writeb(b, addr) \
> > > + ({ wmb(); __raw_writeb(b, addr); })
> > > +#define writew(b, addr) \
> > > + ({ wmb(); __raw_writew(cpu_to_le16(b), addr); })
> > > +#define writel(b, addr) \
> > > + ({ wmb(); __raw_writel(cpu_to_le32(b), addr); })
> > > +#ifdef CONFIG_64BIT
> > > +#define writeq(b, addr) \
> > > + ({ wmb(); __raw_writeq(cpu_to_le64(b), addr); })
> > > +#endif
> > > +
> > > +extern void read_len(const volatile void *addr, void *buf, unsigned len);
> > > +extern void write_len(volatile void *addr, const void *buf, unsigned len);
> > > +
> > > +#endif
> > > --
> > > 1.8.1.4
> >
> > I didn't review all these defines and raw_ functions carefully as I
> > assume the individual functions and defines are copied verbatim from the
> > kernel?
> >
>
> You should take a look, as they're not verbatim - although almost. I can't
> recall where I might have diverged, I just know I didn't copy+paste :-)
>
Wonderful, I'll take a look :)
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 6/9] Introduce a simple iomap structure
2014-01-02 16:04 ` Andrew Jones
@ 2014-01-02 17:23 ` Christoffer Dall
2014-01-02 18:40 ` Andrew Jones
2014-01-02 17:32 ` Peter Maydell
1 sibling, 1 reply; 44+ messages in thread
From: Christoffer Dall @ 2014-01-02 17:23 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvmarm, kvm
On Thu, Jan 02, 2014 at 05:04:48PM +0100, Andrew Jones wrote:
> On Sat, Dec 28, 2013 at 10:30:54PM -0800, Christoffer Dall wrote:
> > > +struct iomap {
> > > + const char *type;
> > > + const char *compats[5];
> >
> > I would name the field compatible to be more in-line with the
> > DT-representation, but OK.
> >
> > it looks from the above like the array must be null terminated?
> >
> > how about #define IOMAP_MAX_COMPATS 5
>
> defines are good.
>
> > and then turn your loop above into:
> >
> > for (i = 0; i < IOMAP_MAX_COMPATS; i++, m++) {
> > if (!m->compats[i])
> > break;
>
> Doesn't improve the loop conditions much, IMO.
>
I think it's much simpler to read a for loop of the typical form of
until "i < CONSTANT"; what you had before was a data structure with an
assumption of null-termination that could only be realized by looking at
the code that deals with it.
> > if (strcmp(m->compats[i], compat) == 0)
> > return m;
> > }
> >
> > > + u32 nr;
> > > + u32 addrs[64];
> >
> > why are we limiting ourselves to a 32 bit physical address space?
>
> I have had this mentally noted from the beginning as something I'll
> need to deal with when getting aarch64 going. Anyway, I think a lot
> of this is going to change as I teach kvm-unit-tests more and more
> about DT.
Shouldn't be a big change to just support u64 in your iomap instead.
>
> <snip>
> > > +print "{\n\t.type = NULL,\n},\n";
> > > +print "};\n";
> > > +exit 0;
> >
> > This script doesn't work on either of the Ubuntu distros I run. The
> > reasons are that the dumpfdt tool is not processing the multi-compatible
> > strings output from the dtb correctly and the fdtget utility included
> > does not yet have the -l option to list subnodes.
> >
> > I spent a fair amount of time trying to fix this, changing dumpfdt to
> > 'dtc -I dtb -O dts', and I tried it on the newest Ubuntu distro, tried
> > compiling fdtget from the kernel sources etc. and failed miserably.
> >
> > I think at the very least we need to check the tools available on the
> > build machine as part of the configure script or test it a little
> > broader.
> >
>
> Drat. I've preferred the idea of using the tools to parse the DT during
> the build - avoiding the need for [cross-compiled] libfdt as a dep, but
> I guess as we need more and more from the DT, or when particular tests
> want to look at the DT itself, and there are already dependency problems,
> then it's looking more and more like we should just use libfdt.
>
Yes, after working with this for a while that's the same conclusion I
came to. From the ARM perspective, anything running in a VM will be
device-tree driven (this is not the time for anybody to say anything
about ACPI), so we could just feed the VM the device tree directly if we
support libfdt in the guest and avoid another point of failure. I can
try to find some time to help you hack that up if you want.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 8/9] Introduce virtio-testdev
2014-01-02 16:16 ` Andrew Jones
@ 2014-01-02 17:27 ` Christoffer Dall
2014-01-02 18:41 ` Andrew Jones
0 siblings, 1 reply; 44+ messages in thread
From: Christoffer Dall @ 2014-01-02 17:27 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvmarm, kvm
On Thu, Jan 02, 2014 at 05:16:56PM +0100, Andrew Jones wrote:
> On Sat, Dec 28, 2013 at 10:31:17PM -0800, Christoffer Dall wrote:
> > > +
> > > +/*
> > > + * We have to write all args; nargs, nrets, ... first to
> > > + * avoid executing token's operation until all args are in
> >
> > the token's ?
>
> ok
>
> >
> > > + * place. Then issue the op, and then read the rets. Reading
> >
> > rets? return values?
>
> ok
>
> > > +
> > > +#define to_virtio_mmio_dev(vdev) \
> > > + container_of(vdev, struct virtio_mmio_dev, vdev)
> >
> > argh, macro pain, can you rename the parameter to _vdev or vdev_ptr or
> > something like that?
>
> ok
>
> > > +static struct virtio_dev *virtio_mmio_bind(const struct iomap *m, u32 device)
> > > +{
> > > + struct virtio_mmio_dev *vmdev;
> > > + void *page;
> > > + u32 devid, i;
> > > +
> > > + page = alloc_page();
> > > + vmdev = page;
> > > + vmdev->vdev.config = page + sizeof(struct virtio_mmio_dev);
> > > +
> > > + vmdev->vdev.id.device = device;
> > > + vmdev->vdev.id.vendor = -1;
> > > + vmdev->vdev.config->get = vm_get;
> > > + vmdev->vdev.config->set = vm_set;
> > > +
> > > + device &= 0xffff;
> >
> > what is this mask again? Is this to correspond to the virtio PCI device
> > ID specs, but then shouldn't we also check the range, seems strange to
> > me to just ignore upper-bits garbage?
>
> Right, we're ignoring the upper bits to comply with the spec (and to
> actually find the device if the upper bits weren't zero). Strangely, at
> least to me, struct virtio_device_id in the kernel has device as a u32,
> even though the spec has it as a u16. So I allow u32 devices to be put in
> the device id, but then throw out the upper bits before searching.
>
Can you use a define for this mask instead then?
> >
> > > +
> > > + for (i = 0; i < m->nr; ++i) {
> > > + vmdev->base = compat_ptr(m->addrs[i]);
> > > + devid = readl(vmdev->base + VIRTIO_MMIO_DEVICE_ID);
> > > + if ((devid & 0xffff) == device)
> > > + break;
> > > + }
> > > +
> > > + if (i >= m->nr) {
> >
> > this can just be 'if (i == m->nr)' right?
>
> yeah, I just prefer to choose the broader condition when possible.
>
hmmm.
> >
> > > + printf("%s: Can't find device 0x%x.\n", __func__, device);
> >
> > I would ditch the '.'
>
> ditched
>
Thanks,
-Christoffer
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 6/9] Introduce a simple iomap structure
2014-01-02 16:04 ` Andrew Jones
2014-01-02 17:23 ` Christoffer Dall
@ 2014-01-02 17:32 ` Peter Maydell
1 sibling, 0 replies; 44+ messages in thread
From: Peter Maydell @ 2014-01-02 17:32 UTC (permalink / raw)
To: Andrew Jones; +Cc: Christoffer Dall, kvmarm@lists.cs.columbia.edu, kvm-devel
On 2 January 2014 16:04, Andrew Jones <drjones@redhat.com> wrote:
> Drat. I've preferred the idea of using the tools to parse the DT during
> the build - avoiding the need for [cross-compiled] libfdt as a dep, but
> I guess as we need more and more from the DT, or when particular tests
> want to look at the DT itself, and there are already dependency problems,
> then it's looking more and more like we should just use libfdt.
You can just have a local copy of the libfdt sources and compile
them in -- libfdt is written to support that (since you need to use
it that way for bootloaders and the like), and QEMU does that
as a fallback if there's no system libfdt. So you don't necessarily
need to require a cross-libfdt to be provided externally.
thanks
-- PMM
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 9/9] arm: initial drop
2014-01-02 16:54 ` Andrew Jones
@ 2014-01-02 17:40 ` Peter Maydell
2014-01-02 18:09 ` Christoffer Dall
2014-01-02 17:44 ` Christoffer Dall
1 sibling, 1 reply; 44+ messages in thread
From: Peter Maydell @ 2014-01-02 17:40 UTC (permalink / raw)
To: Andrew Jones; +Cc: Christoffer Dall, kvmarm@lists.cs.columbia.edu, kvm-devel
On 2 January 2014 16:54, Andrew Jones <drjones@redhat.com> wrote:
> On Sat, Dec 28, 2013 at 10:31:35PM -0800, Christoffer Dall wrote:
>> On Wed, Dec 04, 2013 at 05:42:57PM +0100, Andrew Jones wrote:
>> > + ands r3, r8, #CR_B @set BE, if necessary
>> > + ldrne r3, =cpu_is_be
>> > + movne r4, #1
>>
>> This is deprecated for ARMv7 according to the ARM ARM. What is the
>> intention here? Does qemu support running this test tool with the
>> system configured for big-endian? If so, I think this is a build option
>> for this binary or you need to come up with some other
>> architecture-compliant method of detecting the endian-state.
>
> Yes, qemu allows big-endian. I haven't tested it though, but suspect
> someday we will want big-endian guests tested as well. I'll fix the
> detection.
QEMU does not support system mode big-endian. (Some of the
pieces are there for it but we have no board that needs it.)
Also, you should read up in the ARM ARM about the differences
between old style BE32 and new BE8. (The quick summary is here:
http://translatedcode.wordpress.com/2012/04/)
What you're trying to do here is enable old-style BE32. This is
not supported on any ARMv7 or later CPU, which means it does
not overlap at all with virtualization support.
We probably do care about BE8 big-endian guest support testing.
(kvmtool can run guests in this mode; QEMU doesn't currently).
thanks
-- PMM
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 9/9] arm: initial drop
2014-01-02 16:54 ` Andrew Jones
2014-01-02 17:40 ` Peter Maydell
@ 2014-01-02 17:44 ` Christoffer Dall
2014-01-02 18:50 ` Andrew Jones
1 sibling, 1 reply; 44+ messages in thread
From: Christoffer Dall @ 2014-01-02 17:44 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvmarm, kvm
On Thu, Jan 02, 2014 at 05:54:25PM +0100, Andrew Jones wrote:
> On Sat, Dec 28, 2013 at 10:31:35PM -0800, Christoffer Dall wrote:
> > On Wed, Dec 04, 2013 at 05:42:57PM +0100, Andrew Jones wrote:
> > > This is the initial arm test framework and a first simple test that
> > > checks some bootinfo. kvm isn't needed to run this test. This patch
> > > also adds a common build environment variable, $QEMU_BIN, which
> > > allows makefiles to call on qemu when needed.
> > >
> > > Try it out with
> > > yum install gcc-arm-linux-gnu dtc
> > > export QEMU=[qemu with mach-virt and virtio-testdev]
> > > ./configure --cross-prefix=arm-linux-gnu- --arch=arm
> > > make
> > > ./run_tests.sh
> >
> > You refer to QEMU_BIN but your example uses QEMU= ?
>
> Two different vars. QEMU_BIN is an internal makefile var set in
> config.mak. QEMU is an ENV. Hmm, I guess I could reuse the QEMU
> name in the makefiles too...
>
> <snip>
> > > + return ret;
> > > +}
> >
> > consider renaming this file to boottest.c to avoid the confusion that
> > this file is needed to boot anything that runs tests...
>
> I think I'll rename it to selftest.c, as it's really just a test
> framework selftest.
>
> >
> > > diff --git a/arm/cstart.S b/arm/cstart.S
> > > new file mode 100644
> > > index 0000000000000..05d4bb5becaa0
> > > --- /dev/null
> > > +++ b/arm/cstart.S
> > > @@ -0,0 +1,38 @@
> > > +
> > > +#define CR_B (1 << 7) /* Big endian */
> > > +
> > > +.arm
> > > +
> > > +.section .init
> > > +
> > > +.globl start
> > > +start:
> > > + /* bootloader params are in r0-r2 */
> >
> > which bootlaoder params are they? What boot protocol is used, what are
> > you expecting to be in the various registers?
> >
> > I assume this tool expects r0-r2 to follow the definitions in
> > Documentation/arm/Booting in the kernel?
>
> Correct. I guess I can add a 'see Documentation/arm/Booting comment'
>
> >
> > > + ldr sp, =stacktop
> > > +
> > > + mrc p15, 0, r8, c1, c0, 0 @r8 = sctrl
> >
> > that's sctlr, not sctrl.
>
> fixed
>
> >
> > > + ands r3, r8, #CR_B @set BE, if necessary
> > > + ldrne r3, =cpu_is_be
> > > + movne r4, #1
> >
> > This is deprecated for ARMv7 according to the ARM ARM. What is the
> > intention here? Does qemu support running this test tool with the
> > system configured for big-endian? If so, I think this is a build option
> > for this binary or you need to come up with some other
> > architecture-compliant method of detecting the endian-state.
>
> Yes, qemu allows big-endian. I haven't tested it though, but suspect
> someday we will want big-endian guests tested as well. I'll fix the
> detection.
>
> > > +++ b/arm/unittests.cfg
> > > @@ -0,0 +1,11 @@
> > > +# Define your new unittest following the convention:
> > > +# [unittest_name]
> > > +# file = foo.flat # Name of the flat file to be used
> > > +# smp = 2 # Number of processors the VM will use during this test
> > > +# extra_params = -append <params...> # Additional parameters used
> >
> > used to QEMU I presume?
>
> correct
>
> >
> > > +# arch = arm/arm64 # Only if the test case works only on one of them
> >
> > Do we have any verified support for arm64 yet?
>
> not yet, high on my TODO list though.
>
> > > +
> > > +CFLAGS += -Wextra
> > > +CFLAGS += -marm
> > > +#CFLAGS += -mcpu=$(PROCESSOR)
> >
> > This looks weird, should it not be $(PROCESSOR) and default to
> > cortex-a15 if it's not set?
>
> Agreed.
>
> >
> > (also note that you can now use -cpu host with mach-virt which may make
> > your life easier).
>
> I'll think about how we might/must use '-cpu host'.
>
> >
> > > +CFLAGS += -mcpu=cortex-a15
> > > +CFLAGS += -O2
> >
> > Why do we choose this particular optimzation-level in the arch-specific
> > config?
>
> My cross-compiler was generating broken code with anything less. I
> haven't checked later compilers yet to see if it's fixed or not.
>
which GCC version?
> >
> > > +
> > > +libgcc := $(shell $(CC) -m$(ARCH) --print-libgcc-file-name)
> > > +start_addr := $(shell printf "%x\n" $$(( $(phys_base) + $(kernel_offset) )))
> > > +
> > > +FLATLIBS = $(libcflat) $(libgcc) $(libeabi)
> > > +%.elf: %.o $(FLATLIBS) arm/flat.lds
> > > + $(CC) $(CFLAGS) -nostdlib -o $@ \
> > > + -Wl,-T,arm/flat.lds,--build-id=none,-Ttext=$(start_addr) \
> > > + $(filter %.o, $^) $(FLATLIBS)
> >
> > I have no idea what the above rules are doing :-(
>
> Calls the linker on the *.o files with the supplied linker script, and
> a .text addr of $(start_addr). Also gets rid of the build-id section, which
> messes up the start address. And supplies libs to link with, which need to
> be in a particular order (defined in FLATLIBS).
>
thanks.
> >
> > > +
> > > +$(libeabi): $(eabiobjs)
> > > + $(AR) rcs $@ $^
> > > +
> > > +%.flat: %.elf
> > > + $(OBJCOPY) -O binary $^ $@
> > > +
> > > +tests-common = $(TEST_DIR)/boot.flat
> > > +
> > > +tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg
> > > +
> > > +test_cases: $(tests-common) $(tests)
> >
> > what's the distinction between tests-common and tests? arm/arm64 vs.
> > one or the other, or?
>
> Correct. Eventually we'll have tests-common, which will be the majority
> and apply to both, and also tests which are specific to one.
>
> > > +void io_init_early(void)
> > > +{
> > > + const struct iomap *m = iomaps_find_compatible("arm,pl011");
> > > + if (!m)
> > > + halt(ENXIO);
> > > + uart0_base = (u8 *)compat_ptr(m->addrs[0]);
> > > +}
> >
> > is io_init_early going to do something else later on or is it just
> > early_console_init? If the latter, then name the function as such.
>
> I'll rename for now, as I don't know if it will do something else
> yet. I guess we can rename it again if it ever does.
>
> >
> > > +
> > > +void io_init(void)
> > > +{
> > > + virtio_testdev_init();
> > > +}
> > > diff --git a/lib/arm/io.h b/lib/arm/io.h
> > > new file mode 100644
> > > index 0000000000000..f058f7e54d4a7
> > > --- /dev/null
> > > +++ b/lib/arm/io.h
> > > @@ -0,0 +1,24 @@
> > > +#ifndef _ARM_IO_H_
> > > +#define _ARM_IO_H_
> > > +
> > > +#define cpu_is_be cpu_is_be
> >
> > huh?
> >
> > > +extern bool cpu_is_be;
>
> See lib/libio.h, it has
>
> #ifndef cpu_is_be
> #define cpu_is_be 0
> #endif
>
ah, yuck.
> > > +static void read_atags(u32 id, u32 *info)
> > > +{
> > > + u32 *p = info;
> > > +
> > > + if (!p) {
> > > + printf("Can't find bootinfo. mach-type = %x\n", id);
> > > + exit(ENOEXEC);
> > > + }
> > > +
> > > + /*
> > > + * p[0] count of words for the tag
> > > + * p[1] tag id
> > > + * p[2..] tag data
> > > + */
> > > + for (; p[0] != 0; p += p[0])
> >
> > braces, please.
>
> added.
>
> >
> > > + switch (p[1]) {
> > > + case ATAG_CORE:
> > > + core.flags = p[2];
> > > + core.pagesize = p[3];
> > > + core.rootdev = p[4];
> > > + break;
> > > + case ATAG_MEM:
> > > + mem32.size = p[2];
> > > + mem32.start = p[3];
> > > + break;
> > > + case ATAG_CMDLINE:
> > > + __args = (char *)&p[2];
> > > + break;
> > > + }
> > > +}
> > > +
> > > +static void read_bootinfo(u32 id, u32 *info)
> > > +{
> > > + u32 *atags = NULL;
> > > +
> > > + mach_type_id = id;
> > > +
> > > + if (info[0] == be32_to_cpu(FDT_SIG)) {
> > > + /*
> > > + * fdt reading is not [yet?] implemented. So calculate
> > > + * the ATAGS addr to read that instead.
> > > + */
> > > + atags = (u32 *)(start - KERNEL_OFFSET + ATAG_OFFSET);
> >
> > are the atags always supposed to be loaded even for device-tree booting?
> > I could not find this in any ARM booting documents, and QEMU does seem
> > to do this, but only for auto-generated device trees, which could just
> > be a bug in do_cpu_reset?
>
> Looks like Peter confirms I can't rely on this anymore. I guess it's
> time to just be one with libfdt.
>
> > > diff --git a/lib/test_util.c b/lib/test_util.c
> > > new file mode 100644
> > > index 0000000000000..3de1f74f83455
> > > --- /dev/null
> > > +++ b/lib/test_util.c
> > > @@ -0,0 +1,34 @@
> > > +#include "libcflat.h"
> > > +#include "test_util.h"
> > > +
> > > +bool enough_args(int nargs, int needed)
> > > +{
> > > + if (nargs >= needed)
> > > + return true;
> > > +
> > > + fail("Not enough arguments.\n");
> > > + return false;
> > > +}
> > > +
> > > +/*
> > > + * Typically one would compare val == strtoul(expected, endp, base),
> > > + * but we don't have, nor at this point really need, strtoul, so we
> > > + * convert val to a string instead. base can only be 10 or 16.
> > > + */
> > > +bool check_u32(u32 val, int base, char *expected)
> > > +{
> > > + char *fmt = base == 10 ? "%d" : "%x";
> > > + char val_str[16];
> > > +
> > > + snprintf(val_str, 16, fmt, val);
> > > +
> > > + if (base == 16)
> > > + while (*expected == '0' || *expected == 'x')
> > > + ++expected;
> > > +
> > > + if (strcmp(val_str, expected) == 0)
> > > + return true;
> > > +
> > > + fail("expected %s, but have %s\n", expected, val_str);
> > > + return false;
> > > +}
> > > diff --git a/lib/test_util.h b/lib/test_util.h
> > > new file mode 100644
> > > index 0000000000000..0e3e6c4a80d51
> > > --- /dev/null
> > > +++ b/lib/test_util.h
> > > @@ -0,0 +1,13 @@
> > > +#ifndef _TEST_UTIL_H_
> > > +#define _TEST_UTIL_H_
> > > +#include "libcflat.h"
> > > +
> > > +#define PASS 0
> > > +#define FAIL 1
> > > +
> > > +#define pass(fmt...) printf("PASS: " fmt)
> > > +#define fail(fmt...) printf("FAIL: " fmt)
> > > +
> > > +bool enough_args(int nargs, int needed);
> > > +bool check_u32(u32 val, int base, char *expected);
> > > +#endif
> > > --
> > > 1.8.1.4
> > >
> >
> > I was expecting to see a __raw_... IO accessor definitions for ARM here,
> > specifically so we avoid the register-writeback versions that are not
> > supported on ARM.
> >
> > See arch/arm/include/asm/io.h in the kernel.
>
> k, I'll grab them, but they'll go in lib/arm/io.h. I think I'll drop
> these lib/test_util.* in v3, so far they're fairly useless cruft. We
> can bring them back if they have enough purpose later.
>
I already did that for my WIP, see commit
680054064db4dd710991f064a88a12012944d376 in:
https://github.com/columbia/kvm-unit-tests.git
-Christoffer
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 9/9] arm: initial drop
2014-01-02 17:40 ` Peter Maydell
@ 2014-01-02 18:09 ` Christoffer Dall
2014-01-02 18:44 ` Andrew Jones
0 siblings, 1 reply; 44+ messages in thread
From: Christoffer Dall @ 2014-01-02 18:09 UTC (permalink / raw)
To: Peter Maydell; +Cc: Andrew Jones, kvmarm@lists.cs.columbia.edu, kvm-devel
On Thu, Jan 02, 2014 at 05:40:24PM +0000, Peter Maydell wrote:
> On 2 January 2014 16:54, Andrew Jones <drjones@redhat.com> wrote:
> > On Sat, Dec 28, 2013 at 10:31:35PM -0800, Christoffer Dall wrote:
> >> On Wed, Dec 04, 2013 at 05:42:57PM +0100, Andrew Jones wrote:
> >> > + ands r3, r8, #CR_B @set BE, if necessary
> >> > + ldrne r3, =cpu_is_be
> >> > + movne r4, #1
> >>
> >> This is deprecated for ARMv7 according to the ARM ARM. What is the
> >> intention here? Does qemu support running this test tool with the
> >> system configured for big-endian? If so, I think this is a build option
> >> for this binary or you need to come up with some other
> >> architecture-compliant method of detecting the endian-state.
> >
> > Yes, qemu allows big-endian. I haven't tested it though, but suspect
> > someday we will want big-endian guests tested as well. I'll fix the
> > detection.
>
> QEMU does not support system mode big-endian. (Some of the
> pieces are there for it but we have no board that needs it.)
>
> Also, you should read up in the ARM ARM about the differences
> between old style BE32 and new BE8. (The quick summary is here:
> http://translatedcode.wordpress.com/2012/04/)
> What you're trying to do here is enable old-style BE32. This is
> not supported on any ARMv7 or later CPU, which means it does
> not overlap at all with virtualization support.
>
> We probably do care about BE8 big-endian guest support testing.
> (kvmtool can run guests in this mode; QEMU doesn't currently).
>
Yeah, so I think this logic should go away from the test suite for now,
focs on getting a decent set of actual functional tests up and running,
and then probably add aarch64 support before looking at big-endian
support.
Thanks,
-Christoffer
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 5/9] Introduce libio to common code for io read/write
2014-01-02 17:19 ` Christoffer Dall
@ 2014-01-02 18:38 ` Andrew Jones
0 siblings, 0 replies; 44+ messages in thread
From: Andrew Jones @ 2014-01-02 18:38 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvmarm, kvm
On Thu, Jan 02, 2014 at 09:19:30AM -0800, Christoffer Dall wrote:
> > > How is this going to be used here? The compat ptr stuff in the kernel
> > > deals with user space pointer iirc, but I'm not an expert on the
> > > details. Does typedef'ing a pointer to a u32 in generic code work on a
> > > 64-bit platform?
> >
> > This is necessary to eliminate compiler warnings when casting 64-bit
> > pointers to u32s.
> >
>
> ah, ok, a comment to that effect would be nice for us neandertals still
> mostly stuck in the 32-bit worlds.
OK
> > You should take a look, as they're not verbatim - although almost. I can't
> > recall where I might have diverged, I just know I didn't copy+paste :-)
> >
>
> Wonderful, I'll take a look :)
Thanks!!
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 6/9] Introduce a simple iomap structure
2014-01-02 17:23 ` Christoffer Dall
@ 2014-01-02 18:40 ` Andrew Jones
2014-01-02 21:05 ` Christoffer Dall
0 siblings, 1 reply; 44+ messages in thread
From: Andrew Jones @ 2014-01-02 18:40 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvmarm, kvm
On Thu, Jan 02, 2014 at 09:23:38AM -0800, Christoffer Dall wrote:
> On Thu, Jan 02, 2014 at 05:04:48PM +0100, Andrew Jones wrote:
> > On Sat, Dec 28, 2013 at 10:30:54PM -0800, Christoffer Dall wrote:
> > > > +struct iomap {
> > > > + const char *type;
> > > > + const char *compats[5];
> > >
> > > I would name the field compatible to be more in-line with the
> > > DT-representation, but OK.
> > >
> > > it looks from the above like the array must be null terminated?
> > >
> > > how about #define IOMAP_MAX_COMPATS 5
> >
> > defines are good.
> >
> > > and then turn your loop above into:
> > >
> > > for (i = 0; i < IOMAP_MAX_COMPATS; i++, m++) {
> > > if (!m->compats[i])
> > > break;
> >
> > Doesn't improve the loop conditions much, IMO.
> >
>
> I think it's much simpler to read a for loop of the typical form of
> until "i < CONSTANT"; what you had before was a data structure with an
> assumption of null-termination that could only be realized by looking at
> the code that deals with it.
>
> > > if (strcmp(m->compats[i], compat) == 0)
> > > return m;
> > > }
> > >
> > > > + u32 nr;
> > > > + u32 addrs[64];
> > >
> > > why are we limiting ourselves to a 32 bit physical address space?
> >
> > I have had this mentally noted from the beginning as something I'll
> > need to deal with when getting aarch64 going. Anyway, I think a lot
> > of this is going to change as I teach kvm-unit-tests more and more
> > about DT.
>
> Shouldn't be a big change to just support u64 in your iomap instead.
>
> >
> > <snip>
> > > > +print "{\n\t.type = NULL,\n},\n";
> > > > +print "};\n";
> > > > +exit 0;
> > >
> > > This script doesn't work on either of the Ubuntu distros I run. The
> > > reasons are that the dumpfdt tool is not processing the multi-compatible
> > > strings output from the dtb correctly and the fdtget utility included
> > > does not yet have the -l option to list subnodes.
> > >
> > > I spent a fair amount of time trying to fix this, changing dumpfdt to
> > > 'dtc -I dtb -O dts', and I tried it on the newest Ubuntu distro, tried
> > > compiling fdtget from the kernel sources etc. and failed miserably.
> > >
> > > I think at the very least we need to check the tools available on the
> > > build machine as part of the configure script or test it a little
> > > broader.
> > >
> >
> > Drat. I've preferred the idea of using the tools to parse the DT during
> > the build - avoiding the need for [cross-compiled] libfdt as a dep, but
> > I guess as we need more and more from the DT, or when particular tests
> > want to look at the DT itself, and there are already dependency problems,
> > then it's looking more and more like we should just use libfdt.
> >
> Yes, after working with this for a while that's the same conclusion I
> came to. From the ARM perspective, anything running in a VM will be
> device-tree driven (this is not the time for anybody to say anything
> about ACPI), so we could just feed the VM the device tree directly if we
> support libfdt in the guest and avoid another point of failure. I can
> try to find some time to help you hack that up if you want.
I'll start this work right away. Peter's import libfdt idea sounds like
the perfect solution.
drew
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 8/9] Introduce virtio-testdev
2014-01-02 17:27 ` Christoffer Dall
@ 2014-01-02 18:41 ` Andrew Jones
0 siblings, 0 replies; 44+ messages in thread
From: Andrew Jones @ 2014-01-02 18:41 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvmarm, kvm
On Thu, Jan 02, 2014 at 09:27:18AM -0800, Christoffer Dall wrote:
> On Thu, Jan 02, 2014 at 05:16:56PM +0100, Andrew Jones wrote:
> > On Sat, Dec 28, 2013 at 10:31:17PM -0800, Christoffer Dall wrote:
> > > > +
> > > > +/*
> > > > + * We have to write all args; nargs, nrets, ... first to
> > > > + * avoid executing token's operation until all args are in
> > >
> > > the token's ?
> >
> > ok
> >
> > >
> > > > + * place. Then issue the op, and then read the rets. Reading
> > >
> > > rets? return values?
> >
> > ok
> >
> > > > +
> > > > +#define to_virtio_mmio_dev(vdev) \
> > > > + container_of(vdev, struct virtio_mmio_dev, vdev)
> > >
> > > argh, macro pain, can you rename the parameter to _vdev or vdev_ptr or
> > > something like that?
> >
> > ok
> >
> > > > +static struct virtio_dev *virtio_mmio_bind(const struct iomap *m, u32 device)
> > > > +{
> > > > + struct virtio_mmio_dev *vmdev;
> > > > + void *page;
> > > > + u32 devid, i;
> > > > +
> > > > + page = alloc_page();
> > > > + vmdev = page;
> > > > + vmdev->vdev.config = page + sizeof(struct virtio_mmio_dev);
> > > > +
> > > > + vmdev->vdev.id.device = device;
> > > > + vmdev->vdev.id.vendor = -1;
> > > > + vmdev->vdev.config->get = vm_get;
> > > > + vmdev->vdev.config->set = vm_set;
> > > > +
> > > > + device &= 0xffff;
> > >
> > > what is this mask again? Is this to correspond to the virtio PCI device
> > > ID specs, but then shouldn't we also check the range, seems strange to
> > > me to just ignore upper-bits garbage?
> >
> > Right, we're ignoring the upper bits to comply with the spec (and to
> > actually find the device if the upper bits weren't zero). Strangely, at
> > least to me, struct virtio_device_id in the kernel has device as a u32,
> > even though the spec has it as a u16. So I allow u32 devices to be put in
> > the device id, but then throw out the upper bits before searching.
> >
>
> Can you use a define for this mask instead then?
yup. done.
>
> > >
> > > > +
> > > > + for (i = 0; i < m->nr; ++i) {
> > > > + vmdev->base = compat_ptr(m->addrs[i]);
> > > > + devid = readl(vmdev->base + VIRTIO_MMIO_DEVICE_ID);
> > > > + if ((devid & 0xffff) == device)
> > > > + break;
> > > > + }
> > > > +
> > > > + if (i >= m->nr) {
> > >
> > > this can just be 'if (i == m->nr)' right?
> >
> > yeah, I just prefer to choose the broader condition when possible.
> >
>
> hmmm.
>
> > >
> > > > + printf("%s: Can't find device 0x%x.\n", __func__, device);
> > >
> > > I would ditch the '.'
> >
> > ditched
> >
>
> Thanks,
> -Christoffer
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 9/9] arm: initial drop
2014-01-02 18:09 ` Christoffer Dall
@ 2014-01-02 18:44 ` Andrew Jones
0 siblings, 0 replies; 44+ messages in thread
From: Andrew Jones @ 2014-01-02 18:44 UTC (permalink / raw)
To: Christoffer Dall; +Cc: Peter Maydell, kvmarm@lists.cs.columbia.edu, kvm-devel
On Thu, Jan 02, 2014 at 10:09:50AM -0800, Christoffer Dall wrote:
> On Thu, Jan 02, 2014 at 05:40:24PM +0000, Peter Maydell wrote:
> > On 2 January 2014 16:54, Andrew Jones <drjones@redhat.com> wrote:
> > > On Sat, Dec 28, 2013 at 10:31:35PM -0800, Christoffer Dall wrote:
> > >> On Wed, Dec 04, 2013 at 05:42:57PM +0100, Andrew Jones wrote:
> > >> > + ands r3, r8, #CR_B @set BE, if necessary
> > >> > + ldrne r3, =cpu_is_be
> > >> > + movne r4, #1
> > >>
> > >> This is deprecated for ARMv7 according to the ARM ARM. What is the
> > >> intention here? Does qemu support running this test tool with the
> > >> system configured for big-endian? If so, I think this is a build option
> > >> for this binary or you need to come up with some other
> > >> architecture-compliant method of detecting the endian-state.
> > >
> > > Yes, qemu allows big-endian. I haven't tested it though, but suspect
> > > someday we will want big-endian guests tested as well. I'll fix the
> > > detection.
> >
> > QEMU does not support system mode big-endian. (Some of the
> > pieces are there for it but we have no board that needs it.)
> >
> > Also, you should read up in the ARM ARM about the differences
> > between old style BE32 and new BE8. (The quick summary is here:
> > http://translatedcode.wordpress.com/2012/04/)
> > What you're trying to do here is enable old-style BE32. This is
> > not supported on any ARMv7 or later CPU, which means it does
> > not overlap at all with virtualization support.
> >
> > We probably do care about BE8 big-endian guest support testing.
> > (kvmtool can run guests in this mode; QEMU doesn't currently).
> >
> Yeah, so I think this logic should go away from the test suite for now,
> focs on getting a decent set of actual functional tests up and running,
> and then probably add aarch64 support before looking at big-endian
> support.
>
OK, sounds good. The cpu_is_be stuff scattered about should still be fine
to leave in, and we can go about actually detecting BE and setting
cpu_is_be whenever.
thanks,
drew
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 9/9] arm: initial drop
2014-01-02 17:44 ` Christoffer Dall
@ 2014-01-02 18:50 ` Andrew Jones
2014-01-02 19:17 ` Christoffer Dall
0 siblings, 1 reply; 44+ messages in thread
From: Andrew Jones @ 2014-01-02 18:50 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvmarm, kvm
On Thu, Jan 02, 2014 at 09:44:39AM -0800, Christoffer Dall wrote:
> > My cross-compiler was generating broken code with anything less. I
> > haven't checked later compilers yet to see if it's fixed or not.
> >
>
> which GCC version?
$ arm-linux-gnu-gcc -v
Using built-in specs.
COLLECT_GCC=arm-linux-gnu-gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/arm-linux-gnueabi/4.8.1/lto-wrapper
Target: arm-linux-gnueabi
Configured with: ../gcc-4.8.1-20130717/configure --bindir=/usr/bin
--build=x86_64-redhat-linux-gnu --datadir=/usr/share
--disable-decimal-float --disable-dependency-tracking --disable-gold
--disable-libgomp --disable-libmudflap --disable-libquadmath
--disable-libssp --disable-nls --disable-plugin --disable-shared
--disable-silent-rules --disable-sjlj-exceptions --disable-threads
--enable-checking= --enable-gnu-unique-object --enable-initfini-array
--enable-languages=c --enable-linker-build-id --enable-nls
--enable-obsolete --enable-targets=all --exec-prefix=/usr
--host=x86_64-redhat-linux-gnu --includedir=/usr/include
--infodir=/usr/share/info --libexecdir=/usr/libexec --localstatedir=/var
--mandir=/usr/share/man --prefix=/usr --program-prefix=arm-linux-gnu-
--sbindir=/usr/sbin --sharedstatedir=/var/lib --sysconfdir=/etc
--target=arm-linux-gnueabi
--with-bugurl=http://bugzilla.redhat.com/bugzilla/
--with-linker-hash-style=gnu --with-newlib --with-system-libunwind
--with-system-zlib --without-headers
--with-isl=/builddir/build/BUILD/gcc-4.8.1-20130717/isl-install
--with-cloog=/builddir/build/BUILD/gcc-4.8.1-20130717/cloog-install
Thread model: single
gcc version 4.8.1 20130717 (Red Hat 4.8.1-5) (GCC)
> > > I was expecting to see a __raw_... IO accessor definitions for ARM here,
> > > specifically so we avoid the register-writeback versions that are not
> > > supported on ARM.
> > >
> > > See arch/arm/include/asm/io.h in the kernel.
> >
> > k, I'll grab them, but they'll go in lib/arm/io.h. I think I'll drop
> > these lib/test_util.* in v3, so far they're fairly useless cruft. We
> > can bring them back if they have enough purpose later.
> >
>
> I already did that for my WIP, see commit
> 680054064db4dd710991f064a88a12012944d376 in:
>
> https://github.com/columbia/kvm-unit-tests.git
I'll fetch your tree and start going through it tomorrow. Thanks for
jumping in!!
drew
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 9/9] arm: initial drop
2014-01-02 18:50 ` Andrew Jones
@ 2014-01-02 19:17 ` Christoffer Dall
2014-01-03 17:52 ` Andrew Jones
0 siblings, 1 reply; 44+ messages in thread
From: Christoffer Dall @ 2014-01-02 19:17 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvmarm, kvm
On Thu, Jan 02, 2014 at 07:50:27PM +0100, Andrew Jones wrote:
> On Thu, Jan 02, 2014 at 09:44:39AM -0800, Christoffer Dall wrote:
> > > My cross-compiler was generating broken code with anything less. I
> > > haven't checked later compilers yet to see if it's fixed or not.
> > >
> >
> > which GCC version?
>
> $ arm-linux-gnu-gcc -v
> Using built-in specs.
> COLLECT_GCC=arm-linux-gnu-gcc
> COLLECT_LTO_WRAPPER=/usr/libexec/gcc/arm-linux-gnueabi/4.8.1/lto-wrapper
> Target: arm-linux-gnueabi
> Configured with: ../gcc-4.8.1-20130717/configure --bindir=/usr/bin
> --build=x86_64-redhat-linux-gnu --datadir=/usr/share
> --disable-decimal-float --disable-dependency-tracking --disable-gold
> --disable-libgomp --disable-libmudflap --disable-libquadmath
> --disable-libssp --disable-nls --disable-plugin --disable-shared
> --disable-silent-rules --disable-sjlj-exceptions --disable-threads
> --enable-checking= --enable-gnu-unique-object --enable-initfini-array
> --enable-languages=c --enable-linker-build-id --enable-nls
> --enable-obsolete --enable-targets=all --exec-prefix=/usr
> --host=x86_64-redhat-linux-gnu --includedir=/usr/include
> --infodir=/usr/share/info --libexecdir=/usr/libexec --localstatedir=/var
> --mandir=/usr/share/man --prefix=/usr --program-prefix=arm-linux-gnu-
> --sbindir=/usr/sbin --sharedstatedir=/var/lib --sysconfdir=/etc
> --target=arm-linux-gnueabi
> --with-bugurl=http://bugzilla.redhat.com/bugzilla/
> --with-linker-hash-style=gnu --with-newlib --with-system-libunwind
> --with-system-zlib --without-headers
> --with-isl=/builddir/build/BUILD/gcc-4.8.1-20130717/isl-install
> --with-cloog=/builddir/build/BUILD/gcc-4.8.1-20130717/cloog-install
> Thread model: single
> gcc version 4.8.1 20130717 (Red Hat 4.8.1-5) (GCC)
>
> > > > I was expecting to see a __raw_... IO accessor definitions for ARM here,
> > > > specifically so we avoid the register-writeback versions that are not
> > > > supported on ARM.
> > > >
> > > > See arch/arm/include/asm/io.h in the kernel.
> > >
> > > k, I'll grab them, but they'll go in lib/arm/io.h. I think I'll drop
> > > these lib/test_util.* in v3, so far they're fairly useless cruft. We
> > > can bring them back if they have enough purpose later.
> > >
> >
> > I already did that for my WIP, see commit
> > 680054064db4dd710991f064a88a12012944d376 in:
> >
> > https://github.com/columbia/kvm-unit-tests.git
>
> I'll fetch your tree and start going through it tomorrow. Thanks for
> jumping in!!
>
Sure, if you fix anything in your existing series, I'll be happy to
rebase my patches and take a pass at squashing some of them and such so
we can get them out as an RFC.
-Christoffer
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 6/9] Introduce a simple iomap structure
2014-01-02 18:40 ` Andrew Jones
@ 2014-01-02 21:05 ` Christoffer Dall
0 siblings, 0 replies; 44+ messages in thread
From: Christoffer Dall @ 2014-01-02 21:05 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvmarm, kvm
On Thu, Jan 02, 2014 at 07:40:14PM +0100, Andrew Jones wrote:
> On Thu, Jan 02, 2014 at 09:23:38AM -0800, Christoffer Dall wrote:
> > On Thu, Jan 02, 2014 at 05:04:48PM +0100, Andrew Jones wrote:
> > > On Sat, Dec 28, 2013 at 10:30:54PM -0800, Christoffer Dall wrote:
> > > > > +struct iomap {
> > > > > + const char *type;
> > > > > + const char *compats[5];
> > > >
> > > > I would name the field compatible to be more in-line with the
> > > > DT-representation, but OK.
> > > >
> > > > it looks from the above like the array must be null terminated?
> > > >
> > > > how about #define IOMAP_MAX_COMPATS 5
> > >
> > > defines are good.
> > >
> > > > and then turn your loop above into:
> > > >
> > > > for (i = 0; i < IOMAP_MAX_COMPATS; i++, m++) {
> > > > if (!m->compats[i])
> > > > break;
> > >
> > > Doesn't improve the loop conditions much, IMO.
> > >
> >
> > I think it's much simpler to read a for loop of the typical form of
> > until "i < CONSTANT"; what you had before was a data structure with an
> > assumption of null-termination that could only be realized by looking at
> > the code that deals with it.
> >
> > > > if (strcmp(m->compats[i], compat) == 0)
> > > > return m;
> > > > }
> > > >
> > > > > + u32 nr;
> > > > > + u32 addrs[64];
> > > >
> > > > why are we limiting ourselves to a 32 bit physical address space?
> > >
> > > I have had this mentally noted from the beginning as something I'll
> > > need to deal with when getting aarch64 going. Anyway, I think a lot
> > > of this is going to change as I teach kvm-unit-tests more and more
> > > about DT.
> >
> > Shouldn't be a big change to just support u64 in your iomap instead.
> >
> > >
> > > <snip>
> > > > > +print "{\n\t.type = NULL,\n},\n";
> > > > > +print "};\n";
> > > > > +exit 0;
> > > >
> > > > This script doesn't work on either of the Ubuntu distros I run. The
> > > > reasons are that the dumpfdt tool is not processing the multi-compatible
> > > > strings output from the dtb correctly and the fdtget utility included
> > > > does not yet have the -l option to list subnodes.
> > > >
> > > > I spent a fair amount of time trying to fix this, changing dumpfdt to
> > > > 'dtc -I dtb -O dts', and I tried it on the newest Ubuntu distro, tried
> > > > compiling fdtget from the kernel sources etc. and failed miserably.
> > > >
> > > > I think at the very least we need to check the tools available on the
> > > > build machine as part of the configure script or test it a little
> > > > broader.
> > > >
> > >
> > > Drat. I've preferred the idea of using the tools to parse the DT during
> > > the build - avoiding the need for [cross-compiled] libfdt as a dep, but
> > > I guess as we need more and more from the DT, or when particular tests
> > > want to look at the DT itself, and there are already dependency problems,
> > > then it's looking more and more like we should just use libfdt.
> > >
> > Yes, after working with this for a while that's the same conclusion I
> > came to. From the ARM perspective, anything running in a VM will be
> > device-tree driven (this is not the time for anybody to say anything
> > about ACPI), so we could just feed the VM the device tree directly if we
> > support libfdt in the guest and avoid another point of failure. I can
> > try to find some time to help you hack that up if you want.
>
> I'll start this work right away. Peter's import libfdt idea sounds like
> the perfect solution.
>
Agreed.
-Christoffer
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 9/9] arm: initial drop
2014-01-02 19:17 ` Christoffer Dall
@ 2014-01-03 17:52 ` Andrew Jones
2014-01-03 17:55 ` Christoffer Dall
0 siblings, 1 reply; 44+ messages in thread
From: Andrew Jones @ 2014-01-03 17:52 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvmarm, kvm
On Thu, Jan 02, 2014 at 11:17:51AM -0800, Christoffer Dall wrote:
> On Thu, Jan 02, 2014 at 07:50:27PM +0100, Andrew Jones wrote:
> > On Thu, Jan 02, 2014 at 09:44:39AM -0800, Christoffer Dall wrote:
> > > > My cross-compiler was generating broken code with anything less. I
> > > > haven't checked later compilers yet to see if it's fixed or not.
> > > >
> > >
> > > which GCC version?
> >
> > $ arm-linux-gnu-gcc -v
> > Using built-in specs.
> > COLLECT_GCC=arm-linux-gnu-gcc
> > COLLECT_LTO_WRAPPER=/usr/libexec/gcc/arm-linux-gnueabi/4.8.1/lto-wrapper
> > Target: arm-linux-gnueabi
> > Configured with: ../gcc-4.8.1-20130717/configure --bindir=/usr/bin
> > --build=x86_64-redhat-linux-gnu --datadir=/usr/share
> > --disable-decimal-float --disable-dependency-tracking --disable-gold
> > --disable-libgomp --disable-libmudflap --disable-libquadmath
> > --disable-libssp --disable-nls --disable-plugin --disable-shared
> > --disable-silent-rules --disable-sjlj-exceptions --disable-threads
> > --enable-checking= --enable-gnu-unique-object --enable-initfini-array
> > --enable-languages=c --enable-linker-build-id --enable-nls
> > --enable-obsolete --enable-targets=all --exec-prefix=/usr
> > --host=x86_64-redhat-linux-gnu --includedir=/usr/include
> > --infodir=/usr/share/info --libexecdir=/usr/libexec --localstatedir=/var
> > --mandir=/usr/share/man --prefix=/usr --program-prefix=arm-linux-gnu-
> > --sbindir=/usr/sbin --sharedstatedir=/var/lib --sysconfdir=/etc
> > --target=arm-linux-gnueabi
> > --with-bugurl=http://bugzilla.redhat.com/bugzilla/
> > --with-linker-hash-style=gnu --with-newlib --with-system-libunwind
> > --with-system-zlib --without-headers
> > --with-isl=/builddir/build/BUILD/gcc-4.8.1-20130717/isl-install
> > --with-cloog=/builddir/build/BUILD/gcc-4.8.1-20130717/cloog-install
> > Thread model: single
> > gcc version 4.8.1 20130717 (Red Hat 4.8.1-5) (GCC)
> >
> > > > > I was expecting to see a __raw_... IO accessor definitions for ARM here,
> > > > > specifically so we avoid the register-writeback versions that are not
> > > > > supported on ARM.
> > > > >
> > > > > See arch/arm/include/asm/io.h in the kernel.
> > > >
> > > > k, I'll grab them, but they'll go in lib/arm/io.h. I think I'll drop
> > > > these lib/test_util.* in v3, so far they're fairly useless cruft. We
> > > > can bring them back if they have enough purpose later.
> > > >
> > >
> > > I already did that for my WIP, see commit
> > > 680054064db4dd710991f064a88a12012944d376 in:
> > >
> > > https://github.com/columbia/kvm-unit-tests.git
> >
> > I'll fetch your tree and start going through it tomorrow. Thanks for
> > jumping in!!
> >
> Sure, if you fix anything in your existing series, I'll be happy to
> rebase my patches and take a pass at squashing some of them and such so
> we can get them out as an RFC.
Lot's of good stuff in there. I also had a start on the psci/smp stuff
(in the form of notes, not code) before the holiday break, so I might have
some more suggestions there once we get the patches rebased and cleaned up.
I'd like to get a v3 posted [and committed] of this series, a version that
uses libfdt, before we get too far along, allowing us to build on a clean
base.
Thanks,
drew
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 9/9] arm: initial drop
2014-01-03 17:52 ` Andrew Jones
@ 2014-01-03 17:55 ` Christoffer Dall
0 siblings, 0 replies; 44+ messages in thread
From: Christoffer Dall @ 2014-01-03 17:55 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org
On 3 January 2014 09:52, Andrew Jones <drjones@redhat.com> wrote:
> On Thu, Jan 02, 2014 at 11:17:51AM -0800, Christoffer Dall wrote:
>> On Thu, Jan 02, 2014 at 07:50:27PM +0100, Andrew Jones wrote:
>> > On Thu, Jan 02, 2014 at 09:44:39AM -0800, Christoffer Dall wrote:
>> > > > My cross-compiler was generating broken code with anything less. I
>> > > > haven't checked later compilers yet to see if it's fixed or not.
>> > > >
>> > >
>> > > which GCC version?
>> >
>> > $ arm-linux-gnu-gcc -v
>> > Using built-in specs.
>> > COLLECT_GCC=arm-linux-gnu-gcc
>> > COLLECT_LTO_WRAPPER=/usr/libexec/gcc/arm-linux-gnueabi/4.8.1/lto-wrapper
>> > Target: arm-linux-gnueabi
>> > Configured with: ../gcc-4.8.1-20130717/configure --bindir=/usr/bin
>> > --build=x86_64-redhat-linux-gnu --datadir=/usr/share
>> > --disable-decimal-float --disable-dependency-tracking --disable-gold
>> > --disable-libgomp --disable-libmudflap --disable-libquadmath
>> > --disable-libssp --disable-nls --disable-plugin --disable-shared
>> > --disable-silent-rules --disable-sjlj-exceptions --disable-threads
>> > --enable-checking= --enable-gnu-unique-object --enable-initfini-array
>> > --enable-languages=c --enable-linker-build-id --enable-nls
>> > --enable-obsolete --enable-targets=all --exec-prefix=/usr
>> > --host=x86_64-redhat-linux-gnu --includedir=/usr/include
>> > --infodir=/usr/share/info --libexecdir=/usr/libexec --localstatedir=/var
>> > --mandir=/usr/share/man --prefix=/usr --program-prefix=arm-linux-gnu-
>> > --sbindir=/usr/sbin --sharedstatedir=/var/lib --sysconfdir=/etc
>> > --target=arm-linux-gnueabi
>> > --with-bugurl=http://bugzilla.redhat.com/bugzilla/
>> > --with-linker-hash-style=gnu --with-newlib --with-system-libunwind
>> > --with-system-zlib --without-headers
>> > --with-isl=/builddir/build/BUILD/gcc-4.8.1-20130717/isl-install
>> > --with-cloog=/builddir/build/BUILD/gcc-4.8.1-20130717/cloog-install
>> > Thread model: single
>> > gcc version 4.8.1 20130717 (Red Hat 4.8.1-5) (GCC)
>> >
>> > > > > I was expecting to see a __raw_... IO accessor definitions for ARM here,
>> > > > > specifically so we avoid the register-writeback versions that are not
>> > > > > supported on ARM.
>> > > > >
>> > > > > See arch/arm/include/asm/io.h in the kernel.
>> > > >
>> > > > k, I'll grab them, but they'll go in lib/arm/io.h. I think I'll drop
>> > > > these lib/test_util.* in v3, so far they're fairly useless cruft. We
>> > > > can bring them back if they have enough purpose later.
>> > > >
>> > >
>> > > I already did that for my WIP, see commit
>> > > 680054064db4dd710991f064a88a12012944d376 in:
>> > >
>> > > https://github.com/columbia/kvm-unit-tests.git
>> >
>> > I'll fetch your tree and start going through it tomorrow. Thanks for
>> > jumping in!!
>> >
>> Sure, if you fix anything in your existing series, I'll be happy to
>> rebase my patches and take a pass at squashing some of them and such so
>> we can get them out as an RFC.
>
> Lot's of good stuff in there. I also had a start on the psci/smp stuff
> (in the form of notes, not code) before the holiday break, so I might have
> some more suggestions there once we get the patches rebased and cleaned up.
> I'd like to get a v3 posted [and committed] of this series, a version that
> uses libfdt, before we get too far along, allowing us to build on a clean
> base.
>
Sounds fine, I'll keep building the stuff I need for other
measurements, but fear not, I have magic powers in rebasing complex
systems on top of evolving code bases :)
-Christoffer
^ permalink raw reply [flat|nested] 44+ messages in thread
end of thread, other threads:[~2014-01-03 17:55 UTC | newest]
Thread overview: 44+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-04 16:42 [PATCH 0/9 v2] kvm-unit-tests/arm: initial drop Andrew Jones
2013-12-04 16:42 ` [PATCH 1/9] remove unused files Andrew Jones
2013-12-04 16:42 ` [PATCH 2/9] makefile and run_tests tweaks Andrew Jones
2013-12-29 6:30 ` Christoffer Dall
2014-01-02 14:30 ` Andrew Jones
2013-12-04 16:42 ` [PATCH 3/9] clean root dir of all x86-ness Andrew Jones
2013-12-29 6:30 ` Christoffer Dall
2014-01-02 15:00 ` Andrew Jones
2014-01-02 17:16 ` Christoffer Dall
2013-12-04 16:42 ` [PATCH 4/9] move x86's simple heap management to common code Andrew Jones
2013-12-29 6:30 ` Christoffer Dall
2014-01-02 15:17 ` Andrew Jones
2014-01-02 17:17 ` Christoffer Dall
2013-12-04 16:42 ` [PATCH 5/9] Introduce libio to common code for io read/write Andrew Jones
2013-12-29 6:30 ` Christoffer Dall
2014-01-02 15:47 ` Andrew Jones
2014-01-02 17:19 ` Christoffer Dall
2014-01-02 18:38 ` Andrew Jones
2013-12-04 16:42 ` [PATCH 6/9] Introduce a simple iomap structure Andrew Jones
2013-12-29 6:30 ` Christoffer Dall
2014-01-02 16:04 ` Andrew Jones
2014-01-02 17:23 ` Christoffer Dall
2014-01-02 18:40 ` Andrew Jones
2014-01-02 21:05 ` Christoffer Dall
2014-01-02 17:32 ` Peter Maydell
2013-12-04 16:42 ` [PATCH 7/9] Add halt() and some error codes Andrew Jones
2013-12-29 6:31 ` Christoffer Dall
2013-12-04 16:42 ` [PATCH 8/9] Introduce virtio-testdev Andrew Jones
2013-12-29 6:31 ` Christoffer Dall
2014-01-02 16:16 ` Andrew Jones
2014-01-02 17:27 ` Christoffer Dall
2014-01-02 18:41 ` Andrew Jones
2013-12-04 16:42 ` [PATCH 9/9] arm: initial drop Andrew Jones
2013-12-29 6:31 ` Christoffer Dall
2013-12-29 9:18 ` Peter Maydell
2014-01-02 16:54 ` Andrew Jones
2014-01-02 17:40 ` Peter Maydell
2014-01-02 18:09 ` Christoffer Dall
2014-01-02 18:44 ` Andrew Jones
2014-01-02 17:44 ` Christoffer Dall
2014-01-02 18:50 ` Andrew Jones
2014-01-02 19:17 ` Christoffer Dall
2014-01-03 17:52 ` Andrew Jones
2014-01-03 17:55 ` Christoffer Dall
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).