Re: [PATCH 8/9] arm: initial drop

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

 



On Mon, Oct 14, 2013 at 06:23:34PM +0200, Andrew Jones wrote:
> This is the initial arm test infrastructure and a first test that
> simply checks some bootinfo. kvm isn't needed to run this test. This
> patch also adds a common build environment variable, $QEMU_BIN, which
> allows makefiles to call on qemu when needed.
> 
> Try it out with
>   yum install gcc-arm-linux-gnu dtc
>   export QEMU=[qemu with mach-virt and virtio-testdev]
>   ./configure --cross-prefix=arm-linux-gnu- --arch=arm
>   make
>   ./run_tests.sh
> 
> Signed-off-by: Andrew Jones <drjones@xxxxxxxxxx>
> ---
>  arm/boot.c            | 27 ++++++++++++++++++++
>  arm/cstart.S          | 47 ++++++++++++++++++++++++++++++++++
>  arm/flat.lds          | 18 +++++++++++++
>  arm/run               | 19 ++++++++++++++
>  arm/unittests.cfg     | 11 ++++++++
>  config/config-arm.mak | 62 +++++++++++++++++++++++++++++++++++++++++++++
>  configure             | 10 ++++++--
>  lib/arm/bootinfo.c    | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/arm/bootinfo.h    | 19 ++++++++++++++
>  lib/arm/bswap.h       | 30 ++++++++++++++++++++++
>  lib/arm/io.c          | 26 +++++++++++++++++++
>  lib/bswap.h           |  4 +++
>  lib/libcflat.h        |  1 +
>  13 files changed, 342 insertions(+), 2 deletions(-)
>  create mode 100644 arm/boot.c
>  create mode 100644 arm/cstart.S
>  create mode 100644 arm/flat.lds
>  create mode 100755 arm/run
>  create mode 100644 arm/unittests.cfg
>  create mode 100644 config/config-arm.mak
>  create mode 100644 lib/arm/bootinfo.c
>  create mode 100644 lib/arm/bootinfo.h
>  create mode 100644 lib/arm/bswap.h
>  create mode 100644 lib/arm/io.c
> 
> diff --git a/arm/boot.c b/arm/boot.c
> new file mode 100644
> index 0000000000000..375e8708a7c54

this file's indentation is also funny, you should really check your
editor configuration :)

> --- /dev/null
> +++ b/arm/boot.c
> @@ -0,0 +1,27 @@
> +#include "libcflat.h"
> +#include "arm/bootinfo.h"
> +
> +static bool info_check(u32 var, char *expected)
> +{
> +    char var_str[9];
> +    snprintf(var_str, 9, "%x", var);
> +    while (*expected == '0' || *expected == 'x')
> +	    ++expected;
> +    return !strcmp(var_str, expected);
> +}
> +
> +int main(int argc, char **argv)
> +{
> +    int ret = 0;
> +
> +    if (argc < 3) {
> +	printf("Not enough arguments. Can't test\n");
> +	return 1;
> +    }
> +
> +    if (!strcmp(argv[0], "info"))
> +	ret = !info_check(mem32.size, argv[1])
> +		|| !info_check(core.pagesize, argv[2]);
> +
> +    return ret;
> +}

I'm actually a little confused, when does this main get invoked and by
whom and what are we testing for here?

> diff --git a/arm/cstart.S b/arm/cstart.S
> new file mode 100644
> index 0000000000000..a65809824d4f1
> --- /dev/null
> +++ b/arm/cstart.S
> @@ -0,0 +1,47 @@
> +
> +#define CR_B	(1 << 7)
> +
> +.arm
> +
> +.section .init
> +
> +.globl start
> +start:
> +	/* bootloader params are in r0-r2 */
> +	ldr	sp, =stacktop
> +	push	{ r0-r3 }		@push r3 too for 8-byte alignment
> +
> +	mrc	p15, 0, r8, c1, c0, 0	@r8 = sctrl
> +	bl	get_endianness
> +	bl	io_init
> +
> +	pop	{ r0-r3 }
> +	bl	read_bootinfo
> +	bl	__setup_args
> +	ldr	r0, =__argc
> +	ldr	r0, [r0]
> +	ldr	r1, =__argv
> +	bl	main
> +	bl	exit
> +	b	halt
> +
> +get_endianness:
> +	and	r0, r8, #CR_B
> +	cmp	r0, #0
> +	beq	1f
> +	ldr	r1, =cpu_is_be
> +	mov	r0, #1
> +	str	r0, [r1]
> +1:	mov	pc, lr
> +
> +.text
> +
> +.globl halt
> +halt:
> +1:	wfi
> +	b	1b
> +
> +.data
> +
> +.globl cpu_is_be
> +cpu_is_be:	.word 0
> diff --git a/arm/flat.lds b/arm/flat.lds
> new file mode 100644
> index 0000000000000..3e5d72e24989b
> --- /dev/null
> +++ b/arm/flat.lds
> @@ -0,0 +1,18 @@
> +
> +SECTIONS
> +{
> +    .text : { *(.init) *(.text) *(.text.*) }
> +    . = ALIGN(4K);
> +    .data : { *(.data) }
> +    . = ALIGN(16);
> +    .rodata : { *(.rodata) }
> +    . = ALIGN(16);
> +    .bss : { *(.bss) }
> +    . = ALIGN(4K);
> +    edata = .;
> +    . += 8K;
> +    . = ALIGN(4K);
> +    stacktop = .;
> +}
> +
> +ENTRY(start)
> diff --git a/arm/run b/arm/run
> new file mode 100755
> index 0000000000000..64446e8907564
> --- /dev/null
> +++ b/arm/run
> @@ -0,0 +1,19 @@
> +#!/bin/bash
> +
> +qemu="${QEMU:-qemu-system-arm}"
> +testdev='virtio-testdev'
> +
> +if ! $qemu -device '?' 2>&1 | grep $testdev > /dev/null; then
> +    echo \"$qemu\" has no support for the virtio test device. Exiting.
> +    exit 2
> +fi
> +
> +command="$qemu -device $testdev -display none -serial stdio "
> +command+="-M virt -cpu cortex-a15 "
> +#command+="-enable-kvm "
> +command+="-kernel"
> +echo $command "$@"
> +$command "$@"
> +ret=$?
> +echo Return value from qemu: $ret
> +exit $ret
> diff --git a/arm/unittests.cfg b/arm/unittests.cfg
> new file mode 100644
> index 0000000000000..fb78cd906839a
> --- /dev/null
> +++ b/arm/unittests.cfg
> @@ -0,0 +1,11 @@
> +# Define your new unittest following the convention:
> +# [unittest_name]
> +# file = foo.flat # Name of the flat file to be used
> +# smp = 2 # Number of processors the VM will use during this test
> +# extra_params = -append <params...> # Additional parameters used
> +# arch = arm/arm64 # Only if the test case works only on one of them
> +# groups = group1 group2 # Used to identify test cases with run_tests -g ...
> +
> +[boot_info]
> +file = boot.flat
> +extra_params = -m 256 -append 'info 0x10000000 0x1000'
> diff --git a/config/config-arm.mak b/config/config-arm.mak
> new file mode 100644
> index 0000000000000..066b1f725c5b3
> --- /dev/null
> +++ b/config/config-arm.mak
> @@ -0,0 +1,62 @@
> +mach = mach-virt
> +iodevs = pl011 virtio_mmio
> +phys_base = 0x8000000
> +
> +cstart.o = $(TEST_DIR)/cstart.o
> +bits = 32
> +ldarch = elf32-littlearm
> +kernel_offset = 0x10000
> +CFLAGS += -D__arm__
> +
> +all: test_cases
> +
> +cflatobjs += \
> +	lib/$(TEST_DIR)/iomaps.gen.o \
> +	lib/iomaps.o \
> +	lib/virtio-testdev.o \
> +	lib/arm/io.o \
> +	lib/arm/bootinfo.o
> +
> +$(libcflat): LDFLAGS += -nostdlib
> +$(libcflat): CFLAGS += -ffreestanding -I lib
> +
> +CFLAGS += -Wextra
> +CFLAGS += -marm
> +#CFLAGS += -mcpu=$(PROCESSOR)
> +CFLAGS += -mcpu=cortex-a15
> +CFLAGS += -O2
> +
> +libgcc := $(shell $(CC) -m$(ARCH) --print-libgcc-file-name)
> +start_addr := $(shell printf "%x\n" $$(( $(phys_base) + $(kernel_offset) )))
> +
> +FLATLIBS = lib/libcflat.a $(libgcc)
> +%.elf: %.o $(FLATLIBS) arm/flat.lds
> +	$(CC) $(CFLAGS) -nostdlib -o $@ \
> +		-Wl,-T,arm/flat.lds,--build-id=none,-Ttext=$(start_addr) \
> +		$(filter %.o, $^) $(FLATLIBS)
> +
> +%.flat: %.elf
> +	$(OBJCOPY) -O binary $^ $@
> +
> +tests-common = $(TEST_DIR)/boot.flat
> +
> +tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg
> +
> +test_cases: $(tests-common) $(tests)
> +
> +$(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I lib
> +
> +$(TEST_DIR)/boot.elf: $(cstart.o) $(TEST_DIR)/boot.o
> +
> +lib/$(TEST_DIR)/iomaps.gen.c: lib/$(TEST_DIR)/$(mach).dts
> +	scripts/gen-devtree-iomaps.pl $^ $(iodevs) > $@
> +
> +lib/$(TEST_DIR)/mach-virt.dts: dtb = $(subst .dts,.dtb,$@)
> +lib/$(TEST_DIR)/mach-virt.dts:
> +	$(QEMU_BIN) -kernel /dev/null -M virt -machine dumpdtb=$(dtb)
> +	fdtdump $(dtb) > $@
> +
> +arch_clean:
> +	$(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
> +	$(TEST_DIR)/.*.d lib/arm/.*.d \
> +	lib/$(TEST_DIR)/iomaps.gen.c lib/$(TEST_DIR)/mach-virt.*
> diff --git a/configure b/configure
> index 6cfc64943f6e6..296c70182ea1d 100755
> --- a/configure
> +++ b/configure
> @@ -6,8 +6,7 @@ cc=gcc
>  ld=ld
>  objcopy=objcopy
>  ar=ar
> -arch=`uname -m | sed -e s/i.86/i386/`
> -processor="$arch"
> +arch=`uname -m | sed -e s/i.86/i386/ | sed -e 's/arm.*/arm/'`
>  cross_prefix=
>  
>  usage() {
> @@ -17,6 +16,7 @@ usage() {
>  	Options include:
>  	    --test-dir=DIR         the main directory for tests ($arch)
>  	    --arch=ARCH            architecture to compile for ($arch)
> +	    --processor=PROCESSOR  processor to compile for ($arch)
>  	    --cross-prefix=PREFIX  cross compiler prefix
>  	    --cc=CC		   c compiler to use ($cc)
>  	    --ld=LD		   ld linker to use ($ld)
> @@ -66,6 +66,9 @@ while [[ "$1" = -* ]]; do
>  	    ;;
>      esac
>  done
> +[ -z "$processor" ] && processor="$arch"
> +qemu="${QEMU:-qemu-system-$arch}"
> +
>  if [ -z "$testdir" -a \( "$arch" = "i386" -o "$arch" = "x86_64" \) ]; then
>      testdir=x86
>  elif [ -z "$testdir" ]; then
> @@ -80,6 +83,7 @@ if [ -f $testdir/run ]; then
>  fi
>  
>  # check for dependent 32 bit libraries
> +if [ "$arch" = "i386" -o "$arch" = "x86_64" ]; then
>  cat << EOF > lib_test.c
>  #include <stdc++.h>
>  #include <boost_thread-mt.h>
> @@ -94,6 +98,7 @@ if [ $exit -eq 0 ]; then
>      api=true
>  fi
>  rm -f lib_test.c
> +fi
>  
>  cat <<EOF > config.mak
>  PREFIX=$prefix
> @@ -106,4 +111,5 @@ OBJCOPY=$cross_prefix$objcopy
>  AR=$cross_prefix$ar
>  API=$api
>  TEST_DIR=$testdir
> +QEMU_BIN=$qemu
>  EOF
> diff --git a/lib/arm/bootinfo.c b/lib/arm/bootinfo.c
> new file mode 100644
> index 0000000000000..c362064f661d9
> --- /dev/null
> +++ b/lib/arm/bootinfo.c
> @@ -0,0 +1,70 @@
> +#include "libcflat.h"
> +#include "arm/bootinfo.h"
> +#include "arm/bswap.h"
> +
> +#define FDT_SIG			0xd00dfeed
> +
> +#define KERNEL_OFFSET		0x00010000
> +#define ATAG_OFFSET		0x00000100
> +
> +#define ATAG_CORE		0x54410001
> +#define ATAG_MEM		0x54410002
> +#define ATAG_CMDLINE		0x54410009
> +
> +extern void start(void);
> +extern char *__args;
> +
> +u32 mach_type_id;
> +struct tag_core core;
> +struct tag_mem32 mem32;
> +
> +static void read_atags(u32 id, u32 *info)
> +{
> +    u32 *p = info;
> +
> +    if (!p) {
> +	printf("Can't find bootinfo. mach-type = %x\n", id);
> +	exit(ENOEXEC);
> +    }
> +
> +    /*
> +     * p[0]	count of words for the tag
> +     * p[1]	tag id
> +     * p[2..]	tag data
> +     */
> +    for (; p[0] != 0; p += p[0])
> +	switch (p[1]) {
> +	case ATAG_CORE:
> +	    core.flags = p[2];
> +	    core.pagesize = p[3];
> +	    core.rootdev = p[4];
> +	    break;
> +	case ATAG_MEM:
> +	    mem32.size = p[2];
> +	    mem32.start = p[3];
> +	    break;
> +	case ATAG_CMDLINE:
> +	    __args = (char *)&p[2];
> +	    break;
> +	}
> +}
> +
> +#define __unused __attribute__((__unused__))
> +
> +void read_bootinfo(u32 arg __unused, u32 id, u32 *info)
> +{
> +    u32 *atags = NULL;
> +
> +    mach_type_id = id;
> +
> +    if (info[0] == be32_to_cpu(FDT_SIG)) {
> +	/*
> +	 * fdt reading is not [yet?] implemented. So calculate
> +	 * the ATAGS addr to read that instead.
> +	 */
> +	atags = (u32 *)((u32)start - KERNEL_OFFSET + ATAG_OFFSET);
> +    } else if (info[1] == ATAG_CORE)
> +	atags = info;
> +
> +    read_atags(id, atags);
> +}
> diff --git a/lib/arm/bootinfo.h b/lib/arm/bootinfo.h
> new file mode 100644
> index 0000000000000..9cf547e4cebeb
> --- /dev/null
> +++ b/lib/arm/bootinfo.h
> @@ -0,0 +1,19 @@
> +#ifndef _BOOTINFO_H_
> +#define _BOOTINFO_H_
> +#include "libcflat.h"
> +
> +struct tag_core {
> +    u32 flags;		/* bit 0 = read-only */
> +    u32 pagesize;
> +    u32 rootdev;
> +};
> +
> +struct tag_mem32 {
> +    u32   size;
> +    u32   start;	/* physical start address */
> +};
> +
> +extern u32 mach_type_id;
> +extern struct tag_core core;
> +extern struct tag_mem32 mem32;
> +#endif
> diff --git a/lib/arm/bswap.h b/lib/arm/bswap.h
> new file mode 100644
> index 0000000000000..9bd16e789fcc5
> --- /dev/null
> +++ b/lib/arm/bswap.h
> @@ -0,0 +1,30 @@
> +#ifndef _ARM_BSWAP_H_
> +#define _ARM_BSWAP_H_
> +#include "libcflat.h"
> +
> +extern bool cpu_is_be;
> +
> +static inline u32 bswap32(u32 val)
> +{
> +    u32 ret;
> +    asm volatile("rev %0, %1" : "=r" (ret) :  "r" (val));
> +    return ret;
> +}
> +
> +static inline u16 bswap16(u16 val)
> +{
> +    u16 ret;
> +    asm volatile("rev16 %0, %1" : "=r" (ret) :  "r" (val));
> +    return ret;
> +}
> +
> +#define be32_to_cpu(x) (cpu_is_be ? x : bswap32(x))
> +#define cpu_to_be32(x) (cpu_is_be ? x : bswap32(x))
> +#define be16_to_cpu(x) (cpu_is_be ? x : bswap16(x))
> +#define cpu_to_be16(x) (cpu_is_be ? x : bswap16(x))
> +
> +#define le32_to_cpu(x) (cpu_is_be ? bswap32(x) : x)
> +#define cpu_to_le32(x) (cpu_is_be ? bswap32(x) : x)
> +#define le16_to_cpu(x) (cpu_is_be ? bswap16(x) : x)
> +#define cpu_to_le16(x) (cpu_is_be ? bswap16(x) : x)
> +#endif
> diff --git a/lib/arm/io.c b/lib/arm/io.c
> new file mode 100644
> index 0000000000000..951af60551a4c
> --- /dev/null
> +++ b/lib/arm/io.c
> @@ -0,0 +1,26 @@
> +#include "libcflat.h"
> +#include "iomaps.h"
> +#include "virtio-testdev.h"
> +
> +static volatile u8 *uart0_base;
> +
> +void puts(const char *s)
> +{
> +    while (*s)
> +	*uart0_base = *s++;
> +}
> +
> +void exit(int code)
> +{
> +    virtio_testdev_exit(code);
> +    halt(code);
> +}
> +
> +void io_init(void)
> +{
> +    struct iomap *m = iomaps_find("pl011");
> +    if (!m)
> +	halt(ENXIO);
> +    uart0_base = (u8 *)compat_ptr(m->addrs[0]);
> +    virtio_testdev_init();
> +}
> diff --git a/lib/bswap.h b/lib/bswap.h
> index e63c4d37a8b9a..a428ed6c646dd 100644
> --- a/lib/bswap.h
> +++ b/lib/bswap.h
> @@ -1,7 +1,11 @@
>  #ifndef _BSWAP_H_
>  #define _BSWAP_H_
> +#ifdef __arm__
> +#include "arm/bswap.h"
> +#else
>  #define le32_to_cpu(x) (x)
>  #define cpu_to_le32(x) (x)
>  #define le16_to_cpu(x) (x)
>  #define cpu_to_le16(x) (x)
>  #endif
> +#endif
> diff --git a/lib/libcflat.h b/lib/libcflat.h
> index 41791194657d0..dce9a0f516e7e 100644
> --- a/lib/libcflat.h
> +++ b/lib/libcflat.h
> @@ -55,6 +55,7 @@ extern char *strcat(char *dest, const char *src);
>  extern int strcmp(const char *a, const char *b);
>  
>  extern int printf(const char *fmt, ...);
> +extern int snprintf(char *buf, int size, const char *fmt, ...);
>  extern int vsnprintf(char *buf, int size, const char *fmt, va_list va);
>  
>  extern void puts(const char *s);
> -- 
> 1.8.1.4
> 
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




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