All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/19] kvm-unit-tests/arm: initial drop
@ 2014-04-10 16:56 Andrew Jones
  2014-04-10 16:56 ` [PATCH v4 01/19] remove unused files Andrew Jones
                   ` (19 more replies)
  0 siblings, 20 replies; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: christoffer.dall

This is a v4 of a series that introduces arm to kvm-unit-tests. First,
it does some tidying up of the repo. Then, it adds support for device
trees (libfdt), and for virtio-testdev[1]. Next, it adds the basic
infrastructure for booting a test case (guest), and adds a first
test case, a self-test to confirm setup was completed successfully.
Finally, it further prepares the framework for more complicated tests
by adding vector support, and extends the self-test to test that too.

This initial drop doesn't require kvmarm. qemu-system-arm is enough,
but it must have mach-virt, and the virtio-testdev patch[1].

These patches (v4) are also available from a git repo here
https://github.com/rhdrjones/kvm-unit-tests/commits/arm/v4-initial-drop

The v3 patches are available for reference here
https://github.com/rhdrjones/kvm-unit-tests/commits/arm/v3-initial-drop

Major v3->v4 differences are noted in each patch that has some under
the '---'. There are also some new patches since v3 in this series,
and a few v3 patches were dropped.

Some more interesting v3->v4 changes are:
  * rebased to "7505ea2: realmode: make performance test run..."
  * generation of asm-offsets.h now done like Kbuild
  * cleaner build in general (new asm dir, no libfdt changes)
  * introduction of memregions
  * introduction of spinlocks
  * determination of nr_cpus on setup
  * reworked devicetree.[ch] to cleanup api and better document
  * a more general virtio_bind() implementation
  * more code comments and commit messages

Thanks in advance for reviews!

[1] http://lists.nongnu.org/archive/html/qemu-devel/2013-12/msg00690.html


Andrew Jones (17):
  remove unused files
  makefile and run_tests tweaks
  clean root dir of all x86-ness
  add distclean target and gitignore more
  add 'make cscope' support
  libfdt: Import libfdt source
  libfdt: get libfdt to build
  add support for Linux device trees
  libcflat: add abort() and assert()
  Introduce asm-generic/*.h files
  add minimal virtio support for devtree virtio-mmio
  Introduce virtio-testdev
  libcflat: clean up libcflat.h and add string.h
  printf: support field padding
  arm: initial drop
  arm: add useful headers from the Linux kernel
  arm: vectors support

Christoffer Dall (2):
  arm: Add spinlock implementation
  arm: Add IO accessors to avoid register-writeback

 .gitignore                   |    6 +
 Makefile                     |   55 +-
 README                       |   59 +-
 arm/cstart.S                 |  209 ++++++
 arm/flat.lds                 |   23 +
 arm/run                      |   31 +
 arm/selftest.c               |  207 ++++++
 arm/unittests.cfg            |   30 +
 config-i386.mak              |   13 -
 config-ia64.mak              |    7 -
 config-powerpc-440.mak       |   15 -
 config-powerpc.mak           |   39 --
 config-x86-common.mak        |  124 ----
 config-x86_64.mak            |   14 -
 config/asm-offsets.mak       |   41 ++
 config/config-arm.mak        |   79 +++
 config/config-i386.mak       |   12 +
 config/config-x86-common.mak |  122 ++++
 config/config-x86_64.mak     |   13 +
 configure                    |   40 +-
 docs/testdev.txt             |   13 +
 flat.lds                     |   21 -
 formats                      |   31 -
 iotable.c                    |   53 --
 iotable.h                    |   40 --
 kvmtrace.c                   |  706 --------------------
 kvmtrace_format              |  532 ---------------
 lib/argv.c                   |    6 +
 lib/arm/.gitignore           |    1 +
 lib/arm/asm-offsets.c        |   39 ++
 lib/arm/asm/asm-offsets.h    |    1 +
 lib/arm/asm/barrier.h        |   18 +
 lib/arm/asm/cp15.h           |   37 ++
 lib/arm/asm/io.h             |   81 +++
 lib/arm/asm/processor.h      |   40 ++
 lib/arm/asm/ptrace.h         |  100 +++
 lib/arm/asm/setup.h          |   39 ++
 lib/arm/asm/spinlock.h       |   11 +
 lib/arm/eabi_compat.c        |   20 +
 lib/arm/io.c                 |   66 ++
 lib/arm/processor.c          |  115 ++++
 lib/arm/setup.c              |  142 ++++
 lib/arm/spinlock.c           |   28 +
 lib/asm-generic/io.h         |  154 +++++
 lib/asm-generic/spinlock.h   |    4 +
 lib/devicetree.c             |  289 ++++++++
 lib/devicetree.h             |  230 +++++++
 lib/fwcfg.c                  |   58 --
 lib/generated/.gitignore     |    1 +
 lib/libcflat.h               |   59 +-
 lib/libfdt/Makefile.libfdt   |   10 +
 lib/libfdt/README            |    4 +
 lib/libfdt/fdt.c             |  250 +++++++
 lib/libfdt/fdt.h             |  111 ++++
 lib/libfdt/fdt_empty_tree.c  |   84 +++
 lib/libfdt/fdt_ro.c          |  573 ++++++++++++++++
 lib/libfdt/fdt_rw.c          |  492 ++++++++++++++
 lib/libfdt/fdt_strerror.c    |   96 +++
 lib/libfdt/fdt_sw.c          |  256 +++++++
 lib/libfdt/fdt_wip.c         |  118 ++++
 lib/libfdt/libfdt.h          | 1514 ++++++++++++++++++++++++++++++++++++++++++
 lib/libfdt/libfdt_env.h      |  111 ++++
 lib/libfdt/libfdt_internal.h |   95 +++
 lib/libfdt/version.lds       |   60 ++
 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                 |   82 ++-
 lib/string.c                 |   54 ++
 lib/string.h                 |   15 +
 lib/virtio-testdev.c         |  137 ++++
 lib/virtio-testdev.h         |   18 +
 lib/virtio.c                 |  166 +++++
 lib/virtio.h                 |   89 +++
 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                 |   22 +-
 testdev.txt                  |   14 -
 x86-run                      |   41 --
 x86/README                   |   59 +-
 x86/flat.lds                 |   21 +
 x86/print.h                  |   19 -
 x86/run                      |   41 ++
 x86/run-kvm-unit-tests       |    6 -
 96 files changed, 6782 insertions(+), 2667 deletions(-)
 create mode 100644 arm/cstart.S
 create mode 100644 arm/flat.lds
 create mode 100755 arm/run
 create mode 100644 arm/selftest.c
 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/asm-offsets.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/.gitignore
 create mode 100644 lib/arm/asm-offsets.c
 create mode 100644 lib/arm/asm/asm-offsets.h
 create mode 100644 lib/arm/asm/barrier.h
 create mode 100644 lib/arm/asm/cp15.h
 create mode 100644 lib/arm/asm/io.h
 create mode 100644 lib/arm/asm/processor.h
 create mode 100644 lib/arm/asm/ptrace.h
 create mode 100644 lib/arm/asm/setup.h
 create mode 100644 lib/arm/asm/spinlock.h
 create mode 100644 lib/arm/eabi_compat.c
 create mode 100644 lib/arm/io.c
 create mode 100644 lib/arm/processor.c
 create mode 100644 lib/arm/setup.c
 create mode 100644 lib/arm/spinlock.c
 create mode 100644 lib/asm-generic/io.h
 create mode 100644 lib/asm-generic/spinlock.h
 create mode 100644 lib/devicetree.c
 create mode 100644 lib/devicetree.h
 delete mode 100644 lib/fwcfg.c
 create mode 100644 lib/generated/.gitignore
 create mode 100644 lib/libfdt/Makefile.libfdt
 create mode 100644 lib/libfdt/README
 create mode 100644 lib/libfdt/fdt.c
 create mode 100644 lib/libfdt/fdt.h
 create mode 100644 lib/libfdt/fdt_empty_tree.c
 create mode 100644 lib/libfdt/fdt_ro.c
 create mode 100644 lib/libfdt/fdt_rw.c
 create mode 100644 lib/libfdt/fdt_strerror.c
 create mode 100644 lib/libfdt/fdt_sw.c
 create mode 100644 lib/libfdt/fdt_wip.c
 create mode 100644 lib/libfdt/libfdt.h
 create mode 100644 lib/libfdt/libfdt_env.h
 create mode 100644 lib/libfdt/libfdt_internal.h
 create mode 100644 lib/libfdt/version.lds
 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/string.h
 create mode 100644 lib/virtio-testdev.c
 create mode 100644 lib/virtio-testdev.h
 create mode 100644 lib/virtio.c
 create mode 100644 lib/virtio.h
 delete mode 100644 main-ppc.c
 delete mode 100644 powerpc/44x/tlbsx.S
 delete mode 100644 powerpc/44x/tlbwe.S
 delete mode 100644 powerpc/44x/tlbwe_16KB.S
 delete mode 100644 powerpc/44x/tlbwe_hole.S
 delete mode 100644 powerpc/cstart.S
 delete mode 100644 powerpc/exit.c
 delete mode 100644 powerpc/helloworld.c
 delete mode 100644 powerpc/io.S
 delete mode 100644 powerpc/spin.S
 delete mode 100644 powerpc/sprg.S
 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] 54+ messages in thread

* [PATCH v4 01/19] remove unused files
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
@ 2014-04-10 16:56 ` Andrew Jones
  2014-06-06 18:37   ` Christoffer Dall
  2014-04-10 16:56 ` [PATCH v4 02/19] makefile and run_tests tweaks Andrew Jones
                   ` (18 subsequent siblings)
  19 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: 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 f5eccc77047a7..444b6531b8836 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 \
 	lib/report.o
@@ -40,11 +39,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 $@ $^
 
@@ -58,4 +52,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 f734fdee2df18..1bc7dfcac5663 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, &regs);
-	regs.pc = VM_TEST_LOAD_ADDRESS;
-	kvm_set_regs(kvm, n, &regs);
-
-	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] 54+ messages in thread

* [PATCH v4 02/19] makefile and run_tests tweaks
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
  2014-04-10 16:56 ` [PATCH v4 01/19] remove unused files Andrew Jones
@ 2014-04-10 16:56 ` Andrew Jones
  2014-06-06 18:37   ` Christoffer Dall
  2014-04-10 16:56 ` [PATCH v4 03/19] clean root dir of all x86-ness Andrew Jones
                   ` (17 subsequent siblings)
  19 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: 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>
---
v4: no change other than rebase
v3: reword run_tests.sh help text [Christoffer Dall]
---
 Makefile              | 11 ++++++-----
 config-x86-common.mak | 16 +++++++---------
 run_tests.sh          |  6 +++---
 3 files changed, 16 insertions(+), 17 deletions(-)

diff --git a/Makefile b/Makefile
index 444b6531b8836..17307d1dfd760 100644
--- a/Makefile
+++ b/Makefile
@@ -6,16 +6,16 @@ DESTDIR := $(PREFIX)/share/qemu/tests
 .PHONY: arch_clean clean
 
 #make sure env CFLAGS variable is not used
-CFLAGS = -g
+CFLAGS =
 
 libgcc := $(shell $(CC) --print-libgcc-file-name)
 
 libcflat := lib/libcflat.a
 cflatobjs := \
+	lib/argv.o \
 	lib/printf.o \
 	lib/string.o \
 	lib/report.o
-cflatobjs += lib/argv.o
 
 #include architecure specific make rules
 include config-$(ARCH).mak
@@ -26,8 +26,9 @@ 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 += -g
+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.
@@ -52,4 +53,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 aa5a43965aa0c..5815a9a0302c8 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 \
@@ -107,7 +105,7 @@ $(TEST_DIR)/debug.elf: $(cstart.o) $(TEST_DIR)/debug.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..b077091da18b3 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
@@ -92,8 +92,8 @@ 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-x86_64 to
+specify the appropriate qemu binary for x86-run.
 
 EOF
 }
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 03/19] clean root dir of all x86-ness
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
  2014-04-10 16:56 ` [PATCH v4 01/19] remove unused files Andrew Jones
  2014-04-10 16:56 ` [PATCH v4 02/19] makefile and run_tests tweaks Andrew Jones
@ 2014-04-10 16:56 ` Andrew Jones
  2014-06-06 18:37   ` Christoffer Dall
  2014-04-10 16:56 ` [PATCH v4 04/19] add distclean target and gitignore more Andrew Jones
                   ` (16 subsequent siblings)
  19 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: 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>
---
v4: some more doc touch-ups, check for config.mak in run_tests.sh
---
 Makefile                     |   7 ++-
 README                       |  59 ++++++++-------------
 config-i386.mak              |  13 -----
 config-x86-common.mak        | 122 -------------------------------------------
 config-x86_64.mak            |  14 -----
 config/config-i386.mak       |  12 +++++
 config/config-x86-common.mak | 122 +++++++++++++++++++++++++++++++++++++++++++
 config/config-x86_64.mak     |  13 +++++
 configure                    |  17 ++++++
 docs/testdev.txt             |  13 +++++
 flat.lds                     |  21 --------
 run_tests.sh                 |  22 ++++----
 testdev.txt                  |  14 -----
 x86-run                      |  41 ---------------
 x86/README                   |  59 ++++++++++++++++-----
 x86/flat.lds                 |  21 ++++++++
 x86/run                      |  41 +++++++++++++++
 17 files changed, 322 insertions(+), 289 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 17307d1dfd760..566d2bee771e1 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@ cflatobjs := \
 	lib/report.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)
@@ -31,7 +31,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)
 
@@ -46,11 +45,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 0f5d810738de7..e9869d12bfa20 100644
--- a/README
+++ b/README
@@ -1,40 +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
-
-Note that it's not necessary to specify the "-m" option to qemu. The default
-memory size is enough. Actually, the tests infrastructure doesn't support too
-much RAM anyway, so specifying a large amount of RAM may break it.
-
-Or use a runner script to detect the correct invocation:
-./x86-run ./x86/msr.flat
-To select a specific qemu binary, specify the QEMU=<path> environment:
-QEMU=/tmp/qemu/x86_64-softmmu/qemu-system-x86_64 ./x86-run ./x86/msr.flat
-
-The exit status of the binary (and the script) is inconsistent: with
-qemu-system, after the unittest is done, the exit status of qemu is 1,
-different from the 'old style' qemu-kvm, whose exit status in successful
-completion is 0.
+To create the test images do
+  ./configure
+  make
+in this directory. Test images are created in ./<ARCH>/*.flat
+
+Then use the runner script to detect the correct invocation and
+invoke the test, e.g.
+  ./x86-run ./x86/msr.flat
+or
+  ./run_tests.sh
+to run them all.
+
+To select a specific qemu binary, specify the QEMU=<path>
+environment variable, 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
-
+.:		configure script, top-level Makefile, and run_tests.sh
+./config:	collection of architecture dependent makefiles
+./docs:		documentation files
+./lib:		general architecture neutral 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 architecture 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 5815a9a0302c8..0000000000000
--- a/config-x86-common.mak
+++ /dev/null
@@ -1,122 +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)/svm.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
-
-$(TEST_DIR)/debug.elf: $(cstart.o) $(TEST_DIR)/debug.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 a9a2a9e87c3a6..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 $(TEST_DIR)/debug.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..735c43a73c0b3
--- /dev/null
+++ b/config/config-x86-common.mak
@@ -0,0 +1,122 @@
+#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)/svm.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
+
+$(TEST_DIR)/debug.elf: $(cstart.o) $(TEST_DIR)/debug.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..d69252f3d35b1
--- /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 $(TEST_DIR)/debug.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..854fe20d56f66
--- /dev/null
+++ b/docs/testdev.txt
@@ -0,0 +1,13 @@
+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
+			the 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
+
+The test device uses 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 b077091da18b3..4758573183ba7 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -1,8 +1,13 @@
 #!/bin/bash
 
-testroot=x86
-config=$testroot/unittests.cfg
-qemu=${qemu:-qemu-system-x86_64}
+if [ ! -f config.mak ]; then
+    echo "run ./configure && make first. See ./configure -h"
+    exit
+fi
+source config.mak
+
+config=$TEST_DIR/unittests.cfg
+qemu=${QEMU:-qemu-system-$ARCH}
 verbose=0
 
 function run()
@@ -27,7 +32,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 +70,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 +97,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
-specify the appropriate qemu binary for x86-run.
+Set the environment variable QEMU=/path/to/qemu-system-ARCH to
+specify the appropriate qemu binary for ARCH-run.
 
 EOF
 }
 
-# As it happens, config.mak is valid shell script code, too :-)
-source config.mak
-
 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..996ed33546d62 100644
--- a/x86/README
+++ b/x86/README
@@ -1,16 +1,47 @@
+
+Tests for the x86 architecture are run as kernel images for qemu that support
+multiboot format. The tests use an infrastructure called from the bios code.
+The infrastructure initialize the system/cpus, switches to long-mode, and
+calls the 'main' function of the individual test. Tests use a qemu virtual
+test device, named testdev, for services like printing, exiting, querying
+memory size, etc. See file docs/testdev.txt for more details.
+
+Examples of a test invocation:
+ These invocations run the msr test case and outputs to stdio.
+
+ Using qemu-kvm:
+
+	qemu-kvm -device testdev,chardev=testlog \
+		 -chardev file,id=testlog,path=msr.out \
+		 -serial stdio -kernel ./x86/msr.flat
+
+ 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
 
-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
+Legacy notes:
+ The exit status of the binary (and the script) is inconsistent: with
+ qemu-system, after the unit-test 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] 54+ messages in thread

* [PATCH v4 04/19] add distclean target and gitignore more
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
                   ` (2 preceding siblings ...)
  2014-04-10 16:56 ` [PATCH v4 03/19] clean root dir of all x86-ness Andrew Jones
@ 2014-04-10 16:56 ` Andrew Jones
  2014-06-06 18:37   ` Christoffer Dall
  2014-04-10 16:56 ` [PATCH v4 05/19] add 'make cscope' support Andrew Jones
                   ` (15 subsequent siblings)
  19 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: christoffer.dall

also add a check for config.mak in Makefile

Signed-off-by: Andrew Jones <drjones@redhat.com>
---
 .gitignore | 5 +++++
 Makefile   | 9 ++++++++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index d6663ec10caf1..775d0dfd8263e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,8 @@
 patches
 .stgit-*
 cscope.*
+*.swp
+/config.mak
+/*-run
+/test.log
+/msr.out
diff --git a/Makefile b/Makefile
index 566d2bee771e1..7eeece84300df 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,13 @@
 
+ifeq ($(wildcard config.mak),)
+$(error run ./configure first. See ./configure -h)
+endif
+
 include config.mak
 
 DESTDIR := $(PREFIX)/share/qemu/tests
 
-.PHONY: arch_clean clean
+.PHONY: arch_clean clean distclean
 
 #make sure env CFLAGS variable is not used
 CFLAGS =
@@ -53,3 +57,6 @@ install:
 
 clean: arch_clean
 	$(RM) lib/.*.d $(libcflat) $(cflatobjs)
+
+distclean: clean
+	$(RM) config.mak $(TEST_DIR)-run test.log msr.out
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 05/19] add 'make cscope' support
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
                   ` (3 preceding siblings ...)
  2014-04-10 16:56 ` [PATCH v4 04/19] add distclean target and gitignore more Andrew Jones
@ 2014-04-10 16:56 ` Andrew Jones
  2014-06-06 18:38   ` Christoffer Dall
  2014-04-10 16:56 ` [PATCH v4 07/19] libfdt: get libfdt to build Andrew Jones
                   ` (14 subsequent siblings)
  19 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: christoffer.dall

Add a Makefile target to quickly generate arch-specific cscope
for kvm-unit-tests. Assumes a mostly flat directory structure,
i.e. uses '-maxdepth 1' in the file search.

Signed-off-by: Andrew Jones <drjones@redhat.com>
---
 Makefile | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index 7eeece84300df..32ae9a59db5b0 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ include config.mak
 
 DESTDIR := $(PREFIX)/share/qemu/tests
 
-.PHONY: arch_clean clean distclean
+.PHONY: arch_clean clean distclean cscope
 
 #make sure env CFLAGS variable is not used
 CFLAGS =
@@ -59,4 +59,11 @@ clean: arch_clean
 	$(RM) lib/.*.d $(libcflat) $(cflatobjs)
 
 distclean: clean
-	$(RM) config.mak $(TEST_DIR)-run test.log msr.out
+	$(RM) config.mak $(TEST_DIR)-run test.log msr.out cscope.*
+
+cscope: common_dirs = lib
+cscope:
+	$(RM) ./cscope.*
+	find $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
+		-name '*.[chsS]' -print | sed 's,^\./,,' > ./cscope.files
+	cscope -bk
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 07/19] libfdt: get libfdt to build
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
                   ` (4 preceding siblings ...)
  2014-04-10 16:56 ` [PATCH v4 05/19] add 'make cscope' support Andrew Jones
@ 2014-04-10 16:56 ` Andrew Jones
  2014-06-06 18:38   ` Christoffer Dall
  2014-04-10 16:56 ` [PATCH v4 08/19] add support for Linux device trees Andrew Jones
                   ` (13 subsequent siblings)
  19 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: christoffer.dall

Add string functions needed for libfdt, and add a make target.

Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v4: rewrite strchr w/out use of strlen, drop libfdt_env.h modifications
---
 Makefile       | 21 +++++++++++++++++++--
 lib/libcflat.h |  4 ++++
 lib/string.c   | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index 32ae9a59db5b0..fba58e36f272f 100644
--- a/Makefile
+++ b/Makefile
@@ -21,6 +21,13 @@ cflatobjs := \
 	lib/string.o \
 	lib/report.o
 
+# libfdt paths
+LIBFDT_objdir = lib/libfdt
+LIBFDT_srcdir = lib/libfdt
+LIBFDT_archive = $(LIBFDT_objdir)/libfdt.a
+LIBFDT_include = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_INCLUDES))
+LIBFDT_version = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_VERSION))
+
 #include architecure specific make rules
 include config/config-$(ARCH).mak
 
@@ -46,6 +53,11 @@ LDFLAGS += -pthread -lrt
 $(libcflat): $(cflatobjs)
 	$(AR) rcs $@ $^
 
+include $(LIBFDT_srcdir)/Makefile.libfdt
+$(LIBFDT_archive): CFLAGS += -ffreestanding -I lib -I lib/libfdt -Wno-sign-compare
+$(LIBFDT_archive): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS))
+	$(AR) rcs $@ $^
+
 %.o: %.S
 	$(CC) $(CFLAGS) -c -nostdlib -o $@ $<
 
@@ -58,10 +70,15 @@ install:
 clean: arch_clean
 	$(RM) lib/.*.d $(libcflat) $(cflatobjs)
 
-distclean: clean
+libfdt_clean:
+	$(RM) $(LIBFDT_archive) \
+	$(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS)) \
+	$(LIBFDT_objdir)/.*.d
+
+distclean: clean libfdt_clean
 	$(RM) config.mak $(TEST_DIR)-run test.log msr.out cscope.*
 
-cscope: common_dirs = lib
+cscope: common_dirs = lib lib/libfdt
 cscope:
 	$(RM) ./cscope.*
 	find $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
diff --git a/lib/libcflat.h b/lib/libcflat.h
index 1bc7dfcac5663..76448a33cde5f 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -42,6 +42,7 @@ extern void exit(int code);
 extern unsigned long strlen(const char *buf);
 extern char *strcat(char *dest, const char *src);
 extern int strcmp(const char *a, const char *b);
+extern char *strchr(const char *s, int c);
 
 extern int printf(const char *fmt, ...);
 extern int snprintf(char *buf, int size, const char *fmt, ...);
@@ -51,6 +52,9 @@ extern void puts(const char *s);
 
 extern void *memset(void *s, int c, size_t n);
 extern void *memcpy(void *dest, const void *src, size_t n);
+extern int memcmp(const void *s1, const void *s2, size_t n);
+extern void *memmove(void *dest, const void *src, size_t n);
+extern void *memchr(const void *s, int c, size_t n);
 
 extern long atol(const char *ptr);
 #define ARRAY_SIZE(_a)  (sizeof(_a)/sizeof((_a)[0]))
diff --git a/lib/string.c b/lib/string.c
index 3a9caf720bf2b..fe90c8b1289f2 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -31,6 +31,14 @@ int strcmp(const char *a, const char *b)
     return *a - *b;
 }
 
+char *strchr(const char *s, int c)
+{
+    while (*s != (char)c)
+	if (*s++ == '\0')
+	    return NULL;
+    return (char *)s;
+}
+
 void *memset(void *s, int c, size_t n)
 {
     size_t i;
@@ -54,6 +62,46 @@ void *memcpy(void *dest, const void *src, size_t n)
     return dest;
 }
 
+int memcmp(const void *s1, const void *s2, size_t n)
+{
+    const unsigned char *a = s1, *b = s2;
+    int ret = 0;
+
+    while (n--) {
+	ret = *a - *b;
+	if (ret)
+	    break;
+	++a, ++b;
+    }
+    return ret;
+}
+
+void *memmove(void *dest, const void *src, size_t n)
+{
+    const unsigned char *s = src;
+    unsigned char *d = dest;
+
+    if (d <= s) {
+	while (n--)
+	    *d++ = *s++;
+    } else {
+	d += n, s += n;
+	while (n--)
+	    *--d = *--s;
+    }
+    return dest;
+}
+
+void *memchr(const void *s, int c, size_t n)
+{
+    const unsigned char *str = s, chr = (unsigned char)c;
+
+    while (n--)
+	if (*str++ == chr)
+	    return (void *)(str - 1);
+    return NULL;
+}
+
 long atol(const char *ptr)
 {
     long acc = 0;
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 08/19] add support for Linux device trees
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
                   ` (5 preceding siblings ...)
  2014-04-10 16:56 ` [PATCH v4 07/19] libfdt: get libfdt to build Andrew Jones
@ 2014-04-10 16:56 ` Andrew Jones
  2014-06-06 18:38   ` Christoffer Dall
  2014-04-10 16:56 ` [PATCH v4 09/19] libcflat: add abort() and assert() Andrew Jones
                   ` (12 subsequent siblings)
  19 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: christoffer.dall

Add some device tree functions, built on libfdt, to the arch-neutral
lib code in order to facilitate the extraction of boot info and device
base addresses. These functions should work on device trees conforming
to section III of the kernel doc
Documentation/devicetree/booting-without-of.txt.

Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v4: reworked everything, added lots of comments to devicetree.h
---
 lib/devicetree.c | 289 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/devicetree.h | 230 +++++++++++++++++++++++++++++++++++++++++++
 lib/libcflat.h   |   2 +
 3 files changed, 521 insertions(+)
 create mode 100644 lib/devicetree.c
 create mode 100644 lib/devicetree.h

diff --git a/lib/devicetree.c b/lib/devicetree.c
new file mode 100644
index 0000000000000..482028f066346
--- /dev/null
+++ b/lib/devicetree.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include "libcflat.h"
+#include "libfdt/libfdt.h"
+#include "devicetree.h"
+
+static const void *fdt;
+static u32 root_nr_address_cells, root_nr_size_cells;
+
+const void *dt_fdt(void)
+{
+	return fdt;
+}
+
+bool dt_available(void)
+{
+	return fdt_check_header(fdt) == 0;
+}
+
+int dt_get_nr_cells(int fdtnode, u32 *nr_address_cells, u32 *nr_size_cells)
+{
+	const struct fdt_property *prop;
+	u32 *nr_cells;
+	int len;
+
+	prop = fdt_get_property(fdt, fdtnode, "#address-cells", &len);
+	if (prop == NULL)
+		return len;
+
+	nr_cells = (u32 *)prop->data;
+	*nr_address_cells = fdt32_to_cpu(*nr_cells);
+
+	prop = fdt_get_property(fdt, fdtnode, "#size-cells", &len);
+	if (prop == NULL)
+		return len;
+
+	nr_cells = (u32 *)prop->data;
+	*nr_size_cells = fdt32_to_cpu(*nr_cells);
+
+	return 0;
+}
+
+void dt_reg_init(struct dt_reg *reg, u32 nr_address_cells, u32 nr_size_cells)
+{
+	memset(reg, 0, sizeof(struct dt_reg));
+	reg->nr_address_cells = nr_address_cells;
+	reg->nr_size_cells = nr_size_cells;
+}
+
+int dt_get_reg(int fdtnode, int regidx, struct dt_reg *reg)
+{
+	const struct fdt_property *prop;
+	u32 *cells, i;
+	unsigned nr_tuple_cells;
+	int len;
+
+	prop = fdt_get_property(fdt, fdtnode, "reg", &len);
+	if (prop == NULL)
+		return len;
+
+	cells = (u32 *)prop->data;
+	nr_tuple_cells = reg->nr_address_cells + reg->nr_size_cells;
+	regidx *= nr_tuple_cells;
+
+	if (regidx + nr_tuple_cells > len/sizeof(u32))
+		return -FDT_ERR_NOTFOUND;
+
+	for (i = 0; i < reg->nr_address_cells; ++i)
+		reg->address_cells[i] = fdt32_to_cpu(cells[regidx + i]);
+
+	regidx += reg->nr_address_cells;
+	for (i = 0; i < reg->nr_size_cells; ++i)
+		reg->size_cells[i] = fdt32_to_cpu(cells[regidx + i]);
+
+	return 0;
+}
+
+int dt_pbus_translate_node(int fdtnode, int regidx, void *reg)
+{
+	struct dt_pbus_reg *pbus_reg = (struct dt_pbus_reg *)reg;
+	struct dt_reg raw_reg;
+	int ret;
+
+	dt_reg_init(&raw_reg, root_nr_address_cells, root_nr_size_cells);
+
+	ret = dt_get_reg(fdtnode, regidx, &raw_reg);
+	if (ret < 0)
+		return ret;
+
+	pbus_reg->addr = dt_pbus_read_cells(raw_reg.nr_address_cells,
+					    raw_reg.address_cells);
+	pbus_reg->size = dt_pbus_read_cells(raw_reg.nr_size_cells,
+					    raw_reg.size_cells);
+
+	return 0;
+}
+
+int dt_pbus_translate(const struct dt_device *dev, int regidx,
+		      void *reg)
+{
+	return dt_pbus_translate_node(dev->fdtnode, regidx, reg);
+}
+
+int dt_pbus_get_baseaddr(const struct dt_device *dev, dt_pbus_addr_t *base)
+{
+	struct dt_pbus_reg reg;
+	int ret;
+
+	ret = dt_pbus_translate(dev, 0, &reg);
+	if (ret < 0)
+		return ret;
+
+	*base = reg.addr;
+	return 0;
+}
+
+int dt_bus_match_any(const struct dt_device *dev __unused, int fdtnode)
+{
+	/* matches any device with a valid node */
+	return fdtnode < 0 ? fdtnode : 1;
+}
+
+static const struct dt_bus dt_default_bus = {
+	.match = dt_bus_match_any,
+	.translate = dt_pbus_translate,
+};
+
+void dt_bus_init_defaults(struct dt_bus *bus)
+{
+	memcpy(bus, &dt_default_bus, sizeof(struct dt_bus));
+}
+
+void dt_device_init(struct dt_device *dev, const struct dt_bus *bus,
+		    const void *info)
+{
+	memset(dev, 0, sizeof(struct dt_device));
+	dev->bus = bus;
+	dev->info = (void *)info;
+}
+
+int dt_device_find_compatible(const struct dt_device *dev,
+			      const char *compatible)
+{
+	int node, ret;
+
+	node = fdt_node_offset_by_compatible(fdt, -1, compatible);
+	while (node >= 0) {
+		ret = dev->bus->match(dev, node);
+		if (ret < 0)
+			return ret;
+		else if (ret)
+			break;
+		node = fdt_node_offset_by_compatible(fdt, node, compatible);
+	}
+	return node;
+}
+
+int dt_pbus_get_baseaddr_compatible(const char *compatible,
+				    dt_pbus_addr_t *baseaddr)
+{
+	struct dt_device dev;
+	int node, ret;
+
+	dt_device_init(&dev, &dt_default_bus, NULL);
+
+	node = dt_device_find_compatible(&dev, compatible);
+	if (node < 0)
+		return node;
+
+	dt_device_bind_node(&dev, node);
+
+	ret = dt_pbus_get_baseaddr(&dev, baseaddr);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+int dt_get_memory_params(struct dt_pbus_reg *regs, int nr_regs)
+{
+	const char *pn = "device_type", *pv = "memory";
+	int node, ret, pl = strlen(pv) + 1, nr = 0;
+	struct dt_pbus_reg reg;
+
+	node = fdt_node_offset_by_prop_value(fdt, -1, pn, pv, pl);
+
+	while (node >= 0) {
+
+		while (nr < nr_regs) {
+			ret = dt_pbus_translate_node(node, nr, &reg);
+			if (ret == -FDT_ERR_NOTFOUND)
+				break;
+			if (ret < 0)
+				return ret;
+			regs[nr].addr = reg.addr;
+			regs[nr].size = reg.size;
+			++nr;
+		}
+
+		node = fdt_node_offset_by_prop_value(fdt, node, pn, pv, pl);
+	}
+
+	return node != -FDT_ERR_NOTFOUND ? node : nr;
+}
+
+int dt_for_each_cpu_node(void (*func)(int fdtnode, u32 regval, void *info),
+			 void *info)
+{
+	const struct fdt_property *prop;
+	int cpus, cpu, ret, len;
+	struct dt_reg raw_reg;
+	u32 nac, nsc;
+
+	cpus = fdt_path_offset(fdt, "/cpus");
+	if (cpus < 0)
+		return cpus;
+
+	ret = dt_get_nr_cells(cpus, &nac, &nsc);
+	if (ret < 0)
+		return ret;
+
+	dt_reg_init(&raw_reg, nac, nsc);
+
+	dt_for_each_subnode(cpus, cpu) {
+
+		prop = fdt_get_property(fdt, cpu, "device_type", &len);
+		if (prop == NULL)
+			return len;
+
+		if (len != 4 || strcmp((char *)prop->data, "cpu"))
+			continue;
+
+		ret = dt_get_reg(cpu, 0, &raw_reg);
+		if (ret < 0)
+			return ret;
+
+		func(cpu, raw_reg.address_cells[0], info);
+	}
+
+	return 0;
+}
+
+int dt_get_bootargs(const char **bootargs)
+{
+	const struct fdt_property *prop;
+	int node, len;
+
+	*bootargs = NULL;
+
+	node = fdt_path_offset(fdt, "/chosen");
+	if (node < 0)
+		return node;
+
+	prop = fdt_get_property(fdt, node, "bootargs", &len);
+	if (prop)
+		*bootargs = (char *)prop->data;
+	else if (len < 0 && len != -FDT_ERR_NOTFOUND)
+		return len;
+
+	return 0;
+}
+
+int dt_init(const void *fdt_ptr)
+{
+	struct dt_bus *defbus = (struct dt_bus *)&dt_default_bus;
+	int root, ret;
+
+	ret = fdt_check_header(fdt_ptr);
+	if (ret < 0)
+		return ret;
+	fdt = fdt_ptr;
+
+	root = fdt_path_offset(fdt, "/");
+	if (root < 0)
+		return root;
+
+	ret = dt_get_nr_cells(root, &root_nr_address_cells,
+				    &root_nr_size_cells);
+	if (ret < 0)
+		return ret;
+
+	defbus->nr_address_cells = root_nr_address_cells;
+	defbus->nr_size_cells = root_nr_size_cells;
+
+	return 0;
+}
diff --git a/lib/devicetree.h b/lib/devicetree.h
new file mode 100644
index 0000000000000..032b5497f9db1
--- /dev/null
+++ b/lib/devicetree.h
@@ -0,0 +1,230 @@
+#ifndef _DEVICETREE_H_
+#define _DEVICETREE_H_
+/*
+ * devicetree builds on libfdt to implement abstractions and accessors
+ * for Linux required device tree content. The accessors provided are
+ * common across architectures. See section III of the kernel doc
+ * Documentation/devicetree/booting-without-of.txt
+ *
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include "libcflat.h"
+#include "libfdt/libfdt.h"
+
+/**********************************************************************
+ * devicetree init and libfdt helpers
+ **********************************************************************/
+
+/* dt_init initializes devicetree with a pointer to an fdt, @fdt_ptr */
+extern int dt_init(const void *fdt_ptr);
+
+/* get the fdt pointer that devicetree is using */
+const void *dt_fdt(void);
+
+/* check for an initialized, valid devicetree */
+extern bool dt_available(void);
+
+/* traverse child nodes */
+#define dt_for_each_subnode(n, s)					\
+	for (s = fdt_first_subnode(dt_fdt(), n);			\
+	     s != -FDT_ERR_NOTFOUND;					\
+	     s = fdt_next_subnode(dt_fdt(), s))
+
+/**********************************************************************
+ * Abstractions for required node types and properties
+ **********************************************************************/
+
+struct dt_device {
+	int fdtnode;
+	const struct dt_bus *bus;
+
+	/*
+	 * info is a pointer to device specific data, which may be
+	 * used by the bus match() and translate() functions
+	 */
+	void *info;
+};
+
+struct dt_bus {
+	/*
+	 * match a device @dev to an fdt node @fdtnode
+	 * returns
+	 *  - a positive value on match
+	 *  - zero on no match
+	 *  - a negative FDT_ERR_* value on failure
+	 */
+	int (*match)(const struct dt_device *dev, int fdtnode);
+
+	/*
+	 * translate the @regidx'th "address size" tuple of
+	 * @dev's fdt node's "reg" property, and store the result
+	 * in @reg, a bus specific structure
+	 * returns
+	 *  - zero on success
+	 *  - a negative FDT_ERR_* value on failure
+	 */
+	int (*translate)(const struct dt_device *dev, int regidx, void *reg);
+
+	/* the bus #address-cells and #size-cells properties */
+	u32 nr_address_cells, nr_size_cells;
+};
+
+/* dt_bus_match_any matches any fdt node, i.e. it always returns true */
+extern int dt_bus_match_any(const struct dt_device *dev, int fdtnode);
+
+/* the processor bus (pbus) address type and register tuple */
+typedef u64 dt_pbus_addr_t;
+struct dt_pbus_reg {
+	dt_pbus_addr_t addr;
+	dt_pbus_addr_t size;
+};
+
+static inline dt_pbus_addr_t dt_pbus_read_cells(u32 nr_cells, u32 *cells)
+{
+	return nr_cells == 2 ? ((u64)cells[0] << 32) | cells[1]
+		: nr_cells == 1 ? cells[0] : (~0ULL);
+}
+
+/*
+ * dt_pbus_translate translates device node regs for the
+ * processor bus using the root node's #address-cells and
+ * #size-cells and dt_pbus_read_cells()
+ * returns
+ *  - zero on success
+ *  - a negative FDT_ERR_* value on failure
+ */
+extern int dt_pbus_translate(const struct dt_device *dev, int regidx,
+			     void *reg);
+
+/*
+ * dt_pbus_translate_node is the same as dt_pbus_translate but
+ * operates on an fdt node instead of a dt_device
+ */
+extern int dt_pbus_translate_node(int fdtnode, int regidx, void *reg);
+
+/*
+ * dt_pbus_get_baseaddr is a shortcut for
+ *     dt_pbus_translate(dev, 0, &reg);
+ *     *base = reg.addr;
+ * returns
+ *  - zero on success
+ *  - a negative FDT_ERR_* value on failure
+ */
+extern int dt_pbus_get_baseaddr(const struct dt_device *dev,
+				dt_pbus_addr_t *base);
+
+/*
+ * dt_bus_init_defaults initializes @bus with
+ *  match		<- dt_bus_match_any
+ *  translate		<- dt_pbus_translate
+ *  nr_address_cells	<- #address-cells of the root node
+ *  nr_size_cells	<- #size-cells of the root node
+ */
+extern void dt_bus_init_defaults(struct dt_bus *bus);
+
+/*
+ * dt_device_init initializes a dt_device with the given parameters
+ */
+extern void dt_device_init(struct dt_device *dev, const struct dt_bus *bus,
+			   const void *info);
+
+static inline void dt_device_bind_node(struct dt_device *dev, int fdtnode)
+{
+	dev->fdtnode = fdtnode;
+}
+
+/*
+ * dt_device_find_compatible finds a @compatible node
+ * returns
+ *  - node (>= 0) on success
+ *  - a negative FDT_ERR_* value on failure
+ */
+extern int dt_device_find_compatible(const struct dt_device *dev,
+				     const char *compatible);
+
+/*
+ * dt_pbus_get_baseaddr_compatible simply bundles many functions into
+ * one. It finds the first @compatible fdt node and then translates the
+ * 0th reg tuple (the base address) using the processor bus translation,
+ * and finally stores that address in @baseaddr.
+ * returns
+ *  - zero on success
+ *  - a negative FDT_ERR_* value on failure
+ */
+extern int dt_pbus_get_baseaddr_compatible(const char *compatible,
+					   dt_pbus_addr_t *baseaddr);
+
+/**********************************************************************
+ * Low-level accessors for required node types and properties
+ **********************************************************************/
+
+/*
+ * dt_get_nr_cells sets @nr_address_cells and @nr_size_cells to the
+ * #address-cells and #size-cells properties of @fdtnode
+ * returns
+ *  - zero on success
+ *  - a negative FDT_ERR_* value on failure
+ */
+extern int dt_get_nr_cells(int fdtnode, u32 *nr_address_cells,
+					u32 *nr_size_cells);
+
+/* dt_reg is a structure for "raw" reg tuples */
+#define MAX_ADDRESS_CELLS	4
+#define MAX_SIZE_CELLS		4
+struct dt_reg {
+	u32 nr_address_cells, nr_size_cells;
+	u32 address_cells[MAX_ADDRESS_CELLS];
+	u32 size_cells[MAX_SIZE_CELLS];
+};
+
+/*
+ * dt_reg_init initialize a dt_reg struct to zero and sets
+ * nr_address_cells and nr_size_cells to @nr_address_cells and
+ * @nr_size_cells respectively.
+ */
+extern void dt_reg_init(struct dt_reg *reg, u32 nr_address_cells,
+					    u32 nr_size_cells);
+
+/*
+ * dt_get_reg gets the @regidx'th reg tuple of @fdtnode's reg property
+ * and stores it in @reg. @reg must be initialized.
+ * returns
+ *  - zero on success
+ *  - a negative FDT_ERR_* value on failure
+ */
+extern int dt_get_reg(int fdtnode, int regidx, struct dt_reg *reg);
+
+/**********************************************************************
+ * High-level accessors for required node types and properties
+ **********************************************************************/
+
+/*
+ * dt_get_bootargs gets a pointer to /chosen/bootargs
+ * returns
+ *  - zero on success
+ *  - a negative FDT_ERR_* value on failure
+ */
+extern int dt_get_bootargs(const char **bootargs);
+
+/*
+ * dt_get_memory_params gets the memory parameters from the /memory node(s)
+ * storing each memory region ("address size" tuple) in consecutive entries
+ * of @regs, up to @nr_regs
+ * returns
+ *  - number of memory regions found on success
+ *  - a negative FDT_ERR_* value on failure
+ */
+extern int dt_get_memory_params(struct dt_pbus_reg *regs, int nr_regs);
+
+/*
+ * dt_for_each_cpu_node runs @func on each cpu node in the /cpus node
+ * passing it its fdt node, its reg property value, and @info
+ *  - zero on success
+ *  - a negative FDT_ERR_* value on failure
+ */
+extern int dt_for_each_cpu_node(void (*func)(int fdtnode, u32 regval,
+				void *info), void *info);
+
+#endif /* _DEVICETREE_H_ */
diff --git a/lib/libcflat.h b/lib/libcflat.h
index 76448a33cde5f..99d1cd533dd03 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -22,6 +22,8 @@
 
 #include <stdarg.h>
 
+#define __unused __attribute__((__unused__))
+
 typedef unsigned char u8;
 typedef signed char s8;
 typedef unsigned short u16;
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 09/19] libcflat: add abort() and assert()
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
                   ` (6 preceding siblings ...)
  2014-04-10 16:56 ` [PATCH v4 08/19] add support for Linux device trees Andrew Jones
@ 2014-04-10 16:56 ` Andrew Jones
  2014-06-06 18:38   ` Christoffer Dall
  2014-04-10 16:56 ` [PATCH v4 10/19] Introduce asm-generic/*.h files Andrew Jones
                   ` (11 subsequent siblings)
  19 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: christoffer.dall

The test framework may have external dependencies. assert() provides
the ability to abort when those dependencies aren't met. However,
assert() should only be used for unlikely conditions. We can provide
more informative messages with printf() for the more likely problems.

Signed-off-by: Andrew Jones <drjones@redhat.com>
---
 lib/libcflat.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/lib/libcflat.h b/lib/libcflat.h
index 99d1cd533dd03..c7c31be1cc8e5 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -67,4 +67,13 @@ extern long atol(const char *ptr);
 
 void report(const char *msg_fmt, bool pass, ...);
 int report_summary(void);
+
+#define abort() exit(64)		/* 129 exit status from qemu */
+#define assert(cond)							\
+do {									\
+	if (!(cond))							\
+		printf("%s:%d: assert failed\n", __FILE__, __LINE__),	\
+		abort();						\
+} while (0)
+
 #endif
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 10/19] Introduce asm-generic/*.h files
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
                   ` (7 preceding siblings ...)
  2014-04-10 16:56 ` [PATCH v4 09/19] libcflat: add abort() and assert() Andrew Jones
@ 2014-04-10 16:56 ` Andrew Jones
  2014-06-06 18:39   ` Christoffer Dall
  2014-04-10 16:56 ` [PATCH v4 11/19] add minimal virtio support for devtree virtio-mmio Andrew Jones
                   ` (10 subsequent siblings)
  19 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: christoffer.dall

Architecture neutral code may need to call low-level io accessors,
or use spinlocks. Create a generic io.h to ensure those accessors
are defined, and a generic spinlock.h that complains when included,
as we can't write a generic spinlock. These files can be overridden
or extended by architecture specific versions placed in
lib/$ARCH/asm/.

Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v4: introduce lib/asm symlink to get rid of #ifdef __arm__,
    add spinlock.h too
v3: wrt to io.h (was libio.[ch]) only
    - get rid of CONFIG_64BIT, replace with asserts
    - get rid of {read,write}_len() [libio.c]
    - fix bad *64_to_cpu macros
---
 .gitignore                 |   1 +
 Makefile                   |   6 +-
 configure                  |  11 ++++
 lib/asm-generic/io.h       | 154 +++++++++++++++++++++++++++++++++++++++++++++
 lib/asm-generic/spinlock.h |   4 ++
 5 files changed, 173 insertions(+), 3 deletions(-)
 create mode 100644 lib/asm-generic/io.h
 create mode 100644 lib/asm-generic/spinlock.h

diff --git a/.gitignore b/.gitignore
index 775d0dfd8263e..e21939a8771e9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@ patches
 .stgit-*
 cscope.*
 *.swp
+/lib/asm
 /config.mak
 /*-run
 /test.log
diff --git a/Makefile b/Makefile
index fba58e36f272f..51cacdac00615 100644
--- a/Makefile
+++ b/Makefile
@@ -76,11 +76,11 @@ libfdt_clean:
 	$(LIBFDT_objdir)/.*.d
 
 distclean: clean libfdt_clean
-	$(RM) config.mak $(TEST_DIR)-run test.log msr.out cscope.*
+	$(RM) lib/asm config.mak $(TEST_DIR)-run test.log msr.out cscope.*
 
-cscope: common_dirs = lib lib/libfdt
+cscope: common_dirs = lib lib/libfdt lib/asm lib/asm-generic
 cscope:
 	$(RM) ./cscope.*
-	find $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
+	find -L $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
 		-name '*.[chsS]' -print | sed 's,^\./,,' > ./cscope.files
 	cscope -bk
diff --git a/configure b/configure
index 6cfc64943f6e6..8a81bf92e27b7 100755
--- a/configure
+++ b/configure
@@ -95,6 +95,17 @@ if [ $exit -eq 0 ]; then
 fi
 rm -f lib_test.c
 
+# link lib/asm for the architecture
+rm -f lib/asm
+asm=asm-generic
+if [ -d lib/$arch/asm ]; then
+	asm=$arch/asm
+elif [ -d lib/$testdir/asm ]; then
+	asm=$testdir/asm
+fi
+ln -s $asm lib/asm
+
+# create the config
 cat <<EOF > config.mak
 PREFIX=$prefix
 KERNELDIR=$(readlink -f $kerneldir)
diff --git a/lib/asm-generic/io.h b/lib/asm-generic/io.h
new file mode 100644
index 0000000000000..34569c99ae270
--- /dev/null
+++ b/lib/asm-generic/io.h
@@ -0,0 +1,154 @@
+#ifndef _ASM_GENERIC_IO_H_
+#define _ASM_GENERIC_IO_H_
+/*
+ * asm-generic/io.h
+ *  adapted from the Linux kernel's include/asm-generic/io.h
+ *  and arch/arm/include/asm/io.h
+ *
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include "libcflat.h"
+
+#ifndef __raw_readb
+static inline u8 __raw_readb(const volatile void *addr)
+{
+	return *(const volatile u8 *)addr;
+}
+#endif
+
+#ifndef __raw_readw
+static inline u16 __raw_readw(const volatile void *addr)
+{
+	return *(const volatile u16 *)addr;
+}
+#endif
+
+#ifndef __raw_readl
+static inline u32 __raw_readl(const volatile void *addr)
+{
+	return *(const volatile u32 *)addr;
+}
+#endif
+
+#ifndef __raw_readq
+static inline u64 __raw_readq(const volatile void *addr)
+{
+	assert(sizeof(unsigned long) == sizeof(u64));
+	return *(const volatile u64 *)addr;
+}
+#endif
+
+#ifndef __raw_writeb
+static inline void __raw_writeb(u8 b, volatile void *addr)
+{
+	*(volatile u8 *)addr = b;
+}
+#endif
+
+#ifndef __raw_writew
+static inline void __raw_writew(u16 b, volatile void *addr)
+{
+	*(volatile u16 *)addr = b;
+}
+#endif
+
+#ifndef __raw_writel
+static inline void __raw_writel(u32 b, volatile void *addr)
+{
+	*(volatile u32 *)addr = b;
+}
+#endif
+
+#ifndef __raw_writeq
+static inline void __raw_writeq(u64 b, volatile void *addr)
+{
+	assert(sizeof(unsigned long) == sizeof(u64));
+	*(volatile u64 *)addr = b;
+}
+#endif
+
+#ifndef __bswap16
+static inline u16 __bswap16(u16 x)
+{
+	return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
+}
+#endif
+
+#ifndef __bswap32
+static inline u32 __bswap32(u32 x)
+{
+	return ((x & 0xff000000) >> 24) | ((x & 0x00ff0000) >>  8) |
+	       ((x & 0x0000ff00) <<  8) | ((x & 0x000000ff) << 24);
+}
+#endif
+
+#ifndef __bswap64
+static inline u64 __bswap64(u64 x)
+{
+	return ((x & 0x00000000000000ffULL) << 56) |
+	       ((x & 0x000000000000ff00ULL) << 40) |
+	       ((x & 0x0000000000ff0000ULL) << 24) |
+	       ((x & 0x00000000ff000000ULL) <<  8) |
+	       ((x & 0x000000ff00000000ULL) >>  8) |
+	       ((x & 0x0000ff0000000000ULL) >> 24) |
+	       ((x & 0x00ff000000000000ULL) >> 40) |
+	       ((x & 0xff00000000000000ULL) >> 56);
+}
+#endif
+
+#ifndef __cpu_is_be
+#define __cpu_is_be() (0)
+#endif
+
+#define le16_to_cpu(x) \
+	({ u16 __r = __cpu_is_be() ? __bswap16(x) : (x); __r; })
+#define cpu_to_le16 le16_to_cpu
+
+#define le32_to_cpu(x) \
+	({ u32 __r = __cpu_is_be() ? __bswap32(x) : (x); __r; })
+#define cpu_to_le32 le32_to_cpu
+
+#define le64_to_cpu(x) \
+	({ u64 __r = __cpu_is_be() ? __bswap64(x) : (x); __r; })
+#define cpu_to_le64 le64_to_cpu
+
+#define be16_to_cpu(x) \
+	({ u16 __r = !__cpu_is_be() ? __bswap16(x) : (x); __r; })
+#define cpu_to_be16 be16_to_cpu
+
+#define be32_to_cpu(x) \
+	({ u32 __r = !__cpu_is_be() ? __bswap32(x) : (x); __r; })
+#define cpu_to_be32 be32_to_cpu
+
+#define be64_to_cpu(x) \
+	({ u64 __r = !__cpu_is_be() ? __bswap64(x) : (x); __r; })
+#define cpu_to_be64 be64_to_cpu
+
+#ifndef rmb
+#define rmb() do { } while (0)
+#endif
+#ifndef wmb
+#define wmb() do { } while (0)
+#endif
+
+#define readb(addr) \
+	({ u8 __r = __raw_readb(addr); rmb(); __r; })
+#define readw(addr) \
+	({ u16 __r = le16_to_cpu(__raw_readw(addr)); rmb(); __r; })
+#define readl(addr) \
+	({ u32 __r = le32_to_cpu(__raw_readl(addr)); rmb(); __r; })
+#define readq(addr) \
+	({ u64 __r = le64_to_cpu(__raw_readq(addr)); rmb(); __r; })
+
+#define writeb(b, addr) \
+	({ wmb(); __raw_writeb(b, addr); })
+#define writew(b, addr) \
+	({ wmb(); __raw_writew(cpu_to_le16(b), addr); })
+#define writel(b, addr) \
+	({ wmb(); __raw_writel(cpu_to_le32(b), addr); })
+#define writeq(b, addr) \
+	({ wmb(); __raw_writeq(cpu_to_le64(b), addr); })
+
+#endif /* _ASM_GENERIC_IO_H_ */
diff --git a/lib/asm-generic/spinlock.h b/lib/asm-generic/spinlock.h
new file mode 100644
index 0000000000000..31417442e3330
--- /dev/null
+++ b/lib/asm-generic/spinlock.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_GENERIC_SPINLOCK_H_
+#define _ASM_GENERIC_SPINLOCK_H_
+#error need architecture specific asm/spinlock.h
+#endif
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 11/19] add minimal virtio support for devtree virtio-mmio
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
                   ` (8 preceding siblings ...)
  2014-04-10 16:56 ` [PATCH v4 10/19] Introduce asm-generic/*.h files Andrew Jones
@ 2014-04-10 16:56 ` Andrew Jones
  2014-06-06 18:39   ` Christoffer Dall
  2014-04-10 16:56 ` [PATCH v4 12/19] Introduce virtio-testdev Andrew Jones
                   ` (9 subsequent siblings)
  19 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: christoffer.dall

Support the bare minimum of virtio to enable access to the virtio-mmio
config space of a device. Currently this implementation must use a
device tree to find the device.

Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v4:
 - split from the virtio-testdev patch
 - search a table to "discover" that the device must be DT/virtio-mmio,
   which doesn't change anything, but looks less hacky than comments
   saying the device must be DT/virtio-mmio...
 - manage own pool of virtio-mmio pre-allocated device structures in
   order to avoid needing access to the heap
---
 lib/libcflat.h |   3 ++
 lib/virtio.c   | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/virtio.h   |  89 +++++++++++++++++++++++++++++++
 3 files changed, 258 insertions(+)
 create mode 100644 lib/virtio.c
 create mode 100644 lib/virtio.h

diff --git a/lib/libcflat.h b/lib/libcflat.h
index c7c31be1cc8e5..5bb66d01dfc53 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -62,6 +62,9 @@ extern long atol(const char *ptr);
 #define ARRAY_SIZE(_a)  (sizeof(_a)/sizeof((_a)[0]))
 
 #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
+#define container_of(ptr, type, member) ({				\
+	const typeof( ((type *)0)->member ) *__mptr = (ptr);		\
+	(type *)( (char *)__mptr - offsetof(type,member) );})
 
 #define NULL ((void *)0UL)
 
diff --git a/lib/virtio.c b/lib/virtio.c
new file mode 100644
index 0000000000000..e7161ff591e4c
--- /dev/null
+++ b/lib/virtio.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include "libcflat.h"
+#include "devicetree.h"
+#include "asm/spinlock.h"
+#include "asm/io.h"
+#include "virtio.h"
+
+enum virtio_hwdesc_type {
+	VIRTIO_HWDESC_TYPE_DT = 0,	/* device tree */
+	NR_VIRTIO_HWDESC_TYPES,
+};
+
+enum virtio_bus_type {
+	VIRTIO_BUS_TYPE_MMIO = 0,	/* virtio-mmio */
+	NR_VIRTIO_BUS_TYPES,
+};
+
+struct virtio_bind_bus {
+	bool (*hwdesc_probe)(void);
+	struct virtio_dev *(*device_bind)(u32 devid);
+};
+
+static struct virtio_dev *vm_dt_device_bind(u32 devid);
+
+static struct virtio_bind_bus
+virtio_bind_busses[NR_VIRTIO_HWDESC_TYPES][NR_VIRTIO_BUS_TYPES] = {
+
+[VIRTIO_HWDESC_TYPE_DT] = {
+
+	[VIRTIO_BUS_TYPE_MMIO] = {
+		.hwdesc_probe = dt_available,
+		.device_bind = vm_dt_device_bind,
+	},
+},
+};
+
+struct virtio_dev *virtio_bind(u32 devid)
+{
+	struct virtio_bind_bus *bus;
+	struct virtio_dev *dev;
+	int i, j;
+
+	for (i = 0; i < NR_VIRTIO_HWDESC_TYPES; ++i) {
+		for (j = 0; j < NR_VIRTIO_BUS_TYPES; ++j) {
+
+			bus = &virtio_bind_busses[i][j];
+
+			if (!bus->hwdesc_probe())
+				continue;
+
+			dev = bus->device_bind(devid);
+			if (dev)
+				return dev;
+		}
+	}
+
+	return NULL;
+}
+
+/******************************************************
+ * virtio-mmio support (config space only)
+ ******************************************************/
+
+static void vm_get(struct virtio_dev *vdev, unsigned offset,
+		   void *buf, unsigned len)
+{
+	struct virtio_mmio_dev *vmdev = to_virtio_mmio_dev(vdev);
+	u8 *p = buf;
+	unsigned i;
+
+	for (i = 0; i < len; ++i)
+		p[i] = readb(vmdev->base + VIRTIO_MMIO_CONFIG + offset + i);
+}
+
+static void vm_set(struct virtio_dev *vdev, unsigned offset,
+		   const void *buf, unsigned len)
+{
+	struct virtio_mmio_dev *vmdev = to_virtio_mmio_dev(vdev);
+	const u8 *p = buf;
+	unsigned i;
+
+	for (i = 0; i < len; ++i)
+		writeb(p[i], vmdev->base + VIRTIO_MMIO_CONFIG + offset + i);
+}
+
+#define NR_VM_DEVICES 32
+static struct spinlock vm_lock;
+static struct virtio_mmio_dev vm_devs[NR_VM_DEVICES];
+static struct virtio_conf_ops vm_confs[NR_VM_DEVICES];
+static int nr_vm_devs;
+
+static struct virtio_mmio_dev *vm_new_device(u32 devid)
+{
+	struct virtio_mmio_dev *vmdev;
+
+	if (nr_vm_devs >= NR_VM_DEVICES)
+		return NULL;
+
+	spin_lock(&vm_lock);
+	vmdev = &vm_devs[nr_vm_devs];
+	vmdev->vdev.config = &vm_confs[nr_vm_devs];
+	++nr_vm_devs;
+	spin_unlock(&vm_lock);
+
+	vmdev->vdev.id.device = devid;
+	vmdev->vdev.id.vendor = -1;
+	vmdev->vdev.config->get = vm_get;
+	vmdev->vdev.config->set = vm_set;
+
+	return vmdev;
+}
+
+/******************************************************
+ * virtio-mmio device tree support
+ ******************************************************/
+
+struct vm_dt_info {
+	u32 devid;
+	void *base;
+};
+
+static int vm_dt_match(const struct dt_device *dev, int fdtnode)
+{
+	struct vm_dt_info *info = (struct vm_dt_info *)dev->info;
+	dt_pbus_addr_t base;
+
+	dt_device_bind_node((struct dt_device *)dev, fdtnode);
+
+	assert(dt_pbus_get_baseaddr(dev, &base) == 0);
+	assert(sizeof(long) == 8 || !(base >> 32));
+
+	info->base = (void *)(unsigned long)base;
+
+	return readl(info->base + VIRTIO_MMIO_DEVICE_ID) == info->devid;
+}
+
+static struct virtio_dev *vm_dt_device_bind(u32 devid)
+{
+	struct virtio_mmio_dev *vmdev;
+	struct dt_device dt_dev;
+	struct dt_bus dt_bus;
+	struct vm_dt_info info;
+	int node;
+
+	dt_bus_init_defaults(&dt_bus);
+	dt_bus.match = vm_dt_match;
+
+	info.devid = devid;
+
+	dt_device_init(&dt_dev, &dt_bus, &info);
+
+	node = dt_device_find_compatible(&dt_dev, "virtio,mmio");
+	assert(node >= 0 || node == -FDT_ERR_NOTFOUND);
+
+	if (node == -FDT_ERR_NOTFOUND)
+		return NULL;
+
+	vmdev = vm_new_device(devid);
+	vmdev->base = info.base;
+
+	return &vmdev->vdev;
+}
diff --git a/lib/virtio.h b/lib/virtio.h
new file mode 100644
index 0000000000000..163b9912c4e05
--- /dev/null
+++ b/lib/virtio.h
@@ -0,0 +1,89 @@
+#ifndef _VIRTIO_H_
+#define _VIRTIO_H_
+/*
+ * A minimal implementation of virtio for virtio-mmio config space
+ * access.
+ *
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include "libcflat.h"
+
+struct virtio_devid {
+	u32 device;
+	u32 vendor;
+};
+
+struct virtio_dev {
+	struct virtio_devid id;
+	struct virtio_conf_ops *config;
+};
+
+struct virtio_conf_ops {
+	void (*get)(struct virtio_dev *vdev, unsigned offset,
+		    void *buf, unsigned len);
+	void (*set)(struct virtio_dev *vdev, unsigned offset,
+		    const void *buf, unsigned len);
+};
+
+extern struct virtio_dev *virtio_bind(u32 devid);
+
+static inline u8
+virtio_config_readb(struct virtio_dev *vdev, unsigned offset)
+{
+	u8 val;
+	vdev->config->get(vdev, offset, &val, 1);
+	return val;
+}
+
+static inline u16
+virtio_config_readw(struct virtio_dev *vdev, unsigned offset)
+{
+	u16 val;
+	vdev->config->get(vdev, offset, &val, 2);
+	return val;
+}
+
+static inline u32
+virtio_config_readl(struct virtio_dev *vdev, unsigned offset)
+{
+	u32 val;
+	vdev->config->get(vdev, offset, &val, 4);
+	return val;
+}
+
+static inline void
+virtio_config_writeb(struct virtio_dev *vdev, unsigned offset, u8 val)
+{
+	vdev->config->set(vdev, offset, &val, 1);
+}
+
+static inline void
+virtio_config_writew(struct virtio_dev *vdev, unsigned offset, u16 val)
+{
+	vdev->config->set(vdev, offset, &val, 2);
+}
+
+static inline void
+virtio_config_writel(struct virtio_dev *vdev, unsigned offset, u32 val)
+{
+	vdev->config->set(vdev, offset, &val, 4);
+}
+
+/******************************************************
+ * virtio-mmio
+ ******************************************************/
+
+#define VIRTIO_MMIO_DEVICE_ID	0x008
+#define VIRTIO_MMIO_CONFIG	0x100
+
+#define to_virtio_mmio_dev(vdev_ptr) \
+	container_of(vdev_ptr, struct virtio_mmio_dev, vdev)
+
+struct virtio_mmio_dev {
+	struct virtio_dev vdev;
+	void *base;
+};
+
+#endif /* _VIRTIO_H_ */
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 12/19] Introduce virtio-testdev
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
                   ` (9 preceding siblings ...)
  2014-04-10 16:56 ` [PATCH v4 11/19] add minimal virtio support for devtree virtio-mmio Andrew Jones
@ 2014-04-10 16:56 ` Andrew Jones
  2014-06-06 18:39   ` Christoffer Dall
  2014-04-10 16:56 ` [PATCH v4 13/19] libcflat: clean up libcflat.h and add string.h Andrew Jones
                   ` (8 subsequent siblings)
  19 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: 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>
---
v4: couple tweaks (added spinlock), no functional changes
---
 lib/virtio-testdev.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/virtio-testdev.h |  18 +++++++
 2 files changed, 155 insertions(+)
 create mode 100644 lib/virtio-testdev.c
 create mode 100644 lib/virtio-testdev.h

diff --git a/lib/virtio-testdev.c b/lib/virtio-testdev.c
new file mode 100644
index 0000000000000..3ece6ae58fdc5
--- /dev/null
+++ b/lib/virtio-testdev.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include "libcflat.h"
+#include "asm/spinlock.h"
+#include "virtio.h"
+
+#define TESTDEV_NAME		"virtio-testdev"
+#define VIRTIO_ID_TESTDEV	0xffff
+#define TESTDEV_MAJOR_VER	1
+#define TESTDEV_MINOR_VER	1
+
+#define VIRTIO_CONFIG_SIZE	64
+
+enum {
+	VERSION = 1,
+	CLEAR,
+	EXIT,
+};
+
+#define TOKEN_OFFSET		0x0
+#define NARGS_OFFSET		0x4
+#define NRETS_OFFSET		0x8
+#define ARG_OFFSET(n)		(0xc + (n) * 4)
+#define __RET_OFFSET(nargs, n)	(ARG_OFFSET(nargs) + (n) * 4)
+
+static struct spinlock lock;
+static struct virtio_dev *vdev;
+
+static u32 testdev_readl(unsigned offset)
+{
+	assert(offset <= (VIRTIO_CONFIG_SIZE - 4));
+	return virtio_config_readl(vdev, offset);
+}
+
+static void testdev_writel(unsigned offset, u32 val)
+{
+	assert(offset <= (VIRTIO_CONFIG_SIZE - 4));
+	virtio_config_writel(vdev, offset, val);
+}
+
+/*
+ * We have to write all args; nargs, nrets, ... first to avoid executing
+ * the token's operation until all args are in place. Then issue the op,
+ * and then read the return values. Reading the return values (or just
+ * sanity checking by reading token) will read a zero into qemu's copy
+ * of the token, which allows us to prepare additional ops without
+ * re-executing the last one.
+ */
+void virtio_testdev(u32 token, u32 nargs, u32 nrets, ...)
+{
+	va_list va;
+	unsigned off;
+	u32 n;
+
+	if (!vdev)
+		return;
+
+	spin_lock(&lock);
+
+	testdev_writel(NARGS_OFFSET, nargs);
+	testdev_writel(NRETS_OFFSET, nrets);
+
+	va_start(va, nrets);
+
+	off = ARG_OFFSET(0);
+	n = nargs;
+	while (n--) {
+		testdev_writel(off, va_arg(va, unsigned));
+		off += 4;
+	}
+
+	/* this runs the op, but then resets token to zero */
+	testdev_writel(TOKEN_OFFSET, token);
+	assert(testdev_readl(TOKEN_OFFSET) == 0);
+
+	off = __RET_OFFSET(nargs, 0);
+	n = nrets;
+	while (n--) {
+		u32 *r = va_arg(va, unsigned *);
+		*r = testdev_readl(off);
+		off += 4;
+	}
+
+	spin_unlock(&lock);
+	va_end(va);
+}
+
+void virtio_testdev_version(u32 *version)
+{
+	virtio_testdev(VERSION, 0, 1, version);
+}
+
+void virtio_testdev_clear(void)
+{
+	virtio_testdev(CLEAR, 0, 0);
+}
+
+void virtio_testdev_exit(int code)
+{
+	virtio_testdev(EXIT, 1, 0, code);
+}
+
+void virtio_testdev_init(void)
+{
+	u16 major, minor;
+	u32 version;
+
+	vdev = virtio_bind(VIRTIO_ID_TESTDEV);
+	if (vdev == NULL) {
+		printf("%s: can't find " TESTDEV_NAME ". "
+		       "Is '-device " TESTDEV_NAME "' "
+		       "on the qemu command line?\n", __func__);
+		abort();
+	}
+
+	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("%s: incompatible version of " TESTDEV_NAME ": "
+		       "major = %d, minor = %d. Update %s\n",
+		       __func__, major, minor, u);
+		abort();
+	}
+
+	if (minor > TESTDEV_MINOR_VER)
+		printf("%s: " TESTDEV_NAME " has new features. "
+		       "An update of kvm-unit-tests may be possible.\n",
+		       __func__);
+}
diff --git a/lib/virtio-testdev.h b/lib/virtio-testdev.h
new file mode 100644
index 0000000000000..bed9eaf4aca4b
--- /dev/null
+++ b/lib/virtio-testdev.h
@@ -0,0 +1,18 @@
+#ifndef _VIRTIO_TESTDEV_H_
+#define _VIRTIO_TESTDEV_H_
+/*
+ * virtio-testdev is a driver for the virtio-testdev qemu device.
+ * The virtio-testdev device exposes a simple control interface to
+ * qemu for kvm-unit-tests through virtio.
+ *
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#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] 54+ messages in thread

* [PATCH v4 13/19] libcflat: clean up libcflat.h and add string.h
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
                   ` (10 preceding siblings ...)
  2014-04-10 16:56 ` [PATCH v4 12/19] Introduce virtio-testdev Andrew Jones
@ 2014-04-10 16:56 ` Andrew Jones
  2014-06-06 18:39   ` Christoffer Dall
  2014-04-10 16:56 ` [PATCH v4 14/19] printf: support field padding Andrew Jones
                   ` (7 subsequent siblings)
  19 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: christoffer.dall

Use libgcc's stddef.h and stdint.h, and then remove the redundant
defines from libcflat.h. Also separate out the string function
declarations into a new file string.h. These changes have no affect
on code including libcflat.h, but are needed in order to compile an
unmodified libfdt for kvm-unit-tests using an arm cross-compiler.
While at it, add strcpy.

Signed-off-by: Andrew Jones <drjones@redhat.com>
---
 lib/libcflat.h | 55 +++++++++++++++++++++----------------------------------
 lib/string.c   |  6 ++++++
 lib/string.h   | 15 +++++++++++++++
 3 files changed, 42 insertions(+), 34 deletions(-)
 create mode 100644 lib/string.h

diff --git a/lib/libcflat.h b/lib/libcflat.h
index 5bb66d01dfc53..f6c071c71f0b9 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -21,57 +21,44 @@
 #define __LIBCFLAT_H
 
 #include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include "string.h"
 
 #define __unused __attribute__((__unused__))
 
-typedef unsigned char u8;
-typedef signed char s8;
-typedef unsigned short u16;
-typedef signed short s16;
-typedef unsigned u32;
-typedef signed s32;
-typedef unsigned long ulong;
-typedef unsigned long long u64;
-typedef signed long long s64;
-typedef unsigned long size_t;
-typedef _Bool bool;
-
-#define true 1
+typedef uint8_t		u8;
+typedef int8_t		s8;
+typedef uint16_t	u16;
+typedef int16_t		s16;
+typedef uint32_t	u32;
+typedef int32_t		s32;
+typedef uint64_t	u64;
+typedef int64_t		s64;
+typedef unsigned long	ulong;
+
+typedef _Bool		bool;
 #define false 0
+#define true  1
 
+extern void puts(const char *s);
 extern void exit(int code);
 
-extern unsigned long strlen(const char *buf);
-extern char *strcat(char *dest, const char *src);
-extern int strcmp(const char *a, const char *b);
-extern char *strchr(const char *s, int c);
-
 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 long atol(const char *ptr);
 
-extern void puts(const char *s);
-
-extern void *memset(void *s, int c, size_t n);
-extern void *memcpy(void *dest, const void *src, size_t n);
-extern int memcmp(const void *s1, const void *s2, size_t n);
-extern void *memmove(void *dest, const void *src, size_t n);
-extern void *memchr(const void *s, int c, size_t n);
+void report(const char *msg_fmt, bool pass, ...);
+int report_summary(void);
 
-extern long atol(const char *ptr);
-#define ARRAY_SIZE(_a)  (sizeof(_a)/sizeof((_a)[0]))
+#define ARRAY_SIZE(_a) (sizeof(_a)/sizeof((_a)[0]))
 
-#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
 #define container_of(ptr, type, member) ({				\
 	const typeof( ((type *)0)->member ) *__mptr = (ptr);		\
 	(type *)( (char *)__mptr - offsetof(type,member) );})
 
-#define NULL ((void *)0UL)
-
-void report(const char *msg_fmt, bool pass, ...);
-int report_summary(void);
-
-#define abort() exit(64)		/* 129 exit status from qemu */
+#define abort() exit(64) /* 129 exit status from qemu */
 #define assert(cond)							\
 do {									\
 	if (!(cond))							\
diff --git a/lib/string.c b/lib/string.c
index fe90c8b1289f2..026f50252287c 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -20,6 +20,12 @@ char *strcat(char *dest, const char *src)
     return dest;
 }
 
+char *strcpy(char *dest, const char *src)
+{
+    *dest = 0;
+    return strcat(dest, src);
+}
+
 int strcmp(const char *a, const char *b)
 {
     while (*a == *b) {
diff --git a/lib/string.h b/lib/string.h
new file mode 100644
index 0000000000000..dbab368b1b9e4
--- /dev/null
+++ b/lib/string.h
@@ -0,0 +1,15 @@
+#ifndef __STRING_H
+#define __STRING_H
+
+extern unsigned long strlen(const char *buf);
+extern char *strcat(char *dest, const char *src);
+extern char *strcpy(char *dest, const char *src);
+extern int strcmp(const char *a, const char *b);
+extern char *strchr(const char *s, int c);
+extern void *memset(void *s, int c, size_t n);
+extern void *memcpy(void *dest, const void *src, size_t n);
+extern int memcmp(const void *s1, const void *s2, size_t n);
+extern void *memmove(void *dest, const void *src, size_t n);
+extern void *memchr(const void *s, int c, size_t n);
+
+#endif /* _STRING_H */
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 14/19] printf: support field padding
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
                   ` (11 preceding siblings ...)
  2014-04-10 16:56 ` [PATCH v4 13/19] libcflat: clean up libcflat.h and add string.h Andrew Jones
@ 2014-04-10 16:56 ` Andrew Jones
  2014-06-06 18:39   ` Christoffer Dall
  2014-04-10 16:56 ` [PATCH v4 15/19] arm: initial drop Andrew Jones
                   ` (6 subsequent siblings)
  19 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: christoffer.dall

Support format flags for field padding, such as "%08x", allowing
register dumps to be easier on the eyes.

Signed-off-by: Andrew Jones <drjones@redhat.com>
---
 lib/printf.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 68 insertions(+), 14 deletions(-)

diff --git a/lib/printf.c b/lib/printf.c
index 867eb1926f742..89308fb26b7d2 100644
--- a/lib/printf.c
+++ b/lib/printf.c
@@ -6,6 +6,11 @@ typedef struct pstream {
     int added;
 } pstream_t;
 
+typedef struct strprops {
+    char pad;
+    int npad;
+} strprops_t;
+
 static void addchar(pstream_t *p, char c)
 {
     if (p->remain) {
@@ -15,15 +20,35 @@ static void addchar(pstream_t *p, char c)
     ++p->added;
 }
 
-void print_str(pstream_t *p, const char *s)
+void print_str(pstream_t *p, const char *s, strprops_t props)
 {
+    const char *s_orig = s;
+    int npad = props.npad;
+
+    if (npad > 0) {
+	npad -= strlen(s_orig);
+	while (npad > 0) {
+	    addchar(p, props.pad);
+	    --npad;
+	}
+    }
+
     while (*s)
 	addchar(p, *s++);
+
+    if (npad < 0) {
+	props.pad = ' '; /* ignore '0' flag with '-' flag */
+	npad += strlen(s_orig);
+	while (npad < 0) {
+	    addchar(p, props.pad);
+	    ++npad;
+	}
+    }
 }
 
 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, int base, strprops_t props)
 {
     char buf[sizeof(long) * 3 + 2], *p = buf;
     int s = 0, i;
@@ -54,10 +79,11 @@ void print_int(pstream_t *ps, long long n, int base)
 
     *p = 0;
 
-    print_str(ps, buf);
+    print_str(ps, buf, props);
 }
 
-void print_unsigned(pstream_t *ps, unsigned long long n, int base)
+void print_unsigned(pstream_t *ps, unsigned long long n, int base,
+		    strprops_t props)
 {
     char buf[sizeof(long) * 3 + 1], *p = buf;
     int i;
@@ -80,7 +106,23 @@ void print_unsigned(pstream_t *ps, unsigned long long n, int base)
 
     *p = 0;
 
-    print_str(ps, buf);
+    print_str(ps, buf, props);
+}
+
+static int fmtnum(const char **fmt)
+{
+    const char *f = *fmt;
+    int len = 0, num;
+
+    if (*f == '-')
+	++f, ++len;
+
+    while (*f >= '0' && *f <= '9')
+	++f, ++len;
+
+    num = atol(*fmt);
+    *fmt += len;
+    return num;
 }
 
 int vsnprintf(char *buf, int size, const char *fmt, va_list va)
@@ -93,6 +135,9 @@ int vsnprintf(char *buf, int size, const char *fmt, va_list va)
     while (*fmt) {
 	char f = *fmt++;
 	int nlong = 0;
+	strprops_t props;
+	memset(&props, 0, sizeof(props));
+	props.pad = ' ';
 
 	if (f != '%') {
 	    addchar(&s, f);
@@ -110,41 +155,50 @@ int vsnprintf(char *buf, int size, const char *fmt, va_list va)
 	case '\0':
 	    --fmt;
 	    break;
+	case '0':
+	    props.pad = '0';
+	    ++fmt;
+	    /* fall through */
+	case '1'...'9':
+	case '-':
+	    --fmt;
+	    props.npad = fmtnum(&fmt);
+	    goto morefmt;
 	case 'l':
 	    ++nlong;
 	    goto morefmt;
 	case 'd':
 	    switch (nlong) {
 	    case 0:
-		print_int(&s, va_arg(va, int), 10);
+		print_int(&s, va_arg(va, int), 10, props);
 		break;
 	    case 1:
-		print_int(&s, va_arg(va, long), 10);
+		print_int(&s, va_arg(va, long), 10, props);
 		break;
 	    default:
-		print_int(&s, va_arg(va, long long), 10);
+		print_int(&s, va_arg(va, long long), 10, props);
 		break;
 	    }
 	    break;
 	case 'x':
 	    switch (nlong) {
 	    case 0:
-		print_unsigned(&s, va_arg(va, unsigned), 16);
+		print_unsigned(&s, va_arg(va, unsigned), 16, props);
 		break;
 	    case 1:
-		print_unsigned(&s, va_arg(va, unsigned long), 16);
+		print_unsigned(&s, va_arg(va, unsigned long), 16, props);
 		break;
 	    default:
-		print_unsigned(&s, va_arg(va, unsigned long long), 16);
+		print_unsigned(&s, va_arg(va, unsigned long long), 16, props);
 		break;
 	    }
 	    break;
 	case 'p':
-	    print_str(&s, "0x");
-	    print_unsigned(&s, (unsigned long)va_arg(va, void *), 16);
+	    print_str(&s, "0x", props);
+	    print_unsigned(&s, (unsigned long)va_arg(va, void *), 16, props);
 	    break;
 	case 's':
-	    print_str(&s, va_arg(va, const char *));
+	    print_str(&s, va_arg(va, const char *), props);
 	    break;
 	default:
 	    addchar(&s, f);
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 15/19] arm: initial drop
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
                   ` (12 preceding siblings ...)
  2014-04-10 16:56 ` [PATCH v4 14/19] printf: support field padding Andrew Jones
@ 2014-04-10 16:56 ` Andrew Jones
  2014-06-06 18:39   ` Christoffer Dall
  2014-04-10 16:56 ` [PATCH v4 16/19] arm: Add spinlock implementation Andrew Jones
                   ` (5 subsequent siblings)
  19 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: christoffer.dall

This is the initial drop of the arm test framework and a first test
that just checks that setup completed (a selftest). kvm isn't needed
to run this test unless testing with smp > 1.

Try it out with
  yum install gcc-arm-linux-gnu
  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>
---
v4:
  - moved fdt to just after stacktop (it was in the middle of free memory)
  - switched from using heap to memregions
  - get nr_cpus and added smp=<num> test
  - added barrier.h
  - use new report()/report_summary()
  - config/config-arm.mak cleanup
---
 arm/cstart.S           |  35 ++++++++++++
 arm/flat.lds           |  18 +++++++
 arm/run                |  31 +++++++++++
 arm/selftest.c         |  87 ++++++++++++++++++++++++++++++
 arm/unittests.cfg      |  18 +++++++
 config/config-arm.mak  |  72 +++++++++++++++++++++++++
 configure              |  12 ++++-
 lib/argv.c             |   6 +++
 lib/arm/asm/barrier.h  |  18 +++++++
 lib/arm/asm/io.h       |  24 +++++++++
 lib/arm/asm/setup.h    |  39 ++++++++++++++
 lib/arm/asm/spinlock.h |  16 ++++++
 lib/arm/eabi_compat.c  |  20 +++++++
 lib/arm/io.c           |  66 +++++++++++++++++++++++
 lib/arm/setup.c        | 142 +++++++++++++++++++++++++++++++++++++++++++++++++
 15 files changed, 602 insertions(+), 2 deletions(-)
 create mode 100644 arm/cstart.S
 create mode 100644 arm/flat.lds
 create mode 100755 arm/run
 create mode 100644 arm/selftest.c
 create mode 100644 arm/unittests.cfg
 create mode 100644 config/config-arm.mak
 create mode 100644 lib/arm/asm/barrier.h
 create mode 100644 lib/arm/asm/io.h
 create mode 100644 lib/arm/asm/setup.h
 create mode 100644 lib/arm/asm/spinlock.h
 create mode 100644 lib/arm/eabi_compat.c
 create mode 100644 lib/arm/io.c
 create mode 100644 lib/arm/setup.c

diff --git a/arm/cstart.S b/arm/cstart.S
new file mode 100644
index 0000000000000..e28251db2950d
--- /dev/null
+++ b/arm/cstart.S
@@ -0,0 +1,35 @@
+/*
+ * Boot entry point and assembler functions for armv7 tests.
+ *
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+
+.arm
+
+.section .init
+
+.globl start
+start:
+	/*
+	 * bootloader params are in r0-r2
+	 * See the kernel doc Documentation/arm/Booting
+	 */
+	ldr	sp, =stacktop
+	bl	setup
+
+	/* run the test */
+	ldr	r0, =__argc
+	ldr	r0, [r0]
+	ldr	r1, =__argv
+	bl	main
+	bl	exit
+	b	halt
+
+.text
+
+.globl halt
+halt:
+1:	wfi
+	b	1b
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..985b26e1334da
--- /dev/null
+++ b/arm/run
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+if [ ! -f config.mak ]; then
+	echo run ./configure first. See ./configure -h
+	exit 2
+fi
+source config.mak
+
+qemu="${QEMU:-qemu-system-arm}"
+testdev=virtio-testdev
+
+if ! $qemu -device '?' 2>&1 | grep $testdev > /dev/null; then
+	qpath=$(which $qemu 2>/dev/null)
+	if [ "$qpath" ]; then
+		echo $qpath doesn\'t support virtio-testdev. Exiting.
+	else
+		echo $qemu not found.
+	fi
+	exit 2
+fi
+
+command="$qemu -device $testdev -display none -serial stdio "
+command+="-M virt -cpu $PROCESSOR "
+#command+="-enable-kvm "
+command+="-kernel"
+
+echo $command "$@"
+$command "$@"
+ret=$?
+echo Return value from qemu: $ret
+exit $ret
diff --git a/arm/selftest.c b/arm/selftest.c
new file mode 100644
index 0000000000000..45729e9ac85d9
--- /dev/null
+++ b/arm/selftest.c
@@ -0,0 +1,87 @@
+/*
+ * Test the framework itself. These tests confirm that setup works.
+ *
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include "libcflat.h"
+#include "asm/setup.h"
+
+#define TESTGRP "selftest"
+
+static char testnam[64];
+
+static void testnam_set(const char *subtest)
+{
+	strcpy(testnam, TESTGRP);
+	strcat(testnam, "::");
+	strcat(testnam, subtest);
+}
+
+static void assert_args(int num_args, int needed_args)
+{
+	if (num_args < needed_args) {
+		printf("%s: not enough arguments\n", testnam);
+		abort();
+	}
+}
+
+static char *split_var(char *s, long *val)
+{
+	char *p;
+
+	p = strchr(s, '=');
+	if (!p)
+		return NULL;
+
+	*val = atol(p+1);
+	*p = '\0';
+
+	return s;
+}
+
+static void check_setup(int argc, char **argv)
+{
+	int nr_tests = 0, i;
+	char *var;
+	long val;
+
+	for (i = 0; i < argc; ++i) {
+
+		var = split_var(argv[i], &val);
+		if (!var)
+			continue;
+
+		if (strcmp(argv[i], "mem") == 0) {
+
+			phys_addr_t memsize =
+					memregions[nr_memregions-1].addr
+					+ memregions[nr_memregions-1].size
+					- PHYS_OFFSET;
+			phys_addr_t expected = ((phys_addr_t)val)*1024*1024;
+
+			report("%s[%s]", memsize == expected, testnam, "mem");
+			++nr_tests;
+
+		} else if (strcmp(argv[i], "smp") == 0) {
+
+			report("%s[%s]", nr_cpus == (int)val, testnam, "smp");
+			++nr_tests;
+		}
+	}
+
+	assert_args(nr_tests, 2);
+}
+
+int main(int argc, char **argv)
+{
+	assert_args(argc, 1);
+
+	testnam_set(argv[0]);
+
+	if (strcmp(argv[0], "setup") == 0)
+		check_setup(argc-1, &argv[1]);
+
+	return report_summary();
+}
diff --git a/arm/unittests.cfg b/arm/unittests.cfg
new file mode 100644
index 0000000000000..da9dfd7b1f118
--- /dev/null
+++ b/arm/unittests.cfg
@@ -0,0 +1,18 @@
+# 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 test case is specific to one
+# groups = group1 group2 # Used to identify test cases with run_tests -g ...
+
+#
+# Test that the configured number of processors (smp = <num>), and
+# that the configured amount of memory (-m <MB>) are correctly setup
+# by the framework.
+#
+[selftest::setup]
+file = selftest.flat
+smp  = 1
+extra_params = -m 256 -append 'setup smp=1 mem=256'
+groups = selftest
diff --git a/config/config-arm.mak b/config/config-arm.mak
new file mode 100644
index 0000000000000..915b1cc318d79
--- /dev/null
+++ b/config/config-arm.mak
@@ -0,0 +1,72 @@
+#
+# arm makefile
+#
+# Authors: Andrew Jones <drjones@redhat.com>
+#
+
+tests-common = \
+	$(TEST_DIR)/selftest.flat
+
+tests =
+
+all: test_cases
+
+##################################################################
+bits = 32
+ldarch = elf32-littlearm
+
+ifeq ($(LOADADDR),)
+	LOADADDR = 0x40000000
+endif
+phys_base = $(LOADADDR)
+kernel_offset = 0x10000
+
+CFLAGS += -D__arm__
+CFLAGS += -marm
+CFLAGS += -mcpu=$(PROCESSOR)
+CFLAGS += -std=gnu99
+CFLAGS += -ffreestanding
+CFLAGS += -Wextra
+CFLAGS += -O2
+CFLAGS += -I lib -I lib/libfdt
+
+cflatobjs += \
+	lib/devicetree.o \
+	lib/virtio.o \
+	lib/virtio-testdev.o \
+	lib/arm/io.o \
+	lib/arm/setup.o
+
+libeabi = lib/arm/libeabi.a
+eabiobjs = lib/arm/eabi_compat.o
+
+libgcc := $(shell $(CC) -m$(ARCH) --print-libgcc-file-name)
+start_addr := $(shell printf "%x\n" $$(( $(phys_base) + $(kernel_offset) )))
+
+FLATLIBS = $(libcflat) $(LIBFDT_archive) $(libgcc) $(libeabi)
+%.elf: LDFLAGS = $(CFLAGS) -nostdlib
+%.elf: %.o $(FLATLIBS) arm/flat.lds
+	$(CC) $(LDFLAGS) -o $@ \
+		-Wl,-T,arm/flat.lds,--build-id=none,-Ttext=$(start_addr) \
+		$(filter %.o, $^) $(FLATLIBS)
+
+%.flat: %.elf
+	$(OBJCOPY) -O binary $^ $@
+
+$(libeabi): $(eabiobjs)
+	$(AR) rcs $@ $^
+
+arch_clean: libfdt_clean
+	$(RM) $(TEST_DIR)/*.{o,flat,elf} $(libeabi) $(eabiobjs) \
+	      $(TEST_DIR)/.*.d lib/arm/.*.d
+
+##################################################################
+
+tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg
+
+cstart.o = $(TEST_DIR)/cstart.o
+
+test_cases: $(tests-common) $(tests)
+
+$(TEST_DIR)/selftest.elf: $(cstart.o) $(TEST_DIR)/selftest.o
+
diff --git a/configure b/configure
index 8a81bf92e27b7..f92f585724bb1 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,12 @@ while [[ "$1" = -* ]]; do
 	    ;;
     esac
 done
+[ -z "$processor" ] && processor="$arch"
+
+if [ "$processor" = "arm" ]; then
+    processor="cortex-a15"
+fi
+
 if [ -z "$testdir" -a \( "$arch" = "i386" -o "$arch" = "x86_64" \) ]; then
     testdir=x86
 elif [ -z "$testdir" ]; then
@@ -80,6 +86,7 @@ if [ -f $testdir/run ]; then
 fi
 
 # check for dependent 32 bit libraries
+if [ "$arch" != "arm" ]; then
 cat << EOF > lib_test.c
 #include <stdc++.h>
 #include <boost_thread-mt.h>
@@ -94,6 +101,7 @@ if [ $exit -eq 0 ]; then
     api=true
 fi
 rm -f lib_test.c
+fi
 
 # link lib/asm for the architecture
 rm -f lib/asm
diff --git a/lib/argv.c b/lib/argv.c
index 4ee54a6eeac3e..078a05faffebf 100644
--- a/lib/argv.c
+++ b/lib/argv.c
@@ -31,3 +31,9 @@ void __setup_args(void)
     }
     __argc = argv - __argv;
 }
+
+void setup_args(char *args)
+{
+    __args = args;
+    __setup_args();
+}
diff --git a/lib/arm/asm/barrier.h b/lib/arm/asm/barrier.h
new file mode 100644
index 0000000000000..acaeab5123431
--- /dev/null
+++ b/lib/arm/asm/barrier.h
@@ -0,0 +1,18 @@
+#ifndef _ASMARM_BARRIER_H_
+#define _ASMARM_BARRIER_H_
+/*
+ * Adapted form arch/arm/include/asm/barrier.h
+ */
+
+#define isb(option) __asm__ __volatile__ ("isb " #option : : : "memory")
+#define dsb(option) __asm__ __volatile__ ("dsb " #option : : : "memory")
+#define dmb(option) __asm__ __volatile__ ("dmb " #option : : : "memory")
+
+#define mb()		dsb()
+#define rmb()		dsb()
+#define wmb()		dsb(st)
+#define smp_mb()	dmb(ish)
+#define smp_rmb()	smp_mb()
+#define smp_wmb()	dmb(ishst)
+
+#endif /* _ASMARM_BARRIER_H_ */
diff --git a/lib/arm/asm/io.h b/lib/arm/asm/io.h
new file mode 100644
index 0000000000000..51ec6e9aa2e99
--- /dev/null
+++ b/lib/arm/asm/io.h
@@ -0,0 +1,24 @@
+#ifndef _ASMARM_IO_H_
+#define _ASMARM_IO_H_
+#include "libcflat.h"
+#include "asm/barrier.h"
+
+#define __bswap16 bswap16
+static inline u16 bswap16(u16 val)
+{
+	u16 ret;
+	asm volatile("rev16 %0, %1" : "=r" (ret) :  "r" (val));
+	return ret;
+}
+
+#define __bswap32 bswap32
+static inline u32 bswap32(u32 val)
+{
+	u32 ret;
+	asm volatile("rev %0, %1" : "=r" (ret) :  "r" (val));
+	return ret;
+}
+
+#include "asm-generic/io.h"
+
+#endif /* _ASMARM_IO_H_ */
diff --git a/lib/arm/asm/setup.h b/lib/arm/asm/setup.h
new file mode 100644
index 0000000000000..d451b23434041
--- /dev/null
+++ b/lib/arm/asm/setup.h
@@ -0,0 +1,39 @@
+#ifndef _ASMARM_SETUP_H_
+#define _ASMARM_SETUP_H_
+/*
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include "libcflat.h"
+
+#define NR_CPUS			8
+extern u32 cpus[NR_CPUS];
+extern int nr_cpus;
+
+typedef u64 phys_addr_t;
+
+#define NR_MEMREGIONS		16
+struct memregion {
+	phys_addr_t addr;
+	phys_addr_t size;
+	bool free;
+};
+
+extern struct memregion memregions[NR_MEMREGIONS];
+extern int nr_memregions;
+
+extern struct memregion *memregion_new(phys_addr_t size);
+extern void memregions_show(void);
+
+#define PHYS_OFFSET		({ memregions[0].addr; })
+#define PHYS_SHIFT		40
+#define PHYS_SIZE		(1ULL << PHYS_SHIFT)
+#define PHYS_MASK		(PHYS_SIZE - 1ULL)
+
+#define PAGE_SHIFT		12
+#define PAGE_SIZE		(1UL << PAGE_SHIFT)
+#define PAGE_MASK		(~(PAGE_SIZE - 1UL))
+#define PAGE_ALIGN(addr)	(((addr) + (PAGE_SIZE-1UL)) & PAGE_MASK)
+
+#endif /* _ASMARM_SETUP_H_ */
diff --git a/lib/arm/asm/spinlock.h b/lib/arm/asm/spinlock.h
new file mode 100644
index 0000000000000..04f5a1a5538e2
--- /dev/null
+++ b/lib/arm/asm/spinlock.h
@@ -0,0 +1,16 @@
+#ifndef _ASMARM_SPINLOCK_H_
+#define _ASMARM_SPINLOCK_H_
+
+struct spinlock {
+	int v;
+};
+
+//TODO
+static inline void spin_lock(struct spinlock *lock __unused)
+{
+}
+static inline void spin_unlock(struct spinlock *lock __unused)
+{
+}
+
+#endif /* _ASMARM_SPINLOCK_H_ */
diff --git a/lib/arm/eabi_compat.c b/lib/arm/eabi_compat.c
new file mode 100644
index 0000000000000..59d624dcd9277
--- /dev/null
+++ b/lib/arm/eabi_compat.c
@@ -0,0 +1,20 @@
+/*
+ * Adapted from u-boot's arch/arm/lib/eabi_compat.c
+ */
+#include "libcflat.h"
+
+int raise(int signum __unused)
+{
+	printf("Divide by zero!\n");
+	abort();
+	return 0;
+}
+
+/* Dummy functions to avoid linker complaints */
+void __aeabi_unwind_cpp_pr0(void)
+{
+}
+
+void __aeabi_unwind_cpp_pr1(void)
+{
+}
diff --git a/lib/arm/io.c b/lib/arm/io.c
new file mode 100644
index 0000000000000..c865f61c94934
--- /dev/null
+++ b/lib/arm/io.c
@@ -0,0 +1,66 @@
+/*
+ * Each architecture must implement puts() and exit() with the I/O
+ * devices exposed from QEMU, e.g. pl011 and virtio-testdev. That's
+ * what's done here, along with initialization functions for those
+ * devices.
+ *
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include "libcflat.h"
+#include "devicetree.h"
+#include "virtio-testdev.h"
+#include "asm/spinlock.h"
+#include "asm/io.h"
+
+extern void halt(int code);
+
+/*
+ * Use this guess for the pl011 base in order to make an attempt at
+ * having earlier printf support. We'll overwrite it with the real
+ * base address that we read from the device tree later.
+ */
+#define QEMU_MACH_VIRT_PL011_BASE 0x09000000UL
+
+static struct spinlock uart_lock;
+static volatile u8 *uart0_base = (u8 *)QEMU_MACH_VIRT_PL011_BASE;
+
+static void uart0_init(void)
+{
+	const char *compatible = "arm,pl011";
+	dt_pbus_addr_t base;
+	int ret;
+
+	ret = dt_pbus_get_baseaddr_compatible(compatible, &base);
+	assert(ret == 0 || ret == -FDT_ERR_NOTFOUND);
+
+	if (ret == 0) {
+		assert(sizeof(long) == 8 || !(base >> 32));
+		uart0_base = (u8 *)(unsigned long)base;
+	} else {
+		printf("%s: %s not found in the device tree, aborting...\n",
+			__func__, compatible);
+		abort();
+	}
+}
+
+void io_init(void)
+{
+	uart0_init();
+	virtio_testdev_init();
+}
+
+void puts(const char *s)
+{
+	spin_lock(&uart_lock);
+	while (*s)
+		writel(*s++, uart0_base);
+	spin_unlock(&uart_lock);
+}
+
+void exit(int code)
+{
+	virtio_testdev_exit(code);
+	halt(code);
+}
diff --git a/lib/arm/setup.c b/lib/arm/setup.c
new file mode 100644
index 0000000000000..3794291e94e01
--- /dev/null
+++ b/lib/arm/setup.c
@@ -0,0 +1,142 @@
+/*
+ * Initialize machine setup information and I/O.
+ *
+ * After running setup() a flat file knows how many cpus it has
+ * (nr_cpus), how much free memory it has, and at what physical
+ * address that free memory starts (memregions[1].{addr,size}),
+ * printf() and exit() will both work, and (argc, argv) are ready
+ * to be passed to main().
+ *
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include "libcflat.h"
+#include "libfdt/libfdt.h"
+#include "devicetree.h"
+#include "asm/spinlock.h"
+#include "asm/setup.h"
+
+extern unsigned long stacktop;
+extern void io_init(void);
+extern void setup_args(const char *args);
+
+u32 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0UL) };
+int nr_cpus;
+
+static struct spinlock memregion_lock;
+struct memregion memregions[NR_MEMREGIONS];
+int nr_memregions;
+
+static void cpu_set(int fdtnode __unused, u32 regval, void *info)
+{
+	unsigned *i = (unsigned *)info;
+	cpus[*i] = regval;
+	*i += 1;
+}
+
+static void cpu_init(void)
+{
+	unsigned i = 0;
+	assert(dt_for_each_cpu_node(cpu_set, &i) == 0);
+	nr_cpus = i;
+}
+
+static void memregions_init(phys_addr_t freemem_start)
+{
+	/* we only expect one membank to be defined in the DT */
+	struct dt_pbus_reg regs[1];
+	phys_addr_t addr, size, mem_end;
+
+	nr_memregions = dt_get_memory_params(regs, 1);
+
+	assert(nr_memregions > 0);
+
+	addr = regs[0].addr;
+	size = regs[0].size;
+	mem_end = addr + size;
+
+	assert(!(addr & ~PHYS_MASK) && !((mem_end-1) & ~PHYS_MASK));
+
+#ifdef __arm__
+	/* TODO: support highmem? */
+	assert(!((u64)addr >> 32) && !((u64)(mem_end-1) >> 32));
+#endif
+
+	freemem_start = PAGE_ALIGN(freemem_start);
+
+	memregions[0].addr = PAGE_ALIGN(addr);
+	memregions[0].size = freemem_start - PHYS_OFFSET;
+
+	memregions[1].addr = freemem_start;
+	memregions[1].size = mem_end - freemem_start;
+	memregions[1].free = true;
+	nr_memregions = 2;
+}
+
+struct memregion *memregion_new(phys_addr_t size)
+{
+	phys_addr_t freemem_start, freemem_size, mem_end;
+	struct memregion *m;
+
+	spin_lock(&memregion_lock);
+
+	assert(memregions[nr_memregions-1].free);
+	assert(memregions[nr_memregions-1].size >= size);
+
+	mem_end = memregions[nr_memregions-1].addr
+		+ memregions[nr_memregions-1].size;
+
+	freemem_start = PAGE_ALIGN(memregions[nr_memregions-1].addr + size);
+	freemem_size = mem_end - freemem_start;
+
+	memregions[nr_memregions-1].size = freemem_start
+					 - memregions[nr_memregions-1].addr;
+	memregions[nr_memregions-1].free = false;
+
+	m = &memregions[nr_memregions-1];
+
+	if (nr_memregions < NR_MEMREGIONS) {
+		memregions[nr_memregions].addr = freemem_start;
+		memregions[nr_memregions].size = freemem_size;
+		memregions[nr_memregions].free = true;
+		++nr_memregions;
+	}
+
+	spin_unlock(&memregion_lock);
+
+	return m;
+}
+
+void memregions_show(void)
+{
+	int i;
+	for (i = 0; i < nr_memregions; ++i)
+		printf("%016llx-%016llx [%s]\n",
+			memregions[i].addr,
+			memregions[i].addr + memregions[i].size - 1,
+			memregions[i].free ? "FREE" : "USED");
+}
+
+void setup(unsigned long arg __unused, unsigned long id __unused,
+	   const void *fdt)
+{
+	const char *bootargs;
+	u32 fdt_size;
+
+	/*
+	 * Move the fdt to just above the stack. The free memory
+	 * then starts just after the fdt.
+	 */
+	fdt_size = fdt_totalsize(fdt);
+	assert(fdt_move(fdt, &stacktop, fdt_size) == 0);
+	assert(dt_init(&stacktop) == 0);
+
+	memregions_init((unsigned long)&stacktop + fdt_size);
+
+	io_init();
+	cpu_init();
+
+	assert(dt_get_bootargs(&bootargs) == 0);
+	setup_args(bootargs);
+}
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 16/19] arm: Add spinlock implementation
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
                   ` (13 preceding siblings ...)
  2014-04-10 16:56 ` [PATCH v4 15/19] arm: initial drop Andrew Jones
@ 2014-04-10 16:56 ` Andrew Jones
  2014-04-10 16:56 ` [PATCH v4 17/19] arm: Add IO accessors to avoid register-writeback Andrew Jones
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: christoffer.dall

From: Christoffer Dall <christoffer.dall@linaro.org>

Add simple busy-wait spinlock implementation for ARM.

Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
 config/config-arm.mak  |  3 ++-
 lib/arm/asm/spinlock.h |  9 ++-------
 lib/arm/spinlock.c     | 28 ++++++++++++++++++++++++++++
 3 files changed, 32 insertions(+), 8 deletions(-)
 create mode 100644 lib/arm/spinlock.c

diff --git a/config/config-arm.mak b/config/config-arm.mak
index 915b1cc318d79..d150807ec6fe4 100644
--- a/config/config-arm.mak
+++ b/config/config-arm.mak
@@ -35,7 +35,8 @@ cflatobjs += \
 	lib/virtio.o \
 	lib/virtio-testdev.o \
 	lib/arm/io.o \
-	lib/arm/setup.o
+	lib/arm/setup.o \
+	lib/arm/spinlock.o
 
 libeabi = lib/arm/libeabi.a
 eabiobjs = lib/arm/eabi_compat.o
diff --git a/lib/arm/asm/spinlock.h b/lib/arm/asm/spinlock.h
index 04f5a1a5538e2..2118a4b3751e0 100644
--- a/lib/arm/asm/spinlock.h
+++ b/lib/arm/asm/spinlock.h
@@ -5,12 +5,7 @@ struct spinlock {
 	int v;
 };
 
-//TODO
-static inline void spin_lock(struct spinlock *lock __unused)
-{
-}
-static inline void spin_unlock(struct spinlock *lock __unused)
-{
-}
+extern void spin_lock(struct spinlock *lock);
+extern void spin_unlock(struct spinlock *lock);
 
 #endif /* _ASMARM_SPINLOCK_H_ */
diff --git a/lib/arm/spinlock.c b/lib/arm/spinlock.c
new file mode 100644
index 0000000000000..d8a6d4c3383d6
--- /dev/null
+++ b/lib/arm/spinlock.c
@@ -0,0 +1,28 @@
+#include "libcflat.h"
+#include "asm/spinlock.h"
+#include "asm/barrier.h"
+
+void spin_lock(struct spinlock *lock)
+{
+	u32 val, fail;
+
+	dmb();
+	do {
+		asm volatile(
+		"1:	ldrex	%0, [%2]\n"
+		"	teq	%0, #0\n"
+		"	bne	1b\n"
+		"	mov	%0, #1\n"
+		"	strex	%1, %0, [%2]\n"
+		: "=&r" (val), "=&r" (fail)
+		: "r" (&lock->v)
+		: "cc" );
+	} while (fail);
+	dmb();
+}
+
+void spin_unlock(struct spinlock *lock)
+{
+	lock->v = 0;
+	dmb();
+}
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 17/19] arm: Add IO accessors to avoid register-writeback
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
                   ` (14 preceding siblings ...)
  2014-04-10 16:56 ` [PATCH v4 16/19] arm: Add spinlock implementation Andrew Jones
@ 2014-04-10 16:56 ` Andrew Jones
  2014-04-10 16:56 ` [PATCH v4 18/19] arm: add useful headers from the Linux kernel Andrew Jones
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: christoffer.dall

From: Christoffer Dall <christoffer.dall@linaro.org>

Add IO accessor functions to the arm library functions to avoid
register-writeback IO accessors that are not yet supported by the
kernel.

Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
 lib/arm/asm/io.h | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/lib/arm/asm/io.h b/lib/arm/asm/io.h
index 51ec6e9aa2e99..1d0abb7d9f405 100644
--- a/lib/arm/asm/io.h
+++ b/lib/arm/asm/io.h
@@ -3,6 +3,9 @@
 #include "libcflat.h"
 #include "asm/barrier.h"
 
+#define __iomem
+#define __force
+
 #define __bswap16 bswap16
 static inline u16 bswap16(u16 val)
 {
@@ -19,6 +22,60 @@ static inline u32 bswap32(u32 val)
 	return ret;
 }
 
+#define __raw_readb __raw_readb
+static inline u8 __raw_readb(const volatile void __iomem *addr)
+{
+	u8 val;
+	asm volatile("ldrb %1, %0"
+		     : "+Qo" (*(volatile u8 __force *)addr),
+		       "=r" (val));
+	return val;
+}
+
+#define __raw_readw __raw_readw
+static inline u16 __raw_readw(const volatile void __iomem *addr)
+{
+	u16 val;
+	asm volatile("ldrh %1, %0"
+		     : "+Q" (*(volatile u16 __force *)addr),
+		       "=r" (val));
+	return val;
+}
+
+#define __raw_readl __raw_readl
+static inline u32 __raw_readl(const volatile void __iomem *addr)
+{
+	u32 val;
+	asm volatile("ldr %1, %0"
+		     : "+Qo" (*(volatile u32 __force *)addr),
+		       "=r" (val));
+	return val;
+}
+
+#define __raw_writeb __raw_writeb
+static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
+{
+	asm volatile("strb %1, %0"
+		     : "+Qo" (*(volatile u8 __force *)addr)
+		     : "r" (val));
+}
+
+#define __raw_writew __raw_writew
+static inline void __raw_writew(u16 val, volatile void __iomem *addr)
+{
+	asm volatile("strh %1, %0"
+		     : "+Q" (*(volatile u16 __force *)addr)
+		     : "r" (val));
+}
+
+#define __raw_writel __raw_writel
+static inline void __raw_writel(u32 val, volatile void __iomem *addr)
+{
+	asm volatile("str %1, %0"
+		     : "+Qo" (*(volatile u32 __force *)addr)
+		     : "r" (val));
+}
+
 #include "asm-generic/io.h"
 
 #endif /* _ASMARM_IO_H_ */
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 18/19] arm: add useful headers from the Linux kernel
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
                   ` (15 preceding siblings ...)
  2014-04-10 16:56 ` [PATCH v4 17/19] arm: Add IO accessors to avoid register-writeback Andrew Jones
@ 2014-04-10 16:56 ` Andrew Jones
  2014-06-06 18:40   ` Christoffer Dall
  2014-04-10 16:57 ` [PATCH v4 19/19] arm: vectors support Andrew Jones
                   ` (2 subsequent siblings)
  19 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:56 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: christoffer.dall

We're going to need PSR bit defines and pt_regs. We'll also need
pt_regs offsets in assembly code. This patch adapts the Linux
kernel's ptrace.h and generated/asm-offsets.h to this framework.
It also adapts cp15.h from the kernel, since we'll need bit defines
from there too.

Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v4: much improved asm-offsets.h generation based on Kbuild
---
 config/asm-offsets.mak    |  41 +++++++++++++++++++
 config/config-arm.mak     |   9 ++++-
 lib/arm/.gitignore        |   1 +
 lib/arm/asm-offsets.c     |  39 ++++++++++++++++++
 lib/arm/asm/asm-offsets.h |   1 +
 lib/arm/asm/cp15.h        |  37 +++++++++++++++++
 lib/arm/asm/ptrace.h      | 100 ++++++++++++++++++++++++++++++++++++++++++++++
 lib/generated/.gitignore  |   1 +
 8 files changed, 227 insertions(+), 2 deletions(-)
 create mode 100644 config/asm-offsets.mak
 create mode 100644 lib/arm/.gitignore
 create mode 100644 lib/arm/asm-offsets.c
 create mode 100644 lib/arm/asm/asm-offsets.h
 create mode 100644 lib/arm/asm/cp15.h
 create mode 100644 lib/arm/asm/ptrace.h
 create mode 100644 lib/generated/.gitignore

diff --git a/config/asm-offsets.mak b/config/asm-offsets.mak
new file mode 100644
index 0000000000000..b2578a6692f33
--- /dev/null
+++ b/config/asm-offsets.mak
@@ -0,0 +1,41 @@
+#
+# asm-offsets adapted from the kernel, see
+#   Kbuild
+#   scripts/Kbuild.include
+#   scripts/Makefile.build
+#
+#   Authors: Andrew Jones <drjones@redhat.com>
+#
+
+define sed-y
+	"/^->/{s:->#\(.*\):/* \1 */:; \
+	s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \
+	s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
+	s:->::; p;}"
+endef
+
+define make_asm_offsets
+	(set -e; \
+	 echo "#ifndef __ASM_OFFSETS_H__"; \
+	 echo "#define __ASM_OFFSETS_H__"; \
+	 echo "/*"; \
+	 echo " * Generated file. DO NOT MODIFY."; \
+	 echo " *"; \
+	 echo " */"; \
+	 echo ""; \
+	 sed -ne $(sed-y) $<; \
+	 echo ""; \
+	 echo "#endif" ) > $@
+endef
+
+$(asm-offsets:.h=.s): $(asm-offsets:.h=.c)
+	$(CC) $(CFLAGS) -fverbose-asm -S -o $@ $<
+
+$(asm-offsets): $(asm-offsets:.h=.s)
+	$(call make_asm_offsets)
+	cp -f $(asm-offsets) lib/generated
+
+asm_offsets_clean:
+	$(RM) $(asm-offsets) $(asm-offsets:.h=.s) \
+	      $(addprefix lib/generated/,$(notdir $(asm-offsets)))
+
diff --git a/config/config-arm.mak b/config/config-arm.mak
index d150807ec6fe4..ead191f4954f4 100644
--- a/config/config-arm.mak
+++ b/config/config-arm.mak
@@ -30,6 +30,9 @@ CFLAGS += -Wextra
 CFLAGS += -O2
 CFLAGS += -I lib -I lib/libfdt
 
+asm-offsets = lib/arm/asm-offsets.h
+include config/asm-offsets.mak
+
 cflatobjs += \
 	lib/devicetree.o \
 	lib/virtio.o \
@@ -57,7 +60,7 @@ FLATLIBS = $(libcflat) $(LIBFDT_archive) $(libgcc) $(libeabi)
 $(libeabi): $(eabiobjs)
 	$(AR) rcs $@ $^
 
-arch_clean: libfdt_clean
+arch_clean: libfdt_clean asm_offsets_clean
 	$(RM) $(TEST_DIR)/*.{o,flat,elf} $(libeabi) $(eabiobjs) \
 	      $(TEST_DIR)/.*.d lib/arm/.*.d
 
@@ -67,7 +70,9 @@ tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg
 
 cstart.o = $(TEST_DIR)/cstart.o
 
-test_cases: $(tests-common) $(tests)
+generated_files = $(asm-offsets)
+
+test_cases: $(generated_files) $(tests-common) $(tests)
 
 $(TEST_DIR)/selftest.elf: $(cstart.o) $(TEST_DIR)/selftest.o
 
diff --git a/lib/arm/.gitignore b/lib/arm/.gitignore
new file mode 100644
index 0000000000000..84872bf197c67
--- /dev/null
+++ b/lib/arm/.gitignore
@@ -0,0 +1 @@
+asm-offsets.[hs]
diff --git a/lib/arm/asm-offsets.c b/lib/arm/asm-offsets.c
new file mode 100644
index 0000000000000..a9c349d2d427c
--- /dev/null
+++ b/lib/arm/asm-offsets.c
@@ -0,0 +1,39 @@
+/*
+ * Adapted from arch/arm/kernel/asm-offsets.c
+ *
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include "libcflat.h"
+#include "asm/ptrace.h"
+
+#define DEFINE(sym, val) \
+	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+#define OFFSET(sym, str, mem)	DEFINE(sym, offsetof(struct str, mem))
+#define COMMENT(x)		asm volatile("\n->#" x)
+#define BLANK()			asm volatile("\n->" : : )
+
+int main(void)
+{
+	OFFSET(S_R0, pt_regs, ARM_r0);
+	OFFSET(S_R1, pt_regs, ARM_r1);
+	OFFSET(S_R2, pt_regs, ARM_r2);
+	OFFSET(S_R3, pt_regs, ARM_r3);
+	OFFSET(S_R4, pt_regs, ARM_r4);
+	OFFSET(S_R5, pt_regs, ARM_r5);
+	OFFSET(S_R6, pt_regs, ARM_r6);
+	OFFSET(S_R7, pt_regs, ARM_r7);
+	OFFSET(S_R8, pt_regs, ARM_r8);
+	OFFSET(S_R9, pt_regs, ARM_r9);
+	OFFSET(S_R10, pt_regs, ARM_r10);
+	OFFSET(S_FP, pt_regs, ARM_fp);
+	OFFSET(S_IP, pt_regs, ARM_ip);
+	OFFSET(S_SP, pt_regs, ARM_sp);
+	OFFSET(S_LR, pt_regs, ARM_lr);
+	OFFSET(S_PC, pt_regs, ARM_pc);
+	OFFSET(S_PSR, pt_regs, ARM_cpsr);
+	OFFSET(S_OLD_R0, pt_regs, ARM_ORIG_r0);
+	DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs));
+	return 0;
+}
diff --git a/lib/arm/asm/asm-offsets.h b/lib/arm/asm/asm-offsets.h
new file mode 100644
index 0000000000000..c2ff2ba6ec417
--- /dev/null
+++ b/lib/arm/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include "generated/asm-offsets.h"
diff --git a/lib/arm/asm/cp15.h b/lib/arm/asm/cp15.h
new file mode 100644
index 0000000000000..7690a48f17f1f
--- /dev/null
+++ b/lib/arm/asm/cp15.h
@@ -0,0 +1,37 @@
+#ifndef _ASMARM_CP15_H_
+#define _ASMARM_CP15_H_
+/*
+ * From the Linux kernel arch/arm/include/asm/cp15.h
+ *
+ * CR1 bits (CP#15 CR1)
+ */
+#define CR_M	(1 << 0)	/* MMU enable				*/
+#define CR_A	(1 << 1)	/* Alignment abort enable		*/
+#define CR_C	(1 << 2)	/* Dcache enable			*/
+#define CR_W	(1 << 3)	/* Write buffer enable			*/
+#define CR_P	(1 << 4)	/* 32-bit exception handler		*/
+#define CR_D	(1 << 5)	/* 32-bit data address range		*/
+#define CR_L	(1 << 6)	/* Implementation defined		*/
+#define CR_B	(1 << 7)	/* Big endian				*/
+#define CR_S	(1 << 8)	/* System MMU protection		*/
+#define CR_R	(1 << 9)	/* ROM MMU protection			*/
+#define CR_F	(1 << 10)	/* Implementation defined		*/
+#define CR_Z	(1 << 11)	/* Implementation defined		*/
+#define CR_I	(1 << 12)	/* Icache enable			*/
+#define CR_V	(1 << 13)	/* Vectors relocated to 0xffff0000	*/
+#define CR_RR	(1 << 14)	/* Round Robin cache replacement	*/
+#define CR_L4	(1 << 15)	/* LDR pc can set T bit			*/
+#define CR_DT	(1 << 16)
+#define CR_HA	(1 << 17)	/* Hardware management of Access Flag	*/
+#define CR_IT	(1 << 18)
+#define CR_ST	(1 << 19)
+#define CR_FI	(1 << 21)	/* Fast interrupt (lower latency mode)	*/
+#define CR_U	(1 << 22)	/* Unaligned access operation		*/
+#define CR_XP	(1 << 23)	/* Extended page tables			*/
+#define CR_VE	(1 << 24)	/* Vectored interrupts			*/
+#define CR_EE	(1 << 25)	/* Exception (Big) Endian		*/
+#define CR_TRE	(1 << 28)	/* TEX remap enable			*/
+#define CR_AFE	(1 << 29)	/* Access flag enable			*/
+#define CR_TE	(1 << 30)	/* Thumb exception enable		*/
+
+#endif /* _ASMARM_CP15_H_ */
diff --git a/lib/arm/asm/ptrace.h b/lib/arm/asm/ptrace.h
new file mode 100644
index 0000000000000..3a4c7532258f6
--- /dev/null
+++ b/lib/arm/asm/ptrace.h
@@ -0,0 +1,100 @@
+#ifndef _ASMARM_PTRACE_H_
+#define _ASMARM_PTRACE_H_
+/*
+ * Adapted from Linux kernel headers
+ *   arch/arm/include/asm/ptrace.h
+ *   arch/arm/include/uapi/asm/ptrace.h
+ */
+
+/*
+ * PSR bits
+ */
+#define USR_MODE	0x00000010
+#define SVC_MODE	0x00000013
+#define FIQ_MODE	0x00000011
+#define IRQ_MODE	0x00000012
+#define ABT_MODE	0x00000017
+#define HYP_MODE	0x0000001a
+#define UND_MODE	0x0000001b
+#define SYSTEM_MODE	0x0000001f
+#define MODE32_BIT	0x00000010
+#define MODE_MASK	0x0000001f
+
+#define PSR_T_BIT	0x00000020	/* >= V4T, but not V7M */
+#define PSR_F_BIT	0x00000040	/* >= V4, but not V7M */
+#define PSR_I_BIT	0x00000080	/* >= V4, but not V7M */
+#define PSR_A_BIT	0x00000100	/* >= V6, but not V7M */
+#define PSR_E_BIT	0x00000200	/* >= V6, but not V7M */
+#define PSR_J_BIT	0x01000000	/* >= V5J, but not V7M */
+#define PSR_Q_BIT	0x08000000	/* >= V5E, including V7M */
+#define PSR_V_BIT	0x10000000
+#define PSR_C_BIT	0x20000000
+#define PSR_Z_BIT	0x40000000
+#define PSR_N_BIT	0x80000000
+
+/*
+ * Groups of PSR bits
+ */
+#define PSR_f		0xff000000	/* Flags                */
+#define PSR_s		0x00ff0000	/* Status               */
+#define PSR_x		0x0000ff00	/* Extension            */
+#define PSR_c		0x000000ff	/* Control              */
+
+/*
+ * ARMv7 groups of PSR bits
+ */
+#define APSR_MASK	0xf80f0000	/* N, Z, C, V, Q and GE flags */
+#define PSR_ISET_MASK	0x01000010	/* ISA state (J, T) mask */
+#define PSR_IT_MASK	0x0600fc00	/* If-Then execution state mask */
+#define PSR_ENDIAN_MASK	0x00000200	/* Endianness state mask */
+
+#ifndef __ASSEMBLY__
+#include "libcflat.h"
+
+struct pt_regs {
+	unsigned long uregs[18];
+};
+
+#define ARM_cpsr	uregs[16]
+#define ARM_pc		uregs[15]
+#define ARM_lr		uregs[14]
+#define ARM_sp		uregs[13]
+#define ARM_ip		uregs[12]
+#define ARM_fp		uregs[11]
+#define ARM_r10		uregs[10]
+#define ARM_r9		uregs[9]
+#define ARM_r8		uregs[8]
+#define ARM_r7		uregs[7]
+#define ARM_r6		uregs[6]
+#define ARM_r5		uregs[5]
+#define ARM_r4		uregs[4]
+#define ARM_r3		uregs[3]
+#define ARM_r2		uregs[2]
+#define ARM_r1		uregs[1]
+#define ARM_r0		uregs[0]
+#define ARM_ORIG_r0	uregs[17]
+
+#define user_mode(regs) \
+	(((regs)->ARM_cpsr & 0xf) == 0)
+
+#define processor_mode(regs) \
+	((regs)->ARM_cpsr & MODE_MASK)
+
+#define interrupts_enabled(regs) \
+	(!((regs)->ARM_cpsr & PSR_I_BIT))
+
+#define fast_interrupts_enabled(regs) \
+	(!((regs)->ARM_cpsr & PSR_F_BIT))
+
+#define MAX_REG_OFFSET (offsetof(struct pt_regs, ARM_ORIG_r0))
+
+static inline unsigned long regs_get_register(struct pt_regs *regs,
+					      unsigned int offset)
+{
+	if (offset > MAX_REG_OFFSET)
+		return 0;
+	return *(unsigned long *)((unsigned long)regs + offset);
+}
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASMARM_PTRACE_H_ */
diff --git a/lib/generated/.gitignore b/lib/generated/.gitignore
new file mode 100644
index 0000000000000..72e8ffc0db8aa
--- /dev/null
+++ b/lib/generated/.gitignore
@@ -0,0 +1 @@
+*
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 19/19] arm: vectors support
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
                   ` (16 preceding siblings ...)
  2014-04-10 16:56 ` [PATCH v4 18/19] arm: add useful headers from the Linux kernel Andrew Jones
@ 2014-04-10 16:57 ` Andrew Jones
  2014-06-06 18:40   ` Christoffer Dall
       [not found] ` <1397149020-3501-7-git-send-email-drjones@redhat.com>
  2014-06-06 18:41 ` [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Christoffer Dall
  19 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-04-10 16:57 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: christoffer.dall

Add support for tests to use exception handlers using
install_exception_handler(). This patch also adds phys_start_usr(),
which can be used to start a function in USR mode, using a stack
set up in a new memregion. phys_start_usr() is used by new selftest
tests that check the new vector support.

Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v4: a couple tweaks to fit changes in the other patches,
    vectors-usr test now has an 8K usr stack
v3:
  - squashed in 'arm: Simplify exceptions_init in cstart.S'
    [Christoffer Dall]
  - suggested function name changes and comment additions
    [Christoffer Dall]
  - fix a bug with stack restore from usr mode exceptions that
    Christoffer pointed out. Add a get_sp() accessor too.
---
 arm/cstart.S            | 174 ++++++++++++++++++++++++++++++++++++++++++++++++
 arm/flat.lds            |   7 +-
 arm/selftest.c          | 122 ++++++++++++++++++++++++++++++++-
 arm/unittests.cfg       |  12 ++++
 config/config-arm.mak   |   3 +-
 lib/arm/asm/processor.h |  40 +++++++++++
 lib/arm/processor.c     | 115 ++++++++++++++++++++++++++++++++
 lib/libcflat.h          |   3 +
 8 files changed, 473 insertions(+), 3 deletions(-)
 create mode 100644 lib/arm/asm/processor.h
 create mode 100644 lib/arm/processor.c

diff --git a/arm/cstart.S b/arm/cstart.S
index e28251db2950d..cc87ece4b6b40 100644
--- a/arm/cstart.S
+++ b/arm/cstart.S
@@ -5,6 +5,10 @@
  *
  * This work is licensed under the terms of the GNU LGPL, version 2.
  */
+#define __ASSEMBLY__
+#include "asm/asm-offsets.h"
+#include "asm/ptrace.h"
+#include "asm/cp15.h"
 
 .arm
 
@@ -17,6 +21,13 @@ start:
 	 * See the kernel doc Documentation/arm/Booting
 	 */
 	ldr	sp, =stacktop
+	push	{r0-r3}
+
+	/* set up vector table and mode stacks */
+	bl	exceptions_init
+
+	/* complete setup */
+	pop	{r0-r3}
 	bl	setup
 
 	/* run the test */
@@ -27,9 +38,172 @@ start:
 	bl	exit
 	b	halt
 
+
+.macro set_mode_stack mode, stack
+	add	\stack, #S_FRAME_SIZE
+	msr	cpsr_c, #(\mode | PSR_I_BIT | PSR_F_BIT)
+	mov	sp, \stack
+.endm
+
+exceptions_init:
+	mrc	p15, 0, r2, c1, c0, 0	@ read SCTLR
+	bic	r2, #CR_V		@ SCTLR.V := 0
+	mcr	p15, 0, r2, c1, c0, 0	@ write SCTLR
+	ldr	r2, =vector_table
+	mcr	p15, 0, r2, c12, c0, 0	@ write VBAR
+
+	mrs	r2, cpsr
+	ldr	r1, =exception_stacks
+
+	/* first frame reserved for svc mode */
+	set_mode_stack	UND_MODE, r1
+	set_mode_stack	ABT_MODE, r1
+	set_mode_stack	IRQ_MODE, r1
+	set_mode_stack	FIQ_MODE, r1
+
+	msr	cpsr_cxsf, r2		@ back to svc mode
+	mov	pc, lr
+
 .text
 
 .globl halt
 halt:
 1:	wfi
 	b	1b
+
+/*
+ * Vector stubs
+ * Simplified version of the Linux kernel implementation
+ *   arch/arm/kernel/entry-armv.S
+ *
+ * Each mode has an S_FRAME_SIZE sized stack initialized
+ * in exceptions_init
+ */
+.macro vector_stub, name, vec, mode, correction=0
+.align 5
+vector_\name:
+.if \correction
+	sub	lr, lr, #\correction
+.endif
+	/*
+	 * Save r0, r1, lr_<exception> (parent PC)
+	 * and spsr_<exception> (parent CPSR)
+	 */
+	str	r0, [sp, #S_R0]
+	str	r1, [sp, #S_R1]
+	str	lr, [sp, #S_PC]
+	mrs	r0, spsr
+	str	r0, [sp, #S_PSR]
+
+	/* Prepare for SVC32 mode. */
+	mrs	r0, cpsr
+	bic	r0, #MODE_MASK
+	orr	r0, #SVC_MODE
+	msr	spsr_cxsf, r0
+
+	/* Branch to handler in SVC mode */
+	mov	r0, #\vec
+	mov	r1, sp
+	ldr	lr, =vector_common
+	movs	pc, lr
+.endm
+
+vector_stub 	rst,	0, UND_MODE
+vector_stub	und,	1, UND_MODE
+vector_stub	pabt,	3, ABT_MODE, 4
+vector_stub	dabt,	4, ABT_MODE, 8
+vector_stub	irq,	6, IRQ_MODE, 4
+vector_stub	fiq,	7, FIQ_MODE, 4
+
+.align 5
+vector_svc:
+	/*
+	 * Save r0, r1, lr_<exception> (parent PC)
+	 * and spsr_<exception> (parent CPSR)
+	 */
+	push	{ r1 }
+	ldr	r1, =exception_stacks
+	str	r0, [r1, #S_R0]
+	pop	{ r0 }
+	str	r0, [r1, #S_R1]
+	str	lr, [r1, #S_PC]
+	mrs	r0, spsr
+	str	r0, [r1, #S_PSR]
+
+	/*
+	 * Branch to handler, still in SVC mode.
+	 * r0 := 2 is the svc vector number.
+	 */
+	mov	r0, #2
+	ldr	lr, =vector_common
+	mov	pc, lr
+
+vector_common:
+	/* make room for pt_regs */
+	sub	sp, #S_FRAME_SIZE
+	tst	sp, #4			@ check stack alignment
+	subne	sp, #4
+
+	/* store registers r0-r12 */
+	stmia	sp, { r0-r12 }		@ stored wrong r0 and r1, fix later
+
+	/* get registers saved in the stub */
+	ldr	r2, [r1, #S_R0]		@ r0
+	ldr	r3, [r1, #S_R1]		@ r1
+	ldr	r4, [r1, #S_PC] 	@ lr_<exception> (parent PC)
+	ldr	r5, [r1, #S_PSR]	@ spsr_<exception> (parent CPSR)
+
+	/* fix r0 and r1 */
+	str	r2, [sp, #S_R0]
+	str	r3, [sp, #S_R1]
+
+	/* store sp_svc, if we were in usr mode we'll fix this later */
+	add	r6, sp, #S_FRAME_SIZE
+	addne	r6, #4			@ stack wasn't aligned
+	str	r6, [sp, #S_SP]
+
+	str	lr, [sp, #S_LR]		@ store lr_svc, fix later for usr mode
+	str	r4, [sp, #S_PC]		@ store lr_<exception>
+	str	r5, [sp, #S_PSR]	@ store spsr_<exception>
+
+	/* set ORIG_r0 */
+	mov	r2, #-1
+	str	r2, [sp, #S_OLD_R0]
+
+	/* if we were in usr mode then we need sp_usr and lr_usr instead */
+	and	r1, r5, #MODE_MASK
+	cmp	r1, #USR_MODE
+	bne	1f
+	add	r1, sp, #S_SP
+	stmia	r1, { sp,lr }^
+
+	/* Call the handler. r0 is the vector number, r1 := pt_regs */
+1:	mov	r1, sp
+	bl	do_handle_exception
+
+	/*
+	 * make sure we restore sp_svc on mode change. No need to
+	 * worry about lr_svc though, as that gets clobbered on
+	 * exception entry anyway.
+	 */
+	str	r6, [sp, #S_SP]
+
+	/* return from exception */
+	msr	spsr_cxsf, r5
+	ldmia	sp, { r0-pc }^
+
+.align 5
+vector_addrexcptn:
+	b	vector_addrexcptn
+
+.section .text.ex
+.align 5
+vector_table:
+	b	vector_rst
+	b	vector_und
+	b	vector_svc
+	b	vector_pabt
+	b	vector_dabt
+	b	vector_addrexcptn	@ should never happen
+	b	vector_irq
+	b	vector_fiq
diff --git a/arm/flat.lds b/arm/flat.lds
index 3e5d72e24989b..ee9fc0ab79abc 100644
--- a/arm/flat.lds
+++ b/arm/flat.lds
@@ -3,7 +3,12 @@ SECTIONS
 {
     .text : { *(.init) *(.text) *(.text.*) }
     . = ALIGN(4K);
-    .data : { *(.data) }
+    .data : {
+        exception_stacks = .;
+        . += 4K;
+        exception_stacks_end = .;
+        *(.data)
+    }
     . = ALIGN(16);
     .rodata : { *(.rodata) }
     . = ALIGN(16);
diff --git a/arm/selftest.c b/arm/selftest.c
index 45729e9ac85d9..d8c9cae7e4ec1 100644
--- a/arm/selftest.c
+++ b/arm/selftest.c
@@ -7,6 +7,9 @@
  */
 #include "libcflat.h"
 #include "asm/setup.h"
+#include "asm/ptrace.h"
+#include "asm/asm-offsets.h"
+#include "asm/processor.h"
 
 #define TESTGRP "selftest"
 
@@ -74,14 +77,131 @@ static void check_setup(int argc, char **argv)
 	assert_args(nr_tests, 2);
 }
 
+static struct pt_regs expected_regs;
+/*
+ * Capture the current register state and execute an instruction
+ * that causes an exception. The test handler will check that its
+ * capture of the current register state matches the capture done
+ * here.
+ *
+ * NOTE: update clobber list if passed insns needs more than r0,r1
+ */
+#define test_exception(pre_insns, excptn_insn, post_insns)	\
+	asm volatile(						\
+		pre_insns "\n"					\
+		"mov	r0, %0\n"				\
+		"stmia	r0, { r0-lr }\n"			\
+		"mrs	r1, cpsr\n"				\
+		"str	r1, [r0, #" __stringify(S_PSR) "]\n"	\
+		"mov	r1, #-1\n"				\
+		"str	r1, [r0, #" __stringify(S_OLD_R0) "]\n"	\
+		"add	r1, pc, #8\n"				\
+		"str	r1, [r0, #" __stringify(S_R1) "]\n"	\
+		"str	r1, [r0, #" __stringify(S_PC) "]\n"	\
+		excptn_insn "\n"				\
+		post_insns "\n"					\
+	:: "r" (&expected_regs) : "r0", "r1")
+
+static bool check_regs(struct pt_regs *regs)
+{
+	unsigned i;
+
+	/* exception handlers should always run in svc mode */
+	if (current_mode() != SVC_MODE)
+		return false;
+
+	for (i = 0; i < ARRAY_SIZE(regs->uregs); ++i) {
+		if (regs->uregs[i] != expected_regs.uregs[i])
+			return false;
+	}
+
+	return true;
+}
+
+static bool und_works;
+static void und_handler(struct pt_regs *regs)
+{
+	und_works = check_regs(regs);
+}
+
+static bool check_und(void)
+{
+	install_exception_handler(EXCPTN_UND, und_handler);
+
+	/* issue an instruction to a coprocessor we don't have */
+	test_exception("", "mcr p2, 0, r0, c0, c0", "");
+
+	install_exception_handler(EXCPTN_UND, NULL);
+
+	return und_works;
+}
+
+static bool svc_works;
+static void svc_handler(struct pt_regs *regs)
+{
+	u32 svc = *(u32 *)(regs->ARM_pc - 4) & 0xffffff;
+
+	if (processor_mode(regs) == SVC_MODE) {
+		/*
+		 * When issuing an svc from supervisor mode lr_svc will
+		 * get corrupted. So before issuing the svc, callers must
+		 * always push it on the stack. We pushed it to offset 4.
+		 */
+		regs->ARM_lr = *(unsigned long *)(regs->ARM_sp + 4);
+	}
+
+	svc_works = check_regs(regs) && svc == 123;
+}
+
+static bool check_svc(void)
+{
+	install_exception_handler(EXCPTN_SVC, svc_handler);
+
+	if (current_mode() == SVC_MODE) {
+		/*
+		 * An svc from supervisor mode will corrupt lr_svc and
+		 * spsr_svc. We need to save/restore them separately.
+		 */
+		test_exception(
+			"mrs	r0, spsr\n"
+			"push	{ r0,lr }\n",
+			"svc	#123\n",
+			"pop	{ r0,lr }\n"
+			"msr	spsr_cxsf, r0\n"
+		);
+	} else {
+		test_exception("", "svc #123", "");
+	}
+
+	install_exception_handler(EXCPTN_SVC, NULL);
+
+	return svc_works;
+}
+
+static void check_vectors(void *arg __unused)
+{
+	report("%s", check_und() && check_svc(), testnam);
+	exit(report_summary());
+}
+
 int main(int argc, char **argv)
 {
 	assert_args(argc, 1);
 
 	testnam_set(argv[0]);
 
-	if (strcmp(argv[0], "setup") == 0)
+	if (strcmp(argv[0], "setup") == 0) {
+
 		check_setup(argc-1, &argv[1]);
 
+	} else if (strcmp(argv[0], "vectors-svc") == 0) {
+
+		check_vectors(NULL);
+
+	} else if (strcmp(argv[0], "vectors-usr") == 0) {
+
+		phys_start_usr(2*PAGE_SIZE, check_vectors, NULL);
+	}
+
 	return report_summary();
 }
diff --git a/arm/unittests.cfg b/arm/unittests.cfg
index da9dfd7b1f118..57f5f90f3e808 100644
--- a/arm/unittests.cfg
+++ b/arm/unittests.cfg
@@ -16,3 +16,15 @@ file = selftest.flat
 smp  = 1
 extra_params = -m 256 -append 'setup smp=1 mem=256'
 groups = selftest
+
+# Test vector setup and exception handling (svc mode).
+[selftest::vectors-svc]
+file = selftest.flat
+extra_params = -append 'vectors-svc'
+groups = selftest
+
+# Test vector setup and exception handling (usr mode).
+[selftest::vectors-usr]
+file = selftest.flat
+extra_params = -append 'vectors-usr'
+groups = selftest
diff --git a/config/config-arm.mak b/config/config-arm.mak
index ead191f4954f4..2a62b5847e230 100644
--- a/config/config-arm.mak
+++ b/config/config-arm.mak
@@ -39,7 +39,8 @@ cflatobjs += \
 	lib/virtio-testdev.o \
 	lib/arm/io.o \
 	lib/arm/setup.o \
-	lib/arm/spinlock.o
+	lib/arm/spinlock.o \
+	lib/arm/processor.o
 
 libeabi = lib/arm/libeabi.a
 eabiobjs = lib/arm/eabi_compat.o
diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h
new file mode 100644
index 0000000000000..b7d3be00135fd
--- /dev/null
+++ b/lib/arm/asm/processor.h
@@ -0,0 +1,40 @@
+#ifndef _ASMARM_PROCESSOR_H_
+#define _ASMARM_PROCESSOR_H_
+/*
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include "ptrace.h"
+
+enum vector {
+	EXCPTN_RST,
+	EXCPTN_UND,
+	EXCPTN_SVC,
+	EXCPTN_PABT,
+	EXCPTN_DABT,
+	EXCPTN_ADDREXCPTN,
+	EXCPTN_IRQ,
+	EXCPTN_FIQ,
+	EXCPTN_MAX,
+};
+
+typedef void (*exception_fn)(struct pt_regs *);
+extern void install_exception_handler(enum vector v, exception_fn fn);
+
+extern void show_regs(struct pt_regs *regs);
+extern void *get_sp(void);
+
+static inline unsigned long current_cpsr(void)
+{
+	unsigned long cpsr;
+	asm volatile("mrs %0, cpsr" : "=r" (cpsr));
+	return cpsr;
+}
+
+#define current_mode() (current_cpsr() & MODE_MASK)
+
+extern void
+phys_start_usr(size_t stacksize, void (*func)(void *arg), void *arg);
+
+#endif /* _ASMARM_PROCESSOR_H_ */
diff --git a/lib/arm/processor.c b/lib/arm/processor.c
new file mode 100644
index 0000000000000..3d38ea6f9fd73
--- /dev/null
+++ b/lib/arm/processor.c
@@ -0,0 +1,115 @@
+/*
+ * processor control and status functions
+ *
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include "libcflat.h"
+#include "asm/setup.h"
+#include "asm/ptrace.h"
+#include "asm/processor.h"
+
+static const char *processor_modes[] = {
+	"USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" ,
+	"UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
+	"UK8_26" , "UK9_26" , "UK10_26", "UK11_26",
+	"UK12_26", "UK13_26", "UK14_26", "UK15_26",
+	"USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" ,
+	"UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" ,
+	"UK8_32" , "UK9_32" , "UK10_32", "UND_32" ,
+	"UK12_32", "UK13_32", "UK14_32", "SYS_32"
+};
+
+static char *vector_names[] = {
+	"rst", "und", "svc", "pabt", "dabt", "addrexcptn", "irq", "fiq"
+};
+
+void show_regs(struct pt_regs *regs)
+{
+	unsigned long flags;
+	char buf[64];
+
+	printf("pc : [<%08lx>]    lr : [<%08lx>]    psr: %08lx\n"
+	       "sp : %08lx  ip : %08lx  fp : %08lx\n",
+		regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr,
+		regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
+	printf("r10: %08lx  r9 : %08lx  r8 : %08lx\n",
+		regs->ARM_r10, regs->ARM_r9, regs->ARM_r8);
+	printf("r7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n",
+		regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4);
+	printf("r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
+		regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0);
+
+	flags = regs->ARM_cpsr;
+	buf[0] = flags & PSR_N_BIT ? 'N' : 'n';
+	buf[1] = flags & PSR_Z_BIT ? 'Z' : 'z';
+	buf[2] = flags & PSR_C_BIT ? 'C' : 'c';
+	buf[3] = flags & PSR_V_BIT ? 'V' : 'v';
+	buf[4] = '\0';
+
+	printf("Flags: %s  IRQs o%s  FIQs o%s  Mode %s\n",
+		buf, interrupts_enabled(regs) ? "n" : "ff",
+		fast_interrupts_enabled(regs) ? "n" : "ff",
+		processor_modes[processor_mode(regs)]);
+
+	if (!user_mode(regs)) {
+		unsigned int ctrl, transbase, dac;
+		asm volatile(
+			"mrc p15, 0, %0, c1, c0\n"
+			"mrc p15, 0, %1, c2, c0\n"
+			"mrc p15, 0, %2, c3, c0\n"
+		: "=r" (ctrl), "=r" (transbase), "=r" (dac));
+		printf("Control: %08x  Table: %08x  DAC: %08x\n",
+			ctrl, transbase, dac);
+	}
+}
+
+void *get_sp(void)
+{
+	register unsigned long sp asm("sp");
+	return (void *)sp;
+}
+
+static exception_fn exception_handlers[EXCPTN_MAX];
+
+void install_exception_handler(enum vector v, exception_fn fn)
+{
+	if (v < EXCPTN_MAX)
+		exception_handlers[v] = fn;
+}
+
+void do_handle_exception(enum vector v, struct pt_regs *regs)
+{
+	if (v < EXCPTN_MAX && exception_handlers[v]) {
+		exception_handlers[v](regs);
+		return;
+	}
+
+	if (v < EXCPTN_MAX)
+		printf("Unhandled exception %d (%s)\n", v, vector_names[v]);
+	else
+		printf("%s called with vector=%d\n", __func__, v);
+
+	printf("Exception frame registers:\n");
+	show_regs(regs);
+	abort();
+}
+
+void phys_start_usr(size_t stacksize, void (*func)(void *arg), void *arg)
+{
+	struct memregion *m = memregion_new(stacksize);
+	unsigned long sp_usr = (unsigned long)(m->addr + m->size);
+
+	sp_usr &= (~7UL); /* stack ptr needs 8-byte alignment */
+
+	asm volatile(
+		"mrs	r0, cpsr\n"
+		"bic	r0, #" __stringify(MODE_MASK) "\n"
+		"orr	r0, #" __stringify(USR_MODE) "\n"
+		"msr	cpsr_c, r0\n"
+		"mov	r0, %0\n"
+		"mov	sp, %1\n"
+		"mov	pc, %2\n"
+	:: "r" (arg), "r" (sp_usr), "r" (func) : "r0");
+}
diff --git a/lib/libcflat.h b/lib/libcflat.h
index f6c071c71f0b9..fec6762dd53fb 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -66,4 +66,7 @@ do {									\
 		abort();						\
 } while (0)
 
+#define __stringify_1(x...)	#x
+#define __stringify(x...)	__stringify_1(x)
+
 #endif
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 01/19] remove unused files
  2014-04-10 16:56 ` [PATCH v4 01/19] remove unused files Andrew Jones
@ 2014-06-06 18:37   ` Christoffer Dall
  2014-06-09  8:11     ` Andrew Jones
  0 siblings, 1 reply; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:37 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:56:42PM +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>

Sounds reasonable enough for me, but you probably want an acked-by from
the people who actually know if they should care about these files or
not.

In any case:

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 02/19] makefile and run_tests tweaks
  2014-04-10 16:56 ` [PATCH v4 02/19] makefile and run_tests tweaks Andrew Jones
@ 2014-06-06 18:37   ` Christoffer Dall
  0 siblings, 0 replies; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:37 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:56:43PM +0200, Andrew Jones wrote:
> - 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>

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 03/19] clean root dir of all x86-ness
  2014-04-10 16:56 ` [PATCH v4 03/19] clean root dir of all x86-ness Andrew Jones
@ 2014-06-06 18:37   ` Christoffer Dall
  0 siblings, 0 replies; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:37 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:56:44PM +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.
> 
> Signed-off-by: Andrew Jones <drjones@redhat.com>

looks reasonable to me.

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

-Christoffer

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 04/19] add distclean target and gitignore more
  2014-04-10 16:56 ` [PATCH v4 04/19] add distclean target and gitignore more Andrew Jones
@ 2014-06-06 18:37   ` Christoffer Dall
  0 siblings, 0 replies; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:37 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:56:45PM +0200, Andrew Jones wrote:
> also add a check for config.mak in Makefile
> 
> Signed-off-by: Andrew Jones <drjones@redhat.com>

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 05/19] add 'make cscope' support
  2014-04-10 16:56 ` [PATCH v4 05/19] add 'make cscope' support Andrew Jones
@ 2014-06-06 18:38   ` Christoffer Dall
  0 siblings, 0 replies; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:38 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:56:46PM +0200, Andrew Jones wrote:
> Add a Makefile target to quickly generate arch-specific cscope
> for kvm-unit-tests. Assumes a mostly flat directory structure,
> i.e. uses '-maxdepth 1' in the file search.
> 
> Signed-off-by: Andrew Jones <drjones@redhat.com>

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 06/19] libfdt: Import libfdt source
       [not found] ` <1397149020-3501-7-git-send-email-drjones@redhat.com>
@ 2014-06-06 18:38   ` Christoffer Dall
  0 siblings, 0 replies; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:38 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:56:47PM +0200, Andrew Jones wrote:
> This adds the applicable libfdt source files (unmodified) and a
> README to explain where the source came from. The README says
> 
>   The code in this directory is originally imported from the libfdt
>   directory of git://git.jdl.com/software/dtc.git - version 1.4.0.
> 
> Signed-off-by: Andrew Jones <drjones@redhat.com>

obviously I didn't review the libfdt sources, but I agree with the
approach:

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 07/19] libfdt: get libfdt to build
  2014-04-10 16:56 ` [PATCH v4 07/19] libfdt: get libfdt to build Andrew Jones
@ 2014-06-06 18:38   ` Christoffer Dall
  0 siblings, 0 replies; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:38 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:56:48PM +0200, Andrew Jones wrote:
> Add string functions needed for libfdt, and add a make target.
> 
> Signed-off-by: Andrew Jones <drjones@redhat.com>

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 08/19] add support for Linux device trees
  2014-04-10 16:56 ` [PATCH v4 08/19] add support for Linux device trees Andrew Jones
@ 2014-06-06 18:38   ` Christoffer Dall
  2014-06-09 10:18     ` Andrew Jones
  0 siblings, 1 reply; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:38 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:56:49PM +0200, Andrew Jones wrote:
> Add some device tree functions, built on libfdt, to the arch-neutral
> lib code in order to facilitate the extraction of boot info and device
> base addresses. These functions should work on device trees conforming
> to section III of the kernel doc
> Documentation/devicetree/booting-without-of.txt.
> 
> Signed-off-by: Andrew Jones <drjones@redhat.com>
> ---
> v4: reworked everything, added lots of comments to devicetree.h

 => reworked everything
 that will make it easy to review again ;)

> ---
>  lib/devicetree.c | 289 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/devicetree.h | 230 +++++++++++++++++++++++++++++++++++++++++++
>  lib/libcflat.h   |   2 +
>  3 files changed, 521 insertions(+)
>  create mode 100644 lib/devicetree.c
>  create mode 100644 lib/devicetree.h
> 
> diff --git a/lib/devicetree.c b/lib/devicetree.c
> new file mode 100644
> index 0000000000000..482028f066346
> --- /dev/null
> +++ b/lib/devicetree.c
> @@ -0,0 +1,289 @@
> +/*
> + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#include "libcflat.h"
> +#include "libfdt/libfdt.h"
> +#include "devicetree.h"
> +
> +static const void *fdt;
> +static u32 root_nr_address_cells, root_nr_size_cells;
> +
> +const void *dt_fdt(void)
> +{
> +	return fdt;
> +}
> +
> +bool dt_available(void)
> +{
> +	return fdt_check_header(fdt) == 0;
> +}
> +
> +int dt_get_nr_cells(int fdtnode, u32 *nr_address_cells, u32 *nr_size_cells)
> +{
> +	const struct fdt_property *prop;
> +	u32 *nr_cells;
> +	int len;
> +
> +	prop = fdt_get_property(fdt, fdtnode, "#address-cells", &len);
> +	if (prop == NULL)
> +		return len;
> +
> +	nr_cells = (u32 *)prop->data;
> +	*nr_address_cells = fdt32_to_cpu(*nr_cells);
> +
> +	prop = fdt_get_property(fdt, fdtnode, "#size-cells", &len);
> +	if (prop == NULL)
> +		return len;
> +
> +	nr_cells = (u32 *)prop->data;
> +	*nr_size_cells = fdt32_to_cpu(*nr_cells);
> +
> +	return 0;
> +}
> +
> +void dt_reg_init(struct dt_reg *reg, u32 nr_address_cells, u32 nr_size_cells)
> +{
> +	memset(reg, 0, sizeof(struct dt_reg));
> +	reg->nr_address_cells = nr_address_cells;
> +	reg->nr_size_cells = nr_size_cells;
> +}
> +
> +int dt_get_reg(int fdtnode, int regidx, struct dt_reg *reg)
> +{
> +	const struct fdt_property *prop;
> +	u32 *cells, i;
> +	unsigned nr_tuple_cells;
> +	int len;
> +
> +	prop = fdt_get_property(fdt, fdtnode, "reg", &len);
> +	if (prop == NULL)
> +		return len;
> +
> +	cells = (u32 *)prop->data;
> +	nr_tuple_cells = reg->nr_address_cells + reg->nr_size_cells;
> +	regidx *= nr_tuple_cells;
> +
> +	if (regidx + nr_tuple_cells > len/sizeof(u32))

Shouldn't this be >= ?

> +		return -FDT_ERR_NOTFOUND;
> +
> +	for (i = 0; i < reg->nr_address_cells; ++i)
> +		reg->address_cells[i] = fdt32_to_cpu(cells[regidx + i]);
> +
> +	regidx += reg->nr_address_cells;
> +	for (i = 0; i < reg->nr_size_cells; ++i)
> +		reg->size_cells[i] = fdt32_to_cpu(cells[regidx + i]);
> +
> +	return 0;
> +}
> +
> +int dt_pbus_translate_node(int fdtnode, int regidx, void *reg)

why doesn't this function take a struct dt_pbus_reg * instead of a
void *?

> +{
> +	struct dt_pbus_reg *pbus_reg = (struct dt_pbus_reg *)reg;
> +	struct dt_reg raw_reg;
> +	int ret;
> +
> +	dt_reg_init(&raw_reg, root_nr_address_cells, root_nr_size_cells);
> +
> +	ret = dt_get_reg(fdtnode, regidx, &raw_reg);
> +	if (ret < 0)
> +		return ret;
> +
> +	pbus_reg->addr = dt_pbus_read_cells(raw_reg.nr_address_cells,
> +					    raw_reg.address_cells);
> +	pbus_reg->size = dt_pbus_read_cells(raw_reg.nr_size_cells,
> +					    raw_reg.size_cells);
> +
> +	return 0;
> +}
> +
> +int dt_pbus_translate(const struct dt_device *dev, int regidx,
> +		      void *reg)
> +{
> +	return dt_pbus_translate_node(dev->fdtnode, regidx, reg);
> +}
> +
> +int dt_pbus_get_baseaddr(const struct dt_device *dev, dt_pbus_addr_t *base)
> +{
> +	struct dt_pbus_reg reg;
> +	int ret;
> +
> +	ret = dt_pbus_translate(dev, 0, &reg);
> +	if (ret < 0)
> +		return ret;
> +
> +	*base = reg.addr;
> +	return 0;
> +}
> +
> +int dt_bus_match_any(const struct dt_device *dev __unused, int fdtnode)
> +{
> +	/* matches any device with a valid node */
> +	return fdtnode < 0 ? fdtnode : 1;
> +}
> +
> +static const struct dt_bus dt_default_bus = {
> +	.match = dt_bus_match_any,
> +	.translate = dt_pbus_translate,
> +};
> +
> +void dt_bus_init_defaults(struct dt_bus *bus)
> +{
> +	memcpy(bus, &dt_default_bus, sizeof(struct dt_bus));
> +}
> +
> +void dt_device_init(struct dt_device *dev, const struct dt_bus *bus,
> +		    const void *info)
> +{
> +	memset(dev, 0, sizeof(struct dt_device));
> +	dev->bus = bus;
> +	dev->info = (void *)info;
> +}
> +
> +int dt_device_find_compatible(const struct dt_device *dev,
> +			      const char *compatible)
> +{
> +	int node, ret;
> +
> +	node = fdt_node_offset_by_compatible(fdt, -1, compatible);
> +	while (node >= 0) {
> +		ret = dev->bus->match(dev, node);
> +		if (ret < 0)
> +			return ret;
> +		else if (ret)
> +			break;
> +		node = fdt_node_offset_by_compatible(fdt, node, compatible);
> +	}
> +	return node;
> +}
> +
> +int dt_pbus_get_baseaddr_compatible(const char *compatible,
> +				    dt_pbus_addr_t *baseaddr)
> +{
> +	struct dt_device dev;
> +	int node, ret;
> +
> +	dt_device_init(&dev, &dt_default_bus, NULL);
> +
> +	node = dt_device_find_compatible(&dev, compatible);
> +	if (node < 0)
> +		return node;
> +
> +	dt_device_bind_node(&dev, node);
> +
> +	ret = dt_pbus_get_baseaddr(&dev, baseaddr);
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +int dt_get_memory_params(struct dt_pbus_reg *regs, int nr_regs)
> +{
> +	const char *pn = "device_type", *pv = "memory";
> +	int node, ret, pl = strlen(pv) + 1, nr = 0;
> +	struct dt_pbus_reg reg;
> +
> +	node = fdt_node_offset_by_prop_value(fdt, -1, pn, pv, pl);
> +
> +	while (node >= 0) {
> +
> +		while (nr < nr_regs) {
> +			ret = dt_pbus_translate_node(node, nr, &reg);
> +			if (ret == -FDT_ERR_NOTFOUND)
> +				break;
> +			if (ret < 0)
> +				return ret;
> +			regs[nr].addr = reg.addr;
> +			regs[nr].size = reg.size;
> +			++nr;
> +		}
> +
> +		node = fdt_node_offset_by_prop_value(fdt, node, pn, pv, pl);
> +	}
> +
> +	return node != -FDT_ERR_NOTFOUND ? node : nr;
> +}
> +
> +int dt_for_each_cpu_node(void (*func)(int fdtnode, u32 regval, void *info),
> +			 void *info)
> +{
> +	const struct fdt_property *prop;
> +	int cpus, cpu, ret, len;
> +	struct dt_reg raw_reg;
> +	u32 nac, nsc;
> +
> +	cpus = fdt_path_offset(fdt, "/cpus");
> +	if (cpus < 0)
> +		return cpus;
> +
> +	ret = dt_get_nr_cells(cpus, &nac, &nsc);
> +	if (ret < 0)
> +		return ret;
> +
> +	dt_reg_init(&raw_reg, nac, nsc);
> +
> +	dt_for_each_subnode(cpus, cpu) {
> +
> +		prop = fdt_get_property(fdt, cpu, "device_type", &len);
> +		if (prop == NULL)
> +			return len;
> +
> +		if (len != 4 || strcmp((char *)prop->data, "cpu"))
> +			continue;
> +
> +		ret = dt_get_reg(cpu, 0, &raw_reg);
> +		if (ret < 0)
> +			return ret;
> +
> +		func(cpu, raw_reg.address_cells[0], info);
> +	}
> +
> +	return 0;
> +}
> +
> +int dt_get_bootargs(const char **bootargs)
> +{
> +	const struct fdt_property *prop;
> +	int node, len;
> +
> +	*bootargs = NULL;
> +
> +	node = fdt_path_offset(fdt, "/chosen");
> +	if (node < 0)
> +		return node;
> +
> +	prop = fdt_get_property(fdt, node, "bootargs", &len);
> +	if (prop)
> +		*bootargs = (char *)prop->data;
> +	else if (len < 0 && len != -FDT_ERR_NOTFOUND)
> +		return len;

so if you get FDT_ERR_NOTFOUND you still return success but the bootargs
won't be set? why?

> +
> +	return 0;
> +}
> +
> +int dt_init(const void *fdt_ptr)
> +{
> +	struct dt_bus *defbus = (struct dt_bus *)&dt_default_bus;
> +	int root, ret;
> +
> +	ret = fdt_check_header(fdt_ptr);
> +	if (ret < 0)
> +		return ret;
> +	fdt = fdt_ptr;
> +
> +	root = fdt_path_offset(fdt, "/");
> +	if (root < 0)
> +		return root;
> +
> +	ret = dt_get_nr_cells(root, &root_nr_address_cells,
> +				    &root_nr_size_cells);
> +	if (ret < 0)
> +		return ret;
> +
> +	defbus->nr_address_cells = root_nr_address_cells;
> +	defbus->nr_size_cells = root_nr_size_cells;
> +
> +	return 0;
> +}
> diff --git a/lib/devicetree.h b/lib/devicetree.h
> new file mode 100644
> index 0000000000000..032b5497f9db1
> --- /dev/null
> +++ b/lib/devicetree.h
> @@ -0,0 +1,230 @@
> +#ifndef _DEVICETREE_H_
> +#define _DEVICETREE_H_
> +/*
> + * devicetree builds on libfdt to implement abstractions and accessors
> + * for Linux required device tree content. The accessors provided are
> + * common across architectures. See section III of the kernel doc
> + * Documentation/devicetree/booting-without-of.txt
> + *
> + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#include "libcflat.h"
> +#include "libfdt/libfdt.h"
> +
> +/**********************************************************************
> + * devicetree init and libfdt helpers
> + **********************************************************************/
> +
> +/* dt_init initializes devicetree with a pointer to an fdt, @fdt_ptr */
> +extern int dt_init(const void *fdt_ptr);
> +
> +/* get the fdt pointer that devicetree is using */
> +const void *dt_fdt(void);

nit: why no extern here?

> +
> +/* check for an initialized, valid devicetree */
> +extern bool dt_available(void);
> +
> +/* traverse child nodes */
> +#define dt_for_each_subnode(n, s)					\
> +	for (s = fdt_first_subnode(dt_fdt(), n);			\
> +	     s != -FDT_ERR_NOTFOUND;					\
> +	     s = fdt_next_subnode(dt_fdt(), s))
> +
> +/**********************************************************************
> + * Abstractions for required node types and properties
> + **********************************************************************/
> +
> +struct dt_device {
> +	int fdtnode;
> +	const struct dt_bus *bus;
> +
> +	/*
> +	 * info is a pointer to device specific data, which may be
> +	 * used by the bus match() and translate() functions
> +	 */
> +	void *info;
> +};
> +
> +struct dt_bus {
> +	/*
> +	 * match a device @dev to an fdt node @fdtnode
> +	 * returns
> +	 *  - a positive value on match
> +	 *  - zero on no match
> +	 *  - a negative FDT_ERR_* value on failure
> +	 */
> +	int (*match)(const struct dt_device *dev, int fdtnode);
> +
> +	/*
> +	 * translate the @regidx'th "address size" tuple of
> +	 * @dev's fdt node's "reg" property, and store the result
> +	 * in @reg, a bus specific structure
> +	 * returns
> +	 *  - zero on success
> +	 *  - a negative FDT_ERR_* value on failure
> +	 */
> +	int (*translate)(const struct dt_device *dev, int regidx, void *reg);
> +
> +	/* the bus #address-cells and #size-cells properties */
> +	u32 nr_address_cells, nr_size_cells;
> +};
> +
> +/* dt_bus_match_any matches any fdt node, i.e. it always returns true */
> +extern int dt_bus_match_any(const struct dt_device *dev, int fdtnode);
> +
> +/* the processor bus (pbus) address type and register tuple */
> +typedef u64 dt_pbus_addr_t;
> +struct dt_pbus_reg {
> +	dt_pbus_addr_t addr;
> +	dt_pbus_addr_t size;
> +};
> +
> +static inline dt_pbus_addr_t dt_pbus_read_cells(u32 nr_cells, u32 *cells)
> +{
> +	return nr_cells == 2 ? ((u64)cells[0] << 32) | cells[1]
> +		: nr_cells == 1 ? cells[0] : (~0ULL);

Why the tertiary operator here?  A simple if or select statement should
make the code much easier to read and you don't seem to handle
#address-cells == 4or #size-cells == 4, despite the fact that you define
MAX_ADDRESS_CELLS=4 etc.  This seems a bit weird to me.

> +}
> +
> +/*
> + * dt_pbus_translate translates device node regs for the
> + * processor bus using the root node's #address-cells and
> + * #size-cells and dt_pbus_read_cells()
> + * returns
> + *  - zero on success
> + *  - a negative FDT_ERR_* value on failure
> + */
> +extern int dt_pbus_translate(const struct dt_device *dev, int regidx,
> +			     void *reg);
> +
> +/*
> + * dt_pbus_translate_node is the same as dt_pbus_translate but
> + * operates on an fdt node instead of a dt_device
> + */
> +extern int dt_pbus_translate_node(int fdtnode, int regidx, void *reg);
> +
> +/*
> + * dt_pbus_get_baseaddr is a shortcut for
> + *     dt_pbus_translate(dev, 0, &reg);
> + *     *base = reg.addr;
> + * returns
> + *  - zero on success
> + *  - a negative FDT_ERR_* value on failure
> + */
> +extern int dt_pbus_get_baseaddr(const struct dt_device *dev,
> +				dt_pbus_addr_t *base);
> +
> +/*
> + * dt_bus_init_defaults initializes @bus with
> + *  match		<- dt_bus_match_any
> + *  translate		<- dt_pbus_translate
> + *  nr_address_cells	<- #address-cells of the root node
> + *  nr_size_cells	<- #size-cells of the root node
> + */
> +extern void dt_bus_init_defaults(struct dt_bus *bus);
> +
> +/*
> + * dt_device_init initializes a dt_device with the given parameters
> + */
> +extern void dt_device_init(struct dt_device *dev, const struct dt_bus *bus,
> +			   const void *info);
> +
> +static inline void dt_device_bind_node(struct dt_device *dev, int fdtnode)
> +{
> +	dev->fdtnode = fdtnode;
> +}
> +
> +/*
> + * dt_device_find_compatible finds a @compatible node
> + * returns
> + *  - node (>= 0) on success
> + *  - a negative FDT_ERR_* value on failure
> + */
> +extern int dt_device_find_compatible(const struct dt_device *dev,
> +				     const char *compatible);
> +
> +/*
> + * dt_pbus_get_baseaddr_compatible simply bundles many functions into
> + * one. It finds the first @compatible fdt node and then translates the
> + * 0th reg tuple (the base address) using the processor bus translation,
> + * and finally stores that address in @baseaddr.
> + * returns
> + *  - zero on success
> + *  - a negative FDT_ERR_* value on failure
> + */
> +extern int dt_pbus_get_baseaddr_compatible(const char *compatible,
> +					   dt_pbus_addr_t *baseaddr);
> +
> +/**********************************************************************
> + * Low-level accessors for required node types and properties
> + **********************************************************************/
> +
> +/*
> + * dt_get_nr_cells sets @nr_address_cells and @nr_size_cells to the
> + * #address-cells and #size-cells properties of @fdtnode
> + * returns
> + *  - zero on success
> + *  - a negative FDT_ERR_* value on failure
> + */
> +extern int dt_get_nr_cells(int fdtnode, u32 *nr_address_cells,
> +					u32 *nr_size_cells);
> +
> +/* dt_reg is a structure for "raw" reg tuples */
> +#define MAX_ADDRESS_CELLS	4
> +#define MAX_SIZE_CELLS		4
> +struct dt_reg {
> +	u32 nr_address_cells, nr_size_cells;
> +	u32 address_cells[MAX_ADDRESS_CELLS];
> +	u32 size_cells[MAX_SIZE_CELLS];
> +};
> +
> +/*
> + * dt_reg_init initialize a dt_reg struct to zero and sets
> + * nr_address_cells and nr_size_cells to @nr_address_cells and
> + * @nr_size_cells respectively.
> + */
> +extern void dt_reg_init(struct dt_reg *reg, u32 nr_address_cells,
> +					    u32 nr_size_cells);
> +
> +/*
> + * dt_get_reg gets the @regidx'th reg tuple of @fdtnode's reg property
> + * and stores it in @reg. @reg must be initialized.
> + * returns
> + *  - zero on success
> + *  - a negative FDT_ERR_* value on failure
> + */
> +extern int dt_get_reg(int fdtnode, int regidx, struct dt_reg *reg);
> +
> +/**********************************************************************
> + * High-level accessors for required node types and properties
> + **********************************************************************/
> +
> +/*
> + * dt_get_bootargs gets a pointer to /chosen/bootargs
> + * returns
> + *  - zero on success
> + *  - a negative FDT_ERR_* value on failure
> + */
> +extern int dt_get_bootargs(const char **bootargs);
> +
> +/*
> + * dt_get_memory_params gets the memory parameters from the /memory node(s)
> + * storing each memory region ("address size" tuple) in consecutive entries
> + * of @regs, up to @nr_regs
> + * returns
> + *  - number of memory regions found on success
> + *  - a negative FDT_ERR_* value on failure
> + */
> +extern int dt_get_memory_params(struct dt_pbus_reg *regs, int nr_regs);
> +
> +/*
> + * dt_for_each_cpu_node runs @func on each cpu node in the /cpus node
> + * passing it its fdt node, its reg property value, and @info
> + *  - zero on success
> + *  - a negative FDT_ERR_* value on failure
> + */
> +extern int dt_for_each_cpu_node(void (*func)(int fdtnode, u32 regval,
> +				void *info), void *info);
> +
> +#endif /* _DEVICETREE_H_ */
> diff --git a/lib/libcflat.h b/lib/libcflat.h
> index 76448a33cde5f..99d1cd533dd03 100644
> --- a/lib/libcflat.h
> +++ b/lib/libcflat.h
> @@ -22,6 +22,8 @@
>  
>  #include <stdarg.h>
>  
> +#define __unused __attribute__((__unused__))
> +
>  typedef unsigned char u8;
>  typedef signed char s8;
>  typedef unsigned short u16;
> -- 
> 1.8.1.4
> 

-Christoffer

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 09/19] libcflat: add abort() and assert()
  2014-04-10 16:56 ` [PATCH v4 09/19] libcflat: add abort() and assert() Andrew Jones
@ 2014-06-06 18:38   ` Christoffer Dall
  0 siblings, 0 replies; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:38 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:56:50PM +0200, Andrew Jones wrote:
> The test framework may have external dependencies. assert() provides
> the ability to abort when those dependencies aren't met. However,
> assert() should only be used for unlikely conditions. We can provide
> more informative messages with printf() for the more likely problems.
> 
> Signed-off-by: Andrew Jones <drjones@redhat.com>
> ---

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 10/19] Introduce asm-generic/*.h files
  2014-04-10 16:56 ` [PATCH v4 10/19] Introduce asm-generic/*.h files Andrew Jones
@ 2014-06-06 18:39   ` Christoffer Dall
  2014-06-09  8:23     ` Andrew Jones
  0 siblings, 1 reply; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:39 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:56:51PM +0200, Andrew Jones wrote:
> Architecture neutral code may need to call low-level io accessors,
> or use spinlocks. Create a generic io.h to ensure those accessors
> are defined, and a generic spinlock.h that complains when included,
> as we can't write a generic spinlock. These files can be overridden
> or extended by architecture specific versions placed in
> lib/$ARCH/asm/.
> 
> Signed-off-by: Andrew Jones <drjones@redhat.com>
> ---
> v4: introduce lib/asm symlink to get rid of #ifdef __arm__,
>     add spinlock.h too
> v3: wrt to io.h (was libio.[ch]) only
>     - get rid of CONFIG_64BIT, replace with asserts
>     - get rid of {read,write}_len() [libio.c]
>     - fix bad *64_to_cpu macros
> ---
>  .gitignore                 |   1 +
>  Makefile                   |   6 +-
>  configure                  |  11 ++++
>  lib/asm-generic/io.h       | 154 +++++++++++++++++++++++++++++++++++++++++++++
>  lib/asm-generic/spinlock.h |   4 ++
>  5 files changed, 173 insertions(+), 3 deletions(-)
>  create mode 100644 lib/asm-generic/io.h
>  create mode 100644 lib/asm-generic/spinlock.h
> 
> diff --git a/.gitignore b/.gitignore
> index 775d0dfd8263e..e21939a8771e9 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -9,6 +9,7 @@ patches
>  .stgit-*
>  cscope.*
>  *.swp
> +/lib/asm
>  /config.mak
>  /*-run
>  /test.log
> diff --git a/Makefile b/Makefile
> index fba58e36f272f..51cacdac00615 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -76,11 +76,11 @@ libfdt_clean:
>  	$(LIBFDT_objdir)/.*.d
>  
>  distclean: clean libfdt_clean
> -	$(RM) config.mak $(TEST_DIR)-run test.log msr.out cscope.*
> +	$(RM) lib/asm config.mak $(TEST_DIR)-run test.log msr.out cscope.*
>  
> -cscope: common_dirs = lib lib/libfdt
> +cscope: common_dirs = lib lib/libfdt lib/asm lib/asm-generic
>  cscope:
>  	$(RM) ./cscope.*
> -	find $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
> +	find -L $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
>  		-name '*.[chsS]' -print | sed 's,^\./,,' > ./cscope.files
>  	cscope -bk
> diff --git a/configure b/configure
> index 6cfc64943f6e6..8a81bf92e27b7 100755
> --- a/configure
> +++ b/configure
> @@ -95,6 +95,17 @@ if [ $exit -eq 0 ]; then
>  fi
>  rm -f lib_test.c
>  
> +# link lib/asm for the architecture
> +rm -f lib/asm
> +asm=asm-generic
> +if [ -d lib/$arch/asm ]; then
> +	asm=$arch/asm
> +elif [ -d lib/$testdir/asm ]; then
> +	asm=$testdir/asm

why do you need this elif?  can you not make sure arch is always set?

> +fi
> +ln -s $asm lib/asm
> +
> +# create the config
>  cat <<EOF > config.mak
>  PREFIX=$prefix
>  KERNELDIR=$(readlink -f $kerneldir)

[...]

-Christoffer

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 11/19] add minimal virtio support for devtree virtio-mmio
  2014-04-10 16:56 ` [PATCH v4 11/19] add minimal virtio support for devtree virtio-mmio Andrew Jones
@ 2014-06-06 18:39   ` Christoffer Dall
  2014-06-09  9:02     ` Andrew Jones
  0 siblings, 1 reply; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:39 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:56:52PM +0200, Andrew Jones wrote:
> Support the bare minimum of virtio to enable access to the virtio-mmio
> config space of a device. Currently this implementation must use a
> device tree to find the device.
> 
> Signed-off-by: Andrew Jones <drjones@redhat.com>
> ---
> v4:
>  - split from the virtio-testdev patch
>  - search a table to "discover" that the device must be DT/virtio-mmio,
>    which doesn't change anything, but looks less hacky than comments
>    saying the device must be DT/virtio-mmio...
>  - manage own pool of virtio-mmio pre-allocated device structures in
>    order to avoid needing access to the heap
> ---
>  lib/libcflat.h |   3 ++
>  lib/virtio.c   | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/virtio.h   |  89 +++++++++++++++++++++++++++++++
>  3 files changed, 258 insertions(+)
>  create mode 100644 lib/virtio.c
>  create mode 100644 lib/virtio.h
> 
> diff --git a/lib/libcflat.h b/lib/libcflat.h
> index c7c31be1cc8e5..5bb66d01dfc53 100644
> --- a/lib/libcflat.h
> +++ b/lib/libcflat.h
> @@ -62,6 +62,9 @@ extern long atol(const char *ptr);
>  #define ARRAY_SIZE(_a)  (sizeof(_a)/sizeof((_a)[0]))
>  
>  #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
> +#define container_of(ptr, type, member) ({				\
> +	const typeof( ((type *)0)->member ) *__mptr = (ptr);		\
> +	(type *)( (char *)__mptr - offsetof(type,member) );})
>  
>  #define NULL ((void *)0UL)
>  
> diff --git a/lib/virtio.c b/lib/virtio.c
> new file mode 100644
> index 0000000000000..e7161ff591e4c
> --- /dev/null
> +++ b/lib/virtio.c
> @@ -0,0 +1,166 @@
> +/*
> + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#include "libcflat.h"
> +#include "devicetree.h"
> +#include "asm/spinlock.h"
> +#include "asm/io.h"
> +#include "virtio.h"
> +
> +enum virtio_hwdesc_type {
> +	VIRTIO_HWDESC_TYPE_DT = 0,	/* device tree */
> +	NR_VIRTIO_HWDESC_TYPES,
> +};
> +
> +enum virtio_bus_type {
> +	VIRTIO_BUS_TYPE_MMIO = 0,	/* virtio-mmio */
> +	NR_VIRTIO_BUS_TYPES,
> +};
> +
> +struct virtio_bind_bus {
> +	bool (*hwdesc_probe)(void);
> +	struct virtio_dev *(*device_bind)(u32 devid);
> +};
> +
> +static struct virtio_dev *vm_dt_device_bind(u32 devid);
> +
> +static struct virtio_bind_bus
> +virtio_bind_busses[NR_VIRTIO_HWDESC_TYPES][NR_VIRTIO_BUS_TYPES] = {
> +
> +[VIRTIO_HWDESC_TYPE_DT] = {
> +
> +	[VIRTIO_BUS_TYPE_MMIO] = {
> +		.hwdesc_probe = dt_available,
> +		.device_bind = vm_dt_device_bind,
> +	},
> +},
> +};
> +
> +struct virtio_dev *virtio_bind(u32 devid)
> +{
> +	struct virtio_bind_bus *bus;
> +	struct virtio_dev *dev;
> +	int i, j;
> +
> +	for (i = 0; i < NR_VIRTIO_HWDESC_TYPES; ++i) {
> +		for (j = 0; j < NR_VIRTIO_BUS_TYPES; ++j) {
> +
> +			bus = &virtio_bind_busses[i][j];
> +
> +			if (!bus->hwdesc_probe())
> +				continue;
> +
> +			dev = bus->device_bind(devid);
> +			if (dev)
> +				return dev;
> +		}
> +	}
> +
> +	return NULL;
> +}
> +
> +/******************************************************
> + * virtio-mmio support (config space only)
> + ******************************************************/
> +
> +static void vm_get(struct virtio_dev *vdev, unsigned offset,
> +		   void *buf, unsigned len)
> +{
> +	struct virtio_mmio_dev *vmdev = to_virtio_mmio_dev(vdev);
> +	u8 *p = buf;
> +	unsigned i;
> +
> +	for (i = 0; i < len; ++i)
> +		p[i] = readb(vmdev->base + VIRTIO_MMIO_CONFIG + offset + i);
> +}
> +
> +static void vm_set(struct virtio_dev *vdev, unsigned offset,
> +		   const void *buf, unsigned len)
> +{
> +	struct virtio_mmio_dev *vmdev = to_virtio_mmio_dev(vdev);
> +	const u8 *p = buf;
> +	unsigned i;
> +
> +	for (i = 0; i < len; ++i)
> +		writeb(p[i], vmdev->base + VIRTIO_MMIO_CONFIG + offset + i);
> +}
> +
> +#define NR_VM_DEVICES 32
> +static struct spinlock vm_lock;
> +static struct virtio_mmio_dev vm_devs[NR_VM_DEVICES];
> +static struct virtio_conf_ops vm_confs[NR_VM_DEVICES];
> +static int nr_vm_devs;
> +
> +static struct virtio_mmio_dev *vm_new_device(u32 devid)
> +{
> +	struct virtio_mmio_dev *vmdev;
> +
> +	if (nr_vm_devs >= NR_VM_DEVICES)
> +		return NULL;
> +
> +	spin_lock(&vm_lock);
> +	vmdev = &vm_devs[nr_vm_devs];
> +	vmdev->vdev.config = &vm_confs[nr_vm_devs];

this seems a bit weird, will we ever share vm_confs between vm_devs or
change the vm_conf pointer later on?  Could vm_conf just be part of the
vm_dev struct and you could just have a virtio_mmio_conf_init() to set
the get/set functions?

> +	++nr_vm_devs;
> +	spin_unlock(&vm_lock);
> +
> +	vmdev->vdev.id.device = devid;
> +	vmdev->vdev.id.vendor = -1;
> +	vmdev->vdev.config->get = vm_get;
> +	vmdev->vdev.config->set = vm_set;
> +
> +	return vmdev;
> +}
> +
> +/******************************************************
> + * virtio-mmio device tree support
> + ******************************************************/
> +
> +struct vm_dt_info {
> +	u32 devid;
> +	void *base;

won't work for LPAE and 32-bit arm systems, can't you use
dt_device_bind_node?

I guess that requires you to have an ioremap function, but it sure seems
cleaner to give up there if you don't have proper memory mapping
features yet....

> +};
> +
> +static int vm_dt_match(const struct dt_device *dev, int fdtnode)
> +{
> +	struct vm_dt_info *info = (struct vm_dt_info *)dev->info;
> +	dt_pbus_addr_t base;
> +
> +	dt_device_bind_node((struct dt_device *)dev, fdtnode);
> +
> +	assert(dt_pbus_get_baseaddr(dev, &base) == 0);
> +	assert(sizeof(long) == 8 || !(base >> 32));

again, this assert will break with >32bit LPAE addresses on 32-bit arm systems.

so, not sure if it's an assert, or if you should test for it and print
a more benign error for these types of devices.

> +
> +	info->base = (void *)(unsigned long)base;

why do you need to cast it twice?

> +
> +	return readl(info->base + VIRTIO_MMIO_DEVICE_ID) == info->devid;
> +}
> +
> +static struct virtio_dev *vm_dt_device_bind(u32 devid)
> +{
> +	struct virtio_mmio_dev *vmdev;
> +	struct dt_device dt_dev;
> +	struct dt_bus dt_bus;
> +	struct vm_dt_info info;
> +	int node;
> +
> +	dt_bus_init_defaults(&dt_bus);
> +	dt_bus.match = vm_dt_match;
> +
> +	info.devid = devid;
> +
> +	dt_device_init(&dt_dev, &dt_bus, &info);
> +
> +	node = dt_device_find_compatible(&dt_dev, "virtio,mmio");
> +	assert(node >= 0 || node == -FDT_ERR_NOTFOUND);
> +
> +	if (node == -FDT_ERR_NOTFOUND)
> +		return NULL;
> +
> +	vmdev = vm_new_device(devid);
> +	vmdev->base = info.base;
> +
> +	return &vmdev->vdev;
> +}
> diff --git a/lib/virtio.h b/lib/virtio.h
> new file mode 100644
> index 0000000000000..163b9912c4e05
> --- /dev/null
> +++ b/lib/virtio.h
> @@ -0,0 +1,89 @@
> +#ifndef _VIRTIO_H_
> +#define _VIRTIO_H_
> +/*
> + * A minimal implementation of virtio for virtio-mmio config space
> + * access.
> + *
> + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#include "libcflat.h"
> +
> +struct virtio_devid {
> +	u32 device;
> +	u32 vendor;
> +};
> +
> +struct virtio_dev {
> +	struct virtio_devid id;
> +	struct virtio_conf_ops *config;
> +};
> +
> +struct virtio_conf_ops {
> +	void (*get)(struct virtio_dev *vdev, unsigned offset,
> +		    void *buf, unsigned len);
> +	void (*set)(struct virtio_dev *vdev, unsigned offset,
> +		    const void *buf, unsigned len);
> +};
> +
> +extern struct virtio_dev *virtio_bind(u32 devid);
> +
> +static inline u8
> +virtio_config_readb(struct virtio_dev *vdev, unsigned offset)
> +{
> +	u8 val;
> +	vdev->config->get(vdev, offset, &val, 1);
> +	return val;
> +}
> +
> +static inline u16
> +virtio_config_readw(struct virtio_dev *vdev, unsigned offset)
> +{
> +	u16 val;
> +	vdev->config->get(vdev, offset, &val, 2);
> +	return val;
> +}
> +
> +static inline u32
> +virtio_config_readl(struct virtio_dev *vdev, unsigned offset)
> +{
> +	u32 val;
> +	vdev->config->get(vdev, offset, &val, 4);
> +	return val;
> +}
> +
> +static inline void
> +virtio_config_writeb(struct virtio_dev *vdev, unsigned offset, u8 val)
> +{
> +	vdev->config->set(vdev, offset, &val, 1);
> +}
> +
> +static inline void
> +virtio_config_writew(struct virtio_dev *vdev, unsigned offset, u16 val)
> +{
> +	vdev->config->set(vdev, offset, &val, 2);
> +}
> +
> +static inline void
> +virtio_config_writel(struct virtio_dev *vdev, unsigned offset, u32 val)
> +{
> +	vdev->config->set(vdev, offset, &val, 4);
> +}
> +
> +/******************************************************
> + * virtio-mmio
> + ******************************************************/
> +
> +#define VIRTIO_MMIO_DEVICE_ID	0x008
> +#define VIRTIO_MMIO_CONFIG	0x100
> +
> +#define to_virtio_mmio_dev(vdev_ptr) \
> +	container_of(vdev_ptr, struct virtio_mmio_dev, vdev)
> +
> +struct virtio_mmio_dev {
> +	struct virtio_dev vdev;
> +	void *base;
> +};
> +
> +#endif /* _VIRTIO_H_ */
> -- 
> 1.8.1.4
> 

-Christoffer

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 12/19] Introduce virtio-testdev
  2014-04-10 16:56 ` [PATCH v4 12/19] Introduce virtio-testdev Andrew Jones
@ 2014-06-06 18:39   ` Christoffer Dall
  0 siblings, 0 replies; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:39 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:56:53PM +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>

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 13/19] libcflat: clean up libcflat.h and add string.h
  2014-04-10 16:56 ` [PATCH v4 13/19] libcflat: clean up libcflat.h and add string.h Andrew Jones
@ 2014-06-06 18:39   ` Christoffer Dall
  0 siblings, 0 replies; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:39 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:56:54PM +0200, Andrew Jones wrote:
> Use libgcc's stddef.h and stdint.h, and then remove the redundant
> defines from libcflat.h. Also separate out the string function
> declarations into a new file string.h. These changes have no affect
> on code including libcflat.h, but are needed in order to compile an
> unmodified libfdt for kvm-unit-tests using an arm cross-compiler.
> While at it, add strcpy.
> 
> Signed-off-by: Andrew Jones <drjones@redhat.com>

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 14/19] printf: support field padding
  2014-04-10 16:56 ` [PATCH v4 14/19] printf: support field padding Andrew Jones
@ 2014-06-06 18:39   ` Christoffer Dall
  0 siblings, 0 replies; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:39 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:56:55PM +0200, Andrew Jones wrote:
> Support format flags for field padding, such as "%08x", allowing
> register dumps to be easier on the eyes.
> 
> Signed-off-by: Andrew Jones <drjones@redhat.com>

I think I gave this my Reviewed-by in the last round, and there is no
changelog.  If anything changed here, let me know, otherwise apply the
tag.

-Christoffer

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 15/19] arm: initial drop
  2014-04-10 16:56 ` [PATCH v4 15/19] arm: initial drop Andrew Jones
@ 2014-06-06 18:39   ` Christoffer Dall
  2014-06-09  9:44     ` Andrew Jones
  0 siblings, 1 reply; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:39 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:56:56PM +0200, Andrew Jones wrote:
> This is the initial drop of the arm test framework and a first test
> that just checks that setup completed (a selftest). kvm isn't needed
> to run this test unless testing with smp > 1.
> 
> Try it out with
>   yum install gcc-arm-linux-gnu
>   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>
> ---
> v4:
>   - moved fdt to just after stacktop (it was in the middle of free memory)
>   - switched from using heap to memregions
>   - get nr_cpus and added smp=<num> test
>   - added barrier.h
>   - use new report()/report_summary()
>   - config/config-arm.mak cleanup
> ---
>  arm/cstart.S           |  35 ++++++++++++
>  arm/flat.lds           |  18 +++++++
>  arm/run                |  31 +++++++++++
>  arm/selftest.c         |  87 ++++++++++++++++++++++++++++++
>  arm/unittests.cfg      |  18 +++++++
>  config/config-arm.mak  |  72 +++++++++++++++++++++++++
>  configure              |  12 ++++-
>  lib/argv.c             |   6 +++
>  lib/arm/asm/barrier.h  |  18 +++++++
>  lib/arm/asm/io.h       |  24 +++++++++
>  lib/arm/asm/setup.h    |  39 ++++++++++++++
>  lib/arm/asm/spinlock.h |  16 ++++++
>  lib/arm/eabi_compat.c  |  20 +++++++
>  lib/arm/io.c           |  66 +++++++++++++++++++++++
>  lib/arm/setup.c        | 142 +++++++++++++++++++++++++++++++++++++++++++++++++
>  15 files changed, 602 insertions(+), 2 deletions(-)
>  create mode 100644 arm/cstart.S
>  create mode 100644 arm/flat.lds
>  create mode 100755 arm/run
>  create mode 100644 arm/selftest.c
>  create mode 100644 arm/unittests.cfg
>  create mode 100644 config/config-arm.mak
>  create mode 100644 lib/arm/asm/barrier.h
>  create mode 100644 lib/arm/asm/io.h
>  create mode 100644 lib/arm/asm/setup.h
>  create mode 100644 lib/arm/asm/spinlock.h
>  create mode 100644 lib/arm/eabi_compat.c
>  create mode 100644 lib/arm/io.c
>  create mode 100644 lib/arm/setup.c
> 
> diff --git a/arm/cstart.S b/arm/cstart.S
> new file mode 100644
> index 0000000000000..e28251db2950d
> --- /dev/null
> +++ b/arm/cstart.S
> @@ -0,0 +1,35 @@
> +/*
> + * Boot entry point and assembler functions for armv7 tests.
> + *
> + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +
> +.arm
> +
> +.section .init
> +
> +.globl start
> +start:
> +	/*
> +	 * bootloader params are in r0-r2
> +	 * See the kernel doc Documentation/arm/Booting
> +	 */
> +	ldr	sp, =stacktop
> +	bl	setup
> +
> +	/* run the test */
> +	ldr	r0, =__argc
> +	ldr	r0, [r0]
> +	ldr	r1, =__argv
> +	bl	main
> +	bl	exit
> +	b	halt
> +
> +.text
> +
> +.globl halt
> +halt:
> +1:	wfi
> +	b	1b
> 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..985b26e1334da
> --- /dev/null
> +++ b/arm/run
> @@ -0,0 +1,31 @@
> +#!/bin/bash
> +
> +if [ ! -f config.mak ]; then
> +	echo run ./configure first. See ./configure -h
> +	exit 2
> +fi
> +source config.mak
> +
> +qemu="${QEMU:-qemu-system-arm}"
> +testdev=virtio-testdev
> +
> +if ! $qemu -device '?' 2>&1 | grep $testdev > /dev/null; then
> +	qpath=$(which $qemu 2>/dev/null)
> +	if [ "$qpath" ]; then
> +		echo $qpath doesn\'t support virtio-testdev. Exiting.
> +	else
> +		echo $qemu not found.
> +	fi
> +	exit 2
> +fi
> +
> +command="$qemu -device $testdev -display none -serial stdio "
> +command+="-M virt -cpu $PROCESSOR "
> +#command+="-enable-kvm "
> +command+="-kernel"
> +
> +echo $command "$@"
> +$command "$@"
> +ret=$?
> +echo Return value from qemu: $ret
> +exit $ret
> diff --git a/arm/selftest.c b/arm/selftest.c
> new file mode 100644
> index 0000000000000..45729e9ac85d9
> --- /dev/null
> +++ b/arm/selftest.c
> @@ -0,0 +1,87 @@
> +/*
> + * Test the framework itself. These tests confirm that setup works.
> + *
> + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#include "libcflat.h"
> +#include "asm/setup.h"
> +
> +#define TESTGRP "selftest"
> +
> +static char testnam[64];

is testnam testname?

> +
> +static void testnam_set(const char *subtest)
> +{
> +	strcpy(testnam, TESTGRP);
> +	strcat(testnam, "::");
> +	strcat(testnam, subtest);
> +}
> +
> +static void assert_args(int num_args, int needed_args)
> +{
> +	if (num_args < needed_args) {
> +		printf("%s: not enough arguments\n", testnam);
> +		abort();
> +	}
> +}
> +
> +static char *split_var(char *s, long *val)
> +{
> +	char *p;
> +
> +	p = strchr(s, '=');
> +	if (!p)
> +		return NULL;
> +
> +	*val = atol(p+1);
> +	*p = '\0';
> +
> +	return s;
> +}
> +
> +static void check_setup(int argc, char **argv)
> +{
> +	int nr_tests = 0, i;
> +	char *var;
> +	long val;
> +
> +	for (i = 0; i < argc; ++i) {
> +
> +		var = split_var(argv[i], &val);
> +		if (!var)
> +			continue;
> +
> +		if (strcmp(argv[i], "mem") == 0) {
> +
> +			phys_addr_t memsize =
> +					memregions[nr_memregions-1].addr
> +					+ memregions[nr_memregions-1].size
> +					- PHYS_OFFSET;
> +			phys_addr_t expected = ((phys_addr_t)val)*1024*1024;
> +
> +			report("%s[%s]", memsize == expected, testnam, "mem");
> +			++nr_tests;
> +
> +		} else if (strcmp(argv[i], "smp") == 0) {
> +
> +			report("%s[%s]", nr_cpus == (int)val, testnam, "smp");
> +			++nr_tests;
> +		}
> +	}
> +
> +	assert_args(nr_tests, 2);
> +}
> +
> +int main(int argc, char **argv)
> +{
> +	assert_args(argc, 1);
> +
> +	testnam_set(argv[0]);
> +
> +	if (strcmp(argv[0], "setup") == 0)
> +		check_setup(argc-1, &argv[1]);
> +
> +	return report_summary();
> +}
> diff --git a/arm/unittests.cfg b/arm/unittests.cfg
> new file mode 100644
> index 0000000000000..da9dfd7b1f118
> --- /dev/null
> +++ b/arm/unittests.cfg
> @@ -0,0 +1,18 @@
> +# 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 test case is specific to one
> +# groups = group1 group2 # Used to identify test cases with run_tests -g ...
> +
> +#
> +# Test that the configured number of processors (smp = <num>), and
> +# that the configured amount of memory (-m <MB>) are correctly setup
> +# by the framework.
> +#
> +[selftest::setup]
> +file = selftest.flat
> +smp  = 1
> +extra_params = -m 256 -append 'setup smp=1 mem=256'
> +groups = selftest
> diff --git a/config/config-arm.mak b/config/config-arm.mak
> new file mode 100644
> index 0000000000000..915b1cc318d79
> --- /dev/null
> +++ b/config/config-arm.mak
> @@ -0,0 +1,72 @@
> +#
> +# arm makefile
> +#
> +# Authors: Andrew Jones <drjones@redhat.com>
> +#
> +
> +tests-common = \
> +	$(TEST_DIR)/selftest.flat
> +
> +tests =
> +
> +all: test_cases
> +
> +##################################################################
> +bits = 32
> +ldarch = elf32-littlearm
> +
> +ifeq ($(LOADADDR),)
> +	LOADADDR = 0x40000000
> +endif
> +phys_base = $(LOADADDR)
> +kernel_offset = 0x10000
> +
> +CFLAGS += -D__arm__
> +CFLAGS += -marm
> +CFLAGS += -mcpu=$(PROCESSOR)
> +CFLAGS += -std=gnu99
> +CFLAGS += -ffreestanding
> +CFLAGS += -Wextra
> +CFLAGS += -O2
> +CFLAGS += -I lib -I lib/libfdt
> +
> +cflatobjs += \
> +	lib/devicetree.o \
> +	lib/virtio.o \
> +	lib/virtio-testdev.o \
> +	lib/arm/io.o \
> +	lib/arm/setup.o
> +
> +libeabi = lib/arm/libeabi.a
> +eabiobjs = lib/arm/eabi_compat.o
> +
> +libgcc := $(shell $(CC) -m$(ARCH) --print-libgcc-file-name)
> +start_addr := $(shell printf "%x\n" $$(( $(phys_base) + $(kernel_offset) )))
> +
> +FLATLIBS = $(libcflat) $(LIBFDT_archive) $(libgcc) $(libeabi)
> +%.elf: LDFLAGS = $(CFLAGS) -nostdlib
> +%.elf: %.o $(FLATLIBS) arm/flat.lds
> +	$(CC) $(LDFLAGS) -o $@ \
> +		-Wl,-T,arm/flat.lds,--build-id=none,-Ttext=$(start_addr) \
> +		$(filter %.o, $^) $(FLATLIBS)
> +
> +%.flat: %.elf
> +	$(OBJCOPY) -O binary $^ $@
> +
> +$(libeabi): $(eabiobjs)
> +	$(AR) rcs $@ $^
> +
> +arch_clean: libfdt_clean
> +	$(RM) $(TEST_DIR)/*.{o,flat,elf} $(libeabi) $(eabiobjs) \
> +	      $(TEST_DIR)/.*.d lib/arm/.*.d
> +
> +##################################################################
> +
> +tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg
> +
> +cstart.o = $(TEST_DIR)/cstart.o
> +
> +test_cases: $(tests-common) $(tests)
> +
> +$(TEST_DIR)/selftest.elf: $(cstart.o) $(TEST_DIR)/selftest.o
> +
> diff --git a/configure b/configure
> index 8a81bf92e27b7..f92f585724bb1 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,12 @@ while [[ "$1" = -* ]]; do
>  	    ;;
>      esac
>  done
> +[ -z "$processor" ] && processor="$arch"
> +
> +if [ "$processor" = "arm" ]; then
> +    processor="cortex-a15"
> +fi
> +
>  if [ -z "$testdir" -a \( "$arch" = "i386" -o "$arch" = "x86_64" \) ]; then
>      testdir=x86
>  elif [ -z "$testdir" ]; then
> @@ -80,6 +86,7 @@ if [ -f $testdir/run ]; then
>  fi
>  
>  # check for dependent 32 bit libraries
> +if [ "$arch" != "arm" ]; then
>  cat << EOF > lib_test.c
>  #include <stdc++.h>
>  #include <boost_thread-mt.h>
> @@ -94,6 +101,7 @@ if [ $exit -eq 0 ]; then
>      api=true
>  fi
>  rm -f lib_test.c
> +fi
>  
>  # link lib/asm for the architecture
>  rm -f lib/asm
> diff --git a/lib/argv.c b/lib/argv.c
> index 4ee54a6eeac3e..078a05faffebf 100644
> --- a/lib/argv.c
> +++ b/lib/argv.c
> @@ -31,3 +31,9 @@ void __setup_args(void)
>      }
>      __argc = argv - __argv;
>  }
> +
> +void setup_args(char *args)
> +{
> +    __args = args;
> +    __setup_args();
> +}
> diff --git a/lib/arm/asm/barrier.h b/lib/arm/asm/barrier.h
> new file mode 100644
> index 0000000000000..acaeab5123431
> --- /dev/null
> +++ b/lib/arm/asm/barrier.h
> @@ -0,0 +1,18 @@
> +#ifndef _ASMARM_BARRIER_H_
> +#define _ASMARM_BARRIER_H_
> +/*
> + * Adapted form arch/arm/include/asm/barrier.h
> + */
> +
> +#define isb(option) __asm__ __volatile__ ("isb " #option : : : "memory")
> +#define dsb(option) __asm__ __volatile__ ("dsb " #option : : : "memory")
> +#define dmb(option) __asm__ __volatile__ ("dmb " #option : : : "memory")
> +
> +#define mb()		dsb()
> +#define rmb()		dsb()
> +#define wmb()		dsb(st)
> +#define smp_mb()	dmb(ish)
> +#define smp_rmb()	smp_mb()
> +#define smp_wmb()	dmb(ishst)
> +
> +#endif /* _ASMARM_BARRIER_H_ */
> diff --git a/lib/arm/asm/io.h b/lib/arm/asm/io.h
> new file mode 100644
> index 0000000000000..51ec6e9aa2e99
> --- /dev/null
> +++ b/lib/arm/asm/io.h
> @@ -0,0 +1,24 @@
> +#ifndef _ASMARM_IO_H_
> +#define _ASMARM_IO_H_
> +#include "libcflat.h"
> +#include "asm/barrier.h"
> +
> +#define __bswap16 bswap16
> +static inline u16 bswap16(u16 val)
> +{
> +	u16 ret;
> +	asm volatile("rev16 %0, %1" : "=r" (ret) :  "r" (val));
> +	return ret;
> +}
> +
> +#define __bswap32 bswap32
> +static inline u32 bswap32(u32 val)
> +{
> +	u32 ret;
> +	asm volatile("rev %0, %1" : "=r" (ret) :  "r" (val));
> +	return ret;
> +}
> +
> +#include "asm-generic/io.h"
> +
> +#endif /* _ASMARM_IO_H_ */
> diff --git a/lib/arm/asm/setup.h b/lib/arm/asm/setup.h
> new file mode 100644
> index 0000000000000..d451b23434041
> --- /dev/null
> +++ b/lib/arm/asm/setup.h
> @@ -0,0 +1,39 @@
> +#ifndef _ASMARM_SETUP_H_
> +#define _ASMARM_SETUP_H_
> +/*
> + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#include "libcflat.h"
> +
> +#define NR_CPUS			8
> +extern u32 cpus[NR_CPUS];
> +extern int nr_cpus;
> +
> +typedef u64 phys_addr_t;
> +
> +#define NR_MEMREGIONS		16
> +struct memregion {
> +	phys_addr_t addr;
> +	phys_addr_t size;
> +	bool free;
> +};
> +
> +extern struct memregion memregions[NR_MEMREGIONS];
> +extern int nr_memregions;
> +
> +extern struct memregion *memregion_new(phys_addr_t size);
> +extern void memregions_show(void);
> +
> +#define PHYS_OFFSET		({ memregions[0].addr; })
> +#define PHYS_SHIFT		40
> +#define PHYS_SIZE		(1ULL << PHYS_SHIFT)
> +#define PHYS_MASK		(PHYS_SIZE - 1ULL)

it's pretty funky that you define PHYS_MASK the opposite of PAGE_MASK?

> +
> +#define PAGE_SHIFT		12
> +#define PAGE_SIZE		(1UL << PAGE_SHIFT)
> +#define PAGE_MASK		(~(PAGE_SIZE - 1UL))
> +#define PAGE_ALIGN(addr)	(((addr) + (PAGE_SIZE-1UL)) & PAGE_MASK)
> +
> +#endif /* _ASMARM_SETUP_H_ */
> diff --git a/lib/arm/asm/spinlock.h b/lib/arm/asm/spinlock.h
> new file mode 100644
> index 0000000000000..04f5a1a5538e2
> --- /dev/null
> +++ b/lib/arm/asm/spinlock.h
> @@ -0,0 +1,16 @@
> +#ifndef _ASMARM_SPINLOCK_H_
> +#define _ASMARM_SPINLOCK_H_
> +
> +struct spinlock {
> +	int v;
> +};
> +
> +//TODO
> +static inline void spin_lock(struct spinlock *lock __unused)
> +{
> +}
> +static inline void spin_unlock(struct spinlock *lock __unused)
> +{
> +}
> +
> +#endif /* _ASMARM_SPINLOCK_H_ */
> diff --git a/lib/arm/eabi_compat.c b/lib/arm/eabi_compat.c
> new file mode 100644
> index 0000000000000..59d624dcd9277
> --- /dev/null
> +++ b/lib/arm/eabi_compat.c
> @@ -0,0 +1,20 @@
> +/*
> + * Adapted from u-boot's arch/arm/lib/eabi_compat.c
> + */
> +#include "libcflat.h"
> +
> +int raise(int signum __unused)
> +{
> +	printf("Divide by zero!\n");
> +	abort();
> +	return 0;
> +}
> +
> +/* Dummy functions to avoid linker complaints */
> +void __aeabi_unwind_cpp_pr0(void)
> +{
> +}
> +
> +void __aeabi_unwind_cpp_pr1(void)
> +{
> +}
> diff --git a/lib/arm/io.c b/lib/arm/io.c
> new file mode 100644
> index 0000000000000..c865f61c94934
> --- /dev/null
> +++ b/lib/arm/io.c
> @@ -0,0 +1,66 @@
> +/*
> + * Each architecture must implement puts() and exit() with the I/O
> + * devices exposed from QEMU, e.g. pl011 and virtio-testdev. That's
> + * what's done here, along with initialization functions for those
> + * devices.
> + *
> + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#include "libcflat.h"
> +#include "devicetree.h"
> +#include "virtio-testdev.h"
> +#include "asm/spinlock.h"
> +#include "asm/io.h"
> +
> +extern void halt(int code);
> +
> +/*
> + * Use this guess for the pl011 base in order to make an attempt at
> + * having earlier printf support. We'll overwrite it with the real
> + * base address that we read from the device tree later.
> + */
> +#define QEMU_MACH_VIRT_PL011_BASE 0x09000000UL
> +
> +static struct spinlock uart_lock;
> +static volatile u8 *uart0_base = (u8 *)QEMU_MACH_VIRT_PL011_BASE;
> +
> +static void uart0_init(void)
> +{
> +	const char *compatible = "arm,pl011";
> +	dt_pbus_addr_t base;
> +	int ret;
> +
> +	ret = dt_pbus_get_baseaddr_compatible(compatible, &base);
> +	assert(ret == 0 || ret == -FDT_ERR_NOTFOUND);
> +
> +	if (ret == 0) {
> +		assert(sizeof(long) == 8 || !(base >> 32));

didn't we already check this somewhere?  Or was that virtio specific?

This confirms my suspicion that you should add a dummy identity ioremap
function that can do this check once.

> +		uart0_base = (u8 *)(unsigned long)base;

hmmm, u8*, I guess that sort of makes sense...

> +	} else {
> +		printf("%s: %s not found in the device tree, aborting...\n",
> +			__func__, compatible);
> +		abort();

I think this function would read nicer if you did this right after your
assert:

if (ret) {
	printf(....);
	abort();
	}

uart0_base = ....;

> +	}
> +}
> +
> +void io_init(void)
> +{
> +	uart0_init();
> +	virtio_testdev_init();
> +}
> +
> +void puts(const char *s)
> +{
> +	spin_lock(&uart_lock);
> +	while (*s)
> +		writel(*s++, uart0_base);
> +	spin_unlock(&uart_lock);
> +}
> +
> +void exit(int code)
> +{
> +	virtio_testdev_exit(code);
> +	halt(code);
> +}
> diff --git a/lib/arm/setup.c b/lib/arm/setup.c
> new file mode 100644
> index 0000000000000..3794291e94e01
> --- /dev/null
> +++ b/lib/arm/setup.c
> @@ -0,0 +1,142 @@
> +/*
> + * Initialize machine setup information and I/O.
> + *
> + * After running setup() a flat file knows how many cpus it has

'a flat file knows' ?

> + * (nr_cpus), how much free memory it has, and at what physical
> + * address that free memory starts (memregions[1].{addr,size}),
> + * printf() and exit() will both work, and (argc, argv) are ready
> + * to be passed to main().
> + *
> + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#include "libcflat.h"
> +#include "libfdt/libfdt.h"
> +#include "devicetree.h"
> +#include "asm/spinlock.h"
> +#include "asm/setup.h"
> +
> +extern unsigned long stacktop;
> +extern void io_init(void);
> +extern void setup_args(const char *args);
> +
> +u32 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0UL) };
> +int nr_cpus;
> +
> +static struct spinlock memregion_lock;
> +struct memregion memregions[NR_MEMREGIONS];
> +int nr_memregions;
> +
> +static void cpu_set(int fdtnode __unused, u32 regval, void *info)
> +{
> +	unsigned *i = (unsigned *)info;

shouldn't you assert (*i) < NR_CPUS?

> +	cpus[*i] = regval;
> +	*i += 1;

holy cow that's a convoluted way of counting.  Can't you just bump the
nr_cpus here?

> +}
> +
> +static void cpu_init(void)
> +{
> +	unsigned i = 0;
> +	assert(dt_for_each_cpu_node(cpu_set, &i) == 0);
> +	nr_cpus = i;
> +}
> +
> +static void memregions_init(phys_addr_t freemem_start)
> +{
> +	/* we only expect one membank to be defined in the DT */
> +	struct dt_pbus_reg regs[1];
> +	phys_addr_t addr, size, mem_end;
> +
> +	nr_memregions = dt_get_memory_params(regs, 1);
> +
> +	assert(nr_memregions > 0);
> +
> +	addr = regs[0].addr;
> +	size = regs[0].size;
> +	mem_end = addr + size;
> +
> +	assert(!(addr & ~PHYS_MASK) && !((mem_end-1) & ~PHYS_MASK));
> +
> +#ifdef __arm__
> +	/* TODO: support highmem? */

I don't think highmem is the right term here, the concept is LPAE

> +	assert(!((u64)addr >> 32) && !((u64)(mem_end-1) >> 32));
> +#endif
> +
> +	freemem_start = PAGE_ALIGN(freemem_start);
> +
> +	memregions[0].addr = PAGE_ALIGN(addr);
> +	memregions[0].size = freemem_start - PHYS_OFFSET;

don't you want to assert that the membank found in the dt actually
covers the addresses we're loaded at?

> +
> +	memregions[1].addr = freemem_start;
> +	memregions[1].size = mem_end - freemem_start;
> +	memregions[1].free = true;

you could have defines for 0 and 1 here if you have already decided
these places have special meanings.

> +	nr_memregions = 2;
> +}
> +

this is an allocator of sorts, essentially, right?  It would be most
helpful to document this seemingly very important function.

> +struct memregion *memregion_new(phys_addr_t size)
> +{
> +	phys_addr_t freemem_start, freemem_size, mem_end;
> +	struct memregion *m;
> +
> +	spin_lock(&memregion_lock);
> +
> +	assert(memregions[nr_memregions-1].free);
> +	assert(memregions[nr_memregions-1].size >= size);
> +
> +	mem_end = memregions[nr_memregions-1].addr
> +		+ memregions[nr_memregions-1].size;
> +
> +	freemem_start = PAGE_ALIGN(memregions[nr_memregions-1].addr + size);
> +	freemem_size = mem_end - freemem_start;
> +
> +	memregions[nr_memregions-1].size = freemem_start
> +					 - memregions[nr_memregions-1].addr;
> +	memregions[nr_memregions-1].free = false;
> +
> +	m = &memregions[nr_memregions-1];
> +
> +	if (nr_memregions < NR_MEMREGIONS) {
> +		memregions[nr_memregions].addr = freemem_start;
> +		memregions[nr_memregions].size = freemem_size;
> +		memregions[nr_memregions].free = true;
> +		++nr_memregions;
> +	}
> +
> +	spin_unlock(&memregion_lock);
> +
> +	return m;
> +}
> +
> +void memregions_show(void)
> +{
> +	int i;
> +	for (i = 0; i < nr_memregions; ++i)
> +		printf("%016llx-%016llx [%s]\n",
> +			memregions[i].addr,
> +			memregions[i].addr + memregions[i].size - 1,
> +			memregions[i].free ? "FREE" : "USED");
> +}
> +
> +void setup(unsigned long arg __unused, unsigned long id __unused,
> +	   const void *fdt)
> +{
> +	const char *bootargs;
> +	u32 fdt_size;
> +
> +	/*
> +	 * Move the fdt to just above the stack. The free memory
> +	 * then starts just after the fdt.
> +	 */
> +	fdt_size = fdt_totalsize(fdt);
> +	assert(fdt_move(fdt, &stacktop, fdt_size) == 0);
> +	assert(dt_init(&stacktop) == 0);
> +
> +	memregions_init((unsigned long)&stacktop + fdt_size);
> +
> +	io_init();
> +	cpu_init();
> +
> +	assert(dt_get_bootargs(&bootargs) == 0);
> +	setup_args(bootargs);
> +}
> -- 
> 1.8.1.4
> 

Thanks,
-Christoffer

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 18/19] arm: add useful headers from the Linux kernel
  2014-04-10 16:56 ` [PATCH v4 18/19] arm: add useful headers from the Linux kernel Andrew Jones
@ 2014-06-06 18:40   ` Christoffer Dall
  0 siblings, 0 replies; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:40 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:56:59PM +0200, Andrew Jones wrote:
> We're going to need PSR bit defines and pt_regs. We'll also need
> pt_regs offsets in assembly code. This patch adapts the Linux
> kernel's ptrace.h and generated/asm-offsets.h to this framework.
> It also adapts cp15.h from the kernel, since we'll need bit defines
> from there too.
> 
> Signed-off-by: Andrew Jones <drjones@redhat.com>
> ---
> v4: much improved asm-offsets.h generation based on Kbuild

Wonderful!

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 19/19] arm: vectors support
  2014-04-10 16:57 ` [PATCH v4 19/19] arm: vectors support Andrew Jones
@ 2014-06-06 18:40   ` Christoffer Dall
  0 siblings, 0 replies; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:40 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:57:00PM +0200, Andrew Jones wrote:
> Add support for tests to use exception handlers using
> install_exception_handler(). This patch also adds phys_start_usr(),
> which can be used to start a function in USR mode, using a stack
> set up in a new memregion. phys_start_usr() is used by new selftest
> tests that check the new vector support.
> 
> Signed-off-by: Andrew Jones <drjones@redhat.com>
> ---
> v4: a couple tweaks to fit changes in the other patches,
>     vectors-usr test now has an 8K usr stack

would have appreciated something more concrete than 'a couple tweaks' in
a 600+ lines patch.

But it's looking good:
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 00/19] kvm-unit-tests/arm: initial drop
  2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
                   ` (18 preceding siblings ...)
       [not found] ` <1397149020-3501-7-git-send-email-drjones@redhat.com>
@ 2014-06-06 18:41 ` Christoffer Dall
  2014-06-09  9:51   ` Andrew Jones
  19 siblings, 1 reply; 54+ messages in thread
From: Christoffer Dall @ 2014-06-06 18:41 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Thu, Apr 10, 2014 at 06:56:41PM +0200, Andrew Jones wrote:
> This is a v4 of a series that introduces arm to kvm-unit-tests. First,
> it does some tidying up of the repo. Then, it adds support for device
> trees (libfdt), and for virtio-testdev[1]. Next, it adds the basic
> infrastructure for booting a test case (guest), and adds a first
> test case, a self-test to confirm setup was completed successfully.
> Finally, it further prepares the framework for more complicated tests
> by adding vector support, and extends the self-test to test that too.
> 
> This initial drop doesn't require kvmarm. qemu-system-arm is enough,
> but it must have mach-virt, and the virtio-testdev patch[1].
> 

This is overall looking really good!

I only had a few comments and questions, but you should be able to sort
that out quickly.

It's a lot of code and growing for every iteration, and this time it was
a long gap since the last review, so it took me a while.

I think it would be great if you can address my comments quickly and we
can this merged without futher churn and let new functionality come as
separate extra patches afterwards.

Thanks,
-Christoffer

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 01/19] remove unused files
  2014-06-06 18:37   ` Christoffer Dall
@ 2014-06-09  8:11     ` Andrew Jones
  2014-06-25 12:14       ` Alexander Graf
  0 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-06-09  8:11 UTC (permalink / raw)
  To: Christoffer Dall; +Cc: kvmarm, kvm, agraf, pbonzini

On Fri, Jun 06, 2014 at 08:37:26PM +0200, Christoffer Dall wrote:
> On Thu, Apr 10, 2014 at 06:56:42PM +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>
> 
> Sounds reasonable enough for me, but you probably want an acked-by from
> the people who actually know if they should care about these files or
> not.

Agreed. Alex? Paolo?

> 
> In any case:
> 
> Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

Thanks!

drew

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 10/19] Introduce asm-generic/*.h files
  2014-06-06 18:39   ` Christoffer Dall
@ 2014-06-09  8:23     ` Andrew Jones
  2014-06-09  9:08       ` Christoffer Dall
  0 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-06-09  8:23 UTC (permalink / raw)
  To: Christoffer Dall; +Cc: kvmarm, kvm

On Fri, Jun 06, 2014 at 08:39:09PM +0200, Christoffer Dall wrote:
> On Thu, Apr 10, 2014 at 06:56:51PM +0200, Andrew Jones wrote:
> > Architecture neutral code may need to call low-level io accessors,
> > or use spinlocks. Create a generic io.h to ensure those accessors
> > are defined, and a generic spinlock.h that complains when included,
> > as we can't write a generic spinlock. These files can be overridden
> > or extended by architecture specific versions placed in
> > lib/$ARCH/asm/.
> > 
> > Signed-off-by: Andrew Jones <drjones@redhat.com>
> > ---
> > v4: introduce lib/asm symlink to get rid of #ifdef __arm__,
> >     add spinlock.h too
> > v3: wrt to io.h (was libio.[ch]) only
> >     - get rid of CONFIG_64BIT, replace with asserts
> >     - get rid of {read,write}_len() [libio.c]
> >     - fix bad *64_to_cpu macros
> > ---
> >  .gitignore                 |   1 +
> >  Makefile                   |   6 +-
> >  configure                  |  11 ++++
> >  lib/asm-generic/io.h       | 154 +++++++++++++++++++++++++++++++++++++++++++++
> >  lib/asm-generic/spinlock.h |   4 ++
> >  5 files changed, 173 insertions(+), 3 deletions(-)
> >  create mode 100644 lib/asm-generic/io.h
> >  create mode 100644 lib/asm-generic/spinlock.h
> > 
> > diff --git a/.gitignore b/.gitignore
> > index 775d0dfd8263e..e21939a8771e9 100644
> > --- a/.gitignore
> > +++ b/.gitignore
> > @@ -9,6 +9,7 @@ patches
> >  .stgit-*
> >  cscope.*
> >  *.swp
> > +/lib/asm
> >  /config.mak
> >  /*-run
> >  /test.log
> > diff --git a/Makefile b/Makefile
> > index fba58e36f272f..51cacdac00615 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -76,11 +76,11 @@ libfdt_clean:
> >  	$(LIBFDT_objdir)/.*.d
> >  
> >  distclean: clean libfdt_clean
> > -	$(RM) config.mak $(TEST_DIR)-run test.log msr.out cscope.*
> > +	$(RM) lib/asm config.mak $(TEST_DIR)-run test.log msr.out cscope.*
> >  
> > -cscope: common_dirs = lib lib/libfdt
> > +cscope: common_dirs = lib lib/libfdt lib/asm lib/asm-generic
> >  cscope:
> >  	$(RM) ./cscope.*
> > -	find $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
> > +	find -L $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
> >  		-name '*.[chsS]' -print | sed 's,^\./,,' > ./cscope.files
> >  	cscope -bk
> > diff --git a/configure b/configure
> > index 6cfc64943f6e6..8a81bf92e27b7 100755
> > --- a/configure
> > +++ b/configure
> > @@ -95,6 +95,17 @@ if [ $exit -eq 0 ]; then
> >  fi
> >  rm -f lib_test.c
> >  
> > +# link lib/asm for the architecture
> > +rm -f lib/asm
> > +asm=asm-generic
> > +if [ -d lib/$arch/asm ]; then
> > +	asm=$arch/asm
> > +elif [ -d lib/$testdir/asm ]; then
> > +	asm=$testdir/asm
> 
> why do you need this elif?  can you not make sure arch is always set?

arch is always set, but there's a chance some arch may not add it's own
lib/$arch dir. It's a pretty small chance... but the elif shouldn't hurt.

drew

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 11/19] add minimal virtio support for devtree virtio-mmio
  2014-06-06 18:39   ` Christoffer Dall
@ 2014-06-09  9:02     ` Andrew Jones
  2014-06-09  9:14       ` Christoffer Dall
  0 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-06-09  9:02 UTC (permalink / raw)
  To: Christoffer Dall; +Cc: kvmarm, kvm

On Fri, Jun 06, 2014 at 08:39:18PM +0200, Christoffer Dall wrote:
> On Thu, Apr 10, 2014 at 06:56:52PM +0200, Andrew Jones wrote:
> > Support the bare minimum of virtio to enable access to the virtio-mmio
> > config space of a device. Currently this implementation must use a
> > device tree to find the device.
> > 
> > Signed-off-by: Andrew Jones <drjones@redhat.com>
> > ---
> > v4:
> >  - split from the virtio-testdev patch
> >  - search a table to "discover" that the device must be DT/virtio-mmio,
> >    which doesn't change anything, but looks less hacky than comments
> >    saying the device must be DT/virtio-mmio...
> >  - manage own pool of virtio-mmio pre-allocated device structures in
> >    order to avoid needing access to the heap
> > ---
> >  lib/libcflat.h |   3 ++
> >  lib/virtio.c   | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  lib/virtio.h   |  89 +++++++++++++++++++++++++++++++
> >  3 files changed, 258 insertions(+)
> >  create mode 100644 lib/virtio.c
> >  create mode 100644 lib/virtio.h
> > 
> > diff --git a/lib/libcflat.h b/lib/libcflat.h
> > index c7c31be1cc8e5..5bb66d01dfc53 100644
> > --- a/lib/libcflat.h
> > +++ b/lib/libcflat.h
> > @@ -62,6 +62,9 @@ extern long atol(const char *ptr);
> >  #define ARRAY_SIZE(_a)  (sizeof(_a)/sizeof((_a)[0]))
> >  
> >  #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
> > +#define container_of(ptr, type, member) ({				\
> > +	const typeof( ((type *)0)->member ) *__mptr = (ptr);		\
> > +	(type *)( (char *)__mptr - offsetof(type,member) );})
> >  
> >  #define NULL ((void *)0UL)
> >  
> > diff --git a/lib/virtio.c b/lib/virtio.c
> > new file mode 100644
> > index 0000000000000..e7161ff591e4c
> > --- /dev/null
> > +++ b/lib/virtio.c
> > @@ -0,0 +1,166 @@
> > +/*
> > + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2.
> > + */
> > +#include "libcflat.h"
> > +#include "devicetree.h"
> > +#include "asm/spinlock.h"
> > +#include "asm/io.h"
> > +#include "virtio.h"
> > +
> > +enum virtio_hwdesc_type {
> > +	VIRTIO_HWDESC_TYPE_DT = 0,	/* device tree */
> > +	NR_VIRTIO_HWDESC_TYPES,
> > +};
> > +
> > +enum virtio_bus_type {
> > +	VIRTIO_BUS_TYPE_MMIO = 0,	/* virtio-mmio */
> > +	NR_VIRTIO_BUS_TYPES,
> > +};
> > +
> > +struct virtio_bind_bus {
> > +	bool (*hwdesc_probe)(void);
> > +	struct virtio_dev *(*device_bind)(u32 devid);
> > +};
> > +
> > +static struct virtio_dev *vm_dt_device_bind(u32 devid);
> > +
> > +static struct virtio_bind_bus
> > +virtio_bind_busses[NR_VIRTIO_HWDESC_TYPES][NR_VIRTIO_BUS_TYPES] = {
> > +
> > +[VIRTIO_HWDESC_TYPE_DT] = {
> > +
> > +	[VIRTIO_BUS_TYPE_MMIO] = {
> > +		.hwdesc_probe = dt_available,
> > +		.device_bind = vm_dt_device_bind,
> > +	},
> > +},
> > +};
> > +
> > +struct virtio_dev *virtio_bind(u32 devid)
> > +{
> > +	struct virtio_bind_bus *bus;
> > +	struct virtio_dev *dev;
> > +	int i, j;
> > +
> > +	for (i = 0; i < NR_VIRTIO_HWDESC_TYPES; ++i) {
> > +		for (j = 0; j < NR_VIRTIO_BUS_TYPES; ++j) {
> > +
> > +			bus = &virtio_bind_busses[i][j];
> > +
> > +			if (!bus->hwdesc_probe())
> > +				continue;
> > +
> > +			dev = bus->device_bind(devid);
> > +			if (dev)
> > +				return dev;
> > +		}
> > +	}
> > +
> > +	return NULL;
> > +}
> > +
> > +/******************************************************
> > + * virtio-mmio support (config space only)
> > + ******************************************************/
> > +
> > +static void vm_get(struct virtio_dev *vdev, unsigned offset,
> > +		   void *buf, unsigned len)
> > +{
> > +	struct virtio_mmio_dev *vmdev = to_virtio_mmio_dev(vdev);
> > +	u8 *p = buf;
> > +	unsigned i;
> > +
> > +	for (i = 0; i < len; ++i)
> > +		p[i] = readb(vmdev->base + VIRTIO_MMIO_CONFIG + offset + i);
> > +}
> > +
> > +static void vm_set(struct virtio_dev *vdev, unsigned offset,
> > +		   const void *buf, unsigned len)
> > +{
> > +	struct virtio_mmio_dev *vmdev = to_virtio_mmio_dev(vdev);
> > +	const u8 *p = buf;
> > +	unsigned i;
> > +
> > +	for (i = 0; i < len; ++i)
> > +		writeb(p[i], vmdev->base + VIRTIO_MMIO_CONFIG + offset + i);
> > +}
> > +
> > +#define NR_VM_DEVICES 32
> > +static struct spinlock vm_lock;
> > +static struct virtio_mmio_dev vm_devs[NR_VM_DEVICES];
> > +static struct virtio_conf_ops vm_confs[NR_VM_DEVICES];
> > +static int nr_vm_devs;
> > +
> > +static struct virtio_mmio_dev *vm_new_device(u32 devid)
> > +{
> > +	struct virtio_mmio_dev *vmdev;
> > +
> > +	if (nr_vm_devs >= NR_VM_DEVICES)
> > +		return NULL;
> > +
> > +	spin_lock(&vm_lock);
> > +	vmdev = &vm_devs[nr_vm_devs];
> > +	vmdev->vdev.config = &vm_confs[nr_vm_devs];
> 
> this seems a bit weird, will we ever share vm_confs between vm_devs or
> change the vm_conf pointer later on?  Could vm_conf just be part of the
> vm_dev struct and you could just have a virtio_mmio_conf_init() to set
> the get/set functions?

I can do that, but it'll require a typedef for struct virtio_dev to
appease the compiler.

> 
> > +	++nr_vm_devs;
> > +	spin_unlock(&vm_lock);
> > +
> > +	vmdev->vdev.id.device = devid;
> > +	vmdev->vdev.id.vendor = -1;
> > +	vmdev->vdev.config->get = vm_get;
> > +	vmdev->vdev.config->set = vm_set;
> > +
> > +	return vmdev;
> > +}
> > +
> > +/******************************************************
> > + * virtio-mmio device tree support
> > + ******************************************************/
> > +
> > +struct vm_dt_info {
> > +	u32 devid;
> > +	void *base;
> 
> won't work for LPAE and 32-bit arm systems, can't you use
> dt_device_bind_node?
> 
> I guess that requires you to have an ioremap function, but it sure seems
> cleaner to give up there if you don't have proper memory mapping
> features yet....

Right. I was just skipping past that complexity for now, as mach-virt's
DT is currently "nice" (32-bit only addrs). I agree we need to handle
LPAE addrs on arm eventually though.

> 
> > +};
> > +
> > +static int vm_dt_match(const struct dt_device *dev, int fdtnode)
> > +{
> > +	struct vm_dt_info *info = (struct vm_dt_info *)dev->info;
> > +	dt_pbus_addr_t base;
> > +
> > +	dt_device_bind_node((struct dt_device *)dev, fdtnode);
> > +
> > +	assert(dt_pbus_get_baseaddr(dev, &base) == 0);
> > +	assert(sizeof(long) == 8 || !(base >> 32));
> 
> again, this assert will break with >32bit LPAE addresses on 32-bit arm systems.
> 
> so, not sure if it's an assert, or if you should test for it and print
> a more benign error for these types of devices.

It's supposed to be a crash-and-burn assert, but a message stating
something like >32-bit addrs on arm is not yet supported would certainly be
nicer. Of course that message would only make it out at this point if our uart
address guess is correct.

> 
> > +
> > +	info->base = (void *)(unsigned long)base;
> 
> why do you need to cast it twice?

Same as above (as we still don't support >32-bit addrs on arm). This keeps
the compiler from complaining when casting a dt_pbus_addr_t (u64) to void*
on 32-bit.

> 
> > +
> > +	return readl(info->base + VIRTIO_MMIO_DEVICE_ID) == info->devid;
> > +}
> > +
> > +static struct virtio_dev *vm_dt_device_bind(u32 devid)
> > +{
> > +	struct virtio_mmio_dev *vmdev;
> > +	struct dt_device dt_dev;
> > +	struct dt_bus dt_bus;
> > +	struct vm_dt_info info;
> > +	int node;
> > +
> > +	dt_bus_init_defaults(&dt_bus);
> > +	dt_bus.match = vm_dt_match;
> > +
> > +	info.devid = devid;
> > +
> > +	dt_device_init(&dt_dev, &dt_bus, &info);
> > +
> > +	node = dt_device_find_compatible(&dt_dev, "virtio,mmio");
> > +	assert(node >= 0 || node == -FDT_ERR_NOTFOUND);
> > +
> > +	if (node == -FDT_ERR_NOTFOUND)
> > +		return NULL;
> > +
> > +	vmdev = vm_new_device(devid);
> > +	vmdev->base = info.base;
> > +
> > +	return &vmdev->vdev;
> > +}
> > diff --git a/lib/virtio.h b/lib/virtio.h
> > new file mode 100644
> > index 0000000000000..163b9912c4e05
> > --- /dev/null
> > +++ b/lib/virtio.h
> > @@ -0,0 +1,89 @@
> > +#ifndef _VIRTIO_H_
> > +#define _VIRTIO_H_
> > +/*
> > + * A minimal implementation of virtio for virtio-mmio config space
> > + * access.
> > + *
> > + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2.
> > + */
> > +#include "libcflat.h"
> > +
> > +struct virtio_devid {
> > +	u32 device;
> > +	u32 vendor;
> > +};
> > +
> > +struct virtio_dev {
> > +	struct virtio_devid id;
> > +	struct virtio_conf_ops *config;
> > +};
> > +
> > +struct virtio_conf_ops {
> > +	void (*get)(struct virtio_dev *vdev, unsigned offset,
> > +		    void *buf, unsigned len);
> > +	void (*set)(struct virtio_dev *vdev, unsigned offset,
> > +		    const void *buf, unsigned len);
> > +};
> > +
> > +extern struct virtio_dev *virtio_bind(u32 devid);
> > +
> > +static inline u8
> > +virtio_config_readb(struct virtio_dev *vdev, unsigned offset)
> > +{
> > +	u8 val;
> > +	vdev->config->get(vdev, offset, &val, 1);
> > +	return val;
> > +}
> > +
> > +static inline u16
> > +virtio_config_readw(struct virtio_dev *vdev, unsigned offset)
> > +{
> > +	u16 val;
> > +	vdev->config->get(vdev, offset, &val, 2);
> > +	return val;
> > +}
> > +
> > +static inline u32
> > +virtio_config_readl(struct virtio_dev *vdev, unsigned offset)
> > +{
> > +	u32 val;
> > +	vdev->config->get(vdev, offset, &val, 4);
> > +	return val;
> > +}
> > +
> > +static inline void
> > +virtio_config_writeb(struct virtio_dev *vdev, unsigned offset, u8 val)
> > +{
> > +	vdev->config->set(vdev, offset, &val, 1);
> > +}
> > +
> > +static inline void
> > +virtio_config_writew(struct virtio_dev *vdev, unsigned offset, u16 val)
> > +{
> > +	vdev->config->set(vdev, offset, &val, 2);
> > +}
> > +
> > +static inline void
> > +virtio_config_writel(struct virtio_dev *vdev, unsigned offset, u32 val)
> > +{
> > +	vdev->config->set(vdev, offset, &val, 4);
> > +}
> > +
> > +/******************************************************
> > + * virtio-mmio
> > + ******************************************************/
> > +
> > +#define VIRTIO_MMIO_DEVICE_ID	0x008
> > +#define VIRTIO_MMIO_CONFIG	0x100
> > +
> > +#define to_virtio_mmio_dev(vdev_ptr) \
> > +	container_of(vdev_ptr, struct virtio_mmio_dev, vdev)
> > +
> > +struct virtio_mmio_dev {
> > +	struct virtio_dev vdev;
> > +	void *base;
> > +};
> > +
> > +#endif /* _VIRTIO_H_ */
> > -- 
> > 1.8.1.4
> > 
> 
> -Christoffer

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 10/19] Introduce asm-generic/*.h files
  2014-06-09  8:23     ` Andrew Jones
@ 2014-06-09  9:08       ` Christoffer Dall
  2014-06-09  9:54         ` Andrew Jones
  0 siblings, 1 reply; 54+ messages in thread
From: Christoffer Dall @ 2014-06-09  9:08 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Mon, Jun 09, 2014 at 10:23:27AM +0200, Andrew Jones wrote:
> On Fri, Jun 06, 2014 at 08:39:09PM +0200, Christoffer Dall wrote:
> > On Thu, Apr 10, 2014 at 06:56:51PM +0200, Andrew Jones wrote:
> > > Architecture neutral code may need to call low-level io accessors,
> > > or use spinlocks. Create a generic io.h to ensure those accessors
> > > are defined, and a generic spinlock.h that complains when included,
> > > as we can't write a generic spinlock. These files can be overridden
> > > or extended by architecture specific versions placed in
> > > lib/$ARCH/asm/.
> > > 
> > > Signed-off-by: Andrew Jones <drjones@redhat.com>
> > > ---
> > > v4: introduce lib/asm symlink to get rid of #ifdef __arm__,
> > >     add spinlock.h too
> > > v3: wrt to io.h (was libio.[ch]) only
> > >     - get rid of CONFIG_64BIT, replace with asserts
> > >     - get rid of {read,write}_len() [libio.c]
> > >     - fix bad *64_to_cpu macros
> > > ---
> > >  .gitignore                 |   1 +
> > >  Makefile                   |   6 +-
> > >  configure                  |  11 ++++
> > >  lib/asm-generic/io.h       | 154 +++++++++++++++++++++++++++++++++++++++++++++
> > >  lib/asm-generic/spinlock.h |   4 ++
> > >  5 files changed, 173 insertions(+), 3 deletions(-)
> > >  create mode 100644 lib/asm-generic/io.h
> > >  create mode 100644 lib/asm-generic/spinlock.h
> > > 
> > > diff --git a/.gitignore b/.gitignore
> > > index 775d0dfd8263e..e21939a8771e9 100644
> > > --- a/.gitignore
> > > +++ b/.gitignore
> > > @@ -9,6 +9,7 @@ patches
> > >  .stgit-*
> > >  cscope.*
> > >  *.swp
> > > +/lib/asm
> > >  /config.mak
> > >  /*-run
> > >  /test.log
> > > diff --git a/Makefile b/Makefile
> > > index fba58e36f272f..51cacdac00615 100644
> > > --- a/Makefile
> > > +++ b/Makefile
> > > @@ -76,11 +76,11 @@ libfdt_clean:
> > >  	$(LIBFDT_objdir)/.*.d
> > >  
> > >  distclean: clean libfdt_clean
> > > -	$(RM) config.mak $(TEST_DIR)-run test.log msr.out cscope.*
> > > +	$(RM) lib/asm config.mak $(TEST_DIR)-run test.log msr.out cscope.*
> > >  
> > > -cscope: common_dirs = lib lib/libfdt
> > > +cscope: common_dirs = lib lib/libfdt lib/asm lib/asm-generic
> > >  cscope:
> > >  	$(RM) ./cscope.*
> > > -	find $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
> > > +	find -L $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
> > >  		-name '*.[chsS]' -print | sed 's,^\./,,' > ./cscope.files
> > >  	cscope -bk
> > > diff --git a/configure b/configure
> > > index 6cfc64943f6e6..8a81bf92e27b7 100755
> > > --- a/configure
> > > +++ b/configure
> > > @@ -95,6 +95,17 @@ if [ $exit -eq 0 ]; then
> > >  fi
> > >  rm -f lib_test.c
> > >  
> > > +# link lib/asm for the architecture
> > > +rm -f lib/asm
> > > +asm=asm-generic
> > > +if [ -d lib/$arch/asm ]; then
> > > +	asm=$arch/asm
> > > +elif [ -d lib/$testdir/asm ]; then
> > > +	asm=$testdir/asm
> > 
> > why do you need this elif?  can you not make sure arch is always set?
> 
> arch is always set, but there's a chance some arch may not add it's own
> lib/$arch dir. It's a pretty small chance... but the elif shouldn't hurt.
> 
If we don't have any code that uses this scheme now then let's now have
Makefile rules that encourages non-standard behavior (unless I'm missing
the point and this provides a 'feature' for specific archs or something
like that).

-Christoffer

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 11/19] add minimal virtio support for devtree virtio-mmio
  2014-06-09  9:02     ` Andrew Jones
@ 2014-06-09  9:14       ` Christoffer Dall
  2014-06-09 10:21         ` Andrew Jones
  0 siblings, 1 reply; 54+ messages in thread
From: Christoffer Dall @ 2014-06-09  9:14 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Mon, Jun 09, 2014 at 11:02:57AM +0200, Andrew Jones wrote:
> On Fri, Jun 06, 2014 at 08:39:18PM +0200, Christoffer Dall wrote:
> > On Thu, Apr 10, 2014 at 06:56:52PM +0200, Andrew Jones wrote:
> > > Support the bare minimum of virtio to enable access to the virtio-mmio
> > > config space of a device. Currently this implementation must use a
> > > device tree to find the device.
> > > 
> > > Signed-off-by: Andrew Jones <drjones@redhat.com>
> > > ---
> > > v4:
> > >  - split from the virtio-testdev patch
> > >  - search a table to "discover" that the device must be DT/virtio-mmio,
> > >    which doesn't change anything, but looks less hacky than comments
> > >    saying the device must be DT/virtio-mmio...
> > >  - manage own pool of virtio-mmio pre-allocated device structures in
> > >    order to avoid needing access to the heap
> > > ---
> > >  lib/libcflat.h |   3 ++
> > >  lib/virtio.c   | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >  lib/virtio.h   |  89 +++++++++++++++++++++++++++++++
> > >  3 files changed, 258 insertions(+)
> > >  create mode 100644 lib/virtio.c
> > >  create mode 100644 lib/virtio.h
> > > 
> > > diff --git a/lib/libcflat.h b/lib/libcflat.h
> > > index c7c31be1cc8e5..5bb66d01dfc53 100644
> > > --- a/lib/libcflat.h
> > > +++ b/lib/libcflat.h
> > > @@ -62,6 +62,9 @@ extern long atol(const char *ptr);
> > >  #define ARRAY_SIZE(_a)  (sizeof(_a)/sizeof((_a)[0]))
> > >  
> > >  #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
> > > +#define container_of(ptr, type, member) ({				\
> > > +	const typeof( ((type *)0)->member ) *__mptr = (ptr);		\
> > > +	(type *)( (char *)__mptr - offsetof(type,member) );})
> > >  
> > >  #define NULL ((void *)0UL)
> > >  
> > > diff --git a/lib/virtio.c b/lib/virtio.c
> > > new file mode 100644
> > > index 0000000000000..e7161ff591e4c
> > > --- /dev/null
> > > +++ b/lib/virtio.c
> > > @@ -0,0 +1,166 @@
> > > +/*
> > > + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> > > + *
> > > + * This work is licensed under the terms of the GNU LGPL, version 2.
> > > + */
> > > +#include "libcflat.h"
> > > +#include "devicetree.h"
> > > +#include "asm/spinlock.h"
> > > +#include "asm/io.h"
> > > +#include "virtio.h"
> > > +
> > > +enum virtio_hwdesc_type {
> > > +	VIRTIO_HWDESC_TYPE_DT = 0,	/* device tree */
> > > +	NR_VIRTIO_HWDESC_TYPES,
> > > +};
> > > +
> > > +enum virtio_bus_type {
> > > +	VIRTIO_BUS_TYPE_MMIO = 0,	/* virtio-mmio */
> > > +	NR_VIRTIO_BUS_TYPES,
> > > +};
> > > +
> > > +struct virtio_bind_bus {
> > > +	bool (*hwdesc_probe)(void);
> > > +	struct virtio_dev *(*device_bind)(u32 devid);
> > > +};
> > > +
> > > +static struct virtio_dev *vm_dt_device_bind(u32 devid);
> > > +
> > > +static struct virtio_bind_bus
> > > +virtio_bind_busses[NR_VIRTIO_HWDESC_TYPES][NR_VIRTIO_BUS_TYPES] = {
> > > +
> > > +[VIRTIO_HWDESC_TYPE_DT] = {
> > > +
> > > +	[VIRTIO_BUS_TYPE_MMIO] = {
> > > +		.hwdesc_probe = dt_available,
> > > +		.device_bind = vm_dt_device_bind,
> > > +	},
> > > +},
> > > +};
> > > +
> > > +struct virtio_dev *virtio_bind(u32 devid)
> > > +{
> > > +	struct virtio_bind_bus *bus;
> > > +	struct virtio_dev *dev;
> > > +	int i, j;
> > > +
> > > +	for (i = 0; i < NR_VIRTIO_HWDESC_TYPES; ++i) {
> > > +		for (j = 0; j < NR_VIRTIO_BUS_TYPES; ++j) {
> > > +
> > > +			bus = &virtio_bind_busses[i][j];
> > > +
> > > +			if (!bus->hwdesc_probe())
> > > +				continue;
> > > +
> > > +			dev = bus->device_bind(devid);
> > > +			if (dev)
> > > +				return dev;
> > > +		}
> > > +	}
> > > +
> > > +	return NULL;
> > > +}
> > > +
> > > +/******************************************************
> > > + * virtio-mmio support (config space only)
> > > + ******************************************************/
> > > +
> > > +static void vm_get(struct virtio_dev *vdev, unsigned offset,
> > > +		   void *buf, unsigned len)
> > > +{
> > > +	struct virtio_mmio_dev *vmdev = to_virtio_mmio_dev(vdev);
> > > +	u8 *p = buf;
> > > +	unsigned i;
> > > +
> > > +	for (i = 0; i < len; ++i)
> > > +		p[i] = readb(vmdev->base + VIRTIO_MMIO_CONFIG + offset + i);
> > > +}
> > > +
> > > +static void vm_set(struct virtio_dev *vdev, unsigned offset,
> > > +		   const void *buf, unsigned len)
> > > +{
> > > +	struct virtio_mmio_dev *vmdev = to_virtio_mmio_dev(vdev);
> > > +	const u8 *p = buf;
> > > +	unsigned i;
> > > +
> > > +	for (i = 0; i < len; ++i)
> > > +		writeb(p[i], vmdev->base + VIRTIO_MMIO_CONFIG + offset + i);
> > > +}
> > > +
> > > +#define NR_VM_DEVICES 32
> > > +static struct spinlock vm_lock;
> > > +static struct virtio_mmio_dev vm_devs[NR_VM_DEVICES];
> > > +static struct virtio_conf_ops vm_confs[NR_VM_DEVICES];
> > > +static int nr_vm_devs;
> > > +
> > > +static struct virtio_mmio_dev *vm_new_device(u32 devid)
> > > +{
> > > +	struct virtio_mmio_dev *vmdev;
> > > +
> > > +	if (nr_vm_devs >= NR_VM_DEVICES)
> > > +		return NULL;
> > > +
> > > +	spin_lock(&vm_lock);
> > > +	vmdev = &vm_devs[nr_vm_devs];
> > > +	vmdev->vdev.config = &vm_confs[nr_vm_devs];
> > 
> > this seems a bit weird, will we ever share vm_confs between vm_devs or
> > change the vm_conf pointer later on?  Could vm_conf just be part of the
> > vm_dev struct and you could just have a virtio_mmio_conf_init() to set
> > the get/set functions?
> 
> I can do that, but it'll require a typedef for struct virtio_dev to
> appease the compiler.
> 
> > 
> > > +	++nr_vm_devs;
> > > +	spin_unlock(&vm_lock);
> > > +
> > > +	vmdev->vdev.id.device = devid;
> > > +	vmdev->vdev.id.vendor = -1;
> > > +	vmdev->vdev.config->get = vm_get;
> > > +	vmdev->vdev.config->set = vm_set;
> > > +
> > > +	return vmdev;
> > > +}
> > > +
> > > +/******************************************************
> > > + * virtio-mmio device tree support
> > > + ******************************************************/
> > > +
> > > +struct vm_dt_info {
> > > +	u32 devid;
> > > +	void *base;
> > 
> > won't work for LPAE and 32-bit arm systems, can't you use
> > dt_device_bind_node?
> > 
> > I guess that requires you to have an ioremap function, but it sure seems
> > cleaner to give up there if you don't have proper memory mapping
> > features yet....
> 
> Right. I was just skipping past that complexity for now, as mach-virt's
> DT is currently "nice" (32-bit only addrs). I agree we need to handle
> LPAE addrs on arm eventually though.
> 

So I think the tradeoff here is very small, it's super easy to fix it so
you can support physical addresses > 32 bits in this part of the code.
The difficult thing comes when you start dereferencing them, but since
we may add virtual addresses at some point too, I really think adding a
trivial ioremap function and start using that will make our lives much
easier down the line:

/* We don't support virtual addresses yet, trivial identity implementation */
void __iomem *ioremap(phys_addr_t phys_addr)
{
	assert(sizeof(long) == 8 || !(base >> 32));
	return (void *)(unsigned long)phys_addr;
}

But I can submit that patch after this code goes in if you think it's
too much of a headache at this point?

Thanks,
-Christoffer

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 15/19] arm: initial drop
  2014-06-06 18:39   ` Christoffer Dall
@ 2014-06-09  9:44     ` Andrew Jones
  0 siblings, 0 replies; 54+ messages in thread
From: Andrew Jones @ 2014-06-09  9:44 UTC (permalink / raw)
  To: Christoffer Dall; +Cc: kvmarm, kvm

On Fri, Jun 06, 2014 at 08:39:50PM +0200, Christoffer Dall wrote:
> On Thu, Apr 10, 2014 at 06:56:56PM +0200, Andrew Jones wrote:
> > This is the initial drop of the arm test framework and a first test
> > that just checks that setup completed (a selftest). kvm isn't needed
> > to run this test unless testing with smp > 1.
> > 
> > Try it out with
> >   yum install gcc-arm-linux-gnu
> >   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>
> > ---
> > v4:
> >   - moved fdt to just after stacktop (it was in the middle of free memory)
> >   - switched from using heap to memregions
> >   - get nr_cpus and added smp=<num> test
> >   - added barrier.h
> >   - use new report()/report_summary()
> >   - config/config-arm.mak cleanup
> > ---
> >  arm/cstart.S           |  35 ++++++++++++
> >  arm/flat.lds           |  18 +++++++
> >  arm/run                |  31 +++++++++++
> >  arm/selftest.c         |  87 ++++++++++++++++++++++++++++++
> >  arm/unittests.cfg      |  18 +++++++
> >  config/config-arm.mak  |  72 +++++++++++++++++++++++++
> >  configure              |  12 ++++-
> >  lib/argv.c             |   6 +++
> >  lib/arm/asm/barrier.h  |  18 +++++++
> >  lib/arm/asm/io.h       |  24 +++++++++
> >  lib/arm/asm/setup.h    |  39 ++++++++++++++
> >  lib/arm/asm/spinlock.h |  16 ++++++
> >  lib/arm/eabi_compat.c  |  20 +++++++
> >  lib/arm/io.c           |  66 +++++++++++++++++++++++
> >  lib/arm/setup.c        | 142 +++++++++++++++++++++++++++++++++++++++++++++++++
> >  15 files changed, 602 insertions(+), 2 deletions(-)
> >  create mode 100644 arm/cstart.S
> >  create mode 100644 arm/flat.lds
> >  create mode 100755 arm/run
> >  create mode 100644 arm/selftest.c
> >  create mode 100644 arm/unittests.cfg
> >  create mode 100644 config/config-arm.mak
> >  create mode 100644 lib/arm/asm/barrier.h
> >  create mode 100644 lib/arm/asm/io.h
> >  create mode 100644 lib/arm/asm/setup.h
> >  create mode 100644 lib/arm/asm/spinlock.h
> >  create mode 100644 lib/arm/eabi_compat.c
> >  create mode 100644 lib/arm/io.c
> >  create mode 100644 lib/arm/setup.c
> > 
> > diff --git a/arm/cstart.S b/arm/cstart.S
> > new file mode 100644
> > index 0000000000000..e28251db2950d
> > --- /dev/null
> > +++ b/arm/cstart.S
> > @@ -0,0 +1,35 @@
> > +/*
> > + * Boot entry point and assembler functions for armv7 tests.
> > + *
> > + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2.
> > + */
> > +
> > +.arm
> > +
> > +.section .init
> > +
> > +.globl start
> > +start:
> > +	/*
> > +	 * bootloader params are in r0-r2
> > +	 * See the kernel doc Documentation/arm/Booting
> > +	 */
> > +	ldr	sp, =stacktop
> > +	bl	setup
> > +
> > +	/* run the test */
> > +	ldr	r0, =__argc
> > +	ldr	r0, [r0]
> > +	ldr	r1, =__argv
> > +	bl	main
> > +	bl	exit
> > +	b	halt
> > +
> > +.text
> > +
> > +.globl halt
> > +halt:
> > +1:	wfi
> > +	b	1b
> > 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..985b26e1334da
> > --- /dev/null
> > +++ b/arm/run
> > @@ -0,0 +1,31 @@
> > +#!/bin/bash
> > +
> > +if [ ! -f config.mak ]; then
> > +	echo run ./configure first. See ./configure -h
> > +	exit 2
> > +fi
> > +source config.mak
> > +
> > +qemu="${QEMU:-qemu-system-arm}"
> > +testdev=virtio-testdev
> > +
> > +if ! $qemu -device '?' 2>&1 | grep $testdev > /dev/null; then
> > +	qpath=$(which $qemu 2>/dev/null)
> > +	if [ "$qpath" ]; then
> > +		echo $qpath doesn\'t support virtio-testdev. Exiting.
> > +	else
> > +		echo $qemu not found.
> > +	fi
> > +	exit 2
> > +fi
> > +
> > +command="$qemu -device $testdev -display none -serial stdio "
> > +command+="-M virt -cpu $PROCESSOR "
> > +#command+="-enable-kvm "
> > +command+="-kernel"
> > +
> > +echo $command "$@"
> > +$command "$@"
> > +ret=$?
> > +echo Return value from qemu: $ret
> > +exit $ret
> > diff --git a/arm/selftest.c b/arm/selftest.c
> > new file mode 100644
> > index 0000000000000..45729e9ac85d9
> > --- /dev/null
> > +++ b/arm/selftest.c
> > @@ -0,0 +1,87 @@
> > +/*
> > + * Test the framework itself. These tests confirm that setup works.
> > + *
> > + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2.
> > + */
> > +#include "libcflat.h"
> > +#include "asm/setup.h"
> > +
> > +#define TESTGRP "selftest"
> > +
> > +static char testnam[64];
> 
> is testnam testname?

:-) You're not a fan of single char saving abbreviations, eh? I can
add the 'e' back.

> 
> > +
> > +static void testnam_set(const char *subtest)
> > +{
> > +	strcpy(testnam, TESTGRP);
> > +	strcat(testnam, "::");
> > +	strcat(testnam, subtest);
> > +}
> > +
> > +static void assert_args(int num_args, int needed_args)
> > +{
> > +	if (num_args < needed_args) {
> > +		printf("%s: not enough arguments\n", testnam);
> > +		abort();
> > +	}
> > +}
> > +
> > +static char *split_var(char *s, long *val)
> > +{
> > +	char *p;
> > +
> > +	p = strchr(s, '=');
> > +	if (!p)
> > +		return NULL;
> > +
> > +	*val = atol(p+1);
> > +	*p = '\0';
> > +
> > +	return s;
> > +}
> > +
> > +static void check_setup(int argc, char **argv)
> > +{
> > +	int nr_tests = 0, i;
> > +	char *var;
> > +	long val;
> > +
> > +	for (i = 0; i < argc; ++i) {
> > +
> > +		var = split_var(argv[i], &val);
> > +		if (!var)
> > +			continue;
> > +
> > +		if (strcmp(argv[i], "mem") == 0) {
> > +
> > +			phys_addr_t memsize =
> > +					memregions[nr_memregions-1].addr
> > +					+ memregions[nr_memregions-1].size
> > +					- PHYS_OFFSET;
> > +			phys_addr_t expected = ((phys_addr_t)val)*1024*1024;
> > +
> > +			report("%s[%s]", memsize == expected, testnam, "mem");
> > +			++nr_tests;
> > +
> > +		} else if (strcmp(argv[i], "smp") == 0) {
> > +
> > +			report("%s[%s]", nr_cpus == (int)val, testnam, "smp");
> > +			++nr_tests;
> > +		}
> > +	}
> > +
> > +	assert_args(nr_tests, 2);
> > +}
> > +
> > +int main(int argc, char **argv)
> > +{
> > +	assert_args(argc, 1);
> > +
> > +	testnam_set(argv[0]);
> > +
> > +	if (strcmp(argv[0], "setup") == 0)
> > +		check_setup(argc-1, &argv[1]);
> > +
> > +	return report_summary();
> > +}
> > diff --git a/arm/unittests.cfg b/arm/unittests.cfg
> > new file mode 100644
> > index 0000000000000..da9dfd7b1f118
> > --- /dev/null
> > +++ b/arm/unittests.cfg
> > @@ -0,0 +1,18 @@
> > +# 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 test case is specific to one
> > +# groups = group1 group2 # Used to identify test cases with run_tests -g ...
> > +
> > +#
> > +# Test that the configured number of processors (smp = <num>), and
> > +# that the configured amount of memory (-m <MB>) are correctly setup
> > +# by the framework.
> > +#
> > +[selftest::setup]
> > +file = selftest.flat
> > +smp  = 1
> > +extra_params = -m 256 -append 'setup smp=1 mem=256'
> > +groups = selftest
> > diff --git a/config/config-arm.mak b/config/config-arm.mak
> > new file mode 100644
> > index 0000000000000..915b1cc318d79
> > --- /dev/null
> > +++ b/config/config-arm.mak
> > @@ -0,0 +1,72 @@
> > +#
> > +# arm makefile
> > +#
> > +# Authors: Andrew Jones <drjones@redhat.com>
> > +#
> > +
> > +tests-common = \
> > +	$(TEST_DIR)/selftest.flat
> > +
> > +tests =
> > +
> > +all: test_cases
> > +
> > +##################################################################
> > +bits = 32
> > +ldarch = elf32-littlearm
> > +
> > +ifeq ($(LOADADDR),)
> > +	LOADADDR = 0x40000000
> > +endif
> > +phys_base = $(LOADADDR)
> > +kernel_offset = 0x10000
> > +
> > +CFLAGS += -D__arm__
> > +CFLAGS += -marm
> > +CFLAGS += -mcpu=$(PROCESSOR)
> > +CFLAGS += -std=gnu99
> > +CFLAGS += -ffreestanding
> > +CFLAGS += -Wextra
> > +CFLAGS += -O2
> > +CFLAGS += -I lib -I lib/libfdt
> > +
> > +cflatobjs += \
> > +	lib/devicetree.o \
> > +	lib/virtio.o \
> > +	lib/virtio-testdev.o \
> > +	lib/arm/io.o \
> > +	lib/arm/setup.o
> > +
> > +libeabi = lib/arm/libeabi.a
> > +eabiobjs = lib/arm/eabi_compat.o
> > +
> > +libgcc := $(shell $(CC) -m$(ARCH) --print-libgcc-file-name)
> > +start_addr := $(shell printf "%x\n" $$(( $(phys_base) + $(kernel_offset) )))
> > +
> > +FLATLIBS = $(libcflat) $(LIBFDT_archive) $(libgcc) $(libeabi)
> > +%.elf: LDFLAGS = $(CFLAGS) -nostdlib
> > +%.elf: %.o $(FLATLIBS) arm/flat.lds
> > +	$(CC) $(LDFLAGS) -o $@ \
> > +		-Wl,-T,arm/flat.lds,--build-id=none,-Ttext=$(start_addr) \
> > +		$(filter %.o, $^) $(FLATLIBS)
> > +
> > +%.flat: %.elf
> > +	$(OBJCOPY) -O binary $^ $@
> > +
> > +$(libeabi): $(eabiobjs)
> > +	$(AR) rcs $@ $^
> > +
> > +arch_clean: libfdt_clean
> > +	$(RM) $(TEST_DIR)/*.{o,flat,elf} $(libeabi) $(eabiobjs) \
> > +	      $(TEST_DIR)/.*.d lib/arm/.*.d
> > +
> > +##################################################################
> > +
> > +tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg
> > +
> > +cstart.o = $(TEST_DIR)/cstart.o
> > +
> > +test_cases: $(tests-common) $(tests)
> > +
> > +$(TEST_DIR)/selftest.elf: $(cstart.o) $(TEST_DIR)/selftest.o
> > +
> > diff --git a/configure b/configure
> > index 8a81bf92e27b7..f92f585724bb1 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,12 @@ while [[ "$1" = -* ]]; do
> >  	    ;;
> >      esac
> >  done
> > +[ -z "$processor" ] && processor="$arch"
> > +
> > +if [ "$processor" = "arm" ]; then
> > +    processor="cortex-a15"
> > +fi
> > +
> >  if [ -z "$testdir" -a \( "$arch" = "i386" -o "$arch" = "x86_64" \) ]; then
> >      testdir=x86
> >  elif [ -z "$testdir" ]; then
> > @@ -80,6 +86,7 @@ if [ -f $testdir/run ]; then
> >  fi
> >  
> >  # check for dependent 32 bit libraries
> > +if [ "$arch" != "arm" ]; then
> >  cat << EOF > lib_test.c
> >  #include <stdc++.h>
> >  #include <boost_thread-mt.h>
> > @@ -94,6 +101,7 @@ if [ $exit -eq 0 ]; then
> >      api=true
> >  fi
> >  rm -f lib_test.c
> > +fi
> >  
> >  # link lib/asm for the architecture
> >  rm -f lib/asm
> > diff --git a/lib/argv.c b/lib/argv.c
> > index 4ee54a6eeac3e..078a05faffebf 100644
> > --- a/lib/argv.c
> > +++ b/lib/argv.c
> > @@ -31,3 +31,9 @@ void __setup_args(void)
> >      }
> >      __argc = argv - __argv;
> >  }
> > +
> > +void setup_args(char *args)
> > +{
> > +    __args = args;
> > +    __setup_args();
> > +}
> > diff --git a/lib/arm/asm/barrier.h b/lib/arm/asm/barrier.h
> > new file mode 100644
> > index 0000000000000..acaeab5123431
> > --- /dev/null
> > +++ b/lib/arm/asm/barrier.h
> > @@ -0,0 +1,18 @@
> > +#ifndef _ASMARM_BARRIER_H_
> > +#define _ASMARM_BARRIER_H_
> > +/*
> > + * Adapted form arch/arm/include/asm/barrier.h
> > + */
> > +
> > +#define isb(option) __asm__ __volatile__ ("isb " #option : : : "memory")
> > +#define dsb(option) __asm__ __volatile__ ("dsb " #option : : : "memory")
> > +#define dmb(option) __asm__ __volatile__ ("dmb " #option : : : "memory")
> > +
> > +#define mb()		dsb()
> > +#define rmb()		dsb()
> > +#define wmb()		dsb(st)
> > +#define smp_mb()	dmb(ish)
> > +#define smp_rmb()	smp_mb()
> > +#define smp_wmb()	dmb(ishst)
> > +
> > +#endif /* _ASMARM_BARRIER_H_ */
> > diff --git a/lib/arm/asm/io.h b/lib/arm/asm/io.h
> > new file mode 100644
> > index 0000000000000..51ec6e9aa2e99
> > --- /dev/null
> > +++ b/lib/arm/asm/io.h
> > @@ -0,0 +1,24 @@
> > +#ifndef _ASMARM_IO_H_
> > +#define _ASMARM_IO_H_
> > +#include "libcflat.h"
> > +#include "asm/barrier.h"
> > +
> > +#define __bswap16 bswap16
> > +static inline u16 bswap16(u16 val)
> > +{
> > +	u16 ret;
> > +	asm volatile("rev16 %0, %1" : "=r" (ret) :  "r" (val));
> > +	return ret;
> > +}
> > +
> > +#define __bswap32 bswap32
> > +static inline u32 bswap32(u32 val)
> > +{
> > +	u32 ret;
> > +	asm volatile("rev %0, %1" : "=r" (ret) :  "r" (val));
> > +	return ret;
> > +}
> > +
> > +#include "asm-generic/io.h"
> > +
> > +#endif /* _ASMARM_IO_H_ */
> > diff --git a/lib/arm/asm/setup.h b/lib/arm/asm/setup.h
> > new file mode 100644
> > index 0000000000000..d451b23434041
> > --- /dev/null
> > +++ b/lib/arm/asm/setup.h
> > @@ -0,0 +1,39 @@
> > +#ifndef _ASMARM_SETUP_H_
> > +#define _ASMARM_SETUP_H_
> > +/*
> > + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2.
> > + */
> > +#include "libcflat.h"
> > +
> > +#define NR_CPUS			8
> > +extern u32 cpus[NR_CPUS];
> > +extern int nr_cpus;
> > +
> > +typedef u64 phys_addr_t;
> > +
> > +#define NR_MEMREGIONS		16
> > +struct memregion {
> > +	phys_addr_t addr;
> > +	phys_addr_t size;
> > +	bool free;
> > +};
> > +
> > +extern struct memregion memregions[NR_MEMREGIONS];
> > +extern int nr_memregions;
> > +
> > +extern struct memregion *memregion_new(phys_addr_t size);
> > +extern void memregions_show(void);
> > +
> > +#define PHYS_OFFSET		({ memregions[0].addr; })
> > +#define PHYS_SHIFT		40
> > +#define PHYS_SIZE		(1ULL << PHYS_SHIFT)
> > +#define PHYS_MASK		(PHYS_SIZE - 1ULL)
> 
> it's pretty funky that you define PHYS_MASK the opposite of PAGE_MASK?

I agree. I had a brain flip-flop when I first read it - but then stole it
as is from the kernel. I'm trying to keep all these types of things
identical to the kernel in order to avoid doing even more flip-flops when
bouncing back and forth.

> 
> > +
> > +#define PAGE_SHIFT		12
> > +#define PAGE_SIZE		(1UL << PAGE_SHIFT)
> > +#define PAGE_MASK		(~(PAGE_SIZE - 1UL))
> > +#define PAGE_ALIGN(addr)	(((addr) + (PAGE_SIZE-1UL)) & PAGE_MASK)
> > +
> > +#endif /* _ASMARM_SETUP_H_ */
> > diff --git a/lib/arm/asm/spinlock.h b/lib/arm/asm/spinlock.h
> > new file mode 100644
> > index 0000000000000..04f5a1a5538e2
> > --- /dev/null
> > +++ b/lib/arm/asm/spinlock.h
> > @@ -0,0 +1,16 @@
> > +#ifndef _ASMARM_SPINLOCK_H_
> > +#define _ASMARM_SPINLOCK_H_
> > +
> > +struct spinlock {
> > +	int v;
> > +};
> > +
> > +//TODO
> > +static inline void spin_lock(struct spinlock *lock __unused)
> > +{
> > +}
> > +static inline void spin_unlock(struct spinlock *lock __unused)
> > +{
> > +}
> > +
> > +#endif /* _ASMARM_SPINLOCK_H_ */
> > diff --git a/lib/arm/eabi_compat.c b/lib/arm/eabi_compat.c
> > new file mode 100644
> > index 0000000000000..59d624dcd9277
> > --- /dev/null
> > +++ b/lib/arm/eabi_compat.c
> > @@ -0,0 +1,20 @@
> > +/*
> > + * Adapted from u-boot's arch/arm/lib/eabi_compat.c
> > + */
> > +#include "libcflat.h"
> > +
> > +int raise(int signum __unused)
> > +{
> > +	printf("Divide by zero!\n");
> > +	abort();
> > +	return 0;
> > +}
> > +
> > +/* Dummy functions to avoid linker complaints */
> > +void __aeabi_unwind_cpp_pr0(void)
> > +{
> > +}
> > +
> > +void __aeabi_unwind_cpp_pr1(void)
> > +{
> > +}
> > diff --git a/lib/arm/io.c b/lib/arm/io.c
> > new file mode 100644
> > index 0000000000000..c865f61c94934
> > --- /dev/null
> > +++ b/lib/arm/io.c
> > @@ -0,0 +1,66 @@
> > +/*
> > + * Each architecture must implement puts() and exit() with the I/O
> > + * devices exposed from QEMU, e.g. pl011 and virtio-testdev. That's
> > + * what's done here, along with initialization functions for those
> > + * devices.
> > + *
> > + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2.
> > + */
> > +#include "libcflat.h"
> > +#include "devicetree.h"
> > +#include "virtio-testdev.h"
> > +#include "asm/spinlock.h"
> > +#include "asm/io.h"
> > +
> > +extern void halt(int code);
> > +
> > +/*
> > + * Use this guess for the pl011 base in order to make an attempt at
> > + * having earlier printf support. We'll overwrite it with the real
> > + * base address that we read from the device tree later.
> > + */
> > +#define QEMU_MACH_VIRT_PL011_BASE 0x09000000UL
> > +
> > +static struct spinlock uart_lock;
> > +static volatile u8 *uart0_base = (u8 *)QEMU_MACH_VIRT_PL011_BASE;
> > +
> > +static void uart0_init(void)
> > +{
> > +	const char *compatible = "arm,pl011";
> > +	dt_pbus_addr_t base;
> > +	int ret;
> > +
> > +	ret = dt_pbus_get_baseaddr_compatible(compatible, &base);
> > +	assert(ret == 0 || ret == -FDT_ERR_NOTFOUND);
> > +
> > +	if (ret == 0) {
> > +		assert(sizeof(long) == 8 || !(base >> 32));
> 
> didn't we already check this somewhere?  Or was that virtio specific?

yeah, last one was virtio.

> 
> This confirms my suspicion that you should add a dummy identity ioremap
> function that can do this check once.

Good idea. Will do.

> 
> > +		uart0_base = (u8 *)(unsigned long)base;
> 
> hmmm, u8*, I guess that sort of makes sense...
> 
> > +	} else {
> > +		printf("%s: %s not found in the device tree, aborting...\n",
> > +			__func__, compatible);
> > +		abort();
> 
> I think this function would read nicer if you did this right after your
> assert:
> 
> if (ret) {
> 	printf(....);
> 	abort();
> 	}
> 
> uart0_base = ....;

OK

> 
> > +	}
> > +}
> > +
> > +void io_init(void)
> > +{
> > +	uart0_init();
> > +	virtio_testdev_init();
> > +}
> > +
> > +void puts(const char *s)
> > +{
> > +	spin_lock(&uart_lock);
> > +	while (*s)
> > +		writel(*s++, uart0_base);
> > +	spin_unlock(&uart_lock);
> > +}
> > +
> > +void exit(int code)
> > +{
> > +	virtio_testdev_exit(code);
> > +	halt(code);
> > +}
> > diff --git a/lib/arm/setup.c b/lib/arm/setup.c
> > new file mode 100644
> > index 0000000000000..3794291e94e01
> > --- /dev/null
> > +++ b/lib/arm/setup.c
> > @@ -0,0 +1,142 @@
> > +/*
> > + * Initialize machine setup information and I/O.
> > + *
> > + * After running setup() a flat file knows how many cpus it has
> 
> 'a flat file knows' ?

yeah, I can do better than that :-)

After running setup() unit tests may query...

> 
> > + * (nr_cpus), how much free memory it has, and at what physical
> > + * address that free memory starts (memregions[1].{addr,size}),
> > + * printf() and exit() will both work, and (argc, argv) are ready
> > + * to be passed to main().
> > + *
> > + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2.
> > + */
> > +#include "libcflat.h"
> > +#include "libfdt/libfdt.h"
> > +#include "devicetree.h"
> > +#include "asm/spinlock.h"
> > +#include "asm/setup.h"
> > +
> > +extern unsigned long stacktop;
> > +extern void io_init(void);
> > +extern void setup_args(const char *args);
> > +
> > +u32 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0UL) };
> > +int nr_cpus;
> > +
> > +static struct spinlock memregion_lock;
> > +struct memregion memregions[NR_MEMREGIONS];
> > +int nr_memregions;
> > +
> > +static void cpu_set(int fdtnode __unused, u32 regval, void *info)
> > +{
> > +	unsigned *i = (unsigned *)info;
> 
> shouldn't you assert (*i) < NR_CPUS?

yup. will do.

> 
> > +	cpus[*i] = regval;
> > +	*i += 1;
> 
> holy cow that's a convoluted way of counting.  Can't you just bump the
> nr_cpus here?

true. I might as well just dump 'i' and use nr_cpus.

> 
> > +}
> > +
> > +static void cpu_init(void)
> > +{
> > +	unsigned i = 0;
> > +	assert(dt_for_each_cpu_node(cpu_set, &i) == 0);
> > +	nr_cpus = i;
> > +}
> > +
> > +static void memregions_init(phys_addr_t freemem_start)
> > +{
> > +	/* we only expect one membank to be defined in the DT */
> > +	struct dt_pbus_reg regs[1];
> > +	phys_addr_t addr, size, mem_end;
> > +
> > +	nr_memregions = dt_get_memory_params(regs, 1);
> > +
> > +	assert(nr_memregions > 0);
> > +
> > +	addr = regs[0].addr;
> > +	size = regs[0].size;
> > +	mem_end = addr + size;
> > +
> > +	assert(!(addr & ~PHYS_MASK) && !((mem_end-1) & ~PHYS_MASK));
> > +
> > +#ifdef __arm__
> > +	/* TODO: support highmem? */
> 
> I don't think highmem is the right term here, the concept is LPAE

comment changed.

> 
> > +	assert(!((u64)addr >> 32) && !((u64)(mem_end-1) >> 32));
> > +#endif
> > +
> > +	freemem_start = PAGE_ALIGN(freemem_start);
> > +
> > +	memregions[0].addr = PAGE_ALIGN(addr);
> > +	memregions[0].size = freemem_start - PHYS_OFFSET;
> 
> don't you want to assert that the membank found in the dt actually
> covers the addresses we're loaded at?
> 
> > +
> > +	memregions[1].addr = freemem_start;
> > +	memregions[1].size = mem_end - freemem_start;
> > +	memregions[1].free = true;
> 
> you could have defines for 0 and 1 here if you have already decided
> these places have special meanings.
> 
> > +	nr_memregions = 2;
> > +}
> > +
> 
> this is an allocator of sorts, essentially, right?  It would be most
> helpful to document this seemingly very important function.

I have some tweaks to this in a v4 fixups branch. I'll integrate
those changes, your suggestions, and some documentation into v5.

> 
> > +struct memregion *memregion_new(phys_addr_t size)
> > +{
> > +	phys_addr_t freemem_start, freemem_size, mem_end;
> > +	struct memregion *m;
> > +
> > +	spin_lock(&memregion_lock);
> > +
> > +	assert(memregions[nr_memregions-1].free);
> > +	assert(memregions[nr_memregions-1].size >= size);
> > +
> > +	mem_end = memregions[nr_memregions-1].addr
> > +		+ memregions[nr_memregions-1].size;
> > +
> > +	freemem_start = PAGE_ALIGN(memregions[nr_memregions-1].addr + size);
> > +	freemem_size = mem_end - freemem_start;
> > +
> > +	memregions[nr_memregions-1].size = freemem_start
> > +					 - memregions[nr_memregions-1].addr;
> > +	memregions[nr_memregions-1].free = false;
> > +
> > +	m = &memregions[nr_memregions-1];
> > +
> > +	if (nr_memregions < NR_MEMREGIONS) {
> > +		memregions[nr_memregions].addr = freemem_start;
> > +		memregions[nr_memregions].size = freemem_size;
> > +		memregions[nr_memregions].free = true;
> > +		++nr_memregions;
> > +	}
> > +
> > +	spin_unlock(&memregion_lock);
> > +
> > +	return m;
> > +}
> > +
> > +void memregions_show(void)
> > +{
> > +	int i;
> > +	for (i = 0; i < nr_memregions; ++i)
> > +		printf("%016llx-%016llx [%s]\n",
> > +			memregions[i].addr,
> > +			memregions[i].addr + memregions[i].size - 1,
> > +			memregions[i].free ? "FREE" : "USED");
> > +}
> > +
> > +void setup(unsigned long arg __unused, unsigned long id __unused,
> > +	   const void *fdt)
> > +{
> > +	const char *bootargs;
> > +	u32 fdt_size;
> > +
> > +	/*
> > +	 * Move the fdt to just above the stack. The free memory
> > +	 * then starts just after the fdt.
> > +	 */
> > +	fdt_size = fdt_totalsize(fdt);
> > +	assert(fdt_move(fdt, &stacktop, fdt_size) == 0);
> > +	assert(dt_init(&stacktop) == 0);
> > +
> > +	memregions_init((unsigned long)&stacktop + fdt_size);
> > +
> > +	io_init();
> > +	cpu_init();
> > +
> > +	assert(dt_get_bootargs(&bootargs) == 0);
> > +	setup_args(bootargs);
> > +}
> > -- 
> > 1.8.1.4
> > 
> 
> Thanks,
> -Christoffer

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 00/19] kvm-unit-tests/arm: initial drop
  2014-06-06 18:41 ` [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Christoffer Dall
@ 2014-06-09  9:51   ` Andrew Jones
  2014-06-09  9:57     ` Christoffer Dall
  0 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-06-09  9:51 UTC (permalink / raw)
  To: Christoffer Dall; +Cc: kvmarm, kvm

On Fri, Jun 06, 2014 at 08:41:44PM +0200, Christoffer Dall wrote:
> On Thu, Apr 10, 2014 at 06:56:41PM +0200, Andrew Jones wrote:
> > This is a v4 of a series that introduces arm to kvm-unit-tests. First,
> > it does some tidying up of the repo. Then, it adds support for device
> > trees (libfdt), and for virtio-testdev[1]. Next, it adds the basic
> > infrastructure for booting a test case (guest), and adds a first
> > test case, a self-test to confirm setup was completed successfully.
> > Finally, it further prepares the framework for more complicated tests
> > by adding vector support, and extends the self-test to test that too.
> > 
> > This initial drop doesn't require kvmarm. qemu-system-arm is enough,
> > but it must have mach-virt, and the virtio-testdev patch[1].
> > 
> 
> This is overall looking really good!
> 
> I only had a few comments and questions, but you should be able to sort
> that out quickly.
> 
> It's a lot of code and growing for every iteration, and this time it was
> a long gap since the last review, so it took me a while.
> 
> I think it would be great if you can address my comments quickly and we
> can this merged without futher churn and let new functionality come as
> separate extra patches afterwards.

Thanks a million for the reviewing! I'll get v5 with your acked-by's and
reviewed-by's and comments addressed sent out today or tomorrow.

drew

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 10/19] Introduce asm-generic/*.h files
  2014-06-09  9:08       ` Christoffer Dall
@ 2014-06-09  9:54         ` Andrew Jones
  2014-06-09 11:39           ` Andrew Jones
  0 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-06-09  9:54 UTC (permalink / raw)
  To: Christoffer Dall; +Cc: kvmarm, kvm

On Mon, Jun 09, 2014 at 11:08:32AM +0200, Christoffer Dall wrote:
> On Mon, Jun 09, 2014 at 10:23:27AM +0200, Andrew Jones wrote:
> > On Fri, Jun 06, 2014 at 08:39:09PM +0200, Christoffer Dall wrote:
> > > On Thu, Apr 10, 2014 at 06:56:51PM +0200, Andrew Jones wrote:
> > > > Architecture neutral code may need to call low-level io accessors,
> > > > or use spinlocks. Create a generic io.h to ensure those accessors
> > > > are defined, and a generic spinlock.h that complains when included,
> > > > as we can't write a generic spinlock. These files can be overridden
> > > > or extended by architecture specific versions placed in
> > > > lib/$ARCH/asm/.
> > > > 
> > > > Signed-off-by: Andrew Jones <drjones@redhat.com>
> > > > ---
> > > > v4: introduce lib/asm symlink to get rid of #ifdef __arm__,
> > > >     add spinlock.h too
> > > > v3: wrt to io.h (was libio.[ch]) only
> > > >     - get rid of CONFIG_64BIT, replace with asserts
> > > >     - get rid of {read,write}_len() [libio.c]
> > > >     - fix bad *64_to_cpu macros
> > > > ---
> > > >  .gitignore                 |   1 +
> > > >  Makefile                   |   6 +-
> > > >  configure                  |  11 ++++
> > > >  lib/asm-generic/io.h       | 154 +++++++++++++++++++++++++++++++++++++++++++++
> > > >  lib/asm-generic/spinlock.h |   4 ++
> > > >  5 files changed, 173 insertions(+), 3 deletions(-)
> > > >  create mode 100644 lib/asm-generic/io.h
> > > >  create mode 100644 lib/asm-generic/spinlock.h
> > > > 
> > > > diff --git a/.gitignore b/.gitignore
> > > > index 775d0dfd8263e..e21939a8771e9 100644
> > > > --- a/.gitignore
> > > > +++ b/.gitignore
> > > > @@ -9,6 +9,7 @@ patches
> > > >  .stgit-*
> > > >  cscope.*
> > > >  *.swp
> > > > +/lib/asm
> > > >  /config.mak
> > > >  /*-run
> > > >  /test.log
> > > > diff --git a/Makefile b/Makefile
> > > > index fba58e36f272f..51cacdac00615 100644
> > > > --- a/Makefile
> > > > +++ b/Makefile
> > > > @@ -76,11 +76,11 @@ libfdt_clean:
> > > >  	$(LIBFDT_objdir)/.*.d
> > > >  
> > > >  distclean: clean libfdt_clean
> > > > -	$(RM) config.mak $(TEST_DIR)-run test.log msr.out cscope.*
> > > > +	$(RM) lib/asm config.mak $(TEST_DIR)-run test.log msr.out cscope.*
> > > >  
> > > > -cscope: common_dirs = lib lib/libfdt
> > > > +cscope: common_dirs = lib lib/libfdt lib/asm lib/asm-generic
> > > >  cscope:
> > > >  	$(RM) ./cscope.*
> > > > -	find $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
> > > > +	find -L $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
> > > >  		-name '*.[chsS]' -print | sed 's,^\./,,' > ./cscope.files
> > > >  	cscope -bk
> > > > diff --git a/configure b/configure
> > > > index 6cfc64943f6e6..8a81bf92e27b7 100755
> > > > --- a/configure
> > > > +++ b/configure
> > > > @@ -95,6 +95,17 @@ if [ $exit -eq 0 ]; then
> > > >  fi
> > > >  rm -f lib_test.c
> > > >  
> > > > +# link lib/asm for the architecture
> > > > +rm -f lib/asm
> > > > +asm=asm-generic
> > > > +if [ -d lib/$arch/asm ]; then
> > > > +	asm=$arch/asm
> > > > +elif [ -d lib/$testdir/asm ]; then
> > > > +	asm=$testdir/asm
> > > 
> > > why do you need this elif?  can you not make sure arch is always set?
> > 
> > arch is always set, but there's a chance some arch may not add it's own
> > lib/$arch dir. It's a pretty small chance... but the elif shouldn't hurt.
> > 
> If we don't have any code that uses this scheme now then let's now have
> Makefile rules that encourages non-standard behavior (unless I'm missing
> the point and this provides a 'feature' for specific archs or something
> like that).
>

It would be something of a feature for some imaginary arch. However, as
that imaginary arch doesn't exist right now, then I'm fine removing it.
Whoever makes the imaginary arch a reality can bring it back.

drew 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 00/19] kvm-unit-tests/arm: initial drop
  2014-06-09  9:51   ` Andrew Jones
@ 2014-06-09  9:57     ` Christoffer Dall
  0 siblings, 0 replies; 54+ messages in thread
From: Christoffer Dall @ 2014-06-09  9:57 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Mon, Jun 09, 2014 at 11:51:40AM +0200, Andrew Jones wrote:
> On Fri, Jun 06, 2014 at 08:41:44PM +0200, Christoffer Dall wrote:
> > On Thu, Apr 10, 2014 at 06:56:41PM +0200, Andrew Jones wrote:
> > > This is a v4 of a series that introduces arm to kvm-unit-tests. First,
> > > it does some tidying up of the repo. Then, it adds support for device
> > > trees (libfdt), and for virtio-testdev[1]. Next, it adds the basic
> > > infrastructure for booting a test case (guest), and adds a first
> > > test case, a self-test to confirm setup was completed successfully.
> > > Finally, it further prepares the framework for more complicated tests
> > > by adding vector support, and extends the self-test to test that too.
> > > 
> > > This initial drop doesn't require kvmarm. qemu-system-arm is enough,
> > > but it must have mach-virt, and the virtio-testdev patch[1].
> > > 
> > 
> > This is overall looking really good!
> > 
> > I only had a few comments and questions, but you should be able to sort
> > that out quickly.
> > 
> > It's a lot of code and growing for every iteration, and this time it was
> > a long gap since the last review, so it took me a while.
> > 
> > I think it would be great if you can address my comments quickly and we
> > can this merged without futher churn and let new functionality come as
> > separate extra patches afterwards.
> 
> Thanks a million for the reviewing! I'll get v5 with your acked-by's and
> reviewed-by's and comments addressed sent out today or tomorrow.
> 
Awesome!
-Christoffer

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 08/19] add support for Linux device trees
  2014-06-06 18:38   ` Christoffer Dall
@ 2014-06-09 10:18     ` Andrew Jones
  2014-06-09 10:45       ` Christoffer Dall
  0 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-06-09 10:18 UTC (permalink / raw)
  To: Christoffer Dall; +Cc: kvmarm, kvm

On Fri, Jun 06, 2014 at 08:38:35PM +0200, Christoffer Dall wrote:
> On Thu, Apr 10, 2014 at 06:56:49PM +0200, Andrew Jones wrote:
> > Add some device tree functions, built on libfdt, to the arch-neutral
> > lib code in order to facilitate the extraction of boot info and device
> > base addresses. These functions should work on device trees conforming
> > to section III of the kernel doc
> > Documentation/devicetree/booting-without-of.txt.
> > 
> > Signed-off-by: Andrew Jones <drjones@redhat.com>
> > ---
> > v4: reworked everything, added lots of comments to devicetree.h
> 
>  => reworked everything
>  that will make it easy to review again ;)
> 
> > ---
> >  lib/devicetree.c | 289 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  lib/devicetree.h | 230 +++++++++++++++++++++++++++++++++++++++++++
> >  lib/libcflat.h   |   2 +
> >  3 files changed, 521 insertions(+)
> >  create mode 100644 lib/devicetree.c
> >  create mode 100644 lib/devicetree.h
> > 
> > diff --git a/lib/devicetree.c b/lib/devicetree.c
> > new file mode 100644
> > index 0000000000000..482028f066346
> > --- /dev/null
> > +++ b/lib/devicetree.c
> > @@ -0,0 +1,289 @@
> > +/*
> > + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2.
> > + */
> > +#include "libcflat.h"
> > +#include "libfdt/libfdt.h"
> > +#include "devicetree.h"
> > +
> > +static const void *fdt;
> > +static u32 root_nr_address_cells, root_nr_size_cells;
> > +
> > +const void *dt_fdt(void)
> > +{
> > +	return fdt;
> > +}
> > +
> > +bool dt_available(void)
> > +{
> > +	return fdt_check_header(fdt) == 0;
> > +}
> > +
> > +int dt_get_nr_cells(int fdtnode, u32 *nr_address_cells, u32 *nr_size_cells)
> > +{
> > +	const struct fdt_property *prop;
> > +	u32 *nr_cells;
> > +	int len;
> > +
> > +	prop = fdt_get_property(fdt, fdtnode, "#address-cells", &len);
> > +	if (prop == NULL)
> > +		return len;
> > +
> > +	nr_cells = (u32 *)prop->data;
> > +	*nr_address_cells = fdt32_to_cpu(*nr_cells);
> > +
> > +	prop = fdt_get_property(fdt, fdtnode, "#size-cells", &len);
> > +	if (prop == NULL)
> > +		return len;
> > +
> > +	nr_cells = (u32 *)prop->data;
> > +	*nr_size_cells = fdt32_to_cpu(*nr_cells);
> > +
> > +	return 0;
> > +}
> > +
> > +void dt_reg_init(struct dt_reg *reg, u32 nr_address_cells, u32 nr_size_cells)
> > +{
> > +	memset(reg, 0, sizeof(struct dt_reg));
> > +	reg->nr_address_cells = nr_address_cells;
> > +	reg->nr_size_cells = nr_size_cells;
> > +}
> > +
> > +int dt_get_reg(int fdtnode, int regidx, struct dt_reg *reg)
> > +{
> > +	const struct fdt_property *prop;
> > +	u32 *cells, i;
> > +	unsigned nr_tuple_cells;
> > +	int len;
> > +
> > +	prop = fdt_get_property(fdt, fdtnode, "reg", &len);
> > +	if (prop == NULL)
> > +		return len;
> > +
> > +	cells = (u32 *)prop->data;
> > +	nr_tuple_cells = reg->nr_address_cells + reg->nr_size_cells;
> > +	regidx *= nr_tuple_cells;
> > +
> > +	if (regidx + nr_tuple_cells > len/sizeof(u32))
> 
> Shouldn't this be >= ?

Not this time. The LHS is the total number of words needed (not an
index).

> 
> > +		return -FDT_ERR_NOTFOUND;
> > +
> > +	for (i = 0; i < reg->nr_address_cells; ++i)
> > +		reg->address_cells[i] = fdt32_to_cpu(cells[regidx + i]);
> > +
> > +	regidx += reg->nr_address_cells;
> > +	for (i = 0; i < reg->nr_size_cells; ++i)
> > +		reg->size_cells[i] = fdt32_to_cpu(cells[regidx + i]);
> > +
> > +	return 0;
> > +}
> > +
> > +int dt_pbus_translate_node(int fdtnode, int regidx, void *reg)
> 
> why doesn't this function take a struct dt_pbus_reg * instead of a
> void *?

Guess I forgot my coffee when I wrote it... I'll change that.

> 
> > +{
> > +	struct dt_pbus_reg *pbus_reg = (struct dt_pbus_reg *)reg;
> > +	struct dt_reg raw_reg;
> > +	int ret;
> > +
> > +	dt_reg_init(&raw_reg, root_nr_address_cells, root_nr_size_cells);
> > +
> > +	ret = dt_get_reg(fdtnode, regidx, &raw_reg);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	pbus_reg->addr = dt_pbus_read_cells(raw_reg.nr_address_cells,
> > +					    raw_reg.address_cells);
> > +	pbus_reg->size = dt_pbus_read_cells(raw_reg.nr_size_cells,
> > +					    raw_reg.size_cells);
> > +
> > +	return 0;
> > +}
> > +
> > +int dt_pbus_translate(const struct dt_device *dev, int regidx,
> > +		      void *reg)
> > +{
> > +	return dt_pbus_translate_node(dev->fdtnode, regidx, reg);
> > +}
> > +
> > +int dt_pbus_get_baseaddr(const struct dt_device *dev, dt_pbus_addr_t *base)
> > +{
> > +	struct dt_pbus_reg reg;
> > +	int ret;
> > +
> > +	ret = dt_pbus_translate(dev, 0, &reg);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	*base = reg.addr;
> > +	return 0;
> > +}
> > +
> > +int dt_bus_match_any(const struct dt_device *dev __unused, int fdtnode)
> > +{
> > +	/* matches any device with a valid node */
> > +	return fdtnode < 0 ? fdtnode : 1;
> > +}
> > +
> > +static const struct dt_bus dt_default_bus = {
> > +	.match = dt_bus_match_any,
> > +	.translate = dt_pbus_translate,
> > +};
> > +
> > +void dt_bus_init_defaults(struct dt_bus *bus)
> > +{
> > +	memcpy(bus, &dt_default_bus, sizeof(struct dt_bus));
> > +}
> > +
> > +void dt_device_init(struct dt_device *dev, const struct dt_bus *bus,
> > +		    const void *info)
> > +{
> > +	memset(dev, 0, sizeof(struct dt_device));
> > +	dev->bus = bus;
> > +	dev->info = (void *)info;
> > +}
> > +
> > +int dt_device_find_compatible(const struct dt_device *dev,
> > +			      const char *compatible)
> > +{
> > +	int node, ret;
> > +
> > +	node = fdt_node_offset_by_compatible(fdt, -1, compatible);
> > +	while (node >= 0) {
> > +		ret = dev->bus->match(dev, node);
> > +		if (ret < 0)
> > +			return ret;
> > +		else if (ret)
> > +			break;
> > +		node = fdt_node_offset_by_compatible(fdt, node, compatible);
> > +	}
> > +	return node;
> > +}
> > +
> > +int dt_pbus_get_baseaddr_compatible(const char *compatible,
> > +				    dt_pbus_addr_t *baseaddr)
> > +{
> > +	struct dt_device dev;
> > +	int node, ret;
> > +
> > +	dt_device_init(&dev, &dt_default_bus, NULL);
> > +
> > +	node = dt_device_find_compatible(&dev, compatible);
> > +	if (node < 0)
> > +		return node;
> > +
> > +	dt_device_bind_node(&dev, node);
> > +
> > +	ret = dt_pbus_get_baseaddr(&dev, baseaddr);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	return 0;
> > +}
> > +
> > +int dt_get_memory_params(struct dt_pbus_reg *regs, int nr_regs)
> > +{
> > +	const char *pn = "device_type", *pv = "memory";
> > +	int node, ret, pl = strlen(pv) + 1, nr = 0;
> > +	struct dt_pbus_reg reg;
> > +
> > +	node = fdt_node_offset_by_prop_value(fdt, -1, pn, pv, pl);
> > +
> > +	while (node >= 0) {
> > +
> > +		while (nr < nr_regs) {
> > +			ret = dt_pbus_translate_node(node, nr, &reg);
> > +			if (ret == -FDT_ERR_NOTFOUND)
> > +				break;
> > +			if (ret < 0)
> > +				return ret;
> > +			regs[nr].addr = reg.addr;
> > +			regs[nr].size = reg.size;
> > +			++nr;
> > +		}
> > +
> > +		node = fdt_node_offset_by_prop_value(fdt, node, pn, pv, pl);
> > +	}
> > +
> > +	return node != -FDT_ERR_NOTFOUND ? node : nr;
> > +}
> > +
> > +int dt_for_each_cpu_node(void (*func)(int fdtnode, u32 regval, void *info),
> > +			 void *info)
> > +{
> > +	const struct fdt_property *prop;
> > +	int cpus, cpu, ret, len;
> > +	struct dt_reg raw_reg;
> > +	u32 nac, nsc;
> > +
> > +	cpus = fdt_path_offset(fdt, "/cpus");
> > +	if (cpus < 0)
> > +		return cpus;
> > +
> > +	ret = dt_get_nr_cells(cpus, &nac, &nsc);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	dt_reg_init(&raw_reg, nac, nsc);
> > +
> > +	dt_for_each_subnode(cpus, cpu) {
> > +
> > +		prop = fdt_get_property(fdt, cpu, "device_type", &len);
> > +		if (prop == NULL)
> > +			return len;
> > +
> > +		if (len != 4 || strcmp((char *)prop->data, "cpu"))
> > +			continue;
> > +
> > +		ret = dt_get_reg(cpu, 0, &raw_reg);
> > +		if (ret < 0)
> > +			return ret;
> > +
> > +		func(cpu, raw_reg.address_cells[0], info);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +int dt_get_bootargs(const char **bootargs)
> > +{
> > +	const struct fdt_property *prop;
> > +	int node, len;
> > +
> > +	*bootargs = NULL;
> > +
> > +	node = fdt_path_offset(fdt, "/chosen");
> > +	if (node < 0)
> > +		return node;
> > +
> > +	prop = fdt_get_property(fdt, node, "bootargs", &len);
> > +	if (prop)
> > +		*bootargs = (char *)prop->data;
> > +	else if (len < 0 && len != -FDT_ERR_NOTFOUND)
> > +		return len;
> 
> so if you get FDT_ERR_NOTFOUND you still return success but the bootargs
> won't be set? why?

bootargs will be NULL in that case, which is enough to know there wasn't
any. I also wanted to be able to easily check for any other error without
having to filter FDT_ERR_NOTFOUND at every call site. I can skip this
special behavior though, if a more consistent interface is preferred.

> 
> > +
> > +	return 0;
> > +}
> > +
> > +int dt_init(const void *fdt_ptr)
> > +{
> > +	struct dt_bus *defbus = (struct dt_bus *)&dt_default_bus;
> > +	int root, ret;
> > +
> > +	ret = fdt_check_header(fdt_ptr);
> > +	if (ret < 0)
> > +		return ret;
> > +	fdt = fdt_ptr;
> > +
> > +	root = fdt_path_offset(fdt, "/");
> > +	if (root < 0)
> > +		return root;
> > +
> > +	ret = dt_get_nr_cells(root, &root_nr_address_cells,
> > +				    &root_nr_size_cells);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	defbus->nr_address_cells = root_nr_address_cells;
> > +	defbus->nr_size_cells = root_nr_size_cells;
> > +
> > +	return 0;
> > +}
> > diff --git a/lib/devicetree.h b/lib/devicetree.h
> > new file mode 100644
> > index 0000000000000..032b5497f9db1
> > --- /dev/null
> > +++ b/lib/devicetree.h
> > @@ -0,0 +1,230 @@
> > +#ifndef _DEVICETREE_H_
> > +#define _DEVICETREE_H_
> > +/*
> > + * devicetree builds on libfdt to implement abstractions and accessors
> > + * for Linux required device tree content. The accessors provided are
> > + * common across architectures. See section III of the kernel doc
> > + * Documentation/devicetree/booting-without-of.txt
> > + *
> > + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2.
> > + */
> > +#include "libcflat.h"
> > +#include "libfdt/libfdt.h"
> > +
> > +/**********************************************************************
> > + * devicetree init and libfdt helpers
> > + **********************************************************************/
> > +
> > +/* dt_init initializes devicetree with a pointer to an fdt, @fdt_ptr */
> > +extern int dt_init(const void *fdt_ptr);
> > +
> > +/* get the fdt pointer that devicetree is using */
> > +const void *dt_fdt(void);
> 
> nit: why no extern here?

Just forgot it. Will add it.

> 
> > +
> > +/* check for an initialized, valid devicetree */
> > +extern bool dt_available(void);
> > +
> > +/* traverse child nodes */
> > +#define dt_for_each_subnode(n, s)					\
> > +	for (s = fdt_first_subnode(dt_fdt(), n);			\
> > +	     s != -FDT_ERR_NOTFOUND;					\
> > +	     s = fdt_next_subnode(dt_fdt(), s))
> > +
> > +/**********************************************************************
> > + * Abstractions for required node types and properties
> > + **********************************************************************/
> > +
> > +struct dt_device {
> > +	int fdtnode;
> > +	const struct dt_bus *bus;
> > +
> > +	/*
> > +	 * info is a pointer to device specific data, which may be
> > +	 * used by the bus match() and translate() functions
> > +	 */
> > +	void *info;
> > +};
> > +
> > +struct dt_bus {
> > +	/*
> > +	 * match a device @dev to an fdt node @fdtnode
> > +	 * returns
> > +	 *  - a positive value on match
> > +	 *  - zero on no match
> > +	 *  - a negative FDT_ERR_* value on failure
> > +	 */
> > +	int (*match)(const struct dt_device *dev, int fdtnode);
> > +
> > +	/*
> > +	 * translate the @regidx'th "address size" tuple of
> > +	 * @dev's fdt node's "reg" property, and store the result
> > +	 * in @reg, a bus specific structure
> > +	 * returns
> > +	 *  - zero on success
> > +	 *  - a negative FDT_ERR_* value on failure
> > +	 */
> > +	int (*translate)(const struct dt_device *dev, int regidx, void *reg);
> > +
> > +	/* the bus #address-cells and #size-cells properties */
> > +	u32 nr_address_cells, nr_size_cells;
> > +};
> > +
> > +/* dt_bus_match_any matches any fdt node, i.e. it always returns true */
> > +extern int dt_bus_match_any(const struct dt_device *dev, int fdtnode);
> > +
> > +/* the processor bus (pbus) address type and register tuple */
> > +typedef u64 dt_pbus_addr_t;
> > +struct dt_pbus_reg {
> > +	dt_pbus_addr_t addr;
> > +	dt_pbus_addr_t size;
> > +};
> > +
> > +static inline dt_pbus_addr_t dt_pbus_read_cells(u32 nr_cells, u32 *cells)
> > +{
> > +	return nr_cells == 2 ? ((u64)cells[0] << 32) | cells[1]
> > +		: nr_cells == 1 ? cells[0] : (~0ULL);
> 
> Why the tertiary operator here?  A simple if or select statement should
> make the code much easier to read and you don't seem to handle

I'll change it.

> #address-cells == 4or #size-cells == 4, despite the fact that you define
> MAX_ADDRESS_CELLS=4 etc.  This seems a bit weird to me.

The default translator only knows how to handle nr_cells==2 or
nr_cells==1. DT may have nodes with nr_cells > 2 (up to 4), but users
will have to provide their own translators for those.

> 
> > +}
> > +
> > +/*
> > + * dt_pbus_translate translates device node regs for the
> > + * processor bus using the root node's #address-cells and
> > + * #size-cells and dt_pbus_read_cells()
> > + * returns
> > + *  - zero on success
> > + *  - a negative FDT_ERR_* value on failure
> > + */
> > +extern int dt_pbus_translate(const struct dt_device *dev, int regidx,
> > +			     void *reg);
> > +
> > +/*
> > + * dt_pbus_translate_node is the same as dt_pbus_translate but
> > + * operates on an fdt node instead of a dt_device
> > + */
> > +extern int dt_pbus_translate_node(int fdtnode, int regidx, void *reg);
> > +
> > +/*
> > + * dt_pbus_get_baseaddr is a shortcut for
> > + *     dt_pbus_translate(dev, 0, &reg);
> > + *     *base = reg.addr;
> > + * returns
> > + *  - zero on success
> > + *  - a negative FDT_ERR_* value on failure
> > + */
> > +extern int dt_pbus_get_baseaddr(const struct dt_device *dev,
> > +				dt_pbus_addr_t *base);
> > +
> > +/*
> > + * dt_bus_init_defaults initializes @bus with
> > + *  match		<- dt_bus_match_any
> > + *  translate		<- dt_pbus_translate
> > + *  nr_address_cells	<- #address-cells of the root node
> > + *  nr_size_cells	<- #size-cells of the root node
> > + */
> > +extern void dt_bus_init_defaults(struct dt_bus *bus);
> > +
> > +/*
> > + * dt_device_init initializes a dt_device with the given parameters
> > + */
> > +extern void dt_device_init(struct dt_device *dev, const struct dt_bus *bus,
> > +			   const void *info);
> > +
> > +static inline void dt_device_bind_node(struct dt_device *dev, int fdtnode)
> > +{
> > +	dev->fdtnode = fdtnode;
> > +}
> > +
> > +/*
> > + * dt_device_find_compatible finds a @compatible node
> > + * returns
> > + *  - node (>= 0) on success
> > + *  - a negative FDT_ERR_* value on failure
> > + */
> > +extern int dt_device_find_compatible(const struct dt_device *dev,
> > +				     const char *compatible);
> > +
> > +/*
> > + * dt_pbus_get_baseaddr_compatible simply bundles many functions into
> > + * one. It finds the first @compatible fdt node and then translates the
> > + * 0th reg tuple (the base address) using the processor bus translation,
> > + * and finally stores that address in @baseaddr.
> > + * returns
> > + *  - zero on success
> > + *  - a negative FDT_ERR_* value on failure
> > + */
> > +extern int dt_pbus_get_baseaddr_compatible(const char *compatible,
> > +					   dt_pbus_addr_t *baseaddr);
> > +
> > +/**********************************************************************
> > + * Low-level accessors for required node types and properties
> > + **********************************************************************/
> > +
> > +/*
> > + * dt_get_nr_cells sets @nr_address_cells and @nr_size_cells to the
> > + * #address-cells and #size-cells properties of @fdtnode
> > + * returns
> > + *  - zero on success
> > + *  - a negative FDT_ERR_* value on failure
> > + */
> > +extern int dt_get_nr_cells(int fdtnode, u32 *nr_address_cells,
> > +					u32 *nr_size_cells);
> > +
> > +/* dt_reg is a structure for "raw" reg tuples */
> > +#define MAX_ADDRESS_CELLS	4
> > +#define MAX_SIZE_CELLS		4
> > +struct dt_reg {
> > +	u32 nr_address_cells, nr_size_cells;
> > +	u32 address_cells[MAX_ADDRESS_CELLS];
> > +	u32 size_cells[MAX_SIZE_CELLS];
> > +};
> > +
> > +/*
> > + * dt_reg_init initialize a dt_reg struct to zero and sets
> > + * nr_address_cells and nr_size_cells to @nr_address_cells and
> > + * @nr_size_cells respectively.
> > + */
> > +extern void dt_reg_init(struct dt_reg *reg, u32 nr_address_cells,
> > +					    u32 nr_size_cells);
> > +
> > +/*
> > + * dt_get_reg gets the @regidx'th reg tuple of @fdtnode's reg property
> > + * and stores it in @reg. @reg must be initialized.
> > + * returns
> > + *  - zero on success
> > + *  - a negative FDT_ERR_* value on failure
> > + */
> > +extern int dt_get_reg(int fdtnode, int regidx, struct dt_reg *reg);
> > +
> > +/**********************************************************************
> > + * High-level accessors for required node types and properties
> > + **********************************************************************/
> > +
> > +/*
> > + * dt_get_bootargs gets a pointer to /chosen/bootargs
> > + * returns
> > + *  - zero on success
> > + *  - a negative FDT_ERR_* value on failure
> > + */
> > +extern int dt_get_bootargs(const char **bootargs);
> > +
> > +/*
> > + * dt_get_memory_params gets the memory parameters from the /memory node(s)
> > + * storing each memory region ("address size" tuple) in consecutive entries
> > + * of @regs, up to @nr_regs
> > + * returns
> > + *  - number of memory regions found on success
> > + *  - a negative FDT_ERR_* value on failure
> > + */
> > +extern int dt_get_memory_params(struct dt_pbus_reg *regs, int nr_regs);
> > +
> > +/*
> > + * dt_for_each_cpu_node runs @func on each cpu node in the /cpus node
> > + * passing it its fdt node, its reg property value, and @info
> > + *  - zero on success
> > + *  - a negative FDT_ERR_* value on failure
> > + */
> > +extern int dt_for_each_cpu_node(void (*func)(int fdtnode, u32 regval,
> > +				void *info), void *info);
> > +
> > +#endif /* _DEVICETREE_H_ */
> > diff --git a/lib/libcflat.h b/lib/libcflat.h
> > index 76448a33cde5f..99d1cd533dd03 100644
> > --- a/lib/libcflat.h
> > +++ b/lib/libcflat.h
> > @@ -22,6 +22,8 @@
> >  
> >  #include <stdarg.h>
> >  
> > +#define __unused __attribute__((__unused__))
> > +
> >  typedef unsigned char u8;
> >  typedef signed char s8;
> >  typedef unsigned short u16;
> > -- 
> > 1.8.1.4
> > 
> 
> -Christoffer

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 11/19] add minimal virtio support for devtree virtio-mmio
  2014-06-09  9:14       ` Christoffer Dall
@ 2014-06-09 10:21         ` Andrew Jones
  0 siblings, 0 replies; 54+ messages in thread
From: Andrew Jones @ 2014-06-09 10:21 UTC (permalink / raw)
  To: Christoffer Dall; +Cc: kvmarm, kvm

On Mon, Jun 09, 2014 at 11:14:31AM +0200, Christoffer Dall wrote:
> On Mon, Jun 09, 2014 at 11:02:57AM +0200, Andrew Jones wrote:
> > On Fri, Jun 06, 2014 at 08:39:18PM +0200, Christoffer Dall wrote:
> > > On Thu, Apr 10, 2014 at 06:56:52PM +0200, Andrew Jones wrote:
> > > > Support the bare minimum of virtio to enable access to the virtio-mmio
> > > > config space of a device. Currently this implementation must use a
> > > > device tree to find the device.
> > > > 
> > > > Signed-off-by: Andrew Jones <drjones@redhat.com>
> > > > ---
> > > > v4:
> > > >  - split from the virtio-testdev patch
> > > >  - search a table to "discover" that the device must be DT/virtio-mmio,
> > > >    which doesn't change anything, but looks less hacky than comments
> > > >    saying the device must be DT/virtio-mmio...
> > > >  - manage own pool of virtio-mmio pre-allocated device structures in
> > > >    order to avoid needing access to the heap
> > > > ---
> > > >  lib/libcflat.h |   3 ++
> > > >  lib/virtio.c   | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >  lib/virtio.h   |  89 +++++++++++++++++++++++++++++++
> > > >  3 files changed, 258 insertions(+)
> > > >  create mode 100644 lib/virtio.c
> > > >  create mode 100644 lib/virtio.h
> > > > 
> > > > diff --git a/lib/libcflat.h b/lib/libcflat.h
> > > > index c7c31be1cc8e5..5bb66d01dfc53 100644
> > > > --- a/lib/libcflat.h
> > > > +++ b/lib/libcflat.h
> > > > @@ -62,6 +62,9 @@ extern long atol(const char *ptr);
> > > >  #define ARRAY_SIZE(_a)  (sizeof(_a)/sizeof((_a)[0]))
> > > >  
> > > >  #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
> > > > +#define container_of(ptr, type, member) ({				\
> > > > +	const typeof( ((type *)0)->member ) *__mptr = (ptr);		\
> > > > +	(type *)( (char *)__mptr - offsetof(type,member) );})
> > > >  
> > > >  #define NULL ((void *)0UL)
> > > >  
> > > > diff --git a/lib/virtio.c b/lib/virtio.c
> > > > new file mode 100644
> > > > index 0000000000000..e7161ff591e4c
> > > > --- /dev/null
> > > > +++ b/lib/virtio.c
> > > > @@ -0,0 +1,166 @@
> > > > +/*
> > > > + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> > > > + *
> > > > + * This work is licensed under the terms of the GNU LGPL, version 2.
> > > > + */
> > > > +#include "libcflat.h"
> > > > +#include "devicetree.h"
> > > > +#include "asm/spinlock.h"
> > > > +#include "asm/io.h"
> > > > +#include "virtio.h"
> > > > +
> > > > +enum virtio_hwdesc_type {
> > > > +	VIRTIO_HWDESC_TYPE_DT = 0,	/* device tree */
> > > > +	NR_VIRTIO_HWDESC_TYPES,
> > > > +};
> > > > +
> > > > +enum virtio_bus_type {
> > > > +	VIRTIO_BUS_TYPE_MMIO = 0,	/* virtio-mmio */
> > > > +	NR_VIRTIO_BUS_TYPES,
> > > > +};
> > > > +
> > > > +struct virtio_bind_bus {
> > > > +	bool (*hwdesc_probe)(void);
> > > > +	struct virtio_dev *(*device_bind)(u32 devid);
> > > > +};
> > > > +
> > > > +static struct virtio_dev *vm_dt_device_bind(u32 devid);
> > > > +
> > > > +static struct virtio_bind_bus
> > > > +virtio_bind_busses[NR_VIRTIO_HWDESC_TYPES][NR_VIRTIO_BUS_TYPES] = {
> > > > +
> > > > +[VIRTIO_HWDESC_TYPE_DT] = {
> > > > +
> > > > +	[VIRTIO_BUS_TYPE_MMIO] = {
> > > > +		.hwdesc_probe = dt_available,
> > > > +		.device_bind = vm_dt_device_bind,
> > > > +	},
> > > > +},
> > > > +};
> > > > +
> > > > +struct virtio_dev *virtio_bind(u32 devid)
> > > > +{
> > > > +	struct virtio_bind_bus *bus;
> > > > +	struct virtio_dev *dev;
> > > > +	int i, j;
> > > > +
> > > > +	for (i = 0; i < NR_VIRTIO_HWDESC_TYPES; ++i) {
> > > > +		for (j = 0; j < NR_VIRTIO_BUS_TYPES; ++j) {
> > > > +
> > > > +			bus = &virtio_bind_busses[i][j];
> > > > +
> > > > +			if (!bus->hwdesc_probe())
> > > > +				continue;
> > > > +
> > > > +			dev = bus->device_bind(devid);
> > > > +			if (dev)
> > > > +				return dev;
> > > > +		}
> > > > +	}
> > > > +
> > > > +	return NULL;
> > > > +}
> > > > +
> > > > +/******************************************************
> > > > + * virtio-mmio support (config space only)
> > > > + ******************************************************/
> > > > +
> > > > +static void vm_get(struct virtio_dev *vdev, unsigned offset,
> > > > +		   void *buf, unsigned len)
> > > > +{
> > > > +	struct virtio_mmio_dev *vmdev = to_virtio_mmio_dev(vdev);
> > > > +	u8 *p = buf;
> > > > +	unsigned i;
> > > > +
> > > > +	for (i = 0; i < len; ++i)
> > > > +		p[i] = readb(vmdev->base + VIRTIO_MMIO_CONFIG + offset + i);
> > > > +}
> > > > +
> > > > +static void vm_set(struct virtio_dev *vdev, unsigned offset,
> > > > +		   const void *buf, unsigned len)
> > > > +{
> > > > +	struct virtio_mmio_dev *vmdev = to_virtio_mmio_dev(vdev);
> > > > +	const u8 *p = buf;
> > > > +	unsigned i;
> > > > +
> > > > +	for (i = 0; i < len; ++i)
> > > > +		writeb(p[i], vmdev->base + VIRTIO_MMIO_CONFIG + offset + i);
> > > > +}
> > > > +
> > > > +#define NR_VM_DEVICES 32
> > > > +static struct spinlock vm_lock;
> > > > +static struct virtio_mmio_dev vm_devs[NR_VM_DEVICES];
> > > > +static struct virtio_conf_ops vm_confs[NR_VM_DEVICES];
> > > > +static int nr_vm_devs;
> > > > +
> > > > +static struct virtio_mmio_dev *vm_new_device(u32 devid)
> > > > +{
> > > > +	struct virtio_mmio_dev *vmdev;
> > > > +
> > > > +	if (nr_vm_devs >= NR_VM_DEVICES)
> > > > +		return NULL;
> > > > +
> > > > +	spin_lock(&vm_lock);
> > > > +	vmdev = &vm_devs[nr_vm_devs];
> > > > +	vmdev->vdev.config = &vm_confs[nr_vm_devs];
> > > 
> > > this seems a bit weird, will we ever share vm_confs between vm_devs or
> > > change the vm_conf pointer later on?  Could vm_conf just be part of the
> > > vm_dev struct and you could just have a virtio_mmio_conf_init() to set
> > > the get/set functions?
> > 
> > I can do that, but it'll require a typedef for struct virtio_dev to
> > appease the compiler.
> > 
> > > 
> > > > +	++nr_vm_devs;
> > > > +	spin_unlock(&vm_lock);
> > > > +
> > > > +	vmdev->vdev.id.device = devid;
> > > > +	vmdev->vdev.id.vendor = -1;
> > > > +	vmdev->vdev.config->get = vm_get;
> > > > +	vmdev->vdev.config->set = vm_set;
> > > > +
> > > > +	return vmdev;
> > > > +}
> > > > +
> > > > +/******************************************************
> > > > + * virtio-mmio device tree support
> > > > + ******************************************************/
> > > > +
> > > > +struct vm_dt_info {
> > > > +	u32 devid;
> > > > +	void *base;
> > > 
> > > won't work for LPAE and 32-bit arm systems, can't you use
> > > dt_device_bind_node?
> > > 
> > > I guess that requires you to have an ioremap function, but it sure seems
> > > cleaner to give up there if you don't have proper memory mapping
> > > features yet....
> > 
> > Right. I was just skipping past that complexity for now, as mach-virt's
> > DT is currently "nice" (32-bit only addrs). I agree we need to handle
> > LPAE addrs on arm eventually though.
> > 
> 
> So I think the tradeoff here is very small, it's super easy to fix it so
> you can support physical addresses > 32 bits in this part of the code.
> The difficult thing comes when you start dereferencing them, but since
> we may add virtual addresses at some point too, I really think adding a
> trivial ioremap function and start using that will make our lives much
> easier down the line:
> 
> /* We don't support virtual addresses yet, trivial identity implementation */
> void __iomem *ioremap(phys_addr_t phys_addr)
> {
> 	assert(sizeof(long) == 8 || !(base >> 32));
> 	return (void *)(unsigned long)phys_addr;
> }
> 
> But I can submit that patch after this code goes in if you think it's
> too much of a headache at this point?

Nah, I'll steal your idea and do it now :-)

> 
> Thanks,
> -Christoffer

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 08/19] add support for Linux device trees
  2014-06-09 10:18     ` Andrew Jones
@ 2014-06-09 10:45       ` Christoffer Dall
  0 siblings, 0 replies; 54+ messages in thread
From: Christoffer Dall @ 2014-06-09 10:45 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Mon, Jun 09, 2014 at 12:18:49PM +0200, Andrew Jones wrote:
> On Fri, Jun 06, 2014 at 08:38:35PM +0200, Christoffer Dall wrote:
> > On Thu, Apr 10, 2014 at 06:56:49PM +0200, Andrew Jones wrote:
> > > Add some device tree functions, built on libfdt, to the arch-neutral
> > > lib code in order to facilitate the extraction of boot info and device
> > > base addresses. These functions should work on device trees conforming
> > > to section III of the kernel doc
> > > Documentation/devicetree/booting-without-of.txt.
> > > 
> > > Signed-off-by: Andrew Jones <drjones@redhat.com>
> > > ---
> > > v4: reworked everything, added lots of comments to devicetree.h
> > 
> >  => reworked everything
> >  that will make it easy to review again ;)
> > 
> > > ---
> > >  lib/devicetree.c | 289 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >  lib/devicetree.h | 230 +++++++++++++++++++++++++++++++++++++++++++
> > >  lib/libcflat.h   |   2 +
> > >  3 files changed, 521 insertions(+)
> > >  create mode 100644 lib/devicetree.c
> > >  create mode 100644 lib/devicetree.h
> > > 
> > > diff --git a/lib/devicetree.c b/lib/devicetree.c
> > > new file mode 100644
> > > index 0000000000000..482028f066346
> > > --- /dev/null
> > > +++ b/lib/devicetree.c
> > > @@ -0,0 +1,289 @@
> > > +/*
> > > + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> > > + *
> > > + * This work is licensed under the terms of the GNU LGPL, version 2.
> > > + */
> > > +#include "libcflat.h"
> > > +#include "libfdt/libfdt.h"
> > > +#include "devicetree.h"
> > > +
> > > +static const void *fdt;
> > > +static u32 root_nr_address_cells, root_nr_size_cells;
> > > +
> > > +const void *dt_fdt(void)
> > > +{
> > > +	return fdt;
> > > +}
> > > +
> > > +bool dt_available(void)
> > > +{
> > > +	return fdt_check_header(fdt) == 0;
> > > +}
> > > +
> > > +int dt_get_nr_cells(int fdtnode, u32 *nr_address_cells, u32 *nr_size_cells)
> > > +{
> > > +	const struct fdt_property *prop;
> > > +	u32 *nr_cells;
> > > +	int len;
> > > +
> > > +	prop = fdt_get_property(fdt, fdtnode, "#address-cells", &len);
> > > +	if (prop == NULL)
> > > +		return len;
> > > +
> > > +	nr_cells = (u32 *)prop->data;
> > > +	*nr_address_cells = fdt32_to_cpu(*nr_cells);
> > > +
> > > +	prop = fdt_get_property(fdt, fdtnode, "#size-cells", &len);
> > > +	if (prop == NULL)
> > > +		return len;
> > > +
> > > +	nr_cells = (u32 *)prop->data;
> > > +	*nr_size_cells = fdt32_to_cpu(*nr_cells);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +void dt_reg_init(struct dt_reg *reg, u32 nr_address_cells, u32 nr_size_cells)
> > > +{
> > > +	memset(reg, 0, sizeof(struct dt_reg));
> > > +	reg->nr_address_cells = nr_address_cells;
> > > +	reg->nr_size_cells = nr_size_cells;
> > > +}
> > > +
> > > +int dt_get_reg(int fdtnode, int regidx, struct dt_reg *reg)
> > > +{
> > > +	const struct fdt_property *prop;
> > > +	u32 *cells, i;
> > > +	unsigned nr_tuple_cells;
> > > +	int len;
> > > +
> > > +	prop = fdt_get_property(fdt, fdtnode, "reg", &len);
> > > +	if (prop == NULL)
> > > +		return len;
> > > +
> > > +	cells = (u32 *)prop->data;
> > > +	nr_tuple_cells = reg->nr_address_cells + reg->nr_size_cells;
> > > +	regidx *= nr_tuple_cells;
> > > +
> > > +	if (regidx + nr_tuple_cells > len/sizeof(u32))
> > 
> > Shouldn't this be >= ?
> 
> Not this time. The LHS is the total number of words needed (not an
> index).
> 

I see, you're right.

> > 
> > > +		return -FDT_ERR_NOTFOUND;
> > > +
> > > +	for (i = 0; i < reg->nr_address_cells; ++i)
> > > +		reg->address_cells[i] = fdt32_to_cpu(cells[regidx + i]);
> > > +
> > > +	regidx += reg->nr_address_cells;
> > > +	for (i = 0; i < reg->nr_size_cells; ++i)
> > > +		reg->size_cells[i] = fdt32_to_cpu(cells[regidx + i]);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +int dt_pbus_translate_node(int fdtnode, int regidx, void *reg)
> > 
> > why doesn't this function take a struct dt_pbus_reg * instead of a
> > void *?
> 
> Guess I forgot my coffee when I wrote it... I'll change that.
> 
> > 
> > > +{
> > > +	struct dt_pbus_reg *pbus_reg = (struct dt_pbus_reg *)reg;
> > > +	struct dt_reg raw_reg;
> > > +	int ret;
> > > +
> > > +	dt_reg_init(&raw_reg, root_nr_address_cells, root_nr_size_cells);
> > > +
> > > +	ret = dt_get_reg(fdtnode, regidx, &raw_reg);
> > > +	if (ret < 0)
> > > +		return ret;
> > > +
> > > +	pbus_reg->addr = dt_pbus_read_cells(raw_reg.nr_address_cells,
> > > +					    raw_reg.address_cells);
> > > +	pbus_reg->size = dt_pbus_read_cells(raw_reg.nr_size_cells,
> > > +					    raw_reg.size_cells);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +int dt_pbus_translate(const struct dt_device *dev, int regidx,
> > > +		      void *reg)
> > > +{
> > > +	return dt_pbus_translate_node(dev->fdtnode, regidx, reg);
> > > +}
> > > +
> > > +int dt_pbus_get_baseaddr(const struct dt_device *dev, dt_pbus_addr_t *base)
> > > +{
> > > +	struct dt_pbus_reg reg;
> > > +	int ret;
> > > +
> > > +	ret = dt_pbus_translate(dev, 0, &reg);
> > > +	if (ret < 0)
> > > +		return ret;
> > > +
> > > +	*base = reg.addr;
> > > +	return 0;
> > > +}
> > > +
> > > +int dt_bus_match_any(const struct dt_device *dev __unused, int fdtnode)
> > > +{
> > > +	/* matches any device with a valid node */
> > > +	return fdtnode < 0 ? fdtnode : 1;
> > > +}
> > > +
> > > +static const struct dt_bus dt_default_bus = {
> > > +	.match = dt_bus_match_any,
> > > +	.translate = dt_pbus_translate,
> > > +};
> > > +
> > > +void dt_bus_init_defaults(struct dt_bus *bus)
> > > +{
> > > +	memcpy(bus, &dt_default_bus, sizeof(struct dt_bus));
> > > +}
> > > +
> > > +void dt_device_init(struct dt_device *dev, const struct dt_bus *bus,
> > > +		    const void *info)
> > > +{
> > > +	memset(dev, 0, sizeof(struct dt_device));
> > > +	dev->bus = bus;
> > > +	dev->info = (void *)info;
> > > +}
> > > +
> > > +int dt_device_find_compatible(const struct dt_device *dev,
> > > +			      const char *compatible)
> > > +{
> > > +	int node, ret;
> > > +
> > > +	node = fdt_node_offset_by_compatible(fdt, -1, compatible);
> > > +	while (node >= 0) {
> > > +		ret = dev->bus->match(dev, node);
> > > +		if (ret < 0)
> > > +			return ret;
> > > +		else if (ret)
> > > +			break;
> > > +		node = fdt_node_offset_by_compatible(fdt, node, compatible);
> > > +	}
> > > +	return node;
> > > +}
> > > +
> > > +int dt_pbus_get_baseaddr_compatible(const char *compatible,
> > > +				    dt_pbus_addr_t *baseaddr)
> > > +{
> > > +	struct dt_device dev;
> > > +	int node, ret;
> > > +
> > > +	dt_device_init(&dev, &dt_default_bus, NULL);
> > > +
> > > +	node = dt_device_find_compatible(&dev, compatible);
> > > +	if (node < 0)
> > > +		return node;
> > > +
> > > +	dt_device_bind_node(&dev, node);
> > > +
> > > +	ret = dt_pbus_get_baseaddr(&dev, baseaddr);
> > > +	if (ret < 0)
> > > +		return ret;
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +int dt_get_memory_params(struct dt_pbus_reg *regs, int nr_regs)
> > > +{
> > > +	const char *pn = "device_type", *pv = "memory";
> > > +	int node, ret, pl = strlen(pv) + 1, nr = 0;
> > > +	struct dt_pbus_reg reg;
> > > +
> > > +	node = fdt_node_offset_by_prop_value(fdt, -1, pn, pv, pl);
> > > +
> > > +	while (node >= 0) {
> > > +
> > > +		while (nr < nr_regs) {
> > > +			ret = dt_pbus_translate_node(node, nr, &reg);
> > > +			if (ret == -FDT_ERR_NOTFOUND)
> > > +				break;
> > > +			if (ret < 0)
> > > +				return ret;
> > > +			regs[nr].addr = reg.addr;
> > > +			regs[nr].size = reg.size;
> > > +			++nr;
> > > +		}
> > > +
> > > +		node = fdt_node_offset_by_prop_value(fdt, node, pn, pv, pl);
> > > +	}
> > > +
> > > +	return node != -FDT_ERR_NOTFOUND ? node : nr;
> > > +}
> > > +
> > > +int dt_for_each_cpu_node(void (*func)(int fdtnode, u32 regval, void *info),
> > > +			 void *info)
> > > +{
> > > +	const struct fdt_property *prop;
> > > +	int cpus, cpu, ret, len;
> > > +	struct dt_reg raw_reg;
> > > +	u32 nac, nsc;
> > > +
> > > +	cpus = fdt_path_offset(fdt, "/cpus");
> > > +	if (cpus < 0)
> > > +		return cpus;
> > > +
> > > +	ret = dt_get_nr_cells(cpus, &nac, &nsc);
> > > +	if (ret < 0)
> > > +		return ret;
> > > +
> > > +	dt_reg_init(&raw_reg, nac, nsc);
> > > +
> > > +	dt_for_each_subnode(cpus, cpu) {
> > > +
> > > +		prop = fdt_get_property(fdt, cpu, "device_type", &len);
> > > +		if (prop == NULL)
> > > +			return len;
> > > +
> > > +		if (len != 4 || strcmp((char *)prop->data, "cpu"))
> > > +			continue;
> > > +
> > > +		ret = dt_get_reg(cpu, 0, &raw_reg);
> > > +		if (ret < 0)
> > > +			return ret;
> > > +
> > > +		func(cpu, raw_reg.address_cells[0], info);
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +int dt_get_bootargs(const char **bootargs)
> > > +{
> > > +	const struct fdt_property *prop;
> > > +	int node, len;
> > > +
> > > +	*bootargs = NULL;
> > > +
> > > +	node = fdt_path_offset(fdt, "/chosen");
> > > +	if (node < 0)
> > > +		return node;
> > > +
> > > +	prop = fdt_get_property(fdt, node, "bootargs", &len);
> > > +	if (prop)
> > > +		*bootargs = (char *)prop->data;
> > > +	else if (len < 0 && len != -FDT_ERR_NOTFOUND)
> > > +		return len;
> > 
> > so if you get FDT_ERR_NOTFOUND you still return success but the bootargs
> > won't be set? why?
> 
> bootargs will be NULL in that case, which is enough to know there wasn't
> any. I also wanted to be able to easily check for any other error without
> having to filter FDT_ERR_NOTFOUND at every call site. I can skip this
> special behavior though, if a more consistent interface is preferred.
> 

didn't think about the fact that it's valid not to specify any bootargs.
Not sure if it's nicer to return an empty string or NULL, but it works
either way.

> > 
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +int dt_init(const void *fdt_ptr)
> > > +{
> > > +	struct dt_bus *defbus = (struct dt_bus *)&dt_default_bus;
> > > +	int root, ret;
> > > +
> > > +	ret = fdt_check_header(fdt_ptr);
> > > +	if (ret < 0)
> > > +		return ret;
> > > +	fdt = fdt_ptr;
> > > +
> > > +	root = fdt_path_offset(fdt, "/");
> > > +	if (root < 0)
> > > +		return root;
> > > +
> > > +	ret = dt_get_nr_cells(root, &root_nr_address_cells,
> > > +				    &root_nr_size_cells);
> > > +	if (ret < 0)
> > > +		return ret;
> > > +
> > > +	defbus->nr_address_cells = root_nr_address_cells;
> > > +	defbus->nr_size_cells = root_nr_size_cells;
> > > +
> > > +	return 0;
> > > +}
> > > diff --git a/lib/devicetree.h b/lib/devicetree.h
> > > new file mode 100644
> > > index 0000000000000..032b5497f9db1
> > > --- /dev/null
> > > +++ b/lib/devicetree.h
> > > @@ -0,0 +1,230 @@
> > > +#ifndef _DEVICETREE_H_
> > > +#define _DEVICETREE_H_
> > > +/*
> > > + * devicetree builds on libfdt to implement abstractions and accessors
> > > + * for Linux required device tree content. The accessors provided are
> > > + * common across architectures. See section III of the kernel doc
> > > + * Documentation/devicetree/booting-without-of.txt
> > > + *
> > > + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> > > + *
> > > + * This work is licensed under the terms of the GNU LGPL, version 2.
> > > + */
> > > +#include "libcflat.h"
> > > +#include "libfdt/libfdt.h"
> > > +
> > > +/**********************************************************************
> > > + * devicetree init and libfdt helpers
> > > + **********************************************************************/
> > > +
> > > +/* dt_init initializes devicetree with a pointer to an fdt, @fdt_ptr */
> > > +extern int dt_init(const void *fdt_ptr);
> > > +
> > > +/* get the fdt pointer that devicetree is using */
> > > +const void *dt_fdt(void);
> > 
> > nit: why no extern here?
> 
> Just forgot it. Will add it.
> 
> > 
> > > +
> > > +/* check for an initialized, valid devicetree */
> > > +extern bool dt_available(void);
> > > +
> > > +/* traverse child nodes */
> > > +#define dt_for_each_subnode(n, s)					\
> > > +	for (s = fdt_first_subnode(dt_fdt(), n);			\
> > > +	     s != -FDT_ERR_NOTFOUND;					\
> > > +	     s = fdt_next_subnode(dt_fdt(), s))
> > > +
> > > +/**********************************************************************
> > > + * Abstractions for required node types and properties
> > > + **********************************************************************/
> > > +
> > > +struct dt_device {
> > > +	int fdtnode;
> > > +	const struct dt_bus *bus;
> > > +
> > > +	/*
> > > +	 * info is a pointer to device specific data, which may be
> > > +	 * used by the bus match() and translate() functions
> > > +	 */
> > > +	void *info;
> > > +};
> > > +
> > > +struct dt_bus {
> > > +	/*
> > > +	 * match a device @dev to an fdt node @fdtnode
> > > +	 * returns
> > > +	 *  - a positive value on match
> > > +	 *  - zero on no match
> > > +	 *  - a negative FDT_ERR_* value on failure
> > > +	 */
> > > +	int (*match)(const struct dt_device *dev, int fdtnode);
> > > +
> > > +	/*
> > > +	 * translate the @regidx'th "address size" tuple of
> > > +	 * @dev's fdt node's "reg" property, and store the result
> > > +	 * in @reg, a bus specific structure
> > > +	 * returns
> > > +	 *  - zero on success
> > > +	 *  - a negative FDT_ERR_* value on failure
> > > +	 */
> > > +	int (*translate)(const struct dt_device *dev, int regidx, void *reg);
> > > +
> > > +	/* the bus #address-cells and #size-cells properties */
> > > +	u32 nr_address_cells, nr_size_cells;
> > > +};
> > > +
> > > +/* dt_bus_match_any matches any fdt node, i.e. it always returns true */
> > > +extern int dt_bus_match_any(const struct dt_device *dev, int fdtnode);
> > > +
> > > +/* the processor bus (pbus) address type and register tuple */
> > > +typedef u64 dt_pbus_addr_t;
> > > +struct dt_pbus_reg {
> > > +	dt_pbus_addr_t addr;
> > > +	dt_pbus_addr_t size;
> > > +};
> > > +
> > > +static inline dt_pbus_addr_t dt_pbus_read_cells(u32 nr_cells, u32 *cells)
> > > +{
> > > +	return nr_cells == 2 ? ((u64)cells[0] << 32) | cells[1]
> > > +		: nr_cells == 1 ? cells[0] : (~0ULL);
> > 
> > Why the tertiary operator here?  A simple if or select statement should
> > make the code much easier to read and you don't seem to handle
> 
> I'll change it.
> 
> > #address-cells == 4or #size-cells == 4, despite the fact that you define
> > MAX_ADDRESS_CELLS=4 etc.  This seems a bit weird to me.
> 
> The default translator only knows how to handle nr_cells==2 or
> nr_cells==1. DT may have nodes with nr_cells > 2 (up to 4), but users
> will have to provide their own translators for those.
> 

ok

> > 
> > > +}
> > > +
> > > +/*
> > > + * dt_pbus_translate translates device node regs for the
> > > + * processor bus using the root node's #address-cells and
> > > + * #size-cells and dt_pbus_read_cells()
> > > + * returns
> > > + *  - zero on success
> > > + *  - a negative FDT_ERR_* value on failure
> > > + */
> > > +extern int dt_pbus_translate(const struct dt_device *dev, int regidx,
> > > +			     void *reg);
> > > +
> > > +/*
> > > + * dt_pbus_translate_node is the same as dt_pbus_translate but
> > > + * operates on an fdt node instead of a dt_device
> > > + */
> > > +extern int dt_pbus_translate_node(int fdtnode, int regidx, void *reg);
> > > +
> > > +/*
> > > + * dt_pbus_get_baseaddr is a shortcut for
> > > + *     dt_pbus_translate(dev, 0, &reg);
> > > + *     *base = reg.addr;
> > > + * returns
> > > + *  - zero on success
> > > + *  - a negative FDT_ERR_* value on failure
> > > + */
> > > +extern int dt_pbus_get_baseaddr(const struct dt_device *dev,
> > > +				dt_pbus_addr_t *base);
> > > +
> > > +/*
> > > + * dt_bus_init_defaults initializes @bus with
> > > + *  match		<- dt_bus_match_any
> > > + *  translate		<- dt_pbus_translate
> > > + *  nr_address_cells	<- #address-cells of the root node
> > > + *  nr_size_cells	<- #size-cells of the root node
> > > + */
> > > +extern void dt_bus_init_defaults(struct dt_bus *bus);
> > > +
> > > +/*
> > > + * dt_device_init initializes a dt_device with the given parameters
> > > + */
> > > +extern void dt_device_init(struct dt_device *dev, const struct dt_bus *bus,
> > > +			   const void *info);
> > > +
> > > +static inline void dt_device_bind_node(struct dt_device *dev, int fdtnode)
> > > +{
> > > +	dev->fdtnode = fdtnode;
> > > +}
> > > +
> > > +/*
> > > + * dt_device_find_compatible finds a @compatible node
> > > + * returns
> > > + *  - node (>= 0) on success
> > > + *  - a negative FDT_ERR_* value on failure
> > > + */
> > > +extern int dt_device_find_compatible(const struct dt_device *dev,
> > > +				     const char *compatible);
> > > +
> > > +/*
> > > + * dt_pbus_get_baseaddr_compatible simply bundles many functions into
> > > + * one. It finds the first @compatible fdt node and then translates the
> > > + * 0th reg tuple (the base address) using the processor bus translation,
> > > + * and finally stores that address in @baseaddr.
> > > + * returns
> > > + *  - zero on success
> > > + *  - a negative FDT_ERR_* value on failure
> > > + */
> > > +extern int dt_pbus_get_baseaddr_compatible(const char *compatible,
> > > +					   dt_pbus_addr_t *baseaddr);
> > > +
> > > +/**********************************************************************
> > > + * Low-level accessors for required node types and properties
> > > + **********************************************************************/
> > > +
> > > +/*
> > > + * dt_get_nr_cells sets @nr_address_cells and @nr_size_cells to the
> > > + * #address-cells and #size-cells properties of @fdtnode
> > > + * returns
> > > + *  - zero on success
> > > + *  - a negative FDT_ERR_* value on failure
> > > + */
> > > +extern int dt_get_nr_cells(int fdtnode, u32 *nr_address_cells,
> > > +					u32 *nr_size_cells);
> > > +
> > > +/* dt_reg is a structure for "raw" reg tuples */
> > > +#define MAX_ADDRESS_CELLS	4
> > > +#define MAX_SIZE_CELLS		4
> > > +struct dt_reg {
> > > +	u32 nr_address_cells, nr_size_cells;
> > > +	u32 address_cells[MAX_ADDRESS_CELLS];
> > > +	u32 size_cells[MAX_SIZE_CELLS];
> > > +};
> > > +
> > > +/*
> > > + * dt_reg_init initialize a dt_reg struct to zero and sets
> > > + * nr_address_cells and nr_size_cells to @nr_address_cells and
> > > + * @nr_size_cells respectively.
> > > + */
> > > +extern void dt_reg_init(struct dt_reg *reg, u32 nr_address_cells,
> > > +					    u32 nr_size_cells);
> > > +
> > > +/*
> > > + * dt_get_reg gets the @regidx'th reg tuple of @fdtnode's reg property
> > > + * and stores it in @reg. @reg must be initialized.
> > > + * returns
> > > + *  - zero on success
> > > + *  - a negative FDT_ERR_* value on failure
> > > + */
> > > +extern int dt_get_reg(int fdtnode, int regidx, struct dt_reg *reg);
> > > +
> > > +/**********************************************************************
> > > + * High-level accessors for required node types and properties
> > > + **********************************************************************/
> > > +
> > > +/*
> > > + * dt_get_bootargs gets a pointer to /chosen/bootargs
> > > + * returns
> > > + *  - zero on success
> > > + *  - a negative FDT_ERR_* value on failure
> > > + */
> > > +extern int dt_get_bootargs(const char **bootargs);
> > > +
> > > +/*
> > > + * dt_get_memory_params gets the memory parameters from the /memory node(s)
> > > + * storing each memory region ("address size" tuple) in consecutive entries
> > > + * of @regs, up to @nr_regs
> > > + * returns
> > > + *  - number of memory regions found on success
> > > + *  - a negative FDT_ERR_* value on failure
> > > + */
> > > +extern int dt_get_memory_params(struct dt_pbus_reg *regs, int nr_regs);
> > > +
> > > +/*
> > > + * dt_for_each_cpu_node runs @func on each cpu node in the /cpus node
> > > + * passing it its fdt node, its reg property value, and @info
> > > + *  - zero on success
> > > + *  - a negative FDT_ERR_* value on failure
> > > + */
> > > +extern int dt_for_each_cpu_node(void (*func)(int fdtnode, u32 regval,
> > > +				void *info), void *info);
> > > +
> > > +#endif /* _DEVICETREE_H_ */
> > > diff --git a/lib/libcflat.h b/lib/libcflat.h
> > > index 76448a33cde5f..99d1cd533dd03 100644
> > > --- a/lib/libcflat.h
> > > +++ b/lib/libcflat.h
> > > @@ -22,6 +22,8 @@
> > >  
> > >  #include <stdarg.h>
> > >  
> > > +#define __unused __attribute__((__unused__))
> > > +
> > >  typedef unsigned char u8;
> > >  typedef signed char s8;
> > >  typedef unsigned short u16;
> > > -- 
> > > 1.8.1.4
> > > 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 10/19] Introduce asm-generic/*.h files
  2014-06-09  9:54         ` Andrew Jones
@ 2014-06-09 11:39           ` Andrew Jones
  2014-06-09 12:34             ` Christoffer Dall
  0 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-06-09 11:39 UTC (permalink / raw)
  To: Christoffer Dall; +Cc: kvmarm, kvm

On Mon, Jun 09, 2014 at 11:54:48AM +0200, Andrew Jones wrote:
> On Mon, Jun 09, 2014 at 11:08:32AM +0200, Christoffer Dall wrote:
> > On Mon, Jun 09, 2014 at 10:23:27AM +0200, Andrew Jones wrote:
> > > On Fri, Jun 06, 2014 at 08:39:09PM +0200, Christoffer Dall wrote:
> > > > On Thu, Apr 10, 2014 at 06:56:51PM +0200, Andrew Jones wrote:
> > > > > Architecture neutral code may need to call low-level io accessors,
> > > > > or use spinlocks. Create a generic io.h to ensure those accessors
> > > > > are defined, and a generic spinlock.h that complains when included,
> > > > > as we can't write a generic spinlock. These files can be overridden
> > > > > or extended by architecture specific versions placed in
> > > > > lib/$ARCH/asm/.
> > > > > 
> > > > > Signed-off-by: Andrew Jones <drjones@redhat.com>
> > > > > ---
> > > > > v4: introduce lib/asm symlink to get rid of #ifdef __arm__,
> > > > >     add spinlock.h too
> > > > > v3: wrt to io.h (was libio.[ch]) only
> > > > >     - get rid of CONFIG_64BIT, replace with asserts
> > > > >     - get rid of {read,write}_len() [libio.c]
> > > > >     - fix bad *64_to_cpu macros
> > > > > ---
> > > > >  .gitignore                 |   1 +
> > > > >  Makefile                   |   6 +-
> > > > >  configure                  |  11 ++++
> > > > >  lib/asm-generic/io.h       | 154 +++++++++++++++++++++++++++++++++++++++++++++
> > > > >  lib/asm-generic/spinlock.h |   4 ++
> > > > >  5 files changed, 173 insertions(+), 3 deletions(-)
> > > > >  create mode 100644 lib/asm-generic/io.h
> > > > >  create mode 100644 lib/asm-generic/spinlock.h
> > > > > 
> > > > > diff --git a/.gitignore b/.gitignore
> > > > > index 775d0dfd8263e..e21939a8771e9 100644
> > > > > --- a/.gitignore
> > > > > +++ b/.gitignore
> > > > > @@ -9,6 +9,7 @@ patches
> > > > >  .stgit-*
> > > > >  cscope.*
> > > > >  *.swp
> > > > > +/lib/asm
> > > > >  /config.mak
> > > > >  /*-run
> > > > >  /test.log
> > > > > diff --git a/Makefile b/Makefile
> > > > > index fba58e36f272f..51cacdac00615 100644
> > > > > --- a/Makefile
> > > > > +++ b/Makefile
> > > > > @@ -76,11 +76,11 @@ libfdt_clean:
> > > > >  	$(LIBFDT_objdir)/.*.d
> > > > >  
> > > > >  distclean: clean libfdt_clean
> > > > > -	$(RM) config.mak $(TEST_DIR)-run test.log msr.out cscope.*
> > > > > +	$(RM) lib/asm config.mak $(TEST_DIR)-run test.log msr.out cscope.*
> > > > >  
> > > > > -cscope: common_dirs = lib lib/libfdt
> > > > > +cscope: common_dirs = lib lib/libfdt lib/asm lib/asm-generic
> > > > >  cscope:
> > > > >  	$(RM) ./cscope.*
> > > > > -	find $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
> > > > > +	find -L $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
> > > > >  		-name '*.[chsS]' -print | sed 's,^\./,,' > ./cscope.files
> > > > >  	cscope -bk
> > > > > diff --git a/configure b/configure
> > > > > index 6cfc64943f6e6..8a81bf92e27b7 100755
> > > > > --- a/configure
> > > > > +++ b/configure
> > > > > @@ -95,6 +95,17 @@ if [ $exit -eq 0 ]; then
> > > > >  fi
> > > > >  rm -f lib_test.c
> > > > >  
> > > > > +# link lib/asm for the architecture
> > > > > +rm -f lib/asm
> > > > > +asm=asm-generic
> > > > > +if [ -d lib/$arch/asm ]; then
> > > > > +	asm=$arch/asm
> > > > > +elif [ -d lib/$testdir/asm ]; then
> > > > > +	asm=$testdir/asm
> > > > 
> > > > why do you need this elif?  can you not make sure arch is always set?
> > > 
> > > arch is always set, but there's a chance some arch may not add it's own
> > > lib/$arch dir. It's a pretty small chance... but the elif shouldn't hurt.
> > > 
> > If we don't have any code that uses this scheme now then let's now have
> > Makefile rules that encourages non-standard behavior (unless I'm missing
> > the point and this provides a 'feature' for specific archs or something
> > like that).
> >
> 
> It would be something of a feature for some imaginary arch. However, as
> that imaginary arch doesn't exist right now, then I'm fine removing it.
> Whoever makes the imaginary arch a reality can bring it back.
> 

Oh wait, it's actually not imaginary (just unused). x86 is an example of
such a testdir that doesn't == arch. So, if either i386 or x86_64 wanted
to use lib/asm, then they need this elif.

drew

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 10/19] Introduce asm-generic/*.h files
  2014-06-09 11:39           ` Andrew Jones
@ 2014-06-09 12:34             ` Christoffer Dall
  2014-06-09 13:52               ` Andrew Jones
  0 siblings, 1 reply; 54+ messages in thread
From: Christoffer Dall @ 2014-06-09 12:34 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On Mon, Jun 09, 2014 at 01:39:06PM +0200, Andrew Jones wrote:
> On Mon, Jun 09, 2014 at 11:54:48AM +0200, Andrew Jones wrote:
> > On Mon, Jun 09, 2014 at 11:08:32AM +0200, Christoffer Dall wrote:
> > > On Mon, Jun 09, 2014 at 10:23:27AM +0200, Andrew Jones wrote:
> > > > On Fri, Jun 06, 2014 at 08:39:09PM +0200, Christoffer Dall wrote:
> > > > > On Thu, Apr 10, 2014 at 06:56:51PM +0200, Andrew Jones wrote:
> > > > > > Architecture neutral code may need to call low-level io accessors,
> > > > > > or use spinlocks. Create a generic io.h to ensure those accessors
> > > > > > are defined, and a generic spinlock.h that complains when included,
> > > > > > as we can't write a generic spinlock. These files can be overridden
> > > > > > or extended by architecture specific versions placed in
> > > > > > lib/$ARCH/asm/.
> > > > > > 
> > > > > > Signed-off-by: Andrew Jones <drjones@redhat.com>
> > > > > > ---
> > > > > > v4: introduce lib/asm symlink to get rid of #ifdef __arm__,
> > > > > >     add spinlock.h too
> > > > > > v3: wrt to io.h (was libio.[ch]) only
> > > > > >     - get rid of CONFIG_64BIT, replace with asserts
> > > > > >     - get rid of {read,write}_len() [libio.c]
> > > > > >     - fix bad *64_to_cpu macros
> > > > > > ---
> > > > > >  .gitignore                 |   1 +
> > > > > >  Makefile                   |   6 +-
> > > > > >  configure                  |  11 ++++
> > > > > >  lib/asm-generic/io.h       | 154 +++++++++++++++++++++++++++++++++++++++++++++
> > > > > >  lib/asm-generic/spinlock.h |   4 ++
> > > > > >  5 files changed, 173 insertions(+), 3 deletions(-)
> > > > > >  create mode 100644 lib/asm-generic/io.h
> > > > > >  create mode 100644 lib/asm-generic/spinlock.h
> > > > > > 
> > > > > > diff --git a/.gitignore b/.gitignore
> > > > > > index 775d0dfd8263e..e21939a8771e9 100644
> > > > > > --- a/.gitignore
> > > > > > +++ b/.gitignore
> > > > > > @@ -9,6 +9,7 @@ patches
> > > > > >  .stgit-*
> > > > > >  cscope.*
> > > > > >  *.swp
> > > > > > +/lib/asm
> > > > > >  /config.mak
> > > > > >  /*-run
> > > > > >  /test.log
> > > > > > diff --git a/Makefile b/Makefile
> > > > > > index fba58e36f272f..51cacdac00615 100644
> > > > > > --- a/Makefile
> > > > > > +++ b/Makefile
> > > > > > @@ -76,11 +76,11 @@ libfdt_clean:
> > > > > >  	$(LIBFDT_objdir)/.*.d
> > > > > >  
> > > > > >  distclean: clean libfdt_clean
> > > > > > -	$(RM) config.mak $(TEST_DIR)-run test.log msr.out cscope.*
> > > > > > +	$(RM) lib/asm config.mak $(TEST_DIR)-run test.log msr.out cscope.*
> > > > > >  
> > > > > > -cscope: common_dirs = lib lib/libfdt
> > > > > > +cscope: common_dirs = lib lib/libfdt lib/asm lib/asm-generic
> > > > > >  cscope:
> > > > > >  	$(RM) ./cscope.*
> > > > > > -	find $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
> > > > > > +	find -L $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
> > > > > >  		-name '*.[chsS]' -print | sed 's,^\./,,' > ./cscope.files
> > > > > >  	cscope -bk
> > > > > > diff --git a/configure b/configure
> > > > > > index 6cfc64943f6e6..8a81bf92e27b7 100755
> > > > > > --- a/configure
> > > > > > +++ b/configure
> > > > > > @@ -95,6 +95,17 @@ if [ $exit -eq 0 ]; then
> > > > > >  fi
> > > > > >  rm -f lib_test.c
> > > > > >  
> > > > > > +# link lib/asm for the architecture
> > > > > > +rm -f lib/asm
> > > > > > +asm=asm-generic
> > > > > > +if [ -d lib/$arch/asm ]; then
> > > > > > +	asm=$arch/asm
> > > > > > +elif [ -d lib/$testdir/asm ]; then
> > > > > > +	asm=$testdir/asm
> > > > > 
> > > > > why do you need this elif?  can you not make sure arch is always set?
> > > > 
> > > > arch is always set, but there's a chance some arch may not add it's own
> > > > lib/$arch dir. It's a pretty small chance... but the elif shouldn't hurt.
> > > > 
> > > If we don't have any code that uses this scheme now then let's now have
> > > Makefile rules that encourages non-standard behavior (unless I'm missing
> > > the point and this provides a 'feature' for specific archs or something
> > > like that).
> > >
> > 
> > It would be something of a feature for some imaginary arch. However, as
> > that imaginary arch doesn't exist right now, then I'm fine removing it.
> > Whoever makes the imaginary arch a reality can bring it back.
> > 
> 
> Oh wait, it's actually not imaginary (just unused). x86 is an example of
> such a testdir that doesn't == arch. So, if either i386 or x86_64 wanted
> to use lib/asm, then they need this elif.
> 
ah, ok.  I'll shut up then.
-Christoffer

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 10/19] Introduce asm-generic/*.h files
  2014-06-09 12:34             ` Christoffer Dall
@ 2014-06-09 13:52               ` Andrew Jones
  2014-06-09 15:34                 ` Christoffer Dall
  0 siblings, 1 reply; 54+ messages in thread
From: Andrew Jones @ 2014-06-09 13:52 UTC (permalink / raw)
  To: Christoffer Dall; +Cc: kvmarm, kvm

On Mon, Jun 09, 2014 at 02:34:03PM +0200, Christoffer Dall wrote:
> On Mon, Jun 09, 2014 at 01:39:06PM +0200, Andrew Jones wrote:
> > On Mon, Jun 09, 2014 at 11:54:48AM +0200, Andrew Jones wrote:
> > > On Mon, Jun 09, 2014 at 11:08:32AM +0200, Christoffer Dall wrote:
> > > > On Mon, Jun 09, 2014 at 10:23:27AM +0200, Andrew Jones wrote:
> > > > > On Fri, Jun 06, 2014 at 08:39:09PM +0200, Christoffer Dall wrote:
> > > > > > On Thu, Apr 10, 2014 at 06:56:51PM +0200, Andrew Jones wrote:
> > > > > > > Architecture neutral code may need to call low-level io accessors,
> > > > > > > or use spinlocks. Create a generic io.h to ensure those accessors
> > > > > > > are defined, and a generic spinlock.h that complains when included,
> > > > > > > as we can't write a generic spinlock. These files can be overridden
> > > > > > > or extended by architecture specific versions placed in
> > > > > > > lib/$ARCH/asm/.
> > > > > > > 
> > > > > > > Signed-off-by: Andrew Jones <drjones@redhat.com>
> > > > > > > ---
> > > > > > > v4: introduce lib/asm symlink to get rid of #ifdef __arm__,
> > > > > > >     add spinlock.h too
> > > > > > > v3: wrt to io.h (was libio.[ch]) only
> > > > > > >     - get rid of CONFIG_64BIT, replace with asserts
> > > > > > >     - get rid of {read,write}_len() [libio.c]
> > > > > > >     - fix bad *64_to_cpu macros
> > > > > > > ---
> > > > > > >  .gitignore                 |   1 +
> > > > > > >  Makefile                   |   6 +-
> > > > > > >  configure                  |  11 ++++
> > > > > > >  lib/asm-generic/io.h       | 154 +++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >  lib/asm-generic/spinlock.h |   4 ++
> > > > > > >  5 files changed, 173 insertions(+), 3 deletions(-)
> > > > > > >  create mode 100644 lib/asm-generic/io.h
> > > > > > >  create mode 100644 lib/asm-generic/spinlock.h
> > > > > > > 
> > > > > > > diff --git a/.gitignore b/.gitignore
> > > > > > > index 775d0dfd8263e..e21939a8771e9 100644
> > > > > > > --- a/.gitignore
> > > > > > > +++ b/.gitignore
> > > > > > > @@ -9,6 +9,7 @@ patches
> > > > > > >  .stgit-*
> > > > > > >  cscope.*
> > > > > > >  *.swp
> > > > > > > +/lib/asm
> > > > > > >  /config.mak
> > > > > > >  /*-run
> > > > > > >  /test.log
> > > > > > > diff --git a/Makefile b/Makefile
> > > > > > > index fba58e36f272f..51cacdac00615 100644
> > > > > > > --- a/Makefile
> > > > > > > +++ b/Makefile
> > > > > > > @@ -76,11 +76,11 @@ libfdt_clean:
> > > > > > >  	$(LIBFDT_objdir)/.*.d
> > > > > > >  
> > > > > > >  distclean: clean libfdt_clean
> > > > > > > -	$(RM) config.mak $(TEST_DIR)-run test.log msr.out cscope.*
> > > > > > > +	$(RM) lib/asm config.mak $(TEST_DIR)-run test.log msr.out cscope.*
> > > > > > >  
> > > > > > > -cscope: common_dirs = lib lib/libfdt
> > > > > > > +cscope: common_dirs = lib lib/libfdt lib/asm lib/asm-generic
> > > > > > >  cscope:
> > > > > > >  	$(RM) ./cscope.*
> > > > > > > -	find $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
> > > > > > > +	find -L $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
> > > > > > >  		-name '*.[chsS]' -print | sed 's,^\./,,' > ./cscope.files
> > > > > > >  	cscope -bk
> > > > > > > diff --git a/configure b/configure
> > > > > > > index 6cfc64943f6e6..8a81bf92e27b7 100755
> > > > > > > --- a/configure
> > > > > > > +++ b/configure
> > > > > > > @@ -95,6 +95,17 @@ if [ $exit -eq 0 ]; then
> > > > > > >  fi
> > > > > > >  rm -f lib_test.c
> > > > > > >  
> > > > > > > +# link lib/asm for the architecture
> > > > > > > +rm -f lib/asm
> > > > > > > +asm=asm-generic
> > > > > > > +if [ -d lib/$arch/asm ]; then
> > > > > > > +	asm=$arch/asm
> > > > > > > +elif [ -d lib/$testdir/asm ]; then
> > > > > > > +	asm=$testdir/asm
> > > > > > 
> > > > > > why do you need this elif?  can you not make sure arch is always set?
> > > > > 
> > > > > arch is always set, but there's a chance some arch may not add it's own
> > > > > lib/$arch dir. It's a pretty small chance... but the elif shouldn't hurt.
> > > > > 
> > > > If we don't have any code that uses this scheme now then let's now have
> > > > Makefile rules that encourages non-standard behavior (unless I'm missing
> > > > the point and this provides a 'feature' for specific archs or something
> > > > like that).
> > > >
> > > 
> > > It would be something of a feature for some imaginary arch. However, as
> > > that imaginary arch doesn't exist right now, then I'm fine removing it.
> > > Whoever makes the imaginary arch a reality can bring it back.
> > > 
> > 
> > Oh wait, it's actually not imaginary (just unused). x86 is an example of
> > such a testdir that doesn't == arch. So, if either i386 or x86_64 wanted
> > to use lib/asm, then they need this elif.
> > 
> ah, ok.  I'll shut up then.

Before you go completely silent on it, how about an Ack?

drew

> -Christoffer
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 10/19] Introduce asm-generic/*.h files
  2014-06-09 13:52               ` Andrew Jones
@ 2014-06-09 15:34                 ` Christoffer Dall
  0 siblings, 0 replies; 54+ messages in thread
From: Christoffer Dall @ 2014-06-09 15:34 UTC (permalink / raw)
  To: Andrew Jones; +Cc: kvmarm, kvm

On 9 June 2014 15:52, Andrew Jones <drjones@redhat.com> wrote:
> On Mon, Jun 09, 2014 at 02:34:03PM +0200, Christoffer Dall wrote:
>> On Mon, Jun 09, 2014 at 01:39:06PM +0200, Andrew Jones wrote:
>> > On Mon, Jun 09, 2014 at 11:54:48AM +0200, Andrew Jones wrote:
>> > > On Mon, Jun 09, 2014 at 11:08:32AM +0200, Christoffer Dall wrote:
>> > > > On Mon, Jun 09, 2014 at 10:23:27AM +0200, Andrew Jones wrote:
>> > > > > On Fri, Jun 06, 2014 at 08:39:09PM +0200, Christoffer Dall wrote:
>> > > > > > On Thu, Apr 10, 2014 at 06:56:51PM +0200, Andrew Jones wrote:
>> > > > > > > Architecture neutral code may need to call low-level io accessors,
>> > > > > > > or use spinlocks. Create a generic io.h to ensure those accessors
>> > > > > > > are defined, and a generic spinlock.h that complains when included,
>> > > > > > > as we can't write a generic spinlock. These files can be overridden
>> > > > > > > or extended by architecture specific versions placed in
>> > > > > > > lib/$ARCH/asm/.
>> > > > > > >
>> > > > > > > Signed-off-by: Andrew Jones <drjones@redhat.com>
>> > > > > > > ---
>> > > > > > > v4: introduce lib/asm symlink to get rid of #ifdef __arm__,
>> > > > > > >     add spinlock.h too
>> > > > > > > v3: wrt to io.h (was libio.[ch]) only
>> > > > > > >     - get rid of CONFIG_64BIT, replace with asserts
>> > > > > > >     - get rid of {read,write}_len() [libio.c]
>> > > > > > >     - fix bad *64_to_cpu macros
>> > > > > > > ---
>> > > > > > >  .gitignore                 |   1 +
>> > > > > > >  Makefile                   |   6 +-
>> > > > > > >  configure                  |  11 ++++
>> > > > > > >  lib/asm-generic/io.h       | 154 +++++++++++++++++++++++++++++++++++++++++++++
>> > > > > > >  lib/asm-generic/spinlock.h |   4 ++
>> > > > > > >  5 files changed, 173 insertions(+), 3 deletions(-)
>> > > > > > >  create mode 100644 lib/asm-generic/io.h
>> > > > > > >  create mode 100644 lib/asm-generic/spinlock.h
>> > > > > > >
>> > > > > > > diff --git a/.gitignore b/.gitignore
>> > > > > > > index 775d0dfd8263e..e21939a8771e9 100644
>> > > > > > > --- a/.gitignore
>> > > > > > > +++ b/.gitignore
>> > > > > > > @@ -9,6 +9,7 @@ patches
>> > > > > > >  .stgit-*
>> > > > > > >  cscope.*
>> > > > > > >  *.swp
>> > > > > > > +/lib/asm
>> > > > > > >  /config.mak
>> > > > > > >  /*-run
>> > > > > > >  /test.log
>> > > > > > > diff --git a/Makefile b/Makefile
>> > > > > > > index fba58e36f272f..51cacdac00615 100644
>> > > > > > > --- a/Makefile
>> > > > > > > +++ b/Makefile
>> > > > > > > @@ -76,11 +76,11 @@ libfdt_clean:
>> > > > > > >   $(LIBFDT_objdir)/.*.d
>> > > > > > >
>> > > > > > >  distclean: clean libfdt_clean
>> > > > > > > - $(RM) config.mak $(TEST_DIR)-run test.log msr.out cscope.*
>> > > > > > > + $(RM) lib/asm config.mak $(TEST_DIR)-run test.log msr.out cscope.*
>> > > > > > >
>> > > > > > > -cscope: common_dirs = lib lib/libfdt
>> > > > > > > +cscope: common_dirs = lib lib/libfdt lib/asm lib/asm-generic
>> > > > > > >  cscope:
>> > > > > > >   $(RM) ./cscope.*
>> > > > > > > - find $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
>> > > > > > > + find -L $(TEST_DIR) lib/$(TEST_DIR) $(common_dirs) -maxdepth 1 \
>> > > > > > >           -name '*.[chsS]' -print | sed 's,^\./,,' > ./cscope.files
>> > > > > > >   cscope -bk
>> > > > > > > diff --git a/configure b/configure
>> > > > > > > index 6cfc64943f6e6..8a81bf92e27b7 100755
>> > > > > > > --- a/configure
>> > > > > > > +++ b/configure
>> > > > > > > @@ -95,6 +95,17 @@ if [ $exit -eq 0 ]; then
>> > > > > > >  fi
>> > > > > > >  rm -f lib_test.c
>> > > > > > >
>> > > > > > > +# link lib/asm for the architecture
>> > > > > > > +rm -f lib/asm
>> > > > > > > +asm=asm-generic
>> > > > > > > +if [ -d lib/$arch/asm ]; then
>> > > > > > > + asm=$arch/asm
>> > > > > > > +elif [ -d lib/$testdir/asm ]; then
>> > > > > > > + asm=$testdir/asm
>> > > > > >
>> > > > > > why do you need this elif?  can you not make sure arch is always set?
>> > > > >
>> > > > > arch is always set, but there's a chance some arch may not add it's own
>> > > > > lib/$arch dir. It's a pretty small chance... but the elif shouldn't hurt.
>> > > > >
>> > > > If we don't have any code that uses this scheme now then let's now have
>> > > > Makefile rules that encourages non-standard behavior (unless I'm missing
>> > > > the point and this provides a 'feature' for specific archs or something
>> > > > like that).
>> > > >
>> > >
>> > > It would be something of a feature for some imaginary arch. However, as
>> > > that imaginary arch doesn't exist right now, then I'm fine removing it.
>> > > Whoever makes the imaginary arch a reality can bring it back.
>> > >
>> >
>> > Oh wait, it's actually not imaginary (just unused). x86 is an example of
>> > such a testdir that doesn't == arch. So, if either i386 or x86_64 wanted
>> > to use lib/asm, then they need this elif.
>> >
>> ah, ok.  I'll shut up then.
>
> Before you go completely silent on it, how about an Ack?
>
ack

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 01/19] remove unused files
  2014-06-09  8:11     ` Andrew Jones
@ 2014-06-25 12:14       ` Alexander Graf
  0 siblings, 0 replies; 54+ messages in thread
From: Alexander Graf @ 2014-06-25 12:14 UTC (permalink / raw)
  To: Andrew Jones, Christoffer Dall; +Cc: kvmarm, kvm, pbonzini


On 09.06.14 10:11, Andrew Jones wrote:
> On Fri, Jun 06, 2014 at 08:37:26PM +0200, Christoffer Dall wrote:
>> On Thu, Apr 10, 2014 at 06:56:42PM +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>
>> Sounds reasonable enough for me, but you probably want an acked-by from
>> the people who actually know if they should care about these files or
>> not.
> Agreed. Alex? Paolo?

We haven't managed to revive the test cases in all the years, so yeah :(

Acked-by: Alexander Graf <agraf@suse.de>


Alex


^ permalink raw reply	[flat|nested] 54+ messages in thread

end of thread, other threads:[~2014-06-25 12:14 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
2014-04-10 16:56 ` [PATCH v4 01/19] remove unused files Andrew Jones
2014-06-06 18:37   ` Christoffer Dall
2014-06-09  8:11     ` Andrew Jones
2014-06-25 12:14       ` Alexander Graf
2014-04-10 16:56 ` [PATCH v4 02/19] makefile and run_tests tweaks Andrew Jones
2014-06-06 18:37   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 03/19] clean root dir of all x86-ness Andrew Jones
2014-06-06 18:37   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 04/19] add distclean target and gitignore more Andrew Jones
2014-06-06 18:37   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 05/19] add 'make cscope' support Andrew Jones
2014-06-06 18:38   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 07/19] libfdt: get libfdt to build Andrew Jones
2014-06-06 18:38   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 08/19] add support for Linux device trees Andrew Jones
2014-06-06 18:38   ` Christoffer Dall
2014-06-09 10:18     ` Andrew Jones
2014-06-09 10:45       ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 09/19] libcflat: add abort() and assert() Andrew Jones
2014-06-06 18:38   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 10/19] Introduce asm-generic/*.h files Andrew Jones
2014-06-06 18:39   ` Christoffer Dall
2014-06-09  8:23     ` Andrew Jones
2014-06-09  9:08       ` Christoffer Dall
2014-06-09  9:54         ` Andrew Jones
2014-06-09 11:39           ` Andrew Jones
2014-06-09 12:34             ` Christoffer Dall
2014-06-09 13:52               ` Andrew Jones
2014-06-09 15:34                 ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 11/19] add minimal virtio support for devtree virtio-mmio Andrew Jones
2014-06-06 18:39   ` Christoffer Dall
2014-06-09  9:02     ` Andrew Jones
2014-06-09  9:14       ` Christoffer Dall
2014-06-09 10:21         ` Andrew Jones
2014-04-10 16:56 ` [PATCH v4 12/19] Introduce virtio-testdev Andrew Jones
2014-06-06 18:39   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 13/19] libcflat: clean up libcflat.h and add string.h Andrew Jones
2014-06-06 18:39   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 14/19] printf: support field padding Andrew Jones
2014-06-06 18:39   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 15/19] arm: initial drop Andrew Jones
2014-06-06 18:39   ` Christoffer Dall
2014-06-09  9:44     ` Andrew Jones
2014-04-10 16:56 ` [PATCH v4 16/19] arm: Add spinlock implementation Andrew Jones
2014-04-10 16:56 ` [PATCH v4 17/19] arm: Add IO accessors to avoid register-writeback Andrew Jones
2014-04-10 16:56 ` [PATCH v4 18/19] arm: add useful headers from the Linux kernel Andrew Jones
2014-06-06 18:40   ` Christoffer Dall
2014-04-10 16:57 ` [PATCH v4 19/19] arm: vectors support Andrew Jones
2014-06-06 18:40   ` Christoffer Dall
     [not found] ` <1397149020-3501-7-git-send-email-drjones@redhat.com>
2014-06-06 18:38   ` [PATCH v4 06/19] libfdt: Import libfdt source Christoffer Dall
2014-06-06 18:41 ` [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Christoffer Dall
2014-06-09  9:51   ` Andrew Jones
2014-06-09  9:57     ` Christoffer Dall

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.