new file mode 100644
@@ -0,0 +1,48 @@
+/*
+ * Boot entry point and assembler functions for aarch64 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.
+ */
+#define __ASSEMBLY__
+#include <asm/asm-offsets.h>
+
+.section .init
+
+.globl start
+start:
+ /*
+ * bootloader params are in x0-x3
+ * The physical address of the dtb is in x0, x1-x3 are reserved
+ * See the kernel doc Documentation/arm64/booting.txt
+ */
+ adr x4, stacktop
+ mov sp, x4
+ stp x0, x1, [sp, #-16]!
+
+ /* Enable FP/ASIMD */
+ mov x0, #(3 << 20)
+ msr cpacr_el1, x0
+
+ /* set up exception handling */
+// bl exceptions_init
+
+ /* complete setup */
+ ldp x0, x1, [sp], #16
+ bl setup
+
+ /* run the test */
+ adr x0, __argc
+ ldr x0, [x0]
+ adr x1, __argv
+ bl main
+ bl exit
+ b halt
+
+.text
+
+.globl halt
+halt:
+1: wfi
+ b 1b
@@ -5,8 +5,9 @@ if [ ! -f config.mak ]; then
exit 2
fi
source config.mak
+processor="$PROCESSOR"
-qemu="${QEMU:-qemu-system-arm}"
+qemu="${QEMU:-qemu-system-$ARCH_NAME}"
qpath=$(which $qemu 2>/dev/null)
if [ -z "$qpath" ]; then
@@ -36,7 +37,12 @@ M='-machine virt,accel=kvm:tcg'
chr_testdev='-device virtio-serial-device'
chr_testdev+=' -device virtconsole,chardev=ctd -chardev testdev,id=ctd'
-command="$qemu $M -cpu $PROCESSOR $chr_testdev"
+# arm64 must use '-cpu host' with kvm
+if [ "$(arch)" = "aarch64" ] && [ "$ARCH" = "arm64" ] && [ -c /dev/kvm ]; then
+ processor="host"
+fi
+
+command="$qemu $M -cpu $processor $chr_testdev"
command+=" -display none -serial stdio -kernel"
echo $command "$@"
@@ -8,10 +8,12 @@
#include <libcflat.h>
#include <alloc.h>
#include <asm/setup.h>
+#ifdef __arm__
#include <asm/ptrace.h>
#include <asm/asm-offsets.h>
#include <asm/processor.h>
#include <asm/page.h>
+#endif
#define TESTGRP "selftest"
@@ -78,6 +80,7 @@ static void check_setup(int argc, char **argv)
assert_args(nr_tests, 2);
}
+#ifdef __arm__
static struct pt_regs expected_regs;
/*
* Capture the current register state and execute an instruction
@@ -184,6 +187,7 @@ static void check_vectors(void *arg __unused)
report("%s", check_und() && check_svc(), testname);
exit(report_summary());
}
+#endif
int main(int argc, char **argv)
{
@@ -195,6 +199,7 @@ int main(int argc, char **argv)
check_setup(argc-1, &argv[1]);
+#ifdef __arm__
} else if (strcmp(argv[0], "vectors-kernel") == 0) {
check_vectors(NULL);
@@ -204,6 +209,7 @@ int main(int argc, char **argv)
void *sp = memalign(PAGE_SIZE, PAGE_SIZE);
memset(sp, 0, PAGE_SIZE);
start_usr(check_vectors, NULL, (unsigned long)sp + PAGE_SIZE);
+#endif
}
return report_summary();
@@ -22,9 +22,11 @@ groups = selftest
file = selftest.flat
extra_params = -append 'vectors-kernel'
groups = selftest
+arch = arm
# Test vector setup and exception handling (user mode).
[selftest::vectors-user]
file = selftest.flat
extra_params = -append 'vectors-user'
groups = selftest
+arch = arm
new file mode 100644
@@ -0,0 +1,68 @@
+#
+# arm common makefile
+#
+# Authors: Andrew Jones <drjones@redhat.com>
+#
+
+ifeq ($(LOADADDR),)
+ # qemu mach-virt default load address
+ LOADADDR = 0x40000000
+endif
+
+tests-common = \
+ $(TEST_DIR)/selftest.flat
+
+all: test_cases
+
+##################################################################
+phys_base = $(LOADADDR)
+
+CFLAGS += -std=gnu99
+CFLAGS += -ffreestanding
+CFLAGS += -Wextra
+CFLAGS += -O2
+CFLAGS += -I lib -I lib/libfdt
+
+asm-offsets = lib/$(ARCH)/asm-offsets.h
+include config/asm-offsets.mak
+
+cflatobjs += lib/alloc.o
+cflatobjs += lib/devicetree.o
+cflatobjs += lib/virtio.o
+cflatobjs += lib/virtio-mmio.o
+cflatobjs += lib/chr-testdev.o
+cflatobjs += lib/arm/io.o
+cflatobjs += lib/arm/setup.o
+
+libeabi = lib/arm/libeabi.a
+eabiobjs = lib/arm/eabi_compat.o
+
+libgcc := $(shell $(CC) $(machine) --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 $@ $^
+
+arm_clean: libfdt_clean asm_offsets_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
+
+generated_files = $(asm-offsets)
+
+test_cases: $(generated_files) $(tests-common) $(tests)
+
+$(TEST_DIR)/selftest.elf: $(cstart.o) $(TEST_DIR)/selftest.o
@@ -3,80 +3,23 @@
#
# 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
+machine = -marm
CFLAGS += -D__arm__
-CFLAGS += -marm
+CFLAGS += $(machine)
CFLAGS += -mcpu=$(PROCESSOR)
-CFLAGS += -std=gnu99
-CFLAGS += -ffreestanding
-CFLAGS += -Wextra
-CFLAGS += -O2
-CFLAGS += -I lib -I lib/libfdt
-
-asm-offsets = lib/arm/asm-offsets.h
-include config/asm-offsets.mak
-
-cflatobjs += \
- lib/alloc.o \
- lib/devicetree.o \
- lib/virtio.o \
- lib/virtio-mmio.o \
- lib/chr-testdev.o \
- lib/arm/io.o \
- lib/arm/setup.o \
- lib/arm/spinlock.o \
- lib/arm/processor.o \
- lib/arm/mmu.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 asm_offsets_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
+cflatobjs += lib/arm/spinlock.o
+cflatobjs += lib/arm/processor.o
+cflatobjs += lib/arm/mmu.o
-generated_files = $(asm-offsets)
-
-test_cases: $(generated_files) $(tests-common) $(tests)
+# arm specific tests
+tests =
-$(TEST_DIR)/selftest.elf: $(cstart.o) $(TEST_DIR)/selftest.o
+include config/config-arm-common.mak
+arch_clean: arm_clean
new file mode 100644
@@ -0,0 +1,20 @@
+#
+# arm64 makefile
+#
+# Authors: Andrew Jones <drjones@redhat.com>
+#
+bits = 64
+ldarch = elf64-littleaarch64
+kernel_offset = 0x80000
+
+CFLAGS += -D__aarch64__
+
+cstart.o = $(TEST_DIR)/cstart64.o
+
+# arm64 specific tests
+tests =
+
+include config/config-arm-common.mak
+
+arch_clean: arm_clean
+ $(RM) lib/arm64/.*.d
@@ -62,14 +62,23 @@ while [[ "$1" = -* ]]; do
;;
esac
done
+
+arch_name=$arch
+[ "$arch" = "aarch64" ] && arch="arm64"
+[ "$arch_name" = "arm64" ] && arch_name="aarch64"
+
[ -z "$processor" ] && processor="$arch"
-if [ "$processor" = "arm" ]; then
+if [ "$processor" = "arm64" ]; then
+ processor="cortex-a57"
+elif [ "$processor" = "arm" ]; then
processor="cortex-a15"
fi
if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then
testdir=x86
+elif [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
+ testdir=arm
else
testdir=$arch
fi
@@ -114,6 +123,7 @@ cat <<EOF > config.mak
PREFIX=$prefix
KERNELDIR=$(readlink -f $kerneldir)
ARCH=$arch
+ARCH_NAME=$arch_name
PROCESSOR=$processor
CC=$cross_prefix$cc
LD=$cross_prefix$ld
@@ -6,14 +6,9 @@
* This work is licensed under the terms of the GNU LGPL, version 2.
*/
#include <libcflat.h>
+#include <kbuild.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);
new file mode 100644
@@ -0,0 +1 @@
+asm-offsets.[hs]
new file mode 100644
@@ -0,0 +1,14 @@
+/*
+ * Adapted from arch/arm64/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 <kbuild.h>
+
+int main(void)
+{
+ return 0;
+}
new file mode 100644
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
new file mode 100644
@@ -0,0 +1,17 @@
+#ifndef _ASMARM64_BARRIER_H_
+#define _ASMARM64_BARRIER_H_
+/*
+ * From Linux arch/arm64/include/asm/barrier.h
+ */
+
+#define isb() asm volatile("isb" : : : "memory")
+#define dmb(opt) asm volatile("dmb " #opt : : : "memory")
+#define dsb(opt) asm volatile("dsb " #opt : : : "memory")
+#define mb() dsb(sy)
+#define rmb() dsb(ld)
+#define wmb() dsb(st)
+#define smp_mb() dmb(ish)
+#define smp_rmb() dmb(ishld)
+#define smp_wmb() dmb(ishst)
+
+#endif /* _ASMARM64_BARRIER_H_ */
new file mode 100644
@@ -0,0 +1,84 @@
+#ifndef _ASMARM64_IO_H_
+#define _ASMARM64_IO_H_
+/*
+ * From Linux arch/arm64/include/asm/io.h
+ * Generic IO read/write. These perform native-endian accesses.
+ */
+#include <libcflat.h>
+#include <asm/barrier.h>
+#include <asm/page.h>
+
+#define __iomem
+#define __force
+
+#define __raw_writeb __raw_writeb
+static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
+{
+ asm volatile("strb %w0, [%1]" : : "r" (val), "r" (addr));
+}
+
+#define __raw_writew __raw_writew
+static inline void __raw_writew(u16 val, volatile void __iomem *addr)
+{
+ asm volatile("strh %w0, [%1]" : : "r" (val), "r" (addr));
+}
+
+#define __raw_writel __raw_writel
+static inline void __raw_writel(u32 val, volatile void __iomem *addr)
+{
+ asm volatile("str %w0, [%1]" : : "r" (val), "r" (addr));
+}
+
+#define __raw_writeq __raw_writeq
+static inline void __raw_writeq(u64 val, volatile void __iomem *addr)
+{
+ asm volatile("str %0, [%1]" : : "r" (val), "r" (addr));
+}
+
+#define __raw_readb __raw_readb
+static inline u8 __raw_readb(const volatile void __iomem *addr)
+{
+ u8 val;
+ asm volatile("ldrb %w0, [%1]" : "=r" (val) : "r" (addr));
+ return val;
+}
+
+#define __raw_readw __raw_readw
+static inline u16 __raw_readw(const volatile void __iomem *addr)
+{
+ u16 val;
+ asm volatile("ldrh %w0, [%1]" : "=r" (val) : "r" (addr));
+ return val;
+}
+
+#define __raw_readl __raw_readl
+static inline u32 __raw_readl(const volatile void __iomem *addr)
+{
+ u32 val;
+ asm volatile("ldr %w0, [%1]" : "=r" (val) : "r" (addr));
+ return val;
+}
+
+#define __raw_readq __raw_readq
+static inline u64 __raw_readq(const volatile void __iomem *addr)
+{
+ u64 val;
+ asm volatile("ldr %0, [%1]" : "=r" (val) : "r" (addr));
+ return val;
+}
+
+#define virt_to_phys virt_to_phys
+static inline phys_addr_t virt_to_phys(const volatile void *x)
+{
+ return __virt_to_phys((unsigned long)(x));
+}
+
+#define phys_to_virt phys_to_virt
+static inline void *phys_to_virt(phys_addr_t x)
+{
+ return (void *)__phys_to_virt(x);
+}
+
+#include <asm-generic/io.h>
+
+#endif /* _ASMARM64_IO_H_ */
new file mode 100644
@@ -0,0 +1,18 @@
+#ifndef __ASMARM64_MMU_H_
+#define __ASMARM64_MMU_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.
+ */
+
+static inline bool mmu_enabled(void)
+{
+ return false;
+}
+
+static inline void mmu_enable_idmap(void)
+{
+}
+
+#endif /* __ASMARM64_MMU_H_ */
new file mode 100644
@@ -0,0 +1 @@
+#include "../../arm/asm/page.h"
new file mode 100644
@@ -0,0 +1 @@
+#include "../../arm/asm/setup.h"
new file mode 100644
@@ -0,0 +1,15 @@
+#ifndef _ASMARM64_SPINLOCK_H_
+#define _ASMARM64_SPINLOCK_H_
+
+struct spinlock {
+ int v;
+};
+
+static inline void spin_lock(struct spinlock *lock __unused)
+{
+}
+static inline void spin_unlock(struct spinlock *lock __unused)
+{
+}
+
+#endif /* _ASMARM64_SPINLOCK_H_ */
new file mode 100644
@@ -0,0 +1,8 @@
+#ifndef _KBUILD_H_
+#define _KBUILD_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->" : : )
+#endif
This is the initial drop of the arm64 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-aarch64-linux-gnu ./configure --cross-prefix=aarch64-linux-gnu- --arch=arm64 make QEMU=[qemu with aarch64, mach-virt, and chr-testdev] ./run_tests.sh Signed-off-by: Andrew Jones <drjones@redhat.com> --- arm/cstart64.S | 48 +++++++++++++++++++++++++ arm/run | 10 ++++-- arm/selftest.c | 6 ++++ arm/unittests.cfg | 2 ++ config/config-arm-common.mak | 68 +++++++++++++++++++++++++++++++++++ config/config-arm.mak | 75 +++++---------------------------------- config/config-arm64.mak | 20 +++++++++++ configure | 12 ++++++- lib/arm/asm-offsets.c | 7 +--- lib/arm64/.gitignore | 1 + lib/arm64/asm-offsets.c | 14 ++++++++ lib/arm64/asm/asm-offsets.h | 1 + lib/arm64/asm/barrier.h | 17 +++++++++ lib/arm64/asm/io.h | 84 ++++++++++++++++++++++++++++++++++++++++++++ lib/arm64/asm/mmu.h | 18 ++++++++++ lib/arm64/asm/page.h | 1 + lib/arm64/asm/setup.h | 1 + lib/arm64/asm/spinlock.h | 15 ++++++++ lib/kbuild.h | 8 +++++ 19 files changed, 333 insertions(+), 75 deletions(-) create mode 100644 arm/cstart64.S create mode 100644 config/config-arm-common.mak create mode 100644 config/config-arm64.mak create mode 100644 lib/arm64/.gitignore create mode 100644 lib/arm64/asm-offsets.c create mode 100644 lib/arm64/asm/asm-offsets.h create mode 100644 lib/arm64/asm/barrier.h create mode 100644 lib/arm64/asm/io.h create mode 100644 lib/arm64/asm/mmu.h create mode 100644 lib/arm64/asm/page.h create mode 100644 lib/arm64/asm/setup.h create mode 100644 lib/arm64/asm/spinlock.h create mode 100644 lib/kbuild.h