* [PATCH 0/9] kvm-unit-tests/arm: initial drop
@ 2013-10-14 16:23 Andrew Jones
2013-10-14 16:23 ` [PATCH 1/9] remove unused files Andrew Jones
` (10 more replies)
0 siblings, 11 replies; 38+ messages in thread
From: Andrew Jones @ 2013-10-14 16:23 UTC (permalink / raw)
To: kvm; +Cc: kvmarm, gleb, christoffer.dall
This series introduces arm to kvm-unit-tests. First, it does some
tidying up of the repo. Then, it adds support for virtio-testdev,
which was just posted to qemu-devel[1]. Next, it adds the basic
infrastructure for booting a test case (guest). Finally, it adds
support for vectors. This is just an initial drop, I'm starting
work on smp support now, and then will bring in support for
arm64. At that point we should be able to start actually adding
tests. To use this you need an arm platform or simulator capable
of running kvmarm and a qemu with the mach-virt patches[2], as
well as the previously mentioned virtio-testdev.
[1] http://lists.nongnu.org/archive/html/qemu-devel/2013-10/msg01815.html
[2] http://lists.nongnu.org/archive/html/qemu-devel/2013-09/msg02142.html
This patches are also available from a git repo here
https://github.com/rhdrjones/kvm-unit-tests/tree/arm-branch/master
Andrew Jones (9):
remove unused files
makefile and run_tests tweaks
clean root dir of all x86-ness
Introduce a simple iomap structure
Add halt() and some error codes
Introduce virtio-testdev
arm: replace arbitrary divisions
arm: initial drop
arm: add vectors support
Makefile | 19 +-
README | 56 ++--
arm/boot.c | 46 +++
arm/cstart.S | 93 ++++++
arm/flat.lds | 18 ++
arm/run | 19 ++
arm/unittests.cfg | 17 +
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 | 63 ++++
config/config-i386.mak | 12 +
config/config-x86-common.mak | 120 +++++++
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/bootinfo.c | 68 ++++
lib/arm/bootinfo.h | 19 ++
lib/arm/bswap.h | 30 ++
lib/arm/io.c | 26 ++
lib/arm/processor.h | 45 +++
lib/arm/vectors.c | 65 ++++
lib/arm/vectors.h | 37 +++
lib/bswap.h | 11 +
lib/divmod.h | 20 ++
lib/errno.h | 15 +
lib/fwcfg.c | 58 ----
lib/iomaps.c | 12 +
lib/iomaps.h | 12 +
lib/libcflat.h | 16 +-
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/printf.c | 27 +-
lib/virtio-testdev.c | 126 ++++++++
lib/virtio-testdev.h | 9 +
lib/x86/io.c | 6 +
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 | 81 +++++
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 -
69 files changed, 1195 insertions(+), 2633 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/bootinfo.c
create mode 100644 lib/arm/bootinfo.h
create mode 100644 lib/arm/bswap.h
create mode 100644 lib/arm/io.c
create mode 100644 lib/arm/processor.h
create mode 100644 lib/arm/vectors.c
create mode 100644 lib/arm/vectors.h
create mode 100644 lib/bswap.h
create mode 100644 lib/divmod.h
create mode 100644 lib/errno.h
delete mode 100644 lib/fwcfg.c
create mode 100644 lib/iomaps.c
create mode 100644 lib/iomaps.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/virtio-testdev.c
create mode 100644 lib/virtio-testdev.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] 38+ messages in thread* [PATCH 1/9] remove unused files 2013-10-14 16:23 [PATCH 0/9] kvm-unit-tests/arm: initial drop Andrew Jones @ 2013-10-14 16:23 ` Andrew Jones 2013-10-16 12:52 ` Gleb Natapov 2013-10-14 16:23 ` [PATCH 2/9] makefile and run_tests tweaks Andrew Jones ` (9 subsequent siblings) 10 siblings, 1 reply; 38+ messages in thread From: Andrew Jones @ 2013-10-14 16:23 UTC (permalink / raw) To: kvm; +Cc: kvmarm, gleb, christoffer.dall 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] 38+ messages in thread
* Re: [PATCH 1/9] remove unused files 2013-10-14 16:23 ` [PATCH 1/9] remove unused files Andrew Jones @ 2013-10-16 12:52 ` Gleb Natapov 2013-10-16 13:13 ` Alexander Graf 2013-10-16 13:18 ` Andrew Jones 0 siblings, 2 replies; 38+ messages in thread From: Gleb Natapov @ 2013-10-16 12:52 UTC (permalink / raw) To: Andrew Jones; +Cc: kvm, kvmarm, christoffer.dall, Alexander Graf Copying Alex in case he has an opinion about removing powerpc. On Mon, Oct 14, 2013 at 06:23:27PM +0200, Andrew Jones wrote: > 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 -- Gleb. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/9] remove unused files 2013-10-16 12:52 ` Gleb Natapov @ 2013-10-16 13:13 ` Alexander Graf 2013-10-16 13:18 ` Andrew Jones 1 sibling, 0 replies; 38+ messages in thread From: Alexander Graf @ 2013-10-16 13:13 UTC (permalink / raw) To: Gleb Natapov; +Cc: Andrew Jones, kvm, kvmarm, christoffer.dall, kvm-ppc On 10/16/2013 02:52 PM, Gleb Natapov wrote: > Copying Alex in case he has an opinion about removing powerpc. I would prefer to see it fixed and actually get unit tests, but the code that's there is trivial enough to not really make an impact on that. So no real complaints from my side. Alex > > On Mon, Oct 14, 2013 at 06:23:27PM +0200, Andrew Jones wrote: >> 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 >> [...] ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/9] remove unused files 2013-10-16 12:52 ` Gleb Natapov 2013-10-16 13:13 ` Alexander Graf @ 2013-10-16 13:18 ` Andrew Jones 1 sibling, 0 replies; 38+ messages in thread From: Andrew Jones @ 2013-10-16 13:18 UTC (permalink / raw) To: Gleb Natapov; +Cc: kvm, kvmarm, christoffer.dall, Alexander Graf On Wed, Oct 16, 2013 at 03:52:43PM +0300, Gleb Natapov wrote: > Copying Alex in case he has an opinion about removing powerpc. > We had discussed it earlier[1], and I got the go-ahead to toss out the current code. drew [1] http://comments.gmane.org/gmane.comp.emulators.kvm.powerpc.devel/7747 ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 2/9] makefile and run_tests tweaks 2013-10-14 16:23 [PATCH 0/9] kvm-unit-tests/arm: initial drop Andrew Jones 2013-10-14 16:23 ` [PATCH 1/9] remove unused files Andrew Jones @ 2013-10-14 16:23 ` Andrew Jones 2013-10-14 16:23 ` [PATCH 3/9] clean root dir of all x86-ness Andrew Jones ` (8 subsequent siblings) 10 siblings, 0 replies; 38+ messages in thread From: Andrew Jones @ 2013-10-14 16:23 UTC (permalink / raw) To: kvm; +Cc: kvmarm, gleb, christoffer.dall - 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] 38+ messages in thread
* [PATCH 3/9] clean root dir of all x86-ness 2013-10-14 16:23 [PATCH 0/9] kvm-unit-tests/arm: initial drop Andrew Jones 2013-10-14 16:23 ` [PATCH 1/9] remove unused files Andrew Jones 2013-10-14 16:23 ` [PATCH 2/9] makefile and run_tests tweaks Andrew Jones @ 2013-10-14 16:23 ` Andrew Jones 2013-10-17 1:06 ` Christoffer Dall 2013-10-14 16:23 ` [PATCH 4/9] Introduce a simple iomap structure Andrew Jones ` (7 subsequent siblings) 10 siblings, 1 reply; 38+ messages in thread From: Andrew Jones @ 2013-10-14 16:23 UTC (permalink / raw) To: kvm; +Cc: kvmarm, gleb, christoffer.dall 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> --- 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..49468b94bc7fc 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 tests' images do + ./configure + make +in this directory. Tests' 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] 38+ messages in thread
* Re: [PATCH 3/9] clean root dir of all x86-ness 2013-10-14 16:23 ` [PATCH 3/9] clean root dir of all x86-ness Andrew Jones @ 2013-10-17 1:06 ` Christoffer Dall 2013-10-17 9:35 ` Andrew Jones 0 siblings, 1 reply; 38+ messages in thread From: Christoffer Dall @ 2013-10-17 1:06 UTC (permalink / raw) To: Andrew Jones; +Cc: kvm, kvmarm, gleb On Mon, Oct 14, 2013 at 06:23:29PM +0200, 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. Just giving this a cursory pass... > > Signed-off-by: Andrew Jones <drjones@redhat.com> > --- > 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..49468b94bc7fc 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 tests' images do tests' images doesn't read very nice, can we just say test images? > + ./configure > + make > +in this directory. Tests' 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. While you're at it, it would be great to provide a little more context in the README file. For example, we start talking abouter 'runner scripts', we refer to something called '.flat', and we refer to QEMU without explaining how this whole thing works, what the components are, what is required of QEMU etc. I think that would be useful for the wider adoption of kvm-unit-tests to developers writing ad-hoc patches for KVM. A reference to docs/testdev.txt from somewhere approrpriate in such text would probably also be useful... I know much of this is arch-specific, but there must be something generic or common across the architecture, and that would in essense be capturing what 'kvm-unit-tests' give you, which I think is very useful to have in the readme. > + > +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 [flat|nested] 38+ messages in thread
* Re: [PATCH 3/9] clean root dir of all x86-ness 2013-10-17 1:06 ` Christoffer Dall @ 2013-10-17 9:35 ` Andrew Jones 2013-10-17 19:01 ` Christoffer Dall 0 siblings, 1 reply; 38+ messages in thread From: Andrew Jones @ 2013-10-17 9:35 UTC (permalink / raw) To: Christoffer Dall; +Cc: kvm, kvmarm, gleb On Wed, Oct 16, 2013 at 06:06:06PM -0700, Christoffer Dall wrote: > > -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 tests' images do > > tests' images doesn't read very nice, can we just say test images? OK > > > + ./configure > > + make > > +in this directory. Tests' 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. > > While you're at it, it would be great to provide a little more context > in the README file. > > For example, we start talking abouter 'runner scripts', we refer to > something called '.flat', and we refer to QEMU without explaining how > this whole thing works, what the components are, what is required of > QEMU etc. > > I think that would be useful for the wider adoption of kvm-unit-tests to > developers writing ad-hoc patches for KVM. > > A reference to docs/testdev.txt from somewhere approrpriate in such text > would probably also be useful... > > I know much of this is arch-specific, but there must be something > generic or common across the architecture, and that would in essense be > capturing what 'kvm-unit-tests' give you, which I think is very useful > to have in the readme. > Agreed. I'll see what I can do with the overall documentation. And I need to create an arm/README for arm specific documentation as well. drew ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 3/9] clean root dir of all x86-ness 2013-10-17 9:35 ` Andrew Jones @ 2013-10-17 19:01 ` Christoffer Dall 2013-10-20 16:37 ` Andrew Jones 0 siblings, 1 reply; 38+ messages in thread From: Christoffer Dall @ 2013-10-17 19:01 UTC (permalink / raw) To: Andrew Jones; +Cc: kvm, kvmarm, gleb On Thu, Oct 17, 2013 at 11:35:09AM +0200, Andrew Jones wrote: > On Wed, Oct 16, 2013 at 06:06:06PM -0700, Christoffer Dall wrote: > > > -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 tests' images do > > > > tests' images doesn't read very nice, can we just say test images? > > OK > > > > > > + ./configure > > > + make > > > +in this directory. Tests' 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. > > > > While you're at it, it would be great to provide a little more context > > in the README file. > > > > For example, we start talking abouter 'runner scripts', we refer to > > something called '.flat', and we refer to QEMU without explaining how > > this whole thing works, what the components are, what is required of > > QEMU etc. > > > > I think that would be useful for the wider adoption of kvm-unit-tests to > > developers writing ad-hoc patches for KVM. > > > > A reference to docs/testdev.txt from somewhere approrpriate in such text > > would probably also be useful... > > > > I know much of this is arch-specific, but there must be something > > generic or common across the architecture, and that would in essense be > > capturing what 'kvm-unit-tests' give you, which I think is very useful > > to have in the readme. > > > > Agreed. I'll see what I can do with the overall documentation. And I need > to create an arm/README for arm specific documentation as well. > We can work on this a bit together as well if you want, I need to get a slightly broader understanding of this framework first though. Are you going to be at KVM forum? -Christoffer ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 3/9] clean root dir of all x86-ness 2013-10-17 19:01 ` Christoffer Dall @ 2013-10-20 16:37 ` Andrew Jones 0 siblings, 0 replies; 38+ messages in thread From: Andrew Jones @ 2013-10-20 16:37 UTC (permalink / raw) To: Christoffer Dall; +Cc: kvm, kvmarm, gleb On Thu, Oct 17, 2013 at 12:01:52PM -0700, Christoffer Dall wrote: > On Thu, Oct 17, 2013 at 11:35:09AM +0200, Andrew Jones wrote: > > On Wed, Oct 16, 2013 at 06:06:06PM -0700, Christoffer Dall wrote: > > > > -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 tests' images do > > > > > > tests' images doesn't read very nice, can we just say test images? > > > > OK > > > > > > > > > + ./configure > > > > + make > > > > +in this directory. Tests' 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. > > > > > > While you're at it, it would be great to provide a little more context > > > in the README file. > > > > > > For example, we start talking abouter 'runner scripts', we refer to > > > something called '.flat', and we refer to QEMU without explaining how > > > this whole thing works, what the components are, what is required of > > > QEMU etc. > > > > > > I think that would be useful for the wider adoption of kvm-unit-tests to > > > developers writing ad-hoc patches for KVM. > > > > > > A reference to docs/testdev.txt from somewhere approrpriate in such text > > > would probably also be useful... > > > > > > I know much of this is arch-specific, but there must be something > > > generic or common across the architecture, and that would in essense be > > > capturing what 'kvm-unit-tests' give you, which I think is very useful > > > to have in the readme. > > > > > > > Agreed. I'll see what I can do with the overall documentation. And I need > > to create an arm/README for arm specific documentation as well. > > > We can work on this a bit together as well if you want, I need to get a > slightly broader understanding of this framework first though. Are you > going to be at KVM forum? > Yup. Already here :-) drew ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 4/9] Introduce a simple iomap structure 2013-10-14 16:23 [PATCH 0/9] kvm-unit-tests/arm: initial drop Andrew Jones ` (2 preceding siblings ...) 2013-10-14 16:23 ` [PATCH 3/9] clean root dir of all x86-ness Andrew Jones @ 2013-10-14 16:23 ` Andrew Jones 2013-10-14 16:23 ` [PATCH 5/9] Add halt() and some error codes Andrew Jones ` (6 subsequent siblings) 10 siblings, 0 replies; 38+ messages in thread From: Andrew Jones @ 2013-10-14 16:23 UTC (permalink / raw) To: kvm; +Cc: kvmarm, gleb, christoffer.dall 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> --- README | 1 + lib/iomaps.c | 12 +++++++ lib/iomaps.h | 12 +++++++ scripts/gen-devtree-iomaps.pl | 81 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 106 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 49468b94bc7fc..1e58fd2e3ca00 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..6169bcf2e43d2 --- /dev/null +++ b/lib/iomaps.c @@ -0,0 +1,12 @@ +#include "libcflat.h" +#include "iomaps.h" + +extern struct iomap iomaps[]; + +struct iomap *iomaps_find(const char *type) +{ + struct iomap *m = &iomaps[0]; + for (; m->type && strcmp(m->type, type); ++m) + ; + return m->type ? m : NULL; +} diff --git a/lib/iomaps.h b/lib/iomaps.h new file mode 100644 index 0000000000000..4581eee0e5337 --- /dev/null +++ b/lib/iomaps.h @@ -0,0 +1,12 @@ +#ifndef _IOMAPS_H_ +#define _IOMAPS_H_ +#include "libcflat.h" + +struct iomap { + const char *type; + u32 nr; + u32 addrs[64]; +}; + +struct iomap *iomaps_find(const char *type); +#endif diff --git a/scripts/gen-devtree-iomaps.pl b/scripts/gen-devtree-iomaps.pl new file mode 100755 index 0000000000000..91fa83d521839 --- /dev/null +++ b/scripts/gen-devtree-iomaps.pl @@ -0,0 +1,81 @@ +#!/usr/bin/perl -w +use strict; + +my $fdt = shift @ARGV; +my @types = @ARGV; +my $max_nr = 64; + +if (!defined $fdt || $#types < 0) { + print STDERR "Usage: gen-devtree-iomaps ". + "<fdt-file|-> <addr-type> [addr-types...]\n"; + exit 1; +} + +my @dtb; +if ($fdt eq '-') { + @dtb = <STDIN>; +} else { + open F, "<$fdt" or die "can't read $fdt: $!"; + @dtb = <F>; + close F; +} + +my $g = (join '@|', @types) . '@'; +@dtb = grep { /$g/ } @dtb; +foreach (@dtb) { + chomp($_); + s/^\s*//, s/\s*{$//; +} + +my %iomaps; +foreach (@dtb) { + my ($type, $addr) = split /@/, $_; + if (!exists $iomaps{$type}) { + $iomaps{$type} = [$addr]; + } else { + push $iomaps{$type}, $addr; + } +} + +print <<EOF; +/* + * Generated file. See gen-devtree-iomaps.pl + */ +#include "iomaps.h" +EOF +print "\nstruct iomap iomaps[] = {\n"; +foreach my $type (keys %iomaps) { + @{ $iomaps{$type} } = sort @{ $iomaps{$type} }; + my $nr = $#{ $iomaps{$type} } + 1; + if ($nr > $max_nr) { + print STDERR "$type has $nr addrs, but iomaps can only ". + "support up to $max_nr.\n"; + $nr = $max_nr; + splice @{ $iomaps{$type} }, $nr; + } + print "{\n"; + print " .type = \"$type\",\n"; + print " .nr = $nr,\n"; + print " .addrs = {"; + if ($nr < 5) { + my $line = join ', 0x', @{ $iomaps{$type} }; + print " 0x$line, },\n"; + print "},\n"; + next; + } + print "\n"; + for (my $i = 0; $i < $nr; $i += 5) { + print "\t"; + my $j = $i; + while ($j < $i + 4 && $j < $nr - 1) { + print "0x$iomaps{$type}[$j], "; + ++$j; + } + print "0x$iomaps{$type}[$j],\n"; + } + print " },\n"; + print "},\n"; +} +print "{\n .type = NULL,\n},\n"; +print "};\n"; +exit 0; -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 5/9] Add halt() and some error codes 2013-10-14 16:23 [PATCH 0/9] kvm-unit-tests/arm: initial drop Andrew Jones ` (3 preceding siblings ...) 2013-10-14 16:23 ` [PATCH 4/9] Introduce a simple iomap structure Andrew Jones @ 2013-10-14 16:23 ` Andrew Jones 2013-10-14 16:23 ` [PATCH 6/9] Introduce virtio-testdev Andrew Jones ` (5 subsequent siblings) 10 siblings, 0 replies; 38+ messages in thread From: Andrew Jones @ 2013-10-14 16:23 UTC (permalink / raw) To: kvm; +Cc: kvmarm, gleb, christoffer.dall Add a halt function that can be used by the test infrastructure 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 using its return address. Signed-off-by: Andrew Jones <drjones@redhat.com> --- lib/errno.h | 15 +++++++++++++++ lib/libcflat.h | 2 ++ lib/x86/io.c | 6 ++++++ 3 files changed, 23 insertions(+) create mode 100644 lib/errno.h diff --git a/lib/errno.h b/lib/errno.h new file mode 100644 index 0000000000000..4c7478229baf3 --- /dev/null +++ b/lib/errno.h @@ -0,0 +1,15 @@ +#ifndef _ERRNO_H_ +#define _ERRNO_H_ +/* + * Define some error codes for the test infrastructure's use. + * (Ab)use the standard E* names for syntax highlighting... + */ +#define MAXERR 127 /* exit(-1) */ +#define EINTR (MAXERR - 1) /* unhandled exception */ +#define EIO (MAXERR - 2) /* I/O error */ +#define ENXIO (MAXERR - 3) /* no serial */ +#define ENOEXEC (MAXERR - 4) /* bad test file format */ +#define ENOMEM (MAXERR - 5) /* Out of memory */ +#define ENODEV (MAXERR - 6) /* no testdev device */ +#define EINVAL (MAXERR - 7) /* Invalid argument */ +#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 diff --git a/lib/x86/io.c b/lib/x86/io.c index d3b971ef67b0e..7a36c9ca0c951 100644 --- a/lib/x86/io.c +++ b/lib/x86/io.c @@ -1,4 +1,5 @@ #include "libcflat.h" +#include "processor.h" #include "smp.h" #include "io.h" #ifndef USE_SERIAL @@ -81,3 +82,8 @@ void exit(int code) asm volatile("out %0, %1" : : "a"(code), "d"((short)0xf4)); #endif } + +void halt(int code) +{ + safe_halt(); +} -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 6/9] Introduce virtio-testdev 2013-10-14 16:23 [PATCH 0/9] kvm-unit-tests/arm: initial drop Andrew Jones ` (4 preceding siblings ...) 2013-10-14 16:23 ` [PATCH 5/9] Add halt() and some error codes Andrew Jones @ 2013-10-14 16:23 ` Andrew Jones 2013-10-15 8:39 ` Andrew Jones ` (2 more replies) 2013-10-14 16:23 ` [PATCH 7/9] arm: replace arbitrary divisions Andrew Jones ` (4 subsequent siblings) 10 siblings, 3 replies; 38+ messages in thread From: Andrew Jones @ 2013-10-14 16:23 UTC (permalink / raw) To: kvm; +Cc: kvmarm, gleb, christoffer.dall 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> --- lib/bswap.h | 7 +++ lib/libcflat.h | 10 ++++ lib/virtio-testdev.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/virtio-testdev.h | 9 ++++ 4 files changed, 152 insertions(+) create mode 100644 lib/bswap.h create mode 100644 lib/virtio-testdev.c create mode 100644 lib/virtio-testdev.h diff --git a/lib/bswap.h b/lib/bswap.h new file mode 100644 index 0000000000000..e63c4d37a8b9a --- /dev/null +++ b/lib/bswap.h @@ -0,0 +1,7 @@ +#ifndef _BSWAP_H_ +#define _BSWAP_H_ +#define le32_to_cpu(x) (x) +#define cpu_to_le32(x) (x) +#define le16_to_cpu(x) (x) +#define cpu_to_le16(x) (x) +#endif diff --git a/lib/libcflat.h b/lib/libcflat.h index a1be635ab4ee9..41791194657d0 100644 --- a/lib/libcflat.h +++ b/lib/libcflat.h @@ -37,6 +37,16 @@ typedef _Bool bool; #define true 1 #define false 0 +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; +} + extern void halt(int code); extern void exit(int code); diff --git a/lib/virtio-testdev.c b/lib/virtio-testdev.c new file mode 100644 index 0000000000000..900921302c344 --- /dev/null +++ b/lib/virtio-testdev.c @@ -0,0 +1,126 @@ +#include "libcflat.h" +#include "iomaps.h" +#include "bswap.h" + +#define TESTDEV_MAJOR_VER 1 +#define TESTDEV_MINOR_VER 1 + +#define VIRTIO_MMIO_DEVICEID 0x8 +#define VIRTIO_ID_TESTDEV 0xffff +#define DEV_CONFIG_BASE 0x100 +#define DEV_CONFIG_SIZE 0x100 + +enum { VERSION = 1, CLEAR, EXIT, }; +enum { TOKEN, NARGS, NRETS, ARG1, ARG2, ARG3, ARG4, }; + +#define RET1(nargs) (ARG1 + (nargs) + 0) +#define RET2(nargs) (ARG1 + (nargs) + 1) +#define RET3(nargs) (ARG1 + (nargs) + 2) +#define RET4(nargs) (ARG1 + (nargs) + 3) + +static u32 *testdev_base; + +/* + * 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 base[0]) 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, ...) +{ + volatile u32 *base = testdev_base; + volatile u32 *tdp = base + 1; + va_list va; + + if (!testdev_base) + return; + + *tdp++ = cpu_to_le32(nargs); + *tdp++ = cpu_to_le32(nrets); + + va_start(va, nrets); + + while (nargs--) + *tdp++ = cpu_to_le32(va_arg(va, unsigned)); + + /* this runs the op, but then resets base[0] to zero */ + base[0] = cpu_to_le32(token); + + /* sanity check */ + if (base[0] != 0) { + printf("virtio-testdev base[0] should always be zero!\n"); + halt(EIO); + } + + while (nrets--) { + u32 *r = va_arg(va, unsigned *); + *r = le32_to_cpu(*tdp++); + } + + 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) +{ + struct iomap *m; + u32 version, i; + u16 major, minor; + + m = iomaps_find("virtio_mmio"); + if (!m) { + printf("No virtio-mmio transports for virtio-testdev found!\n"); + halt(ENODEV); + } + + for (i = 0; i < m->nr; ++i) { + volatile u32 *base = (u32 *)compat_ptr(m->addrs[i]); + u32 devid32 = base[VIRTIO_MMIO_DEVICEID / 4]; + u16 devid = devid32 & 0xffff; + devid = le16_to_cpu(devid); + if (devid == VIRTIO_ID_TESTDEV) { + testdev_base = (u32 *)compat_ptr(m->addrs[i] + DEV_CONFIG_BASE); + break; + } + } + + if (!testdev_base) { + 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("Refusing to run with 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 -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH 6/9] Introduce virtio-testdev 2013-10-14 16:23 ` [PATCH 6/9] Introduce virtio-testdev Andrew Jones @ 2013-10-15 8:39 ` Andrew Jones 2013-10-17 1:06 ` Christoffer Dall 2013-10-17 1:06 ` Christoffer Dall 2 siblings, 0 replies; 38+ messages in thread From: Andrew Jones @ 2013-10-15 8:39 UTC (permalink / raw) To: kvm; +Cc: kvmarm, gleb, christoffer.dall On Mon, Oct 14, 2013 at 06:23:32PM +0200, 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> > --- > lib/bswap.h | 7 +++ > lib/libcflat.h | 10 ++++ > lib/virtio-testdev.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++ > lib/virtio-testdev.h | 9 ++++ > 4 files changed, 152 insertions(+) > create mode 100644 lib/bswap.h > create mode 100644 lib/virtio-testdev.c > create mode 100644 lib/virtio-testdev.h > > diff --git a/lib/bswap.h b/lib/bswap.h > new file mode 100644 > index 0000000000000..e63c4d37a8b9a > --- /dev/null > +++ b/lib/bswap.h > @@ -0,0 +1,7 @@ > +#ifndef _BSWAP_H_ > +#define _BSWAP_H_ > +#define le32_to_cpu(x) (x) > +#define cpu_to_le32(x) (x) > +#define le16_to_cpu(x) (x) > +#define cpu_to_le16(x) (x) > +#endif > diff --git a/lib/libcflat.h b/lib/libcflat.h > index a1be635ab4ee9..41791194657d0 100644 > --- a/lib/libcflat.h > +++ b/lib/libcflat.h > @@ -37,6 +37,16 @@ typedef _Bool bool; > #define true 1 > #define false 0 > > +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; > +} > + > extern void halt(int code); > extern void exit(int code); > > diff --git a/lib/virtio-testdev.c b/lib/virtio-testdev.c > new file mode 100644 > index 0000000000000..900921302c344 > --- /dev/null > +++ b/lib/virtio-testdev.c > @@ -0,0 +1,126 @@ > +#include "libcflat.h" > +#include "iomaps.h" > +#include "bswap.h" > + > +#define TESTDEV_MAJOR_VER 1 > +#define TESTDEV_MINOR_VER 1 > + > +#define VIRTIO_MMIO_DEVICEID 0x8 > +#define VIRTIO_ID_TESTDEV 0xffff > +#define DEV_CONFIG_BASE 0x100 > +#define DEV_CONFIG_SIZE 0x100 > + > +enum { VERSION = 1, CLEAR, EXIT, }; > +enum { TOKEN, NARGS, NRETS, ARG1, ARG2, ARG3, ARG4, }; > + > +#define RET1(nargs) (ARG1 + (nargs) + 0) > +#define RET2(nargs) (ARG1 + (nargs) + 1) > +#define RET3(nargs) (ARG1 + (nargs) + 2) > +#define RET4(nargs) (ARG1 + (nargs) + 3) > + > +static u32 *testdev_base; > + > +/* > + * 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 base[0]) 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, ...) > +{ > + volatile u32 *base = testdev_base; > + volatile u32 *tdp = base + 1; > + va_list va; > + > + if (!testdev_base) > + return; > + > + *tdp++ = cpu_to_le32(nargs); > + *tdp++ = cpu_to_le32(nrets); > + > + va_start(va, nrets); > + > + while (nargs--) > + *tdp++ = cpu_to_le32(va_arg(va, unsigned)); > + > + /* this runs the op, but then resets base[0] to zero */ > + base[0] = cpu_to_le32(token); > + > + /* sanity check */ > + if (base[0] != 0) { > + printf("virtio-testdev base[0] should always be zero!\n"); > + halt(EIO); > + } > + > + while (nrets--) { > + u32 *r = va_arg(va, unsigned *); > + *r = le32_to_cpu(*tdp++); > + } > + > + 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) > +{ > + struct iomap *m; > + u32 version, i; > + u16 major, minor; > + > + m = iomaps_find("virtio_mmio"); > + if (!m) { > + printf("No virtio-mmio transports for virtio-testdev found!\n"); > + halt(ENODEV); > + } > + > + for (i = 0; i < m->nr; ++i) { > + volatile u32 *base = (u32 *)compat_ptr(m->addrs[i]); > + u32 devid32 = base[VIRTIO_MMIO_DEVICEID / 4]; > + u16 devid = devid32 & 0xffff; > + devid = le16_to_cpu(devid); > + if (devid == VIRTIO_ID_TESTDEV) { Argh, I was just looking back over this file, and now see that I screwed up here. It should of course be u32 devid32 = le32_to_cpu(base[VIRTIO_MMIO_DEVICEID / 4]); u16 devid = devid32 & 0xffff; I'll need to send a v2 for this, but I'll wait a bit for other comments to roll in before doing so. drew > + testdev_base = (u32 *)compat_ptr(m->addrs[i] + DEV_CONFIG_BASE); > + break; > + } > + } > + > + if (!testdev_base) { > + 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("Refusing to run with 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 > -- > 1.8.1.4 > ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 6/9] Introduce virtio-testdev 2013-10-14 16:23 ` [PATCH 6/9] Introduce virtio-testdev Andrew Jones 2013-10-15 8:39 ` Andrew Jones @ 2013-10-17 1:06 ` Christoffer Dall 2013-10-17 9:51 ` Andrew Jones 2013-10-17 1:06 ` Christoffer Dall 2 siblings, 1 reply; 38+ messages in thread From: Christoffer Dall @ 2013-10-17 1:06 UTC (permalink / raw) To: Andrew Jones; +Cc: kvm, kvmarm, gleb On Mon, Oct 14, 2013 at 06:23:32PM +0200, 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> > --- > lib/bswap.h | 7 +++ > lib/libcflat.h | 10 ++++ > lib/virtio-testdev.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++ > lib/virtio-testdev.h | 9 ++++ > 4 files changed, 152 insertions(+) > create mode 100644 lib/bswap.h > create mode 100644 lib/virtio-testdev.c > create mode 100644 lib/virtio-testdev.h > > diff --git a/lib/bswap.h b/lib/bswap.h > new file mode 100644 > index 0000000000000..e63c4d37a8b9a > --- /dev/null > +++ b/lib/bswap.h > @@ -0,0 +1,7 @@ > +#ifndef _BSWAP_H_ > +#define _BSWAP_H_ > +#define le32_to_cpu(x) (x) > +#define cpu_to_le32(x) (x) > +#define le16_to_cpu(x) (x) > +#define cpu_to_le16(x) (x) > +#endif > diff --git a/lib/libcflat.h b/lib/libcflat.h > index a1be635ab4ee9..41791194657d0 100644 > --- a/lib/libcflat.h > +++ b/lib/libcflat.h > @@ -37,6 +37,16 @@ typedef _Bool bool; > #define true 1 > #define false 0 > > +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; > +} > + > extern void halt(int code); > extern void exit(int code); > > diff --git a/lib/virtio-testdev.c b/lib/virtio-testdev.c > new file mode 100644 > index 0000000000000..900921302c344 > --- /dev/null > +++ b/lib/virtio-testdev.c There's an interesting mix of space and tab indentations in this file... I assume using the kernel coding style would be approprate here... Actually, that could be added to the readme too. (Or whichever format we choose). Could you fix? > @@ -0,0 +1,126 @@ > +#include "libcflat.h" > +#include "iomaps.h" > +#include "bswap.h" > + > +#define TESTDEV_MAJOR_VER 1 > +#define TESTDEV_MINOR_VER 1 > + > +#define VIRTIO_MMIO_DEVICEID 0x8 > +#define VIRTIO_ID_TESTDEV 0xffff > +#define DEV_CONFIG_BASE 0x100 > +#define DEV_CONFIG_SIZE 0x100 > + > +enum { VERSION = 1, CLEAR, EXIT, }; > +enum { TOKEN, NARGS, NRETS, ARG1, ARG2, ARG3, ARG4, }; > + > +#define RET1(nargs) (ARG1 + (nargs) + 0) > +#define RET2(nargs) (ARG1 + (nargs) + 1) > +#define RET3(nargs) (ARG1 + (nargs) + 2) > +#define RET4(nargs) (ARG1 + (nargs) + 3) > + > +static u32 *testdev_base; > + > +/* > + * 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 base[0]) 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, ...) > +{ > + volatile u32 *base = testdev_base; > + volatile u32 *tdp = base + 1; > + va_list va; > + > + if (!testdev_base) > + return; > + > + *tdp++ = cpu_to_le32(nargs); > + *tdp++ = cpu_to_le32(nrets); > + > + va_start(va, nrets); > + > + while (nargs--) > + *tdp++ = cpu_to_le32(va_arg(va, unsigned)); > + > + /* this runs the op, but then resets base[0] to zero */ > + base[0] = cpu_to_le32(token); > + > + /* sanity check */ > + if (base[0] != 0) { > + printf("virtio-testdev base[0] should always be zero!\n"); > + halt(EIO); > + } > + > + while (nrets--) { > + u32 *r = va_arg(va, unsigned *); > + *r = le32_to_cpu(*tdp++); > + } > + > + 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) > +{ > + struct iomap *m; > + u32 version, i; > + u16 major, minor; > + > + m = iomaps_find("virtio_mmio"); > + if (!m) { > + printf("No virtio-mmio transports for virtio-testdev found!\n"); > + halt(ENODEV); > + } > + > + for (i = 0; i < m->nr; ++i) { > + volatile u32 *base = (u32 *)compat_ptr(m->addrs[i]); > + u32 devid32 = base[VIRTIO_MMIO_DEVICEID / 4]; do we have readl/writel in this framework? If not, maybe we should to indicate IO read/writes and ensure the compiler doesn't reorder things and that we have the necessary memory barriers etc...? That would apply to virtio_testdev above as well. > + u16 devid = devid32 & 0xffff; > + devid = le16_to_cpu(devid); > + if (devid == VIRTIO_ID_TESTDEV) { > + testdev_base = (u32 *)compat_ptr(m->addrs[i] + DEV_CONFIG_BASE); > + break; > + } > + } > + > + if (!testdev_base) { > + 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("Refusing to run with virtio-testdev major = %d, minor = %d\n", > + major, minor); "Refusing to run"? How about "incompatible version of virtio-testdev"? > + 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 > -- > 1.8.1.4 > ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 6/9] Introduce virtio-testdev 2013-10-17 1:06 ` Christoffer Dall @ 2013-10-17 9:51 ` Andrew Jones 2013-10-17 19:01 ` Christoffer Dall 0 siblings, 1 reply; 38+ messages in thread From: Andrew Jones @ 2013-10-17 9:51 UTC (permalink / raw) To: Christoffer Dall; +Cc: kvm, kvmarm, gleb On Wed, Oct 16, 2013 at 06:06:14PM -0700, Christoffer Dall wrote: > There's an interesting mix of space and tab indentations in this file... > > I assume using the kernel coding style would be approprate here... > Actually, that could be added to the readme too. (Or whichever format we > choose). > > Could you fix? I was attempting to adopt the style from the common code lib/*, see lib/string.c, lib/printf.c, lib/argv,c. The style used there is 1. 'four spaces' 2. 'tab' 3. 'tab + four spaces' 4. 'tab + tab' ... However, I'd actually prefer to use the kernel style as well, and I see that not even those three common files are consistent. argv.c only uses spaces. Other x86 files also have a variety of styles (kernel style being one of them). So probably the best choice is to go with kernel style, and to add another cleanup patch that changes lib/* files as well. > > + for (i = 0; i < m->nr; ++i) { > > + volatile u32 *base = (u32 *)compat_ptr(m->addrs[i]); > > + u32 devid32 = base[VIRTIO_MMIO_DEVICEID / 4]; > > do we have readl/writel in this framework? If not, maybe we should to > indicate IO read/writes and ensure the compiler doesn't reorder things > and that we have the necessary memory barriers etc...? > > That would apply to virtio_testdev above as well. OK, I agree it makes sense to add readl and writel in. I'll do that, and then rework my mmio reads to use them. > + printf("Refusing to run with virtio-testdev major = %d, minor = %d\n", > + major, minor); > "Refusing to run"? > How about "incompatible version of virtio-testdev"? Sure. OK. drew ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 6/9] Introduce virtio-testdev 2013-10-17 9:51 ` Andrew Jones @ 2013-10-17 19:01 ` Christoffer Dall 0 siblings, 0 replies; 38+ messages in thread From: Christoffer Dall @ 2013-10-17 19:01 UTC (permalink / raw) To: Andrew Jones; +Cc: kvm, kvmarm, gleb On Thu, Oct 17, 2013 at 11:51:26AM +0200, Andrew Jones wrote: > On Wed, Oct 16, 2013 at 06:06:14PM -0700, Christoffer Dall wrote: > > There's an interesting mix of space and tab indentations in this file... > > > > I assume using the kernel coding style would be approprate here... > > Actually, that could be added to the readme too. (Or whichever format we > > choose). > > > > Could you fix? > > I was attempting to adopt the style from the common code lib/*, see > lib/string.c, lib/printf.c, lib/argv,c. The style used there is > > 1. 'four spaces' > 2. 'tab' > 3. 'tab + four spaces' > 4. 'tab + tab' > ... that sounds like the most horrible broken coding style I have ever heard of. At least it reads like sh*t in mutt. > > However, I'd actually prefer to use the kernel style as well, and I see > that not even those three common files are consistent. argv.c only uses > spaces. Other x86 files also have a variety of styles (kernel style > being one of them). So probably the best choice is to go with kernel > style, and to add another cleanup patch that changes lib/* files as > well. > > > > + for (i = 0; i < m->nr; ++i) { > > > + volatile u32 *base = (u32 *)compat_ptr(m->addrs[i]); > > > + u32 devid32 = base[VIRTIO_MMIO_DEVICEID / 4]; Yeah, I think it's is by far the easiest and most convenient for everyone. > > > > do we have readl/writel in this framework? If not, maybe we should to > > indicate IO read/writes and ensure the compiler doesn't reorder things > > and that we have the necessary memory barriers etc...? > > > > That would apply to virtio_testdev above as well. > > OK, I agree it makes sense to add readl and writel in. I'll do that, and > then rework my mmio reads to use them. > > > + printf("Refusing to run with virtio-testdev major = %d, minor = %d\n", > > + major, minor); > > > "Refusing to run"? > > How about "incompatible version of virtio-testdev"? > > Sure. OK. > > drew ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 6/9] Introduce virtio-testdev 2013-10-14 16:23 ` [PATCH 6/9] Introduce virtio-testdev Andrew Jones 2013-10-15 8:39 ` Andrew Jones 2013-10-17 1:06 ` Christoffer Dall @ 2013-10-17 1:06 ` Christoffer Dall 2 siblings, 0 replies; 38+ messages in thread From: Christoffer Dall @ 2013-10-17 1:06 UTC (permalink / raw) To: Andrew Jones; +Cc: kvm, kvmarm, gleb On Mon, Oct 14, 2013 at 06:23:32PM +0200, 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> > --- > lib/bswap.h | 7 +++ > lib/libcflat.h | 10 ++++ > lib/virtio-testdev.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++ > lib/virtio-testdev.h | 9 ++++ > 4 files changed, 152 insertions(+) > create mode 100644 lib/bswap.h > create mode 100644 lib/virtio-testdev.c > create mode 100644 lib/virtio-testdev.h > > diff --git a/lib/bswap.h b/lib/bswap.h > new file mode 100644 > index 0000000000000..e63c4d37a8b9a > --- /dev/null > +++ b/lib/bswap.h > @@ -0,0 +1,7 @@ > +#ifndef _BSWAP_H_ > +#define _BSWAP_H_ > +#define le32_to_cpu(x) (x) > +#define cpu_to_le32(x) (x) > +#define le16_to_cpu(x) (x) > +#define cpu_to_le16(x) (x) > +#endif > diff --git a/lib/libcflat.h b/lib/libcflat.h > index a1be635ab4ee9..41791194657d0 100644 > --- a/lib/libcflat.h > +++ b/lib/libcflat.h > @@ -37,6 +37,16 @@ typedef _Bool bool; > #define true 1 > #define false 0 > > +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; > +} > + > extern void halt(int code); > extern void exit(int code); > > diff --git a/lib/virtio-testdev.c b/lib/virtio-testdev.c > new file mode 100644 > index 0000000000000..900921302c344 > --- /dev/null > +++ b/lib/virtio-testdev.c There's an interesting mix of space and tab indentations in this file... I assume using the kernel coding style would be approprate here... Actually, that could be added to the readme too. (Or whichever format we choose). Could you fix? > @@ -0,0 +1,126 @@ > +#include "libcflat.h" > +#include "iomaps.h" > +#include "bswap.h" > + > +#define TESTDEV_MAJOR_VER 1 > +#define TESTDEV_MINOR_VER 1 > + > +#define VIRTIO_MMIO_DEVICEID 0x8 > +#define VIRTIO_ID_TESTDEV 0xffff > +#define DEV_CONFIG_BASE 0x100 > +#define DEV_CONFIG_SIZE 0x100 > + > +enum { VERSION = 1, CLEAR, EXIT, }; > +enum { TOKEN, NARGS, NRETS, ARG1, ARG2, ARG3, ARG4, }; > + > +#define RET1(nargs) (ARG1 + (nargs) + 0) > +#define RET2(nargs) (ARG1 + (nargs) + 1) > +#define RET3(nargs) (ARG1 + (nargs) + 2) > +#define RET4(nargs) (ARG1 + (nargs) + 3) > + > +static u32 *testdev_base; > + > +/* > + * 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 base[0]) 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, ...) > +{ > + volatile u32 *base = testdev_base; > + volatile u32 *tdp = base + 1; > + va_list va; > + > + if (!testdev_base) > + return; > + > + *tdp++ = cpu_to_le32(nargs); > + *tdp++ = cpu_to_le32(nrets); > + > + va_start(va, nrets); > + > + while (nargs--) > + *tdp++ = cpu_to_le32(va_arg(va, unsigned)); > + > + /* this runs the op, but then resets base[0] to zero */ > + base[0] = cpu_to_le32(token); > + > + /* sanity check */ > + if (base[0] != 0) { > + printf("virtio-testdev base[0] should always be zero!\n"); > + halt(EIO); > + } > + > + while (nrets--) { > + u32 *r = va_arg(va, unsigned *); > + *r = le32_to_cpu(*tdp++); > + } > + > + 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) > +{ > + struct iomap *m; > + u32 version, i; > + u16 major, minor; > + > + m = iomaps_find("virtio_mmio"); > + if (!m) { > + printf("No virtio-mmio transports for virtio-testdev found!\n"); > + halt(ENODEV); > + } > + > + for (i = 0; i < m->nr; ++i) { > + volatile u32 *base = (u32 *)compat_ptr(m->addrs[i]); > + u32 devid32 = base[VIRTIO_MMIO_DEVICEID / 4]; do we have readl/writel in this framework? If not, maybe we should to indicate IO read/writes and ensure the compiler doesn't reorder things and that we have the necessary memory barriers etc...? That would apply to virtio_testdev above as well. > + u16 devid = devid32 & 0xffff; > + devid = le16_to_cpu(devid); > + if (devid == VIRTIO_ID_TESTDEV) { > + testdev_base = (u32 *)compat_ptr(m->addrs[i] + DEV_CONFIG_BASE); > + break; > + } > + } > + > + if (!testdev_base) { > + 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("Refusing to run with virtio-testdev major = %d, minor = %d\n", > + major, minor); "Refusing to run"? How about "incompatible version of virtio-testdev"? > + 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 > -- > 1.8.1.4 > ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 7/9] arm: replace arbitrary divisions 2013-10-14 16:23 [PATCH 0/9] kvm-unit-tests/arm: initial drop Andrew Jones ` (5 preceding siblings ...) 2013-10-14 16:23 ` [PATCH 6/9] Introduce virtio-testdev Andrew Jones @ 2013-10-14 16:23 ` Andrew Jones 2013-10-17 1:06 ` Christoffer Dall 2013-10-14 16:23 ` [PATCH 8/9] arm: initial drop Andrew Jones ` (3 subsequent siblings) 10 siblings, 1 reply; 38+ messages in thread From: Andrew Jones @ 2013-10-14 16:23 UTC (permalink / raw) To: kvm; +Cc: kvmarm, gleb, christoffer.dall arm can't do arbitrary divisions without software support. Usually libgcc would jump in here, but depending on the toolchain used that may or may not work. Luckily, we only care about two types of divisions. Divide by 10 and divide by 16. Divide by 16 is already covered by gcc since it's a power of two. Divide by 10 can be hacked up using a multiplication and shift. Signed-off-by: Andrew Jones <drjones@redhat.com> --- lib/divmod.h | 20 ++++++++++++++++++++ lib/printf.c | 27 ++++++++++++++------------- 2 files changed, 34 insertions(+), 13 deletions(-) create mode 100644 lib/divmod.h diff --git a/lib/divmod.h b/lib/divmod.h new file mode 100644 index 0000000000000..c0f04d7d8386d --- /dev/null +++ b/lib/divmod.h @@ -0,0 +1,20 @@ +#ifndef _DIVMOD_H_ +#define _DIVMOD_H_ +#ifdef __arm__ +static inline long long div10(long long n) +{ + /* + * multiply n by 2^32/10 and the result of n/10 + * will be in the upper word + */ + return (n * 0x1999999aU) >> 32; +} +static inline int mod10(long long n) +{ + return n - div10(n) * 10; +} +#else +#define div10(n) ((n) / 10) +#define mod10(n) ((n) % 10) +#endif +#endif diff --git a/lib/printf.c b/lib/printf.c index 867eb1926f742..9fb8133868c7a 100644 --- a/lib/printf.c +++ b/lib/printf.c @@ -1,4 +1,5 @@ #include "libcflat.h" +#include "divmod.h" typedef struct pstream { char *buffer; @@ -23,7 +24,7 @@ void print_str(pstream_t *p, const char *s) static char digits[16] = "0123456789abcdef"; -void print_int(pstream_t *ps, long long n, int base) +void print_int(pstream_t *ps, long long n) { char buf[sizeof(long) * 3 + 2], *p = buf; int s = 0, i; @@ -34,8 +35,8 @@ void print_int(pstream_t *ps, long long n, int base) } while (n) { - *p++ = digits[n % base]; - n /= base; + *p++ = digits[mod10(n)]; + n = div10(n); } if (s) @@ -57,14 +58,14 @@ void print_int(pstream_t *ps, long long n, int base) print_str(ps, buf); } -void print_unsigned(pstream_t *ps, unsigned long long n, int base) +void print_unsigned(pstream_t *ps, unsigned long long n) { char buf[sizeof(long) * 3 + 1], *p = buf; int i; while (n) { - *p++ = digits[n % base]; - n /= base; + *p++ = digits[n % 16]; + n /= 16; } if (p == buf) @@ -116,32 +117,32 @@ int vsnprintf(char *buf, int size, const char *fmt, va_list va) case 'd': switch (nlong) { case 0: - print_int(&s, va_arg(va, int), 10); + print_int(&s, va_arg(va, int)); break; case 1: - print_int(&s, va_arg(va, long), 10); + print_int(&s, va_arg(va, long)); break; default: - print_int(&s, va_arg(va, long long), 10); + print_int(&s, va_arg(va, long long)); break; } break; case 'x': switch (nlong) { case 0: - print_unsigned(&s, va_arg(va, unsigned), 16); + print_unsigned(&s, va_arg(va, unsigned)); break; case 1: - print_unsigned(&s, va_arg(va, unsigned long), 16); + print_unsigned(&s, va_arg(va, unsigned long)); break; default: - print_unsigned(&s, va_arg(va, unsigned long long), 16); + print_unsigned(&s, va_arg(va, unsigned long long)); break; } break; case 'p': print_str(&s, "0x"); - print_unsigned(&s, (unsigned long)va_arg(va, void *), 16); + print_unsigned(&s, (unsigned long)va_arg(va, void *)); break; case 's': print_str(&s, va_arg(va, const char *)); -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH 7/9] arm: replace arbitrary divisions 2013-10-14 16:23 ` [PATCH 7/9] arm: replace arbitrary divisions Andrew Jones @ 2013-10-17 1:06 ` Christoffer Dall 2013-10-17 10:03 ` Andrew Jones 0 siblings, 1 reply; 38+ messages in thread From: Christoffer Dall @ 2013-10-17 1:06 UTC (permalink / raw) To: Andrew Jones; +Cc: kvm, kvmarm, gleb On Mon, Oct 14, 2013 at 06:23:33PM +0200, Andrew Jones wrote: > arm can't do arbitrary divisions without software support. Usually > libgcc would jump in here, but depending on the toolchain used that may > or may not work. Luckily, we only care about two types of divisions. > Divide by 10 and divide by 16. Divide by 16 is already covered by gcc > since it's a power of two. Divide by 10 can be hacked up using a > multiplication and shift. Isn't this just a matter of supplying a few libc implementations to handle div_by_0 and that sort? I'm pretty sure we had that working in the kvm-selftest for ARM thingy that allowed you to use the standard '/' operator in C code.... I suspect there will be more users of this eventually. Or wait, do you mean 'long long' operations by arbitrary? In that case, I'm less sure... A library implementation to support the operator would still be preferred IMHO. > > Signed-off-by: Andrew Jones <drjones@redhat.com> > --- > lib/divmod.h | 20 ++++++++++++++++++++ > lib/printf.c | 27 ++++++++++++++------------- > 2 files changed, 34 insertions(+), 13 deletions(-) > create mode 100644 lib/divmod.h > > diff --git a/lib/divmod.h b/lib/divmod.h > new file mode 100644 > index 0000000000000..c0f04d7d8386d > --- /dev/null > +++ b/lib/divmod.h > @@ -0,0 +1,20 @@ > +#ifndef _DIVMOD_H_ > +#define _DIVMOD_H_ > +#ifdef __arm__ > +static inline long long div10(long long n) > +{ > + /* > + * multiply n by 2^32/10 and the result of n/10 > + * will be in the upper word > + */ > + return (n * 0x1999999aU) >> 32; > +} > +static inline int mod10(long long n) > +{ > + return n - div10(n) * 10; > +} > +#else > +#define div10(n) ((n) / 10) > +#define mod10(n) ((n) % 10) > +#endif > +#endif > diff --git a/lib/printf.c b/lib/printf.c > index 867eb1926f742..9fb8133868c7a 100644 > --- a/lib/printf.c > +++ b/lib/printf.c > @@ -1,4 +1,5 @@ > #include "libcflat.h" > +#include "divmod.h" > > typedef struct pstream { > char *buffer; > @@ -23,7 +24,7 @@ void print_str(pstream_t *p, const char *s) > > static char digits[16] = "0123456789abcdef"; > > -void print_int(pstream_t *ps, long long n, int base) > +void print_int(pstream_t *ps, long long n) > { > char buf[sizeof(long) * 3 + 2], *p = buf; > int s = 0, i; > @@ -34,8 +35,8 @@ void print_int(pstream_t *ps, long long n, int base) > } > > while (n) { > - *p++ = digits[n % base]; > - n /= base; > + *p++ = digits[mod10(n)]; > + n = div10(n); > } > > if (s) > @@ -57,14 +58,14 @@ void print_int(pstream_t *ps, long long n, int base) > print_str(ps, buf); > } > > -void print_unsigned(pstream_t *ps, unsigned long long n, int base) > +void print_unsigned(pstream_t *ps, unsigned long long n) > { > char buf[sizeof(long) * 3 + 1], *p = buf; > int i; > > while (n) { > - *p++ = digits[n % base]; > - n /= base; > + *p++ = digits[n % 16]; > + n /= 16; > } > > if (p == buf) > @@ -116,32 +117,32 @@ int vsnprintf(char *buf, int size, const char *fmt, va_list va) > case 'd': > switch (nlong) { > case 0: > - print_int(&s, va_arg(va, int), 10); > + print_int(&s, va_arg(va, int)); > break; > case 1: > - print_int(&s, va_arg(va, long), 10); > + print_int(&s, va_arg(va, long)); > break; > default: > - print_int(&s, va_arg(va, long long), 10); > + print_int(&s, va_arg(va, long long)); > break; > } > break; > case 'x': > switch (nlong) { > case 0: > - print_unsigned(&s, va_arg(va, unsigned), 16); > + print_unsigned(&s, va_arg(va, unsigned)); > break; > case 1: > - print_unsigned(&s, va_arg(va, unsigned long), 16); > + print_unsigned(&s, va_arg(va, unsigned long)); > break; > default: > - print_unsigned(&s, va_arg(va, unsigned long long), 16); > + print_unsigned(&s, va_arg(va, unsigned long long)); > break; > } > break; > case 'p': > print_str(&s, "0x"); > - print_unsigned(&s, (unsigned long)va_arg(va, void *), 16); > + print_unsigned(&s, (unsigned long)va_arg(va, void *)); > break; > case 's': > print_str(&s, va_arg(va, const char *)); > -- > 1.8.1.4 > ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 7/9] arm: replace arbitrary divisions 2013-10-17 1:06 ` Christoffer Dall @ 2013-10-17 10:03 ` Andrew Jones 2013-10-17 18:59 ` Christoffer Dall 0 siblings, 1 reply; 38+ messages in thread From: Andrew Jones @ 2013-10-17 10:03 UTC (permalink / raw) To: Christoffer Dall; +Cc: kvm, kvmarm, gleb On Wed, Oct 16, 2013 at 06:06:29PM -0700, Christoffer Dall wrote: > On Mon, Oct 14, 2013 at 06:23:33PM +0200, Andrew Jones wrote: > > arm can't do arbitrary divisions without software support. Usually > > libgcc would jump in here, but depending on the toolchain used that may > > or may not work. Luckily, we only care about two types of divisions. > > Divide by 10 and divide by 16. Divide by 16 is already covered by gcc > > since it's a power of two. Divide by 10 can be hacked up using a > > multiplication and shift. > > Isn't this just a matter of supplying a few libc implementations to > handle div_by_0 and that sort? I'm pretty sure we had that working in > the kvm-selftest for ARM thingy that allowed you to use the standard '/' > operator in C code.... I suspect there will be more users of this > eventually. > > Or wait, do you mean 'long long' operations by arbitrary? In that case, > I'm less sure... A library implementation to support the operator would > still be preferred IMHO. No, that's not what I meant, nor can I pretend that's what I meant now :-) I saw that you had brought lib1funcs.S into kvm-selftest, but I'm not sure why I rejected doing the same thing... Probably because my reflex was to not adopt a bunch of assembler that I didn't want to maintain. But I guess there's nothing to maintain there. It works, and will always work. I'll switch to using it. drew ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 7/9] arm: replace arbitrary divisions 2013-10-17 10:03 ` Andrew Jones @ 2013-10-17 18:59 ` Christoffer Dall 0 siblings, 0 replies; 38+ messages in thread From: Christoffer Dall @ 2013-10-17 18:59 UTC (permalink / raw) To: Andrew Jones; +Cc: kvm, kvmarm, gleb On Thu, Oct 17, 2013 at 12:03:23PM +0200, Andrew Jones wrote: > On Wed, Oct 16, 2013 at 06:06:29PM -0700, Christoffer Dall wrote: > > On Mon, Oct 14, 2013 at 06:23:33PM +0200, Andrew Jones wrote: > > > arm can't do arbitrary divisions without software support. Usually > > > libgcc would jump in here, but depending on the toolchain used that may > > > or may not work. Luckily, we only care about two types of divisions. > > > Divide by 10 and divide by 16. Divide by 16 is already covered by gcc > > > since it's a power of two. Divide by 10 can be hacked up using a > > > multiplication and shift. > > > > Isn't this just a matter of supplying a few libc implementations to > > handle div_by_0 and that sort? I'm pretty sure we had that working in > > the kvm-selftest for ARM thingy that allowed you to use the standard '/' > > operator in C code.... I suspect there will be more users of this > > eventually. > > > > Or wait, do you mean 'long long' operations by arbitrary? In that case, > > I'm less sure... A library implementation to support the operator would > > still be preferred IMHO. > > No, that's not what I meant, nor can I pretend that's what I meant now :-) > I saw that you had brought lib1funcs.S into kvm-selftest, but I'm not sure > why I rejected doing the same thing... Probably because my reflex was to > not adopt a bunch of assembler that I didn't want to maintain. But I guess > there's nothing to maintain there. It works, and will always work. I'll > switch to using it. > I think so, and I'll gladly help you maintain those bits. -Christoffer ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 8/9] arm: initial drop 2013-10-14 16:23 [PATCH 0/9] kvm-unit-tests/arm: initial drop Andrew Jones ` (6 preceding siblings ...) 2013-10-14 16:23 ` [PATCH 7/9] arm: replace arbitrary divisions Andrew Jones @ 2013-10-14 16:23 ` Andrew Jones 2013-10-17 1:06 ` Christoffer Dall 2013-10-14 16:23 ` [PATCH 9/9] arm: add vectors support Andrew Jones ` (2 subsequent siblings) 10 siblings, 1 reply; 38+ messages in thread From: Andrew Jones @ 2013-10-14 16:23 UTC (permalink / raw) To: kvm; +Cc: kvmarm, gleb, christoffer.dall This is the initial arm test infrastructure and a first test that simply 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> --- arm/boot.c | 27 ++++++++++++++++++++ arm/cstart.S | 47 ++++++++++++++++++++++++++++++++++ arm/flat.lds | 18 +++++++++++++ arm/run | 19 ++++++++++++++ arm/unittests.cfg | 11 ++++++++ config/config-arm.mak | 62 +++++++++++++++++++++++++++++++++++++++++++++ configure | 10 ++++++-- lib/arm/bootinfo.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/arm/bootinfo.h | 19 ++++++++++++++ lib/arm/bswap.h | 30 ++++++++++++++++++++++ lib/arm/io.c | 26 +++++++++++++++++++ lib/bswap.h | 4 +++ lib/libcflat.h | 1 + 13 files changed, 342 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/bootinfo.c create mode 100644 lib/arm/bootinfo.h create mode 100644 lib/arm/bswap.h create mode 100644 lib/arm/io.c diff --git a/arm/boot.c b/arm/boot.c new file mode 100644 index 0000000000000..375e8708a7c54 --- /dev/null +++ b/arm/boot.c @@ -0,0 +1,27 @@ +#include "libcflat.h" +#include "arm/bootinfo.h" + +static bool info_check(u32 var, char *expected) +{ + char var_str[9]; + snprintf(var_str, 9, "%x", var); + while (*expected == '0' || *expected == 'x') + ++expected; + return !strcmp(var_str, expected); +} + +int main(int argc, char **argv) +{ + int ret = 0; + + if (argc < 3) { + printf("Not enough arguments. Can't test\n"); + return 1; + } + + if (!strcmp(argv[0], "info")) + ret = !info_check(mem32.size, argv[1]) + || !info_check(core.pagesize, argv[2]); + + return ret; +} diff --git a/arm/cstart.S b/arm/cstart.S new file mode 100644 index 0000000000000..a65809824d4f1 --- /dev/null +++ b/arm/cstart.S @@ -0,0 +1,47 @@ + +#define CR_B (1 << 7) + +.arm + +.section .init + +.globl start +start: + /* bootloader params are in r0-r2 */ + ldr sp, =stacktop + push { r0-r3 } @push r3 too for 8-byte alignment + + mrc p15, 0, r8, c1, c0, 0 @r8 = sctrl + bl get_endianness + bl io_init + + pop { r0-r3 } + bl read_bootinfo + bl __setup_args + ldr r0, =__argc + ldr r0, [r0] + ldr r1, =__argv + bl main + bl exit + b halt + +get_endianness: + and r0, r8, #CR_B + cmp r0, #0 + beq 1f + ldr r1, =cpu_is_be + mov r0, #1 + str r0, [r1] +1: mov pc, lr + +.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..fb78cd906839a --- /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 'info 0x10000000 0x1000' diff --git a/config/config-arm.mak b/config/config-arm.mak new file mode 100644 index 0000000000000..066b1f725c5b3 --- /dev/null +++ b/config/config-arm.mak @@ -0,0 +1,62 @@ +mach = mach-virt +iodevs = pl011 virtio_mmio +phys_base = 0x8000000 + +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/iomaps.o \ + lib/virtio-testdev.o \ + lib/arm/io.o \ + lib/arm/bootinfo.o + +$(libcflat): LDFLAGS += -nostdlib +$(libcflat): 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 = lib/libcflat.a $(libgcc) +%.elf: %.o $(FLATLIBS) arm/flat.lds + $(CC) $(CFLAGS) -nostdlib -o $@ \ + -Wl,-T,arm/flat.lds,--build-id=none,-Ttext=$(start_addr) \ + $(filter %.o, $^) $(FLATLIBS) + +%.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 \ + $(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/bootinfo.c b/lib/arm/bootinfo.c new file mode 100644 index 0000000000000..c362064f661d9 --- /dev/null +++ b/lib/arm/bootinfo.c @@ -0,0 +1,70 @@ +#include "libcflat.h" +#include "arm/bootinfo.h" +#include "arm/bswap.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 char *__args; + +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; + } +} + +#define __unused __attribute__((__unused__)) + +void read_bootinfo(u32 arg __unused, 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 *)((u32)start - KERNEL_OFFSET + ATAG_OFFSET); + } else if (info[1] == ATAG_CORE) + atags = info; + + read_atags(id, atags); +} diff --git a/lib/arm/bootinfo.h b/lib/arm/bootinfo.h new file mode 100644 index 0000000000000..9cf547e4cebeb --- /dev/null +++ b/lib/arm/bootinfo.h @@ -0,0 +1,19 @@ +#ifndef _BOOTINFO_H_ +#define _BOOTINFO_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/arm/bswap.h b/lib/arm/bswap.h new file mode 100644 index 0000000000000..9bd16e789fcc5 --- /dev/null +++ b/lib/arm/bswap.h @@ -0,0 +1,30 @@ +#ifndef _ARM_BSWAP_H_ +#define _ARM_BSWAP_H_ +#include "libcflat.h" + +extern bool cpu_is_be; + +static inline u32 bswap32(u32 val) +{ + u32 ret; + asm volatile("rev %0, %1" : "=r" (ret) : "r" (val)); + return ret; +} + +static inline u16 bswap16(u16 val) +{ + u16 ret; + asm volatile("rev16 %0, %1" : "=r" (ret) : "r" (val)); + return ret; +} + +#define be32_to_cpu(x) (cpu_is_be ? x : bswap32(x)) +#define cpu_to_be32(x) (cpu_is_be ? x : bswap32(x)) +#define be16_to_cpu(x) (cpu_is_be ? x : bswap16(x)) +#define cpu_to_be16(x) (cpu_is_be ? x : bswap16(x)) + +#define le32_to_cpu(x) (cpu_is_be ? bswap32(x) : x) +#define cpu_to_le32(x) (cpu_is_be ? bswap32(x) : x) +#define le16_to_cpu(x) (cpu_is_be ? bswap16(x) : x) +#define cpu_to_le16(x) (cpu_is_be ? bswap16(x) : x) +#endif diff --git a/lib/arm/io.c b/lib/arm/io.c new file mode 100644 index 0000000000000..951af60551a4c --- /dev/null +++ b/lib/arm/io.c @@ -0,0 +1,26 @@ +#include "libcflat.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(void) +{ + struct iomap *m = iomaps_find("pl011"); + if (!m) + halt(ENXIO); + uart0_base = (u8 *)compat_ptr(m->addrs[0]); + virtio_testdev_init(); +} diff --git a/lib/bswap.h b/lib/bswap.h index e63c4d37a8b9a..a428ed6c646dd 100644 --- a/lib/bswap.h +++ b/lib/bswap.h @@ -1,7 +1,11 @@ #ifndef _BSWAP_H_ #define _BSWAP_H_ +#ifdef __arm__ +#include "arm/bswap.h" +#else #define le32_to_cpu(x) (x) #define cpu_to_le32(x) (x) #define le16_to_cpu(x) (x) #define cpu_to_le16(x) (x) #endif +#endif diff --git a/lib/libcflat.h b/lib/libcflat.h index 41791194657d0..dce9a0f516e7e 100644 --- a/lib/libcflat.h +++ b/lib/libcflat.h @@ -55,6 +55,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); -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH 8/9] arm: initial drop 2013-10-14 16:23 ` [PATCH 8/9] arm: initial drop Andrew Jones @ 2013-10-17 1:06 ` Christoffer Dall 2013-10-17 10:16 ` Andrew Jones 0 siblings, 1 reply; 38+ messages in thread From: Christoffer Dall @ 2013-10-17 1:06 UTC (permalink / raw) To: Andrew Jones; +Cc: kvm, kvmarm, gleb On Mon, Oct 14, 2013 at 06:23:34PM +0200, Andrew Jones wrote: > This is the initial arm test infrastructure and a first test that > simply 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> > --- > arm/boot.c | 27 ++++++++++++++++++++ > arm/cstart.S | 47 ++++++++++++++++++++++++++++++++++ > arm/flat.lds | 18 +++++++++++++ > arm/run | 19 ++++++++++++++ > arm/unittests.cfg | 11 ++++++++ > config/config-arm.mak | 62 +++++++++++++++++++++++++++++++++++++++++++++ > configure | 10 ++++++-- > lib/arm/bootinfo.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ > lib/arm/bootinfo.h | 19 ++++++++++++++ > lib/arm/bswap.h | 30 ++++++++++++++++++++++ > lib/arm/io.c | 26 +++++++++++++++++++ > lib/bswap.h | 4 +++ > lib/libcflat.h | 1 + > 13 files changed, 342 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/bootinfo.c > create mode 100644 lib/arm/bootinfo.h > create mode 100644 lib/arm/bswap.h > create mode 100644 lib/arm/io.c > > diff --git a/arm/boot.c b/arm/boot.c > new file mode 100644 > index 0000000000000..375e8708a7c54 this file's indentation is also funny, you should really check your editor configuration :) > --- /dev/null > +++ b/arm/boot.c > @@ -0,0 +1,27 @@ > +#include "libcflat.h" > +#include "arm/bootinfo.h" > + > +static bool info_check(u32 var, char *expected) > +{ > + char var_str[9]; > + snprintf(var_str, 9, "%x", var); > + while (*expected == '0' || *expected == 'x') > + ++expected; > + return !strcmp(var_str, expected); > +} > + > +int main(int argc, char **argv) > +{ > + int ret = 0; > + > + if (argc < 3) { > + printf("Not enough arguments. Can't test\n"); > + return 1; > + } > + > + if (!strcmp(argv[0], "info")) > + ret = !info_check(mem32.size, argv[1]) > + || !info_check(core.pagesize, argv[2]); > + > + return ret; > +} I'm actually a little confused, when does this main get invoked and by whom and what are we testing for here? > diff --git a/arm/cstart.S b/arm/cstart.S > new file mode 100644 > index 0000000000000..a65809824d4f1 > --- /dev/null > +++ b/arm/cstart.S > @@ -0,0 +1,47 @@ > + > +#define CR_B (1 << 7) > + > +.arm > + > +.section .init > + > +.globl start > +start: > + /* bootloader params are in r0-r2 */ > + ldr sp, =stacktop > + push { r0-r3 } @push r3 too for 8-byte alignment > + > + mrc p15, 0, r8, c1, c0, 0 @r8 = sctrl > + bl get_endianness > + bl io_init > + > + pop { r0-r3 } > + bl read_bootinfo > + bl __setup_args > + ldr r0, =__argc > + ldr r0, [r0] > + ldr r1, =__argv > + bl main > + bl exit > + b halt > + > +get_endianness: > + and r0, r8, #CR_B > + cmp r0, #0 > + beq 1f > + ldr r1, =cpu_is_be > + mov r0, #1 > + str r0, [r1] > +1: mov pc, lr > + > +.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..fb78cd906839a > --- /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 'info 0x10000000 0x1000' > diff --git a/config/config-arm.mak b/config/config-arm.mak > new file mode 100644 > index 0000000000000..066b1f725c5b3 > --- /dev/null > +++ b/config/config-arm.mak > @@ -0,0 +1,62 @@ > +mach = mach-virt > +iodevs = pl011 virtio_mmio > +phys_base = 0x8000000 > + > +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/iomaps.o \ > + lib/virtio-testdev.o \ > + lib/arm/io.o \ > + lib/arm/bootinfo.o > + > +$(libcflat): LDFLAGS += -nostdlib > +$(libcflat): 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 = lib/libcflat.a $(libgcc) > +%.elf: %.o $(FLATLIBS) arm/flat.lds > + $(CC) $(CFLAGS) -nostdlib -o $@ \ > + -Wl,-T,arm/flat.lds,--build-id=none,-Ttext=$(start_addr) \ > + $(filter %.o, $^) $(FLATLIBS) > + > +%.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 \ > + $(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/bootinfo.c b/lib/arm/bootinfo.c > new file mode 100644 > index 0000000000000..c362064f661d9 > --- /dev/null > +++ b/lib/arm/bootinfo.c > @@ -0,0 +1,70 @@ > +#include "libcflat.h" > +#include "arm/bootinfo.h" > +#include "arm/bswap.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 char *__args; > + > +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; > + } > +} > + > +#define __unused __attribute__((__unused__)) > + > +void read_bootinfo(u32 arg __unused, 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 *)((u32)start - KERNEL_OFFSET + ATAG_OFFSET); > + } else if (info[1] == ATAG_CORE) > + atags = info; > + > + read_atags(id, atags); > +} > diff --git a/lib/arm/bootinfo.h b/lib/arm/bootinfo.h > new file mode 100644 > index 0000000000000..9cf547e4cebeb > --- /dev/null > +++ b/lib/arm/bootinfo.h > @@ -0,0 +1,19 @@ > +#ifndef _BOOTINFO_H_ > +#define _BOOTINFO_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/arm/bswap.h b/lib/arm/bswap.h > new file mode 100644 > index 0000000000000..9bd16e789fcc5 > --- /dev/null > +++ b/lib/arm/bswap.h > @@ -0,0 +1,30 @@ > +#ifndef _ARM_BSWAP_H_ > +#define _ARM_BSWAP_H_ > +#include "libcflat.h" > + > +extern bool cpu_is_be; > + > +static inline u32 bswap32(u32 val) > +{ > + u32 ret; > + asm volatile("rev %0, %1" : "=r" (ret) : "r" (val)); > + return ret; > +} > + > +static inline u16 bswap16(u16 val) > +{ > + u16 ret; > + asm volatile("rev16 %0, %1" : "=r" (ret) : "r" (val)); > + return ret; > +} > + > +#define be32_to_cpu(x) (cpu_is_be ? x : bswap32(x)) > +#define cpu_to_be32(x) (cpu_is_be ? x : bswap32(x)) > +#define be16_to_cpu(x) (cpu_is_be ? x : bswap16(x)) > +#define cpu_to_be16(x) (cpu_is_be ? x : bswap16(x)) > + > +#define le32_to_cpu(x) (cpu_is_be ? bswap32(x) : x) > +#define cpu_to_le32(x) (cpu_is_be ? bswap32(x) : x) > +#define le16_to_cpu(x) (cpu_is_be ? bswap16(x) : x) > +#define cpu_to_le16(x) (cpu_is_be ? bswap16(x) : x) > +#endif > diff --git a/lib/arm/io.c b/lib/arm/io.c > new file mode 100644 > index 0000000000000..951af60551a4c > --- /dev/null > +++ b/lib/arm/io.c > @@ -0,0 +1,26 @@ > +#include "libcflat.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(void) > +{ > + struct iomap *m = iomaps_find("pl011"); > + if (!m) > + halt(ENXIO); > + uart0_base = (u8 *)compat_ptr(m->addrs[0]); > + virtio_testdev_init(); > +} > diff --git a/lib/bswap.h b/lib/bswap.h > index e63c4d37a8b9a..a428ed6c646dd 100644 > --- a/lib/bswap.h > +++ b/lib/bswap.h > @@ -1,7 +1,11 @@ > #ifndef _BSWAP_H_ > #define _BSWAP_H_ > +#ifdef __arm__ > +#include "arm/bswap.h" > +#else > #define le32_to_cpu(x) (x) > #define cpu_to_le32(x) (x) > #define le16_to_cpu(x) (x) > #define cpu_to_le16(x) (x) > #endif > +#endif > diff --git a/lib/libcflat.h b/lib/libcflat.h > index 41791194657d0..dce9a0f516e7e 100644 > --- a/lib/libcflat.h > +++ b/lib/libcflat.h > @@ -55,6 +55,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); > -- > 1.8.1.4 > ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 8/9] arm: initial drop 2013-10-17 1:06 ` Christoffer Dall @ 2013-10-17 10:16 ` Andrew Jones 2013-10-17 13:28 ` Andrew Jones 0 siblings, 1 reply; 38+ messages in thread From: Andrew Jones @ 2013-10-17 10:16 UTC (permalink / raw) To: Christoffer Dall; +Cc: kvm, kvmarm, gleb On Wed, Oct 16, 2013 at 06:06:35PM -0700, Christoffer Dall wrote: > > diff --git a/arm/boot.c b/arm/boot.c > > new file mode 100644 > > index 0000000000000..375e8708a7c54 > > this file's indentation is also funny, you should really check your > editor configuration :) Actually the editor prefers kernel style, I had to keep trying to force the other style on it, and now see below that I wasn't always successful. '++expected' should have had just a tab, not a tab+4spaces... > > --- /dev/null > > +++ b/arm/boot.c > > @@ -0,0 +1,27 @@ > > +#include "libcflat.h" > > +#include "arm/bootinfo.h" > > + > > +static bool info_check(u32 var, char *expected) > > +{ > > + char var_str[9]; > > + snprintf(var_str, 9, "%x", var); > > + while (*expected == '0' || *expected == 'x') > > + ++expected; > > + return !strcmp(var_str, expected); > > +} > > + > > +int main(int argc, char **argv) > > +{ > > + int ret = 0; > > + > > + if (argc < 3) { > > + printf("Not enough arguments. Can't test\n"); > > + return 1; > > + } > > + > > + if (!strcmp(argv[0], "info")) > > + ret = !info_check(mem32.size, argv[1]) > > + || !info_check(core.pagesize, argv[2]); > > + > > + return ret; > > +} > > I'm actually a little confused, when does this main get invoked and by > whom and what are we testing for here? See cstart.S:start 'bl main' below for the who invokes. And arm/unittests.cfg, also below, for the (poorly documented) test case definition. You'll see we config the test to have 256G memory, and then here we confirm that we read the bootinfo correctly, i.e. it says 256G. There's also a check for pagesize, which isn't really necessary, but as that info comes from a different ATAG, it (sort of) checks something else. > > > diff --git a/arm/cstart.S b/arm/cstart.S > > new file mode 100644 > > index 0000000000000..a65809824d4f1 > > --- /dev/null > > +++ b/arm/cstart.S > > @@ -0,0 +1,47 @@ > > + > > +#define CR_B (1 << 7) > > + > > +.arm > > + > > +.section .init > > + > > +.globl start > > +start: > > + /* bootloader params are in r0-r2 */ > > + ldr sp, =stacktop > > + push { r0-r3 } @push r3 too for 8-byte alignment > > + > > + mrc p15, 0, r8, c1, c0, 0 @r8 = sctrl > > + bl get_endianness > > + bl io_init > > + > > + pop { r0-r3 } > > + bl read_bootinfo > > + bl __setup_args > > + ldr r0, =__argc > > + ldr r0, [r0] > > + ldr r1, =__argv > > + bl main > > + bl exit > > + b halt > > + > > +get_endianness: > > + and r0, r8, #CR_B > > + cmp r0, #0 > > + beq 1f > > + ldr r1, =cpu_is_be > > + mov r0, #1 > > + str r0, [r1] > > +1: mov pc, lr > > + > > +.text > > + > > +.globl halt > > +halt: > > +1: wfi > > + b 1b > > + > > +.data > > + > > +.globl cpu_is_be > > +cpu_is_be: .word 0 [snip] > > diff --git a/arm/unittests.cfg b/arm/unittests.cfg > > new file mode 100644 > > index 0000000000000..fb78cd906839a > > --- /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 'info 0x10000000 0x1000' > > diff --git a/config/config-arm.mak b/config/config-arm.mak [snip] drew ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 8/9] arm: initial drop 2013-10-17 10:16 ` Andrew Jones @ 2013-10-17 13:28 ` Andrew Jones 2013-10-17 18:39 ` Christoffer Dall 0 siblings, 1 reply; 38+ messages in thread From: Andrew Jones @ 2013-10-17 13:28 UTC (permalink / raw) To: Christoffer Dall; +Cc: kvm, kvmarm, gleb On Thu, Oct 17, 2013 at 12:16:18PM +0200, Andrew Jones wrote: > On Wed, Oct 16, 2013 at 06:06:35PM -0700, Christoffer Dall wrote: > > > diff --git a/arm/boot.c b/arm/boot.c > > > new file mode 100644 > > > index 0000000000000..375e8708a7c54 > > > > this file's indentation is also funny, you should really check your > > editor configuration :) > > Actually the editor prefers kernel style, I had to keep trying to > force the other style on it, and now see below that I wasn't always > successful. '++expected' should have had just a tab, not a > tab+4spaces... > > > > --- /dev/null > > > +++ b/arm/boot.c > > > @@ -0,0 +1,27 @@ > > > +#include "libcflat.h" > > > +#include "arm/bootinfo.h" > > > + > > > +static bool info_check(u32 var, char *expected) > > > +{ > > > + char var_str[9]; > > > + snprintf(var_str, 9, "%x", var); > > > + while (*expected == '0' || *expected == 'x') > > > + ++expected; > > > + return !strcmp(var_str, expected); > > > +} > > > + > > > +int main(int argc, char **argv) > > > +{ > > > + int ret = 0; > > > + > > > + if (argc < 3) { > > > + printf("Not enough arguments. Can't test\n"); > > > + return 1; > > > + } > > > + > > > + if (!strcmp(argv[0], "info")) > > > + ret = !info_check(mem32.size, argv[1]) > > > + || !info_check(core.pagesize, argv[2]); > > > + > > > + return ret; > > > +} > > > > I'm actually a little confused, when does this main get invoked and by > > whom and what are we testing for here? > > See cstart.S:start 'bl main' below for the who invokes. And > arm/unittests.cfg, also below, for the (poorly documented) test case > definition. You'll see we config the test to have 256G memory, and then > here we confirm that we read the bootinfo correctly, i.e. it says 256G. The above 'G's are of course 'M's. Who remapped my keyboard? drew ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 8/9] arm: initial drop 2013-10-17 13:28 ` Andrew Jones @ 2013-10-17 18:39 ` Christoffer Dall 0 siblings, 0 replies; 38+ messages in thread From: Christoffer Dall @ 2013-10-17 18:39 UTC (permalink / raw) To: Andrew Jones; +Cc: kvm, kvmarm, gleb On Thu, Oct 17, 2013 at 03:28:15PM +0200, Andrew Jones wrote: > On Thu, Oct 17, 2013 at 12:16:18PM +0200, Andrew Jones wrote: > > On Wed, Oct 16, 2013 at 06:06:35PM -0700, Christoffer Dall wrote: > > > > diff --git a/arm/boot.c b/arm/boot.c > > > > new file mode 100644 > > > > index 0000000000000..375e8708a7c54 > > > > > > this file's indentation is also funny, you should really check your > > > editor configuration :) > > > > Actually the editor prefers kernel style, I had to keep trying to > > force the other style on it, and now see below that I wasn't always > > successful. '++expected' should have had just a tab, not a > > tab+4spaces... > > > > > > --- /dev/null > > > > +++ b/arm/boot.c > > > > @@ -0,0 +1,27 @@ > > > > +#include "libcflat.h" > > > > +#include "arm/bootinfo.h" > > > > + > > > > +static bool info_check(u32 var, char *expected) > > > > +{ > > > > + char var_str[9]; > > > > + snprintf(var_str, 9, "%x", var); > > > > + while (*expected == '0' || *expected == 'x') > > > > + ++expected; > > > > + return !strcmp(var_str, expected); > > > > +} > > > > + > > > > +int main(int argc, char **argv) > > > > +{ > > > > + int ret = 0; > > > > + > > > > + if (argc < 3) { > > > > + printf("Not enough arguments. Can't test\n"); > > > > + return 1; > > > > + } > > > > + > > > > + if (!strcmp(argv[0], "info")) > > > > + ret = !info_check(mem32.size, argv[1]) > > > > + || !info_check(core.pagesize, argv[2]); > > > > + > > > > + return ret; > > > > +} > > > > > > I'm actually a little confused, when does this main get invoked and by > > > whom and what are we testing for here? > > > > See cstart.S:start 'bl main' below for the who invokes. And > > arm/unittests.cfg, also below, for the (poorly documented) test case > > definition. You'll see we config the test to have 256G memory, and then > > here we confirm that we read the bootinfo correctly, i.e. it says 256G. Thanks. > > The above 'G's are of course 'M's. Who remapped my keyboard? > That would be one swanky ARM board. -Chrsitoffer ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 9/9] arm: add vectors support 2013-10-14 16:23 [PATCH 0/9] kvm-unit-tests/arm: initial drop Andrew Jones ` (7 preceding siblings ...) 2013-10-14 16:23 ` [PATCH 8/9] arm: initial drop Andrew Jones @ 2013-10-14 16:23 ` Andrew Jones 2013-10-17 1:06 ` Christoffer Dall 2013-11-20 23:06 ` [PATCH 0/9] kvm-unit-tests/arm: initial drop María Soler Heredia 2013-12-29 9:24 ` Christoffer Dall 10 siblings, 1 reply; 38+ messages in thread From: Andrew Jones @ 2013-10-14 16:23 UTC (permalink / raw) To: kvm; +Cc: kvmarm, gleb, christoffer.dall Add support for tests to manage exception handlers. Now we need kvm. Signed-off-by: Andrew Jones <drjones@redhat.com> --- arm/boot.c | 29 +++++++++++++++++++---- arm/cstart.S | 46 ++++++++++++++++++++++++++++++++++++ arm/run | 2 +- arm/unittests.cfg | 6 +++++ config/config-arm.mak | 1 + lib/arm/bootinfo.c | 2 -- lib/arm/processor.h | 45 +++++++++++++++++++++++++++++++++++ lib/arm/vectors.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/arm/vectors.h | 37 +++++++++++++++++++++++++++++ lib/libcflat.h | 2 ++ 10 files changed, 227 insertions(+), 8 deletions(-) create mode 100644 lib/arm/processor.h create mode 100644 lib/arm/vectors.c create mode 100644 lib/arm/vectors.h diff --git a/arm/boot.c b/arm/boot.c index 375e8708a7c54..5103499b83155 100644 --- a/arm/boot.c +++ b/arm/boot.c @@ -1,5 +1,10 @@ #include "libcflat.h" #include "arm/bootinfo.h" +#include "arm/vectors.h" + +#define die(msg...) printf(msg), exit(1) + +static bool svc_works; static bool info_check(u32 var, char *expected) { @@ -10,18 +15,32 @@ static bool info_check(u32 var, char *expected) return !strcmp(var_str, expected); } +static void svc_check(struct ex_regs *regs __unused) +{ + svc_works = true; +} + +static bool vectors_check(void) +{ + handle_exception(V_SVC, svc_check); + asm volatile("svc #123"); + return svc_works; +} + int main(int argc, char **argv) { int ret = 0; - if (argc < 3) { - printf("Not enough arguments. Can't test\n"); - return 1; - } + if (argc < 1) + die("boot: No test name appended to qemu command line\n"); - if (!strcmp(argv[0], "info")) + if (!strcmp(argv[0], "info")) { + if (argc < 3) + die("boot info: Not enough arguments for test\n"); ret = !info_check(mem32.size, argv[1]) || !info_check(core.pagesize, argv[2]); + } else if (!strcmp(argv[0], "vectors")) + ret = !vectors_check(); return ret; } diff --git a/arm/cstart.S b/arm/cstart.S index a65809824d4f1..0907c620bd83f 100644 --- a/arm/cstart.S +++ b/arm/cstart.S @@ -1,5 +1,6 @@ #define CR_B (1 << 7) +#define CR_V (1 << 13) .arm @@ -12,6 +13,13 @@ start: push { r0-r3 } @push r3 too for 8-byte alignment mrc p15, 0, r8, c1, c0, 0 @r8 = sctrl + + /* set up vector table */ + bic r8, #CR_V @sctrl.V = 0 + mcr p15, 0, r8, c1, c0, 0 + ldr r0, =vector_table @vbar = vector_table + mcr p15, 0, r0, c12, c0, 0 + bl get_endianness bl io_init @@ -41,6 +49,44 @@ halt: 1: wfi b 1b +vector_common: + add r2, sp, #(14 * 4) + mrs r3, spsr + push { r0-r3 } @push r0 too for padding + add r0, sp, #4 @skip pad + bl do_handle_exception + pop { r0-r3 } + msr spsr_fsxc, r3 + ldm sp!, { r0-r12,pc }^ + +.macro m_vector, v + push { r0-r12,lr } + mov r1, \v + b vector_common +.endm + +reset: m_vector #0 +undef: m_vector #1 +svc: m_vector #2 +prefetch: m_vector #3 +data: m_vector #4 +impossible: m_vector #5 +irq: m_vector #6 +fiq: m_vector #7 + +.section .text.ex +.align 5 + +vector_table: + b reset + b undef + b svc + b prefetch + b data + b impossible + b irq + b fiq + .data .globl cpu_is_be diff --git a/arm/run b/arm/run index 64446e8907564..b512880e28cb7 100755 --- a/arm/run +++ b/arm/run @@ -10,7 +10,7 @@ fi command="$qemu -device $testdev -display none -serial stdio " command+="-M virt -cpu cortex-a15 " -#command+="-enable-kvm " +command+="-enable-kvm " command+="-kernel" echo $command "$@" $command "$@" diff --git a/arm/unittests.cfg b/arm/unittests.cfg index fb78cd906839a..9c4faa600e9c5 100644 --- a/arm/unittests.cfg +++ b/arm/unittests.cfg @@ -9,3 +9,9 @@ [boot_info] file = boot.flat extra_params = -m 256 -append 'info 0x10000000 0x1000' +groups = boot + +[boot_vectors] +file = boot.flat +extra_params = -append 'vectors' +groups = boot diff --git a/config/config-arm.mak b/config/config-arm.mak index 066b1f725c5b3..87d61872ab16a 100644 --- a/config/config-arm.mak +++ b/config/config-arm.mak @@ -15,6 +15,7 @@ cflatobjs += \ lib/iomaps.o \ lib/virtio-testdev.o \ lib/arm/io.o \ + lib/arm/vectors.o \ lib/arm/bootinfo.o $(libcflat): LDFLAGS += -nostdlib diff --git a/lib/arm/bootinfo.c b/lib/arm/bootinfo.c index c362064f661d9..fd74fac2c5a2f 100644 --- a/lib/arm/bootinfo.c +++ b/lib/arm/bootinfo.c @@ -49,8 +49,6 @@ static void read_atags(u32 id, u32 *info) } } -#define __unused __attribute__((__unused__)) - void read_bootinfo(u32 arg __unused, u32 id, u32 *info) { u32 *atags = NULL; diff --git a/lib/arm/processor.h b/lib/arm/processor.h new file mode 100644 index 0000000000000..32e1778477be2 --- /dev/null +++ b/lib/arm/processor.h @@ -0,0 +1,45 @@ +#ifndef _PROCESSOR_H_ +#define _PROCESSOR_H_ +#include "libcflat.h" + +#define __stringify_1(x...) #x +#define __stringify(x...) __stringify_1(x) + +#undef __regfn +#define __regfn(reg) \ +static inline u32 read_##reg(void) \ +{ \ + u32 val; \ + asm volatile("mov %0, " __stringify(reg) : "=r" (val)); \ + return val; \ +} +__regfn(lr) + +#undef __regfn +#define __regfn(reg) \ +static inline void write_##reg(u32 val) \ +{ \ + asm volatile("mov " __stringify(reg) ", %0" :: "r" (val)); \ +} +__regfn(lr) + +#undef __regfn +#define __regfn(reg) \ +static inline u32 read_##reg(void) \ +{ \ + u32 val; \ + asm volatile("mrs %0, " __stringify(reg) : "=r" (val)); \ + return val; \ +} +__regfn(cpsr) + +#undef __regfn +#define __regfn(reg) \ +static inline void write_##reg(u32 val) \ +{ \ + asm volatile("msr " __stringify(reg) ", %0" :: "r" (val)); \ +} +__regfn(cpsr) + +#undef __regfn +#endif diff --git a/lib/arm/vectors.c b/lib/arm/vectors.c new file mode 100644 index 0000000000000..c1e2dea519e56 --- /dev/null +++ b/lib/arm/vectors.c @@ -0,0 +1,65 @@ +#include "libcflat.h" +#include "arm/processor.h" +#include "arm/vectors.h" + +#define abort(msg...) \ + printf(msg), dump_ex_regs(regs), exit(EINTR) + +const char *mode_names[] = { + "usr", "fiq", "irq", "svc", NULL, NULL, NULL, + "abt", NULL, NULL, NULL, "und", +}; + +const char *vector_names[] = { + "Reset", "Undefined", "SVC", "Prefetch abort", "Data abort", + "Impossible vector 0x14", "IRQ", "FIQ", +}; + +void dump_ex_regs(struct ex_regs *regs) +{ + u32 cpsr = read_cpsr(); + u8 mode, smode; + + mode = cpsr & MODE_MASK; + smode = ex_reg(regs, R_SPSR) & MODE_MASK; + + printf("vector = %s\n", vector_name(ex_vector(regs))); + printf("mode %s to %s\n", mode_name(smode), mode_name(mode)); + printf("cpsr=%x\n", cpsr); + printf( + "r0=%x\n" "r1=%x\n" "r2=%x\n" "r3=%x\n" + "r4=%x\n" "r5=%x\n" "r6=%x\n" "r7=%x\n" + "r8=%x\n" "r9=%x\n" "r10=%x\n" "r11=%x\n" + "ip=%x\n" "sp_%s=%x\n" "lr_%s=%x\n" "cpsr_%s=%x\n", + ex_reg(regs,0), ex_reg(regs,1), ex_reg(regs,2), ex_reg(regs,3), + ex_reg(regs,4), ex_reg(regs,5), ex_reg(regs,6), ex_reg(regs,7), + ex_reg(regs,8), ex_reg(regs,9), ex_reg(regs,10), ex_reg(regs,11), + ex_reg(regs, R_IP), + mode_name(mode), ex_reg(regs, R_SP), + mode_name(mode), ex_reg(regs, R_LR), + mode_name(mode), ex_reg(regs, R_SPSR) + ); +} + +static void (*exception_handlers[8])(struct ex_regs *regs); + +void handle_exception(u8 v, void (*func)(struct ex_regs *regs)) +{ + if (v < 8) + exception_handlers[v] = func; +} + +void do_handle_exception(struct ex_regs *regs) +{ + u8 v; + + if ((v = ex_vector(regs)) > 7) + abort("%s called with vector=%d\n", __func__, v); + + if (exception_handlers[v]) { + exception_handlers[v](regs); + return; + } + + abort("Exception %s\n", vector_name(v)); +} diff --git a/lib/arm/vectors.h b/lib/arm/vectors.h new file mode 100644 index 0000000000000..ca074aab674a3 --- /dev/null +++ b/lib/arm/vectors.h @@ -0,0 +1,37 @@ +#ifndef _VECTORS_H_ +#define _VECTORS_H_ + +/* modes */ +enum { + M_USR = 0x10, M_FIQ = 0x11, M_IRQ = 0x12, M_SVC = 0x13, + M_ABT = 0x17, M_UND = 0x1b, +}; +#define MODE_MASK 0x1f +extern const char *mode_names[]; +#define mode_name(m) mode_names[(m) - 0x10] + +/* vectors */ +enum { + V_RESET, V_UNDEF, V_SVC, V_PREFETCH_ABT, V_DATA_ABT, + V_IMPOSSIBLE, V_IRQ, V_FIQ, +}; +extern const char *vector_names[]; +#define vector_name(v) vector_names[v] + +#define R_IP 12 +#define R_SP 13 +#define R_LR 14 +#define R_SPSR 16 +#define __ex_reg(n) \ + ((n) == R_SP ? 1 : (n) == R_LR ? 16 : (n) == R_SPSR ? 2 : ((n)+3)) +#define ex_reg(regs, n) ((regs)->words[__ex_reg(n)]) +#define ex_vector(regs) ((regs)->words[0]) + +struct ex_regs { + /* see cstart.S for the register push order */ + unsigned long words[18]; +}; + +void handle_exception(u8 v, void (*func)(struct ex_regs *regs)); + +#endif diff --git a/lib/libcflat.h b/lib/libcflat.h index dce9a0f516e7e..6ebd903a27f46 100644 --- a/lib/libcflat.h +++ b/lib/libcflat.h @@ -68,6 +68,8 @@ extern long atol(const char *ptr); #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) +#define __unused __attribute__((__unused__)) + #define NULL ((void *)0UL) #include "errno.h" #endif -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH 9/9] arm: add vectors support 2013-10-14 16:23 ` [PATCH 9/9] arm: add vectors support Andrew Jones @ 2013-10-17 1:06 ` Christoffer Dall 2013-10-17 10:38 ` Andrew Jones 0 siblings, 1 reply; 38+ messages in thread From: Christoffer Dall @ 2013-10-17 1:06 UTC (permalink / raw) To: Andrew Jones; +Cc: kvm, kvmarm, gleb On Mon, Oct 14, 2013 at 06:23:35PM +0200, Andrew Jones wrote: > Add support for tests to manage exception handlers. Now we need kvm. > > Signed-off-by: Andrew Jones <drjones@redhat.com> > --- > arm/boot.c | 29 +++++++++++++++++++---- > arm/cstart.S | 46 ++++++++++++++++++++++++++++++++++++ > arm/run | 2 +- > arm/unittests.cfg | 6 +++++ > config/config-arm.mak | 1 + > lib/arm/bootinfo.c | 2 -- > lib/arm/processor.h | 45 +++++++++++++++++++++++++++++++++++ > lib/arm/vectors.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++ > lib/arm/vectors.h | 37 +++++++++++++++++++++++++++++ > lib/libcflat.h | 2 ++ > 10 files changed, 227 insertions(+), 8 deletions(-) > create mode 100644 lib/arm/processor.h > create mode 100644 lib/arm/vectors.c > create mode 100644 lib/arm/vectors.h > > diff --git a/arm/boot.c b/arm/boot.c > index 375e8708a7c54..5103499b83155 100644 > --- a/arm/boot.c > +++ b/arm/boot.c > @@ -1,5 +1,10 @@ > #include "libcflat.h" > #include "arm/bootinfo.h" > +#include "arm/vectors.h" > + > +#define die(msg...) printf(msg), exit(1) > + > +static bool svc_works; > > static bool info_check(u32 var, char *expected) > { > @@ -10,18 +15,32 @@ static bool info_check(u32 var, char *expected) > return !strcmp(var_str, expected); > } > > +static void svc_check(struct ex_regs *regs __unused) > +{ > + svc_works = true; > +} > + > +static bool vectors_check(void) > +{ > + handle_exception(V_SVC, svc_check); > + asm volatile("svc #123"); > + return svc_works; > +} > + > int main(int argc, char **argv) > { > int ret = 0; > > - if (argc < 3) { > - printf("Not enough arguments. Can't test\n"); > - return 1; > - } > + if (argc < 1) > + die("boot: No test name appended to qemu command line\n"); > > - if (!strcmp(argv[0], "info")) > + if (!strcmp(argv[0], "info")) { > + if (argc < 3) > + die("boot info: Not enough arguments for test\n"); > ret = !info_check(mem32.size, argv[1]) > || !info_check(core.pagesize, argv[2]); > + } else if (!strcmp(argv[0], "vectors")) > + ret = !vectors_check(); > > return ret; > } > diff --git a/arm/cstart.S b/arm/cstart.S > index a65809824d4f1..0907c620bd83f 100644 > --- a/arm/cstart.S > +++ b/arm/cstart.S > @@ -1,5 +1,6 @@ > > #define CR_B (1 << 7) > +#define CR_V (1 << 13) > > .arm > > @@ -12,6 +13,13 @@ start: > push { r0-r3 } @push r3 too for 8-byte alignment > > mrc p15, 0, r8, c1, c0, 0 @r8 = sctrl > + > + /* set up vector table */ > + bic r8, #CR_V @sctrl.V = 0 > + mcr p15, 0, r8, c1, c0, 0 > + ldr r0, =vector_table @vbar = vector_table > + mcr p15, 0, r0, c12, c0, 0 > + > bl get_endianness > bl io_init > > @@ -41,6 +49,44 @@ halt: > 1: wfi > b 1b > > +vector_common: > + add r2, sp, #(14 * 4) this looks weird, what are you pointing to here? > + mrs r3, spsr > + push { r0-r3 } @push r0 too for padding > + add r0, sp, #4 @skip pad so you're embedding the exception number into the regs structure? That's weird too... Why not have regs be regs at the time of calling the exception and then pass that little bit of extra information here? If not, could we at least call the regs structure something like ex_info and have named fields on there? > + bl do_handle_exception > + pop { r0-r3 } > + msr spsr_fsxc, r3 > + ldm sp!, { r0-r12,pc }^ > + > +.macro m_vector, v > + push { r0-r12,lr } > + mov r1, \v > + b vector_common > +.endm > + > +reset: m_vector #0 > +undef: m_vector #1 > +svc: m_vector #2 > +prefetch: m_vector #3 > +data: m_vector #4 > +impossible: m_vector #5 > +irq: m_vector #6 > +fiq: m_vector #7 > + > +.section .text.ex > +.align 5 > + > +vector_table: > + b reset > + b undef > + b svc > + b prefetch > + b data > + b impossible > + b irq > + b fiq > + > .data > > .globl cpu_is_be > diff --git a/arm/run b/arm/run > index 64446e8907564..b512880e28cb7 100755 > --- a/arm/run > +++ b/arm/run > @@ -10,7 +10,7 @@ fi > > command="$qemu -device $testdev -display none -serial stdio " > command+="-M virt -cpu cortex-a15 " > -#command+="-enable-kvm " > +command+="-enable-kvm " > command+="-kernel" > echo $command "$@" > $command "$@" > diff --git a/arm/unittests.cfg b/arm/unittests.cfg > index fb78cd906839a..9c4faa600e9c5 100644 > --- a/arm/unittests.cfg > +++ b/arm/unittests.cfg > @@ -9,3 +9,9 @@ > [boot_info] > file = boot.flat > extra_params = -m 256 -append 'info 0x10000000 0x1000' > +groups = boot > + > +[boot_vectors] > +file = boot.flat > +extra_params = -append 'vectors' > +groups = boot > diff --git a/config/config-arm.mak b/config/config-arm.mak > index 066b1f725c5b3..87d61872ab16a 100644 > --- a/config/config-arm.mak > +++ b/config/config-arm.mak > @@ -15,6 +15,7 @@ cflatobjs += \ > lib/iomaps.o \ > lib/virtio-testdev.o \ > lib/arm/io.o \ > + lib/arm/vectors.o \ > lib/arm/bootinfo.o > > $(libcflat): LDFLAGS += -nostdlib > diff --git a/lib/arm/bootinfo.c b/lib/arm/bootinfo.c > index c362064f661d9..fd74fac2c5a2f 100644 > --- a/lib/arm/bootinfo.c > +++ b/lib/arm/bootinfo.c > @@ -49,8 +49,6 @@ static void read_atags(u32 id, u32 *info) > } > } > > -#define __unused __attribute__((__unused__)) > - > void read_bootinfo(u32 arg __unused, u32 id, u32 *info) > { > u32 *atags = NULL; > diff --git a/lib/arm/processor.h b/lib/arm/processor.h > new file mode 100644 > index 0000000000000..32e1778477be2 > --- /dev/null > +++ b/lib/arm/processor.h > @@ -0,0 +1,45 @@ > +#ifndef _PROCESSOR_H_ > +#define _PROCESSOR_H_ > +#include "libcflat.h" > + > +#define __stringify_1(x...) #x > +#define __stringify(x...) __stringify_1(x) > + > +#undef __regfn > +#define __regfn(reg) \ > +static inline u32 read_##reg(void) \ > +{ \ > + u32 val; \ > + asm volatile("mov %0, " __stringify(reg) : "=r" (val)); \ > + return val; \ > +} > +__regfn(lr) > + > +#undef __regfn > +#define __regfn(reg) \ > +static inline void write_##reg(u32 val) \ > +{ \ > + asm volatile("mov " __stringify(reg) ", %0" :: "r" (val)); \ > +} > +__regfn(lr) > + > +#undef __regfn > +#define __regfn(reg) \ > +static inline u32 read_##reg(void) \ > +{ \ > + u32 val; \ > + asm volatile("mrs %0, " __stringify(reg) : "=r" (val)); \ > + return val; \ > +} > +__regfn(cpsr) > + > +#undef __regfn > +#define __regfn(reg) \ > +static inline void write_##reg(u32 val) \ > +{ \ > + asm volatile("msr " __stringify(reg) ", %0" :: "r" (val)); \ > +} > +__regfn(cpsr) > + > +#undef __regfn > +#endif > diff --git a/lib/arm/vectors.c b/lib/arm/vectors.c > new file mode 100644 > index 0000000000000..c1e2dea519e56 > --- /dev/null > +++ b/lib/arm/vectors.c > @@ -0,0 +1,65 @@ > +#include "libcflat.h" > +#include "arm/processor.h" > +#include "arm/vectors.h" > + > +#define abort(msg...) \ > + printf(msg), dump_ex_regs(regs), exit(EINTR) > + > +const char *mode_names[] = { > + "usr", "fiq", "irq", "svc", NULL, NULL, NULL, > + "abt", NULL, NULL, NULL, "und", > +}; > + > +const char *vector_names[] = { > + "Reset", "Undefined", "SVC", "Prefetch abort", "Data abort", > + "Impossible vector 0x14", "IRQ", "FIQ", > +}; > + > +void dump_ex_regs(struct ex_regs *regs) > +{ > + u32 cpsr = read_cpsr(); > + u8 mode, smode; > + > + mode = cpsr & MODE_MASK; > + smode = ex_reg(regs, R_SPSR) & MODE_MASK; > + > + printf("vector = %s\n", vector_name(ex_vector(regs))); > + printf("mode %s to %s\n", mode_name(smode), mode_name(mode)); > + printf("cpsr=%x\n", cpsr); > + printf( > + "r0=%x\n" "r1=%x\n" "r2=%x\n" "r3=%x\n" > + "r4=%x\n" "r5=%x\n" "r6=%x\n" "r7=%x\n" > + "r8=%x\n" "r9=%x\n" "r10=%x\n" "r11=%x\n" > + "ip=%x\n" "sp_%s=%x\n" "lr_%s=%x\n" "cpsr_%s=%x\n", > + ex_reg(regs,0), ex_reg(regs,1), ex_reg(regs,2), ex_reg(regs,3), > + ex_reg(regs,4), ex_reg(regs,5), ex_reg(regs,6), ex_reg(regs,7), > + ex_reg(regs,8), ex_reg(regs,9), ex_reg(regs,10), ex_reg(regs,11), > + ex_reg(regs, R_IP), > + mode_name(mode), ex_reg(regs, R_SP), > + mode_name(mode), ex_reg(regs, R_LR), > + mode_name(mode), ex_reg(regs, R_SPSR) > + ); > +} > + > +static void (*exception_handlers[8])(struct ex_regs *regs); > + > +void handle_exception(u8 v, void (*func)(struct ex_regs *regs)) > +{ > + if (v < 8) > + exception_handlers[v] = func; > +} > + > +void do_handle_exception(struct ex_regs *regs) > +{ > + u8 v; > + > + if ((v = ex_vector(regs)) > 7) > + abort("%s called with vector=%d\n", __func__, v); > + > + if (exception_handlers[v]) { > + exception_handlers[v](regs); > + return; > + } > + > + abort("Exception %s\n", vector_name(v)); > +} > diff --git a/lib/arm/vectors.h b/lib/arm/vectors.h > new file mode 100644 > index 0000000000000..ca074aab674a3 > --- /dev/null > +++ b/lib/arm/vectors.h > @@ -0,0 +1,37 @@ > +#ifndef _VECTORS_H_ > +#define _VECTORS_H_ > + > +/* modes */ > +enum { > + M_USR = 0x10, M_FIQ = 0x11, M_IRQ = 0x12, M_SVC = 0x13, > + M_ABT = 0x17, M_UND = 0x1b, > +}; > +#define MODE_MASK 0x1f > +extern const char *mode_names[]; > +#define mode_name(m) mode_names[(m) - 0x10] > + > +/* vectors */ > +enum { > + V_RESET, V_UNDEF, V_SVC, V_PREFETCH_ABT, V_DATA_ABT, > + V_IMPOSSIBLE, V_IRQ, V_FIQ, > +}; > +extern const char *vector_names[]; > +#define vector_name(v) vector_names[v] > + > +#define R_IP 12 > +#define R_SP 13 > +#define R_LR 14 > +#define R_SPSR 16 > +#define __ex_reg(n) \ > + ((n) == R_SP ? 1 : (n) == R_LR ? 16 : (n) == R_SPSR ? 2 : ((n)+3)) > +#define ex_reg(regs, n) ((regs)->words[__ex_reg(n)]) > +#define ex_vector(regs) ((regs)->words[0]) > + > +struct ex_regs { > + /* see cstart.S for the register push order */ > + unsigned long words[18]; > +}; referring to an assembly file to understand a data structure is not super user-friendly. You could also consider being inspired by ptrace.h from the kernel here to use a well-known format for this data. > + > +void handle_exception(u8 v, void (*func)(struct ex_regs *regs)); > + > +#endif > diff --git a/lib/libcflat.h b/lib/libcflat.h > index dce9a0f516e7e..6ebd903a27f46 100644 > --- a/lib/libcflat.h > +++ b/lib/libcflat.h > @@ -68,6 +68,8 @@ extern long atol(const char *ptr); > > #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) > > +#define __unused __attribute__((__unused__)) > + > #define NULL ((void *)0UL) > #include "errno.h" > #endif > -- > 1.8.1.4 > Looks roughly ok as a first drop, but I would like to reuse a bit more familiar names from the kernel for mode definitions etc., and possibly copy in the kernel header file for the data structure. I'll review the implementation in more depth for v2 when the indentations are fixed. Thanks a lot for working on this and doing the initial legwork here. -Christoffer ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 9/9] arm: add vectors support 2013-10-17 1:06 ` Christoffer Dall @ 2013-10-17 10:38 ` Andrew Jones 2013-10-17 18:58 ` Christoffer Dall 0 siblings, 1 reply; 38+ messages in thread From: Andrew Jones @ 2013-10-17 10:38 UTC (permalink / raw) To: Christoffer Dall; +Cc: kvm, kvmarm, gleb On Wed, Oct 16, 2013 at 06:06:42PM -0700, Christoffer Dall wrote: > > +++ b/arm/cstart.S > > @@ -1,5 +1,6 @@ > > > > #define CR_B (1 << 7) > > +#define CR_V (1 << 13) > > > > .arm > > > > @@ -12,6 +13,13 @@ start: > > push { r0-r3 } @push r3 too for 8-byte alignment > > > > mrc p15, 0, r8, c1, c0, 0 @r8 = sctrl > > + > > + /* set up vector table */ > > + bic r8, #CR_V @sctrl.V = 0 > > + mcr p15, 0, r8, c1, c0, 0 > > + ldr r0, =vector_table @vbar = vector_table > > + mcr p15, 0, r0, c12, c0, 0 > > + > > bl get_endianness > > bl io_init > > > > @@ -41,6 +49,44 @@ halt: > > 1: wfi > > b 1b > > > > +vector_common: > > + add r2, sp, #(14 * 4) > > this looks weird, what are you pointing to here? What sp was at the time of exception. So if you look at ex_regs->sp, then you'll see what sp was when the exception occurred, not that plus what we're pushing on now for the handler. > > > + mrs r3, spsr > > + push { r0-r3 } @push r0 too for padding > > + add r0, sp, #4 @skip pad > > so you're embedding the exception number into the regs structure? > That's weird too... Why not have regs be regs at the time of calling > the exception and then pass that little bit of extra information here? Just to be somewhat consistent with the way x86 does it. See lib/x86/desc.h. I imagine there will be developers working on both arches, and so I want to try to keep some interfaces consistent. > > If not, could we at least call the regs structure something like > ex_info and have named fields on there? I should have used named fields. I'll switch to that, but I guess if I want to maintain my consistent naming with x86, then I can't rename to ex_info... > > +#define R_IP 12 > > +#define R_SP 13 > > +#define R_LR 14 > > +#define R_SPSR 16 > > +#define __ex_reg(n) \ > > + ((n) == R_SP ? 1 : (n) == R_LR ? 16 : (n) == R_SPSR ? 2 : ((n)+3)) > > +#define ex_reg(regs, n) ((regs)->words[__ex_reg(n)]) > > +#define ex_vector(regs) ((regs)->words[0]) > > + > > +struct ex_regs { > > + /* see cstart.S for the register push order */ > > + unsigned long words[18]; > > +}; > > referring to an assembly file to understand a data structure is not > super user-friendly. You could also consider being inspired by ptrace.h > from the kernel here to use a well-known format for this data. OK, I'm inspired. Actually, inspired enough that I'll just include ptrace.h I'll use struct pt_regs and forget about consistency with x86. That means vector will be passed as a separate argument as well. > > > + > > +void handle_exception(u8 v, void (*func)(struct ex_regs *regs)); > > + > > +#endif > > diff --git a/lib/libcflat.h b/lib/libcflat.h > > index dce9a0f516e7e..6ebd903a27f46 100644 > > --- a/lib/libcflat.h > > +++ b/lib/libcflat.h > > @@ -68,6 +68,8 @@ extern long atol(const char *ptr); > > > > #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) > > > > +#define __unused __attribute__((__unused__)) > > + > > #define NULL ((void *)0UL) > > #include "errno.h" > > #endif > > -- > > 1.8.1.4 > > > > Looks roughly ok as a first drop, but I would like to reuse a bit more > familiar names from the kernel for mode definitions etc., and possibly > copy in the kernel header file for the data structure. Agreed. ptrace.h will come over. > > I'll review the implementation in more depth for v2 when the > indentations are fixed. > > Thanks a lot for working on this and doing the initial legwork here. Thanks for reviewing. drew ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 9/9] arm: add vectors support 2013-10-17 10:38 ` Andrew Jones @ 2013-10-17 18:58 ` Christoffer Dall 2013-10-20 16:35 ` Andrew Jones 0 siblings, 1 reply; 38+ messages in thread From: Christoffer Dall @ 2013-10-17 18:58 UTC (permalink / raw) To: Andrew Jones; +Cc: kvm, kvmarm, gleb On Thu, Oct 17, 2013 at 12:38:59PM +0200, Andrew Jones wrote: > On Wed, Oct 16, 2013 at 06:06:42PM -0700, Christoffer Dall wrote: > > > +++ b/arm/cstart.S > > > @@ -1,5 +1,6 @@ > > > > > > #define CR_B (1 << 7) > > > +#define CR_V (1 << 13) > > > > > > .arm > > > > > > @@ -12,6 +13,13 @@ start: > > > push { r0-r3 } @push r3 too for 8-byte alignment > > > > > > mrc p15, 0, r8, c1, c0, 0 @r8 = sctrl > > > + > > > + /* set up vector table */ > > > + bic r8, #CR_V @sctrl.V = 0 > > > + mcr p15, 0, r8, c1, c0, 0 > > > + ldr r0, =vector_table @vbar = vector_table > > > + mcr p15, 0, r0, c12, c0, 0 > > > + > > > bl get_endianness > > > bl io_init > > > > > > @@ -41,6 +49,44 @@ halt: > > > 1: wfi > > > b 1b > > > > > > +vector_common: > > > + add r2, sp, #(14 * 4) > > > > this looks weird, what are you pointing to here? > > What sp was at the time of exception. So if you look at ex_regs->sp, > then you'll see what sp was when the exception occurred, not that plus > what we're pushing on now for the handler. > Hmmm, so you're assuming that all exceptions will be taken from SVC mode? I assume we will run tests in more than SVC mode, no? Also note that the lr you're pushing here is not the lr at the time the exception occurs, but the return address from the exception. If the SVC instruction is executed from SVC mode, the original lr is lost iirc, and the caller needs to save it. If you're from user mode, something like stm sp, {r0-lr}^ will take care of this for you, and if you're from svc mode, you may want consider doing something like push {sp, lr} push {r0-r12} instead (assuming this is only ever compiled in ARM mode, not Thumb2, in which case the whole thing gets more complicated. > > > > > + mrs r3, spsr > > > + push { r0-r3 } @push r0 too for padding > > > + add r0, sp, #4 @skip pad > > > > so you're embedding the exception number into the regs structure? > > That's weird too... Why not have regs be regs at the time of calling > > the exception and then pass that little bit of extra information here? > > Just to be somewhat consistent with the way x86 does it. See > lib/x86/desc.h. I imagine there will be developers working on both > arches, and so I want to try to keep some interfaces consistent. > I imagine more that ARM guys will be working on this, and x86 guys will be working on x86, but I guess the future will tell, but it seems you are leaning to the conclusion as well below... > > > > If not, could we at least call the regs structure something like > > ex_info and have named fields on there? > > I should have used named fields. I'll switch to that, but I guess > if I want to maintain my consistent naming with x86, then I can't > rename to ex_info... > > > > +#define R_IP 12 > > > +#define R_SP 13 > > > +#define R_LR 14 > > > +#define R_SPSR 16 > > > +#define __ex_reg(n) \ > > > + ((n) == R_SP ? 1 : (n) == R_LR ? 16 : (n) == R_SPSR ? 2 : ((n)+3)) > > > +#define ex_reg(regs, n) ((regs)->words[__ex_reg(n)]) > > > +#define ex_vector(regs) ((regs)->words[0]) > > > + > > > +struct ex_regs { > > > + /* see cstart.S for the register push order */ > > > + unsigned long words[18]; > > > +}; > > > > referring to an assembly file to understand a data structure is not > > super user-friendly. You could also consider being inspired by ptrace.h > > from the kernel here to use a well-known format for this data. > > OK, I'm inspired. Actually, inspired enough that I'll just include > ptrace.h I'll use struct pt_regs and forget about consistency with x86. > That means vector will be passed as a separate argument as well. > nice! :) > > > > > + > > > +void handle_exception(u8 v, void (*func)(struct ex_regs *regs)); > > > + > > > +#endif > > > diff --git a/lib/libcflat.h b/lib/libcflat.h > > > index dce9a0f516e7e..6ebd903a27f46 100644 > > > --- a/lib/libcflat.h > > > +++ b/lib/libcflat.h > > > @@ -68,6 +68,8 @@ extern long atol(const char *ptr); > > > > > > #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) > > > > > > +#define __unused __attribute__((__unused__)) > > > + > > > #define NULL ((void *)0UL) > > > #include "errno.h" > > > #endif > > > -- > > > 1.8.1.4 > > > > > > > Looks roughly ok as a first drop, but I would like to reuse a bit more > > familiar names from the kernel for mode definitions etc., and possibly > > copy in the kernel header file for the data structure. > > Agreed. ptrace.h will come over. > > > > > I'll review the implementation in more depth for v2 when the > > indentations are fixed. > > > > Thanks a lot for working on this and doing the initial legwork here. > > Thanks for reviewing. > > drew ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 9/9] arm: add vectors support 2013-10-17 18:58 ` Christoffer Dall @ 2013-10-20 16:35 ` Andrew Jones 2013-10-21 9:59 ` Christoffer Dall 0 siblings, 1 reply; 38+ messages in thread From: Andrew Jones @ 2013-10-20 16:35 UTC (permalink / raw) To: Christoffer Dall; +Cc: kvm, kvmarm, gleb On Thu, Oct 17, 2013 at 11:58:43AM -0700, Christoffer Dall wrote: > On Thu, Oct 17, 2013 at 12:38:59PM +0200, Andrew Jones wrote: > > On Wed, Oct 16, 2013 at 06:06:42PM -0700, Christoffer Dall wrote: > > > > +++ b/arm/cstart.S > > > > @@ -1,5 +1,6 @@ > > > > > > > > #define CR_B (1 << 7) > > > > +#define CR_V (1 << 13) > > > > > > > > .arm > > > > > > > > @@ -12,6 +13,13 @@ start: > > > > push { r0-r3 } @push r3 too for 8-byte alignment > > > > > > > > mrc p15, 0, r8, c1, c0, 0 @r8 = sctrl > > > > + > > > > + /* set up vector table */ > > > > + bic r8, #CR_V @sctrl.V = 0 > > > > + mcr p15, 0, r8, c1, c0, 0 > > > > + ldr r0, =vector_table @vbar = vector_table > > > > + mcr p15, 0, r0, c12, c0, 0 > > > > + > > > > bl get_endianness > > > > bl io_init > > > > > > > > @@ -41,6 +49,44 @@ halt: > > > > 1: wfi > > > > b 1b > > > > > > > > +vector_common: > > > > + add r2, sp, #(14 * 4) > > > > > > this looks weird, what are you pointing to here? > > > > What sp was at the time of exception. So if you look at ex_regs->sp, > > then you'll see what sp was when the exception occurred, not that plus > > what we're pushing on now for the handler. > > > > Hmmm, so you're assuming that all exceptions will be taken from SVC > mode? I assume we will run tests in more than SVC mode, no? > > Also note that the lr you're pushing here is not the lr at the time the > exception occurs, but the return address from the exception. If the SVC > instruction is executed from SVC mode, the original lr is lost iirc, and > the caller needs to save it. If you're from user mode, something like > > stm sp, {r0-lr}^ > > will take care of this for you, and if you're from svc > mode, you may want consider doing something like > > push {sp, lr} > push {r0-r12} > > instead (assuming this is only ever compiled in ARM mode, not Thumb2, in > which case the whole thing gets more complicated. I think the lr pushing should be ok. That part is done in the macro that all vectors start with. It got snipped from this mail, so here it is .macro m_vector, v push { r0-r12,lr } mov r1, \v b vector_common .endm I realize it may still not be correct, just as the calculated sp may not be correct, depending on which mode,vector combo is used, but I was expecting to have different paths in the C code for fixing it up. Although that said, I haven't thought about it a bunch yet, so maybe it won't work that way... drew ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 9/9] arm: add vectors support 2013-10-20 16:35 ` Andrew Jones @ 2013-10-21 9:59 ` Christoffer Dall 0 siblings, 0 replies; 38+ messages in thread From: Christoffer Dall @ 2013-10-21 9:59 UTC (permalink / raw) To: Andrew Jones; +Cc: kvm, kvmarm, gleb On Sun, Oct 20, 2013 at 06:35:34PM +0200, Andrew Jones wrote: > On Thu, Oct 17, 2013 at 11:58:43AM -0700, Christoffer Dall wrote: > > On Thu, Oct 17, 2013 at 12:38:59PM +0200, Andrew Jones wrote: > > > On Wed, Oct 16, 2013 at 06:06:42PM -0700, Christoffer Dall wrote: > > > > > +++ b/arm/cstart.S > > > > > @@ -1,5 +1,6 @@ > > > > > > > > > > #define CR_B (1 << 7) > > > > > +#define CR_V (1 << 13) > > > > > > > > > > .arm > > > > > > > > > > @@ -12,6 +13,13 @@ start: > > > > > push { r0-r3 } @push r3 too for 8-byte alignment > > > > > > > > > > mrc p15, 0, r8, c1, c0, 0 @r8 = sctrl > > > > > + > > > > > + /* set up vector table */ > > > > > + bic r8, #CR_V @sctrl.V = 0 > > > > > + mcr p15, 0, r8, c1, c0, 0 > > > > > + ldr r0, =vector_table @vbar = vector_table > > > > > + mcr p15, 0, r0, c12, c0, 0 > > > > > + > > > > > bl get_endianness > > > > > bl io_init > > > > > > > > > > @@ -41,6 +49,44 @@ halt: > > > > > 1: wfi > > > > > b 1b > > > > > > > > > > +vector_common: > > > > > + add r2, sp, #(14 * 4) > > > > > > > > this looks weird, what are you pointing to here? > > > > > > What sp was at the time of exception. So if you look at ex_regs->sp, > > > then you'll see what sp was when the exception occurred, not that plus > > > what we're pushing on now for the handler. > > > > > > > Hmmm, so you're assuming that all exceptions will be taken from SVC > > mode? I assume we will run tests in more than SVC mode, no? > > > > Also note that the lr you're pushing here is not the lr at the time the > > exception occurs, but the return address from the exception. If the SVC > > instruction is executed from SVC mode, the original lr is lost iirc, and > > the caller needs to save it. If you're from user mode, something like > > > > stm sp, {r0-lr}^ > > > > will take care of this for you, and if you're from svc > > mode, you may want consider doing something like > > > > push {sp, lr} > > push {r0-r12} > > > > instead (assuming this is only ever compiled in ARM mode, not Thumb2, in > > which case the whole thing gets more complicated. > > I think the lr pushing should be ok. That part is done in the macro that > all vectors start with. It got snipped from this mail, so here it is > > .macro m_vector, v > push { r0-r12,lr } > mov r1, \v > b vector_common > .endm You push this lr after taking the exception, so the lr will point to the instruction following the trap instruction itself; if your convention is that the regs struct is the lr as it was when the trap was generated, well then, things don't match. If the exception is taken from SVC mode, I'm not sure there's a proper way to get this information though, so it really depends on how you imagine this to be used... > > I realize it may still not be correct, just as the calculated sp > may not be correct, depending on which mode,vector combo is used, > but I was expecting to have different paths in the C code for > fixing it up. Although that said, I haven't thought about it a > bunch yet, so maybe it won't work that way... > I think it may be worth taking an extra look at how the kernel handles all this and somewhat replicate some of what we're doing, but again, it depends on what the goal here is. The SP calculation is probably correct, but it's error-prone and bound to confuse people IMHO, but it's up to you at this point. -Christoffer ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 0/9] kvm-unit-tests/arm: initial drop 2013-10-14 16:23 [PATCH 0/9] kvm-unit-tests/arm: initial drop Andrew Jones ` (8 preceding siblings ...) 2013-10-14 16:23 ` [PATCH 9/9] arm: add vectors support Andrew Jones @ 2013-11-20 23:06 ` María Soler Heredia 2013-11-26 17:23 ` Andrew Jones 2013-12-29 9:24 ` Christoffer Dall 10 siblings, 1 reply; 38+ messages in thread From: María Soler Heredia @ 2013-11-20 23:06 UTC (permalink / raw) To: kvm Andrew Jones <drjones <at> redhat.com> writes: > This series introduces arm to kvm-unit-tests. > To use this you need an arm platform or simulator capable > of running kvmarm and a qemu with the mach-virt patches[2], as > well as the previously mentioned virtio-testdev. Hello, I have been playing with your tests for a while and I cannot seem to get them to work all right. When I run them disabling kvm on the arm-run script, they do work, but when I run them with kvm enabled they fail. This is my output: ./arm-run arm/boot.flat -smp 1 -m 256 -append 'info 0x10000000 0x1000' qemu-system-arm -device virtio-testdev -display none -serial stdio -M virt -cpu cortex-a15 -enable-kvm -kernel arm/boot.flat -smp 1 -m 256 -append info 0x10000000 0x1000 kvm [1252]: load/store instruction decoding not implemented error: kvm run failed Function not implemented ./arm-run: line 16: 1251 Aborted $command "$@" Return value from qemu: 134 FAIL boot_info ./arm-run arm/boot.flat -smp 1 -append 'vectors' qemu-system-arm -device virtio-testdev -display none -serial stdio -M virt -cpu cortex-a15 -enable-kvm -kernel arm/boot.flat -smp 1 -append vectors kvm [1257]: load/store instruction decoding not implemented error: kvm run failed Function not implemented ./arm-run: line 16: 1256 Aborted $command "$@" Return value from qemu: 134 FAIL boot_vectors I am using FastModels Model Debugger version 8.2.028, with a model of this characteristics: Model: ------ Model name: ARM_Cortex-A15 Instance: cluster.cpu0 Using CADI 2.0 interface revision 0. Version: 8.2.72 Generated by Core Generator: No Needs SimGen License: No running the latest stable linux release and qemu-devel's latest qemu with the patches indicated here https://lists.gnu.org/archive/html/qemu-devel/2013-10/msg02428.html plus > [1] http://lists.nongnu.org/archive/html/qemu-devel/2013-10/msg01815.html I tested the instalation by running a linux with the same setup using this call: qemu-system-arm \ -display none \ -enable-kvm \ -kernel zImage\ -m 128 -M virt -cpu cortex-a15 \ -drive if=none,file=linux.img,id=fs \ -device virtio-blk-device,drive=fs As I said, the tests pass if the kvm is not enabled and fail otherwise. I have added a few printfs for debugging and I can tell that the code in boot.c runs ok, but then when virtio_testdev is called (from virtio_testdev_exit) the execution throws an exception (more specifically the line *tdp++ = cpu_to_le32(va_arg(va, unsigned)); inside the first while. I am not used to sending emails to this kind of list, so I don't know if I am being too specific, too little or maybe not even giving the right information. Please tell me what else you need and if you can help me solve this problem. Thank you very much, María. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 0/9] kvm-unit-tests/arm: initial drop 2013-11-20 23:06 ` [PATCH 0/9] kvm-unit-tests/arm: initial drop María Soler Heredia @ 2013-11-26 17:23 ` Andrew Jones 0 siblings, 0 replies; 38+ messages in thread From: Andrew Jones @ 2013-11-26 17:23 UTC (permalink / raw) To: María Soler Heredia; +Cc: kvm, kvmarm Sorry, just noticed this - you dropped me and the kvmarm list from your reply. On Wed, Nov 20, 2013 at 11:06:11PM +0000, María Soler Heredia wrote: > Andrew Jones <drjones <at> redhat.com> writes: > > > > This series introduces arm to kvm-unit-tests. > > > To use this you need an arm platform or simulator capable > > of running kvmarm and a qemu with the mach-virt patches[2], as > > well as the previously mentioned virtio-testdev. > > Hello, > > I have been playing with your tests for a while and I cannot seem to get > them to work all right. When I run them disabling kvm on the arm-run script, > they do work, but when I run them with kvm enabled they fail. > > This is my output: > > ./arm-run arm/boot.flat -smp 1 -m 256 -append 'info 0x10000000 0x1000' > qemu-system-arm -device virtio-testdev -display none -serial stdio -M virt > -cpu cortex-a15 -enable-kvm -kernel arm/boot.flat -smp 1 -m 256 -append info > 0x10000000 0x1000 > kvm [1252]: load/store instruction decoding not implemented > error: kvm run failed Function not implemented The above errors come from the kernel and qemu. It's easy to see under what condition you would hit them, but it's not clear to me why that condition is present for you. > ./arm-run: line 16: 1251 Aborted $command "$@" > Return value from qemu: 134 > FAIL boot_info > ./arm-run arm/boot.flat -smp 1 -append 'vectors' > qemu-system-arm -device virtio-testdev -display none -serial stdio -M virt > -cpu cortex-a15 -enable-kvm -kernel arm/boot.flat -smp 1 -append vectors > kvm [1257]: load/store instruction decoding not implemented > error: kvm run failed Function not implemented > ./arm-run: line 16: 1256 Aborted $command "$@" > Return value from qemu: 134 > FAIL boot_vectors > > I am using FastModels Model Debugger version 8.2.028, with a model of this > characteristics: > > Model: > ------ > Model name: ARM_Cortex-A15 > Instance: cluster.cpu0 > Using CADI 2.0 interface revision 0. > Version: 8.2.72 > Generated by Core Generator: No > Needs SimGen License: No So far I've only tested on real hardware. So this could be the difference. > > running the latest stable linux release and qemu-devel's latest qemu with > the patches indicated here > https://lists.gnu.org/archive/html/qemu-devel/2013-10/msg02428.html plus > > [1] http://lists.nongnu.org/archive/html/qemu-devel/2013-10/msg01815.html > > I tested the instalation by running a linux with the same setup using this call: > qemu-system-arm \ > -display none \ > -enable-kvm \ > -kernel zImage\ > -m 128 -M virt -cpu cortex-a15 \ > -drive if=none,file=linux.img,id=fs \ > -device virtio-blk-device,drive=fs > > As I said, the tests pass if the kvm is not enabled and fail otherwise. I > have added a few printfs for debugging and I can tell that the code in > boot.c runs ok, but then when virtio_testdev is called (from > virtio_testdev_exit) the execution throws an exception (more specifically > the line *tdp++ = cpu_to_le32(va_arg(va, unsigned)); inside the first while. Hmm, even more confusing, as this isn't the first mmio access. > > I am not used to sending emails to this kind of list, so I don't know if I > am being too specific, too little or maybe not even giving the right > information. Please tell me what else you need and if you can help me solve > this problem. Your details are good, but instead of just stating 'latest' for your kernel and qemu versions, please give the exact version numbers. I've been busy with other things lately, but I'm due to post a v2 of this series. I should be able to finish that off this week. When I do, I'll see if I can test it over FastModel as well this time. Thanks for starting to poke at this! drew ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 0/9] kvm-unit-tests/arm: initial drop 2013-10-14 16:23 [PATCH 0/9] kvm-unit-tests/arm: initial drop Andrew Jones ` (9 preceding siblings ...) 2013-11-20 23:06 ` [PATCH 0/9] kvm-unit-tests/arm: initial drop María Soler Heredia @ 2013-12-29 9:24 ` Christoffer Dall 2014-01-02 18:56 ` Andrew Jones 10 siblings, 1 reply; 38+ messages in thread From: Christoffer Dall @ 2013-12-29 9:24 UTC (permalink / raw) To: Andrew Jones; +Cc: kvm, kvmarm, gleb On Mon, Oct 14, 2013 at 06:23:26PM +0200, Andrew Jones wrote: Hi Drew, > This series introduces arm to kvm-unit-tests. First, it does some > tidying up of the repo. Then, it adds support for virtio-testdev, > which was just posted to qemu-devel[1]. Next, it adds the basic > infrastructure for booting a test case (guest). Finally, it adds > support for vectors. This is just an initial drop, I'm starting > work on smp support now, and then will bring in support for > arm64. At that point we should be able to start actually adding > tests. To use this you need an arm platform or simulator capable > of running kvmarm and a qemu with the mach-virt patches[2], as > well as the previously mentioned virtio-testdev. > > [1] http://lists.nongnu.org/archive/html/qemu-devel/2013-10/msg01815.html > [2] http://lists.nongnu.org/archive/html/qemu-devel/2013-09/msg02142.html > > This patches are also available from a git repo here > https://github.com/rhdrjones/kvm-unit-tests/tree/arm-branch/master > I'm playing around with this, thanks again for working on it. It's long overdue that we're getting something real done in this area. I have run into some problems trying to run this thing on real hardware. The biggest problem is the known cache coherency issue where we need to flush the data cache to make things coherent when the guest runs with the MMU disabled. It shows up quite frequently if you just try to run the small flat binaries with KVM, and I suspec the only reason we are not seeing this with real kernels is that they are large enough that we end up writing the necessary data all the way to main memory. I'm working on a vmexit test to measure stuff, and I noticed that we: - really need to find a way to let a guest read the cycle counter - need a way to let a call a dummy HVC to KVM to measure round-trip times - ... This is probably something we should try to discuss on one of the next kvm/arm sync-up calls. I remember something about you not being able to make those, but we can arrange a different time for one of them some time. For now, I can work around the cache issue by enabling the DC bits and by adding a terrible hack for the cycle counter and dummy HVC. You can follow my hackings here: Kernel: https://git.linaro.org/people/christoffer.dall/linux-kvm-arm.git/shortlog/refs/heads/kvm-arm-next-measure unit-tests: https://github.com/columbia/kvm-unit-tests/tree/arm-support -Christoffer ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 0/9] kvm-unit-tests/arm: initial drop 2013-12-29 9:24 ` Christoffer Dall @ 2014-01-02 18:56 ` Andrew Jones 0 siblings, 0 replies; 38+ messages in thread From: Andrew Jones @ 2014-01-02 18:56 UTC (permalink / raw) To: Christoffer Dall; +Cc: kvm, kvmarm, gleb On Sun, Dec 29, 2013 at 01:24:11AM -0800, Christoffer Dall wrote: > On Mon, Oct 14, 2013 at 06:23:26PM +0200, Andrew Jones wrote: > > Hi Drew, > > > This series introduces arm to kvm-unit-tests. First, it does some > > tidying up of the repo. Then, it adds support for virtio-testdev, > > which was just posted to qemu-devel[1]. Next, it adds the basic > > infrastructure for booting a test case (guest). Finally, it adds > > support for vectors. This is just an initial drop, I'm starting > > work on smp support now, and then will bring in support for > > arm64. At that point we should be able to start actually adding > > tests. To use this you need an arm platform or simulator capable > > of running kvmarm and a qemu with the mach-virt patches[2], as > > well as the previously mentioned virtio-testdev. > > > > [1] http://lists.nongnu.org/archive/html/qemu-devel/2013-10/msg01815.html > > [2] http://lists.nongnu.org/archive/html/qemu-devel/2013-09/msg02142.html > > > > This patches are also available from a git repo here > > https://github.com/rhdrjones/kvm-unit-tests/tree/arm-branch/master > > > > I'm playing around with this, thanks again for working on it. It's long > overdue that we're getting something real done in this area. > > I have run into some problems trying to run this thing on real hardware. > The biggest problem is the known cache coherency issue where we need to > flush the data cache to make things coherent when the guest runs with > the MMU disabled. It shows up quite frequently if you just try to run > the small flat binaries with KVM, and I suspec the only reason we are > not seeing this with real kernels is that they are large enough that we > end up writing the necessary data all the way to main memory. > > I'm working on a vmexit test to measure stuff, and I noticed that we: > - really need to find a way to let a guest read the cycle counter > - need a way to let a call a dummy HVC to KVM to measure round-trip > times > - ... > > This is probably something we should try to discuss on one of the next > kvm/arm sync-up calls. I remember something about you not being able to > make those, but we can arrange a different time for one of them some > time. > > For now, I can work around the cache issue by enabling the DC bits and > by adding a terrible hack for the cycle counter and dummy HVC. You can > follow my hackings here: > > Kernel: > https://git.linaro.org/people/christoffer.dall/linux-kvm-arm.git/shortlog/refs/heads/kvm-arm-next-measure > > unit-tests: > https://github.com/columbia/kvm-unit-tests/tree/arm-support > > -Christoffer Thanks Christoffer! I'll look at these branches tomorrow. I'm glad we're getting some momentum on kvm-unit-tests/arm! drew ^ permalink raw reply [flat|nested] 38+ messages in thread
end of thread, other threads:[~2014-01-02 18:56 UTC | newest] Thread overview: 38+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-10-14 16:23 [PATCH 0/9] kvm-unit-tests/arm: initial drop Andrew Jones 2013-10-14 16:23 ` [PATCH 1/9] remove unused files Andrew Jones 2013-10-16 12:52 ` Gleb Natapov 2013-10-16 13:13 ` Alexander Graf 2013-10-16 13:18 ` Andrew Jones 2013-10-14 16:23 ` [PATCH 2/9] makefile and run_tests tweaks Andrew Jones 2013-10-14 16:23 ` [PATCH 3/9] clean root dir of all x86-ness Andrew Jones 2013-10-17 1:06 ` Christoffer Dall 2013-10-17 9:35 ` Andrew Jones 2013-10-17 19:01 ` Christoffer Dall 2013-10-20 16:37 ` Andrew Jones 2013-10-14 16:23 ` [PATCH 4/9] Introduce a simple iomap structure Andrew Jones 2013-10-14 16:23 ` [PATCH 5/9] Add halt() and some error codes Andrew Jones 2013-10-14 16:23 ` [PATCH 6/9] Introduce virtio-testdev Andrew Jones 2013-10-15 8:39 ` Andrew Jones 2013-10-17 1:06 ` Christoffer Dall 2013-10-17 9:51 ` Andrew Jones 2013-10-17 19:01 ` Christoffer Dall 2013-10-17 1:06 ` Christoffer Dall 2013-10-14 16:23 ` [PATCH 7/9] arm: replace arbitrary divisions Andrew Jones 2013-10-17 1:06 ` Christoffer Dall 2013-10-17 10:03 ` Andrew Jones 2013-10-17 18:59 ` Christoffer Dall 2013-10-14 16:23 ` [PATCH 8/9] arm: initial drop Andrew Jones 2013-10-17 1:06 ` Christoffer Dall 2013-10-17 10:16 ` Andrew Jones 2013-10-17 13:28 ` Andrew Jones 2013-10-17 18:39 ` Christoffer Dall 2013-10-14 16:23 ` [PATCH 9/9] arm: add vectors support Andrew Jones 2013-10-17 1:06 ` Christoffer Dall 2013-10-17 10:38 ` Andrew Jones 2013-10-17 18:58 ` Christoffer Dall 2013-10-20 16:35 ` Andrew Jones 2013-10-21 9:59 ` Christoffer Dall 2013-11-20 23:06 ` [PATCH 0/9] kvm-unit-tests/arm: initial drop María Soler Heredia 2013-11-26 17:23 ` Andrew Jones 2013-12-29 9:24 ` Christoffer Dall 2014-01-02 18:56 ` Andrew Jones
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).