diff --git a/arm/cstart64.S b/arm/cstart64.S
new file mode 100644
index 0000000000000..1d98066d0e187
--- /dev/null
+++ b/arm/cstart64.S
@@ -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
diff --git a/arm/run b/arm/run
index 4c5e52525d687..662a8564674a3 100755
--- a/arm/run
+++ b/arm/run
@@ -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 "$@"
diff --git a/arm/selftest.c b/arm/selftest.c
index 885a54fee0e4a..30f44261d47db 100644
--- a/arm/selftest.c
+++ b/arm/selftest.c
@@ -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();
diff --git a/arm/unittests.cfg b/arm/unittests.cfg
index efcca6bf24af6..9ac6ecaa55d3b 100644
--- a/arm/unittests.cfg
+++ b/arm/unittests.cfg
@@ -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
diff --git a/config/config-arm-common.mak b/config/config-arm-common.mak
new file mode 100644
index 0000000000000..b61a2a6044ab2
--- /dev/null
+++ b/config/config-arm-common.mak
@@ -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
diff --git a/config/config-arm.mak b/config/config-arm.mak
index 86e1d75169b59..96686fb639d2d 100644
--- a/config/config-arm.mak
+++ b/config/config-arm.mak
@@ -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
diff --git a/config/config-arm64.mak b/config/config-arm64.mak
new file mode 100644
index 0000000000000..37db3d6026424
--- /dev/null
+++ b/config/config-arm64.mak
@@ -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
diff --git a/configure b/configure
index afdd62800f56e..b2ad32a3e3a52 100755
--- a/configure
+++ b/configure
@@ -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
diff --git a/lib/arm/asm-offsets.c b/lib/arm/asm-offsets.c
index 76380dfa15ab8..1ee9da070f609 100644
--- a/lib/arm/asm-offsets.c
+++ b/lib/arm/asm-offsets.c
@@ -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);
diff --git a/lib/arm64/.gitignore b/lib/arm64/.gitignore
new file mode 100644
index 0000000000000..84872bf197c67
--- /dev/null
+++ b/lib/arm64/.gitignore
@@ -0,0 +1 @@
+asm-offsets.[hs]
diff --git a/lib/arm64/asm-offsets.c b/lib/arm64/asm-offsets.c
new file mode 100644
index 0000000000000..c85b9a1e97e44
--- /dev/null
+++ b/lib/arm64/asm-offsets.c
@@ -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;
+}
diff --git a/lib/arm64/asm/asm-offsets.h b/lib/arm64/asm/asm-offsets.h
new file mode 100644
index 0000000000000..d370ee36a182b
--- /dev/null
+++ b/lib/arm64/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/lib/arm64/asm/barrier.h b/lib/arm64/asm/barrier.h
new file mode 100644
index 0000000000000..8ebdfdf7f1037
--- /dev/null
+++ b/lib/arm64/asm/barrier.h
@@ -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_ */
diff --git a/lib/arm64/asm/io.h b/lib/arm64/asm/io.h
new file mode 100644
index 0000000000000..07b82cb9d8695
--- /dev/null
+++ b/lib/arm64/asm/io.h
@@ -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_ */
diff --git a/lib/arm64/asm/mmu.h b/lib/arm64/asm/mmu.h
new file mode 100644
index 0000000000000..cbafbca6701e7
--- /dev/null
+++ b/lib/arm64/asm/mmu.h
@@ -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_ */
diff --git a/lib/arm64/asm/page.h b/lib/arm64/asm/page.h
new file mode 100644
index 0000000000000..395760cad5f82
--- /dev/null
+++ b/lib/arm64/asm/page.h
@@ -0,0 +1 @@
+#include "../../arm/asm/page.h"
diff --git a/lib/arm64/asm/setup.h b/lib/arm64/asm/setup.h
new file mode 100644
index 0000000000000..e3b4702716c6b
--- /dev/null
+++ b/lib/arm64/asm/setup.h
@@ -0,0 +1 @@
+#include "../../arm/asm/setup.h"
diff --git a/lib/arm64/asm/spinlock.h b/lib/arm64/asm/spinlock.h
new file mode 100644
index 0000000000000..36b7b44fa4edf
--- /dev/null
+++ b/lib/arm64/asm/spinlock.h
@@ -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_ */
diff --git a/lib/kbuild.h b/lib/kbuild.h
new file mode 100644
index 0000000000000..ab99db6770efa
--- /dev/null
+++ b/lib/kbuild.h
@@ -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
