[PATCH 0/5] arm64 (aka aarch64/armv8) support in Xvisor

665 views
Skip to first unread message

Sukanto Ghosh

unread,
Sep 15, 2013, 4:08:43 AM9/15/13
to an...@brainfault.org, Sukanto Ghosh, xvisor...@googlegroups.com
This set of 5 patches adds much-awaited arm64 support in Xvisor.
Specifically this supports the folllowing environment:

Host: ARMv8 Foundation model (free download from ARM website
http://www.arm.com/products/tools/models/fast-models/foundation-model.php)
Guest: Virt-v8 (a completely device-tree based guest having generic
armv8 cpus, virtio-based devices, GIC and arch-timers).
Toolchain: Downloadable from linaro website
(http://www.linaro.org/engineering/engineering-projects/armv8#tab3)

Sukanto Ghosh (5):
[ARM] Introduce arm64 CPU support
[ARM] Introduce virt-v8 guest template for arm64 guest
[ARM] Introduce generic armv8 board
[DOCS] Add light-weight bootwrapper for ARMv8 foundation models
[TESTS] Add arm64 basic firmware for virt-v8 guest

arch/arm/board/common/guests/virt-v8x2.dtsi | 94 ++
arch/arm/board/generic-v8/brd_defterm.c | 93 ++
arch/arm/board/generic-v8/brd_main.c | 130 ++
arch/arm/board/generic-v8/brd_smp.c | 232 ++++
.../dts/foundation-v8/foundation-v8.dtsi | 122 ++
.../dts/foundation-v8/one_guest_virt_v8.dts | 41 +
arch/arm/board/generic-v8/dts/skeleton.dts | 24 +
arch/arm/board/generic-v8/include/arch_host_irq.h | 61 +
arch/arm/board/generic-v8/include/gic_config.h | 29 +
arch/arm/board/generic-v8/objects.mk | 30 +
arch/arm/board/generic-v8/openconf.cfg | 31 +
arch/arm/board/openconf.cfg | 21 +
arch/arm/configs/generic-v8-defconfig | 322 +++++
arch/arm/cpu/arm64/cpu_atomic.c | 124 ++
arch/arm/cpu/arm64/cpu_atomic64.c | 125 ++
arch/arm/cpu/arm64/cpu_cache.S | 278 ++++
arch/arm/cpu/arm64/cpu_delay.S | 32 +
arch/arm/cpu/arm64/cpu_elf.c | 66 +
arch/arm/cpu/arm64/cpu_entry.S | 665 ++++++++++
arch/arm/cpu/arm64/cpu_init.c | 105 ++
arch/arm/cpu/arm64/cpu_interrupts.c | 237 ++++
arch/arm/cpu/arm64/cpu_locks.c | 202 +++
arch/arm/cpu/arm64/cpu_smp.S | 32 +
arch/arm/cpu/arm64/cpu_stacktrace.c | 125 ++
arch/arm/cpu/arm64/cpu_vcpu_coproc.c | 306 +++++
arch/arm/cpu/arm64/cpu_vcpu_emulate.c | 506 +++++++
arch/arm/cpu/arm64/cpu_vcpu_helper.c | 991 ++++++++++++++
arch/arm/cpu/arm64/cpu_vcpu_irq.c | 201 +++
arch/arm/cpu/arm64/cpu_vcpu_mem.c | 135 ++
arch/arm/cpu/arm64/cpu_vcpu_spr.c | 359 +++++
arch/arm/cpu/arm64/include/arch_barrier.h | 48 +
arch/arm/cpu/arm64/include/arch_cache.h | 56 +
arch/arm/cpu/arm64/include/arch_config.h | 30 +
arch/arm/cpu/arm64/include/arch_cpu_irq.h | 82 ++
arch/arm/cpu/arm64/include/arch_delay.h | 39 +
arch/arm/cpu/arm64/include/arch_elf.h | 99 ++
arch/arm/cpu/arm64/include/arch_io.h | 193 +++
arch/arm/cpu/arm64/include/arch_regs.h | 152 +++
arch/arm/cpu/arm64/include/arch_sections.h | 69 +
arch/arm/cpu/arm64/include/arch_types.h | 71 +
arch/arm/cpu/arm64/include/cpu_cache.h | 76 ++
arch/arm/cpu/arm64/include/cpu_defines.h | 706 ++++++++++
arch/arm/cpu/arm64/include/cpu_generic_timer.h | 159 +++
arch/arm/cpu/arm64/include/cpu_inline_asm.h | 243 ++++
arch/arm/cpu/arm64/include/cpu_mmu_lpae.h | 55 +
arch/arm/cpu/arm64/include/cpu_vcpu_coproc.h | 90 ++
arch/arm/cpu/arm64/include/cpu_vcpu_emulate.h | 96 ++
arch/arm/cpu/arm64/include/cpu_vcpu_helper.h | 59 +
arch/arm/cpu/arm64/include/cpu_vcpu_mem.h | 57 +
arch/arm/cpu/arm64/include/cpu_vcpu_spr.h | 69 +
arch/arm/cpu/arm64/linker.ld | 119 ++
arch/arm/cpu/arm64/objects.mk | 52 +
arch/arm/cpu/arm64/openconf.cfg | 56 +
arch/arm/cpu/common/openconf.cfg | 4 +-
arch/arm/cpu/openconf.cfg | 24 +
docs/arm/foundation_v8_boot.S | 176 +++
tests/arm64/common/README | 9 +
tests/arm64/common/basic/Makefile.inc | 134 ++
tests/arm64/common/basic/README | 5 +
tests/arm64/common/basic/arm_asm_macro.h | 139 ++
tests/arm64/common/basic/arm_board.h | 60 +
tests/arm64/common/basic/arm_defines.h | 312 +++++
tests/arm64/common/basic/arm_entry.S | 323 +++++
tests/arm64/common/basic/arm_heap.c | 44 +
tests/arm64/common/basic/arm_heap.h | 32 +
tests/arm64/common/basic/arm_inline_asm.h | 118 ++
tests/arm64/common/basic/arm_io.h | 39 +
tests/arm64/common/basic/arm_irq.c | 122 ++
tests/arm64/common/basic/arm_irq.h | 48 +
tests/arm64/common/basic/arm_main.c | 675 ++++++++++
tests/arm64/common/basic/arm_math.c | 117 ++
tests/arm64/common/basic/arm_math.h | 60 +
tests/arm64/common/basic/arm_mmu.c | 235 ++++
tests/arm64/common/basic/arm_mmu.h | 36 +
tests/arm64/common/basic/arm_stdio.c | 360 +++++
tests/arm64/common/basic/arm_stdio.h | 38 +
tests/arm64/common/basic/arm_string.c | 357 +++++
tests/arm64/common/basic/arm_string.h | 47 +
tests/arm64/common/basic/arm_types.h | 88 ++
tests/arm64/common/basic/dhry.h | 395 ++++++
tests/arm64/common/basic/dhry_1.c | 431 ++++++
tests/arm64/common/basic/dhry_2.c | 197 +++
tests/arm64/common/basic/dhry_port.c | 83 ++
tests/arm64/common/basic/dhry_port.h | 42 +
tests/arm64/common/basic/firmware.ld | 97 ++
tests/arm64/common/basic/libfdt/cmd_fdt.c | 443 +++++++
tests/arm64/common/basic/libfdt/fdt.c | 222 ++++
tests/arm64/common/basic/libfdt/fdt.h | 62 +
tests/arm64/common/basic/libfdt/fdt_ro.c | 574 ++++++++
tests/arm64/common/basic/libfdt/fdt_rw.c | 465 +++++++
tests/arm64/common/basic/libfdt/fdt_strerror.c | 96 ++
tests/arm64/common/basic/libfdt/fdt_support.c | 1318 ++++++++++++++++++
tests/arm64/common/basic/libfdt/fdt_support.h | 123 ++
tests/arm64/common/basic/libfdt/fdt_sw.c | 256 ++++
tests/arm64/common/basic/libfdt/fdt_wip.c | 118 ++
tests/arm64/common/basic/libfdt/libfdt.h | 1237 +++++++++++++++++
tests/arm64/common/basic/libfdt/libfdt_env.h | 49 +
tests/arm64/common/basic/libfdt/libfdt_internal.h | 95 ++
tests/arm64/common/basic/pic/gic.c | 225 ++++
tests/arm64/common/basic/pic/gic.h | 56 +
tests/arm64/common/basic/serial/pl01x.c | 138 ++
tests/arm64/common/basic/serial/pl01x.h | 150 +++
tests/arm64/common/basic/serial/virtio_console.c | 70 +
tests/arm64/common/basic/serial/virtio_console.h | 57 +
tests/arm64/common/basic/timer/generic_timer.c | 166 +++
tests/arm64/common/basic/timer/generic_timer.h | 36 +
tests/arm64/common/busybox/README | 38 +
.../arm64/common/busybox/busybox-1.21.0_defconfig | 1034 +++++++++++++++
tests/arm64/common/busybox/busybox_dev.txt | 70 +
tests/arm64/virt-v8/README | 29 +
tests/arm64/virt-v8/basic/Makefile | 43 +
tests/arm64/virt-v8/basic/README | 61 +
tests/arm64/virt-v8/basic/arm_board.c | 214 +++
tests/arm64/virt-v8/basic/arm_plat.h | 63 +
tests/arm64/virt-v8/basic/gic_config.h | 41 +
tests/arm64/virt-v8/linux/README | 95 ++
tests/arm64/virt-v8/linux/cmdlist | 5 +
.../linux-3.11-virtio-console-earlyprintk.patch | 61 +
.../virt-v8/linux/linux-3.11_virt_v8_defconfig | 1399 ++++++++++++++++++++
tests/arm64/virt-v8/linux/virt-v8.dts | 153 +++
120 files changed, 22502 insertions(+), 2 deletions(-)
create mode 100644 arch/arm/board/common/guests/virt-v8x2.dtsi
create mode 100644 arch/arm/board/generic-v8/brd_defterm.c
create mode 100644 arch/arm/board/generic-v8/brd_main.c
create mode 100644 arch/arm/board/generic-v8/brd_smp.c
create mode 100644 arch/arm/board/generic-v8/dts/foundation-v8/foundation-v8.dtsi
create mode 100644 arch/arm/board/generic-v8/dts/foundation-v8/one_guest_virt_v8.dts
create mode 100644 arch/arm/board/generic-v8/dts/skeleton.dts
create mode 100644 arch/arm/board/generic-v8/include/arch_host_irq.h
create mode 100644 arch/arm/board/generic-v8/include/gic_config.h
create mode 100644 arch/arm/board/generic-v8/objects.mk
create mode 100644 arch/arm/board/generic-v8/openconf.cfg
create mode 100644 arch/arm/configs/generic-v8-defconfig
create mode 100644 arch/arm/cpu/arm64/cpu_atomic.c
create mode 100644 arch/arm/cpu/arm64/cpu_atomic64.c
create mode 100644 arch/arm/cpu/arm64/cpu_cache.S
create mode 100644 arch/arm/cpu/arm64/cpu_delay.S
create mode 100644 arch/arm/cpu/arm64/cpu_elf.c
create mode 100644 arch/arm/cpu/arm64/cpu_entry.S
create mode 100644 arch/arm/cpu/arm64/cpu_init.c
create mode 100644 arch/arm/cpu/arm64/cpu_interrupts.c
create mode 100644 arch/arm/cpu/arm64/cpu_locks.c
create mode 100644 arch/arm/cpu/arm64/cpu_smp.S
create mode 100644 arch/arm/cpu/arm64/cpu_stacktrace.c
create mode 100644 arch/arm/cpu/arm64/cpu_vcpu_coproc.c
create mode 100644 arch/arm/cpu/arm64/cpu_vcpu_emulate.c
create mode 100644 arch/arm/cpu/arm64/cpu_vcpu_helper.c
create mode 100644 arch/arm/cpu/arm64/cpu_vcpu_irq.c
create mode 100644 arch/arm/cpu/arm64/cpu_vcpu_mem.c
create mode 100644 arch/arm/cpu/arm64/cpu_vcpu_spr.c
create mode 100644 arch/arm/cpu/arm64/include/arch_barrier.h
create mode 100644 arch/arm/cpu/arm64/include/arch_cache.h
create mode 100644 arch/arm/cpu/arm64/include/arch_config.h
create mode 100644 arch/arm/cpu/arm64/include/arch_cpu_irq.h
create mode 100644 arch/arm/cpu/arm64/include/arch_delay.h
create mode 100644 arch/arm/cpu/arm64/include/arch_elf.h
create mode 100644 arch/arm/cpu/arm64/include/arch_io.h
create mode 100644 arch/arm/cpu/arm64/include/arch_regs.h
create mode 100644 arch/arm/cpu/arm64/include/arch_sections.h
create mode 100644 arch/arm/cpu/arm64/include/arch_types.h
create mode 100644 arch/arm/cpu/arm64/include/cpu_cache.h
create mode 100644 arch/arm/cpu/arm64/include/cpu_defines.h
create mode 100644 arch/arm/cpu/arm64/include/cpu_generic_timer.h
create mode 100644 arch/arm/cpu/arm64/include/cpu_inline_asm.h
create mode 100644 arch/arm/cpu/arm64/include/cpu_mmu_lpae.h
create mode 100644 arch/arm/cpu/arm64/include/cpu_vcpu_coproc.h
create mode 100644 arch/arm/cpu/arm64/include/cpu_vcpu_emulate.h
create mode 100644 arch/arm/cpu/arm64/include/cpu_vcpu_helper.h
create mode 100644 arch/arm/cpu/arm64/include/cpu_vcpu_mem.h
create mode 100644 arch/arm/cpu/arm64/include/cpu_vcpu_spr.h
create mode 100755 arch/arm/cpu/arm64/linker.ld
create mode 100644 arch/arm/cpu/arm64/objects.mk
create mode 100644 arch/arm/cpu/arm64/openconf.cfg
create mode 100644 docs/arm/foundation_v8_boot.S
create mode 100644 tests/arm64/common/README
create mode 100644 tests/arm64/common/basic/Makefile.inc
create mode 100644 tests/arm64/common/basic/README
create mode 100644 tests/arm64/common/basic/arm_asm_macro.h
create mode 100644 tests/arm64/common/basic/arm_board.h
create mode 100644 tests/arm64/common/basic/arm_defines.h
create mode 100644 tests/arm64/common/basic/arm_entry.S
create mode 100644 tests/arm64/common/basic/arm_heap.c
create mode 100644 tests/arm64/common/basic/arm_heap.h
create mode 100644 tests/arm64/common/basic/arm_inline_asm.h
create mode 100644 tests/arm64/common/basic/arm_io.h
create mode 100644 tests/arm64/common/basic/arm_irq.c
create mode 100644 tests/arm64/common/basic/arm_irq.h
create mode 100644 tests/arm64/common/basic/arm_main.c
create mode 100644 tests/arm64/common/basic/arm_math.c
create mode 100644 tests/arm64/common/basic/arm_math.h
create mode 100644 tests/arm64/common/basic/arm_mmu.c
create mode 100644 tests/arm64/common/basic/arm_mmu.h
create mode 100644 tests/arm64/common/basic/arm_stdio.c
create mode 100644 tests/arm64/common/basic/arm_stdio.h
create mode 100644 tests/arm64/common/basic/arm_string.c
create mode 100644 tests/arm64/common/basic/arm_string.h
create mode 100644 tests/arm64/common/basic/arm_types.h
create mode 100644 tests/arm64/common/basic/dhry.h
create mode 100644 tests/arm64/common/basic/dhry_1.c
create mode 100644 tests/arm64/common/basic/dhry_2.c
create mode 100644 tests/arm64/common/basic/dhry_port.c
create mode 100644 tests/arm64/common/basic/dhry_port.h
create mode 100755 tests/arm64/common/basic/firmware.ld
create mode 100644 tests/arm64/common/basic/libfdt/cmd_fdt.c
create mode 100644 tests/arm64/common/basic/libfdt/fdt.c
create mode 100644 tests/arm64/common/basic/libfdt/fdt.h
create mode 100644 tests/arm64/common/basic/libfdt/fdt_ro.c
create mode 100644 tests/arm64/common/basic/libfdt/fdt_rw.c
create mode 100644 tests/arm64/common/basic/libfdt/fdt_strerror.c
create mode 100644 tests/arm64/common/basic/libfdt/fdt_support.c
create mode 100644 tests/arm64/common/basic/libfdt/fdt_support.h
create mode 100644 tests/arm64/common/basic/libfdt/fdt_sw.c
create mode 100644 tests/arm64/common/basic/libfdt/fdt_wip.c
create mode 100644 tests/arm64/common/basic/libfdt/libfdt.h
create mode 100644 tests/arm64/common/basic/libfdt/libfdt_env.h
create mode 100644 tests/arm64/common/basic/libfdt/libfdt_internal.h
create mode 100644 tests/arm64/common/basic/pic/gic.c
create mode 100644 tests/arm64/common/basic/pic/gic.h
create mode 100644 tests/arm64/common/basic/serial/pl01x.c
create mode 100644 tests/arm64/common/basic/serial/pl01x.h
create mode 100644 tests/arm64/common/basic/serial/virtio_console.c
create mode 100644 tests/arm64/common/basic/serial/virtio_console.h
create mode 100644 tests/arm64/common/basic/timer/generic_timer.c
create mode 100644 tests/arm64/common/basic/timer/generic_timer.h
create mode 100644 tests/arm64/common/busybox/README
create mode 100644 tests/arm64/common/busybox/busybox-1.21.0_defconfig
create mode 100644 tests/arm64/common/busybox/busybox_dev.txt
create mode 100644 tests/arm64/virt-v8/README
create mode 100644 tests/arm64/virt-v8/basic/Makefile
create mode 100644 tests/arm64/virt-v8/basic/README
create mode 100644 tests/arm64/virt-v8/basic/arm_board.c
create mode 100644 tests/arm64/virt-v8/basic/arm_plat.h
create mode 100644 tests/arm64/virt-v8/basic/gic_config.h
create mode 100644 tests/arm64/virt-v8/linux/README
create mode 100644 tests/arm64/virt-v8/linux/cmdlist
create mode 100644 tests/arm64/virt-v8/linux/linux-3.11-virtio-console-earlyprintk.patch
create mode 100644 tests/arm64/virt-v8/linux/linux-3.11_virt_v8_defconfig
create mode 100644 tests/arm64/virt-v8/linux/virt-v8.dts

--
1.7.9.5

Sukanto Ghosh

unread,
Sep 15, 2013, 4:08:44 AM9/15/13
to an...@brainfault.org, Sukanto Ghosh, xvisor...@googlegroups.com
This is the main patch for arm64 or armv8 or aarch64 CPU support.

This new arm64 port is very much in-line with arm32ve port because
the arm64 virtualization extensions is just 64-bit version of arm32ve
virtualization extensions.

Signed-off-by: Sukanto Ghosh <sukant...@gmail.com>
---
arch/arm/cpu/arm64/cpu_atomic.c | 124 +++
arch/arm/cpu/arm64/cpu_atomic64.c | 125 +++
arch/arm/cpu/arm64/cpu_cache.S | 278 +++++++
arch/arm/cpu/arm64/cpu_delay.S | 32 +
arch/arm/cpu/arm64/cpu_elf.c | 66 ++
arch/arm/cpu/arm64/cpu_entry.S | 665 ++++++++++++++++
arch/arm/cpu/arm64/cpu_init.c | 105 +++
arch/arm/cpu/arm64/cpu_interrupts.c | 237 ++++++
arch/arm/cpu/arm64/cpu_locks.c | 202 +++++
arch/arm/cpu/arm64/cpu_smp.S | 32 +
arch/arm/cpu/arm64/cpu_stacktrace.c | 125 +++
arch/arm/cpu/arm64/cpu_vcpu_coproc.c | 306 ++++++++
arch/arm/cpu/arm64/cpu_vcpu_emulate.c | 506 ++++++++++++
arch/arm/cpu/arm64/cpu_vcpu_helper.c | 991 ++++++++++++++++++++++++
arch/arm/cpu/arm64/cpu_vcpu_irq.c | 201 +++++
arch/arm/cpu/arm64/cpu_vcpu_mem.c | 135 ++++
arch/arm/cpu/arm64/cpu_vcpu_spr.c | 359 +++++++++
arch/arm/cpu/arm64/include/arch_barrier.h | 48 ++
arch/arm/cpu/arm64/include/arch_cache.h | 56 ++
arch/arm/cpu/arm64/include/arch_config.h | 30 +
arch/arm/cpu/arm64/include/arch_cpu_irq.h | 82 ++
arch/arm/cpu/arm64/include/arch_delay.h | 39 +
arch/arm/cpu/arm64/include/arch_elf.h | 99 +++
arch/arm/cpu/arm64/include/arch_io.h | 193 +++++
arch/arm/cpu/arm64/include/arch_regs.h | 152 ++++
arch/arm/cpu/arm64/include/arch_sections.h | 69 ++
arch/arm/cpu/arm64/include/arch_types.h | 71 ++
arch/arm/cpu/arm64/include/cpu_cache.h | 76 ++
arch/arm/cpu/arm64/include/cpu_defines.h | 706 +++++++++++++++++
arch/arm/cpu/arm64/include/cpu_generic_timer.h | 159 ++++
arch/arm/cpu/arm64/include/cpu_inline_asm.h | 243 ++++++
arch/arm/cpu/arm64/include/cpu_mmu_lpae.h | 55 ++
arch/arm/cpu/arm64/include/cpu_vcpu_coproc.h | 90 +++
arch/arm/cpu/arm64/include/cpu_vcpu_emulate.h | 96 +++
arch/arm/cpu/arm64/include/cpu_vcpu_helper.h | 59 ++
arch/arm/cpu/arm64/include/cpu_vcpu_mem.h | 57 ++
arch/arm/cpu/arm64/include/cpu_vcpu_spr.h | 69 ++
arch/arm/cpu/arm64/linker.ld | 119 +++
arch/arm/cpu/arm64/objects.mk | 52 ++
arch/arm/cpu/arm64/openconf.cfg | 56 ++
arch/arm/cpu/common/openconf.cfg | 4 +-
arch/arm/cpu/openconf.cfg | 24 +
42 files changed, 7191 insertions(+), 2 deletions(-)
diff --git a/arch/arm/cpu/arm64/cpu_atomic.c b/arch/arm/cpu/arm64/cpu_atomic.c
new file mode 100644
index 0000000..d5eb947
--- /dev/null
+++ b/arch/arm/cpu/arm64/cpu_atomic.c
@@ -0,0 +1,124 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_atomic.c
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief ARM64 specific synchronization mechanisms.
+ */
+
+#include <vmm_error.h>
+#include <vmm_types.h>
+#include <vmm_compiler.h>
+#include <arch_barrier.h>
+#include <arch_atomic.h>
+
+long __lock arch_atomic_read(atomic_t *atom)
+{
+ long ret = atom->counter;
+ arch_rmb();
+ return ret;
+}
+
+void __lock arch_atomic_write(atomic_t *atom, long value)
+{
+ atom->counter = value;
+ arch_wmb();
+}
+
+void __lock arch_atomic_add(atomic_t *atom, long value)
+{
+ unsigned int tmp;
+ long result;
+
+ asm volatile("// atomic_add\n"
+"1: ldxr %w0, [%3]\n"
+" add %w0, %w0, %w4\n"
+" stxr %w1, %w0, [%3]\n"
+" cbnz %w1,1b"
+ : "=&r" (result), "=&r" (tmp), "+o" (atom->counter)
+ : "r" (&atom->counter), "Ir" (value)
+ : "cc");
+}
+
+void __lock arch_atomic_sub(atomic_t *atom, long value)
+{
+ unsigned int tmp;
+ long result;
+
+ asm volatile("// atomic_sub\n"
+"1: ldxr %w0, [%3]\n"
+" sub %w0, %w0, %w4\n"
+" stxr %w1, %w0, [%3]\n"
+" cbnz %w1, 1b"
+ : "=&r" (result), "=&r" (tmp), "+o" (atom->counter)
+ : "r" (&atom->counter), "Ir" (value)
+ : "cc");
+}
+
+long __lock arch_atomic_add_return(atomic_t *atom, long value)
+{
+ unsigned int tmp;
+ long result;
+
+ asm volatile("// atomic_add_return\n"
+"1: ldaxr %w0, [%3]\n"
+" add %w0, %w0, %w4\n"
+" stlxr %w1, %w0, [%3]\n"
+" cbnz %w1, 1b"
+ : "=&r" (result), "=&r" (tmp), "+o" (atom->counter)
+ : "r" (&atom->counter), "Ir" (value)
+ : "cc");
+
+ return result;
+}
+
+long __lock arch_atomic_sub_return(atomic_t *atom, long value)
+{
+ unsigned int tmp;
+ long result;
+
+ asm volatile("// atomic_sub_return\n"
+"1: ldaxr %w0, [%3]\n"
+" sub %w0, %w0, %w4\n"
+" stlxr %w1, %w0, [%3]\n"
+" cbnz %w1, 1b"
+ : "=&r" (result), "=&r" (tmp), "+o" (atom->counter)
+ : "r" (&atom->counter), "Ir" (value)
+ : "cc");
+
+ return result;
+}
+
+long __lock arch_atomic_cmpxchg(atomic_t *atom, long oldval, long newval)
+{
+ unsigned int tmp;
+ long previous;
+
+ asm volatile("// atomic_cmpxchg\n"
+"1: ldaxr %w1, [%3]\n"
+" cmp %w1, %w4\n"
+" b.ne 2f\n"
+" stlxr %w0, %w5, [%3]\n"
+" cbnz %w0, 1b\n"
+"2:"
+ : "=&r" (tmp), "=&r" (previous), "+o" (atom->counter)
+ : "r" (&atom->counter), "Ir" (oldval), "r" (newval)
+ : "cc");
+
+ return previous;
+}
diff --git a/arch/arm/cpu/arm64/cpu_atomic64.c b/arch/arm/cpu/arm64/cpu_atomic64.c
new file mode 100644
index 0000000..604c990
--- /dev/null
+++ b/arch/arm/cpu/arm64/cpu_atomic64.c
@@ -0,0 +1,125 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_atomic64.c
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief ARM specific 64 bits synchronization mechanisms.
+ *
+ * derived from linux/arch/arm64/include/asm/atomic.h
+ *
+ * Copyright (C) 1996 Russell King.
+ * Copyright (C) 2002 Deep Blue Solutions Ltd.
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ */
+
+#include <vmm_error.h>
+#include <vmm_types.h>
+#include <vmm_compiler.h>
+#include <arch_cpu_irq.h>
+#include <arch_barrier.h>
+#include <arch_atomic64.h>
+
+u64 __lock arch_atomic64_read(atomic64_t *atom)
+{
+ return (*(volatile long *)&atom->counter);
+}
+
+void __lock arch_atomic64_write(atomic64_t *atom, u64 value)
+{
+ atom->counter = value;
+}
+
+void __lock arch_atomic64_add(atomic64_t *atom, u64 value)
+{
+ u64 result, tmp;
+
+ asm volatile("// atomic64_add\n"
+"1: ldxr %0, %2\n"
+" add %0, %0, %3\n"
+" stxr %w1, %0, %2\n"
+" cbnz %w1, 1b"
+ : "=&r" (result), "=&r" (tmp), "+Q" (atom->counter)
+ : "Ir" (value)
+ : "cc");
+}
+
+void __lock arch_atomic64_sub(atomic64_t *atom, u64 value)
+{
+ u64 result, tmp;
+
+ asm volatile("// atomic64_sub\n"
+"1: ldxr %0, %2\n"
+" sub %0, %0, %3\n"
+" stxr %w1, %0, %2\n"
+" cbnz %w1, 1b"
+ : "=&r" (result), "=&r" (tmp), "+Q" (atom->counter)
+ : "Ir" (value)
+ : "cc");
+}
+
+u64 __lock arch_atomic64_add_return(atomic64_t *atom, u64 value)
+{
+ u64 result, tmp;
+
+ asm volatile("// atomic64_add_return\n"
+"1: ldaxr %0, %2\n"
+" add %0, %0, %3\n"
+" stlxr %w1, %0, %2\n"
+" cbnz %w1, 1b"
+ : "=&r" (result), "=&r" (tmp), "+Q" (atom->counter)
+ : "Ir" (value)
+ : "cc", "memory");
+
+ return result;
+}
+
+u64 __lock arch_atomic64_sub_return(atomic64_t *atom, u64 value)
+{
+ u64 result, tmp;
+
+ asm volatile("// atomic64_sub_return\n"
+"1: ldaxr %0, %2\n"
+" sub %0, %0, %3\n"
+" stlxr %w1, %0, %2\n"
+" cbnz %w1, 1b"
+ : "=&r" (result), "=&r" (tmp), "+Q" (atom->counter)
+ : "Ir" (value)
+ : "cc", "memory");
+
+ return result;
+}
+
+u64 __lock arch_atomic64_cmpxchg(atomic64_t *atom, u64 oldval, u64 newval)
+{
+ u64 previous;
+ unsigned long res;
+
+ asm volatile("// atomic64_cmpxchg\n"
+"1: ldaxr %1, %2\n"
+" cmp %1, %3\n"
+" b.ne 2f\n"
+" stlxr %w0, %4, %2\n"
+" cbnz %w0, 1b\n"
+"2:"
+ : "=&r" (res), "=&r" (previous), "+Q" (atom->counter)
+ : "Ir" (oldval), "r" (newval)
+ : "cc", "memory");
+
+ return previous;
+}
diff --git a/arch/arm/cpu/arm64/cpu_cache.S b/arch/arm/cpu/arm64/cpu_cache.S
new file mode 100644
index 0000000..4022136
--- /dev/null
+++ b/arch/arm/cpu/arm64/cpu_cache.S
@@ -0,0 +1,278 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_cache.S
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief Low-level implementation of cache ARMv8 functions
+ */
+
+/* Stack pushing/popping (register pairs only).
+ Equivalent to store decrement before, load increment after */
+
+.macro push, xreg1, xreg2
+ stp \xreg1, \xreg2, [sp, #-16]!
+.endm
+
+.macro pop, xreg1, xreg2
+ ldp \xreg1, \xreg2, [sp], #16
+.endm
+
+#define lr x30
+
+/*
+ * dcache_line_size - get the minimum D-cache line size from the CTR register
+ * on ARMv8.
+ */
+.macro dcache_line_size, reg, tmp
+ mrs \tmp, ctr_el0 /* read ctr_el0 */
+ lsr \tmp, \tmp, #16
+ and \tmp, \tmp, #0xf /* cache line size encoding */
+ mov \reg, #4 /* bytes per word */
+ lsl \reg, \reg, \tmp /* actual cache line size */
+.endm
+
+/*
+ * Registers x0 - x10 are used.
+ */
+#define ARM_ENTIRE_DCACHE_OP(cacheop) \
+ \
+ push x0, x1 /* save registers */;\
+ push x2, x3 /* save registers */;\
+ push x4, x5 /* save registers */;\
+ push x6, x7 /* save registers */;\
+ push x8, x9 /* save registers */;\
+ push x10, x11 /* save registers */;\
+ dsb sy /* ensure ordering with previous memory accesses */;\
+ \
+ mrs x0, clidr_el1 /* Read CLIDR */;\
+ ands x3, x0, #0x7000000 ;\
+ lsr x3, x3, #23 /* Cache level value (naturally aligned) */; \
+ cbz x3, 5f ;\
+ mov x8, #0 ;\
+1: ;\
+ add x2, x8, x8, lsr #1 /* Work out 3xcachelevel */; \
+ lsr x1, x0, x2 /* bottom 3 bits are the Cache type for this level */; \
+ and x1, x1, #7 /* get those 3 bits alone */; \
+ cmp x1, #2 ;\
+ blt 4f /* no cache or only instruction cache at this level */; \
+ msr csselr_el1, x8 /* write the Cache Size selection register */; \
+ isb /* isb to sync the change to the CacheSizeID reg */; \
+ mrs x1, ccsidr_el1 /* reads current Cache Size ID register */; \
+ and x2, x1, #7 /* extract the line length field */; \
+ add x2, x2, #4 /* add 4 for the line length offset (log2 16 bytes) */; \
+ mov x4, #0x3ff ;\
+ ands x4, x4, x1, lsr #3 /* x4 is the max number on the way size (right aligned) */; \
+ clz w5, w4 /* x5 is the bit position of the way size increment */; \
+ mov x6, #0x7fff ;\
+ ands x6, x6, x1, lsr #13 /* x6 is the max number of the index size (right aligned) */; \
+2: ;\
+ mov x7, x4 /* x7 working copy of the max way size (right aligned) */; \
+3: ;\
+ lsl x1, x7, x5 ;\
+ orr x9, x10, x1 /* factor way and cache number into x9 */; \
+ lsl x1, x6, x2 ;\
+ orr x9, x9, x1 /* factor index number into x9 */; \
+ dc cacheop, x9 /* clean/invalidate/flush by set/way */; \
+ subs x7, x7, #1 /* decrement the way number */; \
+ bge 3b ;\
+ subs x6, x6, #1 /* decrement the index */; \
+ bge 2b ;\
+4: ;\
+ add x8, x8, #2 /* increment the cache number */; \
+ cmp x3, x8 ;\
+ bgt 1b ;\
+5: ;\
+ pop x10, x11 /* restore registers */;\
+ pop x8, x9 /* restore registers */;\
+ pop x6, x7 /* restore registers */;\
+ pop x4, x5 /* restore registers */;\
+ pop x2, x3 /* restore registers */;\
+ pop x0, x1 /* restore registers */;\
+
+ /*
+ * Operations on entire data Cache to POC
+ */
+
+ /* clean the entire data cache */
+ .globl clean_dcache
+clean_dcache:
+ ARM_ENTIRE_DCACHE_OP(csw) /* clean all */
+ dsb sy
+ isb
+ ret
+
+ /* clean & invalidate the entire data cache */
+ .globl clean_invalidate_dcache
+clean_invalidate_dcache:
+ ARM_ENTIRE_DCACHE_OP(cisw) /* clean and invalidate all */
+ dsb sy
+ isb
+ ret
+
+ /*
+ * Operations on data cache by MVA
+ */
+
+ /* clean by mva */
+ .globl clean_dcache_mva
+clean_dcache_mva:
+ dc cvac, x0
+ dsb sy
+ isb
+ ret
+
+ /* clean by memory region by mva range
+ * x0 - start address of region
+ * x1 - end address of region
+ */
+ .globl clean_dcache_mva_range
+clean_dcache_mva_range:
+ push x2, x3
+ dcache_line_size x2, x3
+ sub x3, x2, #1
+ bic x0, x0, x3
+1:
+ dc cvac, x0
+ add x0, x0, x2
+ cmp x0, x1
+ blo 1b
+ dsb sy
+ isb
+ pop x2, x3
+ ret
+
+ /* clean and invalidate by mva */
+ .globl clean_invalidate_dcache_mva
+clean_invalidate_dcache_mva:
+ dc civac, x0
+ dsb sy
+ isb
+ ret
+
+ /* clean and invalidate a memory region by mva
+ * x0 - start address of region
+ * x1 - end address of region
+ */
+ .globl clean_invalidate_dcache_mva_range
+clean_invalidate_dcache_mva_range:
+ push x2, x3
+ dcache_line_size x2, x3
+ sub x3, x2, #1
+ bic x0, x0, x3
+1:
+ dc civac, x0 /* clean & invalidate D / U line */
+ add x0, x0, x2
+ cmp x0, x1
+ blo 1b
+ dsb sy
+ isb
+ pop x2, x3
+ ret
+
+ /*
+ * Operations on data cache line by set/way
+ */
+
+ /* clean line by set/way */
+ .globl clean_dcache_line
+clean_dcache_line:
+ dc cvac, x0
+ dsb sy
+ isb
+ ret
+
+ /* clean and invalidate line by set/way */
+ .globl clean_invalidate_dcache_line
+clean_invalidate_dcache_line:
+ dc civac, x0
+ dsb sy
+ isb
+ ret
+
+ /*
+ * Operation on entire Instruction cache
+ */
+
+ /* invalidate the entire i-cache */
+ .globl invalidate_icache
+invalidate_icache:
+ ic ialluis /* invalidate all */
+ isb
+ ret
+
+ /* invalidate i-cache by mva */
+ .globl invalidate_icache_mva
+invalidate_icache_mva:
+ ic ivau, x0
+ isb
+ ret
+
+ /*
+ * Operations on entire instruction an data cache
+ */
+
+ /* clean the entire i-cache and d-cache */
+ .globl clean_idcache
+clean_idcache:
+ b clean_dcache
+
+ /* clean and invalidate the entire i-cache and d-cache */
+ .globl clean_invalidate_idcache
+clean_invalidate_idcache:
+ str lr, [sp, #8]!
+ bl invalidate_icache
+ bl clean_invalidate_dcache
+ ldr lr, [sp], #8
+ ret
+
+ /*
+ * operation on both i-cache and d-cache by mva
+ */
+
+ /* clean both i-cache and d-cache by mva */
+ .globl clean_idcache_mva
+clean_idcache_mva:
+ b clean_dcache_mva
+
+ /* clean and invalidate both i-cache and d-cache by mva */
+ .globl clean_invalidate_idcache_mva
+clean_invalidate_idcache_mva:
+ str lr, [sp, #8]!
+ bl invalidate_icache_mva
+ bl clean_invalidate_dcache_mva
+ ldr lr, [sp], #8
+ ret
+
+ /*
+ * operation on both i-cache and d-cache line by set/way
+ */
+
+ /* clean both i-cache and d-cache line by set/way */
+ .globl clean_idcache_line
+clean_idcache_line:
+ b clean_dcache_line
+
+ /* clean and invalidate both i-cache and d-cache line by set/way */
+ .globl clean_invalidate_idcache_line
+clean_invalidate_idcache_line:
+ str lr, [sp, #8]!
+ bl invalidate_icache
+ bl clean_invalidate_dcache_line
+ ldr lr, [sp], #8
+ ret
+
diff --git a/arch/arm/cpu/arm64/cpu_delay.S b/arch/arm/cpu/arm64/cpu_delay.S
new file mode 100644
index 0000000..0ecefd3
--- /dev/null
+++ b/arch/arm/cpu/arm64/cpu_delay.S
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_delay.S
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief Low-level implementation of delay functions
+ */
+
+ /*
+ * arch specific delay loop
+ */
+ .globl arch_delay_loop
+arch_delay_loop:
+ subs w0, w0, #1
+ b.hi arch_delay_loop
+ ret
+
diff --git a/arch/arm/cpu/arm64/cpu_elf.c b/arch/arm/cpu/arm64/cpu_elf.c
new file mode 100644
index 0000000..d7153ac
--- /dev/null
+++ b/arch/arm/cpu/arm64/cpu_elf.c
@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_elf.c
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief implementation of CPU specific elf functions
+ */
+
+#include <vmm_error.h>
+#include <vmm_stdio.h>
+#include <vmm_modules.h>
+#include <libs/elf.h>
+
+int arch_elf_check_hdr(const struct elf64_hdr *x)
+{
+ /* Make sure it's an AARCH64 executable */
+ if (x->e_machine != EM_AARCH64)
+ return 0;
+
+ /* Make sure the entry address is reasonable */
+ if (x->e_entry & 3)
+ return 0;
+
+ /* Don't allow unknown ABI */
+ if ((x->e_flags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int arch_elf_apply_relocate(struct elf64_shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relindex,
+ struct vmm_module *mod)
+{
+ vmm_printf("module %s: RELOCATION unsupported\n", mod->name);
+ return 0;
+}
+
+int arch_elf_apply_relocate_add(struct elf64_shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct vmm_module *mod)
+{
+ vmm_printf("module %s: ADD RELOCATION unsupported\n", mod->name);
+ return VMM_ENOEXEC;
+}
+
diff --git a/arch/arm/cpu/arm64/cpu_entry.S b/arch/arm/cpu/arm64/cpu_entry.S
new file mode 100644
index 0000000..55e76f8
--- /dev/null
+++ b/arch/arm/cpu/arm64/cpu_entry.S
@@ -0,0 +1,665 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_entry.S
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief entry points (booting, reset, exceptions) for ARMv8 family
+ */
+
+#include <cpu_defines.h>
+
+ /*
+ * _start: Primary CPU startup code
+ * _start_secondary: Secondary CPU startup code
+ *
+ * Note: Xvisor could be loaded any where in memory by boot loaders.
+ * The _start ensures that Xvisor exectues from intended
+ * base address provided at compile time.
+ */
+ .section .entry, "ax", %progbits
+ .globl _start
+ .globl _start_secondary
+_start:
+ /*
+ * x4 -> load start
+ * x5 -> load end
+ * x6 -> execution start
+ * x7 -> execution end
+ */
+ adr x4, . /* x4 <- pc */
+ ldr x6, __exec_start
+ ldr x7, __exec_end
+ sub x3, x7, x6
+ add x5, x4, x3
+
+ /* Save boot reg0 (i.e. x0) */
+ ldr x3, __boot_reg0
+ sub x3, x3, x6
+ add x3, x3, x4
+ str x0, [x3]
+
+ /* Save load start and load end addresses */
+ ldr x0, __load_start
+ sub x0, x0, x6
+ add x0, x0, x4
+ str x4, [x0]
+ ldr x0, __load_end
+ sub x0, x0, x6
+ add x0, x0, x4
+ str x5, [x0]
+
+ /* Hang if execution start is not 4 KB aligned */
+ movn x3, #0xfff
+ mov x0, x6
+ ands x0, x0, x3
+ cmp x0, x6
+ blt _start_hang
+
+ /* Hang if execution end is not 4 KB aligned */
+ mov x0, x7
+ ands x0, x0, x3
+ cmp x0, x7
+ blt _start_hang
+
+ /* Ensure that we are in hypervisor mode */
+ mrs x0, currentEL
+ cmp w0, #PSR_MODE64_EL2t
+ bne _start_hang
+
+ /*
+ * Setup Hypervisor System Control Register
+ * (we need to at least clear the A bit for
+ * _copy routine to work properly)
+ */
+ ldr x2, __hsctlr_clear
+ mrs x3, sctlr_el2
+ and x3, x3, x2
+ msr sctlr_el2, x3
+ dsb sy
+ isb
+
+ /* Zero-out bss section */
+ ldr x1, __bss_start
+ sub x1, x1, x6
+ add x1, x1, x4
+ ldr x2, __bss_end
+ sub x2, x2, x6
+ add x2, x2, x4
+_bss_zero:
+ str xzr, [x1], #8
+ cmp x1, x2
+ blt _bss_zero
+
+ /* Determine if a valid external dtb is provided */
+ /* Get DTB address */
+ ldr x3, __boot_reg0
+ sub x3, x3, x6
+ add x3, x3, x4
+ ldr x2, [x3]
+
+ /* First check for 8B alignment */
+ tst x2, #0x7
+ bne align_4k_boundary
+
+ /* Now check for FDT_MAGIC */
+ ldr w0, [x2]
+ ldr x1, __fdt_magic
+ cmp w0, w1
+ bne align_4k_boundary
+
+ /* Now get the dtb total-size */
+ ldr w0, [x2, #4]
+ rev w0, w0 /* Byte-swap as FDt is in big-endian */
+
+ /* Compare with max supported dtb size */
+ ldr x1, __max_dtb_size
+ cmp x0, x1
+ bgt align_4k_boundary
+
+ /* Overwrite the built-in fdt with the one passed */
+ ldr x1, __builtin_dtb
+ sub x1, x1, x6
+ add x1, x1, x4
+
+ /* x0 = dtb total size */
+ /* x1 = builtin_dtb load-address */
+ /* x2 = passed dtb address */
+
+dtb_save_loop:
+ ldr x3, [x2], #8
+ str x3, [x1], #8
+ subs x0, x0, #8
+ bgt dtb_save_loop
+
+align_4k_boundary:
+ /* Relocate code if load start is not 4 KB aligned */
+ mov x0, x4
+ movn x3, #0xfff
+ ands x0, x0, x3
+ cmp x0, x4
+ b.eq _start_mmu_init
+
+_start_relocate:
+ /* Relocate copy function at end after load end address */
+ ldr x0, __copy_start
+ ldr x1, __copy_end
+ sub x2, x1, x0
+ sub x0, x0, x6
+ add x0, x0, x4
+ mov x1, x0
+ mov x0, x5
+ bl _copy
+ /*
+ * Use newly relocated copy function to relocate entire code
+ */
+ mov x1, x4
+ mov x0, x5
+ sub x2, x5, x4
+ mov x0, x4
+ movn x3, #0xfff
+ ands x0, x0, x3
+ bl _start_nextpc1
+_start_nextpc1:
+ add x30, x30, #16
+ sub x30, x30, x4
+ add x30, x30, x0
+ br x5
+ /*
+ * Update load start and load end
+ * x4 -> new load start
+ * x5 -> new load end
+ */
+ mov x0, x4
+ movn x3, #0xfff
+ ands x0, x0, x3
+ sub x1, x4, x0
+ sub x4, x4, x1
+ sub x5, x5, x1
+ ldr x0, __load_start
+ sub x0, x0, x6
+ add x0, x0, x4
+ str x4, [x0]
+ ldr x0, __load_end
+ sub x0, x0, x6
+ add x0, x0, x4
+ str x5, [x0]
+
+_start_mmu_init:
+ /* Setup SP as-per load address */
+ ldr x0, __hvc_stack_end
+ mov sp, x0
+ sub sp, sp, x6
+ add sp, sp, x4
+
+ /* Saving x4 .. x7 in callee-saved regs */
+ mov x21, x4
+ mov x22, x5
+ mov x23, x6
+ mov x24, x7
+
+ /* Setup arguments and call setup_initial_ttbl */
+ mov x0, x4
+ mov x1, x5
+ mov x2, x6
+ mov x3, x7
+
+ bl _setup_initial_ttbl
+
+ /* Restoring x4 .. x7 from callee-saved regs */
+ mov x4, x21
+ mov x5, x22
+ mov x6, x23
+ mov x7, x24
+
+ /* Update the httbr value */
+ ldr x1, __httbr_set_addr
+ sub x1, x1, x6
+ add x1, x1, x4
+ ldr x0, [x1]
+ sub x0, x0, x6
+ add x0, x0, x4
+ str x0, [x1]
+ b _common_init
+
+#ifdef CONFIG_SMP
+ .align 3
+1: .dword .
+ .dword secondary_holding_pen_release
+__leds_base:
+ .dword 0x1c010008
+
+#define MPIDR_HWID_BITMASK 0xff00ffffff
+
+ /*
+ * Secondary CPU startup code
+ */
+_start_secondary:
+ /*
+ * This provides a "holding pen" for platforms to hold all secondary
+ * cores are held until we're ready for them to initialise.
+ */
+ ldr x15, __leds_base
+ mov w14, #0
+ str w14, [x15]
+
+ mrs x0, mpidr_el1
+ ldr x1, =MPIDR_HWID_BITMASK
+ and x0, x0, x1
+
+ /* Calculate load address of secondary_holding_pen_release */
+ adr x1, 1b
+ ldp x2, x3, [x1]
+ sub x1, x1, x2
+ add x3, x3, x1
+ sevl
+pen: wfe
+ ldr x4, [x3]
+ cmp x4, x0
+ bne pen
+#endif
+
+ /*
+ * Note: From this point primary CPU startup is same as secondary CPU
+ */
+_common_init:
+ /* Disable IRQ & FIQ */
+ msr daifset, #3
+
+ /* Ensure that we are in hypervisor mode */
+ mrs x0, currentEL
+ cmp w0, #PSR_MODE64_EL2t
+ bne _start_hang
+
+ /* Setup Hypervisor MAIR0 & MAIR1 */
+ ldr x0, __hmair_set
+ msr mair_el2, x0
+
+ /* Setup Hypervisor Translation Control Register */
+ ldr x0, __htcr_set
+ msr tcr_el2, x0
+
+ /* Setup Hypervisor Translation Base Register */
+ ldr x0, __httbr_set
+ msr ttbr0_el2, x0
+
+ /* Setup Hypervisor Stage2 Translation Control Register */
+ ldr x0, __vtcr_set
+ msr vtcr_el2, x0
+
+ /* Setup HCR */
+ ldr x0, __hcr_set
+ msr hcr_el2, x0
+
+ /* Setup temporary vector containing branch to self for debug */
+ ldr x0, __vbar_val
+ msr vbar_el2, x0
+
+ /* Set Hypervisor Stack */
+ ldr x0, __hvc_stack_end
+#ifdef CONFIG_SMP
+ mov x1, #CONFIG_IRQ_STACK_SIZE
+ mrs x10, mpidr_el1
+ ldr x2, =MPIDR_HWID_BITMASK
+ and x10, x2, x10
+ mul x1, x1, x10
+ sub x0, x0, x1
+#endif
+ mov sp, x0
+
+ /* Setup Hypervisor System Control Register */
+ ldr x1, __hsctlr_set
+ mrs x3, sctlr_el2
+ orr x3, x3, x1
+ msr sctlr_el2, x3
+ dsb sy
+ isb
+
+ ldr x0, __cpu_init
+ blr x0
+
+_start_hang:
+ b .
+
+#define FDT_MAGIC 0xedfe0dd0 /* 0xd00dfeed in big-endian */
+
+ .align 3
+__fdt_magic:
+ .dword FDT_MAGIC
+__builtin_dtb:
+ .dword dt_blob_start
+__max_dtb_size:
+ .dword CONFIG_ARM_MAX_DTB_SIZE
+__hmair_set:
+ .dword (MAIR_INITVAL)
+__htcr_set:
+ .dword ((0x19 << TCR_T0SZ_SHIFT) | (0x2 << TCR_PS_SHIFT) | (0x3 << TCR_SH0_SHIFT) | (0x1 << TCR_ORGN0_SHIFT) | (0x1 << TCR_IRGN0_SHIFT))
+__vtcr_set:
+ .dword ((0x1 << VTCR_SL0_SHIFT) | (0x19 << VTCR_T0SZ_SHIFT) | (0x2 << VTCR_PS_SHIFT) | (0x3 << VTCR_SH0_SHIFT) | (0x1 << VTCR_ORGN0_SHIFT) | (0x1 << VTCR_IRGN0_SHIFT))
+__hsctlr_clear:
+ .dword ~(SCTLR_A_MASK)
+__hsctlr_set:
+ .dword (SCTLR_M_MASK | SCTLR_C_MASK | SCTLR_I_MASK)
+__hcr_set:
+ .dword (HCR_AMO_MASK | HCR_IMO_MASK | HCR_FMO_MASK | HCR_VM_MASK)
+__exec_start:
+ .dword _code_start
+__exec_end:
+ .dword _code_end
+__load_start:
+ .dword _load_start
+__load_end:
+ .dword _load_end
+__bss_start:
+ .dword _bss_start
+__bss_end:
+ .dword _bss_end
+__copy_start:
+ .dword _copy
+__copy_end:
+ .dword _copy_end
+__httbr_set_addr:
+ .dword __httbr_set
+__httbr_set:
+ .dword def_ttbl
+__cpu_init:
+ .dword cpu_init
+__vbar_val:
+ .dword vectors
+__boot_reg0:
+ .dword _boot_reg0
+
+ /*
+ * Boot register 0 passed by bootloader
+ */
+ .globl _boot_reg0
+_boot_reg0:
+ .dword 0x0
+
+ /*
+ * Load start address storage
+ */
+ .globl _load_start
+_load_start:
+ .dword 0x0
+
+ /*
+ * Load end address storage
+ */
+ .globl _load_end
+_load_end:
+ .dword 0x0
+
+ /*
+ * Exception stacks.
+ */
+__hvc_stack_end:
+ .dword _hvc_stack_end
+
+ /*
+ * Copy data from source to destination
+ * (alignment handled by hardware)
+ * Arguments:
+ * x0 -> destination address
+ * x1 -> source address
+ * x2 -> byte count
+ * Return:
+ * x0 -> bytes copied
+ */
+ .section .entry, "ax", %progbits
+ .globl _copy
+_copy:
+ mov x4, x2
+ subs x2, x2, #8
+ b.mi 2f
+1: ldr x3, [x1], #8
+ subs x2, x2, #8
+ str x3, [x0], #8
+ b.pl 1b
+2: adds x2, x2, #4
+ b.mi 3f
+ ldr w3, [x1], #4
+ sub x2, x2, #4
+ str w3, [x0], #4
+3: adds x2, x2, #2
+ b.mi 4f
+ ldrh w3, [x1], #2
+ sub x2, x2, #2
+ strh w3, [x0], #2
+4: adds x2, x2, #1
+ b.mi 5f
+ ldrb w3, [x1]
+ strb w3, [x0]
+5: mov x0, x4
+ ret
+_copy_end:
+
+
+
+
+/* Stack pushing/popping (register pairs only).
+ Equivalent to store decrement before, load increment after */
+
+.macro push, xreg1, xreg2
+ stp \xreg1, \xreg2, [sp, #-16]!
+.endm
+
+.macro pop, xreg1, xreg2
+ ldp \xreg1, \xreg2, [sp], #16
+.endm
+
+
+.macro EXCEPTION_HANDLER irqname
+ .align 6
+\irqname:
+.endm
+
+
+/* Push registers on stack */
+.macro PUSH_REGS
+ sub sp, sp, #0x20 /* room for LR, SP, SPSR, ELR */
+ push x28, x29
+ push x26, x27
+ push x24, x25
+ push x22, x23
+ push x20, x21
+ push x18, x19
+ push x16, x17
+ push x14, x15
+ push x12, x13
+ push x10, x11
+ push x8, x9
+ push x6, x7
+ push x4, x5
+ push x2, x3
+ push x0, x1
+ add x21, sp, #0x110
+ mrs x22, elr_el2
+ mrs x23, spsr_el2
+ stp x30, x21, [sp, #0xF0]
+ stp x22, x23, [sp, #0x100]
+ /*
+ * Registers that may be useful after this macro is invoked:
+ *
+ * x21 - aborted SP
+ * x22 - aborted PC
+ * x23 - aborted PSTATE
+ */
+.endm
+
+/* Call C function to handle exception */
+.macro CALL_EXCEPTION_CFUNC cfunc
+ mov x0, sp
+ bl \cfunc
+.endm
+
+/* Pull registers from stack */
+.macro PULL_REGS
+ ldp x21, x22, [sp, #0x100] /* load ELR, SPSR */
+ msr elr_el2, x21
+ msr spsr_el2, x22
+ pop x0, x1
+ pop x2, x3
+ pop x4, x5
+ pop x6, x7
+ pop x8, x9
+ pop x10, x11
+ pop x12, x13
+ pop x14, x15
+ pop x16, x17
+ pop x18, x19
+ pop x20, x21
+ pop x22, x23
+ pop x24, x25
+ pop x26, x27
+ pop x28, x29
+ msr tpidr_el2, x24
+ ldp x30, x24, [sp]
+ mov sp, x24
+ mrs x24, tpidr_el2
+ eret
+.endm
+
+
+/*
+ * Exception vectors.
+ */
+.macro ventry label
+ .align 7
+ b \label
+.endm
+
+ .align 11
+ .globl vectors;
+vectors:
+ ventry hyp_sync_invalid /* Synchronous EL1t */
+ ventry hyp_irq_invalid /* IRQ EL1t */
+ ventry hyp_fiq_invalid /* FIQ EL1t */
+ ventry hyp_error_invalid /* Error EL1t */
+
+ ventry hyp_sync /* Synchronous EL1h */
+ ventry hyp_irq /* IRQ EL1h */
+ ventry hyp_fiq_invalid /* FIQ EL1h */
+ ventry hyp_error_invalid /* Error EL1h */
+
+ ventry guest_sync_a64 /* Synchronous 64-bit EL0 */
+ ventry guest_irq_a64 /* IRQ 64-bit EL0 */
+ ventry guest_fiq_a64 /* FIQ 64-bit EL0 */
+ ventry guest_error_a64 /* Error 64-bit EL0 */
+
+ ventry guest_sync_a32 /* Synchronous 32-bit EL0 */
+ ventry guest_irq_a32 /* IRQ 32-bit EL0 */
+ ventry guest_fiq_a32 /* FIQ 32-bit EL0 */
+ ventry guest_error_a32 /* Error 32-bit EL0 */
+
+
+EXCEPTION_HANDLER hyp_sync_invalid
+ PUSH_REGS
+ mov x1, EXC_HYP_SYNC_SP0
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER hyp_irq_invalid
+ PUSH_REGS
+ mov x1, EXC_HYP_IRQ_SP0
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER hyp_fiq_invalid
+ PUSH_REGS
+ mov x1, EXC_HYP_FIQ_SP0
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER hyp_error_invalid
+ PUSH_REGS
+ mov x1, EXC_HYP_SERROR_SP0
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER hyp_sync
+ PUSH_REGS
+ mov x1, EXC_HYP_SYNC_SPx
+ CALL_EXCEPTION_CFUNC do_sync
+ PULL_REGS
+
+EXCEPTION_HANDLER hyp_irq
+ PUSH_REGS
+ mov x1, EXC_HYP_IRQ_SPx
+ CALL_EXCEPTION_CFUNC do_irq
+ PULL_REGS
+
+EXCEPTION_HANDLER hyp_fiq
+ PUSH_REGS
+ mov x1, EXC_HYP_FIQ_SPx
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER hyp_error
+ PUSH_REGS
+ mov x1, EXC_HYP_SERROR_SPx
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER guest_sync_a64
+ PUSH_REGS
+ mov x1, EXC_GUEST_SYNC_A64
+ CALL_EXCEPTION_CFUNC do_sync
+ PULL_REGS
+
+EXCEPTION_HANDLER guest_irq_a64
+ PUSH_REGS
+ mov x1, EXC_GUEST_IRQ_A64
+ CALL_EXCEPTION_CFUNC do_irq
+ PULL_REGS
+
+EXCEPTION_HANDLER guest_fiq_a64
+ PUSH_REGS
+ mov x1, EXC_GUEST_FIQ_A64
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER guest_error_a64
+ PUSH_REGS
+ mov x1, EXC_GUEST_SERROR_A64
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER guest_sync_a32
+ PUSH_REGS
+ mov x1, EXC_GUEST_SYNC_A32
+ CALL_EXCEPTION_CFUNC do_sync
+ PULL_REGS
+
+EXCEPTION_HANDLER guest_irq_a32
+ PUSH_REGS
+ mov x1, EXC_GUEST_IRQ_A32
+ CALL_EXCEPTION_CFUNC do_irq
+ PULL_REGS
+
+EXCEPTION_HANDLER guest_fiq_a32
+ PUSH_REGS
+ mov x1, EXC_GUEST_FIQ_A32
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER guest_error_a32
+ PUSH_REGS
+ mov x1, EXC_GUEST_SERROR_A32
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
diff --git a/arch/arm/cpu/arm64/cpu_init.c b/arch/arm/cpu/arm64/cpu_init.c
new file mode 100644
index 0000000..5f7df86
--- /dev/null
+++ b/arch/arm/cpu/arm64/cpu_init.c
@@ -0,0 +1,105 @@
+/**
+ * Copyright (c) 2012 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_init.c
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief intialization functions for CPU
+ */
+
+#include <vmm_error.h>
+#include <vmm_smp.h>
+#include <vmm_main.h>
+#include <vmm_params.h>
+#include <vmm_devtree.h>
+#include <arch_cpu.h>
+
+extern u8 _code_start;
+extern u8 _code_end;
+extern physical_addr_t _load_start;
+extern physical_addr_t _load_end;
+
+virtual_addr_t arch_code_vaddr_start(void)
+{
+ return (virtual_addr_t) &_code_start;
+}
+
+physical_addr_t arch_code_paddr_start(void)
+{
+ return (physical_addr_t) _load_start;
+}
+
+virtual_size_t arch_code_size(void)
+{
+ return (virtual_size_t) (&_code_end - &_code_start);
+}
+
+int __init arch_cpu_early_init(void)
+{
+ char *attr;
+ struct vmm_devtree_node *node;
+
+ /*
+ * Host virtual memory, device tree, heap is up.
+ * Do necessary early stuff like iomapping devices
+ * memory or boot time memory reservation here.
+ */
+
+ node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
+ VMM_DEVTREE_CHOSEN_NODE_NAME);
+ if (!node) {
+ return VMM_ENODEV;
+ }
+
+ attr = vmm_devtree_attrval(node, VMM_DEVTREE_BOOTARGS_ATTR_NAME);
+ if (attr) {
+ vmm_parse_early_options(attr);
+ }
+
+ return VMM_OK;
+}
+
+void arch_cpu_print_info(struct vmm_chardev *cdev)
+{
+ /* FIXME: To be implemented. */
+}
+
+int __init arch_cpu_final_init(void)
+{
+ /* All VMM API's are available here */
+ /* We can register a CPU specific resources here */
+ return VMM_OK;
+}
+
+void __init cpu_init(void)
+{
+#if defined(CONFIG_SMP)
+ u32 cpu = vmm_smp_processor_id();
+
+ if (!cpu) { /* Primary CPU */
+ vmm_init();
+ } else { /* Secondary CPUs */
+ vmm_init_secondary();
+ }
+#else
+ /* Initialize VMM (APIs only available after this) */
+ vmm_init();
+#endif
+
+ /* We will never come back here. */
+ vmm_hang();
+}
diff --git a/arch/arm/cpu/arm64/cpu_interrupts.c b/arch/arm/cpu/arm64/cpu_interrupts.c
new file mode 100644
index 0000000..64824e8
--- /dev/null
+++ b/arch/arm/cpu/arm64/cpu_interrupts.c
@@ -0,0 +1,237 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_interrupts.c
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief source code for handling cpu interrupts
+ */
+
+#include <vmm_error.h>
+#include <vmm_smp.h>
+#include <vmm_stdio.h>
+#include <vmm_host_irq.h>
+#include <vmm_scheduler.h>
+#include <cpu_inline_asm.h>
+#include <cpu_vcpu_spr.h>
+#include <cpu_vcpu_emulate.h>
+#include <cpu_vcpu_helper.h>
+#include <cpu_defines.h>
+
+void do_bad_mode(arch_regs_t *regs, unsigned long mode)
+{
+ u32 ec, il, iss;
+ u64 esr, far, elr;
+ struct vmm_vcpu *vcpu;
+
+ esr = mrs(esr_el2);
+ far = mrs(far_el2);
+ elr = mrs(elr_el2);
+
+ ec = (esr & ESR_EC_MASK) >> ESR_EC_SHIFT;
+ il = (esr & ESR_IL_MASK) >> ESR_IL_SHIFT;
+ iss = (esr & ESR_ISS_MASK) >> ESR_ISS_SHIFT;
+
+ vcpu = vmm_scheduler_current_vcpu();
+
+ vmm_printf("%s: CPU%d VCPU=%s unexpected exception\n",
+ __func__, vmm_smp_processor_id(),
+ (vcpu) ? vcpu->name : "(NULL)");
+ vmm_printf("%s: ESR=0x%016lx EC=0x%x IL=0x%x ISS=0x%x\n",
+ __func__, esr, ec, il, iss);
+ vmm_printf("%s: ELR=0x%016lx FAR=0x%016lx HPFAR=0x%016lx\n",
+ __func__, elr, far, mrs(hpfar_el2));
+ cpu_vcpu_dump_user_reg(regs);
+ vmm_panic("%s: please reboot ...\n", __func__);
+}
+
+void do_sync(arch_regs_t *regs, unsigned long mode)
+{
+ int rc = VMM_OK;
+ u32 ec, il, iss;
+ u64 esr, far, elr;
+ physical_addr_t fipa = 0;
+ struct vmm_vcpu *vcpu;
+
+ esr = mrs(esr_el2);
+ far = mrs(far_el2);
+ elr = mrs(elr_el2);
+
+ ec = (esr & ESR_EC_MASK) >> ESR_EC_SHIFT;
+ il = (esr & ESR_IL_MASK) >> ESR_IL_SHIFT;
+ iss = (esr & ESR_ISS_MASK) >> ESR_ISS_SHIFT;
+
+ vcpu = vmm_scheduler_current_vcpu();
+
+ /* We dont expect any faults from hypervisor code itself
+ * so, any trap we get from hypervisor mode means something
+ * unexpected has occured.
+ */
+ if ((regs->pstate & PSR_EL_MASK) == PSR_EL_2) {
+ if ((ec == EC_TRAP_HVC_A64) && (iss == 0)) {
+ vmm_scheduler_preempt_orphan(regs);
+ return;
+ }
+ vmm_printf("%s: CPU%d VCPU=%s unexpected exception\n",
+ __func__, vmm_smp_processor_id(),
+ (vcpu) ? vcpu->name : "(NULL)");
+ vmm_printf("%s: ESR=0x%016lx EC=0x%x IL=0x%x ISS=0x%x\n",
+ __func__, esr, ec, il, iss);
+ vmm_printf("%s: ELR=0x%016lx FAR=0x%016lx HPFAR=0x%016lx\n",
+ __func__, elr, far, mrs(hpfar_el2));
+ cpu_vcpu_dump_user_reg(regs);
+ vmm_panic("%s: please reboot ...\n", __func__);
+ }
+
+ vmm_scheduler_irq_enter(regs, TRUE);
+
+ switch (ec) {
+ case EC_UNKNOWN:
+ /* We dont expect to get this trap so error */
+ rc = VMM_EFAIL;
+ break;
+ case EC_TRAP_WFI_WFE:
+ /* WFI emulation */
+ rc = cpu_vcpu_emulate_wfi_wfe(vcpu, regs, il, iss);
+ break;
+ case EC_TRAP_MCR_MRC_CP15_A32:
+ /* MCR/MRC CP15 emulation */
+ rc = cpu_vcpu_emulate_mcr_mrc_cp15(vcpu, regs, il, iss);
+ break;
+ case EC_TRAP_MCRR_MRRC_CP15_A32:
+ /* MCRR/MRRC CP15 emulation */
+ rc = cpu_vcpu_emulate_mcrr_mrrc_cp15(vcpu, regs, il, iss);
+ break;
+ case EC_TRAP_MCR_MRC_CP14_A32:
+ /* MCR/MRC CP14 emulation */
+ rc = cpu_vcpu_emulate_mcr_mrc_cp14(vcpu, regs, il, iss);
+ break;
+ case EC_TRAP_LDC_STC_CP14_A32:
+ /* LDC/STC CP14 emulation */
+ rc = cpu_vcpu_emulate_ldc_stc_cp14(vcpu, regs, il, iss);
+ break;
+ case EC_SIMD_FPU:
+ /* Advanced SIMD and FPU emulation */
+ rc = cpu_vcpu_emulate_simd_fp_regs(vcpu, regs, il, iss);
+ break;
+ case EC_FPEXC_A32:
+ case EC_FPEXC_A64:
+ /* We dont expect any FP execution faults */
+ rc = VMM_EFAIL;
+ break;
+ case EC_TRAP_MRC_VMRS_CP10_A32:
+ /* MRC (or VMRS) to CP10 for MVFR0, MVFR1 or FPSID */
+ rc = cpu_vcpu_emulate_vmrs(vcpu, regs, il, iss);
+ break;
+ case EC_TRAP_MCRR_MRRC_CP14_A32:
+ /* MRRC to CP14 emulation */
+ rc = cpu_vcpu_emulate_mcrr_mrrc_cp14(vcpu, regs, il, iss);
+ break;
+ case EC_TRAP_SVC_A32:
+ case EC_TRAP_SVC_A64:
+ case EC_TRAP_SMC_A32:
+ case EC_TRAP_SMC_A64:
+ /* We dont expect to get these traps so error */
+ rc = VMM_EFAIL;
+ break;
+ case EC_TRAP_HVC_A32:
+ /* Hypercall or HVC emulation for A32 guest */
+ rc = cpu_vcpu_emulate_hvc32(vcpu, regs, il, iss);
+ break;
+ case EC_TRAP_HVC_A64:
+ /* Hypercall or HVC emulation for A64 guest */
+ rc = cpu_vcpu_emulate_hvc64(vcpu, regs, il, iss);
+ break;
+ case EC_TRAP_MSR_MRS_SYSTEM:
+ /* MSR/MRS/SystemRegs emulation */
+ rc = cpu_vcpu_emulate_msr_mrs_system(vcpu, regs, il, iss);
+ break;
+ case EC_TRAP_LWREL_INST_ABORT:
+ /* Stage2 instruction abort */
+ fipa = (mrs(hpfar_el2) & HPFAR_FIPA_MASK) >> HPFAR_FIPA_SHIFT;
+ fipa = fipa << HPFAR_FIPA_PAGE_SHIFT;
+ fipa = fipa | (mrs(far_el2) & HPFAR_FIPA_PAGE_MASK);
+ rc = cpu_vcpu_inst_abort(vcpu, regs, il, iss, fipa);
+ break;
+ case EC_TRAP_LWREL_DATA_ABORT:
+ /* Stage2 data abort */
+ fipa = (mrs(hpfar_el2) & HPFAR_FIPA_MASK) >> HPFAR_FIPA_SHIFT;
+ fipa = fipa << HPFAR_FIPA_PAGE_SHIFT;
+ fipa = fipa | (mrs(far_el2) & HPFAR_FIPA_PAGE_MASK);
+ rc = cpu_vcpu_data_abort(vcpu, regs, il, iss, fipa);
+ break;
+ case EC_CUREL_INST_ABORT:
+ case EC_CUREL_DATA_ABORT:
+ case EC_SERROR:
+ /* We dont expect to get aborts from EL2 so error */
+ rc = VMM_EFAIL;
+ break;
+ case EC_PC_UNALIGNED:
+ case EC_SP_UNALIGNED:
+ /* We dont expect to get alignment faults from EL2 */
+ rc = VMM_EFAIL;
+ break;
+ default:
+ /* Unhandled or unknown EC value so error */
+ rc = VMM_EFAIL;
+ break;
+ };
+
+ if (rc) {
+ vmm_printf("%s: CPU%d VCPU=%s sync failed (error %d)\n",
+ __func__, vmm_smp_processor_id(),
+ (vcpu) ? vcpu->name : "(NULL)", rc);
+ vmm_printf("%s: ESR=0x%016lx EC=0x%x IL=0x%x ISS=0x%x\n",
+ __func__, esr, ec, il, iss);
+ vmm_printf("%s: ELR=0x%016lx FAR=0x%016lx HPFAR=0x%016lx\n",
+ __func__, elr, far, mrs(hpfar_el2));
+ if (vcpu->state != VMM_VCPU_STATE_HALTED) {
+ cpu_vcpu_halt(vcpu, regs);
+ }
+ }
+
+ vmm_scheduler_irq_exit(regs);
+}
+
+void do_irq(arch_regs_t *regs)
+{
+ vmm_scheduler_irq_enter(regs, FALSE);
+
+ vmm_host_irq_exec(EXC_HYP_IRQ_SPx);
+
+ vmm_scheduler_irq_exit(regs);
+}
+
+void do_hyp_fiq(arch_regs_t *regs)
+{
+ vmm_scheduler_irq_enter(regs, FALSE);
+
+ vmm_host_irq_exec(CPU_EXTERNAL_FIQ);
+
+ vmm_scheduler_irq_exit(regs);
+}
+
+int __cpuinit arch_cpu_irq_setup(void)
+{
+ extern u32 vectors[];
+
+ /* Update VBAR_EL2 to point to hypervisor vector table */
+ msr_sync(vbar_el2, (virtual_addr_t)&vectors);
+
+ return VMM_OK;
+}
+
diff --git a/arch/arm/cpu/arm64/cpu_locks.c b/arch/arm/cpu/arm64/cpu_locks.c
new file mode 100644
index 0000000..2feb633
--- /dev/null
+++ b/arch/arm/cpu/arm64/cpu_locks.c
@@ -0,0 +1,202 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_locks.c
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief ARM64 specific synchronization mechanisms.
+ */
+
+#include <vmm_error.h>
+#include <vmm_types.h>
+#include <vmm_smp.h>
+#include <vmm_compiler.h>
+#include <arch_barrier.h>
+
+bool __lock arch_spin_lock_check(arch_spinlock_t *lock)
+{
+ return (lock->lock == __ARCH_SPIN_UNLOCKED) ? FALSE : TRUE;
+}
+
+void __lock arch_spin_lock(arch_spinlock_t *lock)
+{
+ u32 cpu = vmm_smp_processor_id();
+ unsigned long tmp;
+
+ __asm__ __volatile__(
+" sevl\n"
+"1: wfe\n"
+"2: ldaxr %w0, %1\n"
+" cmp %w0, %w3\n"
+" b.ne 1b\n"
+" stxr %w0, %w2, %1\n"
+" cbnz %w0, 2b\n"
+ : "=&r" (tmp), "+Q" (lock->lock)
+ : "r" (cpu), "r" (__ARCH_SPIN_UNLOCKED)
+ : "cc", "memory");
+
+ arch_smp_mb();
+}
+
+int arch_spin_trylock(arch_spinlock_t *lock)
+{
+ u32 cpu = vmm_smp_processor_id();
+ unsigned int tmp;
+
+ asm volatile(
+" ldaxr %w0, %1\n"
+" cmp %w0, %w3\n"
+" b.ne 1f\n"
+" stxr %w0, %w2, %1\n"
+" b 2f\n"
+"1: mov %w0, #1\n"
+"2:\n"
+ : "=&r" (tmp), "+Q" (lock->lock)
+ : "r" (cpu), "r" (__ARCH_SPIN_UNLOCKED)
+ : "cc", "memory");
+
+ if (tmp == 0) {
+ arch_smp_mb(); /* do mb if we succeeded */
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void __lock arch_spin_unlock(arch_spinlock_t *lock)
+{
+ arch_smp_mb();
+
+ __asm__ __volatile__(
+" stlr %w1, %0\n"
+ : "=Q" (lock->lock) : "r" (__ARCH_SPIN_UNLOCKED)
+ : "memory");
+}
+
+bool __lock arch_write_lock_check(arch_rwlock_t *lock)
+{
+ return (lock->lock & __ARCH_RW_LOCKED) ? TRUE : FALSE;
+}
+
+/*
+ * To take a write lock we set bit 31 to 1
+ */
+void __lock arch_write_lock(arch_rwlock_t *lock)
+{
+ unsigned int tmp;
+
+ __asm__ __volatile__(
+ " sevl\n"
+ "1: wfe\n"
+ "2: ldaxr %w0, [%1]\n"
+ " cbnz %w0, 1b\n"
+ " stxr %w0, %w2, [%1]\n"
+ " cbnz %w0, 2b\n"
+ : "=&r" (tmp)
+ : "r" (&lock->lock), "r" (__ARCH_RW_LOCKED)
+ : "memory");
+
+ arch_smp_mb();
+}
+
+int __lock arch_write_trylock(arch_rwlock_t *lock)
+{
+ unsigned int tmp;
+
+ asm volatile(
+ " ldaxr %w0, [%1]\n"
+ " cbnz %w0, 1f\n"
+ " stxr %w0, %w2, [%1]\n"
+ "1:\n"
+ : "=&r" (tmp)
+ : "r" (&lock->lock), "r" (__ARCH_RW_LOCKED)
+ : "memory");
+
+ if (tmp == 0) {
+ arch_smp_mb();
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void __lock arch_write_unlock(arch_rwlock_t *lock)
+{
+ asm volatile(
+ " stlr %w1, [%0]\n"
+ : : "r" (&lock->lock), "r" (0) : "memory");
+}
+
+bool __lock arch_read_lock_check(arch_rwlock_t *lock)
+{
+ return (lock->lock == __ARCH_RW_UNLOCKED) ? FALSE : TRUE;
+}
+
+void __lock arch_read_lock(arch_rwlock_t *lock)
+{
+ unsigned int tmp, tmp2;
+
+ asm volatile(
+ " sevl\n"
+ "1: wfe\n"
+ "2: ldaxr %w0, [%2]\n"
+ " add %w0, %w0, #1\n"
+ " tbnz %w0, #31, 1b\n"
+ " stxr %w1, %w0, [%2]\n"
+ " cbnz %w1, 2b\n"
+ : "=&r" (tmp), "=&r" (tmp2)
+ : "r" (&lock->lock)
+ : "memory");
+}
+
+int __lock arch_read_trylock(arch_rwlock_t *lock)
+{
+ unsigned int tmp, tmp2 = 1;
+
+ asm volatile(
+ " ldaxr %w0, [%2]\n"
+ " add %w0, %w0, #1\n"
+ " tbnz %w0, #31, 1f\n"
+ " stxr %w1, %w0, [%2]\n"
+ "1:\n"
+ : "=&r" (tmp), "+r" (tmp2)
+ : "r" (&lock->lock)
+ : "memory");
+
+ if (tmp2 == 0) {
+ arch_smp_mb(); /* do mb if we succeeded */
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void __lock arch_read_unlock(arch_rwlock_t *lock)
+{
+ unsigned int tmp, tmp2;
+
+ arch_smp_mb();
+
+ asm volatile(
+ "1: ldxr %w0, [%2]\n"
+ " sub %w0, %w0, #1\n"
+ " stlxr %w1, %w0, [%2]\n"
+ " cbnz %w1, 1b\n"
+ : "=&r" (tmp), "=&r" (tmp2)
+ : "r" (&lock->lock)
+ : "memory");
+}
diff --git a/arch/arm/cpu/arm64/cpu_smp.S b/arch/arm/cpu/arm64/cpu_smp.S
new file mode 100644
index 0000000..4885187
--- /dev/null
+++ b/arch/arm/cpu/arm64/cpu_smp.S
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_smp.S
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief Low-level implementation of SMP functions
+ */
+
+ /*
+ * Retrive SMP ID of current processor
+ */
+ .globl arch_smp_id
+arch_smp_id:
+ mrs x0, mpidr_el1
+ ands x0, x0, #0xff
+ ret
+
diff --git a/arch/arm/cpu/arm64/cpu_stacktrace.c b/arch/arm/cpu/arm64/cpu_stacktrace.c
new file mode 100644
index 0000000..9567fc6
--- /dev/null
+++ b/arch/arm/cpu/arm64/cpu_stacktrace.c
@@ -0,0 +1,125 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_stacktrace.c
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief ARM64 specific function stacktrace.
+ *
+ * Portions of this file are derived from arch/arm/kernel/stacktrace.c
+ * in linux source
+ *
+ */
+
+#include <vmm_compiler.h>
+#include <vmm_stdio.h>
+#include <vmm_error.h>
+#include <libs/kallsyms.h>
+#include <libs/stacktrace.h>
+
+struct stackframe {
+ unsigned long fp;
+ unsigned long sp;
+ unsigned long lr;
+ unsigned long pc;
+};
+
+/*
+ * AArch64 PCS assigns the frame pointer to x29.
+ *
+ * A simple function prologue looks like this:
+ * sub sp, sp, #0x10
+ * stp x29, x30, [sp]
+ * mov x29, sp
+ *
+ * A simple function epilogue looks like this:
+ * mov sp, x29
+ * ldp x29, x30, [sp]
+ * add sp, sp, #0x10
+ */
+int unwind_frame(struct stackframe *frame)
+{
+ unsigned long low;
+ unsigned long fp = frame->fp;
+
+ low = frame->sp;
+
+ // if (fp < low || fp & 0xf)
+ if (fp < low)
+ return -1;
+
+ frame->sp = fp + 0x10;
+ frame->fp = *(unsigned long *)(fp);
+ frame->pc = *(unsigned long *)(fp + 8);
+
+ return 0;
+}
+
+void walk_stackframe(struct stackframe *frame,
+ int (*fn)(struct stackframe *, void *), void *data)
+{
+ while (1) {
+ int ret;
+
+ if (fn(frame, data))
+ break;
+ ret = unwind_frame(frame);
+ if (ret < 0)
+ break;
+ }
+}
+
+struct stack_trace_data {
+ struct stack_trace *trace;
+ unsigned int skip;
+};
+
+static int save_trace(struct stackframe *frame, void *d)
+{
+ struct stack_trace_data *data = d;
+ struct stack_trace *trace = data->trace;
+ unsigned long addr = frame->pc;
+
+ if (data->skip) {
+ data->skip--;
+ return 0;
+ }
+
+ trace->entries[trace->nr_entries++] = addr;
+
+ return trace->nr_entries >= trace->max_entries;
+}
+
+void arch_save_stacktrace(struct stack_trace *trace)
+{
+ struct stack_trace_data data;
+ struct stackframe frame;
+
+ data.trace = trace;
+ data.skip = trace->skip;
+
+ register unsigned long current_sp asm ("sp");
+
+ frame.fp = (unsigned long)__builtin_frame_address(0);
+ frame.sp = current_sp;
+ frame.lr = (unsigned long)__builtin_return_address(0);
+ frame.pc = (unsigned long)arch_save_stacktrace;
+
+ walk_stackframe(&frame, save_trace, &data);
+}
+
+
diff --git a/arch/arm/cpu/arm64/cpu_vcpu_coproc.c b/arch/arm/cpu/arm64/cpu_vcpu_coproc.c
new file mode 100644
index 0000000..1a992e0
--- /dev/null
+++ b/arch/arm/cpu/arm64/cpu_vcpu_coproc.c
@@ -0,0 +1,306 @@
+/**
+ * Copyright (c) 2012 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_vcpu_coproc.c
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief source file for coprocessor access
+ */
+
+#include <cpu_defines.h>
+#include <cpu_vcpu_spr.h>
+#include <cpu_vcpu_coproc.h>
+
+static bool cpu_vcpu_cpx_ldcstc_accept_nop(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 D, u32 CRd,
+ u32 uopt, u32 imm8)
+{
+ return TRUE;
+}
+
+static bool cpu_vcpu_cpx_ldcstc_done_nop(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 index, u32 D, u32 CRd,
+ u32 uopt, u32 imm8)
+{
+ return TRUE;
+}
+
+static u32 cpu_vcpu_cpx_ldcstc_read_zero(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 index, u32 D, u32 CRd,
+ u32 uopt, u32 imm8)
+{
+ return 0;
+}
+
+static void cpu_vcpu_cpx_ldcstc_ignore_write(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 index, u32 D, u32 CRd,
+ u32 uopt, u32 imm8, u32 data)
+{
+}
+
+static bool cpu_vcpu_cpx_read2_zero(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 CRm,
+ u32 *data, u32 *data2)
+{
+ *data = 0x0;
+ *data2 = 0x0;
+
+ return TRUE;
+}
+
+static bool cpu_vcpu_cpx_ignore_write2(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 CRm,
+ u32 data, u32 data2)
+{
+ return TRUE;
+}
+
+static bool cpu_vcpu_cpx_data_process_nop(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 opc2,
+ u32 CRd, u32 CRn, u32 CRm)
+{
+ return TRUE;
+}
+
+static bool cpu_vcpu_cpx_ignore_write(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 opc2, u32 CRn,
+ u32 CRm, u32 data)
+{
+ return TRUE;
+}
+
+static bool cpu_vcpu_cpx_read_zero(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 opc2, u32 CRn,
+ u32 CRm, u32 *data)
+{
+ *data = 0x0;
+
+ return TRUE;
+}
+
+static struct cpu_vcpu_coproc cp_array[CPU_COPROC_COUNT] =
+{
+ {
+ .cpnum = 0,
+ .ldcstc_accept = NULL,
+ .ldcstc_done = NULL,
+ .ldcstc_read = NULL,
+ .ldcstc_write = NULL,
+ .write2 = NULL,
+ .read2 = NULL,
+ .data_process = NULL,
+ .write = NULL,
+ .read = NULL,
+ },
+ {
+ .cpnum = 1,
+ .ldcstc_accept = NULL,
+ .ldcstc_done = NULL,
+ .ldcstc_read = NULL,
+ .ldcstc_write = NULL,
+ .write2 = NULL,
+ .read2 = NULL,
+ .data_process = NULL,
+ .write = NULL,
+ .read = NULL,
+ },
+ {
+ .cpnum = 2,
+ .ldcstc_accept = NULL,
+ .ldcstc_done = NULL,
+ .ldcstc_read = NULL,
+ .ldcstc_write = NULL,
+ .write2 = NULL,
+ .read2 = NULL,
+ .data_process = NULL,
+ .write = NULL,
+ .read = NULL,
+ },
+ {
+ .cpnum = 3,
+ .ldcstc_accept = NULL,
+ .ldcstc_done = NULL,
+ .ldcstc_read = NULL,
+ .ldcstc_write = NULL,
+ .write2 = NULL,
+ .read2 = NULL,
+ .data_process = NULL,
+ .write = NULL,
+ .read = NULL,
+ },
+ {
+ .cpnum = 4,
+ .ldcstc_accept = NULL,
+ .ldcstc_done = NULL,
+ .ldcstc_read = NULL,
+ .ldcstc_write = NULL,
+ .write2 = NULL,
+ .read2 = NULL,
+ .data_process = NULL,
+ .write = NULL,
+ .read = NULL,
+ },
+ {
+ .cpnum = 5,
+ .ldcstc_accept = NULL,
+ .ldcstc_done = NULL,
+ .ldcstc_read = NULL,
+ .ldcstc_write = NULL,
+ .write2 = NULL,
+ .read2 = NULL,
+ .data_process = NULL,
+ .write = NULL,
+ .read = NULL,
+ },
+ {
+ .cpnum = 6,
+ .ldcstc_accept = NULL,
+ .ldcstc_done = NULL,
+ .ldcstc_read = NULL,
+ .ldcstc_write = NULL,
+ .write2 = NULL,
+ .read2 = NULL,
+ .data_process = NULL,
+ .write = NULL,
+ .read = NULL,
+ },
+ {
+ .cpnum = 7,
+ .ldcstc_accept = NULL,
+ .ldcstc_done = NULL,
+ .ldcstc_read = NULL,
+ .ldcstc_write = NULL,
+ .write2 = NULL,
+ .read2 = NULL,
+ .data_process = NULL,
+ .write = NULL,
+ .read = NULL,
+ },
+ {
+ .cpnum = 8,
+ .ldcstc_accept = NULL,
+ .ldcstc_done = NULL,
+ .ldcstc_read = NULL,
+ .ldcstc_write = NULL,
+ .write2 = NULL,
+ .read2 = NULL,
+ .data_process = NULL,
+ .write = NULL,
+ .read = NULL,
+ },
+ {
+ .cpnum = 9,
+ .ldcstc_accept = NULL,
+ .ldcstc_done = NULL,
+ .ldcstc_read = NULL,
+ .ldcstc_write = NULL,
+ .write2 = NULL,
+ .read2 = NULL,
+ .data_process = NULL,
+ .write = NULL,
+ .read = NULL,
+ },
+ {
+ .cpnum = 10,
+ .ldcstc_accept = NULL,
+ .ldcstc_done = NULL,
+ .ldcstc_read = NULL,
+ .ldcstc_write = NULL,
+ .write2 = NULL,
+ .read2 = NULL,
+ .data_process = NULL,
+ .write = NULL,
+ .read = NULL
+ },
+ {
+ .cpnum = 11,
+ .ldcstc_accept = NULL,
+ .ldcstc_done = NULL,
+ .ldcstc_read = NULL,
+ .ldcstc_write = NULL,
+ .write2 = NULL,
+ .read2 = NULL,
+ .data_process = NULL,
+ .write = NULL,
+ .read = NULL,
+ },
+ {
+ .cpnum = 12,
+ .ldcstc_accept = NULL,
+ .ldcstc_done = NULL,
+ .ldcstc_read = NULL,
+ .ldcstc_write = NULL,
+ .write2 = NULL,
+ .read2 = NULL,
+ .data_process = NULL,
+ .write = NULL,
+ .read = NULL,
+ },
+ {
+ .cpnum = 13,
+ .ldcstc_accept = NULL,
+ .ldcstc_done = NULL,
+ .ldcstc_read = NULL,
+ .ldcstc_write = NULL,
+ .write2 = NULL,
+ .read2 = NULL,
+ .data_process = NULL,
+ .write = NULL,
+ .read = NULL,
+ },
+ {
+ .cpnum = 14,
+ .ldcstc_accept = cpu_vcpu_cpx_ldcstc_accept_nop,
+ .ldcstc_done = cpu_vcpu_cpx_ldcstc_done_nop,
+ .ldcstc_read = cpu_vcpu_cpx_ldcstc_read_zero,
+ .ldcstc_write = cpu_vcpu_cpx_ldcstc_ignore_write,
+ .write2 = cpu_vcpu_cpx_ignore_write2,
+ .read2 = cpu_vcpu_cpx_read2_zero,
+ .data_process = cpu_vcpu_cpx_data_process_nop,
+ .write = cpu_vcpu_cpx_ignore_write,
+ .read = cpu_vcpu_cpx_read_zero,
+ },
+ {
+ .cpnum = 15,
+ .ldcstc_accept = cpu_vcpu_cpx_ldcstc_accept_nop,
+ .ldcstc_done = cpu_vcpu_cpx_ldcstc_done_nop,
+ .ldcstc_read = cpu_vcpu_cpx_ldcstc_read_zero,
+ .ldcstc_write = cpu_vcpu_cpx_ldcstc_ignore_write,
+ .write2 = cpu_vcpu_cpx_ignore_write2,
+ .read2 = cpu_vcpu_cpx_read2_zero,
+ .data_process = cpu_vcpu_cpx_data_process_nop,
+ .write = &cpu_vcpu_cpx_ignore_write,
+ .read = &cpu_vcpu_cpx_read_zero,
+ },
+};
+
+struct cpu_vcpu_coproc *cpu_vcpu_coproc_get(u32 cpnum)
+{
+ if (cpnum < CPU_COPROC_COUNT) {
+ return &cp_array[cpnum];
+ }
+ return NULL;
+}
diff --git a/arch/arm/cpu/arm64/cpu_vcpu_emulate.c b/arch/arm/cpu/arm64/cpu_vcpu_emulate.c
new file mode 100644
index 0000000..1f85f8d
--- /dev/null
+++ b/arch/arm/cpu/arm64/cpu_vcpu_emulate.c
@@ -0,0 +1,506 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_vcpu_emulate.c
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief Implementation of hardware assisted instruction emulation
+ */
+
+#include <vmm_types.h>
+#include <vmm_error.h>
+#include <vmm_stdio.h>
+#include <vmm_scheduler.h>
+#include <vmm_vcpu_irq.h>
+#include <vmm_host_aspace.h>
+#include <vmm_devemu.h>
+#include <generic_timer.h>
+#include <cpu_inline_asm.h>
+#include <cpu_vcpu_helper.h>
+#include <cpu_vcpu_spr.h>
+#include <cpu_vcpu_emulate.h>
+#include <arm_features.h>
+
+/**
+ * A conditional instruction can trap, even though its condition was
+ * FALSE. Hence emulate condition checking in software!
+ */
+static bool cpu_vcpu_condition_check(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 iss)
+{
+ bool ret = FALSE;
+ u32 cond;
+
+ /* Condition check parameters */
+ if (iss & ISS_CV_MASK) {
+ cond = (iss & ISS_COND_MASK) >> ISS_COND_SHIFT;
+ } else {
+ /* This can happen in Thumb mode: examine IT state. */
+ u32 it;
+
+ it = ((regs->pstate >> 8) & 0xFC) | ((regs->pstate >> 25) & 0x3);
+
+ /* it == 0 => unconditional. */
+ if (it == 0)
+ return TRUE;
+
+ /* The cond for this insn works out as the top 4 bits. */
+ cond = (it >> 4);
+ }
+
+ /* Emulate condition checking */
+ switch (cond >> 1) {
+ case 0:
+ ret = (regs->pstate & PSR_ZERO_MASK) ? TRUE : FALSE;
+ break;
+ case 1:
+ ret = (regs->pstate & PSR_CARRY_MASK) ? TRUE : FALSE;
+ break;
+ case 2:
+ ret = (regs->pstate & PSR_NEGATIVE_MASK) ? TRUE : FALSE;
+ break;
+ case 3:
+ ret = (regs->pstate & PSR_OVERFLOW_MASK) ? TRUE : FALSE;
+ break;
+ case 4:
+ ret = (regs->pstate & PSR_CARRY_MASK) ? TRUE : FALSE;
+ ret = (ret && !(regs->pstate & PSR_ZERO_MASK)) ?
+ TRUE : FALSE;
+ break;
+ case 5:
+ if (regs->pstate & PSR_NEGATIVE_MASK) {
+ ret = (regs->pstate & PSR_OVERFLOW_MASK) ?
+ TRUE : FALSE;
+ } else {
+ ret = (regs->pstate & PSR_OVERFLOW_MASK) ?
+ FALSE : TRUE;
+ }
+ break;
+ case 6:
+ if (regs->pstate & PSR_NEGATIVE_MASK) {
+ ret = (regs->pstate & PSR_OVERFLOW_MASK) ?
+ TRUE : FALSE;
+ } else {
+ ret = (regs->pstate & PSR_OVERFLOW_MASK) ?
+ FALSE : TRUE;
+ }
+ ret = (ret && !(regs->pstate & PSR_ZERO_MASK)) ?
+ TRUE : FALSE;
+ break;
+ case 7:
+ ret = TRUE;
+ break;
+ default:
+ break;
+ };
+
+ if ((cond & 0x1) && (cond != 0xF)) {
+ ret = !ret;
+ }
+
+ return ret;
+}
+
+/**
+ * Update ITSTATE when emulating instructions inside an IT-block
+ *
+ * When IO abort occurs from Thumb IF-THEN blocks, the ITSTATE field
+ * of the CPSR is not updated, so we do this manually.
+ */
+static void cpu_vcpu_update_itstate(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs)
+{
+ u32 itbits, cond;
+
+ if (!(regs->pstate & PSR_IT_MASK)) {
+ return;
+ }
+
+ cond = (regs->pstate & 0xe000) >> 13;
+ itbits = (regs->pstate & 0x1c00) >> (10 - 2);
+ itbits |= (regs->pstate & (0x3 << 25)) >> 25;
+
+ /* Perform ITAdvance (see page A-52 in ARM DDI 0406C) */
+ if ((itbits & 0x7) == 0)
+ itbits = cond = 0;
+ else
+ itbits = (itbits << 1) & 0x1f;
+
+ regs->pstate &= ~PSR_IT_MASK;
+ regs->pstate |= cond << 13;
+ regs->pstate |= (itbits & 0x1c) << (10 - 2);
+ regs->pstate |= (itbits & 0x3) << 25;
+}
+
+int cpu_vcpu_emulate_wfi_wfe(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 il, u32 iss)
+{
+ u64 timeout_nsecs = 0;
+
+ /* Check instruction condition */
+ if (!cpu_vcpu_condition_check(vcpu, regs, iss)) {
+ /* Skip this instruction */
+ goto done;
+ }
+
+ if (iss & ISS_WFI_WFE_TRAPPED_MASK) { /* WFE */
+ /* Yield current timeslice */
+ vmm_scheduler_yield();
+ } else { /* WFI */
+ /* Estimate wakeup timeout if possible */
+ if (arm_feature(vcpu, ARM_FEATURE_GENERIC_TIMER)) {
+ timeout_nsecs = generic_timer_wakeup_timeout();
+ }
+
+ /* Wait for irq on this vcpu */
+ vmm_vcpu_irq_wait_timeout(vcpu, timeout_nsecs);
+ }
+
+done:
+ /* Next instruction */
+ regs->pc += (il) ? 4 : 2;
+
+ /* Update ITSTATE for Thumb mode */
+ if (regs->pstate & PSR_THUMB_ENABLED) {
+ cpu_vcpu_update_itstate(vcpu, regs);
+ }
+
+ return VMM_OK;
+}
+
+int cpu_vcpu_emulate_mcr_mrc_cp15(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 il, u32 iss)
+{
+ int rc = VMM_OK;
+ u32 opc2, opc1, CRn, Rt, CRm;
+ u64 t;
+
+ /* Check instruction condition */
+ if (!cpu_vcpu_condition_check(vcpu, regs, iss)) {
+ /* Skip this instruction */
+ goto done;
+ }
+
+ /* More MCR/MRC parameters */
+ opc2 = (iss & ISS_MCR_MRC_OPC2_MASK) >> ISS_MCR_MRC_OPC2_SHIFT;
+ opc1 = (iss & ISS_MCR_MRC_OPC1_MASK) >> ISS_MCR_MRC_OPC1_SHIFT;
+ CRn = (iss & ISS_MCR_MRC_CRN_MASK) >> ISS_MCR_MRC_CRN_SHIFT;
+ Rt = (iss & ISS_MCR_MRC_RT_MASK) >> ISS_MCR_MRC_RT_SHIFT;
+ CRm = (iss & ISS_MCR_MRC_CRM_MASK) >> ISS_MCR_MRC_CRM_SHIFT;
+
+ if (iss & ISS_MCR_MRC_DIR_MASK) {
+ /* MRC CP15 */
+ if (!cpu_vcpu_cp15_read(vcpu, regs, opc1, opc2, CRn, CRm, &t)) {
+ rc = VMM_EFAIL;
+ }
+ if (!rc) {
+ cpu_vcpu_reg_write(vcpu, regs, Rt, t);
+ }
+ } else {
+ /* MCR CP15 */
+ t = cpu_vcpu_reg_read(vcpu, regs, Rt);
+ if (!cpu_vcpu_cp15_write(vcpu, regs, opc1, opc2, CRn, CRm, t)) {
+ rc = VMM_EFAIL;
+ }
+ }
+
+done:
+ if (!rc) {
+ /* Next instruction */
+ regs->pc += (il) ? 4 : 2;
+ /* Update ITSTATE for Thumb mode */
+ if (regs->pstate & PSR_THUMB_ENABLED) {
+ cpu_vcpu_update_itstate(vcpu, regs);
+ }
+ }
+
+ return rc;
+}
+
+/* TODO: To be implemented later */
+int cpu_vcpu_emulate_mcrr_mrrc_cp15(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 il, u32 iss)
+{
+ return VMM_EFAIL;
+}
+
+/* TODO: To be implemented later */
+int cpu_vcpu_emulate_mcr_mrc_cp14(struct vmm_vcpu *vcpu,
+ arch_regs_t * regs,
+ u32 il, u32 iss)
+{
+ u32 Rt;
+
+ /* Check instruction condition */
+ if (!cpu_vcpu_condition_check(vcpu, regs, iss)) {
+ /* Skip this instruction */
+ goto done;
+ }
+
+ /* More MCR/MRC parameters */
+ Rt = (iss & ISS_MCR_MRC_RT_MASK) >> ISS_MCR_MRC_RT_SHIFT;
+
+ if (iss & ISS_MCR_MRC_DIR_MASK) {
+ /* MRC CP14 */
+ /* Read always zero. */
+ cpu_vcpu_reg_write(vcpu, regs, Rt, 0x0);
+ } else {
+ /* MCR CP14 */
+ /* Ignore it. */
+ }
+
+done:
+ /* Next instruction */
+ regs->pc += (il) ? 4 : 2;
+ /* Update ITSTATE for Thumb mode */
+ if (regs->pstate & PSR_THUMB_ENABLED) {
+ cpu_vcpu_update_itstate(vcpu, regs);
+ }
+
+ return VMM_OK;
+}
+
+/* TODO: To be implemented later */
+int cpu_vcpu_emulate_ldc_stc_cp14(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 il, u32 iss)
+{
+ return VMM_EFAIL;
+}
+
+int cpu_vcpu_emulate_simd_fp_regs(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 il, u32 iss)
+{
+ msr_sync(cptr_el2, CPTR_TTA_MASK | CPTR_RES1_MASK);
+ /* TFA bit should be removed before we try to restore the FP-state */
+ vfp_simd_restore_regs(arm_priv(vcpu)->fpregs);
+ msr(fpexc32_el2, arm_priv(vcpu)->fpexc);
+ msr(fpcr, arm_priv(vcpu)->fpcr);
+ msr(fpsr, arm_priv(vcpu)->fpsr);
+ return VMM_OK;
+}
+
+/* TODO: Can we optimize this by determining the source and target registers
+ * and avoid copying all the FPU-regs */
+int cpu_vcpu_emulate_vmrs(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 il, u32 iss)
+{
+ vmm_printf("\n\n%s\n", __func__);
+ msr(cptr_el2, CPTR_TTA_MASK | CPTR_RES1_MASK);
+ /* TFA bit should be removed before we try to restore the FP-state */
+ vfp_simd_restore_regs(arm_priv(vcpu)->fpregs);
+ msr(fpexc32_el2, arm_priv(vcpu)->fpexc);
+ msr(fpcr, arm_priv(vcpu)->fpcr);
+ msr(fpsr, arm_priv(vcpu)->fpsr);
+ return VMM_OK;
+}
+
+/* TODO: To be implemented later */
+int cpu_vcpu_emulate_mcrr_mrrc_cp14(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 il, u32 iss)
+{
+ return VMM_EFAIL;
+}
+
+/* TODO: To be implemented later */
+int cpu_vcpu_emulate_hvc32(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 il, u32 iss)
+{
+ return VMM_EFAIL;
+}
+
+/* TODO: To be implemented later */
+int cpu_vcpu_emulate_hvc64(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 il, u32 iss)
+{
+ return VMM_EFAIL;
+}
+
+/* TODO: To be implemented later */
+int cpu_vcpu_emulate_msr_mrs_system(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 il, u32 iss)
+{
+ bool read = (!!(iss & ISS_SYSREG_READ));
+ int rt = ((iss & ISS_RT_MASK) >> ISS_RT_SHIFT);
+
+ switch (iss & ISS_SYSREG_MASK) {
+ case ISS_CPACR_EL1:
+ vmm_printf("Trying to access CPACR_EL1\n");
+ break;
+ case ISS_CNTFRQ_EL0:
+ vmm_printf("Trying to access CNTFRQ_EL0 \n");
+ break;
+ case ISS_CNTPCT_EL0:
+ vmm_printf("Trying to access CNTPCT_EL0 \n");
+ break;
+ case ISS_CNTKCTL_EL1:
+ vmm_printf("Trying to access CNTKCTL_EL1 \n");
+ break;
+ case ISS_CNTP_TVAL_EL0:
+ vmm_printf("Trying to access CNTP_TVAL_EL0 \n");
+ break;
+ case ISS_CNTP_CTL_EL0:
+ vmm_printf("Trying to access CNTP_CTL_EL0 \n");
+ break;
+ case ISS_CNTP_CVAL_EL0:
+ vmm_printf("Trying to access CNTP_CVAL_EL0 \n");
+ break;
+ case ISS_ACTLR_EL1:
+ if (read) {
+ cpu_vcpu_reg_write(vcpu, regs, rt, arm_priv(vcpu)->actlr);
+ } else {
+ arm_priv(vcpu)->actlr = cpu_vcpu_reg_read(vcpu, regs, rt);
+ }
+ regs->pc += 4;
+ return VMM_OK;
+ break;
+ default:
+ vmm_printf("Guest MSR/MRS Emulation @ PC:0x%X\n", regs->pc);
+ break;
+ }
+ return VMM_EFAIL;
+}
+
+static inline u32 arm_sign_extend(u32 imm, u32 len, u32 bits)
+{
+ if (imm & (1 << (len - 1))) {
+ imm = imm | (~((1 << len) - 1));
+ }
+ return imm & ((1 << bits) - 1);
+}
+
+int cpu_vcpu_emulate_load(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 il, u32 iss,
+ physical_addr_t ipa)
+{
+ int rc;
+ u8 data8;
+ u16 data16;
+ u32 data32, sas, sse, srt;
+
+ sas = (iss & ISS_ABORT_SAS_MASK) >> ISS_ABORT_SAS_SHIFT;
+ sse = (iss & ISS_ABORT_SSE_MASK) >> ISS_ABORT_SSE_SHIFT;
+ srt = (iss & ISS_ABORT_SRT_MASK) >> ISS_ABORT_SRT_SHIFT;
+
+ sse = (sas == 2) ? 0 : sse;
+
+ switch (sas) {
+ case 0:
+ rc = vmm_devemu_emulate_read(vcpu, ipa,
+ &data8, sizeof(data8));
+ if (!rc) {
+ if (sse) {
+ cpu_vcpu_reg_write(vcpu, regs, srt,
+ arm_sign_extend(data8, 8, 32));
+ } else {
+ cpu_vcpu_reg_write(vcpu, regs, srt, data8);
+ }
+ }
+ break;
+ case 1:
+ rc = vmm_devemu_emulate_read(vcpu, ipa,
+ &data16, sizeof(data16));
+ if (!rc) {
+ if (sse) {
+ cpu_vcpu_reg_write(vcpu, regs, srt,
+ arm_sign_extend(data16, 16, 32));
+ } else {
+ cpu_vcpu_reg_write(vcpu, regs, srt, data16);
+ }
+ }
+ break;
+ case 2:
+ rc = vmm_devemu_emulate_read(vcpu, ipa,
+ &data32, sizeof(data32));
+ if (!rc) {
+ cpu_vcpu_reg_write(vcpu, regs, srt, data32);
+ }
+ break;
+ default:
+ rc = VMM_EFAIL;
+ break;
+ };
+
+ if (!rc) {
+ /* Next instruction */
+ regs->pc += (il) ? 4 : 2;
+ /* Update ITSTATE for Thumb mode */
+ if (regs->pstate & PSR_THUMB_ENABLED) {
+ cpu_vcpu_update_itstate(vcpu, regs);
+ }
+ }
+
+ return rc;
+}
+
+int cpu_vcpu_emulate_store(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 il, u32 iss,
+ physical_addr_t ipa)
+{
+ int rc;
+ u8 data8;
+ u16 data16;
+ u32 data32, sas, srt;
+
+ sas = (iss & ISS_ABORT_SAS_MASK) >> ISS_ABORT_SAS_SHIFT;
+ srt = (iss & ISS_ABORT_SRT_MASK) >> ISS_ABORT_SRT_SHIFT;
+
+ switch (sas) {
+ case 0:
+ data8 = cpu_vcpu_reg_read(vcpu, regs, srt);
+ rc = vmm_devemu_emulate_write(vcpu, ipa,
+ &data8, sizeof(data8));
+ break;
+ case 1:
+ data16 = cpu_vcpu_reg_read(vcpu, regs, srt);
+ rc = vmm_devemu_emulate_write(vcpu, ipa,
+ &data16, sizeof(data16));
+ break;
+ case 2:
+ data32 = cpu_vcpu_reg_read(vcpu, regs, srt);
+ rc = vmm_devemu_emulate_write(vcpu, ipa,
+ &data32, sizeof(data32));
+ break;
+ default:
+ rc = VMM_EFAIL;
+ break;
+ };
+
+ if (!rc) {
+ /* Next instruction */
+ regs->pc += (il) ? 4 : 2;
+ /* Update ITSTATE for Thumb mode */
+ if (regs->pstate & PSR_THUMB_ENABLED) {
+ cpu_vcpu_update_itstate(vcpu, regs);
+ }
+ }
+
+ return rc;
+}
+
diff --git a/arch/arm/cpu/arm64/cpu_vcpu_helper.c b/arch/arm/cpu/arm64/cpu_vcpu_helper.c
new file mode 100644
index 0000000..49070c5
--- /dev/null
+++ b/arch/arm/cpu/arm64/cpu_vcpu_helper.c
@@ -0,0 +1,991 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modifycpu_vcpu_helper.c
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_vcpu_helper.c
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief source of VCPU helper functions
+ */
+
+#include <vmm_error.h>
+#include <vmm_heap.h>
+#include <vmm_smp.h>
+#include <vmm_stdio.h>
+#include <vmm_timer.h>
+#include <vmm_manager.h>
+#include <vmm_scheduler.h>
+#include <arch_barrier.h>
+#include <libs/stringlib.h>
+#include <libs/mathlib.h>
+#include <cpu_defines.h>
+#include <cpu_inline_asm.h>
+#include <cpu_vcpu_spr.h>
+#include <cpu_vcpu_helper.h>
+#include <generic_timer.h>
+#include <arm_features.h>
+#include <mmu_lpae.h>
+
+void cpu_vcpu_halt(struct vmm_vcpu *vcpu, arch_regs_t *regs)
+{
+ if (vcpu->state != VMM_VCPU_STATE_HALTED) {
+ vmm_printf("\n");
+ cpu_vcpu_dump_user_reg(regs);
+ vmm_manager_vcpu_halt(vcpu);
+ }
+}
+
+static u32 __cpu_vcpu_regmode32_read(arch_regs_t *regs,
+ u32 mode, u32 reg)
+{
+ switch (reg) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ return regs->gpr[reg];
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ if (mode == CPSR_MODE_FIQ) {
+ return regs->gpr[16 + reg];
+ } else {
+ return regs->gpr[reg];
+ }
+ case 13:
+ switch (mode) {
+ case CPSR_MODE_USER:
+ case CPSR_MODE_SYSTEM:
+ return regs->gpr[13];
+ case CPSR_MODE_FIQ:
+ return regs->gpr[29];
+ case CPSR_MODE_IRQ:
+ return regs->gpr[17];
+ case CPSR_MODE_SUPERVISOR:
+ return regs->gpr[19];
+ case CPSR_MODE_ABORT:
+ return regs->gpr[21];
+ case CPSR_MODE_UNDEFINED:
+ return regs->gpr[23];
+ case CPSR_MODE_HYPERVISOR:
+ return regs->gpr[15];
+ default:
+ break;
+ };
+ break;
+ case 14:
+ switch (mode) {
+ case CPSR_MODE_USER:
+ case CPSR_MODE_SYSTEM:
+ return regs->gpr[14];
+ case CPSR_MODE_FIQ:
+ return regs->gpr[30];
+ case CPSR_MODE_IRQ:
+ return regs->gpr[16];
+ case CPSR_MODE_SUPERVISOR:
+ return regs->gpr[18];
+ case CPSR_MODE_ABORT:
+ return regs->gpr[20];
+ case CPSR_MODE_UNDEFINED:
+ return regs->gpr[22];
+ case CPSR_MODE_HYPERVISOR:
+ return regs->gpr[14];
+ default:
+ break;
+ };
+ break;
+ case 15:
+ return regs->pc;
+ default:
+ break;
+ };
+
+ return 0x0;
+}
+
+static void __cpu_vcpu_regmode32_write(arch_regs_t *regs,
+ u32 mode, u32 reg, u32 val)
+{
+ switch (reg) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ regs->gpr[reg] = val;
+ break;
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ if (mode == CPSR_MODE_FIQ) {
+ regs->gpr[16 + reg] = val;
+ } else {
+ regs->gpr[reg] = val;
+ }
+ break;
+ case 13:
+ switch (mode) {
+ case CPSR_MODE_USER:
+ case CPSR_MODE_SYSTEM:
+ regs->gpr[13] = val;
+ break;
+ case CPSR_MODE_FIQ:
+ regs->gpr[29] = val;
+ break;
+ case CPSR_MODE_IRQ:
+ regs->gpr[17] = val;
+ break;
+ case CPSR_MODE_SUPERVISOR:
+ regs->gpr[19] = val;
+ break;
+ case CPSR_MODE_ABORT:
+ regs->gpr[21] = val;
+ break;
+ case CPSR_MODE_UNDEFINED:
+ regs->gpr[23] = val;
+ break;
+ case CPSR_MODE_HYPERVISOR:
+ regs->gpr[15] = val;
+ break;
+ default:
+ break;
+ };
+ break;
+ case 14:
+ switch (mode) {
+ case CPSR_MODE_USER:
+ case CPSR_MODE_SYSTEM:
+ regs->gpr[14] = val;
+ case CPSR_MODE_FIQ:
+ regs->gpr[30] = val;
+ case CPSR_MODE_IRQ:
+ regs->gpr[16] = val;
+ case CPSR_MODE_SUPERVISOR:
+ regs->gpr[18] = val;
+ case CPSR_MODE_ABORT:
+ regs->gpr[20] = val;
+ case CPSR_MODE_UNDEFINED:
+ regs->gpr[22] = val;
+ case CPSR_MODE_HYPERVISOR:
+ regs->gpr[14] = val;
+ default:
+ break;
+ };
+ break;
+ case 15:
+ regs->pc = val;
+ break;
+ default:
+ break;
+ };
+}
+
+u64 cpu_vcpu_reg_read(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 reg)
+{
+ if (regs->pstate & PSR_MODE32) {
+ return __cpu_vcpu_regmode32_read(regs,
+ regs->pstate & PSR_MODE32_MASK, reg & 0xF);
+ } else {
+ return (regs->gpr[reg]);
+ }
+}
+
+void cpu_vcpu_reg_write(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 reg, u64 val)
+{
+ if (regs->pstate & PSR_MODE32) {
+ __cpu_vcpu_regmode32_write(regs,
+ regs->pstate & PSR_MODE32_MASK, reg & 0xF, val);
+ } else {
+ regs->gpr[reg] = val;
+ }
+}
+
+void __cpu_vcpu_spsr32_update(struct vmm_vcpu *vcpu, u32 mode, u32 new_spsr)
+{
+ switch (mode) {
+ case CPSR_MODE_ABORT:
+ msr(spsr_abt, new_spsr);
+ arm_priv(vcpu)->spsr_abt = new_spsr;
+ break;
+ case CPSR_MODE_UNDEFINED:
+ msr(spsr_und, new_spsr);
+ arm_priv(vcpu)->spsr_und = new_spsr;
+ break;
+ case CPSR_MODE_SUPERVISOR:
+ msr(spsr_el1, new_spsr);
+ arm_priv(vcpu)->spsr_el1 = new_spsr;
+ break;
+ case CPSR_MODE_IRQ:
+ msr(spsr_irq, new_spsr);
+ arm_priv(vcpu)->spsr_irq = new_spsr;
+ break;
+ case CPSR_MODE_FIQ:
+ msr(spsr_fiq, new_spsr);
+ arm_priv(vcpu)->spsr_fiq = new_spsr;
+ break;
+ case CPSR_MODE_HYPERVISOR:
+ msr(spsr_el2, new_spsr);
+ break;
+ default:
+ break;
+ };
+}
+
+static int __cpu_vcpu_inject_und32(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs)
+{
+ u32 old_cpsr, new_cpsr, sctlr;
+
+ /* Retrive current SCTLR */
+ sctlr = mrs(sctlr_el1);
+
+ /* Compute CPSR changes */
+ old_cpsr = new_cpsr = regs->pstate & 0xFFFFFFFFULL;
+ new_cpsr &= ~CPSR_MODE_MASK;
+ new_cpsr |= (CPSR_MODE_UNDEFINED | CPSR_IRQ_DISABLED);
+ new_cpsr &= ~(CPSR_IT2_MASK |
+ CPSR_IT1_MASK |
+ CPSR_JAZZLE_ENABLED |
+ CPSR_BE_ENABLED |
+ CPSR_THUMB_ENABLED);
+ if (sctlr & SCTLR_TE_MASK) {
+ new_cpsr |= CPSR_THUMB_ENABLED;
+ }
+ if (sctlr & SCTLR_EE_MASK) {
+ new_cpsr |= CPSR_BE_ENABLED;
+ }
+
+ /* Update CPSR, SPSR, LR and PC */
+ __cpu_vcpu_spsr32_update(vcpu, CPSR_MODE_UNDEFINED, old_cpsr);
+ __cpu_vcpu_regmode32_write(regs, CPSR_MODE_UNDEFINED, 14,
+ regs->pc - ((old_cpsr & CPSR_THUMB_ENABLED) ? 2 : 4));
+ if (sctlr & SCTLR_V_MASK) {
+ regs->pc = CPU_IRQ_HIGHVEC_BASE;
+ } else {
+ regs->pc = mrs(vbar_el1);
+ }
+ regs->pc = regs->pc & 0xFFFFFFFFULL;
+ regs->pc += 4;
+ regs->pstate &= ~0xFFFFFFFFULL;
+ regs->pstate |= (u64)new_cpsr;
+
+ return VMM_OK;
+}
+
+#define EL1_EXCEPT_SYNC_OFFSET 0x200
+
+static int __cpu_vcpu_inject_und64(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs)
+{
+ u32 esr;
+
+ /* Save old PSTATE to SPSR_EL1 */
+ msr(spsr_el1, regs->pstate);
+
+ /* Save current PC to ELR_EL1 */
+ msr(elr_el1, regs->pc);
+
+ /* Update PSTATE */
+ regs->pstate = (PSR_MODE64_EL1h |
+ PSR_ASYNC_ABORT_DISABLED |
+ PSR_FIQ_DISABLED |
+ PSR_IRQ_DISABLED |
+ PSR_MODE64_DEBUG_DISABLED);
+
+ /* Update PC */
+ regs->pc = mrs(vbar_el1) + EL1_EXCEPT_SYNC_OFFSET;
+
+ /* Update ESR_EL1 */
+ esr = (EC_UNKNOWN << ESR_EC_SHIFT);
+ if (mrs(esr_el2) & ESR_IL_MASK) {
+ esr |= ESR_IL_MASK;
+ }
+ msr(esr_el1, esr);
+
+ return VMM_OK;
+}
+
+static int __cpu_vcpu_inject_abt32(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ bool is_pabt,
+ virtual_addr_t addr)
+{
+ u64 far;
+ u32 old_cpsr, new_cpsr, sctlr, ttbcr;
+
+ /* Retrive current SCTLR */
+ sctlr = mrs(sctlr_el1);
+
+ /* Compute CPSR changes */
+ old_cpsr = new_cpsr = regs->pstate & 0xFFFFFFFFULL;
+ new_cpsr &= ~CPSR_MODE_MASK;
+ new_cpsr |= (CPSR_MODE_ABORT |
+ CPSR_ASYNC_ABORT_DISABLED |
+ CPSR_IRQ_DISABLED);
+ new_cpsr &= ~(CPSR_IT2_MASK |
+ CPSR_IT1_MASK |
+ CPSR_JAZZLE_ENABLED |
+ CPSR_BE_ENABLED |
+ CPSR_THUMB_ENABLED);
+ if (sctlr & SCTLR_TE_MASK) {
+ new_cpsr |= CPSR_THUMB_ENABLED;
+ }
+ if (sctlr & SCTLR_EE_MASK) {
+ new_cpsr |= CPSR_BE_ENABLED;
+ }
+
+ /* Update CPSR, SPSR, LR and PC */
+ __cpu_vcpu_spsr32_update(vcpu, CPSR_MODE_ABORT, old_cpsr);
+ __cpu_vcpu_regmode32_write(regs, CPSR_MODE_ABORT, 14,
+ regs->pc - ((old_cpsr & CPSR_THUMB_ENABLED) ? 4 : 0));
+ if (sctlr & SCTLR_V_MASK) {
+ regs->pc = CPU_IRQ_HIGHVEC_BASE;
+ } else {
+ regs->pc = mrs(vbar_el1);
+ }
+ regs->pc = regs->pc & 0xFFFFFFFFULL;
+ regs->pc += (is_pabt) ? 12 : 16;
+ regs->pstate &= ~0xFFFFFFFFULL;
+ regs->pstate |= (u64)new_cpsr;
+
+ /* Update abort registers */
+ ttbcr = mrs(tcr_el1) & 0xFFFFFFFFULL;
+ if (is_pabt) {
+ /* Set IFAR and IFSR */
+ far = mrs(far_el1) & 0xFFFFFFFFULL;
+ far |= (addr << 32) & 0xFFFFFFFF00000000ULL;
+ msr(far_el1, far);
+ if (ttbcr >> 31) { /* LPAE MMU */
+ msr(ifsr32_el2, (1 << 9) | 0x34);
+ } else { /* Legacy ARMv6 MMU */
+ msr(ifsr32_el2, 0x14);
+ }
+ } else {
+ /* Set DFAR and DFSR */
+ far = mrs(far_el1) & 0xFFFFFFFF00000000ULL;
+ far |= addr & 0xFFFFFFFFULL;
+ msr(far_el1, far);
+ if (ttbcr >> 31) { /* LPAE MMU */
+ msr(esr_el1, (1 << 9) | 0x34);
+ } else { /* Legacy ARMv6 MMU */
+ msr(esr_el1, 0x14);
+ }
+ }
+
+ return VMM_OK;
+}
+
+static int __cpu_vcpu_inject_abt64(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ bool is_pabt,
+ virtual_addr_t addr)
+{
+ u32 esr, old_pstate;
+ bool is_aarch32 = (regs->pstate & PSR_MODE32) ? TRUE : FALSE;
+
+ /* Save old PSTATE to SPSR_EL1 */
+ old_pstate = regs->pstate;
+ msr(spsr_el1, old_pstate);
+
+ /* Save current PC to ELR_EL1 */
+ msr(elr_el1, regs->pc);
+
+ /* Update PSTATE */
+ regs->pstate = (PSR_MODE64_EL1h |
+ PSR_ASYNC_ABORT_DISABLED |
+ PSR_FIQ_DISABLED |
+ PSR_IRQ_DISABLED |
+ PSR_MODE64_DEBUG_DISABLED);
+
+ /* Update PC */
+ regs->pc = mrs(vbar_el1) + EL1_EXCEPT_SYNC_OFFSET;
+
+ /* Update FAR_EL1 */
+ msr(far_el1, addr);
+
+ /* Update ESR_EL1
+ * NOTE: The guest runs in AArch64 mode when in EL1. If we get
+ * an AArch32 fault or AArch64 EL0t fault then we have trapped
+ * guest user space.
+ */
+ esr = 0;
+ if (is_aarch32 || (old_pstate & PSR_MODE64_MASK) == PSR_MODE64_EL0t) {
+ if (is_pabt) {
+ esr |= (EC_TRAP_LWREL_INST_ABORT << ESR_EC_SHIFT);
+ } else {
+ esr |= (EC_TRAP_LWREL_DATA_ABORT << ESR_EC_SHIFT);
+ }
+ } else {
+ if (is_pabt) {
+ esr |= (EC_CUREL_INST_ABORT << ESR_EC_SHIFT);
+ } else {
+ esr |= (EC_CUREL_DATA_ABORT << ESR_EC_SHIFT);
+ }
+ }
+ esr |= FSC_SYNC_EXTERNAL_ABORT;
+ if (mrs(esr_el2) & ESR_IL_MASK) {
+ esr |= ESR_IL_MASK;
+ }
+ msr(esr_el1, esr);
+
+ return VMM_OK;
+}
+
+int cpu_vcpu_inject_undef(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs)
+{
+ /* Sanity checks */
+ if (!vcpu || !regs) {
+ return VMM_EFAIL;
+ }
+ if (vcpu != vmm_scheduler_current_vcpu()) {
+ /* This function should only be called for current VCPU */
+ vmm_panic("%d not called for current vcpu\n", __func__);
+ }
+
+ if (arm_priv(vcpu)->hcr & HCR_RW_MASK) {
+ return __cpu_vcpu_inject_und64(vcpu, regs);
+ } else {
+ return __cpu_vcpu_inject_und32(vcpu, regs);
+ }
+}
+
+int cpu_vcpu_inject_pabt(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs)
+{
+ /* Sanity checks */
+ if (!vcpu || !regs) {
+ return VMM_EFAIL;
+ }
+ if (vcpu != vmm_scheduler_current_vcpu()) {
+ /* This function should only be called for current VCPU */
+ vmm_panic("%d not called for current vcpu\n", __func__);
+ }
+
+ if (arm_priv(vcpu)->hcr & HCR_RW_MASK) {
+ return __cpu_vcpu_inject_abt64(vcpu, regs, TRUE, regs->pc);
+ } else {
+ return __cpu_vcpu_inject_abt32(vcpu, regs, TRUE, regs->pc);
+ }
+}
+
+int cpu_vcpu_inject_dabt(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ virtual_addr_t addr)
+{
+ /* Sanity checks */
+ if (!vcpu || !regs) {
+ return VMM_EFAIL;
+ }
+ if (vcpu != vmm_scheduler_current_vcpu()) {
+ /* This function should only be called for current VCPU */
+ vmm_panic("%d not called for current vcpu\n", __func__);
+ }
+
+ if (arm_priv(vcpu)->hcr & HCR_RW_MASK) {
+ return __cpu_vcpu_inject_abt64(vcpu, regs, FALSE, addr);
+ } else {
+ return __cpu_vcpu_inject_abt32(vcpu, regs, FALSE, addr);
+ }
+}
+
+int arch_guest_init(struct vmm_guest *guest)
+{
+ if (!guest->reset_count) {
+ guest->arch_priv = vmm_malloc(sizeof(arm_guest_priv_t));
+ if (!guest->arch_priv) {
+ return VMM_EFAIL;
+ }
+ arm_guest_priv(guest)->ttbl = mmu_lpae_ttbl_alloc(TTBL_STAGE2);
+ }
+ return VMM_OK;
+}
+
+int arch_guest_deinit(struct vmm_guest *guest)
+{
+ int rc;
+
+ if (guest->arch_priv) {
+ if ((rc = mmu_lpae_ttbl_free(arm_guest_priv(guest)->ttbl))) {
+ return rc;
+ }
+ vmm_free(guest->arch_priv);
+ }
+
+ return VMM_OK;
+}
+
+int arch_vcpu_init(struct vmm_vcpu *vcpu)
+{
+ u32 cpuid = 0;
+ const char *attr;
+ irq_flags_t flags;
+ /* Initialize User Mode Registers */
+ /* For both Orphan & Normal VCPUs */
+ memset(arm_regs(vcpu), 0, sizeof(arch_regs_t));
+ arm_regs(vcpu)->pc = vcpu->start_pc;
+ arm_regs(vcpu)->sp = vcpu->stack_va + vcpu->stack_sz - 8;
+ if (!vcpu->is_normal) {
+ arm_regs(vcpu)->pstate = PSR_MODE64_EL2h;
+ arm_regs(vcpu)->pstate |= PSR_ASYNC_ABORT_DISABLED;
+ return VMM_OK;
+ }
+ /* Following initialization for normal VCPUs only */
+ attr = vmm_devtree_attrval(vcpu->node,
+ VMM_DEVTREE_COMPATIBLE_ATTR_NAME);
+ if (strcmp(attr, "armv7a,cortex-a8") == 0) {
+ cpuid = ARM_CPUID_CORTEXA8;
+ arm_regs(vcpu)->pstate = PSR_MODE32;
+ } else if (strcmp(attr, "armv7a,cortex-a9") == 0) {
+ cpuid = ARM_CPUID_CORTEXA9;
+ arm_regs(vcpu)->pstate = PSR_MODE32;
+ } else if (strcmp(attr, "armv7a,cortex-a15") == 0) {
+ cpuid = ARM_CPUID_CORTEXA15;
+ arm_regs(vcpu)->pstate = PSR_MODE32;
+ } else if (strcmp(attr, "armv8,generic") == 0) {
+ cpuid = ARM_CPUID_ARMV8;
+ } else {
+ return VMM_EFAIL;
+ }
+ if (arm_regs(vcpu)->pstate == PSR_MODE32) {
+ /* Check if the host supports A32 mode @ EL1 */
+ if (!cpu_supports_el1_a32()) {
+ vmm_printf("Host does not support AArch32 mode\n");
+ return VMM_EFAIL;
+ }
+ arm_regs(vcpu)->pstate |= PSR_ZERO_MASK;
+ arm_regs(vcpu)->pstate |= PSR_MODE32_SUPERVISOR;
+ } else {
+ arm_regs(vcpu)->pstate |= PSR_MODE64_DEBUG_DISABLED;
+ arm_regs(vcpu)->pstate |= PSR_MODE64_EL1h;
+ }
+ arm_regs(vcpu)->pstate |= PSR_ASYNC_ABORT_DISABLED;
+ arm_regs(vcpu)->pstate |= PSR_IRQ_DISABLED;
+ arm_regs(vcpu)->pstate |= PSR_FIQ_DISABLED;
+ if (!vcpu->reset_count) {
+ /* Alloc private context */
+ vcpu->arch_priv = vmm_zalloc(sizeof(arm_priv_t));
+ if (!vcpu->arch_priv) {
+ return VMM_ENOMEM;
+ }
+ } else {
+ /* No need to init the other SPRs as their
+ * state is unknown as per AArch64 spec
+ */
+ arm_priv(vcpu)->sctlr = 0x0;
+ arm_priv(vcpu)->sp_el0 = 0x0;
+ arm_priv(vcpu)->sp_el1 = 0x0;
+ arm_priv(vcpu)->elr_el1 = 0x0;
+ arm_priv(vcpu)->spsr_el1 = 0x0;
+ arm_priv(vcpu)->spsr_abt = 0x0;
+ arm_priv(vcpu)->spsr_und = 0x0;
+ arm_priv(vcpu)->spsr_irq = 0x0;
+ arm_priv(vcpu)->spsr_fiq = 0x0;
+ }
+ arm_priv(vcpu)->last_hcpu = 0xFFFFFFFF;
+ generic_timer_vcpu_context_init(arm_gentimer_context(vcpu));
+ if (!vcpu->reset_count) {
+ /* Generic timer physical & virtual irq for the vcpu */
+ attr = vmm_devtree_attrval(vcpu->node, "gentimer_phys_irq");
+ arm_gentimer_context(vcpu)->phys_timer_irq =
+ (attr) ? (*(u32 *)attr) : 0;
+ attr = vmm_devtree_attrval(vcpu->node, "gentimer_virt_irq");
+ arm_gentimer_context(vcpu)->virt_timer_irq =
+ (attr) ? (*(u32 *)attr) : 0;
+ /* Initialize Hypervisor Configuration */
+ INIT_SPIN_LOCK(&arm_priv(vcpu)->hcr_lock);
+ arm_priv(vcpu)->hcr = (HCR_TACR_MASK |
+ HCR_TIDCP_MASK |
+ HCR_TSC_MASK |
+ HCR_TWI_MASK |
+ HCR_AMO_MASK |
+ HCR_IMO_MASK |
+ HCR_FMO_MASK |
+ HCR_SWIO_MASK |
+ HCR_VM_MASK);
+ if (!(arm_regs(vcpu)->pstate & PSR_MODE32)) {
+ arm_priv(vcpu)->hcr |= HCR_RW_MASK;
+ }
+ /* Initialize Hypervisor System Trap Register */
+ arm_priv(vcpu)->hstr = 0;
+ /* Initialize VCPU features */
+ arm_priv(vcpu)->features = 0;
+ switch (cpuid) {
+ case ARM_CPUID_CORTEXA8:
+ arm_set_feature(vcpu, ARM_FEATURE_V4T);
+ arm_set_feature(vcpu, ARM_FEATURE_V5);
+ arm_set_feature(vcpu, ARM_FEATURE_V6);
+ arm_set_feature(vcpu, ARM_FEATURE_V6K);
+ arm_set_feature(vcpu, ARM_FEATURE_V7);
+ arm_set_feature(vcpu, ARM_FEATURE_AUXCR);
+ arm_set_feature(vcpu, ARM_FEATURE_THUMB2);
+ arm_set_feature(vcpu, ARM_FEATURE_VFP);
+ arm_set_feature(vcpu, ARM_FEATURE_VFP3);
+ arm_set_feature(vcpu, ARM_FEATURE_NEON);
+ arm_set_feature(vcpu, ARM_FEATURE_THUMB2EE);
+ break;
+ case ARM_CPUID_CORTEXA9:
+ arm_set_feature(vcpu, ARM_FEATURE_V4T);
+ arm_set_feature(vcpu, ARM_FEATURE_V5);
+ arm_set_feature(vcpu, ARM_FEATURE_V6);
+ arm_set_feature(vcpu, ARM_FEATURE_V6K);
+ arm_set_feature(vcpu, ARM_FEATURE_V7);
+ arm_set_feature(vcpu, ARM_FEATURE_AUXCR);
+ arm_set_feature(vcpu, ARM_FEATURE_THUMB2);
+ arm_set_feature(vcpu, ARM_FEATURE_VFP);
+ arm_set_feature(vcpu, ARM_FEATURE_VFP3);
+ arm_set_feature(vcpu, ARM_FEATURE_VFP_FP16);
+ arm_set_feature(vcpu, ARM_FEATURE_NEON);
+ arm_set_feature(vcpu, ARM_FEATURE_THUMB2EE);
+ arm_set_feature(vcpu, ARM_FEATURE_V7MP);
+ break;
+ case ARM_CPUID_CORTEXA15:
+ arm_set_feature(vcpu, ARM_FEATURE_V4T);
+ arm_set_feature(vcpu, ARM_FEATURE_V5);
+ arm_set_feature(vcpu, ARM_FEATURE_V6);
+ arm_set_feature(vcpu, ARM_FEATURE_V6K);
+ arm_set_feature(vcpu, ARM_FEATURE_V7);
+ arm_set_feature(vcpu, ARM_FEATURE_V7MP);
+ arm_set_feature(vcpu, ARM_FEATURE_AUXCR);
+ arm_set_feature(vcpu, ARM_FEATURE_THUMB2);
+ arm_set_feature(vcpu, ARM_FEATURE_THUMB2EE);
+ arm_set_feature(vcpu, ARM_FEATURE_ARM_DIV);
+ arm_set_feature(vcpu, ARM_FEATURE_VFP);
+ arm_set_feature(vcpu, ARM_FEATURE_VFP4);
+ arm_set_feature(vcpu, ARM_FEATURE_VFP_FP16);
+ arm_set_feature(vcpu, ARM_FEATURE_NEON);
+ arm_set_feature(vcpu, ARM_FEATURE_LPAE);
+ arm_set_feature(vcpu, ARM_FEATURE_GENERIC_TIMER);
+ break;
+ case ARM_CPUID_ARMV8:
+ arm_set_feature(vcpu, ARM_FEATURE_V8);
+ arm_set_feature(vcpu, ARM_FEATURE_VFP);
+ arm_set_feature(vcpu, ARM_FEATURE_VFP4);
+ arm_set_feature(vcpu, ARM_FEATURE_ARM_DIV);
+ arm_set_feature(vcpu, ARM_FEATURE_LPAE);
+ arm_set_feature(vcpu, ARM_FEATURE_GENERIC_TIMER);
+ break;
+ default:
+ break;
+ };
+ } else {
+ /* Clear virtual exception bits in HCR */
+ vmm_spin_lock_irqsave(&arm_priv(vcpu)->hcr_lock, flags);
+ arm_priv(vcpu)->hcr &= ~(HCR_VSE_MASK |
+ HCR_VI_MASK |
+ HCR_VF_MASK);
+ vmm_spin_unlock_irqrestore(&arm_priv(vcpu)->hcr_lock, flags);
+ }
+
+ arm_priv(vcpu)->cpuid = cpuid;
+ arm_priv(vcpu)->tcr = 0x0;
+
+ if (!vcpu->reset_count) {
+ /* Cleanup VGIC context first time */
+ arm_vgic_cleanup(vcpu);
+ }
+
+ return VMM_OK;
+}
+
+int arch_vcpu_deinit(struct vmm_vcpu *vcpu)
+{
+ /* For both Orphan & Normal VCPUs */
+ memset(arm_regs(vcpu), 0, sizeof(arch_regs_t));
+
+ /* For Orphan VCPUs do nothing else */
+ if (!vcpu->is_normal) {
+ return VMM_OK;
+ }
+
+ /* Free private context */
+ vmm_free(vcpu->arch_priv);
+ vcpu->arch_priv = NULL;
+
+ return VMM_OK;
+}
+
+static inline void cpu_vcpu_special_regs_save(struct vmm_vcpu *vcpu)
+{
+ arm_priv(vcpu)->sp_el0 = mrs(sp_el0);
+ arm_priv(vcpu)->sp_el1 = mrs(sp_el1);
+ arm_priv(vcpu)->elr_el1 = mrs(elr_el1);
+ arm_priv(vcpu)->spsr_el1 = mrs(spsr_el1);
+ arm_priv(vcpu)->spsr_abt = mrs(spsr_abt);
+ arm_priv(vcpu)->spsr_und = mrs(spsr_und);
+ arm_priv(vcpu)->spsr_irq = mrs(spsr_irq);
+ arm_priv(vcpu)->spsr_fiq = mrs(spsr_fiq);
+ arm_priv(vcpu)->spsr_irq = mrs(spsr_irq);
+ arm_priv(vcpu)->ttbr0 = mrs(ttbr0_el1);
+ arm_priv(vcpu)->ttbr1 = mrs(ttbr1_el1);
+ arm_priv(vcpu)->sctlr = mrs(sctlr_el1);
+ arm_priv(vcpu)->cpacr = mrs(cpacr_el1);
+ arm_priv(vcpu)->tcr = mrs(tcr_el1);
+ arm_priv(vcpu)->esr = mrs(esr_el1);
+ arm_priv(vcpu)->far = mrs(far_el1);
+ arm_priv(vcpu)->mair = mrs(mair_el1);
+ arm_priv(vcpu)->vbar = mrs(vbar_el1);
+ arm_priv(vcpu)->contextidr = mrs(contextidr_el1);
+ arm_priv(vcpu)->tpidr_el0 = mrs(tpidr_el0);
+ arm_priv(vcpu)->tpidr_el1 = mrs(tpidr_el1);
+ arm_priv(vcpu)->tpidrro = mrs(tpidrro_el0);
+ if (cpu_supports_thumbee()) {
+ arm_priv(vcpu)->teecr = mrs(teecr32_el1);
+ arm_priv(vcpu)->teehbr = mrs(teehbr32_el1);
+ }
+ if (cpu_supports_fpu()) {
+ if (!(mrs(cptr_el2) & CPTR_TFP_MASK)) {
+ arm_priv(vcpu)->fpexc = mrs(fpexc32_el2);
+ arm_priv(vcpu)->fpcr = mrs(fpcr);
+ arm_priv(vcpu)->fpsr = mrs(fpsr);
+ vfp_simd_save_regs(&arm_priv(vcpu)->fpregs);
+ }
+ }
+ arm_priv(vcpu)->dacr = mrs(dacr32_el2);
+ arm_priv(vcpu)->ifsr = mrs(ifsr32_el2);
+}
+
+static inline void cpu_vcpu_special_regs_restore(struct vmm_vcpu * vcpu)
+{
+ msr(sp_el0, arm_priv(vcpu)->sp_el0);
+ msr(sp_el1, arm_priv(vcpu)->sp_el1);
+ msr(elr_el1, arm_priv(vcpu)->elr_el1);
+ msr(spsr_el1, arm_priv(vcpu)->spsr_el1);
+ msr(spsr_abt, arm_priv(vcpu)->spsr_abt);
+ msr(spsr_und, arm_priv(vcpu)->spsr_und);
+ msr(spsr_irq, arm_priv(vcpu)->spsr_irq);
+ msr(spsr_fiq, arm_priv(vcpu)->spsr_fiq);
+ msr(spsr_irq, arm_priv(vcpu)->spsr_irq);
+ msr(ttbr0_el1, arm_priv(vcpu)->ttbr0);
+ msr(ttbr1_el1, arm_priv(vcpu)->ttbr1);
+ msr(sctlr_el1, arm_priv(vcpu)->sctlr);
+ msr(cpacr_el1, arm_priv(vcpu)->cpacr);
+ msr(tcr_el1, arm_priv(vcpu)->tcr);
+ msr(esr_el1, arm_priv(vcpu)->esr);
+ msr(far_el1, arm_priv(vcpu)->far);
+ msr(mair_el1, arm_priv(vcpu)->mair);
+ msr(vbar_el1, arm_priv(vcpu)->vbar);
+ msr(contextidr_el1, arm_priv(vcpu)->contextidr);
+ msr(tpidr_el0, arm_priv(vcpu)->tpidr_el0);
+ msr(tpidr_el1, arm_priv(vcpu)->tpidr_el1);
+ msr(tpidrro_el0, arm_priv(vcpu)->tpidrro);
+ if (cpu_supports_thumbee()) {
+ msr(teecr32_el1, arm_priv(vcpu)->teecr);
+ msr(teehbr32_el1, arm_priv(vcpu)->teehbr);
+ }
+ /* Note that we just disable the FP access and
+ * do not restore the FP/SIMD state
+ * unless the guest accesses FP regs
+ */
+ msr(cptr_el2, CPTR_TTA_MASK | CPTR_TFP_MASK | CPTR_RES1_MASK);
+ msr(dacr32_el2, arm_priv(vcpu)->dacr);
+ msr(ifsr32_el2, arm_priv(vcpu)->ifsr);
+}
+
+void arch_vcpu_switch(struct vmm_vcpu *tvcpu,
+ struct vmm_vcpu *vcpu,
+ arch_regs_t *regs)
+{
+ u32 ite;
+ irq_flags_t flags;
+
+ /* Save user registers & banked registers */
+ if (tvcpu) {
+ arm_regs(tvcpu)->pc = regs->pc;
+ arm_regs(tvcpu)->lr = regs->lr;
+ arm_regs(tvcpu)->sp = regs->sp;
+ for (ite = 0; ite < CPU_GPR_COUNT; ite++) {
+ arm_regs(tvcpu)->gpr[ite] = regs->gpr[ite];
+ }
+ arm_regs(tvcpu)->pstate = regs->pstate;
+ if(tvcpu->is_normal) {
+ /* Save VGIC registers */
+ arm_vgic_save(tvcpu);
+ /* Save generic timer */
+ if (arm_feature(tvcpu, ARM_FEATURE_GENERIC_TIMER)) {
+ generic_timer_vcpu_context_save(arm_gentimer_context(tvcpu));
+ }
+ /* Save special registers */
+ cpu_vcpu_special_regs_save(tvcpu);
+ /* Update last host CPU */
+ arm_priv(tvcpu)->last_hcpu = vmm_smp_processor_id();
+ }
+ }
+ /* Restore user registers & special registers */
+ regs->pc = arm_regs(vcpu)->pc;
+ regs->lr = arm_regs(vcpu)->lr;
+ regs->sp = arm_regs(vcpu)->sp;
+ for (ite = 0; ite < CPU_GPR_COUNT; ite++) {
+ regs->gpr[ite] = arm_regs(vcpu)->gpr[ite];
+ }
+ regs->pstate = arm_regs(vcpu)->pstate;
+ if (vcpu->is_normal) {
+ /* Update Stage2 MMU context */
+ mmu_lpae_stage2_chttbl(vcpu->guest->id,
+ arm_guest_priv(vcpu->guest)->ttbl);
+ msr(vpidr_el2, arm_priv(vcpu)->cpuid);
+ if (arm_feature(vcpu, ARM_FEATURE_V7MP)) {
+ msr(vmpidr_el2, (1 << 31) | vcpu->subid);
+ } else {
+ msr(vmpidr_el2, vcpu->subid);
+ }
+ /* Flush TLB if moved to new host CPU */
+ if (arm_priv(vcpu)->last_hcpu != vmm_smp_processor_id()) {
+ /* Invalidate all guest TLB enteries because
+ * we might have stale guest TLB enteries from
+ * our previous run on new_hcpu host CPU
+ */
+ inv_tlb_guest_allis();
+ /* Ensure changes are visible */
+ dsb();
+ isb();
+ }
+ /* Restore hypervisor context */
+ vmm_spin_lock_irqsave(&arm_priv(vcpu)->hcr_lock, flags);
+ msr(hcr_el2, arm_priv(vcpu)->hcr);
+ vmm_spin_unlock_irqrestore(&arm_priv(vcpu)->hcr_lock, flags);
+ msr(hstr_el2, arm_priv(vcpu)->hstr);
+ /* Restore special registers */
+ cpu_vcpu_special_regs_restore(vcpu);
+ /* Restore generic timer */
+ if(arm_feature(vcpu, ARM_FEATURE_GENERIC_TIMER)) {
+ generic_timer_vcpu_context_restore(
+ arm_gentimer_context(vcpu));
+ }
+ /* Restore VGIC registers */
+ arm_vgic_restore(vcpu);
+ }
+ /* Clear exclusive monitor */
+ clrex();
+}
+
+void arch_vcpu_preempt_orphan(void)
+{
+ /* Trigger HVC call from hypervisor mode. This will cause
+ * do_soft_irq() function to call vmm_scheduler_preempt_orphan()
+ */
+ asm volatile ("hvc #0\t\n");
+}
+
+static void __cpu_vcpu_dump_user_reg(struct vmm_chardev *cdev,
+ arch_regs_t *regs)
+{
+ u32 ite;
+ vmm_cprintf(cdev, " Core Registers\n");
+ vmm_cprintf(cdev, " SP=0x%016lX LR=0x%016lX\n",
+ regs->sp, regs->lr);
+ vmm_cprintf(cdev, " PC=0x%016lX PSTATE=0x%08lX\n",
+ regs->pc, (regs->pstate & 0xffffffff));
+ vmm_cprintf(cdev, " General Purpose Registers");
+ for (ite = 0; ite < (CPU_GPR_COUNT); ite++) {
+ if (ite % 2 == 0)
+ vmm_cprintf(cdev, "\n");
+ vmm_cprintf(cdev, " X%02d=0x%016lX ", ite, regs->gpr[ite]);
+ }
+ vmm_cprintf(cdev, "\n");
+}
+
+void cpu_vcpu_dump_user_reg(arch_regs_t *regs)
+{
+ __cpu_vcpu_dump_user_reg(NULL, regs);
+}
+
+void arch_vcpu_regs_dump(struct vmm_chardev *cdev, struct vmm_vcpu *vcpu)
+{
+ /* For both Normal & Orphan VCPUs */
+ __cpu_vcpu_dump_user_reg(cdev, arm_regs(vcpu));
+ /* For only Normal VCPUs */
+ if (!vcpu->is_normal) {
+ return;
+ }
+ vmm_cprintf(cdev, " TTBR_EL2: 0x%016lX\n",
+ arm_guest_priv(vcpu->guest)->ttbl->tbl_pa);
+ vmm_cprintf(cdev, " HCR_EL2: 0x%016lX\n",
+ arm_priv(vcpu)->hcr);
+ vmm_cprintf(cdev, " CPTR_EL2: 0x%016lX\n",
+ arm_priv(vcpu)->cptr);
+ vmm_cprintf(cdev, " HSTR_EL2: 0x%016lX\n",
+ arm_priv(vcpu)->hstr);
+ vmm_cprintf(cdev, " SP_EL0: 0x%016lX\n",
+ arm_priv(vcpu)->sp_el0);
+ vmm_cprintf(cdev, " SP_EL1: 0x%016lX\n",
+ arm_priv(vcpu)->sp_el1);
+ vmm_cprintf(cdev, " ELR_EL1: 0x%016lX\n",
+ arm_priv(vcpu)->elr_el1);
+ vmm_cprintf(cdev, " SPSR_EL1: 0x%016lX\n",
+ arm_priv(vcpu)->spsr_el1);
+ vmm_cprintf(cdev, " SPSR_ABT: 0x%08lX\n",
+ arm_priv(vcpu)->spsr_abt);
+ vmm_cprintf(cdev, " SPSR_UND: 0x%08lX\n",
+ arm_priv(vcpu)->spsr_und);
+ vmm_cprintf(cdev, " SPSR_IRQ: 0x%08lX\n",
+ arm_priv(vcpu)->spsr_irq);
+ vmm_cprintf(cdev, " SPSR_FIQ: 0x%08lX\n",
+ arm_priv(vcpu)->spsr_fiq);
+ vmm_cprintf(cdev, " MIDR_EL1: 0x%016lX\n",
+ arm_priv(vcpu)->cpuid);
+ vmm_cprintf(cdev, " MPIDR_EL1: 0x%016lX\n",
+ arm_priv(vcpu)->mpidr);
+ vmm_cprintf(cdev, " SCTLR_EL1: 0x%016lX\n",
+ arm_priv(vcpu)->sctlr);
+ vmm_cprintf(cdev, " CPACR_EL1: 0x%016lX\n",
+ arm_priv(vcpu)->cpacr);
+ vmm_cprintf(cdev, " TTBR0_EL1: 0x%016lX\n",
+ arm_priv(vcpu)->ttbr0);
+ vmm_cprintf(cdev, " TTBR1_EL1: 0x%016lX\n",
+ arm_priv(vcpu)->ttbr1);
+ vmm_cprintf(cdev, " TCR_EL1: 0x%016lX\n",
+ arm_priv(vcpu)->tcr);
+ vmm_cprintf(cdev, " ESR_EL1: 0x%016lX\n",
+ arm_priv(vcpu)->esr);
+ vmm_cprintf(cdev, " FAR_EL1: 0x%016lX\n",
+ arm_priv(vcpu)->far);
+ vmm_cprintf(cdev, " PAR_EL1: 0x%016lX\n",
+ arm_priv(vcpu)->par);
+ vmm_cprintf(cdev, " MAIR_EL1: 0x%016lX\n",
+ arm_priv(vcpu)->mair);
+ vmm_cprintf(cdev, " VBAR_EL1: 0x%016lX\n",
+ arm_priv(vcpu)->vbar);
+ vmm_cprintf(cdev, " CONTEXTIDR_EL1: 0x%016lX\n",
+ arm_priv(vcpu)->contextidr);
+ vmm_cprintf(cdev, " TPIDR_EL0: 0x%016lX\n",
+ arm_priv(vcpu)->tpidr_el0);
+ vmm_cprintf(cdev, " TPIDR_EL1: 0x%016lX\n",
+ arm_priv(vcpu)->tpidr_el1);
+ vmm_cprintf(cdev, " TPIDRRO: 0x%016lX\n",
+ arm_priv(vcpu)->tpidrro);
+ vmm_cprintf(cdev, "\n");
+}
+
+void arch_vcpu_stat_dump(struct vmm_chardev *cdev, struct vmm_vcpu *vcpu)
+{
+ /* For now no arch specific stats */
+}
diff --git a/arch/arm/cpu/arm64/cpu_vcpu_irq.c b/arch/arm/cpu/arm64/cpu_vcpu_irq.c
new file mode 100644
index 0000000..6a01abf
--- /dev/null
+++ b/arch/arm/cpu/arm64/cpu_vcpu_irq.c
@@ -0,0 +1,201 @@
+/**
+ * Copyright (c) 2012 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_vcpu_irq.c
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief source code for handling vcpu interrupts
+ */
+
+#include <vmm_error.h>
+#include <vmm_scheduler.h>
+#include <vmm_vcpu_irq.h>
+#include <vmm_stdio.h>
+#include <arch_vcpu.h>
+#include <cpu_inline_asm.h>
+#include <cpu_vcpu_helper.h>
+#include <cpu_defines.h>
+
+u32 arch_vcpu_irq_count(struct vmm_vcpu *vcpu)
+{
+ return CPU_IRQ_NR;
+}
+
+u32 arch_vcpu_irq_priority(struct vmm_vcpu *vcpu, u32 irq_no)
+{
+ u32 ret = 3;
+
+ switch (irq_no) {
+ case CPU_RESET_IRQ:
+ ret = 0;
+ break;
+ case CPU_UNDEF_INST_IRQ:
+ ret = 1;
+ break;
+ case CPU_SOFT_IRQ:
+ ret = 2;
+ break;
+ case CPU_PREFETCH_ABORT_IRQ:
+ ret = 2;
+ break;
+ case CPU_DATA_ABORT_IRQ:
+ ret = 2;
+ break;
+ case CPU_HYP_TRAP_IRQ:
+ ret = 2;
+ break;
+ case CPU_EXTERNAL_IRQ:
+ ret = 2;
+ break;
+ case CPU_EXTERNAL_FIQ:
+ ret = 2;
+ break;
+ default:
+ break;
+ };
+
+ return ret;
+}
+
+int arch_vcpu_irq_assert(struct vmm_vcpu *vcpu, u32 irq_no, u64 reason)
+{
+ u64 hcr;
+ bool update_hcr;
+ irq_flags_t flags;
+
+ /* Skip IRQ & FIQ if VGIC available */
+ if (arm_vgic_avail(vcpu) &&
+ ((irq_no == CPU_EXTERNAL_IRQ) ||
+ (irq_no == CPU_EXTERNAL_FIQ))) {
+ return VMM_OK;
+ }
+
+ vmm_spin_lock_irqsave(&arm_priv(vcpu)->hcr_lock, flags);
+
+ hcr = arm_priv(vcpu)->hcr;
+ update_hcr = FALSE;
+
+ switch(irq_no) {
+ case CPU_EXTERNAL_IRQ:
+ hcr |= HCR_VI_MASK;
+ /* VI bit will be cleared on deassertion */
+ update_hcr = TRUE;
+ break;
+ case CPU_EXTERNAL_FIQ:
+ hcr |= HCR_VF_MASK;
+ /* VF bit will be cleared on deassertion */
+ update_hcr = TRUE;
+ break;
+ default:
+ break;
+ };
+
+ if (update_hcr) {
+ arm_priv(vcpu)->hcr = hcr;
+ if (vcpu == vmm_scheduler_current_vcpu()) {
+ msr(hcr_el2, hcr);
+ }
+ }
+
+ vmm_spin_unlock_irqrestore(&arm_priv(vcpu)->hcr_lock, flags);
+
+ return VMM_OK;
+}
+
+
+int arch_vcpu_irq_execute(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 irq_no, u64 reason)
+{
+ int rc;
+ irq_flags_t flags;
+
+ /* Skip IRQ & FIQ if VGIC available */
+ if (arm_vgic_avail(vcpu) &&
+ ((irq_no == CPU_EXTERNAL_IRQ) ||
+ (irq_no == CPU_EXTERNAL_FIQ))) {
+ return VMM_OK;
+ }
+
+ /* Undefined, Data abort, and Prefetch abort
+ * can only be emulated in normal context.
+ */
+ switch(irq_no) {
+ case CPU_UNDEF_INST_IRQ:
+ rc = cpu_vcpu_inject_undef(vcpu, regs);
+ break;
+ case CPU_PREFETCH_ABORT_IRQ:
+ rc = cpu_vcpu_inject_pabt(vcpu, regs);
+ break;
+ case CPU_DATA_ABORT_IRQ:
+ rc = cpu_vcpu_inject_dabt(vcpu, regs, (virtual_addr_t)reason);
+ break;
+ default:
+ rc = VMM_OK;
+ break;
+ };
+
+ vmm_spin_lock_irqsave(&arm_priv(vcpu)->hcr_lock, flags);
+ msr(hcr_el2, arm_priv(vcpu)->hcr);
+ vmm_spin_unlock_irqrestore(&arm_priv(vcpu)->hcr_lock, flags);
+
+ return rc;
+}
+
+int arch_vcpu_irq_deassert(struct vmm_vcpu *vcpu, u32 irq_no, u64 reason)
+{
+ u64 hcr;
+ bool update_hcr;
+ irq_flags_t flags;
+
+ /* Skip IRQ & FIQ if VGIC available */
+ if (arm_vgic_avail(vcpu) &&
+ ((irq_no == CPU_EXTERNAL_IRQ) ||
+ (irq_no == CPU_EXTERNAL_FIQ))) {
+ return VMM_OK;
+ }
+
+ vmm_spin_lock_irqsave(&arm_priv(vcpu)->hcr_lock, flags);
+
+ hcr = arm_priv(vcpu)->hcr;
+ update_hcr = FALSE;
+
+ switch(irq_no) {
+ case CPU_EXTERNAL_IRQ:
+ hcr &= ~HCR_VI_MASK;
+ update_hcr = TRUE;
+ break;
+ case CPU_EXTERNAL_FIQ:
+ hcr &= ~HCR_VF_MASK;
+ update_hcr = TRUE;
+ break;
+ default:
+ break;
+ };
+
+ if (update_hcr) {
+ arm_priv(vcpu)->hcr = hcr;
+ if (vcpu == vmm_scheduler_current_vcpu()) {
+ msr(hcr_el2, hcr);
+ }
+ }
+
+ vmm_spin_unlock_irqrestore(&arm_priv(vcpu)->hcr_lock, flags);
+
+ return VMM_OK;
+}
+
diff --git a/arch/arm/cpu/arm64/cpu_vcpu_mem.c b/arch/arm/cpu/arm64/cpu_vcpu_mem.c
new file mode 100644
index 0000000..1b58f0f
--- /dev/null
+++ b/arch/arm/cpu/arm64/cpu_vcpu_mem.c
@@ -0,0 +1,135 @@
+/**
+ * Copyright (c) 2012 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_vcpu_mem.c
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief This source file is for VCPU memory read/write emulation
+ */
+
+#include <vmm_error.h>
+#include <vmm_devemu.h>
+#include <cpu_inline_asm.h>
+#include <cpu_vcpu_helper.h>
+#include <cpu_vcpu_mem.h>
+
+int cpu_vcpu_mem_read(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ virtual_addr_t addr,
+ void *dst, u32 dst_len,
+ bool force_unpriv)
+{
+ int rc;
+ u8 data8;
+ u16 data16;
+ u32 data32;
+ physical_addr_t guest_pa;
+
+ /* Determine guest physical address */
+ va2pa_at(VA2PA_STAGE1, VA2PA_EL1, VA2PA_RD, addr);
+ guest_pa = mrs(par_el1);
+ guest_pa &= PAR_PA_MASK;
+ guest_pa |= (addr & 0x00000FFF);
+
+ /* Do guest memory read */
+ switch (dst_len) {
+ case 1:
+ rc = vmm_devemu_emulate_read(vcpu, guest_pa,
+ &data8, sizeof(data8));
+ *((u8 *)dst) = (!rc) ? data8 : 0;
+ break;
+ case 2:
+ rc = vmm_devemu_emulate_read(vcpu, guest_pa,
+ &data16, sizeof(data16));
+ *((u16 *)dst) = (!rc) ? data16 : 0;
+ break;
+ case 4:
+ rc = vmm_devemu_emulate_read(vcpu, guest_pa,
+ &data32, sizeof(data32));
+ *((u32 *)dst) = (!rc) ? data32 : 0;
+ break;
+ default:
+ rc = VMM_EFAIL;
+ break;
+ };
+
+ return rc;
+}
+
+int cpu_vcpu_mem_write(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ virtual_addr_t addr,
+ void *src, u32 src_len,
+ bool force_unpriv)
+{
+ int rc;
+ u8 data8;
+ u16 data16;
+ u32 data32;
+ physical_addr_t guest_pa;
+
+ /* Determine guest physical address */
+ va2pa_at(VA2PA_STAGE1, VA2PA_EL1, VA2PA_WR, addr);
+ guest_pa = mrs(par_el1);
+ guest_pa &= PAR_PA_MASK;
+ guest_pa |= (addr & 0x00000FFF);
+
+ /* Do guest memory read */
+ switch (src_len) {
+ case 1:
+ data8 = *((u8 *)src);
+ rc = vmm_devemu_emulate_write(vcpu, guest_pa,
+ &data8, sizeof(data8));
+ break;
+ case 2:
+ data16 = *((u16 *)src);
+ rc = vmm_devemu_emulate_write(vcpu, guest_pa,
+ &data16, sizeof(data16));
+ break;
+ case 4:
+ data32 = *((u32 *)src);
+ rc = vmm_devemu_emulate_write(vcpu, guest_pa,
+ &data32, sizeof(data32));
+ break;
+ default:
+ rc = VMM_EFAIL;
+ break;
+ };
+
+ return rc;
+}
+
+int cpu_vcpu_mem_readex(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ virtual_addr_t addr,
+ void *dst, u32 dst_len,
+ bool force_unpriv)
+{
+ /* Not supported */
+ return VMM_EFAIL;
+}
+
+int cpu_vcpu_mem_writeex(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ virtual_addr_t addr,
+ void *src, u32 src_len,
+ bool force_unpriv)
+{
+ /* Not supported */
+ return VMM_EFAIL;
+}
+
diff --git a/arch/arm/cpu/arm64/cpu_vcpu_spr.c b/arch/arm/cpu/arm64/cpu_vcpu_spr.c
new file mode 100644
index 0000000..de22a0d
--- /dev/null
+++ b/arch/arm/cpu/arm64/cpu_vcpu_spr.c
@@ -0,0 +1,359 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_vcpu_spr.c
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief VCPU SPR Emulation
+ * @details This source file implements SPRs for each VCPU.
+ */
+
+#include <vmm_heap.h>
+#include <vmm_error.h>
+#include <vmm_stdio.h>
+#include <vmm_devemu.h>
+#include <vmm_scheduler.h>
+#include <vmm_host_aspace.h>
+#include <vmm_guest_aspace.h>
+#include <vmm_vcpu_irq.h>
+#include <libs/stringlib.h>
+#include <cpu_inline_asm.h>
+#include <cpu_vcpu_helper.h>
+#include <cpu_vcpu_emulate.h>
+#include <cpu_vcpu_spr.h>
+#include <mmu_lpae.h>
+#include <emulate_arm.h>
+#include <emulate_thumb.h>
+#include <arm_features.h>
+
+static int cpu_vcpu_stage2_map(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ physical_addr_t fipa)
+{
+ int rc, rc1;
+ u32 reg_flags = 0x0;
+ struct cpu_page pg;
+ physical_addr_t inaddr, outaddr;
+ physical_size_t size, availsz;
+
+ memset(&pg, 0, sizeof(pg));
+
+ inaddr = fipa & TTBL_L3_MAP_MASK;
+ size = TTBL_L3_BLOCK_SIZE;
+ pg.sh = 3U;
+
+ rc = vmm_guest_physical_map(vcpu->guest, inaddr, size,
+ &outaddr, &availsz, &reg_flags);
+ if (rc) {
+ vmm_printf("%s: IPA=0x%lx size=0x%lx map failed\n",
+ __func__, inaddr, size);
+ return rc;
+ }
+
+ if (availsz < TTBL_L3_BLOCK_SIZE) {
+ vmm_printf("%s: availsz=0x%lx insufficent for IPA=0x%lx\n",
+ __func__, availsz, inaddr);
+ return VMM_EFAIL;
+ }
+
+ pg.ia = inaddr;
+ pg.sz = size;
+ pg.oa = outaddr;
+
+ if (reg_flags & (VMM_REGION_ISRAM | VMM_REGION_ISROM)) {
+ inaddr = fipa & TTBL_L2_MAP_MASK;
+ size = TTBL_L2_BLOCK_SIZE;
+ rc = vmm_guest_physical_map(vcpu->guest, inaddr, size,
+ &outaddr, &availsz, &reg_flags);
+ if (!rc && (availsz >= TTBL_L2_BLOCK_SIZE)) {
+ pg.ia = inaddr;
+ pg.sz = size;
+ pg.oa = outaddr;
+ }
+ }
+
+ if (reg_flags & VMM_REGION_VIRTUAL) {
+ pg.af = 0;
+ pg.ap = TTBL_HAP_NOACCESS;
+ } else if (reg_flags & VMM_REGION_READONLY) {
+ pg.af = 1;
+ pg.ap = TTBL_HAP_READONLY;
+ } else {
+ pg.af = 1;
+ pg.ap = TTBL_HAP_READWRITE;
+ }
+
+ /* memattr in stage 2
+ * ------------------
+ * 0x0 - strongly ordered
+ * 0x5 - normal-memory NC
+ * 0xA - normal-memory WT
+ * 0xF - normal-memory WB
+ */
+ if (reg_flags & VMM_REGION_CACHEABLE) {
+ if (reg_flags & VMM_REGION_BUFFERABLE) {
+ pg.memattr = 0xF;
+ } else {
+ pg.memattr = 0xA;
+ }
+ } else {
+ pg.memattr = 0x0;
+ }
+
+ /* Try to map the page in Stage2 */
+ rc = mmu_lpae_map_page(arm_guest_priv(vcpu->guest)->ttbl, &pg);
+ if (rc) {
+ /* On SMP Guest, two different VCPUs may try to map same
+ * Guest region in Stage2 at the same time. This may cause
+ * mmu_lpae_map_page() to fail for one of the Guest VCPUs.
+ *
+ * To take care of this situation, we recheck Stage2 mapping
+ * when mmu_lpae_map_page() fails.
+ */
+ memset(&pg, 0, sizeof(pg));
+ rc1 = mmu_lpae_get_page(arm_guest_priv(vcpu->guest)->ttbl,
+ fipa, &pg);
+ if (rc1) {
+ return rc1;
+ }
+ rc = VMM_OK;
+ }
+
+ return rc;
+}
+
+int cpu_vcpu_inst_abort(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 il, u32 iss,
+ physical_addr_t fipa)
+{
+ switch (iss & ISS_ABORT_FSC_MASK) {
+ case FSC_TRANS_FAULT_LEVEL1:
+ case FSC_TRANS_FAULT_LEVEL2:
+ case FSC_TRANS_FAULT_LEVEL3:
+ return cpu_vcpu_stage2_map(vcpu, regs, fipa);
+ default:
+ break;
+ };
+
+ return VMM_EFAIL;
+}
+
+int cpu_vcpu_data_abort(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 il, u32 iss,
+ physical_addr_t fipa)
+{
+ u32 read_count, inst;
+ physical_addr_t inst_pa;
+
+ switch (iss & ISS_ABORT_FSC_MASK) {
+ case FSC_TRANS_FAULT_LEVEL1:
+ case FSC_TRANS_FAULT_LEVEL2:
+ case FSC_TRANS_FAULT_LEVEL3:
+ return cpu_vcpu_stage2_map(vcpu, regs, fipa);
+ case FSC_ACCESS_FAULT_LEVEL1:
+ case FSC_ACCESS_FAULT_LEVEL2:
+ case FSC_ACCESS_FAULT_LEVEL3:
+ if (!(iss & ISS_ABORT_ISV_MASK)) {
+ /* Determine instruction physical address */
+ va2pa_at(VA2PA_STAGE1, VA2PA_EL1, VA2PA_RD, regs->pc);
+ inst_pa = mrs(par_el1);
+ inst_pa &= PAR_PA_MASK;
+ inst_pa |= (regs->pc & 0x00000FFF);
+
+ /* Read the faulting instruction */
+ read_count =
+ vmm_host_memory_read(inst_pa, &inst, sizeof(inst));
+ if (read_count != sizeof(inst)) {
+ return VMM_EFAIL;
+ }
+ if (regs->pstate & PSR_THUMB_ENABLED) {
+ return emulate_thumb_inst(vcpu, regs, inst);
+ } else {
+ return emulate_arm_inst(vcpu, regs, inst);
+ }
+ }
+ if (iss & ISS_ABORT_WNR_MASK) {
+ return cpu_vcpu_emulate_store(vcpu, regs,
+ il, iss, fipa);
+ } else {
+ return cpu_vcpu_emulate_load(vcpu, regs,
+ il, iss, fipa);
+ }
+ default:
+ vmm_printf("%s: Unhandled FSC=0x%x\n",
+ __func__, iss & ISS_ABORT_FSC_MASK);
+ break;
+ };
+
+ return VMM_EFAIL;
+}
+
+bool cpu_vcpu_cp15_read(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 opc2, u32 CRn, u32 CRm,
+ u64 *data)
+{
+ *data = 0x0;
+ switch (CRn) {
+ case 1: /* System configuration. */
+ switch (opc2) {
+ case 1: /* Auxiliary control register. */
+ if (!arm_feature(vcpu, ARM_FEATURE_AUXCR))
+ goto bad_reg;
+ switch (arm_cpuid(vcpu)) {
+ case ARM_CPUID_CORTEXA8:
+ *data = 2;
+ break;
+ case ARM_CPUID_CORTEXA9:
+ *data = 0;
+ if (arm_feature(vcpu, ARM_FEATURE_V7MP)) {
+ *data |= (1 << 6);
+ } else {
+ *data &= ~(1 << 6);
+ }
+ break;
+ case ARM_CPUID_CORTEXA15:
+ *data = 0;
+ if (arm_feature(vcpu, ARM_FEATURE_V7MP)) {
+ *data |= (1 << 6);
+ } else {
+ *data &= ~(1 << 6);
+ }
+ break;
+ default:
+ goto bad_reg;
+ }
+ break;
+ default:
+ goto bad_reg;
+ };
+ break;
+ case 15:
+ switch (opc1) {
+ case 4: /* CBAR: Configuration Base Address Register */
+ switch (arm_cpuid(vcpu)) {
+ case ARM_CPUID_CORTEXA9:
+ *data = 0x1e000000;
+ break;
+ case ARM_CPUID_CORTEXA15:
+ *data = 0x2c000000;
+ break;
+ default:
+ goto bad_reg;
+ };
+ break;
+ default:
+ goto bad_reg;
+ };
+ break;
+ break;
+ }
+ return TRUE;
+bad_reg:
+ vmm_printf("Unimplemented [mrc p15, %d, <Rt>, c%d, c%d, %d]\n",
+ opc1, CRn, CRm, opc2);
+ return FALSE;
+}
+
+bool cpu_vcpu_cp15_write(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 opc2, u32 CRn, u32 CRm,
+ u64 data)
+{
+ switch (CRn) {
+ case 1: /* System configuration. */
+ switch (opc2) {
+ case 1: /* Auxiliary control register. */
+ /* Not implemented. */
+ break;
+ default:
+ goto bad_reg;
+ };
+ break;
+ }
+ return TRUE;
+bad_reg:
+ vmm_printf("Unimplemented [mcr p15, %d, <Rt>, c%d, c%d, %d]\n",
+ opc1, CRn, CRm, opc2);
+ return FALSE;
+}
+
+bool cpu_vcpu_cp14_read(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 opc2, u32 CRn, u32 CRm,
+ u64 *data)
+{
+ *data = 0x0;
+ switch (opc1) {
+ case 6: /* ThumbEE registers */
+ switch (CRn) {
+ case 0: /* TEECR */
+ *data = arm_priv(vcpu)->teecr;
+ break;
+ case 1: /* TEEHBR */
+ *data = arm_priv(vcpu)->teehbr;
+ break;
+ default:
+ goto bad_reg;
+ };
+ break;
+ case 0: /* Debug registers */
+ case 1: /* Trace registers */
+ case 7: /* Jazelle registers */
+ default:
+ goto bad_reg;
+ };
+ return TRUE;
+bad_reg:
+ vmm_printf("Unimplemented [mrc p14, %d, <Rt>, c%d, c%d, %d]\n",
+ opc1, CRn, CRm, opc2);
+ return FALSE;
+}
+
+bool cpu_vcpu_cp14_write(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 opc2, u32 CRn, u32 CRm,
+ u64 data)
+{
+ switch (opc1) {
+ case 6: /* ThumbEE registers */
+ switch (CRn) {
+ case 0: /* TEECR */
+ arm_priv(vcpu)->teecr = data;
+ break;
+ case 1: /* TEEHBR */
+ arm_priv(vcpu)->teehbr = data;
+ break;
+ default:
+ goto bad_reg;
+ };
+ break;
+ case 0: /* Debug registers */
+ case 1: /* Trace registers */
+ case 7: /* Jazelle registers */
+ default:
+ goto bad_reg;
+ };
+ return TRUE;
+bad_reg:
+ vmm_printf("Unimplemented [mcr p14, %d, <Rt>, c%d, c%d, %d]\n",
+ opc1, CRn, CRm, opc2);
+ return FALSE;
+}
+
diff --git a/arch/arm/cpu/arm64/include/arch_barrier.h b/arch/arm/cpu/arm64/include/arch_barrier.h
new file mode 100644
index 0000000..c7c53fe
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/arch_barrier.h
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arch_barrier.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief architecure specific memory barriers
+ */
+#ifndef __ARCH_BARRIER_H__
+#define __ARCH_BARRIER_H__
+
+#define isb() asm volatile ("isb" : : : "memory")
+#define dsb() asm volatile ("dsb sy" : : : "memory")
+#define dmb() asm volatile ("dmb sy" : : : "memory")
+
+/* Read & Write Memory barrier */
+#define arch_mb() dmb()
+
+/* Read Memory barrier */
+#define arch_rmb() asm volatile ("dmb ld" : : : "memory")
+
+/* Write Memory barrier */
+#define arch_wmb() asm volatile ("dmb st" : : : "memory")
+
+/* SMP Read & Write Memory barrier */
+#define arch_smp_mb() asm volatile ("dmb ish" : : : "memory")
+
+/* SMP Read Memory barrier */
+#define arch_smp_rmb() asm volatile ("dmb ishld" : : : "memory")
+
+/* SMP Write Memory barrier */
+#define arch_smp_wmb() asm volatile ("dmb ishst" : : : "memory")
+
+#endif /* __ARCH_BARRIER_H__ */
diff --git a/arch/arm/cpu/arm64/include/arch_cache.h b/arch/arm/cpu/arm64/include/arch_cache.h
new file mode 100644
index 0000000..45f1d11
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/arch_cache.h
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arch_cache.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief arch specific cache operation
+ */
+#ifndef _ARCH_CACHE_H__
+#define _ARCH_CACHE_H__
+
+#include <cpu_cache.h>
+
+#define ARCH_CACHE_LINE_SIZE 64
+#define ARCH_CACHE_LINE_SHIFT 6
+
+/* Prototype:
+ * void arch_flush_cache_all(void)
+ */
+#define ARCH_HAS_FLUSH_CACHE_ALL
+#define arch_flush_cache_all() do { \
+ clean_invalidate_dcache(); \
+ } while (0)
+
+/* Prototype:
+ * void arch_flush_cache_range(virtual_addr_t start, virtual_addr_t end)
+ */
+#define ARCH_HAS_FLUSH_CACHE_RANGE
+#define arch_flush_cache_range(start, end) do { \
+ clean_invalidate_dcache_mva_range((start),(end)); \
+ } while (0)
+
+/* Prototype:
+ * void arch_flush_dcache_range(virtual_addr_t start, virtual_addr_t end)
+ */
+#define ARCH_HAS_FLUSH_DCACHE_RANGE
+#define arch_flush_dcache_range(start, end) do { \
+ clean_invalidate_dcache_mva_range((start),(end)); \
+ } while (0)
+
+
+#endif /* _ARCH_CACHE_H__ */
diff --git a/arch/arm/cpu/arm64/include/arch_config.h b/arch/arm/cpu/arm64/include/arch_config.h
new file mode 100644
index 0000000..33a7870
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/arch_config.h
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arch_config.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief config file for specifying arch specific optional features
+ *
+ */
+#ifndef _ARCH_CONFIG_H__
+#define _ARCH_CONFIG_H__
+
+//#define ARCH_HAS_MEMCPY
+//#define ARCH_HAS_MEMSET
+
+#endif /* _ARCH_CONFIG_H__ */
diff --git a/arch/arm/cpu/arm64/include/arch_cpu_irq.h b/arch/arm/cpu/arm64/include/arch_cpu_irq.h
new file mode 100644
index 0000000..b343ec1
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/arch_cpu_irq.h
@@ -0,0 +1,82 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arch_cpu_irq.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief interface for controlling CPU IRQs
+ */
+#ifndef _ARCH_CPU_IRQ_H__
+#define _ARCH_CPU_IRQ_H__
+
+#include <vmm_types.h>
+#include <cpu_defines.h>
+
+/** Setup IRQ for CPU */
+int arch_cpu_irq_setup(void);
+
+/** Enable IRQ
+ * Prototype: void arch_cpu_irq_enable(void);
+ */
+#define arch_cpu_irq_enable() do { \
+ asm volatile("msr daifclr, #2":::"memory"); \
+ } while (0)
+
+/** Disable IRQ
+ * Prototype: void arch_cpu_irq_disable(void);
+ */
+#define arch_cpu_irq_disable() do { \
+ asm volatile("msr daifset, #2":::"memory"); \
+ } while (0)
+
+/** Check whether IRQs are disabled
+ * Prototype: bool arch_cpu_irq_disabled(void);
+ */
+#define arch_cpu_irq_disabled() ({ unsigned long __flgs; \
+ asm volatile (" mrs %0, daif" \
+ :"=r" (__flgs)::"memory", "cc"); \
+ (__flgs & PSR_IRQ_DISABLED) ? TRUE : FALSE; \
+ })
+
+
+/** Save IRQ flags and disable IRQ
+ * Prototype: void arch_cpu_irq_save(irq_flags_t flags);
+ */
+#define arch_cpu_irq_save(flags) do { \
+ asm volatile ( \
+ "mrs %0, daif\n\t" \
+ "msr daifset, #2" \
+ :"=r" (flags)::"memory", "cc"); \
+ } while(0)
+
+/** Restore IRQ flags
+ * Prototype: void arch_cpu_irq_restore(irq_flags_t flags);
+ */
+#define arch_cpu_irq_restore(flags) do { \
+ asm volatile ( \
+ "msr daif, %0"::"r" (flags) \
+ :"memory", "cc"); \
+ } while(0)
+
+/** Wait for IRQ
+ * Prototype: void arch_cpu_wait_for_irq(void);
+ */
+#define arch_cpu_wait_for_irq() do { \
+ asm volatile ("wfi"); \
+ } while (0)
+
+#endif
diff --git a/arch/arm/cpu/arm64/include/arch_delay.h b/arch/arm/cpu/arm64/include/arch_delay.h
new file mode 100644
index 0000000..88e7c9b
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/arch_delay.h
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arch_delay.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief arch specific delay routines
+ */
+#ifndef _ARCH_DELAY_H__
+#define _ARCH_DELAY_H__
+
+#include <vmm_types.h>
+
+/** Low-level delay loop */
+void arch_delay_loop(u32 count);
+
+/** Estimated cycles for given loop count
+ * Note: This can be processor specific
+ */
+static inline u32 arch_delay_loop_cycles(u32 count)
+{
+ return count * 2;
+}
+
+#endif
diff --git a/arch/arm/cpu/arm64/include/arch_elf.h b/arch/arm/cpu/arm64/include/arch_elf.h
new file mode 100644
index 0000000..c7078f8
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/arch_elf.h
@@ -0,0 +1,99 @@
+/**
+ * Copyright (c) 2012 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arch_elf.h
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief arch specific ELF routines
+ */
+#ifndef _ARCH_ELF_H__
+#define _ARCH_ELF_H__
+
+#include <vmm_types.h>
+
+/* ARM elf specific declarations */
+
+#define EF_ARM_EABI_MASK 0xff000000
+#define EF_ARM_EABI_UNKNOWN 0x00000000
+#define EF_ARM_EABI_VER1 0x01000000
+#define EF_ARM_EABI_VER2 0x02000000
+#define EF_ARM_EABI_VER3 0x03000000
+#define EF_ARM_EABI_VER4 0x04000000
+#define EF_ARM_EABI_VER5 0x05000000
+
+#define EF_ARM_BE8 0x00800000 /* ABI 4,5 */
+#define EF_ARM_LE8 0x00400000 /* ABI 4,5 */
+#define EF_ARM_MAVERICK_FLOAT 0x00000800 /* ABI 0 */
+#define EF_ARM_VFP_FLOAT 0x00000400 /* ABI 0 */
+#define EF_ARM_SOFT_FLOAT 0x00000200 /* ABI 0 */
+#define EF_ARM_OLD_ABI 0x00000100 /* ABI 0 */
+#define EF_ARM_NEW_ABI 0x00000080 /* ABI 0 */
+#define EF_ARM_ALIGN8 0x00000040 /* ABI 0 */
+#define EF_ARM_PIC 0x00000020 /* ABI 0 */
+#define EF_ARM_MAPSYMSFIRST 0x00000010 /* ABI 2 */
+#define EF_ARM_APCS_FLOAT 0x00000010 /* ABI 0, floats in fp regs */
+#define EF_ARM_DYNSYMSUSESEGIDX 0x00000008 /* ABI 2 */
+#define EF_ARM_APCS_26 0x00000008 /* ABI 0 */
+#define EF_ARM_SYMSARESORTED 0x00000004 /* ABI 1,2 */
+#define EF_ARM_INTERWORK 0x00000004 /* ABI 0 */
+#define EF_ARM_HASENTRY 0x00000002 /* All */
+#define EF_ARM_RELEXEC 0x00000001 /* All */
+
+#define R_ARM_NONE 0
+#define R_ARM_PC24 1
+#define R_ARM_ABS32 2
+#define R_ARM_CALL 28
+#define R_ARM_JUMP24 29
+#define R_ARM_V4BX 40
+#define R_ARM_PREL31 42
+#define R_ARM_MOVW_ABS_NC 43
+#define R_ARM_MOVT_ABS 44
+
+#define R_ARM_THM_CALL 10
+#define R_ARM_THM_JUMP24 30
+#define R_ARM_THM_MOVW_ABS_NC 47
+#define R_ARM_THM_MOVT_ABS 48
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS ELFCLASS64
+#ifdef __ARMEB__
+#define ELF_DATA ELFDATA2MSB
+#else
+#define ELF_DATA ELFDATA2LSB
+#endif
+#define ELF_ARCH EM_AARCH64
+
+struct elf64_hdr;
+struct elf64_shdr;
+
+int arch_elf_check_hdr(const struct elf64_hdr *x);
+
+int arch_elf_apply_relocate(struct elf64_shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relindex,
+ struct vmm_module *mod);
+
+int arch_elf_apply_relocate_add(struct elf64_shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct vmm_module *mod);
+
+#endif
diff --git a/arch/arm/cpu/arm64/include/arch_io.h b/arch/arm/cpu/arm64/include/arch_io.h
new file mode 100644
index 0000000..130d9cd
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/arch_io.h
@@ -0,0 +1,193 @@
+/**
+ * Copyright (c) 2012 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arch_io.h
+ * @author Anup Patel (an...@brainfault.org)
+ * @author Jim Huang (js...@0xlab.org)
+ * @brief header file for CPU I/O or Memory read/write functions
+ */
+#ifndef _ARCH_IO_H__
+#define _ARCH_IO_H__
+
+#include <vmm_types.h>
+#include <arch_barrier.h>
+#include <cpu_inline_asm.h>
+
+#define __raw_write8(a,v) (*(volatile u8 *)(a) = (v))
+#define __raw_write16(a,v) (*(volatile u16 *)(a) = (v))
+#define __raw_write32(a,v) (*(volatile u32 *)(a) = (v))
+#define __raw_write64(a,v) (*(volatile u64 *)(a) = (v))
+
+#define __raw_read8(a) (*(volatile u8 *)(a))
+#define __raw_read16(a) (*(volatile u16 *)(a))
+#define __raw_read32(a) (*(volatile u32 *)(a))
+#define __raw_read64(a) (*(volatile u64 *)(a))
+
+#define __iormb() arch_rmb()
+#define __iowmb() arch_wmb()
+
+/*
+ * Endianness primitives
+ * ------------------------
+ */
+#define arch_cpu_to_le16(v) (v)
+
+#define arch_le16_to_cpu(v) (v)
+
+#define arch_cpu_to_be16(v) rev16(v)
+
+#define arch_be16_to_cpu(v) rev16(v)
+
+#define arch_cpu_to_le32(v) (v)
+
+#define arch_le32_to_cpu(v) (v)
+
+#define arch_cpu_to_be32(v) rev32(v)
+
+#define arch_be32_to_cpu(v) rev32(v)
+
+#define arch_cpu_to_le64(v) (v)
+
+#define arch_le64_to_cpu(v) (v)
+
+#define arch_cpu_to_be64(v) rev64(v)
+
+#define arch_be64_to_cpu(v) rev64(v)
+
+#define __io(p) ((void *)p)
+
+/*
+ * IO port access primitives
+ * -------------------------
+ *
+ * The ARM doesn't have special IO access instructions; all IO is memory
+ * mapped. Note that these are defined to perform little endian accesses
+ * only. For ARM, IO port read/write operations translate to a read/write
+ * operation to memory address. All IO port read/write operations are
+ * assumed to be little-endian.
+ */
+#define arch_outb(v, p) {__iowmb(); __raw_write8(__io(p), v); }
+#define arch_outw(v, p) {__iowmb(); __raw_write16(__io(p), v); }
+#define arch_outl(v, p) {__iowmb(); __raw_write32(__io(p), v); }
+#define arch_inb(p) ({u8 v = __raw_read8(__io(p)); __iormb(); v; })
+#define arch_inw(p) ({u16 v = __raw_read16(__io(p)); __iormb(); v; })
+#define arch_inl(p) ({u32 v = __raw_read32(__io(p)); __iormb(); v; })
+
+#define arch_outb_p(v, p) arch_outb((v), (p))
+#define arch_outw_p(v, p) arch_outw((v), (p))
+#define arch_outl_p(v, p) arch_outl((v), (p))
+#define arch_inb_p(p) arch_inb((p))
+#define arch_inw_p(p) arch_inw((p))
+#define arch_inl_p(p) arch_inl((p))
+
+static inline void arch_insb(unsigned long p, void *b, int c)
+{
+ if (c) {
+ u8 *buf = b;
+ do {
+ u8 x = arch_inb(p);
+ *buf++ = x;
+ } while (--c);
+ }
+}
+
+static inline void arch_insw(unsigned long p, void *b, int c)
+{
+ if (c) {
+ u16 *buf = b;
+ do {
+ u16 x = arch_inw(p);
+ *buf++ = x;
+ } while (--c);
+ }
+}
+
+static inline void arch_insl(unsigned long p, void *b, int c)
+{
+ if (c) {
+ u32 *buf = b;
+ do {
+ u32 x = arch_inl(p);
+ *buf++ = x;
+ } while (--c);
+ }
+}
+
+static inline void arch_outsb(unsigned long p, const void *b, int c)
+{
+ if (c) {
+ const u8 *buf = b;
+ do {
+ arch_outb(*buf++, p);
+ } while (--c);
+ }
+}
+
+static inline void arch_outsw(unsigned long p, const void *b, int c)
+{
+ if (c) {
+ const u16 *buf = b;
+ do {
+ arch_outw(*buf++, p);
+ } while (--c);
+ }
+}
+
+static inline void arch_outsl(unsigned long p, const void *b, int c)
+{
+ if (c) {
+ const u32 *buf = b;
+ do {
+ arch_outl(*buf++, p);
+ } while (--c);
+ }
+}
+
+/*
+ * Memory access primitives
+ * ------------------------
+ */
+#define arch_in_8(a) ({u8 v = __raw_read8(a); __iormb(); v; })
+
+#define arch_out_8(a, v) {__iowmb(); __raw_write8(a, v); }
+
+#define arch_in_le16(a) ({u16 v = __raw_read16(a); __iormb(); v; })
+
+#define arch_out_le16(a, v) ({__raw_write16(a, v); __iowmb(); })
+
+#define arch_in_be16(a) ({u16 v = __raw_read16(a); __iormb(); rev16(v); })
+
+#define arch_out_be16(a, v) {__iowmb(); __raw_write16(a, (rev16(v))); }
+
+#define arch_in_le32(a) ({u32 v = __raw_read32(a); __iormb(); v; })
+
+#define arch_out_le32(a, v) {__iowmb(); __raw_write32(a, v); }
+
+#define arch_in_be32(a) ({u32 v = __raw_read32(a); __iormb(); rev32(v); })
+
+#define arch_out_be32(a, v) {__iowmb(); __raw_write32(a, rev32(v)); }
+
+#define arch_in_le64(a) ({u32 v = __raw_read64(a); __iormb(); v; })
+
+#define arch_out_le64(a, v) {__iowmb(); __raw_write64(a, v); }
+
+#define arch_in_be64(a) ({u32 v = __raw_read64(a); __iormb(); rev64(v); })
+
+#define arch_out_be64(a, v) {__iowmb(); __raw_write64(a, rev64(v)); }
+
+#endif
diff --git a/arch/arm/cpu/arm64/include/arch_regs.h b/arch/arm/cpu/arm64/include/arch_regs.h
new file mode 100644
index 0000000..431a98b
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/arch_regs.h
@@ -0,0 +1,152 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arch_regs.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief common header file for CPU registers
+ */
+#ifndef _ARCH_REGS_H__
+#define _ARCH_REGS_H__
+
+#include <vmm_types.h>
+#include <vmm_spinlocks.h>
+#include <cpu_defines.h>
+#include <generic_timer.h>
+
+struct arch_regs {
+ u64 gpr[CPU_GPR_COUNT]; /* X0 - X29 */
+ u64 lr;
+ u64 sp; /* Stack Pointer */
+ u64 pc; /* Program Counter */
+ u64 pstate; /* PState/SPSR */
+} __attribute((packed));
+
+typedef struct arch_regs arch_regs_t;
+
+struct arm_priv {
+ /* Internal CPU feature flags. */
+ u64 features;
+ /* Hypervisor context */
+ vmm_spinlock_t hcr_lock;
+ u64 hcr; /* Hypervisor Configuration */
+ u64 cptr; /* Coprocessor Trap Register */
+ u64 hstr; /* Hypervisor System Trap Register */
+ /* EL1 Registers */
+ u64 sp_el0;
+ u64 sp_el1;
+ u64 elr_el1;
+ u64 spsr_el1;
+ u32 spsr_abt;
+ u32 spsr_und;
+ u32 spsr_irq;
+ u32 spsr_fiq;
+ u64 cpuid;
+ u64 mpidr;
+ u64 sctlr; /* System control register. */
+ u64 actlr; /* Auxillary control register. */
+ u64 cpacr; /* Coprocessor access register. */
+ u64 ttbr0; /* MMU translation table base 0. */
+ u64 ttbr1; /* MMU translation table base 1. */
+ u64 tcr; /* MMU translation control register. */
+ u64 esr; /* Exception status register. */
+ u64 far; /* Fault address register. */
+ u64 par; /* Translation result. */
+ u64 mair; /* Memory attribute Index Register */
+ u64 vbar; /* Vector base address register */
+ u64 contextidr; /* Context ID. */
+ u64 tpidr_el0; /* User RW Thread register. */
+ u64 tpidr_el1; /* Privileged Thread register. */
+ u64 tpidrro; /* User RO Thread register. */
+ /* ThumbEE registers */
+ u64 teecr;
+ u32 teehbr;
+ /* VFP & SMID registers */
+ u32 fpexc;
+ u32 fpcr;
+ u32 fpsr;
+ u64 fpregs[128]; /* 32x32 floating point registers. */
+ /* 32bit only registers */
+ u32 cp15_c0_c1[8];
+ u32 cp15_c0_c2[8];
+ u32 dacr; /* MMU domain access control register */
+ u32 ifsr; /* Fault status registers. */
+ /* Last host CPU on which this VCPU ran */
+ u32 last_hcpu;
+ /* Generic timer context */
+ struct generic_timer_context gentimer_context;
+ /* VGIC context */
+ bool vgic_avail;
+ void (*vgic_save)(void *vcpu_ptr);
+ void (*vgic_restore)(void *vcpu_ptr);
+ void *vgic_priv;
+} __attribute((packed));
+
+typedef struct arm_priv arm_priv_t;
+
+struct arm_guest_priv {
+ /* Stage2 table */
+ struct cpu_ttbl *ttbl;
+};
+
+typedef struct arm_guest_priv arm_guest_priv_t;
+
+#define arm_regs(vcpu) (&((vcpu)->regs))
+#define arm_priv(vcpu) ((arm_priv_t *)((vcpu)->arch_priv))
+#define arm_guest_priv(guest) ((arm_guest_priv_t *)((guest)->arch_priv))
+
+#define arm_cpuid(vcpu) (arm_priv(vcpu)->cpuid)
+#define arm_set_feature(vcpu, feat) (arm_priv(vcpu)->features |= (0x1ULL << (feat)))
+#define arm_feature(vcpu, feat) (arm_priv(vcpu)->features & (0x1ULL << (feat)))
+
+/**
+ * Instruction emulation support macros
+ */
+#define arm_cpsr(regs) ((u32)((regs)->pstate & 0xffffffff))
+#define arm_pc(regs) ((regs)->pc)
+
+/**
+ * Generic timers support macro
+ */
+#define arm_gentimer_context(vcpu) (&(arm_priv(vcpu)->gentimer_context))
+
+/**
+ * VGIC support macros
+ */
+#define arm_vgic_setup(vcpu, __save_func, __restore_func, __priv) \
+ do { \
+ arm_priv(vcpu)->vgic_avail = TRUE; \
+ arm_priv(vcpu)->vgic_save = __save_func; \
+ arm_priv(vcpu)->vgic_restore = __restore_func; \
+ arm_priv(vcpu)->vgic_priv = __priv; \
+ } while (0)
+#define arm_vgic_cleanup(vcpu) do { \
+ arm_priv(vcpu)->vgic_avail = FALSE; \
+ arm_priv(vcpu)->vgic_save = NULL; \
+ arm_priv(vcpu)->vgic_restore = NULL; \
+ arm_priv(vcpu)->vgic_priv = NULL; \
+ } while (0)
+#define arm_vgic_avail(vcpu) (arm_priv(vcpu)->vgic_avail)
+#define arm_vgic_save(vcpu) if (arm_vgic_avail(vcpu)) { \
+ arm_priv(vcpu)->vgic_save(vcpu); \
+ }
+#define arm_vgic_restore(vcpu) if (arm_vgic_avail(vcpu)) { \
+ arm_priv(vcpu)->vgic_restore(vcpu); \
+ }
+#define arm_vgic_priv(vcpu) (arm_priv(vcpu)->vgic_priv)
+
+#endif
diff --git a/arch/arm/cpu/arm64/include/arch_sections.h b/arch/arm/cpu/arm64/include/arch_sections.h
new file mode 100644
index 0000000..80367ba
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/arch_sections.h
@@ -0,0 +1,69 @@
+/**
+ * Copyright (c) 2012 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arch_sections.h
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief interface for accessing VMM sections
+ */
+#ifndef _ARCH_SECTIONS_H__
+#define _ARCH_SECTIONS_H__
+
+#include <vmm_types.h>
+
+/** Overall code */
+virtual_addr_t arch_code_vaddr_start(void);
+physical_addr_t arch_code_paddr_start(void);
+virtual_size_t arch_code_size(void);
+
+/** Module table */
+extern u8 _modtbl_start;
+extern u8 _modtbl_end;
+static inline virtual_addr_t arch_modtbl_vaddr(void)
+{
+ return (virtual_addr_t) &_modtbl_start;
+}
+static inline virtual_size_t arch_modtbl_size(void)
+{
+ return (virtual_size_t) (&_modtbl_end - &_modtbl_start);
+}
+
+/** PerCPU section */
+extern u8 _percpu_start;
+extern u8 _percpu_end;
+static inline virtual_addr_t arch_percpu_vaddr(void)
+{
+ return (virtual_addr_t) &_percpu_start;
+}
+static inline virtual_size_t arch_percpu_size(void)
+{
+ return (virtual_size_t) (&_percpu_end - &_percpu_start);
+}
+
+/** Init section */
+extern u8 _init_start;
+extern u8 _init_end;
+static inline virtual_addr_t arch_init_vaddr(void)
+{
+ return (virtual_addr_t) &_init_start;
+}
+static inline virtual_size_t arch_init_size(void)
+{
+ return (virtual_size_t) (&_init_end - &_init_start);
+}
+
+#endif
diff --git a/arch/arm/cpu/arm64/include/arch_types.h b/arch/arm/cpu/arm64/include/arch_types.h
new file mode 100644
index 0000000..bfb3bcb
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/arch_types.h
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arch_types.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief common header file for typedefs
+ */
+#ifndef _ARCH_TYPES_H__
+#define _ARCH_TYPES_H__
+
+/** cpu specific types */
+typedef unsigned int irq_flags_t;
+typedef unsigned long virtual_addr_t;
+typedef unsigned long virtual_size_t;
+typedef unsigned long physical_addr_t;
+typedef unsigned long physical_size_t;
+
+typedef struct {
+ volatile long counter;
+} atomic_t;
+
+typedef struct {
+ volatile long long counter;
+} atomic64_t;
+
+typedef struct {
+ volatile long lock;
+} arch_spinlock_t;
+
+#define __ARCH_SPIN_UNLOCKED 0xffffffffUL
+
+/* FIXME: Need memory barrier for this. */
+#define ARCH_SPIN_LOCK_INIT(_lptr) \
+ (_lptr)->lock = __ARCH_SPIN_UNLOCKED
+
+#define ARCH_SPIN_LOCK_INITIALIZER \
+ { .lock = __ARCH_SPIN_UNLOCKED, }
+typedef struct {
+ volatile long lock;
+} arch_rwlock_t;
+
+#define __ARCH_RW_LOCKED 0x80000000UL
+#define __ARCH_RW_UNLOCKED 0
+
+/* FIXME: Need memory barrier for this. */
+#define ARCH_RW_LOCK_INIT(_lptr) \
+ (_lptr)->lock = __ARCH_RW_UNLOCKED
+
+#define ARCH_RW_LOCK_INITIALIZER \
+ { .lock = __ARCH_RW_UNLOCKED, }
+
+#define ARCH_BITS_PER_LONG 64
+
+#endif /* _ARCH_TYPES_H__ */
+
+
diff --git a/arch/arm/cpu/arm64/include/cpu_cache.h b/arch/arm/cpu/arm64/include/cpu_cache.h
new file mode 100644
index 0000000..d296f97
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/cpu_cache.h
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_cache.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief cache interface of a ARM processor
+ */
+#ifndef __CPU_CACHE_H__
+#define __CPU_CACHE_H__
+
+#include <vmm_types.h>
+
+/** Invalidate all instruction caches */
+void invalidate_icache(void);
+
+/** Invalidate instruction cache line by MVA to PoU */
+void invalidate_icache_mva(virtual_addr_t mva);
+
+/** Clean data cache */
+void clean_dcache(void);
+
+/** Clean data cache line by MVA */
+void clean_dcache_mva(virtual_addr_t mva);
+
+/** Clean data cache line by MVA range */
+void clean_dcache_mva_range(virtual_addr_t start, virtual_addr_t end);
+
+/** Clean data cache line by set/way */
+void clean_dcache_line(u32 line);
+
+/** Clean unified (instruction or data) cache */
+void clean_idcache(void);
+
+/** Clean unified cache line by MVA */
+void clean_idcache_mva(virtual_addr_t mva);
+
+/** Clean unified cache line by set/way */
+void clean_idcache_line(u32 line);
+
+/** Clean and invalidate data cache */
+void clean_invalidate_dcache(void);
+
+/** Clean and invalidate data cache line by MVA */
+void clean_invalidate_dcache_mva(virtual_addr_t mva);
+
+/** Clean and invalidate data cache lines by MVA range */
+void clean_invalidate_dcache_mva_range(virtual_addr_t start, virtual_addr_t end);
+
+/** Clean and invalidate data cache line by set/way */
+void clean_invalidate_dcache_line(u32 line);
+
+/** Clean and invalidate unified (instruction or data) cache */
+void clean_invalidate_idcache(void);
+
+/** Clean and invalidate unified cache line by MVA */
+void clean_invalidate_idcache_mva(virtual_addr_t mva);
+
+/** Clean and invalidate unified cache line by set/way */
+void clean_invalidate_idcache_line(u32 line);
+
+#endif /* __CPU_CACHE_H__ */
diff --git a/arch/arm/cpu/arm64/include/cpu_defines.h b/arch/arm/cpu/arm64/include/cpu_defines.h
new file mode 100644
index 0000000..6ded7ec
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/cpu_defines.h
@@ -0,0 +1,706 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_defines.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief common macros & defines for shared by all C & Assembly code
+ */
+#ifndef __CPU_DEFINES_H__
+#define __CPU_DEFINES_H__
+
+/* Maximum allowed VTLB entries */
+#define CPU_VCPU_VTLB_LINE_MASK 0x00000000
+#define CPU_VCPU_VTLB_LINE_SHIFT 0
+#define CPU_VCPU_VTLB_LINE_COUNT 1
+#define CPU_VCPU_VTLB_LINE_ENTRY_COUNT 128
+#define CPU_VCPU_VTLB_ENTRY_COUNT 128
+
+/* Coprocessor related macros & defines */
+#define CPU_COPROC_COUNT 16
+
+/* GPR related macros & defines */
+#define CPU_GPR_COUNT 30
+
+/* Interrupt or Exception related macros & defines */
+#define EXC_HYP_SYNC_SP0 0
+#define EXC_HYP_IRQ_SP0 1
+#define EXC_HYP_FIQ_SP0 2
+#define EXC_HYP_SERROR_SP0 3
+#define EXC_HYP_SYNC_SPx 4
+#define EXC_HYP_IRQ_SPx 5
+#define EXC_HYP_FIQ_SPx 6
+#define EXC_HYP_SERROR_SPx 7
+#define EXC_GUEST_SYNC_A64 8
+#define EXC_GUEST_IRQ_A64 9
+#define EXC_GUEST_FIQ_A64 10
+#define EXC_GUEST_SERROR_A64 11
+#define EXC_GUEST_SYNC_A32 12
+#define EXC_GUEST_IRQ_A32 13
+#define EXC_GUEST_FIQ_A32 14
+#define EXC_GUEST_SERROR_A32 15
+
+/** Placeholder interrupt/exceptions for arm_emulate */
+#define CPU_IRQ_LOWVEC_BASE 0x00000000
+#define CPU_IRQ_HIGHVEC_BASE 0xFFFF0000
+#define CPU_RESET_IRQ 0
+#define CPU_UNDEF_INST_IRQ 1
+#define CPU_SOFT_IRQ 2
+#define CPU_PREFETCH_ABORT_IRQ 3
+#define CPU_DATA_ABORT_IRQ 4
+#define CPU_HYP_TRAP_IRQ 5
+#define CPU_EXTERNAL_IRQ 6
+#define CPU_EXTERNAL_FIQ 7
+#define CPU_IRQ_NR 8
+
+/* PSR related macros & defines */
+#define PSR_MODE_MASK 0x0000001f
+
+#define PSR_EL_MASK 0x0000000C
+#define PSR_EL_0 0x00000000
+#define PSR_EL_1 0x00000004
+#define PSR_EL_2 0x00000008
+#define PSR_EL_3 0x0000000C
+#define PSR_MODE64_MASK 0x0000000f
+#define PSR_MODE64_EL0t 0x00000000
+#define PSR_MODE64_EL1t 0x00000004
+#define PSR_MODE64_EL1h 0x00000005
+#define PSR_MODE64_EL2t 0x00000008
+#define PSR_MODE64_EL2h 0x00000009
+#define PSR_MODE64_EL3t 0x0000000c
+#define PSR_MODE64_EL3h 0x0000000d
+
+#define PSR_MODE32 0x00000010
+#define PSR_MODE32_MASK 0x0000001f
+#define PSR_MODE32_USER 0x00000010
+#define PSR_MODE32_FIQ 0x00000011
+#define PSR_MODE32_IRQ 0x00000012
+#define PSR_MODE32_SUPERVISOR 0x00000013
+#define PSR_MODE32_MONITOR 0x00000016
+#define PSR_MODE32_ABORT 0x00000017
+#define PSR_MODE32_HYPERVISOR 0x0000001a
+#define PSR_MODE32_UNDEFINED 0x0000001b
+#define PSR_MODE32_SYSTEM 0x0000001f
+#define PSR_FIQ_DISABLED (1 << 6)
+#define PSR_IRQ_DISABLED (1 << 7)
+#define PSR_ASYNC_ABORT_DISABLED (1 << 8)
+#define PSR_MODE64_DEBUG_DISABLED (1 << 9)
+#define PSR_MODE32_BE_ENABLED (1 << 9)
+#define PSR_IL_MASK 0x00100000
+#define PSR_IL_SHIFT 20
+#define PSR_SS_MASK 0x00200000
+#define PSR_SS_SHIFT 21
+#define PSR_OVERFLOW_MASK (1 << 28)
+#define PSR_OVERFLOW_SHIFT 28
+#define PSR_CARRY_MASK (1 << 29)
+#define PSR_CARRY_SHIFT 29
+#define PSR_ZERO_MASK (1 << 30)
+#define PSR_ZERO_SHIFT 30
+#define PSR_NEGATIVE_MASK (1 << 31)
+#define PSR_NEGATIVE_SHIFT 31
+
+/* Fields of AArch32-PSR which will be RES0 in Aarch64 */
+/* Section 3.8.8 Unused fields of SPSR - Exception Model */
+#define PSR_THUMB_ENABLED (1 << 5)
+#define PSR_IT2_MASK 0x0000FC00
+#define PSR_IT2_SHIFT 10
+#define PSR_GE_MASK 0x000F0000
+#define PSR_GE_SHIFT 16
+#define PSR_JAZZLE_ENABLED (1 << 24)
+#define PSR_IT1_MASK 0x06000000
+#define PSR_IT1_SHIFT 25
+#define PSR_CUMMULATE_MASK (1 << 27)
+#define PSR_CUMMULATE_SHIFT 27
+
+#define PSR_NZCV_MASK (PSR_NEGATIVE_MASK |\
+ PSR_ZERO_MASK |\
+ PSR_CARRY_MASK |\
+ PSR_OVERFLOW_MASK)
+#define PSR_IT_MASK (PSR_IT2_MASK |\
+ PSR_IT1_MASK)
+#define PSR_USERBITS_MASK (PSR_NZCV_MASK |\
+ PSR_CUMMULATE_MASK |\
+ PSR_GE_MASK |\
+ PSR_IT_MASK |\
+ PSR_THUMB_ENABLED)
+#define PSR_PRIVBITS_MASK (~PSR_USERBITS_MASK)
+#define PSR_ALLBITS_MASK 0xFFFFFFFF
+
+#define CPSR_MODE_MASK PSR_MODE32_MASK
+#define CPSR_MODE_USER PSR_MODE32_USER
+#define CPSR_MODE_FIQ PSR_MODE32_FIQ
+#define CPSR_MODE_IRQ PSR_MODE32_IRQ
+#define CPSR_MODE_SUPERVISOR PSR_MODE32_SUPERVISOR
+#define CPSR_MODE_MONITOR PSR_MODE32_MONITOR
+#define CPSR_MODE_ABORT PSR_MODE32_ABORT
+#define CPSR_MODE_HYPERVISOR PSR_MODE32_HYPERVISOR
+#define CPSR_MODE_UNDEFINED PSR_MODE32_UNDEFINED
+#define CPSR_MODE_SYSTEM PSR_MODE32_SYSTEM
+#define CPSR_THUMB_ENABLED PSR_THUMB_ENABLED
+#define CPSR_FIQ_DISABLED PSR_FIQ_DISABLED
+#define CPSR_IRQ_DISABLED PSR_IRQ_DISABLED
+#define CPSR_ASYNC_ABORT_DISABLED PSR_ASYNC_ABORT_DISABLED
+#define CPSR_BE_ENABLED PSR_MODE32_BE_ENABLED
+#define CPSR_IT2_MASK PSR_IT2_MASK
+#define CPSR_IT2_SHIFT PSR_IT2_SHIFT
+#define CPSR_GE_MASK PSR_GE_MASK
+#define CPSR_GE_SHIFT PSR_GE_SHIFT
+#define CPSR_JAZZLE_ENABLED PSR_JAZZLE_ENABLED
+#define CPSR_IT1_MASK PSR_IT1_MASK
+#define CPSR_IT1_SHIFT PSR_IT1_SHIFT
+#define CPSR_CUMMULATE_MASK PSR_CUMMULATE_MASK
+#define CPSR_CUMMULATE_SHIFT PSR_CUMMULATE_SHIFT
+#define CPSR_OVERFLOW_MASK PSR_OVERFLOW_MASK
+#define CPSR_OVERFLOW_SHIFT PSR_OVERFLOW_SHIFT
+#define CPSR_CARRY_MASK PSR_CARRY_MASK
+#define CPSR_CARRY_SHIFT PSR_CARRY_SHIFT
+#define CPSR_ZERO_MASK PSR_ZERO_MASK
+#define CPSR_ZERO_SHIFT PSR_ZERO_SHIFT
+#define CPSR_NEGATIVE_MASK PSR_NEGATIVE_MASK
+#define CPSR_NEGATIVE_SHIFT PSR_NEGATIVE_SHIFT
+
+#define CPSR_NZCV_MASK PSR_NZCV_MASK
+#define CPSR_IT_MASK PSR_IT_MASK
+#define CPSR_USERBITS_MASK PSR_USERBITS_MASK
+#define CPSR_PRIVBITS_MASK PSR_PRIVBITS_MASK
+#define CPSR_ALLBITS_MASK PSR_ALLBITS_MASK
+
+/* SCTLR related macros & defines */
+#define SCTLR_TE_MASK 0x40000000
+#define SCTLR_AFE_MASK 0x20000000
+#define SCTLR_TRE_MASK 0x10000000
+#define SCTLR_NFI_MASK 0x08000000
+#define SCTLR_EE_MASK 0x02000000
+#define SCTLR_VE_MASK 0x01000000
+#define SCTLR_U_MASK 0x00400000
+#define SCTLR_FI_MASK 0x00200000
+#define SCTLR_HA_MASK 0x00020000
+#define SCTLR_RR_MASK 0x00004000
+#define SCTLR_V_MASK 0x00002000
+#define SCTLR_I_MASK 0x00001000
+#define SCTLR_Z_MASK 0x00000800
+#define SCTLR_SW_MASK 0x00000400
+#define SCTLR_B_MASK 0x00000080
+#define SCTLR_C_MASK 0x00000004
+#define SCTLR_A_MASK 0x00000002
+#define SCTLR_M_MASK 0x00000001
+
+/* CTR related macros & defines */
+#define CTR_FORMAT_MASK 0xE0000000
+#define CTR_FORMAT_SHIFT 29
+#define CTR_FORMAT_V6 0x0
+#define CTR_FORMAT_V7 0x4
+#define CTR_CWG_MASK 0x0F000000
+#define CTR_CWG_SHIFT 24
+#define CTR_ERG_MASK 0x00F00000
+#define CTR_ERG_SHIFT 20
+#define CTR_DMINLINE_MASK 0x000F0000
+#define CTR_DMINLINE_SHIFT 20
+#define CTR_L1IP_MASK 0x0000C000
+#define CTR_L1IP_SHIFT 14
+#define CTR_IMINLINE_MASK 0x0000000F
+#define CTR_IMINLINE_SHIFT 0
+#define CTR_V6_CTYPE_MASK 0x1E000000
+#define CTR_V6_CTYPE_SHIFT 25
+#define CTR_V6_S_MASK 0x01000000
+#define CTR_V6_S_SHIFT 24
+#define CTR_V6_DSIZE_MASK 0x00FFF000
+#define CTR_V6_DSIZE_SHIFT 12
+#define CTR_V6_ISIZE_MASK 0x00000FFF
+#define CTR_V6_ISIZE_SHIFT 0
+
+/* CLIDR related macros & defines */
+#define CLIDR_LOUU_MASK 0x38000000
+#define CLIDR_LOUU_SHIFT 27
+#define CLIDR_LOC_MASK 0x07000000
+#define CLIDR_LOC_SHIFT 24
+#define CLIDR_LOUIS_MASK 0x00E00000
+#define CLIDR_LOUIS_SHIFT 21
+#define CLIDR_CTYPE7_MASK 0x001C0000
+#define CLIDR_CTYPE7_SHIFT 18
+#define CLIDR_CTYPE6_MASK 0x00038000
+#define CLIDR_CTYPE6_SHIFT 15
+#define CLIDR_CTYPE5_MASK 0x00007000
+#define CLIDR_CTYPE5_SHIFT 12
+#define CLIDR_CTYPE4_MASK 0x00000E00
+#define CLIDR_CTYPE4_SHIFT 9
+#define CLIDR_CTYPE3_MASK 0x000001C0
+#define CLIDR_CTYPE3_SHIFT 6
+#define CLIDR_CTYPE2_MASK 0x00000038
+#define CLIDR_CTYPE2_SHIFT 3
+#define CLIDR_CTYPE1_MASK 0x00000007
+#define CLIDR_CTYPE1_SHIFT 0
+#define CLIDR_CTYPE_NOCACHE 0x0
+#define CLIDR_CTYPE_ICACHE 0x1
+#define CLIDR_CTYPE_DCACHE 0x2
+#define CLIDR_CTYPE_SPLITCACHE 0x3
+#define CLIDR_CTYPE_UNICACHE 0x4
+#define CLIDR_CTYPE_RESERVED1 0x5
+#define CLIDR_CTYPE_RESERVED2 0x6
+#define CLIDR_CTYPE_RESERVED3 0x7
+
+/* CSSELR related macros & defines */
+#define CSSELR_LEVEL_MASK 0x0000000E
+#define CSSELR_LEVEL_SHIFT 1
+#define CSSELR_IND_MASK 0x00000001
+#define CSSELR_IND_SHIFT 0
+
+/* CSSIDR related macros & defines */
+#define CCSIDR_WT_MASK 0x80000000
+#define CCSIDR_WT_SHIFT 31
+#define CCSIDR_WB_MASK 0x40000000
+#define CCSIDR_WB_SHIFT 30
+#define CCSIDR_RA_MASK 0x20000000
+#define CCSIDR_RA_SHIFT 29
+#define CCSIDR_WA_MASK 0x10000000
+#define CCSIDR_WA_SHIFT 28
+#define CCSIDR_NUMSETS_MASK 0x0FFFE000
+#define CCSIDR_NUMSETS_SHIFT 13
+#define CCSIDR_ASSOC_MASK 0x00001FF8
+#define CCSIDR_ASSOC_SHIFT 3
+#define CCSIDR_LINESZ_MASK 0x00000007
+#define CCSIDR_LINESZ_SHIFT 0
+
+/* HCR_EL2 */
+#define HCR_INITVAL 0x000000000
+#define HCR_ID_MASK 0x200000000
+#define HCR_ID_SHIFT 33
+#define HCR_CD_MASK 0x100000000
+#define HCR_CD_SHIFT 32
+#define HCR_RW_MASK 0x080000000
+#define HCR_RW_SHIFT 31
+#define HCR_TRVM_MASK 0x040000000
+#define HCR_TRVM_SHIFT 30
+#define HCR_HCD_MASK 0x020000000
+#define HCR_HCD_SHIFT 29
+#define HCR_TDZ_MASK 0x010000000
+#define HCR_TDZ_SHIFT 28
+#define HCR_TGE_MASK 0x008000000
+#define HCR_TGE_SHIFT 27
+#define HCR_TVM_MASK 0x004000000
+#define HCR_TVM_SHIFT 26
+#define HCR_TTLB_MASK 0x002000000
+#define HCR_TTLB_SHIFT 25
+#define HCR_TPU_MASK 0x001000000
+#define HCR_TPU_SHIFT 24
+#define HCR_TPC_MASK 0x000800000
+#define HCR_TPC_SHIFT 23
+#define HCR_TSW_MASK 0x000400000
+#define HCR_TSW_SHIFT 22
+#define HCR_TACR_MASK 0x000200000
+#define HCR_TACR_SHIFT 21
+#define HCR_TIDCP_MASK 0x000100000
+#define HCR_TIDCP_SHIFT 20
+#define HCR_TSC_MASK 0x000080000
+#define HCR_TSC_SHIFT 19
+#define HCR_TID3_MASK 0x000040000
+#define HCR_TID3_SHIFT 18
+#define HCR_TID2_MASK 0x000020000
+#define HCR_TID2_SHIFT 17
+#define HCR_TID1_MASK 0x000010000
+#define HCR_TID1_SHIFT 16
+#define HCR_TID0_MASK 0x000008000
+#define HCR_TID0_SHIFT 15
+#define HCR_TWE_MASK 0x000004000
+#define HCR_TWE_SHIFT 14
+#define HCR_TWI_MASK 0x000002000
+#define HCR_TWI_SHIFT 13
+#define HCR_DC_MASK 0x000001000
+#define HCR_DC_SHIFT 12
+#define HCR_BSU_MASK 0x000000C00
+#define HCR_BSU_SHIFT 10
+#define HCR_FB_MASK 0x000000200
+#define HCR_FB_SHIFT 9
+#define HCR_VSE_MASK 0x000000100
+#define HCR_VSE_SHIFT 8
+#define HCR_VI_MASK 0x000000080
+#define HCR_VI_SHIFT 7
+#define HCR_VF_MASK 0x000000040
+#define HCR_VF_SHIFT 6
+#define HCR_AMO_MASK 0x000000020
+#define HCR_AMO_SHIFT 5
+#define HCR_IMO_MASK 0x000000010
+#define HCR_IMO_SHIFT 4
+#define HCR_FMO_MASK 0x000000008
+#define HCR_FMO_SHIFT 3
+#define HCR_PTW_MASK 0x000000004
+#define HCR_PTW_SHIFT 2
+#define HCR_SWIO_MASK 0x000000002
+#define HCR_SWIO_SHIFT 1
+#define HCR_VM_MASK 0x000000001
+#define HCR_VM_SHIFT 0
+
+/* CPTR_EL2 */
+#define CPTR_INITVAL 0x00000000LU
+#define CPTR_TCPAC_MASK 0x80000000LU
+#define CPTR_TCPAC_SHIFT 31
+#define CPTR_TTA_MASK 0x00100000LU
+#define CPTR_TTA_SHIFT 20
+#define CPTR_TFP_MASK 0x00000400LU
+#define CPTR_TFP_SHIFT 10
+#define CPTR_RES1_MASK 0x000033FFLU
+
+/* HSTR_EL2 */
+#define HSTR_INITVAL 0x00000000LU
+#define HSTR_TTEE_MASK 0x00010000LU
+#define HSTR_TTEE_SHIFT 16
+#define HSTR_T_MASK 0x0000BFEFLU
+#define HSTR_T_SHIFT 0
+#define HSTR_T15_MASK 0x00008000LU
+#define HSTR_T15_SHIFT 15
+#define HSTR_T13_MASK 0x00002000LU
+#define HSTR_T13_SHIFT 13
+#define HSTR_T12_MASK 0x00001000LU
+#define HSTR_T12_SHIFT 12
+#define HSTR_T11_MASK 0x00000800LU
+#define HSTR_T11_SHIFT 11
+#define HSTR_T10_MASK 0x00000400LU
+#define HSTR_T10_SHIFT 10
+#define HSTR_T9_MASK 0x00000200LU
+#define HSTR_T9_SHIFT 9
+#define HSTR_T8_MASK 0x00000100LU
+#define HSTR_T8_SHIFT 8
+#define HSTR_T7_MASK 0x00000080LU
+#define HSTR_T7_SHIFT 7
+#define HSTR_T6_MASK 0x00000040LU
+#define HSTR_T6_SHIFT 6
+#define HSTR_T5_MASK 0x00000020LU
+#define HSTR_T5_SHIFT 5
+#define HSTR_T3_MASK 0x00000008LU
+#define HSTR_T3_SHIFT 3
+#define HSTR_T2_MASK 0x00000004LU
+#define HSTR_T2_SHIFT 2
+#define HSTR_T1_MASK 0x00000002LU
+#define HSTR_T1_SHIFT 1
+#define HSTR_T0_MASK 0x00000001LU
+#define HSTR_T0_SHIFT 0
+
+/* HPFAR_EL2 */
+#define HPFAR_INITVAL 0x00000000UL
+#define HPFAR_FIPA_MASK 0xFFFFFFFFFFFFFFF0UL
+#define HPFAR_FIPA_SHIFT 4
+#define HPFAR_FIPA_PAGE_MASK 0x00000FFFUL
+#define HPFAR_FIPA_PAGE_SHIFT 12
+
+/* ESR_EL2 */
+#define ESR_INITVAL 0x00000000LU
+#define ESR_EC_MASK 0xFC000000LU
+#define ESR_EC_SHIFT 26
+#define ESR_IL_MASK 0x02000000LU
+#define ESR_IL_SHIFT 25
+#define ESR_ISS_MASK 0x01FFFFFFLU
+#define ESR_ISS_SHIFT 0
+
+/* Exception Class (EC) Values */
+#define EC_UNKNOWN 0x00
+#define EC_TRAP_WFI_WFE 0x01
+#define EC_TRAP_MCR_MRC_CP15_A32 0x03
+#define EC_TRAP_MCRR_MRRC_CP15_A32 0x04
+#define EC_TRAP_MCR_MRC_CP14_A32 0x05
+#define EC_TRAP_LDC_STC_CP14_A32 0x06
+#define EC_SIMD_FPU 0x07
+#define EC_TRAP_MRC_VMRS_CP10_A32 0x08
+#define EC_TRAP_MCRR_MRRC_CP14_A32 0x0C
+#define EC_TRAP_IL 0x0E
+#define EC_TRAP_SVC_A32 0x11
+#define EC_TRAP_HVC_A32 0x12
+#define EC_TRAP_SMC_A32 0x13
+#define EC_TRAP_SVC_A64 0x15
+#define EC_TRAP_HVC_A64 0x16
+#define EC_TRAP_SMC_A64 0x17
+#define EC_TRAP_MSR_MRS_SYSTEM 0x18
+#define EC_TRAP_LWREL_INST_ABORT 0x20
+#define EC_CUREL_INST_ABORT 0x21
+#define EC_PC_UNALIGNED 0x22
+#define EC_TRAP_LWREL_DATA_ABORT 0x24
+#define EC_CUREL_DATA_ABORT 0x25
+#define EC_SP_UNALIGNED 0x26
+#define EC_FPEXC_A32 0x28
+#define EC_FPEXC_A64 0x2C
+#define EC_SERROR 0x2F
+#define EC_DBG_EXC_MASK 0x30
+
+/* Condition Field ISS Encodings */
+#define ISS_CV_MASK 0x01000000
+#define ISS_CV_SHIFT 24
+#define ISS_COND_MASK 0x00F00000
+#define ISS_COND_SHIFT 20
+
+/* MRS/MSR Trap ISS Encodings */
+#define ISS_SYSREG_ENC(op0, op2, op1, crn, crm) (((op0) << 20) | \
+ ((op2) << 17) | ((op1) << 14) | \
+ ((crn) << 10) | ((crm) << 1))
+
+#define ISS_SYSREG_MASK 0xfffffc1e
+#define ISS_RT_MASK 0x000003e0
+#define ISS_RT_SHIFT 5
+#define ISS_DIR_MASK 0x00000001
+#define ISS_SYSREG_READ 0x00000001
+
+#define ISS_CPACR_EL1 ISS_SYSREG_ENC(3,2,0,1,0)
+#define ISS_CNTFRQ_EL0 ISS_SYSREG_ENC(3,0,3,14,0)
+#define ISS_CNTPCT_EL0 ISS_SYSREG_ENC(3,1,3,14,0)
+#define ISS_CNTVCT_EL0 ISS_SYSREG_ENC(3,2,3,14,0)
+#define ISS_CNTKCTL_EL1 ISS_SYSREG_ENC(3,0,0,14,1)
+#define ISS_CNTP_TVAL_EL0 ISS_SYSREG_ENC(3,0,3,14,2)
+#define ISS_CNTP_CTL_EL0 ISS_SYSREG_ENC(3,1,3,14,2)
+#define ISS_CNTP_CVAL_EL0 ISS_SYSREG_ENC(3,2,3,14,2)
+#define ISS_CNTV_TVAL_EL0 ISS_SYSREG_ENC(3,0,3,14,3)
+#define ISS_CNTV_CTL_EL0 ISS_SYSREG_ENC(3,1,3,14,3)
+#define ISS_CNTV_CVAL_EL0 ISS_SYSREG_ENC(3,2,3,14,3)
+#define ISS_ACTLR_EL1 ISS_SYSREG_ENC(3,1,0,1,0)
+#define ISS_ACTLR_EL2 ISS_SYSREG_ENC(3,1,0,1,4)
+#define ISS_ACTLR_EL3 ISS_SYSREG_ENC(3,1,0,1,6)
+
+/* WFI/WFE ISS Encodings */
+#define ISS_WFI_WFE_TRAPPED_MASK 0x00000001
+#define ISS_WFI_WFE_TRAPPED_SHIFT 0
+
+/* MCR/MRC ISS Encodings */
+#define ISS_MCR_MRC_OPC2_MASK 0x000E0000
+#define ISS_MCR_MRC_OPC2_SHIFT 17
+#define ISS_MCR_MRC_OPC1_MASK 0x0001C000
+#define ISS_MCR_MRC_OPC1_SHIFT 14
+#define ISS_MCR_MRC_CRN_MASK 0x00003C00
+#define ISS_MCR_MRC_CRN_SHIFT 10
+#define ISS_MCR_MRC_RT_MASK 0x000001E0
+#define ISS_MCR_MRC_RT_SHIFT 5
+#define ISS_MCR_MRC_CRM_MASK 0x0000001E
+#define ISS_MCR_MRC_CRM_SHIFT 1
+#define ISS_MCR_MRC_DIR_MASK 0x00000001
+#define ISS_MCR_MRC_DIR_SHIFT 0
+
+/* Instruction/Data Abort ISS Encodings */
+#define ISS_ABORT_ISV_MASK 0x01000000
+#define ISS_ABORT_ISV_SHIFT 24
+#define ISS_ABORT_SAS_MASK 0x00C00000
+#define ISS_ABORT_SAS_SHIFT 22
+#define ISS_ABORT_SSE_MASK 0x00200000
+#define ISS_ABORT_SSE_SHIFT 21
+#define ISS_ABORT_SRT_MASK 0x001F0000
+#define ISS_ABORT_SRT_SHIFT 16
+#define ISS_ABORT_SF_MASK 0x00008000
+#define ISS_ABORT_SF_SHIFT 15
+#define ISS_ABORT_AR_MASK 0x00004000
+#define ISS_ABORT_AR_SHIFT 14
+#define ISS_ABORT_EA_MASK 0x00000200
+#define ISS_ABORT_EA_SHIFT 9
+#define ISS_ABORT_CM_MASK 0x00000100
+#define ISS_ABORT_CM_SHIFT 8
+#define ISS_ABORT_S1PTW_MASK 0x00000080
+#define ISS_ABORT_S1PTW_SHIFT 7
+#define ISS_ABORT_WNR_MASK 0x00000040
+#define ISS_ABORT_WNR_SHIFT 6
+#define ISS_ABORT_FSC_MASK 0x0000003F
+#define ISS_ABORT_FSC_SHIFT 0
+
+/* Fault Status (IFSC/DFSC) Encodings */
+#define FSC_TRANS_FAULT_LEVEL0 0x04
+#define FSC_TRANS_FAULT_LEVEL1 0x05
+#define FSC_TRANS_FAULT_LEVEL2 0x06
+#define FSC_TRANS_FAULT_LEVEL3 0x07
+#define FSC_ACCESS_FAULT_LEVEL0 0x08
+#define FSC_ACCESS_FAULT_LEVEL1 0x09
+#define FSC_ACCESS_FAULT_LEVEL2 0x0A
+#define FSC_ACCESS_FAULT_LEVEL3 0x0B
+#define FSC_PERM_FAULT_LEVEL0 0x0C
+#define FSC_PERM_FAULT_LEVEL1 0x0D
+#define FSC_PERM_FAULT_LEVEL2 0x0E
+#define FSC_PERM_FAULT_LEVEL3 0x0F
+#define FSC_SYNC_EXTERNAL_ABORT 0x10
+#define FSC_ASYNC_EXTERNAL_ABORT 0x11
+#define FSC_SYNC_TWALK_EXTERNAL_ABORT_LEVEL0 0x14
+#define FSC_SYNC_TWALK_EXTERNAL_ABORT_LEVEL1 0x15
+#define FSC_SYNC_TWALK_EXTERNAL_ABORT_LEVEL2 0x16
+#define FSC_SYNC_TWALK_EXTERNAL_ABORT_LEVEL3 0x17
+#define FSC_SYNC_PARITY_ERROR 0x18
+#define FSC_ASYNC_PARITY_ERROR 0x19
+#define FSC_SYNC_TWALK_PARITY_ERROR_LEVEL0 0x1C
+#define FSC_SYNC_TWALK_PARITY_ERROR_LEVEL1 0x1D
+#define FSC_SYNC_TWALK_PARITY_ERROR_LEVEL2 0x1E
+#define FSC_SYNC_TWALK_PARITY_ERROR_LEVEL3 0x1F
+#define FSC_ALIGN_FAULT 0x21
+#define FSC_DEBUG_EVENT 0x22
+#define FSC_TLB_CONFLICT_ABORT 0x30
+#define FSC_DOMAIN_FAULT_LEVEL0 0x3C
+#define FSC_DOMAIN_FAULT_LEVEL1 0x3D
+#define FSC_DOMAIN_FAULT_LEVEL2 0x3E
+#define FSC_DOMAIN_FAULT_LEVEL3 0x3F
+
+/* HTTBR */
+#define HTTBR_INITVAL 0x0000000000000000ULL
+#define HTTBR_BADDR_MASK 0x000000FFFFFFF000ULL
+#define HTTBR_BADDR_SHIFT 12
+
+/* TCR_EL2 */
+#define TCR_INITVAL 0x80800000
+#define TCR_TBI_MASK 0x00100000
+#define TCR_TBI_SHIFT 20
+#define TCR_PS_MASK 0x00070000
+#define TCR_PS_SHIFT 16
+#define TCR_TG0_MASK 0x00004000
+#define TCR_TG0_SHIFT 14
+#define TCR_SH0_MASK 0x00003000
+#define TCR_SH0_SHIFT 12
+#define TCR_ORGN0_MASK 0x00000C00
+#define TCR_ORGN0_SHIFT 10
+#define TCR_IRGN0_MASK 0x00000300
+#define TCR_IRGN0_SHIFT 8
+#define TCR_T0SZ_MASK 0x0000003f
+#define TCR_T0SZ_SHIFT 0
+
+/* VTTBR */
+#define VTTBR_INITVAL 0x0000000000000000ULL
+#define VTTBR_VMID_MASK 0x00FF000000000000ULL
+#define VTTBR_VMID_SHIFT 48
+#define VTTBR_BADDR_MASK 0x000000FFFFFFF000ULL
+#define VTTBR_BADDR_SHIFT 12
+
+/* VTCR_EL2 */
+#define VTCR_INITVAL 0x80000000
+#define VTCR_PS_MASK 0x00070000
+#define VTCR_PS_SHIFT 16
+#define VTCR_TG0_MASK 0x00004000
+#define VTCR_TG0_SHIFT 14
+#define VTCR_SH0_MASK 0x00003000
+#define VTCR_SH0_SHIFT 12
+#define VTCR_ORGN0_MASK 0x00000C00
+#define VTCR_ORGN0_SHIFT 10
+#define VTCR_IRGN0_MASK 0x00000300
+#define VTCR_IRGN0_SHIFT 8
+#define VTCR_SL0_MASK 0x000000C0
+#define VTCR_SL0_SHIFT 6
+#define VTCR_T0SZ_MASK 0x0000003f
+#define VTCR_T0SZ_SHIFT 0
+
+/* MAIR_EL2 encodings */
+#define AINDEX_SO 0
+#define AINDEX_NORMAL_WT 1
+#define AINDEX_NORMAL_WB 2
+#define AINDEX_NORMAL_UC 3
+#define MAIR_INITVAL 0x0000000044FFBB00
+
+/* VPIDR */
+#define VPIDR_INITVAL 0x00000000
+
+/* VMPIDR */
+#define VMPIDR_INITVAL 0x00000000
+
+/* DBGVIDSR */
+#define DBGVIDSR_INITVAL 0x00000000
+#define DBGVIDSR_NS_MASK 0x80000000
+#define DBGVIDSR_NS_SHIFT 31
+#define DBGVIDSR_H_MASK 0x40000000
+#define DBGVIDSR_H_SHIFT 30
+#define DBGVIDSR_VMID_MASK 0x000000FF
+#define DBGVIDSR_VMID_SHIFT 0
+
+/* SCTLR_ELx */
+#define SCTLR_INITVAL 0x30C50878
+#define SCTLR_TE_MASK 0x40000000
+#define SCTLR_TE_SHIFT 30
+#define SCTLR_EE_MASK 0x02000000
+#define SCTLR_EE_SHIFT 25
+#define SCTLR_FI_MASK 0x00200000
+#define SCTLR_FI_SHIFT 21
+#define SCTLR_WXN_MASK 0x00080000
+#define SCTLR_WXN_SHIFT 19
+#define SCTLR_I_MASK 0x00001000
+#define SCTLR_I_SHIFT 12
+#define SCTLR_SA0_MASK 0x00000010
+#define SCTLR_SA0_SHIFT 4
+#define SCTLR_SA_MASK 0x00000008
+#define SCTLR_SA_SHIFT 3
+#define SCTLR_C_MASK 0x00000004
+#define SCTLR_C_SHIFT 2
+#define SCTLR_A_MASK 0x00000002
+#define SCTLR_A_SHIFT 1
+#define SCTLR_M_MASK 0x00000001
+#define SCTLR_M_SHIFT 0
+
+/* DBGBXVR */
+#define DBGBXVR_INITVAL 0x00000000
+#define DBGBXVR_VMID_MASK 0x000000FF
+#define DBGBXVR_VMID_SHIFT 0
+
+/* PAR_EL1 common fields */
+#define PAR_PA_MASK 0x0000FFFFFFFFF000ULL
+#define PAR_PA_SHIFT 12
+#define PAR_F_MASK 0x0000000000000001ULL
+#define PAR_F_SHIFT 0
+
+/* PAR_EL1 @ fault */
+#define PAR_STAGE_MASK 0x0000000000000200ULL
+#define PAR_STAGE_SHIFT 9
+#define PAR_STAGE1 0
+#define PAR_STAGE2 1
+#define PAR_PTW_MASK 0x0000000000000100ULL
+#define PAR_PTW_SHIFT 8
+#define PAR_FS_MASK 0x000000000000007EULL
+#define PAR_FS_SHIFT 1
+#define PAR_F_FAULT 0x0000000000000001ULL
+
+/* PAR_EL1 @ address-translation */
+#define PAR_MAIR_MASK 0xFF00000000000000ULL
+#define PAR_MAIR_SHIFT 56
+#define PAR64_NS_MASK 0x0000000000000200ULL
+#define PAR64_NS_SHIFT 9
+#define PAR64_SH_MASK 0x0000000000000180ULL
+#define PAR64_SH_SHIFT 7
+
+/* ID_PFR0_EL1 */
+#define ID_PFR0_THUMBEE_MASK 0x0000f000
+#define ID_PFR0_THUMBEE_SHIFT 12
+#define ID_PFR0_JAZELLE_MASK 0x00000f00
+#define ID_PFR0_JAZELLE_SHIFT 8
+#define ID_PFR0_THUMB2 0x00000030
+#define ID_PFR0_THUMB_MASK 0x000000f0
+#define ID_PFR0_THUMB_SHIFT 4
+#define ID_PFR0_ARM_MASK 0x0000000f
+#define ID_PFR0_ARM_SHIFT 0
+
+/* ID_PFR1_EL1 */
+#define ID_PFR1_GENTIMER_MASK 0x000f0000
+#define ID_PFR1_GENTIMER_SHIFT 16
+#define ID_PFR1_VIRTEXT_MASK 0x0000f000
+#define ID_PFR1_VIRTEXT_SHIFT 12
+#define ID_PFR1_2STACK_MASK 0x00000f00
+#define ID_PFR1_2STACK_SHIFT 8
+#define ID_PFR1_SECURE_MASK 0x000000f0
+#define ID_PFR1_SECURE_SHIFT 4
+#define ID_PFR1_PROGMODEL_MASK 0x0000000f
+#define ID_PFR1_PROGMODEL_SHIFT 0
+
+/* ID_AA64PFR0_EL1 */
+#define ID_AA64PFR0_ASIMD_MASK 0x00020000
+#define ID_AA64PFR0_ASIMD_SHIFT 17
+#define ID_AA64PFR0_FPU_MASK 0x00010000
+#define ID_AA64PFR0_FPU_SHIFT 16
+#define ID_AA64PFR0_EL3_A32 0x00002000
+#define ID_AA64PFR0_EL3_MASK 0x0000f000
+#define ID_AA64PFR0_EL3_SHIFT 12
+#define ID_AA64PFR0_EL2_A32 0x00000200
+#define ID_AA64PFR0_EL2_MASK 0x00000f00
+#define ID_AA64PFR0_EL2_SHIFT 8
+#define ID_AA64PFR0_EL1_A32 0x00000020
+#define ID_AA64PFR0_EL1_MASK 0x000000f0
+#define ID_AA64PFR0_EL1_SHIFT 4
+#define ID_AA64PFR0_EL0_A32 0x00000002
+#define ID_AA64PFR0_EL0_MASK 0x0000000f
+#define ID_AA64PFR0_EL0_SHIFT 0
+
+#endif
diff --git a/arch/arm/cpu/arm64/include/cpu_generic_timer.h b/arch/arm/cpu/arm64/include/cpu_generic_timer.h
new file mode 100644
index 0000000..a72a0ec
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/cpu_generic_timer.h
@@ -0,0 +1,159 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_generic_timer.c
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief CPU specific functions for ARM architecture generic timers
+ */
+
+#ifndef __CPU_GENERIC_TIMER_H__
+#define __CPU_GENERIC_TIMER_H__
+
+#include <vmm_types.h>
+
+#define generic_timer_pcounter_read() mrs(cntpct_el0)
+#define generic_timer_vcounter_read() mrs(cntvct_el0)
+
+/* cntfrq_el0 is writeable by highest implemented EL.
+ * We are running at EL2 and if EL3 is not implemented,
+ * hypervisor can write to cntfrq_el0 */
+#define generic_timer_freq_writeable() (!cpu_supports_el3())
+
+static inline void generic_timer_reg_write(int reg, u32 val)
+{
+ switch (reg) {
+ case GENERIC_TIMER_REG_FREQ:
+ msr(cntfrq_el0, val);
+ break;
+ case GENERIC_TIMER_REG_HCTL:
+ msr(cnthctl_el2, val);
+ break;
+ case GENERIC_TIMER_REG_KCTL:
+ msr(cntkctl_el1, val);
+ break;
+ case GENERIC_TIMER_REG_HYP_CTRL:
+ msr(cnthp_ctl_el2, val);
+ break;
+ case GENERIC_TIMER_REG_HYP_TVAL:
+ msr(cnthp_tval_el2, val);
+ break;
+ case GENERIC_TIMER_REG_PHYS_CTRL:
+ msr(cntp_ctl_el0, val);
+ break;
+ case GENERIC_TIMER_REG_PHYS_TVAL:
+ msr(cntp_tval_el0, val);
+ break;
+ case GENERIC_TIMER_REG_VIRT_CTRL:
+ msr(cntv_ctl_el0, val);
+ break;
+ case GENERIC_TIMER_REG_VIRT_TVAL:
+ msr(cntv_tval_el0, val);
+ break;
+ default:
+ vmm_panic("Trying to write invalid generic-timer register\n");
+ }
+
+ isb();
+}
+
+static inline u32 generic_timer_reg_read(int reg)
+{
+ u32 val;
+
+ switch (reg) {
+ case GENERIC_TIMER_REG_FREQ:
+ val = mrs(cntfrq_el0);
+ break;
+ case GENERIC_TIMER_REG_HCTL:
+ val = mrs(cnthctl_el2);
+ break;
+ case GENERIC_TIMER_REG_KCTL:
+ val = mrs(cntkctl_el1);
+ break;
+ case GENERIC_TIMER_REG_HYP_CTRL:
+ val = mrs(cnthp_ctl_el2);
+ break;
+ case GENERIC_TIMER_REG_HYP_TVAL:
+ val = mrs(cnthp_tval_el2);
+ break;
+ case GENERIC_TIMER_REG_PHYS_CTRL:
+ val = mrs(cntp_ctl_el0);
+ break;
+ case GENERIC_TIMER_REG_PHYS_TVAL:
+ val = mrs(cntp_tval_el0);
+ break;
+ case GENERIC_TIMER_REG_VIRT_CTRL:
+ val = mrs(cntv_ctl_el0);
+ break;
+ case GENERIC_TIMER_REG_VIRT_TVAL:
+ val = mrs(cntv_tval_el0);
+ break;
+ default:
+ vmm_panic("Trying to read invalid generic-timer register\n");
+ }
+
+ return val;
+}
+
+static inline void generic_timer_reg_write64(int reg, u64 val)
+{
+ switch (reg) {
+ case GENERIC_TIMER_REG_HYP_CVAL:
+ msr(cnthp_cval_el2, val);
+ break;
+ case GENERIC_TIMER_REG_PHYS_CVAL:
+ msr(cntp_cval_el0, val);
+ break;
+ case GENERIC_TIMER_REG_VIRT_CVAL:
+ msr(cntv_cval_el0, val);
+ break;
+ case GENERIC_TIMER_REG_VIRT_OFF:
+ msr(cntvoff_el2, val);
+ break;
+ default:
+ vmm_panic("Trying to write invalid generic-timer register\n");
+ }
+
+ isb();
+}
+
+static inline u64 generic_timer_reg_read64(int reg)
+{
+ u64 val;
+
+ switch (reg) {
+ case GENERIC_TIMER_REG_HYP_CVAL:
+ val = mrs(cnthp_cval_el2);
+ break;
+ case GENERIC_TIMER_REG_PHYS_CVAL:
+ val = mrs(cntp_cval_el0);
+ break;
+ case GENERIC_TIMER_REG_VIRT_CVAL:
+ val = mrs(cntv_cval_el0);
+ break;
+ case GENERIC_TIMER_REG_VIRT_OFF:
+ val = mrs(cntvoff_el2);
+ break;
+ default:
+ vmm_panic("Trying to read invalid generic-timer register\n");
+ }
+
+ return val;
+}
+
+#endif /* __CPU_GENERIC_TIMER_H__ */
diff --git a/arch/arm/cpu/arm64/include/cpu_inline_asm.h b/arch/arm/cpu/arm64/include/cpu_inline_asm.h
new file mode 100644
index 0000000..8d1b472
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/cpu_inline_asm.h
@@ -0,0 +1,243 @@
+/**
+ * Copyright (c) 2012 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_inline_asm.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief Frequently required inline assembly macros
+ */
+#ifndef __CPU_INLINE_ASM_H__
+#define __CPU_INLINE_ASM_H__
+
+#include <vmm_types.h>
+
+#define rev16(val) ({ u16 rval; asm volatile(\
+ " rev16 %0, %1\n\t" : "=r" (rval) : \
+ "r" (val) : "memory", "cc"); rval;})
+
+#define rev32(val) ({ u32 rval; asm volatile(\
+ " rev32 %0, %1\n\t" : "=r" (rval) : \
+ "r" (val) : "memory", "cc"); rval;})
+
+#define rev64(val) ({ u32 d1, d2; \
+ d1 = (u32)((u64)val >> 32); d2 = (u32)val; \
+ d1 = rev32(d1); d2 = rev32(d2); \
+ (((u64)d2 << 32) | ((u64)d1));})
+
+#define ldxr(addr, data) asm volatile("ldxr %0, [%1]\n\t" \
+ : "=r"(data) : "r"(addr))
+
+#define stxr(addr, data, res) asm volatile("stxr %0, %1, [%2]\n\t" \
+ : "=r"(res) : "r"(data), "r"(addr))
+
+#define clrex() asm volatile("clrex\n\t")
+
+#define mrs(spr) ({ u64 rval; asm volatile(\
+ "mrs %0," #spr :"=r"(rval)); rval; })
+
+#define msr(spr, val) asm volatile("msr " #spr ", %0" ::"r"(val))
+
+#define msr_sync(spr, val) asm volatile("msr " #spr ", %0\n\t" \
+ "dsb sy\n\t" \
+ "isb\n\t" ::"r"(val))
+
+/* TLB maintainence */
+
+#define inv_tlb_hyp_all() asm volatile("tlbi alle2is\n\t" \
+ "dsb sy\n\t" \
+ "isb\n\t" \
+ ::: "memory", "cc")
+
+#define inv_tlb_guest_allis() asm volatile("tlbi alle1is\n\t" \
+ "dsb sy\n\t" \
+ "isb\n\t" \
+ ::: "memory", "cc")
+
+#define inv_tlb_guest_cur() asm volatile("tlbi vmalls12e1is\n\t" \
+ "dsb sy\n\t" \
+ "isb\n\t" \
+ ::: "memory", "cc")
+
+#define inv_tlb_hyp_vais(va) asm volatile("tlbi vae2is, %0\n\t" \
+ "dsb sy\n\t" \
+ "isb\n\t" \
+ ::"r"((va)>>12): "memory", "cc")
+
+#define inv_tlb_guest_ipa(va) asm volatile("tlbi ipas2e1is, %0\n\t" \
+ "dsb sy\n\t" \
+ "isb\n\t" \
+ ::"r"((va)>>12): "memory", "cc")
+
+#define inv_tlb_guest_va(va) asm volatile("tlbi vaae1is, %0\n\t" \
+ "dsb sy\n\t" \
+ "isb\n\t" \
+ ::"r"((va)>>12): "memory", "cc")
+
+/* VA to PA Address Translation */
+
+#define VA2PA_STAGE1 "s1"
+#define VA2PA_STAGE12 "s12"
+#define VA2PA_EL0 "e0"
+#define VA2PA_EL1 "e1"
+#define VA2PA_EL2 "e2"
+#define VA2PA_EL3 "e3"
+#define VA2PA_RD "r"
+#define VA2PA_WR "w"
+#define va2pa_at(stage, el, rw, va) asm volatile( \
+ "at " stage el rw ", %0" \
+ : : "r"(va) : "memory", "cc");
+
+
+/* Features */
+#define cpu_supports_thumbee() ({ u64 pfr0; \
+ asm volatile("mrs %0, id_pfr0_el1" \
+ : "=r"(pfr0)); \
+ (pfr0 & ID_PFR0_THUMBEE_MASK); \
+ })
+
+#define cpu_supports_thumb() ({ u64 pfr0; \
+ asm volatile("mrs %0, id_pfr0_el1" \
+ : "=r"(pfr0)); \
+ (pfr0 & ID_PFR0_THUMBEE_MASK); \
+ })
+
+#define cpu_supports_thumb2() ({ u64 pfr0; \
+ asm volatile("mrs %0, id_pfr0_el1" \
+ : "=r"(pfr0)); \
+ ((pfr0 & ID_PFR0_THUMB_MASK) == ID_PFR0_THUMB2_MASK); \
+ })
+
+#define cpu_supports_jazelle() ({ u64 pfr0; \
+ asm volatile("mrs %0, id_pfr0_el1" \
+ : "=r"(pfr0)); \
+ (pfr0 & ID_PFR0_JAZELLE_MASK); \
+ })
+
+#define cpu_supports_arm() ({ u64 pfr0; \
+ asm volatile("mrs %0, id_pfr0_el1" \
+ : "=r"(pfr0)); \
+ (pfr0 & ID_PFR0_ARM_MASK); \
+ })
+
+#define cpu_supports_asimd() ({ u64 pfr0; \
+ asm volatile("mrs %0, id_aa64pfr0_el1" \
+ : "=r"(pfr0)); \
+ ((pfr0 & ID_AA64PFR0_ASIMD_MASK) == 0); \
+ })
+
+#define cpu_supports_fpu() ({ u64 pfr0; \
+ asm volatile("mrs %0, id_aa64pfr0_el1" \
+ : "=r"(pfr0)); \
+ ((pfr0 & ID_AA64PFR0_FPU_MASK) == 0); \
+ })
+
+#define cpu_supports_el0_a32() ({ u64 pfr0; \
+ asm volatile("mrs %0, id_aa64pfr0_el1" \
+ : "=r"(pfr0)); \
+ ((pfr0 & ID_AA64PFR0_EL0_MASK) == ID_AA64PFR0_EL0_A32); \
+ })
+
+#define cpu_supports_el1_a32() ({ u64 pfr0; \
+ asm volatile("mrs %0, id_aa64pfr0_el1" \
+ : "=r"(pfr0)); \
+ ((pfr0 & ID_AA64PFR0_EL1_MASK) == ID_AA64PFR0_EL1_A32); \
+ })
+
+#define cpu_supports_el2_a32() ({ u64 pfr0; \
+ asm volatile("mrs %0, id_aa64pfr0_el1" \
+ : "=r"(pfr0)); \
+ ((pfr0 & ID_AA64PFR0_EL2_MASK) == ID_AA64PFR0_EL2_A32); \
+ })
+
+#define cpu_supports_el3_a32() ({ u64 pfr0; \
+ asm volatile("mrs %0, id_aa64pfr0_el1" \
+ : "=r"(pfr0)); \
+ ((pfr0 & ID_AA64PFR0_EL3_MASK) == ID_AA64PFR0_EL3_A32); \
+ })
+
+#define cpu_supports_el0() ({ u64 pfr0; \
+ asm volatile("mrs %0, id_aa64pfr0_el1" \
+ : "=r"(pfr0)); \
+ (pfr0 & ID_AA64PFR0_EL0_MASK); \
+ })
+
+#define cpu_supports_el1() ({ u64 pfr0; \
+ asm volatile("mrs %0, id_aa64pfr0_el1" \
+ : "=r"(pfr0)); \
+ (pfr0 & ID_AA64PFR0_EL1_MASK); \
+ })
+
+#define cpu_supports_el2() ({ u64 pfr0; \
+ asm volatile("mrs %0, id_aa64pfr0_el1" \
+ : "=r"(pfr0)); \
+ (pfr0 & ID_AA64PFR0_EL2_MASK); \
+ })
+
+#define cpu_supports_el3() ({ u64 pfr0; \
+ asm volatile("mrs %0, id_aa64pfr0_el1" \
+ : "=r"(pfr0)); \
+ (pfr0 & ID_AA64PFR0_EL3_MASK); \
+ })
+
+#define vfp_simd_save_regs(addr) { \
+ asm volatile("stnp Q0, Q1, [%0, #0x00]\n\t" \
+ "stnp Q2, Q3, [%0, #0x20]\n\t" \
+ "stnp Q4, Q5, [%0, #0x40]\n\t" \
+ "stnp Q6, Q7, [%0, #0x60]\n\t" \
+ :: "r"((char *)(addr) + 0x000)); \
+ asm volatile("stnp Q8, Q9, [%0, #0x00]\n\t" \
+ "stnp Q10, Q11, [%0, #0x20]\n\t" \
+ "stnp Q12, Q13, [%0, #0x40]\n\t" \
+ "stnp Q14, Q15, [%0, #0x60]\n\t" \
+ :: "r"((char *)(addr) + 0x080)); \
+ asm volatile("stnp Q16, Q17, [%0, #0x00]\n\t" \
+ "stnp Q18, Q19, [%0, #0x20]\n\t" \
+ "stnp Q20, Q21, [%0, #0x40]\n\t" \
+ "stnp Q22, Q23, [%0, #0x60]\n\t" \
+ :: "r"((char *)(addr) + 0x100)); \
+ asm volatile("stnp Q24, Q25, [%0, #0x00]\n\t" \
+ "stnp Q26, Q27, [%0, #0x20]\n\t" \
+ "stnp Q28, Q29, [%0, #0x40]\n\t" \
+ "stnp Q30, Q31, [%0, #0x60]\n\t" \
+ :: "r"((char *)(addr) + 0x180)); \
+ }
+
+
+#define vfp_simd_restore_regs(addr) { \
+ asm volatile("ldnp Q0, Q1, [%0, #0x00]\n\t" \
+ "ldnp Q2, Q3, [%0, #0x20]\n\t" \
+ "ldnp Q4, Q5, [%0, #0x40]\n\t" \
+ "ldnp Q6, Q7, [%0, #0x60]\n\t" \
+ :: "r"((char *)(addr) + 0x000)); \
+ asm volatile("ldnp Q8, Q9, [%0, #0x00]\n\t" \
+ "ldnp Q10, Q11, [%0, #0x20]\n\t" \
+ "ldnp Q12, Q13, [%0, #0x40]\n\t" \
+ "ldnp Q14, Q15, [%0, #0x60]\n\t" \
+ :: "r"((char *)(addr) + 0x080)); \
+ asm volatile("ldnp Q16, Q17, [%0, #0x00]\n\t" \
+ "ldnp Q18, Q19, [%0, #0x20]\n\t" \
+ "ldnp Q20, Q21, [%0, #0x40]\n\t" \
+ "ldnp Q22, Q23, [%0, #0x60]\n\t" \
+ :: "r"((char *)(addr) + 0x100)); \
+ asm volatile("ldnp Q24, Q25, [%0, #0x00]\n\t" \
+ "ldnp Q26, Q27, [%0, #0x20]\n\t" \
+ "ldnp Q28, Q29, [%0, #0x40]\n\t" \
+ "ldnp Q30, Q31, [%0, #0x60]\n\t" \
+ :: "r"((char *)(addr) + 0x180)); \
+ }
+
+#endif
diff --git a/arch/arm/cpu/arm64/include/cpu_mmu_lpae.h b/arch/arm/cpu/arm64/include/cpu_mmu_lpae.h
new file mode 100644
index 0000000..d75bd42
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/cpu_mmu_lpae.h
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_mmu_lpae.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief MMU interface of LPAE enabled ARM processor
+ */
+#ifndef _CPU_MMU_LPAE_H__
+#define _CPU_MMU_LPAE_H__
+
+#include <cpu_cache.h>
+#include <cpu_inline_asm.h>
+#include <arch_barrier.h>
+
+#define TTBL_FIRST_LEVEL 1
+#define TTBL_LAST_LEVEL 3
+
+#define cpu_invalid_all_guest_tlbs() inv_tlb_guest_allis()
+#define cpu_invalid_va_hypervisor_tlb(va) inv_tlb_hyp_vais((va))
+#define cpu_invalid_all_tlbs() inv_tlb_hyp_all()
+
+#define cpu_stage2_ttbl_pa() \
+ (mrs(vttbr_el2) & VTTBR_BADDR_MASK)
+#define cpu_stage2_vmid() \
+ ((mrs(vttbr_el2) & VTTBR_VMID_MASK) >> VTTBR_VMID_SHIFT)
+#define cpu_stage2_update(ttbl_pa, vmid) \
+ do { \
+ u64 vttbr = 0x0; \
+ vttbr |= ((u64)(vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK; \
+ vttbr |= (ttbl_pa) & VTTBR_BADDR_MASK; \
+ msr(vttbr_el2, vttbr); \
+ } while(0);
+
+static inline void cpu_mmu_sync_tte(u64 *tte)
+{
+ isb();
+ dsb();
+}
+
+#endif /* _CPU_MMU_LPAE_H */
diff --git a/arch/arm/cpu/arm64/include/cpu_vcpu_coproc.h b/arch/arm/cpu/arm64/include/cpu_vcpu_coproc.h
new file mode 100644
index 0000000..9094765
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/cpu_vcpu_coproc.h
@@ -0,0 +1,90 @@
+/**
+ * Copyright (c) 2012 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_vcpu_coproc.h
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief header file for coprocessor access
+ */
+#ifndef _CPU_VCPU_COPROC_H__
+#define _CPU_VCPU_COPROC_H__
+
+#include <vmm_types.h>
+#include <vmm_manager.h>
+
+typedef bool (*cpu_coproc_ldcstc_accept)(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 D, u32 CRd,
+ u32 uopt, u32 imm8);
+
+typedef bool (*cpu_coproc_ldcstc_done)(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 index, u32 D, u32 CRd,
+ u32 uopt, u32 imm8);
+
+typedef u32 (*cpu_coproc_ldcstc_read)(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 index, u32 D, u32 CRd,
+ u32 uopt, u32 imm8);
+
+typedef void (*cpu_coproc_ldcstc_write)(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 index, u32 D, u32 CRd,
+ u32 uopt, u32 imm8, u32 data);
+
+typedef bool (*cpu_coproc_read2)(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 CRm,
+ u32 *data, u32 *data2);
+
+typedef bool (*cpu_coproc_write2)(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 CRm,
+ u32 data, u32 data2);
+
+typedef bool (*cpu_coproc_data_process)(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 opc2,
+ u32 CRd, u32 CRn, u32 CRm);
+
+typedef bool (*cpu_coproc_read)(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 opc2, u32 CRn, u32 CRm,
+ u32 *data);
+
+typedef bool (*cpu_coproc_write)(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 opc2, u32 CRn, u32 CRm,
+ u32 data);
+
+struct cpu_vcpu_coproc {
+ u32 cpnum;
+ cpu_coproc_ldcstc_accept ldcstc_accept;
+ cpu_coproc_ldcstc_done ldcstc_done;
+ cpu_coproc_ldcstc_read ldcstc_read;
+ cpu_coproc_ldcstc_write ldcstc_write;
+ cpu_coproc_read2 read2;
+ cpu_coproc_write2 write2;
+ cpu_coproc_data_process data_process;
+ cpu_coproc_read read;
+ cpu_coproc_write write;
+};
+
+/** Retrive a coprocessor with given number */
+struct cpu_vcpu_coproc *cpu_vcpu_coproc_get(u32 cpnum);
+
+#endif /* _CPU_VCPU_COPROC_H */
diff --git a/arch/arm/cpu/arm64/include/cpu_vcpu_emulate.h b/arch/arm/cpu/arm64/include/cpu_vcpu_emulate.h
new file mode 100644
index 0000000..11d1256
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/cpu_vcpu_emulate.h
@@ -0,0 +1,96 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_vcpu_emulate.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief Inferace for hardware assisted instruction emulation
+ */
+#ifndef _CPU_VCPU_EMULATE_H__
+#define _CPU_VCPU_EMULATE_H__
+
+#include <vmm_types.h>
+#include <vmm_manager.h>
+
+/** Emulate WFI/WFE instruction */
+int cpu_vcpu_emulate_wfi_wfe(struct vmm_vcpu * vcpu,
+ arch_regs_t * regs,
+ u32 il, u32 iss);
+
+/** Emulate MCR/MRC CP15 instruction */
+int cpu_vcpu_emulate_mcr_mrc_cp15(struct vmm_vcpu * vcpu,
+ arch_regs_t * regs,
+ u32 il, u32 iss);
+
+/** Emulate MCRR/MRRC CP15 instruction */
+int cpu_vcpu_emulate_mcrr_mrrc_cp15(struct vmm_vcpu * vcpu,
+ arch_regs_t * regs,
+ u32 il, u32 iss);
+
+/** Emulate MCR/MRC CP14 instruction */
+int cpu_vcpu_emulate_mcr_mrc_cp14(struct vmm_vcpu * vcpu,
+ arch_regs_t * regs,
+ u32 il, u32 iss);
+
+/** Emulate LDC/STC CP14 instruction */
+int cpu_vcpu_emulate_ldc_stc_cp14(struct vmm_vcpu * vcpu,
+ arch_regs_t * regs,
+ u32 il, u32 iss);
+
+/** Emulate Advanced SIMD or FPU register access */
+int cpu_vcpu_emulate_simd_fp_regs(struct vmm_vcpu * vcpu,
+ arch_regs_t * regs,
+ u32 il, u32 iss);
+
+/** Emulate MRC (or VMRS) to CP10 instruction */
+int cpu_vcpu_emulate_vmrs(struct vmm_vcpu * vcpu,
+ arch_regs_t * regs,
+ u32 il, u32 iss);
+
+/** Emulate MCRR/MRRC to CP14 instruction */
+int cpu_vcpu_emulate_mcrr_mrrc_cp14(struct vmm_vcpu * vcpu,
+ arch_regs_t * regs,
+ u32 il, u32 iss);
+
+/** Emulate HVC instruction (or Handle Hypercall) for A32 guest */
+int cpu_vcpu_emulate_hvc32(struct vmm_vcpu * vcpu,
+ arch_regs_t * regs,
+ u32 il, u32 iss);
+
+/** Emulate HVC instruction (or Handle Hypercall) for A64 guest */
+int cpu_vcpu_emulate_hvc64(struct vmm_vcpu * vcpu,
+ arch_regs_t * regs,
+ u32 il, u32 iss);
+
+/** Emulate MRS/MSR/System Regs access */
+int cpu_vcpu_emulate_msr_mrs_system(struct vmm_vcpu * vcpu,
+ arch_regs_t * regs,
+ u32 il, u32 iss);
+
+/** Emulate Load instruction */
+int cpu_vcpu_emulate_load(struct vmm_vcpu * vcpu,
+ arch_regs_t * regs,
+ u32 il, u32 iss,
+ physical_addr_t ipa);
+
+/** Emulate Store instruction */
+int cpu_vcpu_emulate_store(struct vmm_vcpu * vcpu,
+ arch_regs_t * regs,
+ u32 il, u32 iss,
+ physical_addr_t ipa);
+
+#endif
diff --git a/arch/arm/cpu/arm64/include/cpu_vcpu_helper.h b/arch/arm/cpu/arm64/include/cpu_vcpu_helper.h
new file mode 100644
index 0000000..19be3d3
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/cpu_vcpu_helper.h
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2012 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_vcpu_helper.h
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief header of VCPU helper functions
+ */
+#ifndef _CPU_VCPU_HELPER_H__
+#define _CPU_VCPU_HELPER_H__
+
+#include <vmm_types.h>
+#include <vmm_manager.h>
+
+/* Function to halt VCPU */
+void cpu_vcpu_halt(struct vmm_vcpu *vcpu, arch_regs_t *regs);
+
+/* Function to read a VCPU register of current mode */
+u64 cpu_vcpu_reg_read(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 reg_num);
+
+/* Function to write a VCPU register of current mode */
+void cpu_vcpu_reg_write(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ u32 reg_num,
+ u64 reg_val);
+
+/* Function to inject undef exception to a VCPU */
+int cpu_vcpu_inject_undef(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs);
+
+/* Function to inject prefetch abort exception to a VCPU */
+int cpu_vcpu_inject_pabt(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs);
+
+/* Function to inject data abort exception to a VCPU */
+int cpu_vcpu_inject_dabt(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ virtual_addr_t addr);
+
+/* Function to dump user registers */
+void cpu_vcpu_dump_user_reg(arch_regs_t *regs);
+
+#endif
diff --git a/arch/arm/cpu/arm64/include/cpu_vcpu_mem.h b/arch/arm/cpu/arm64/include/cpu_vcpu_mem.h
new file mode 100644
index 0000000..5cb132f
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/cpu_vcpu_mem.h
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_vcpu_mem.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief Header File for VCPU memory read/write emulation
+ */
+#ifndef _CPU_VCPU_MEM_H__
+#define _CPU_VCPU_MEM_H__
+
+#include <vmm_types.h>
+#include <vmm_manager.h>
+
+/** Read from memory for VCPU */
+int cpu_vcpu_mem_read(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ virtual_addr_t addr,
+ void *dst, u32 dst_len,
+ bool force_unpriv);
+
+/** Write to memory for VCPU */
+int cpu_vcpu_mem_write(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ virtual_addr_t addr,
+ void *src, u32 src_len,
+ bool force_unpriv);
+
+/** Read-Exclusive from memory for VCPU */
+int cpu_vcpu_mem_readex(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ virtual_addr_t addr,
+ void *dst, u32 dst_len,
+ bool force_unpriv);
+
+/** Write-Exclusive to memory for VCPU */
+int cpu_vcpu_mem_writeex(struct vmm_vcpu *vcpu,
+ arch_regs_t *regs,
+ virtual_addr_t addr,
+ void *src, u32 src_len,
+ bool force_unpriv);
+
+#endif /* _CPU_VCPU_MEM_H */
diff --git a/arch/arm/cpu/arm64/include/cpu_vcpu_spr.h b/arch/arm/cpu/arm64/include/cpu_vcpu_spr.h
new file mode 100644
index 0000000..eeb4e9b
--- /dev/null
+++ b/arch/arm/cpu/arm64/include/cpu_vcpu_spr.h
@@ -0,0 +1,69 @@
+/**
+ * Copyright (c) 2012 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file cpu_vcpu_cp15.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief Header File for VCPU cp15 emulation
+ */
+#ifndef _CPU_VCPU_CP15_H__
+#define _CPU_VCPU_CP15_H__
+
+#include <vmm_types.h>
+#include <vmm_manager.h>
+
+/** Handle stage2 instruction abort */
+int cpu_vcpu_inst_abort(struct vmm_vcpu * vcpu,
+ arch_regs_t * regs,
+ u32 il, u32 iss,
+ physical_addr_t fipa);
+
+/** Handle stage2 data abort */
+int cpu_vcpu_data_abort(struct vmm_vcpu * vcpu,
+ arch_regs_t * regs,
+ u32 il, u32 iss,
+ physical_addr_t fipa);
+
+/** Read one SPR */
+bool cpu_vcpu_spr_read(struct vmm_vcpu * vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 opc2, u32 CRn, u32 CRm,
+ u64 *data);
+
+/** Write one SPR */
+bool cpu_vcpu_spr_write(struct vmm_vcpu * vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 opc2, u32 CRn, u32 CRm,
+ u64 data);
+
+bool cpu_vcpu_cp15_read(struct vmm_vcpu * vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 opc2, u32 CRn, u32 CRm,
+ u64 *data);
+
+bool cpu_vcpu_cp15_write(struct vmm_vcpu * vcpu,
+ arch_regs_t *regs,
+ u32 opc1, u32 opc2, u32 CRn, u32 CRm,
+ u64 data);
+
+/** Initialize SPR subsystem for a VCPU */
+int cpu_vcpu_spr_init(struct vmm_vcpu * vcpu, u32 cpuid);
+
+/** DeInitialize SPR subsystem for a VCPU */
+int cpu_vcpu_spr_deinit(struct vmm_vcpu * vcpu);
+
+#endif /* _CPU_VCPU_CP15_H */
diff --git a/arch/arm/cpu/arm64/linker.ld b/arch/arm/cpu/arm64/linker.ld
new file mode 100755
index 0000000..3673602
--- /dev/null
+++ b/arch/arm/cpu/arm64/linker.ld
@@ -0,0 +1,119 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file linker.ld
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief CPU specific linker script
+ */
+
+OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
+OUTPUT_ARCH("aarch64")
+ENTRY(_start)
+
+SECTIONS
+{
+ . = TEXT_START;
+
+ . = ALIGN(0x1000); /* Need this to create proper sections */
+
+ PROVIDE(_code_start = .);
+
+ .text :
+ {
+ PROVIDE(_text_start = .);
+ *(.entry)
+ *(.text)
+ . = ALIGN(8);
+ PROVIDE(_text_end = .);
+ }
+
+ .data :
+ {
+ PROVIDE(_data_start = .);
+ *(.data)
+ . = ALIGN(8);
+ PROVIDE(_data_end = .);
+ }
+
+ .rodata :
+ {
+ PROVIDE(_rodata_start = .);
+ *(.rodata .rodata.*)
+ . = ALIGN(8);
+ PROVIDE(_rodata_end = .);
+ }
+
+ .percpu :
+ {
+ PROVIDE(_percpu_start = .);
+ *(.percpu)
+ . = ALIGN(8);
+ PROVIDE(_percpu_end = .);
+ }
+
+ . = ALIGN(0x1000); /* init section is page aligned */
+
+ .init :
+ {
+ PROVIDE(_init_start = .);
+
+ *(.init.*)
+ . = ALIGN(8);
+
+ PROVIDE(_modtbl_start = .);
+ *(.modtbl)
+ . = ALIGN(8);
+ PROVIDE(_modtbl_end = .);
+
+ . = ALIGN(8);
+ PROVIDE(__setup_start = .);
+ *(.setup.init);
+ PROVIDE(__setup_end = .);
+
+ . = ALIGN(CONFIG_ARM_MAX_DTB_SIZE);
+ *(.devtree)
+ . = ALIGN(CONFIG_ARM_MAX_DTB_SIZE);
+
+ PROVIDE(_init_end = .);
+ }
+
+ . = ALIGN(0x1000); /* bss is page aligned */
+
+ .bss :
+ {
+ PROVIDE(_bss_start = .);
+ *(.bss)
+ *(.bss.*)
+ . = ALIGN(8);
+ PROVIDE(_bss_end = .);
+ }
+
+ . = ALIGN(0x1000); /* all stacks are page aligned */
+
+ .hvc_stack :
+ {
+ PROVIDE(_hvc_stack_start = .);
+ . = . + (CONFIG_IRQ_STACK_SIZE * CONFIG_CPU_COUNT);
+ . = ALIGN(8);
+ PROVIDE(_hvc_stack_end = .);
+ }
+
+ . = ALIGN(0x1000); /* Need this to create proper pages */
+
+ PROVIDE(_code_end = .);
+}
diff --git a/arch/arm/cpu/arm64/objects.mk b/arch/arm/cpu/arm64/objects.mk
new file mode 100644
index 0000000..5ffb162
--- /dev/null
+++ b/arch/arm/cpu/arm64/objects.mk
@@ -0,0 +1,52 @@
+#/**
+# Copyright (c) 2013 Sukanto Ghosh.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# @file objects.mk
+# @author Sukanto Ghosh (sukant...@gmail.com)
+# @brief list of ARM64 cpu objects.
+# */
+
+# This selects which instruction set is used.
+# Note that GCC does not numerically define an architecture version
+# macro, but instead defines a whole series of macros which makes
+# testing for a specific architecture or later rather impossible.
+arch-$(CONFIG_ARMV8) += -mgeneral-regs-only -mlittle-endian
+
+cpu-cppflags+=-DTEXT_START=0x00000000
+cpu-cflags += $(arch-y) $(tune-y)
+cpu-asflags += $(arch-y) $(tune-y)
+cpu-ldflags +=
+
+cpu-objs-y+= cpu_entry.o
+cpu-objs-y+= cpu_cache.o
+cpu-objs-y+= cpu_init.o
+cpu-objs-y+= cpu_delay.o
+cpu-objs-y+= cpu_elf.o
+cpu-objs-$(CONFIG_ARM64_STACKTRACE)+= cpu_stacktrace.o
+cpu-objs-$(CONFIG_SMP)+= cpu_smp.o
+cpu-objs-$(CONFIG_SMP)+= cpu_locks.o
+cpu-objs-y+= cpu_atomic.o
+cpu-objs-y+= cpu_atomic64.o
+cpu-objs-y+= cpu_interrupts.o
+cpu-objs-y+= cpu_vcpu_helper.o
+cpu-objs-y+= cpu_vcpu_coproc.o
+cpu-objs-y+= cpu_vcpu_spr.o
+cpu-objs-y+= cpu_vcpu_mem.o
+cpu-objs-y+= cpu_vcpu_irq.o
+cpu-objs-y+= cpu_vcpu_emulate.o
+
diff --git a/arch/arm/cpu/arm64/openconf.cfg b/arch/arm/cpu/arm64/openconf.cfg
new file mode 100644
index 0000000..15c8012
--- /dev/null
+++ b/arch/arm/cpu/arm64/openconf.cfg
@@ -0,0 +1,56 @@
+#/**
+# Copyright (c) 2013 Sukanto Ghosh.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# @file openconf.cfg
+# @author Sukanto Ghosh (sukant...@gmail.com)
+# @brief Config file for ARM64
+#*/
+
+config CONFIG_CPU
+ string
+ default "arm64"
+
+config CONFIG_CPU_LE
+ bool
+ default y
+
+config CONFIG_CPU_BE
+ bool
+ default n
+
+config CONFIG_64BIT
+ bool
+ default y
+
+config CONFIG_ARM64_STACKTRACE
+ bool "Enable Stack Tracing"
+ default y
+ help
+ This option forces ARM compiler to use frame pointer for
+ all functions hence making stack tracing possible.
+
+ Enabling this option forces compiler to add additional
+ instructions to setup stack frame in function prolog of
+ all functions.
+
+ Disabling this option makes hypervisor slightly faster but
+ disable stack trace information printed by hypervisor.
+
+ By default, this options is always enabled. You can disable
+ this option in-case you want slightly faster and slight
+ smaller hypervisor
diff --git a/arch/arm/cpu/common/openconf.cfg b/arch/arm/cpu/common/openconf.cfg
index ffb96bc..25fd347 100644
--- a/arch/arm/cpu/common/openconf.cfg
+++ b/arch/arm/cpu/common/openconf.cfg
@@ -28,12 +28,12 @@ config CONFIG_ARM_LOCKS

config CONFIG_ARM_VGIC
bool "ARM GIC with Virtualization Extensions"
- depends on CONFIG_ARM_GIC && CONFIG_ARM32VE
+ depends on CONFIG_ARM_GIC && (CONFIG_ARM32VE || CONFIG_ARM64)
default n

config CONFIG_ARM_GENERIC_TIMER
bool "ARM Generic Timer"
- depends on CONFIG_ARM_GIC && CONFIG_ARM32VE
+ depends on CONFIG_ARM_GIC && (CONFIG_ARM32VE || CONFIG_ARM64)
default n

config CONFIG_ARM_MMU_LPAE
diff --git a/arch/arm/cpu/openconf.cfg b/arch/arm/cpu/openconf.cfg
index ccc4c6d..47b255c 100644
--- a/arch/arm/cpu/openconf.cfg
+++ b/arch/arm/cpu/openconf.cfg
@@ -72,6 +72,14 @@ choice
Select this if you are using Cortex-A15 (with virtualization
extension)

+ config CONFIG_CPU_GENERIC_V8
+ bool "generic-v8"
+ select CONFIG_SMP
+ select CONFIG_ARMV8
+ select CONFIG_ARM_MMU_LPAE
+ help
+ Select this if you are using Generic ARMv8 CPU
+
endchoice

config CONFIG_CPU_COUNT
@@ -80,6 +88,7 @@ config CONFIG_CPU_COUNT
default 4 if CONFIG_CPU_ARM11MP
default 4 if CONFIG_CPU_CORTEX_A9
default 4 if CONFIG_CPU_CORTEX_A15
+ default 8 if CONFIG_CPU_GENERIC_V8
default 1

config CONFIG_ARMV5
@@ -107,6 +116,11 @@ config CONFIG_ARMV7A_VE
select CONFIG_ARM32VE
default n

+config CONFIG_ARMV8
+ bool
+ select CONFIG_ARM64
+ default n
+
config CONFIG_ARM32
bool
default n
@@ -115,6 +129,10 @@ config CONFIG_ARM32VE
bool
default n

+config CONFIG_ARM64
+ bool
+ default n
+
menu "ARM Options"

config CONFIG_VAPOOL_SIZE_MB
@@ -138,5 +156,11 @@ source "arch/arm/cpu/arm32ve/openconf.cfg"

endif

+if CONFIG_ARM64
+
+source "arch/arm/cpu/arm64/openconf.cfg"
+
+endif
+
endmenu

--
1.7.9.5

Sukanto Ghosh

unread,
Sep 15, 2013, 4:08:45 AM9/15/13
to an...@brainfault.org, Sukanto Ghosh, xvisor...@googlegroups.com
There are no real development boards openly available for arm64
hence we introduce a completely paravirtualized virt-v8 guest
for folks interested in having a dummy or paravirtualized
hardware for guest.

This virt-v8 guest is a virtual machine with VirtIO-based
devices, GIC and ARMv8 generic timer.

This patch adds guest template for virt-v8 guest.

Signed-off-by: Sukanto Ghosh <sukant...@gmail.com>
---
arch/arm/board/common/guests/virt-v8x2.dtsi | 94 +++++++++++++++++++++++++++
1 file changed, 94 insertions(+)
create mode 100644 arch/arm/board/common/guests/virt-v8x2.dtsi

diff --git a/arch/arm/board/common/guests/virt-v8x2.dtsi b/arch/arm/board/common/guests/virt-v8x2.dtsi
new file mode 100644
index 0000000..a6f4959
--- /dev/null
+++ b/arch/arm/board/common/guests/virt-v8x2.dtsi
@@ -0,0 +1,94 @@
+
+/ {
+ templates {
+ virt-v8x2 {
+ model = "virt-v8";
+ device_type = "guest";
+
+ vcpus {
+ vcpu0 {
+ device_type = "vcpu";
+ compatible = "armv8,generic";
+ start_pc = <0x00000000>;
+ gentimer_virt_irq = <27>;
+ gentimer_phys_irq = <30>;
+ };
+
+ vcpu1 {
+ device_type = "vcpu";
+ compatible = "armv8,generic";
+ start_pc = <0x00000000>;
+ gentimer_virt_irq = <27>;
+ gentimer_phys_irq = <30>;
+ };
+ };
+
+ aspace {
+ guest_irq_count = <2048>;
+
+ mem0 {
+ manifest_type = "real";
+ address_type = "memory";
+ guest_physical_addr = <0x80000000>;
+ host_physical_addr = <0x00000000>; /* To be set by DTS including this file */
+ physical_size = <0x00000000>; /* To be set by DTS including this file */
+ device_type = "ram";
+ };
+
+ gic {
+ manifest_type = "virtual";
+ address_type = "memory";
+ guest_physical_addr = <0x2C000000>;
+ physical_size = <0x3000>;
+ device_type = "pic";
+ compatible = "vexpress,gicv2";
+ parent_irq = <6>;
+ };
+
+ nor_flash0 {
+ manifest_type = "real";
+ address_type = "memory";
+ guest_physical_addr = <0x00000000>;
+ host_physical_addr = <0x00000000>; /* To be set by DTS including this file */
+ physical_size = <0x00000000>; /* To be set by DTS including this file */
+ device_type = "rom";
+ };
+
+ virtio-net0 {
+ manifest_type = "virtual";
+ address_type = "memory";
+ device_type = "virtio";
+ compatible = "virtio,mmio";
+ virtio_type = <1>;
+ guest_physical_addr = <0x40200000>;
+ physical_size = <0x1000>;
+ switch = ""; /* To be set by DTS including this file */
+ interrupts = <40>;
+ };
+
+ virtio-blk0 {
+ manifest_type = "virtual";
+ address_type = "memory";
+ device_type = "virtio";
+ compatible = "virtio,mmio";
+ virtio_type = <2>;
+ guest_physical_addr = <0x40400000>;
+ physical_size = <0x1000>;
+ blkdev = ""; /* To be set by DTS including this file */
+ interrupts = <41>;
+ };
+
+ virtio-con0 {
+ manifest_type = "virtual";
+ address_type = "memory";
+ device_type = "virtio";
+ compatible = "virtio,mmio";
+ virtio_type = <3>;
+ guest_physical_addr = <0x40600000>;
+ physical_size = <0x1000>;
+ interrupts = <42>;
+ };
+ };
+ };
+ };
+};
--
1.7.9.5

Sukanto Ghosh

unread,
Sep 15, 2013, 4:08:46 AM9/15/13
to an...@brainfault.org, Sukanto Ghosh, xvisor...@googlegroups.com
With the new arm64 (or armv8) port we try to implement unified
Xvisor binary for all arm64 boards.

To achieve this we introduce generic armv8 board which is fully
device tree based (i.e. DTB-based) similar to linux arm64 port.

The only constraint with generic armv8 board support is that
actual HW board on which Xvisor runs should have GICv2 or higher
as PIC.

Signed-off-by: Sukanto Ghosh <sukant...@gmail.com>
---
arch/arm/board/generic-v8/brd_defterm.c | 93 ++++++
arch/arm/board/generic-v8/brd_main.c | 130 ++++++++
arch/arm/board/generic-v8/brd_smp.c | 232 ++++++++++++++
.../dts/foundation-v8/foundation-v8.dtsi | 122 ++++++++
.../dts/foundation-v8/one_guest_virt_v8.dts | 41 +++
arch/arm/board/generic-v8/dts/skeleton.dts | 24 ++
arch/arm/board/generic-v8/include/arch_host_irq.h | 61 ++++
arch/arm/board/generic-v8/include/gic_config.h | 29 ++
arch/arm/board/generic-v8/objects.mk | 30 ++
arch/arm/board/generic-v8/openconf.cfg | 31 ++
arch/arm/board/openconf.cfg | 21 ++
arch/arm/configs/generic-v8-defconfig | 322 ++++++++++++++++++++
12 files changed, 1136 insertions(+)
create mode 100644 arch/arm/board/generic-v8/brd_defterm.c
create mode 100644 arch/arm/board/generic-v8/brd_main.c
create mode 100644 arch/arm/board/generic-v8/brd_smp.c
create mode 100644 arch/arm/board/generic-v8/dts/foundation-v8/foundation-v8.dtsi
create mode 100644 arch/arm/board/generic-v8/dts/foundation-v8/one_guest_virt_v8.dts
create mode 100644 arch/arm/board/generic-v8/dts/skeleton.dts
create mode 100644 arch/arm/board/generic-v8/include/arch_host_irq.h
create mode 100644 arch/arm/board/generic-v8/include/gic_config.h
create mode 100644 arch/arm/board/generic-v8/objects.mk
create mode 100644 arch/arm/board/generic-v8/openconf.cfg
create mode 100644 arch/arm/configs/generic-v8-defconfig

diff --git a/arch/arm/board/generic-v8/brd_defterm.c b/arch/arm/board/generic-v8/brd_defterm.c
new file mode 100644
index 0000000..727ac95
--- /dev/null
+++ b/arch/arm/board/generic-v8/brd_defterm.c
@@ -0,0 +1,93 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file brd_defterm.c
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief default serial terminal
+ */
+
+#include <vmm_error.h>
+#include <vmm_types.h>
+#include <vmm_compiler.h>
+#include <vmm_devtree.h>
+#include <vmm_host_aspace.h>
+#include <drv/pl011.h>
+
+static virtual_addr_t v2m_defterm_base;
+static u32 v2m_defterm_inclk;
+static u32 v2m_defterm_baud;
+
+int arch_defterm_putc(u8 ch)
+{
+ if (!pl011_lowlevel_can_putc(v2m_defterm_base)) {
+ return VMM_EFAIL;
+ }
+ pl011_lowlevel_putc(v2m_defterm_base, ch);
+ return VMM_OK;
+}
+
+int arch_defterm_getc(u8 * ch)
+{
+ if (!pl011_lowlevel_can_getc(v2m_defterm_base)) {
+ return VMM_EFAIL;
+ }
+ *ch = pl011_lowlevel_getc(v2m_defterm_base);
+ return VMM_OK;
+}
+
+int __init arch_defterm_init(void)
+{
+ int rc;
+ u32 *val;
+ const char *attr;
+ struct vmm_devtree_node *node;
+
+ node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
+ VMM_DEVTREE_CHOSEN_NODE_NAME);
+ if (!node) {
+ return VMM_ENODEV;
+ }
+
+ attr = vmm_devtree_attrval(node, VMM_DEVTREE_CONSOLE_ATTR_NAME);
+ if (!attr) {
+ return VMM_ENODEV;
+ }
+
+ node = vmm_devtree_getnode(attr);
+ if (!node) {
+ return VMM_ENODEV;
+ }
+
+ rc = vmm_devtree_regmap(node, &v2m_defterm_base, 0);
+ if (rc) {
+ return rc;
+ }
+
+ rc = vmm_devtree_clock_frequency(node, &v2m_defterm_inclk);
+ if (rc) {
+ return rc;
+ }
+
+ val = vmm_devtree_attrval(node, "baudrate");
+ v2m_defterm_baud = (val) ? *val : 115200;
+
+ pl011_lowlevel_init(v2m_defterm_base,
+ v2m_defterm_baud,
+ v2m_defterm_inclk);
+ return VMM_OK;
+}
diff --git a/arch/arm/board/generic-v8/brd_main.c b/arch/arm/board/generic-v8/brd_main.c
new file mode 100644
index 0000000..dfef9e5
--- /dev/null
+++ b/arch/arm/board/generic-v8/brd_main.c
@@ -0,0 +1,130 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file brd_main.c
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief main source file for board specific code
+ */
+
+#include <vmm_error.h>
+#include <vmm_smp.h>
+#include <vmm_spinlocks.h>
+#include <vmm_devtree.h>
+#include <vmm_devdrv.h>
+#include <vmm_host_io.h>
+#include <vmm_host_aspace.h>
+#include <vmm_stdio.h>
+#include <arch_board.h>
+#include <arch_timer.h>
+#include <generic_timer.h>
+
+/*
+ * Reset & Shutdown
+ */
+
+int arch_board_reset(void)
+{
+ /* FIXME: To be implemented. */
+ vmm_printf("%s: not implemented\n", __func__);
+ return VMM_EFAIL;
+}
+
+/*
+ * Print board information
+ */
+
+void arch_board_print_info(struct vmm_chardev *cdev)
+{
+ /* FIXME: To be implemented. */
+}
+
+int arch_board_shutdown(void)
+{
+ /* FIXME: To be implemented. */
+ vmm_printf("%s: not implemented\n", __func__);
+ return VMM_EFAIL;
+}
+
+/*
+ * Initialization functions
+ */
+
+int __init arch_board_early_init(void)
+{
+ /* Host aspace, Heap, Device tree, and Host IRQ available.
+ *
+ * Do necessary early stuff like:
+ * iomapping devices,
+ * SOC clocking init,
+ * Setting-up system data in device tree nodes,
+ * ....
+ */
+
+ return VMM_OK;
+}
+
+int __init arch_clocksource_init(void)
+{
+ int rc;
+
+ /* Initialize generic timer as clock source */
+ rc = generic_timer_clocksource_init();
+ if (rc) {
+ vmm_printf("%s: generic clocksource init failed (error %d)\n",
+ __func__, rc);
+ }
+
+ return VMM_OK;
+}
+
+int __cpuinit arch_clockchip_init(void)
+{
+ int rc;
+
+ /* Initialize generic timer as clock source */
+ rc = generic_timer_clockchip_init();
+ if (rc) {
+ vmm_printf("%s: generic clockchip init failed (error %d)\n",
+ __func__, rc);
+ }
+
+ return VMM_OK;
+}
+
+int __init arch_board_final_init(void)
+{
+ int rc;
+ struct vmm_devtree_node *node;
+
+ /* All VMM API's are available here */
+ /* We can register a Board specific resource here */
+
+ /* Find simple-bus node */
+ node = vmm_devtree_find_compatible(NULL, NULL, "simple-bus");
+ if (!node) {
+ return VMM_ENODEV;
+ }
+
+ /* Do probing using device driver framework */
+ rc = vmm_devdrv_probe(node);
+ if (rc) {
+ return rc;
+ }
+
+ return VMM_OK;
+}
diff --git a/arch/arm/board/generic-v8/brd_smp.c b/arch/arm/board/generic-v8/brd_smp.c
new file mode 100644
index 0000000..b967b62
--- /dev/null
+++ b/arch/arm/board/generic-v8/brd_smp.c
@@ -0,0 +1,232 @@
+/**
+ * Copyright (c) 2012 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file brd_smp.c
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief board specific smp functions
+ */
+
+#include <vmm_error.h>
+#include <vmm_types.h>
+#include <vmm_smp.h>
+#include <vmm_stdio.h>
+#include <vmm_delay.h>
+#include <vmm_cache.h>
+#include <vmm_host_io.h>
+#include <vmm_host_irq.h>
+#include <vmm_host_aspace.h>
+#include <vmm_compiler.h>
+#include <libs/libfdt.h>
+#include <libs/stringlib.h>
+#include <smp_scu.h>
+#include <gic.h>
+
+#define MPIDR_HWID_BITMASK 0xff00ffffffLU
+
+int __init arch_smp_init_cpus(void)
+{
+ int i = 0;
+ const char *aval;
+ struct dlist *l;
+ struct vmm_devtree_node *node, *cnode;
+
+ node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
+ "cpus");
+ if (!node) {
+ return VMM_EFAIL;
+ }
+
+ list_for_each(l, &node->child_list) {
+ cnode = list_entry(l, struct vmm_devtree_node, head);
+ aval = vmm_devtree_attrval(cnode,
+ VMM_DEVTREE_DEVICE_TYPE_ATTR_NAME);
+ if (aval &&
+ !strcmp(aval, VMM_DEVTREE_DEVICE_TYPE_VAL_CPU)) {
+ vmm_set_cpu_possible(i, TRUE);
+ i++;
+ }
+ }
+
+ return VMM_OK;
+}
+
+extern u8 _start_secondary;
+volatile unsigned long secondary_holding_pen_release;
+
+/*
+ * Write secondary_holding_pen_release in a way that is guaranteed to be
+ * visible to all observers, irrespective of whether they're taking part
+ * in coherency or not. This is necessary for the hotplug code to work
+ * reliably.
+ */
+static void write_pen_release(u64 val)
+{
+ virtual_addr_t start = (virtual_addr_t)&secondary_holding_pen_release;
+ unsigned long size = sizeof(secondary_holding_pen_release);
+
+ secondary_holding_pen_release = val;
+ vmm_flush_dcache_range(start, start + size);
+}
+
+int __init arch_smp_prepare_cpus(unsigned int max_cpus)
+{
+ int cpu = 0, rc = VMM_OK;
+ struct dlist *l;
+ struct vmm_devtree_node *node, *cnode;
+
+ node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
+ "cpus");
+ if (!node) {
+ return VMM_EFAIL;
+ }
+
+ list_for_each(l, &node->child_list) {
+ physical_addr_t *release_addr_pa;
+ virtual_addr_t release_addr_va;
+ physical_addr_t secondary_jump_addr;
+ const char *enable_method;
+
+ cnode = list_entry(l, struct vmm_devtree_node, head);
+
+ if (cpu >= max_cpus) {
+ break;
+ }
+
+ enable_method = vmm_devtree_attrval(cnode,
+ VMM_DEVTREE_ENABLE_METHOD_ATTR_NAME);
+ if (!enable_method) {
+ vmm_printf("%s: enable-method not set\n", cnode->name);
+ continue;
+ }
+
+ /* We currently support only the "spin-table" enable-method. */
+ if (strcmp(enable_method, "spin-table")) {
+ vmm_printf("%s: enable-method \'%s\' not supported\n",
+ cnode->name, enable_method);
+ continue;
+ }
+
+ release_addr_pa = vmm_devtree_attrval(cnode,
+ VMM_DEVTREE_CPU_RELEASE_ADDR_ATTR_NAME);
+ if (!release_addr_pa) {
+ vmm_printf("%s: cpu-release-addr not set\n", cnode->name);
+ continue;
+ }
+
+ release_addr_va = vmm_host_iomap(*release_addr_pa,
+ sizeof(physical_addr_t));
+ rc = vmm_host_va2pa((virtual_addr_t)&_start_secondary,
+ &secondary_jump_addr);
+ if (rc) {
+ vmm_printf("%s: failed to iomap cpu-release-addr\n",
+ cnode->name);
+ continue;
+ }
+ vmm_writeq(secondary_jump_addr, (void *)release_addr_va);
+ vmm_host_iounmap((virtual_addr_t)release_addr_va,
+ sizeof(physical_addr_t));
+
+ /* Send an event to wake up the secondary CPU. */
+ asm volatile ("sev");
+
+ vmm_set_cpu_present(cpu, TRUE);
+
+ cpu++;
+ }
+
+ return VMM_OK;
+}
+
+int __init arch_smp_start_cpu(u32 cpu)
+{
+ int i = 0;
+ struct dlist *l;
+ physical_addr_t hwid;
+ struct vmm_devtree_node *node, *cnode;
+
+ node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
+ "cpus");
+ if (!node) {
+ return VMM_EFAIL;
+ }
+
+ list_for_each(l, &node->child_list) {
+ if (i++ == cpu) {
+ cnode = list_entry(l, struct vmm_devtree_node, head);
+ break;
+ }
+ }
+
+ if (vmm_devtree_regaddr(cnode, &hwid, 0)) {
+ return VMM_EFAIL;
+ }
+
+ /*
+ * Non affinity bits must be set to 0 in the DT
+ */
+ if (hwid & ~MPIDR_HWID_BITMASK) {
+ vmm_printf("%s: invalid mpidr value in reg property\n",
+ cnode->name);
+ return VMM_EFAIL;
+ }
+
+ write_pen_release(hwid);
+ asm volatile ("sev");
+ vmm_udelay(1000);
+
+ return VMM_OK;
+}
+
+static vmm_irq_return_t smp_ipi_handler(int irq_no, void *dev)
+{
+ /* Call core code to handle IPI1 */
+ vmm_smp_ipi_exec();
+
+ return VMM_IRQ_HANDLED;
+}
+
+void arch_smp_ipi_trigger(const struct vmm_cpumask *dest)
+{
+ /* Send IPI1 to other cores */
+ gic_raise_softirq(dest, 1);
+}
+
+int __cpuinit arch_smp_ipi_init(void)
+{
+ int rc;
+ u32 cpu = vmm_smp_processor_id();
+
+ if (!cpu) {
+ /* Register IPI1 interrupt handler */
+ rc = vmm_host_irq_register(1, "IPI1", &smp_ipi_handler, NULL);
+ if (rc) {
+ return rc;
+ }
+
+ /* Mark IPI1 interrupt as per-cpu */
+ rc = vmm_host_irq_mark_per_cpu(1);
+ if (rc) {
+ return rc;
+ }
+ }
+
+ /* Explicitly enable IPI1 interrupt */
+ gic_enable_ppi(1);
+
+ return VMM_OK;
+}
diff --git a/arch/arm/board/generic-v8/dts/foundation-v8/foundation-v8.dtsi b/arch/arm/board/generic-v8/dts/foundation-v8/foundation-v8.dtsi
new file mode 100644
index 0000000..60eec29
--- /dev/null
+++ b/arch/arm/board/generic-v8/dts/foundation-v8/foundation-v8.dtsi
@@ -0,0 +1,122 @@
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ model = "foundation-v8";
+
+ chosen { };
+ aliases { };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu0 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ model = "Cortex-A57";
+ reg = <0x0 0x0>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x84000000>;
+ };
+
+ cpu1 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ model = "Cortex-A57";
+ reg = <0x0 0x1>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x84000000>;
+ };
+
+ cpu2 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ model = "Cortex-A57";
+ reg = <0x0 0x2>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x84000000>;
+ };
+
+ cpu3 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ model = "Cortex-A57";
+ reg = <0x0 0x3>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x84000000>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0x0 0x10000000>; /* 256 MB */
+ };
+
+ gic { /* Generic Interrupt Controller */
+ device_type = "pic";
+ compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+ reg = <0x0 0x2C001000 0x0 0x1000 /* Dist Interface */
+ 0x0 0x2C002000 0x0 0x1000 /* CPU Interface */
+ 0x0 0x2C004000 0x0 0x2000 /* VCPU Control Interface */
+ 0x0 0x2C006000 0x0 0x2000>; /* VCPU Interface */
+ irq_start = <16>;
+ interrupts = <25>; /* VGIC Maintanence IRQ */
+ };
+
+ gen-timer { /* Generic Timer */
+ device_type = "timer";
+ compatible = "arm,armv8-timer";
+ clock-frequency = <100000000>;
+ interrupts = <26 30 27>;
+ };
+
+ motherboard {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+
+ eth0 {
+ device_type = "nic";
+ compatible = "smc91x";
+ reg = <0x1A000000 0x10000>;
+ interrupts = <47>;
+ switch = "netbridge0";
+ };
+
+ sysreg { /* System Registers */
+ device_type = "sys";
+ compatible = "arm,vexpress-sysreg";
+ reg = <0x1C010000 0x1000>;
+ };
+
+ SERIAL0: uart0 {
+ device_type = "serial";
+ compatible = "arm,pl011";
+ reg = <0x1C090000 0x1000>;
+ clock-frequency = <24000000>;
+ baudrate = <115200>;
+ interrupts = <37>;
+ };
+ };
+
+ vmm {
+ net {
+ netbridge0 {
+ device_type = "netswitch";
+ compatible = "bridge";
+ };
+ };
+ };
+
+ /* Empty guests node */
+ guests {
+ };
+};
+
+/* Add guest templates */
+/include/ "../../../common/guests/realview-pb-a8.dtsi"
+/include/ "../../../common/guests/vexpress-a9x2.dtsi"
+/include/ "../../../common/guests/vexpress-a15x2.dtsi"
+/include/ "../../../common/guests/virt-v8x2.dtsi"
+
diff --git a/arch/arm/board/generic-v8/dts/foundation-v8/one_guest_virt_v8.dts b/arch/arm/board/generic-v8/dts/foundation-v8/one_guest_virt_v8.dts
new file mode 100644
index 0000000..12dca86
--- /dev/null
+++ b/arch/arm/board/generic-v8/dts/foundation-v8/one_guest_virt_v8.dts
@@ -0,0 +1,41 @@
+
+/dts-v1/;
+
+/include/ "foundation-v8.dtsi"
+
+/ {
+ chosen {
+ console = &SERIAL0;
+ bootcmd = /* Copy guest0 device tree from templates */
+ "devtree node copy /guests guest0 /templates/virt-v8x2",
+
+ /* Update guest0 memory regions */
+ "devtree attr set /guests/guest0/aspace/mem0 host_physical_addr physaddr 0x82000000",
+ "devtree attr set /guests/guest0/aspace/mem0 physical_size physsize 0x06000000",
+
+ /* Update guest0 flash region */
+ "devtree attr set /guests/guest0/aspace/nor_flash0 host_physical_addr physaddr 0x81000000",
+ "devtree attr set /guests/guest0/aspace/nor_flash0 physical_size physsize 0x01000000",
+
+ /* Connect guest0/virtio-net0 netport to netbridge0 */
+ "devtree attr set /guests/guest0/aspace/virtio-net0 switch string netbridge0",
+
+ /* Replace guest0 GIC emulator with vGIC emulator */
+ "devtree node copy /guests/guest0/aspace gic_cpu /guests/guest0/aspace/gic",
+ "devtree attr set /guests/guest0/aspace/gic_cpu manifest_type string real",
+ "devtree attr set /guests/guest0/aspace/gic_cpu guest_physical_addr physaddr 0x2C002000",
+ "devtree attr set /guests/guest0/aspace/gic_cpu host_physical_addr physaddr 0x2C006000",
+ "devtree attr set /guests/guest0/aspace/gic_cpu physical_size physsize 0x1000",
+ "devtree attr del /guests/guest0/aspace/gic_cpu compatible",
+ "devtree attr del /guests/guest0/aspace/gic_cpu parent_irq",
+ "devtree node copy /guests/guest0/aspace gic_dist /guests/guest0/aspace/gic",
+ "devtree attr set /guests/guest0/aspace/gic_dist guest_physical_addr physaddr 0x2C001000",
+ "devtree attr set /guests/guest0/aspace/gic_dist physical_size physsize 0x1000",
+ "devtree attr set /guests/guest0/aspace/gic_dist compatible string arm,vgic",
+ "devtree node del /guests/guest0/aspace/gic",
+
+ /* Create guest0 */
+ "guest create guest0";
+ };
+};
+
diff --git a/arch/arm/board/generic-v8/dts/skeleton.dts b/arch/arm/board/generic-v8/dts/skeleton.dts
new file mode 100644
index 0000000..1738cec
--- /dev/null
+++ b/arch/arm/board/generic-v8/dts/skeleton.dts
@@ -0,0 +1,24 @@
+
+/dts-v1/;
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ model = "skeleton-armv8";
+
+ chosen { };
+ aliases { };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x0 0x0 0x0>;
+ };
+
+ vmm {
+ };
+
+ /* Empty guests node */
+ guests {
+ };
+};
+
diff --git a/arch/arm/board/generic-v8/include/arch_host_irq.h b/arch/arm/board/generic-v8/include/arch_host_irq.h
new file mode 100644
index 0000000..1ebc5be
--- /dev/null
+++ b/arch/arm/board/generic-v8/include/arch_host_irq.h
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arch_host_irq.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief board specific host irq functions
+ */
+#ifndef _ARCH_HOST_IRQ_H__
+#define _ARCH_HOST_IRQ_H__
+
+#include <vmm_types.h>
+#include <vmm_smp.h>
+#include <gic.h>
+
+#define ARCH_HOST_IRQ_COUNT GIC_NR_IRQS
+
+/* Get current active host irq */
+static inline u32 arch_host_irq_active(u32 cpu_irq_no)
+{
+ return gic_active_irq(0);
+}
+
+/* Initialize board specifig host irq hardware (i.e PIC) */
+static inline int arch_host_irq_init(void)
+{
+ int rc;
+ u32 cpu = vmm_smp_processor_id();
+ struct vmm_devtree_node *node;
+
+ if (!cpu) {
+ node = vmm_devtree_find_compatible(NULL, NULL,
+ "arm,cortex-a9-gic");
+ if (!node) {
+ return VMM_ENODEV;
+ }
+
+ rc = gic_devtree_init(node, NULL);
+ } else {
+ gic_secondary_init(0);
+ rc = VMM_OK;
+ }
+
+ return rc;
+}
+
+#endif
diff --git a/arch/arm/board/generic-v8/include/gic_config.h b/arch/arm/board/generic-v8/include/gic_config.h
new file mode 100644
index 0000000..7e104e6
--- /dev/null
+++ b/arch/arm/board/generic-v8/include/gic_config.h
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2012 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file gic_config.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief GIC Configuration Header
+ */
+#ifndef __GIC_CONFIG_H__
+#define __GIC_CONFIG_H__
+
+#define GIC_NR_IRQS 256
+#define GIC_MAX_NR 1
+
+#endif /* __GIC_CONFIG_H__ */
diff --git a/arch/arm/board/generic-v8/objects.mk b/arch/arm/board/generic-v8/objects.mk
new file mode 100644
index 0000000..dc2545b
--- /dev/null
+++ b/arch/arm/board/generic-v8/objects.mk
@@ -0,0 +1,30 @@
+#/**
+# Copyright (c) 2013 Sukanto Ghosh.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# @file objects.mk
+# @author Sukanto Ghosh (sukant...@gmail.com)
+# @brief list of Generic ARMv8 board objects.
+# */
+
+board-objs-y+=brd_defterm.o
+board-objs-y+=brd_main.o
+board-objs-$(CONFIG_SMP)+=brd_smp.o
+board-objs-y+=dts/skeleton.o
+
+board-dtbs-$(CONFIG_FOUNDATION_V8_ONE_GUEST_VIRT_V8_DTS)+=dts/foundation-v8/one_guest_virt_v8.dtb
+
diff --git a/arch/arm/board/generic-v8/openconf.cfg b/arch/arm/board/generic-v8/openconf.cfg
new file mode 100644
index 0000000..086a2a1
--- /dev/null
+++ b/arch/arm/board/generic-v8/openconf.cfg
@@ -0,0 +1,31 @@
+#/**
+# Copyright (c) 2013 Sukanto Ghosh.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# @file openconf.cfg
+# @author Sukanto Ghosh (sukant...@gmail.com)
+# @brief Board config file for Generic ARMv8 board
+# */
+
+menu "Generic-v8 Options"
+
+config CONFIG_FOUNDATION_V8_ONE_GUEST_VIRT_V8_DTS
+ bool "1x virt-v8 guest DTS"
+ help
+ This option enables DTS for one virt-v8 paravirtualized guest
+
+endmenu
diff --git a/arch/arm/board/openconf.cfg b/arch/arm/board/openconf.cfg
index 6ed8d75..8f5d081 100644
--- a/arch/arm/board/openconf.cfg
+++ b/arch/arm/board/openconf.cfg
@@ -144,6 +144,17 @@ if CONFIG_CPU_CORTEX_A9
Exynos4 SOC family from Samsung
endif

+if CONFIG_CPU_GENERIC_V8
+ config CONFIG_BOARD_GENERIC_V8
+ bool "generic-v8"
+ select CONFIG_ARM_GIC
+ select CONFIG_ARM_GENERIC_TIMER
+ select CONFIG_SERIAL
+ select CONFIG_SERIAL_PL01X
+ help
+ Generic ARMv8 board.
+endif
+
endchoice

if CONFIG_BOARD_VERSATILE
@@ -236,4 +247,14 @@ source "arch/arm/board/exynos4/openconf.cfg"

endif

+if CONFIG_BOARD_GENERIC_V8
+
+config CONFIG_BOARD
+ string
+ default "generic-v8"
+
+source "arch/arm/board/generic-v8/openconf.cfg"
+
+endif
+
source "arch/arm/board/common/openconf.cfg"
diff --git a/arch/arm/configs/generic-v8-defconfig b/arch/arm/configs/generic-v8-defconfig
new file mode 100644
index 0000000..e987d8d
--- /dev/null
+++ b/arch/arm/configs/generic-v8-defconfig
@@ -0,0 +1,322 @@
+#
+# Automatically generated make config: don't edit
+# Project: Xvisor (eXtensible Versatile hypervISOR)
+# Version: 0.2.2
+# Sat Aug 24 21:09:30 2013
+#
+CONFIG_SMP=y
+CONFIG_ARCH_ARM=y
+# CONFIG_ARCH_x86 is not set
+CONFIG_ARCH="arm"
+# CONFIG_CPU_ARM926T is not set
+# CONFIG_CPU_ARM11 is not set
+# CONFIG_CPU_ARM11MP is not set
+# CONFIG_CPU_CORTEX_A8 is not set
+# CONFIG_CPU_CORTEX_A9 is not set
+# CONFIG_CPU_CORTEX_A15 is not set
+CONFIG_CPU_GENERIC_V8=y
+CONFIG_CPU_COUNT=4
+# CONFIG_ARMV5 is not set
+# CONFIG_ARMV6 is not set
+# CONFIG_ARMV6K is not set
+# CONFIG_ARMV7A is not set
+# CONFIG_ARMV7A_VE is not set
+CONFIG_ARMV8=y
+# CONFIG_ARM32 is not set
+# CONFIG_ARM32VE is not set
+CONFIG_ARM64=y
+
+#
+# ARM Options
+#
+CONFIG_VAPOOL_SIZE_MB=16
+CONFIG_ARM_VGIC=y
+CONFIG_ARM_GENERIC_TIMER=y
+CONFIG_ARM_MMU_LPAE=y
+CONFIG_ARM_MAX_DTB_SIZE=0xC000
+CONFIG_CPU="arm64"
+CONFIG_CPU_LE=y
+# CONFIG_CPU_BE is not set
+CONFIG_64BIT=y
+CONFIG_ARM64_STACKTRACE=y
+# CONFIG_BOARD_VERSATILE is not set
+# CONFIG_BOARD_IMX25 is not set
+# CONFIG_BOARD_BCM2835 is not set
+# CONFIG_BOARD_IMX31 is not set
+# CONFIG_BOARD_REALVIEW is not set
+# CONFIG_BOARD_OMAP3 is not set
+# CONFIG_BOARD_SUN4I is not set
+# CONFIG_BOARD_VEXPRESS is not set
+# CONFIG_BOARD_EXYNOS4 is not set
+CONFIG_BOARD_GENERIC_V8=y
+CONFIG_BOARD="generic-v8"
+
+#
+# Generic-V8 Options
+#
+# CONFIG_FOUNDATION_V8_SKELETON_DTS is not set
+CONFIG_FOUNDATION_V8_ONE_GUEST_VIRT_V8_DTS=y
+# CONFIG_ARM_VIC is not set
+CONFIG_ARM_GIC=y
+# CONFIG_ARM_TIMER_SP804 is not set
+# CONFIG_ARM_TWD is not set
+# CONFIG_ICST is not set
+# CONFIG_ARM_SCU is not set
+# CONFIG_VERSATILE_CLOCK is not set
+# CONFIG_VERSATILE_CLCD is not set
+# CONFIG_OMAP is not set
+# CONFIG_SAMSUNG_MCT is not set
+# CONFIG_SAMSUNG_MCT_LOCAL_TIMERS is not set
+# CONFIG_SUNXI is not set
+# CONFIG_FREESCALE_AVIC is not set
+# CONFIG_FREESCALE_EPIT is not set
+
+#
+# Hypervisor Options
+#
+
+#
+# General Configuration
+#
+MODULES=y
+# CONFIG_VERBOSE_MODE is not set
+CONFIG_BANNER_NONE=y
+# CONFIG_BANNER_BANNER4 is not set
+# CONFIG_BANNER_COLOSSAL is not set
+# CONFIG_BANNER_O8 is not set
+# CONFIG_BANNER_ROMAN is not set
+CONFIG_IRQ_STACK_SIZE=4096
+CONFIG_THREAD_STACK_SIZE=8192
+CONFIG_MAX_VCPU_COUNT=64
+CONFIG_MAX_GUEST_COUNT=16
+CONFIG_VGPA2REG_CACHE_SIZE=8
+CONFIG_WFI_TIMEOUT_SECS=10
+# CONFIG_PROFILE is not set
+
+#
+# Heap Configuration
+#
+CONFIG_HEAP_SIZE_MB=4
+CONFIG_HEAP_BUDDY=y
+
+#
+# Scheduler Configuration
+#
+# CONFIG_SCHEDALGO_RR is not set
+CONFIG_SCHEDALGO_PRR=y
+# CONFIG_TSLICE_1MS is not set
+CONFIG_TSLICE_10MS=y
+# CONFIG_TSLICE_100MS is not set
+CONFIG_TSLICE_MS=10
+
+#
+# Load Balancer Configuration
+#
+CONFIG_LOADBAL_CRUDE=y
+
+#
+# Device Support
+#
+CONFIG_RTC=y
+CONFIG_INPUT=y
+# CONFIG_FB is not set
+CONFIG_BLOCK=y
+CONFIG_BLOCKPART=y
+CONFIG_BLOCKPART_DOS=y
+CONFIG_NET=y
+CONFIG_NET_MBUF_POOL_SIZE=2048
+CONFIG_NET_MBUF_EXT_POOL_SIZE_KB=256
+
+#
+# Command Options
+#
+CONFIG_CMD_VERSION=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_SHUTDOWN=y
+CONFIG_CMD_HOST=y
+CONFIG_CMD_DEVTREE=y
+CONFIG_CMD_VCPU=y
+CONFIG_CMD_GUEST=y
+CONFIG_CMD_MEMORY=y
+CONFIG_CMD_THREAD=y
+CONFIG_CMD_CHARDEV=y
+CONFIG_CMD_VSERIAL=y
+CONFIG_CMD_STDIO=y
+CONFIG_CMD_HEAP=y
+CONFIG_CMD_WALLCLOCK=y
+CONFIG_CMD_MODULE=y
+CONFIG_CMD_RTCDEV=y
+CONFIG_CMD_INPUT=y
+CONFIG_CMD_BLOCKDEV=y
+CONFIG_CMD_NET=y
+
+#
+# Daemon Options
+#
+CONFIG_MTERM=y
+CONFIG_MTERM_CMD_WIDTH=256
+CONFIG_MTERM_HISTORY=y
+CONFIG_MTERM_HISTORY_SIZE=10
+
+#
+# Library Options
+#
+
+#
+# Network Stack Options
+#
+# CONFIG_NET_STACK is not set
+CONFIG_NET_STACK_LWIP=y
+
+#
+# Virtual FileSystem Options
+#
+# CONFIG_VFS is not set
+
+#
+# Device Drivers
+#
+
+#
+# Serial Port Drivers
+#
+CONFIG_SERIAL=y
+# CONFIG_SERIAL_8250_UART is not set
+# CONFIG_SERIAL_OMAP_UART is not set
+CONFIG_SERIAL_PL01X=y
+# CONFIG_SERIAL_SAMSUNG is not set
+# CONFIG_SERIAL_IMX is not set
+
+#
+# RTC Drivers
+#
+# CONFIG_RTC_PL031 is not set
+# CONFIG_RTC_S3C is not set
+
+#
+# Block Drivers
+#
+# CONFIG_BLOCK_RBD is not set
+
+#
+# MMC/SD/SDIO drivers
+#
+# CONFIG_MMC is not set
+
+#
+# USB drivers
+#
+# CONFIG_USB is not set
+
+#
+# Input Device Support
+#
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+
+#
+# Network Drivers
+#
+CONFIG_NET_DRIVERS=y
+# CONFIG_ETHER_SMSC_911x is not set
+CONFIG_ETHER_SMSC_91x=y
+
+#
+# Clock Drivers
+#
+# CONFIG_CLKDEV_LOOKUP is not set
+
+#
+# Device Emulators
+#
+
+#
+# VirtIO Support
+#
+CONFIG_EMU_VIRTIO=y
+CONFIG_EMU_VIRTIO_MMIO=y
+
+#
+# System Emulators
+#
+CONFIG_EMU_SYS=y
+CONFIG_EMU_SYS_ARM_SYSREGS=y
+CONFIG_EMU_SYS_SP810=y
+
+#
+# PIC Emulators
+#
+CONFIG_EMU_PIC=y
+CONFIG_EMU_PIC_GIC=y
+CONFIG_EMU_PIC_PL190=y
+
+#
+# Network Interface Controller Emulators
+#
+CONFIG_EMU_NET=y
+CONFIG_EMU_NET_LAN9118=y
+CONFIG_EMU_NET_SMC91C111=y
+CONFIG_EMU_NET_VIRTIO=y
+
+#
+# Block Device Emulators
+#
+CONFIG_EMU_BLOCK=y
+CONFIG_EMU_BLOCK_VIRTIO=y
+
+#
+# Console Emulators
+#
+CONFIG_EMU_CONSOLE=y
+CONFIG_EMU_CONSOLE_VIRTIO=y
+
+#
+# Timer Emulators
+#
+CONFIG_EMU_TIMER=y
+CONFIG_EMU_TIMER_SP804=y
+CONFIG_EMU_TIMER_ARM_MPTIMER=y
+
+#
+# Serial Port Emulators
+#
+CONFIG_EMU_SERIAL=y
+CONFIG_EMU_SERIAL_PL011=y
+
+#
+# Real-Time Clock Emulators
+#
+CONFIG_EMU_RTC=y
+CONFIG_EMU_RTC_PL031=y
+
+#
+# Cache Controller Emulators
+#
+CONFIG_EMU_CACHE_L2X0=y
+
+#
+# GPIO Emulators
+#
+CONFIG_EMU_GPIO=y
+CONFIG_EMU_GPIO_PL061=y
+
+#
+# Miscellaneous Emulators
+#
+CONFIG_EMU_MISC_ZERO=y
+CONFIG_EMU_MISC_ARM11MPCORE=y
+CONFIG_EMU_MISC_A9MPCORE=y
+
+#
+# Tool Options
+#
+# CONFIG_CPATCH is not set
+# CONFIG_BBFLASH is not set
--
1.7.9.5

Sukanto Ghosh

unread,
Sep 15, 2013, 4:08:47 AM9/15/13
to an...@brainfault.org, Sukanto Ghosh, xvisor...@googlegroups.com
This patch adds light-weight and minimalistic bootwrapper assembly
source for booting Xvisor on ARMv8 foundation models.

In simpler words, it is a minimalistic bootloader for launching
Xvisor on ARMv8 foundation model.

Signed-off-by: Sukanto Ghosh <sukant...@gmail.com>
---
docs/arm/foundation_v8_boot.S | 176 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 176 insertions(+)
create mode 100644 docs/arm/foundation_v8_boot.S

diff --git a/docs/arm/foundation_v8_boot.S b/docs/arm/foundation_v8_boot.S
new file mode 100644
index 0000000..0cadc37
--- /dev/null
+++ b/docs/arm/foundation_v8_boot.S
@@ -0,0 +1,176 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file foundation_v8_boot.S
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief light-weight boot-wrapper for ARMv8 foundation models
+ */
+
+#define PSR_MODE64_EL3 0x0000000c
+#define PSR_MODE64_EL2h 0x00000009
+#define PSR_MODE64_MASK 0x0000001f
+#define PSR_FIQ_DISABLED (1 << 6)
+#define PSR_IRQ_DISABLED (1 << 7)
+#define PSR_ASYNC_ABORT_DISABLED (1 << 8)
+#define PSR_MODE64_DEBUG_DISABLED (1 << 9)
+
+ /* Boot-wrapper entry point */
+ .section .text, "ax", %progbits
+ .globl _start
+_start:
+ /* Assume EL2 mode if not in EL3 mode */
+ mrs x0, CurrentEL
+ cmp x0, #PSR_MODE64_EL3
+ b.ne _start_el2
+
+ /* Setup EL3 security control register */
+ mov x0, #0x30 /* RES1 */
+ orr x0, x0, #(1 << 0) /* Non-secure EL1 */
+ orr x0, x0, #(1 << 8) /* HVC enable */
+ orr x0, x0, #(1 << 10) /* 64-bit EL2 */
+ msr scr_el3, x0
+
+ /* Disable copro. traps to EL3 */
+ msr cptr_el3, xzr
+
+ /* Setup generic timer cntfrq */
+ ldr x0, __gentimer_freq
+ msr cntfrq_el0, x0
+
+ /* GIC Distributor Interface Init */
+ mrs x4, mpidr_el1
+ and x4, x4, #0xffff /* CPU number */
+__gic_dist_init:
+ ldr x0, __gic_dist_base /* Dist GIC base */
+ mov x1, #0 /* non-0 cpus should at least */
+ cmp x4, xzr /* program IGROUP0 */
+ bne 1f
+ mov x1, #3 /* Enable group0 & group1 */
+ str w1, [x0, #0x00] /* Ctrl Register */
+ ldr w1, [x0, #0x04] /* Type Register */
+1: and x1, x1, #0x1f /* No. of IGROUPn registers */
+ add x2, x0, #0x080 /* IGROUP0 Register */
+ movn x3, #0 /* All interrupts to group-1 */
+2: str w3, [x2], #4
+ subs x1, x1, #1
+ bge 2b
+
+__gic_cpu_init:
+ /* GIC Secured CPU Interface Init */
+ ldr x0, __gic_cpu_base /* GIC CPU base */
+ mov x1, #0x80
+ str w1, [x0, #0x4] /* GIC CPU Priority Mask */
+ mov x1, #0x3 /* Enable group0 & group1 */
+ str w1, [x0] /* GIC CPU Control */
+
+ /* Clear EL2 control register */
+ msr sctlr_el2, xzr
+
+ /* Prepare the switch to EL2 mode from EL3 mode */
+ ldr x0, __start_el2 /* Return after mode switch */
+ mov x1, #0x3c9 /* EL2_SP1 | D | A | I | F */
+ msr elr_el3, x0
+ msr spsr_el3, x1
+ eret
+
+ .align 3
+__gentimer_freq:
+ .dword GENTIMER_FREQ
+__gic_dist_base:
+ .dword GIC_DIST_BASE
+__gic_cpu_base:
+ .dword GIC_CPU_BASE
+__start_el2:
+ .dword _start_el2
+
+_start_el2:
+ /* Skip secondary loop for Primary core */
+ mrs x4, mpidr_el1
+ ands x4, x4, #0xffff
+ beq __secondary_spin_skip
+
+ /* Copy the secondary_spin(start, end) to SPIN_LOOP_ADDR */
+ adr x0, __secondary_spin_code_start
+ adr x1, __secondary_spin_code_end
+ ldr x2, __secondary_spin_loc
+
+1: ldr x4, [x0], #8
+ str x4, [x2], #8
+ cmp x1, x0
+ bge 1b
+ adr x3, __secondary_spin
+ sub x3, x3, x0
+ add x3, x3, x2
+ br x3
+
+ .align 3
+__secondary_spin_code_start:
+ .dword 0x0
+__secondary_spin_loc:
+ .dword SPIN_LOOP_ADDR
+__leds_base:
+ .dword 0x1c010008
+#ifdef DTB
+__dtb_addr:
+ .dword dtb
+#endif
+
+__secondary_spin:
+ ldr x0, __secondary_spin_loc
+ sevl
+1: wfe
+ ldr x1, [x0]
+ cmp x1, xzr
+ beq 1b
+
+ ldr x15, __leds_base
+ mov w14, #1
+ str w14, [x15]
+
+ br x1
+__secondary_spin_code_end:
+
+__secondary_spin_skip:
+#ifdef DTB
+ /* if dtb provided load the address where we placed it */
+ ldr x0, __dtb_addr
+#else
+ /* deliberately put a non-8B aligned value to x0 skip dtb checking */
+ mov x0, #1
+#endif
+ /* Jump to input binary */
+ b input_bin
+
+#define str(s) #s
+#define stringify(s) str(s)
+
+ .section .text, "ax", %progbits
+#ifdef DTB
+ /* DTB binary */
+ .globl dtb
+ .balign 0x1000
+dtb:
+ .incbin stringify(DTB)
+#endif
+ /* Input binary containing OS images */
+ .globl input_bin
+ .balign 0x10000
+input_bin:
+ .incbin stringify(IMAGE)
+ .globl input_bin_end
+input_bin_end:
--
1.7.9.5

Sukanto Ghosh

unread,
Sep 15, 2013, 4:08:48 AM9/15/13
to an...@brainfault.org, Sukanto Ghosh, xvisor...@googlegroups.com
We need a Xvisor friendly firmware/bootloader for Virt-v8 guest which
will help us launch Guest OSes on Virt-v8 guest and also help us do
some testing of virtual CPU emulated by Xvisor ARM64.

This patch adds arm64 basic firmware for Virt-v8 Guest which is very
similar to arm32 basic firmware for VExpress-A15 Guest. This firmware
is capable of booting upstream arm64 linux kernel.

Signed-off-by: Sukanto Ghosh <sukant...@gmail.com>
---
64 files changed, 13905 insertions(+)
diff --git a/tests/arm64/common/README b/tests/arm64/common/README
new file mode 100644
index 0000000..c6f8f0d
--- /dev/null
+++ b/tests/arm64/common/README
@@ -0,0 +1,9 @@
+ ARM64 common code
+
+This directory contains directories:
+
+ 1. busybox - Busybox based root filesystem for all ARM64 systems
+ 2. basic - Common code for the basic firmware
+
+Please follow the README under specific platform directory for detailed
+steps to configure, compile and run.
diff --git a/tests/arm64/common/basic/Makefile.inc b/tests/arm64/common/basic/Makefile.inc
new file mode 100644
index 0000000..c54e880
--- /dev/null
+++ b/tests/arm64/common/basic/Makefile.inc
@@ -0,0 +1,134 @@
+#/**
+# Copyright (c) 2013 Sukanto Ghosh.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# @file Makefile.inc
+# @author Sukanto Ghosh (sukant...@gmail.com)
+# @brief common makefile to build basic firmware
+# */
+
+# Include top-level configuration file if present
+-include $(build_dir)/.config
+
+ifdef CROSS_COMPILE
+FW_CROSS_COMPILE=$(CROSS_COMPILE)
+else
+FW_CROSS_COMPILE=aarch64-none-linux-gnu-
+endif
+FW_CPPFLAGS=-I. -I$(common_dir) -DTEXT_START=$(board_text_start)
+FW_CFLAGS=$(FW_CPPFLAGS) -g -Wall -Werror -nostdlib -mgeneral-regs-only -mlittle-endian
+FW_ASFLAGS=$(FW_CPPFLAGS) -g -Wall -Werror -nostdlib -mgeneral-regs-only -mlittle-endian -D__ASSEMBLY__
+FW_LDFLAGS=$(FW_CFLAGS) -Wl,--build-id=none
+FW_AS=$(FW_CROSS_COMPILE)gcc
+FW_CC=$(FW_CROSS_COMPILE)gcc
+FW_CPP=$(FW_CROSS_COMPILE)cpp
+FW_OBJCOPY=$(FW_CROSS_COMPILE)objcopy
+
+FIRMWARE_OBJS=$(obj_dir)/arm_entry.o \
+ $(obj_dir)/arm_mmu.o
+
+FIRMWARE_OBJS+=$(board_objs)
+
+FIRMWARE_OBJS+=$(obj_dir)/arm_main.o \
+ $(obj_dir)/arm_heap.o \
+ $(obj_dir)/arm_irq.o \
+ $(obj_dir)/arm_stdio.o \
+ $(obj_dir)/arm_string.o \
+ $(obj_dir)/dhry_1.o \
+ $(obj_dir)/dhry_2.o \
+ $(obj_dir)/dhry_port.o \
+ $(obj_dir)/libfdt/fdt.o \
+ $(obj_dir)/libfdt/fdt_ro.o \
+ $(obj_dir)/libfdt/fdt_rw.o \
+ $(obj_dir)/libfdt/fdt_strerror.o \
+ $(obj_dir)/libfdt/fdt_support.o \
+ $(obj_dir)/libfdt/fdt_sw.o \
+ $(obj_dir)/libfdt/fdt_wip.o
+
+FIRMWARE_CPPFLAGS=-DFIRMWARE_BOOT
+FIRMWARE_CFLAGS=$(FIRMWARE_CPPFLAGS)
+FIRMWARE_ASFLAGS=$(FIRMWARE_CPPFLAGS)
+FIRMWARE_LINK_SCRIPT=$(obj_dir)/firmware.lnk
+FIRMWARE_LDFLAGS=-Wl,-T$(FIRMWARE_LINK_SCRIPT) $(FIRMWARE_CPPFLAGS)
+
+FIRMWARE_COMMON_DEPS=$(common_dir)/arm_asm_macro.h \
+ $(common_dir)/arm_math.h \
+ $(common_dir)/arm_defines.h \
+ $(common_dir)/arm_types.h \
+ $(common_dir)/arm_board.h \
+ $(common_dir)/arm_heap.h \
+ $(common_dir)/arm_inline_asm.h \
+ $(common_dir)/arm_io.h \
+ $(common_dir)/arm_irq.h \
+ $(common_dir)/arm_mmu.h \
+ $(common_dir)/arm_stdio.h \
+ $(common_dir)/arm_string.h \
+ $(common_dir)/libfdt/fdt.h \
+ $(common_dir)/libfdt/fdt_support.h \
+ $(common_dir)/libfdt/libfdt.h \
+ $(common_dir)/libfdt/libfdt_env.h \
+ $(common_dir)/libfdt/libfdt_internal.h
+
+FIRMWARE_TARGETS = $(obj_dir)/firmware.bin
+
+.PHONY: all
+all: $(FIRMWARE_TARGETS)
+
+$(obj_dir)/firmware.bin: $(obj_dir)/firmware.elf
+ @mkdir -p `dirname $@`
+ @echo " (OBJCOPY) $(subst $(obj_dir)/,,$@)"
+ @$(FW_OBJCOPY) -O binary $< $@
+
+$(obj_dir)/firmware.elf: $(FIRMWARE_OBJS) $(FIRMWARE_LINK_SCRIPT)
+ @mkdir -p `dirname $@`
+ @echo " (LD) $(subst $(obj_dir)/,,$@)"
+ @$(FW_CC) $(FIRMWARE_OBJS) $(FW_LDFLAGS) $(FIRMWARE_LDFLAGS) -o $@
+
+$(obj_dir)/%.lnk: $(common_dir)/%.ld
+ @mkdir -p `dirname $@`
+ @echo " (CPP) $(subst $(obj_dir)/,,$@)"
+ @$(FW_CPP) $(FW_CPPFLAGS) $(FIRMWARE_CPPFLAGS) $< | grep -v "\#" > $@
+
+$(obj_dir)/%.o: %.c $(FIRMWARE_COMMON_DEPS)
+ @mkdir -p `dirname $@`
+ @echo " (CC) $(subst $(obj_dir)/,,$@)"
+ @$(FW_CC) $(FW_CFLAGS) $(FIRMWARE_CFLAGS) -c $< -o $@
+
+$(obj_dir)/%.o: $(common_dir)/%.c $(FIRMWARE_COMMON_DEPS)
+ @mkdir -p `dirname $@`
+ @echo " (CC) $(subst $(obj_dir)/,,$@)"
+ @$(FW_CC) $(FW_CFLAGS) $(FIRMWARE_CFLAGS) -c $< -o $@
+
+$(obj_dir)/%.o: %.S $(FIRMWARE_COMMON_DEPS)
+ @mkdir -p `dirname $@`
+ @echo " (AS) $(subst $(obj_dir)/,,$@)"
+ @$(FW_AS) $(FW_ASFLAGS) $(FIRMWARE_ASFLAGS) -c $< -o $@
+
+$(obj_dir)/%.o: $(common_dir)/%.S $(FIRMWARE_COMMON_DEPS)
+ @mkdir -p `dirname $@`
+ @echo " (AS) $(subst $(obj_dir)/,,$@)"
+ @$(FW_AS) $(FW_ASFLAGS) $(FIRMWARE_ASFLAGS) -c $< -o $@
+
+.PHONY: clean
+clean:
+ @echo " (RM) firmware.elf*"
+ @rm -f $(obj_dir)/firmware.elf*
+ @echo " (RM) firmware.bin*"
+ @rm -f $(obj_dir)/firmware.bin*
+ @echo " (RM) $(obj_dir)"
+ @rm -rf $(obj_dir)
+
diff --git a/tests/arm64/common/basic/README b/tests/arm64/common/basic/README
new file mode 100644
index 0000000..70e5ee4
--- /dev/null
+++ b/tests/arm64/common/basic/README
@@ -0,0 +1,5 @@
+ Common basic firmware code
+
+This directory contains souce code files that are common to all boards and
+arm64 processors.
+
diff --git a/tests/arm64/common/basic/arm_asm_macro.h b/tests/arm64/common/basic/arm_asm_macro.h
new file mode 100644
index 0000000..4ab7955
--- /dev/null
+++ b/tests/arm64/common/basic/arm_asm_macro.h
@@ -0,0 +1,139 @@
+/**
+ * Copyright (c) 2010 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_asm_macros.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief common assembly macros for ARM test code
+ */
+#ifndef __ARM_ASM_MACRO_H__
+#define __ARM_ASM_MACRO_H__
+
+#include <arm_defines.h>
+
+#ifdef __ASSEMBLY__
+
+/*
+ * Register aliases.
+ */
+lr .req x30 /* link register */
+
+#define ENTRY(name) \
+ .globl name; \
+ .align 4; \
+ name:
+
+#define END(name) \
+ .size name, .-name
+ mrs x22, elr_el1
+ mrs x23, spsr_el1
+ stp lr, x21, [sp, #0xF0]
+ stp x22, x23, [sp, #0x100]
+ /*
+ * Registers that may be useful after this macro is invoked:
+ *
+ * x21 - aborted SP
+ * x22 - aborted PC
+ * x23 - aborted PSTATE
+ */
+.endm
+
+/* Call C function to handle exception */
+.macro CALL_EXCEPTION_CFUNC cfunc
+ mov x0, sp
+ bl \cfunc
+.endm
+
+/* Pull registers from stack */
+.macro PULL_REGS
+ ldp x21, x22, [sp, #0x100] /* load ELR, SPSR */
+ msr elr_el1, x21
+ msr spsr_el1, x22
+ pop x0, x1
+ pop x2, x3
+ pop x4, x5
+ pop x6, x7
+ pop x8, x9
+ pop x10, x11
+ pop x12, x13
+ pop x14, x15
+ pop x16, x17
+ pop x18, x19
+ pop x20, x21
+ pop x22, x23
+ pop x24, x25
+ pop x26, x27
+ pop x28, x29
+ msr tpidr_el1, x24
+ ldp lr, x24, [sp]
+ mov sp, x24
+ mrs x24, tpidr_el1
+ eret
+.endm
+
+/*
+ * Exception vectors.
+ */
+.macro ventry label
+ .align 7
+ b \label
+.endm
+
+
+
+#endif /* __ASSEMBLY__ */
+
+#endif
diff --git a/tests/arm64/common/basic/arm_board.h b/tests/arm64/common/basic/arm_board.h
new file mode 100644
index 0000000..b0dac5f
--- /dev/null
+++ b/tests/arm64/common/basic/arm_board.h
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2012 Jean-Christophe Dubois.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_board.h
+ * @author Jean-Christophe Dubois (j...@tribudubois.net)
+ * @brief ARM Platform misc functions Header
+ */
+#ifndef _ARM_BOARD_H__
+#define _ARM_BOARD_H__
+
+#include <arm_types.h>
+
+void arm_board_reset(void);
+void arm_board_init(void);
+char *arm_board_name(void);
+physical_addr_t arm_board_ram_start(void);
+physical_size_t arm_board_ram_size(void);
+physical_addr_t arm_board_flash_addr(void);
+u32 arm_board_linux_machine_type(void);
+void arm_board_linux_default_cmdline(char *cmdline, u32 cmdline_sz);
+
+u32 arm_board_iosection_count(void);
+physical_addr_t arm_board_iosection_addr(int num);
+
+u32 arm_board_pic_nr_irqs(void);
+int arm_board_pic_init(void);
+u32 arm_board_pic_active_irq(void);
+int arm_board_pic_ack_irq(u32 irq);
+int arm_board_pic_eoi_irq(u32 irq);
+int arm_board_pic_mask(u32 irq);
+int arm_board_pic_unmask(u32 irq);
+
+void arm_board_timer_enable(void);
+void arm_board_timer_disable(void);
+u64 arm_board_timer_irqcount(void);
+u64 arm_board_timer_irqdelay(void);
+u64 arm_board_timer_timestamp(void);
+void arm_board_timer_change_period(u32 usecs);
+int arm_board_timer_init(u32 usecs);
+
+int arm_board_serial_init(void);
+void arm_board_serial_putc(char ch);
+char arm_board_serial_getc(void);
+
+#endif
diff --git a/tests/arm64/common/basic/arm_defines.h b/tests/arm64/common/basic/arm_defines.h
new file mode 100644
index 0000000..4084e0a
--- /dev/null
+++ b/tests/arm64/common/basic/arm_defines.h
@@ -0,0 +1,312 @@
+/**
+ * Copyright (c) 2010 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_defines.h
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief register related macros & defines for ARM test code
+ */
+#ifndef __ARM_DEFINES_H__
+#define __ARM_DEFINES_H__
+
+/* Interrupt or Exception related macros & defines */
+#define EXC_SVC_SYNC_SP0 0
+#define EXC_SVC_IRQ_SP0 1
+#define EXC_SVC_FIQ_SP0 2
+#define EXC_SVC_SERROR_SP0 3
+#define EXC_SVC_SYNC_SPx 4
+#define EXC_SVC_IRQ_SPx 5
+#define EXC_SVC_FIQ_SPx 6
+#define EXC_SVC_SERROR_SPx 7
+#define EXC_USR_SYNC_A64 8
+#define EXC_USR_IRQ_A64 9
+#define EXC_USR_FIQ_A64 10
+#define EXC_USR_SERROR_A64 11
+#define EXC_USR_SYNC_A32 12
+#define EXC_USR_IRQ_A32 13
+#define EXC_USR_FIQ_A32 14
+#define EXC_USR_SERROR_A32 15
+
+/* PSR related macros & defines */
+#define PSR_EL_MASK 0x0000000C
+#define PSR_EL_0 0x00000000
+#define PSR_EL_1 0x00000004
+#define PSR_EL_2 0x00000008
+#define PSR_EL_3 0x0000000C
+#define PSR_MODE_MASK 0x0000000f
+#define PSR_MODE_EL0t 0x00000000
+#define PSR_MODE_EL1t 0x00000004
+#define PSR_MODE_EL1h 0x00000005
+#define PSR_MODE_EL2t 0x00000008
+#define PSR_MODE_EL2h 0x00000009
+#define PSR_MODE_EL3t 0x0000000c
+#define PSR_MODE_EL3h 0x0000000d
+
+#define PSR_FIQ_DISABLED (1 << 6)
+#define PSR_IRQ_DISABLED (1 << 7)
+#define PSR_ASYNC_ABORT_DISABLED (1 << 8)
+#define PSR_BE_ENABLED (1 << 9)
+
+#define PSR_COND_OVERFLOW (1 << 28)
+#define PSR_COND_CARRY (1 << 29)
+#define PSR_COND_ZERO (1 << 30)
+#define PSR_COND_NEGATIVE (1 << 31)
+
+/* SCTLR related macros & defines */
+#define SCTLR_TE_MASK 0x40000000
+#define SCTLR_AFE_MASK 0x20000000
+#define SCTLR_TRE_MASK 0x10000000
+#define SCTLR_NFI_MASK 0x08000000
+#define SCTLR_EE_MASK 0x02000000
+#define SCTLR_VE_MASK 0x01000000
+#define SCTLR_U_MASK 0x00400000
+#define SCTLR_FI_MASK 0x00200000
+#define SCTLR_HA_MASK 0x00020000
+#define SCTLR_RR_MASK 0x00004000
+#define SCTLR_V_MASK 0x00002000
+#define SCTLR_I_MASK 0x00001000
+#define SCTLR_Z_MASK 0x00000800
+#define SCTLR_SW_MASK 0x00000400
+#define SCTLR_B_MASK 0x00000080
+#define SCTLR_C_MASK 0x00000004
+#define SCTLR_A_MASK 0x00000002
+#define SCTLR_M_MASK 0x00000001
+
+/* TCR_EL1 */
+#define TCR_INITVAL 0x80800000
+#define TCR_TBI_MASK 0x00100000
+#define TCR_TBI_SHIFT 20
+#define TCR_PS_MASK 0x00070000
+#define TCR_PS_SHIFT 16
+#define TCR_TG0_MASK 0x00004000
+#define TCR_TG0_SHIFT 14
+#define TCR_SH0_MASK 0x00003000
+#define TCR_SH0_SHIFT 12
+#define TCR_ORGN0_MASK 0x00000C00
+#define TCR_ORGN0_SHIFT 10
+#define TCR_IRGN0_MASK 0x00000300
+#define TCR_IRGN0_SHIFT 8
+#define TCR_T0SZ_MASK 0x0000003f
+#define TCR_T0SZ_SHIFT 0
+
+/* MAIR_EL1 encodings */
+#define AINDEX_SO 0
+#define AINDEX_NORMAL_WT 1
+#define AINDEX_NORMAL_WB 2
+#define AINDEX_NORMAL_UC 3
+#define MAIR_INITVAL 0x0000000044FFBB00
+
+/* Translation table related macros & defines */
+#define TTBL_INITIAL_TABLE_COUNT 8
+#define TTBL_TABLE_SIZE 0x00001000
+#define TTBL_TABLE_SIZE_SHIFT 12
+#define TTBL_TABLE_ENTCNT 512
+#define TTBL_TABLE_ENTSZ 8
+#define TTBL_STAGE1 1
+#define TTBL_STAGE2 2
+#define TTBL_FIRST_LEVEL 1
+#define TTBL_LEVEL1 1
+#define TTBL_LEVEL2 2
+#define TTBL_LEVEL3 3
+#define TTBL_LAST_LEVEL 3
+/* L1 index Bit[39:30] */
+#define TTBL_L1_INDEX_MASK 0x000000FFC0000000ULL
+#define TTBL_L1_INDEX_SHIFT 30
+#define TTBL_L1_BLOCK_SIZE 0x0000000040000000ULL
+#define TTBL_L1_MAP_MASK (~(TTBL_L1_BLOCK_SIZE - 1))
+/* L2 index Bit[29:21] */
+#define TTBL_L2_INDEX_MASK 0x000000003FE00000ULL
+#define TTBL_L2_INDEX_SHIFT 21
+#define TTBL_L2_BLOCK_SIZE 0x0000000000200000ULL
+#define TTBL_L2_MAP_MASK (~(TTBL_L2_BLOCK_SIZE - 1))
+/* L3 index Bit[20:12] */
+#define TTBL_L3_INDEX_MASK 0x00000000001FF000ULL
+#define TTBL_L3_INDEX_SHIFT 12
+#define TTBL_L3_BLOCK_SIZE 0x0000000000001000ULL
+#define TTBL_L3_MAP_MASK (~(TTBL_L3_BLOCK_SIZE - 1))
+#define TTBL_UPPER_MASK 0xFFF0000000000000ULL
+#define TTBL_UPPER_SHIFT 52
+#define TTBL_OUTADDR_MASK 0x000000FFFFFFF000ULL
+#define TTBL_OUTADDR_SHIFT 12
+#define TTBL_AP_SRW_U 0x0
+#define TTBL_AP_S_URW 0x1
+#define TTBL_AP_SR_U 0x2
+#define TTBL_AP_S_UR 0x3
+#define TTBL_HAP_NOACCESS 0x0
+#define TTBL_HAP_READONLY 0x1
+#define TTBL_HAP_WRITEONLY 0x2
+#define TTBL_HAP_READWRITE 0x3
+#define TTBL_LOWER_MASK 0x0000000000000FFCULL
+#define TTBL_LOWER_SHIFT 2
+#define TTBL_TABLE_MASK 0x0000000000000002ULL
+#define TTBL_TABLE_SHIFT 1
+#define TTBL_VALID_MASK 0x0000000000000001ULL
+#define TTBL_VALID_SHIFT 0
+
+/* TTBL Stage1 Table Attributes */
+#define TTBL_STAGE1_TABLE_NS_MASK 0x8000000000000000ULL
+#define TTBL_STAGE1_TABLE_NS_SHIFT 63
+#define TTBL_STAGE1_TABLE_AP_MASK 0x6000000000000000ULL
+#define TTBL_STAGE1_TABLE_AP_SHIFT 61
+#define TTBL_STAGE1_TABLE_XN_MASK 0x1000000000000000ULL
+#define TTBL_STAGE1_TABLE_XN_SHIFT 60
+#define TTBL_STAGE1_TABLE_PXN_MASK 0x0800000000000000ULL
+#define TTBL_STAGE1_TABLE_PXN_SHIFT 59
+
+/* TTBL Stage1 Block Upper Attributes */
+#define TTBL_STAGE1_UPPER_XN_MASK 0x0040000000000000ULL
+#define TTBL_STAGE1_UPPER_XN_SHIFT 54
+#define TTBL_STAGE1_UPPER_PXN_MASK 0x0020000000000000ULL
+#define TTBL_STAGE1_UPPER_PXN_SHIFT 53
+#define TTBL_STAGE1_UPPER_CONT_MASK 0x0010000000000000ULL
+#define TTBL_STAGE1_UPPER_CONT_SHIFT 52
+
+/* TTBL Stage1 Block Lower Attributes */
+#define TTBL_STAGE1_LOWER_NG_MASK 0x0000000000000800ULL
+#define TTBL_STAGE1_LOWER_NG_SHIFT 11
+#define TTBL_STAGE1_LOWER_AF_MASK 0x0000000000000400ULL
+#define TTBL_STAGE1_LOWER_AF_SHIFT 10
+#define TTBL_STAGE1_LOWER_SH_MASK 0x0000000000000300ULL
+#define TTBL_STAGE1_LOWER_SH_SHIFT 8
+#define TTBL_STAGE1_LOWER_AP_MASK 0x00000000000000C0ULL
+#define TTBL_STAGE1_LOWER_AP_SHIFT 6
+#define TTBL_STAGE1_LOWER_NS_MASK 0x0000000000000020ULL
+#define TTBL_STAGE1_LOWER_NS_SHIFT 5
+#define TTBL_STAGE1_LOWER_AINDEX_MASK 0x000000000000001CULL
+#define TTBL_STAGE1_LOWER_AINDEX_SHIFT 2
+
+/* ESR_EL1 */
+/* WFI/WFE ISS Encodings */
+#define ISS_WFI_WFE_TRAPPED_MASK 0x00080000
+#define ISS_WFI_WFE_TRAPPED_SHIFT 19
+
+
+#endif
diff --git a/tests/arm64/common/basic/arm_entry.S b/tests/arm64/common/basic/arm_entry.S
new file mode 100644
index 0000000..c1a988d
--- /dev/null
+++ b/tests/arm64/common/basic/arm_entry.S
@@ -0,0 +1,323 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_entry.S
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief Entry point code for basic firmware
+ */
+
+#include <arm_asm_macro.h>
+#include <gic_config.h>
+#include <arm_plat.h>
+
+ /*
+ * Basic firmware could be loaded any where in memory.
+ * The _start function ensures that it exectues from intended
+ * base address provided at compile time.
+ */
+ .section .text, "ax", %progbits
+ .globl _start
+_start:
+ /*
+ * x4 -> load start
+ * x5 -> load end
+ * x6 -> execution start
+ * x7 -> execution end
+ * x8 -> code size
+ */
+ adr x4, . /* x4 <- pc */
+ /* Disable IRQ & FIQ */
+ msr daifset, #3
+ ldr x6, __reloc_region_start
+ ldr x7, __reloc_region_end
+ sub x8, x7, x6
+ add x5, x4, x8
+
+ /* If not-running at EL1 then hang */
+ mrs x0, CurrentEL
+ cmp x0, #PSR_MODE_EL1t
+ ccmp x0, #PSR_MODE_EL1h, #0x4, ne
+ b.ne _start_hang
+
+ /* Set GIC priority mask bit [7] = 1 */
+ ldr x0, __gic_cpu_base /* CPU GIC base */
+ mov x1, #0x1
+ str w1, [x0] /* GIC CPU CTRL */
+ mov x1, #0xFF
+ str w1, [x0, #0x4] /* GIC CPU PMR */
+
+ /* Skip secondary spin for primary core */
+ mrs x0, mpidr_el1
+ ands x0, x0, #15 /* CPU number */
+ cmp x0, #0
+ b.eq primary_cpu_boot
+
+ /* Secondary spin loop */
+ ldr x0, __jump_addr
+ str xzr, [x0]
+secondary_cpu_spin:
+ ldr x1, [x0]
+ cbnz x1, secondary_cpu_jump
+ wfe
+ b secondary_cpu_spin
+secondary_cpu_jump:
+ br x1
+
+ .align 3
+__gic_cpu_base:
+ .dword GIC_CPU_BASE
+
+ .align 3
+ .global __jump_addr
+__jump_addr:
+ .dword ARM_PLAT_SPIN_ADDR
+
+ /* Primary core boot-up sequence */
+primary_cpu_boot:
+ /* Check if relocation required */
+ cmp x4, x6
+ b.eq _relocate_end
+
+ /*
+ * We need to clear the A bit in sctlr_el1
+ * for the relocate routine to work properly
+ */
+ mrs x3, sctlr_el1
+ ldr x2, __sctlr_mmu_clear
+ and x3, x3, x2
+ /* We also enable I/D caching */
+ ldr x2, __sctlr_mmu_val
+ orr x3, x3, x2
+ msr sctlr_el1, x3
+ dsb sy
+ isb
+
+ mov x0, x6 /* destination */
+ mov x1, x4 /* source */
+ mov x2, x8 /* byte count */
+ /* TODO: Handle overlaps */
+_relocate:
+ subs x2, x2, #8
+ b.mi 2f
+1: ldr x3, [x1], #8
+ subs x2, x2, #8
+ str x3, [x0], #8
+ b.pl 1b
+2: adds x2, x2, #4
+ b.mi 3f
+ ldr w3, [x1], #4
+ sub x2, x2, #4
+ str w3, [x0], #4
+3: adds x2, x2, #2
+ b.mi 4f
+ ldrh w3, [x1], #2
+ sub x2, x2, #2
+ strh w3, [x0], #2
+4: adds x2, x2, #1
+ b.mi _relocate_end
+ ldrb w3, [x1]
+ strb w3, [x0]
+_relocate_end:
+
+ ldr x0, __relocated
+ br x0
+
+_relocated:
+
+ /* Zero out bss & heap */
+ ldr x0, __zero_region_start
+ ldr x1, __zero_region_end
+1: subs x2, x1, x0
+ b.le 2f
+ str xzr, [x0]
+ add x0, x0, 8
+ b 1b
+2:
+ /* Set exception vectors */
+ adr x0, vectors
+ msr vbar_el1, x0
+ /* Set EL1 stack-pointer */
+ ldr x0, __el1_stack
+ mov sp, x0
+ /* Set EL0 stack-pointer */
+ ldr x0, __el0_stack
+ msr sp_el0, x0
+
+ bl arm_init
+ bl arm_main
+
+_start_hang:
+ b .
+
+ .align 3
+__relocated:
+ .dword _relocated
+
+ .globl _switch_to_user_mode
+_switch_to_user_mode:
+ msr tpidr_el1, x0
+ mov x0, #(PSR_FIQ_DISABLED | PSR_IRQ_DISABLED |\
+ PSR_ASYNC_ABORT_DISABLED | PSR_MODE_EL0t)
+ msr spsr_el1, x0
+ mrs x0, tpidr_el1
+ msr elr_el1, lr
+ eret
+
+ .align 3
+__sctlr_mmu_clear:
+ .dword ~(SCTLR_A_MASK)
+__sctlr_mmu_val:
+ .dword (SCTLR_C_MASK | SCTLR_I_MASK)
+__reloc_region_start:
+ .dword _reloc_region_start
+__reloc_region_end:
+ .dword _reloc_region_end
+__zero_region_start:
+ .dword _zero_region_start
+__zero_region_end:
+ .dword _zero_region_end
+
+ /*
+ * Stacks.
+ */
+__el0_stack:
+ .dword _usr_stack_end
+__el1_stack:
+ .dword _svc_stack_end
+
+
+ .align 11
+ENTRY(vectors)
+ ventry svc_sync_invalid /* Synchronous EL1t */
+ ventry svc_irq_invalid /* IRQ EL1t */
+ ventry svc_fiq_invalid /* FIQ EL1t */
+ ventry svc_error_invalid /* Error EL1t */
+
+ ventry svc_sync /* Synchronous EL1h */
+ ventry svc_irq /* IRQ EL1h */
+ ventry svc_fiq_invalid /* FIQ EL1h */
+ ventry svc_error_invalid /* Error EL1h */
+
+ ventry usr_sync_a64 /* Synchronous 64-bit EL0 */
+ ventry usr_irq_a64 /* IRQ 64-bit EL0 */
+ ventry usr_fiq_a64 /* FIQ 64-bit EL0 */
+ ventry usr_error_a64 /* Error 64-bit EL0 */
+
+ ventry usr_sync_a32 /* Synchronous 32-bit EL0 */
+ ventry usr_irq_a32 /* IRQ 32-bit EL0 */
+ ventry usr_fiq_a32 /* FIQ 32-bit EL0 */
+ ventry usr_error_a32 /* Error 32-bit EL0 */
+END(vectors)
+
+EXCEPTION_HANDLER svc_sync_invalid
+ PUSH_REGS
+ mov x1, EXC_SVC_SYNC_SP0
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER svc_irq_invalid
+ PUSH_REGS
+ mov x1, EXC_SVC_IRQ_SP0
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER svc_fiq_invalid
+ PUSH_REGS
+ mov x1, EXC_SVC_FIQ_SP0
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER svc_error_invalid
+ PUSH_REGS
+ mov x1, EXC_SVC_SERROR_SP0
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER svc_sync
+ PUSH_REGS
+ mov x1, EXC_SVC_SYNC_SPx
+ CALL_EXCEPTION_CFUNC do_sync
+ PULL_REGS
+
+EXCEPTION_HANDLER svc_irq
+ PUSH_REGS
+ mov x1, EXC_SVC_IRQ_SPx
+ CALL_EXCEPTION_CFUNC do_irq
+ PULL_REGS
+
+EXCEPTION_HANDLER svc_fiq
+ PUSH_REGS
+ mov x1, EXC_SVC_FIQ_SPx
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER svc_error
+ PUSH_REGS
+ mov x1, EXC_SVC_SERROR_SPx
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER usr_sync_a64
+ PUSH_REGS
+ mov x1, EXC_USR_SYNC_A64
+ CALL_EXCEPTION_CFUNC do_sync
+ PULL_REGS
+
+EXCEPTION_HANDLER usr_irq_a64
+ PUSH_REGS
+ mov x1, EXC_USR_IRQ_A64
+ CALL_EXCEPTION_CFUNC do_irq
+ PULL_REGS
+
+EXCEPTION_HANDLER usr_fiq_a64
+ PUSH_REGS
+ mov x1, EXC_USR_FIQ_A64
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER usr_error_a64
+ PUSH_REGS
+ mov x1, EXC_USR_SERROR_A64
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER usr_sync_a32
+ PUSH_REGS
+ mov x1, EXC_USR_SYNC_A32
+ CALL_EXCEPTION_CFUNC do_sync
+ PULL_REGS
+
+EXCEPTION_HANDLER usr_irq_a32
+ PUSH_REGS
+ mov x1, EXC_USR_IRQ_A32
+ CALL_EXCEPTION_CFUNC do_irq
+ PULL_REGS
+
+EXCEPTION_HANDLER usr_fiq_a32
+ PUSH_REGS
+ mov x1, EXC_USR_FIQ_A32
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER usr_error_a32
+ PUSH_REGS
+ mov x1, EXC_USR_SERROR_A32
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+
diff --git a/tests/arm64/common/basic/arm_heap.c b/tests/arm64/common/basic/arm_heap.c
new file mode 100644
index 0000000..03a4989
--- /dev/null
+++ b/tests/arm64/common/basic/arm_heap.c
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_heap.c
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief source file for heap managment
+ */
+
+#include <arm_heap.h>
+
+static void * heap_curr;
+extern u8 _heap_start;
+
+void * arm_malloc(size_t size)
+{
+ void * retval;
+ /* Make size 8B aligned */
+ if (size & 0x7)
+ size = ((size / 8) + 1) * 8;
+ retval = heap_curr;
+ heap_curr += size;
+ return retval;
+}
+
+void arm_heap_init(void)
+{
+ heap_curr = &_heap_start;
+}
+
diff --git a/tests/arm64/common/basic/arm_heap.h b/tests/arm64/common/basic/arm_heap.h
new file mode 100644
index 0000000..4c3565b
--- /dev/null
+++ b/tests/arm64/common/basic/arm_heap.h
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_heap.h
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief Header file for heap managment
+ */
+
+#ifndef __ARM_HEAP_H_
+#define __ARM_HEAP_H_
+
+#include <arm_types.h>
+
+void * arm_malloc(size_t size);
+void arm_heap_init(void);
+
+#endif /* __ARM_HEAP_H_ */
diff --git a/tests/arm64/common/basic/arm_inline_asm.h b/tests/arm64/common/basic/arm_inline_asm.h
new file mode 100644
index 0000000..5be7b32
--- /dev/null
+++ b/tests/arm64/common/basic/arm_inline_asm.h
@@ -0,0 +1,118 @@
+/**
+ * Copyright (c) 2012 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_inline_asm.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief Frequently required inline assembly macros
+ */
+#ifndef __ARM_INLINE_ASM_H__
+#define __ARM_INLINE_ASM_H__
+
+#include <arm_types.h>
+#define msr_sync(spr, val) asm volatile("msr " #spr ", %0\n\tdsb sy\n\tisb" ::"r"(val));
+
+#define dsb() asm volatile("dsb sy":::"memory","cc");
+
+#define isb() asm volatile("isb":::"memory","cc");
+
+
+/* TLB maintainence */
+
+#define inv_tlb_all() asm volatile("tlbi vmalle1is\n\tdsb sy\n\tisb\n\t"::: "memory", "cc");
+
+#define inv_tlb_va(va) asm volatile("tlbi vaae1is, %0\n\tdsb sy\n\tisb\n\t" \
+ :: "r" ((va >> 12)) : "memory", "cc")
+
+
+/* VA to PA Address Translation */
+
+#define VA2PA_STAGE1 "s1"
+#define VA2PA_STAGE12 "s12"
+#define VA2PA_EL0 "e0"
+#define VA2PA_EL1 "e1"
+#define VA2PA_EL2 "e2"
+#define VA2PA_EL3 "e3"
+#define VA2PA_RD "r"
+#define VA2PA_WR "w"
+#define va2pa_at(stage, el, rw, va) asm volatile( \
+ "at " stage el rw ", %0" \
+ : : "r"(va) : "memory", "cc");
+
+
+/* Features */
+#define cpu_supports_thumbee() ({ u64 pfr0; asm volatile("mrs %0, id_pfr0_el1": "=r"(pfr0)); \
+ (pfr0 & ID_PFR0_THUMBEE_MASK); })
+
+#define cpu_supports_thumb() ({ u64 pfr0; asm volatile("mrs %0, id_pfr0_el1": "=r"(pfr0)); \
+ (pfr0 & ID_PFR0_THUMBEE_MASK); })
+
+#define cpu_supports_thumb2() ({ u64 pfr0; asm volatile("mrs %0, id_pfr0_el1": "=r"(pfr0)); \
+ ((pfr0 & ID_PFR0_THUMB_MASK) == ID_PFR0_THUMB2_MASK); })
+
+#define cpu_supports_jazelle() ({ u64 pfr0; asm volatile("mrs %0, id_pfr0_el1": "=r"(pfr0)); \
+ (pfr0 & ID_PFR0_JAZELLE_MASK); })
+
+#define cpu_supports_arm() ({ u64 pfr0; asm volatile("mrs %0, id_pfr0_el1": "=r"(pfr0)); \
+ (pfr0 & ID_PFR0_ARM_MASK); })
+
+#define cpu_supports_asimd() ({ u64 pfr0; asm volatile("mrs %0, id_aa64pfr0_el1": "=r"(pfr0)); \
+ ((pfr0 & ID_AA64PFR0_ASIMD_MASK) == 0); })
+
+#define cpu_supports_fpu() ({ u64 pfr0; asm volatile("mrs %0, id_aa64pfr0_el1": "=r"(pfr0)); \
+ ((pfr0 & ID_AA64PFR0_FPU_MASK) == 0); })
+
+#define cpu_supports_el0_a32() ({ u64 pfr0; asm volatile("mrs %0, id_aa64pfr0_el1": "=r"(pfr0)); \
+ (pfr0 & ID_AA64PFR0_EL0_A32); })
+
+#define cpu_supports_el1_a32() ({ u64 pfr0; asm volatile("mrs %0, id_aa64pfr0_el1": "=r"(pfr0)); \
+ (pfr0 & ID_AA64PFR0_EL1_A32);})
+
+#define cpu_supports_el2_a32() ({ u64 pfr0; asm volatile("mrs %0, id_aa64pfr0_el1": "=r"(pfr0)); \
+ (pfr0 & ID_AA64PFR0_EL2_A32); })
+
+#define cpu_supports_el3_a32() ({ u64 pfr0; asm volatile("mrs %0, id_aa64pfr0_el1": "=r"(pfr0)); \
+ (pfr0 & ID_AA64PFR0_EL3_A32); })
+
+#endif
diff --git a/tests/arm64/common/basic/arm_io.h b/tests/arm64/common/basic/arm_io.h
new file mode 100644
index 0000000..05049aa
--- /dev/null
+++ b/tests/arm64/common/basic/arm_io.h
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_io.h
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief Header file for common I/O functions
+ */
+
+#ifndef __ARM_IO_H_
+#define __ARM_IO_H_
+
+#include <arm_types.h>
+
+static inline u32 arm_readl(void *addr)
+{
+ return *((u32 *)addr);
+}
+
+static inline void arm_writel(u32 data, void *addr)
+{
+ *((u32 *)addr) = data;
+}
+
+#endif /* __ARM_IO_H_ */
diff --git a/tests/arm64/common/basic/arm_irq.c b/tests/arm64/common/basic/arm_irq.c
new file mode 100644
index 0000000..2e450f1
--- /dev/null
+++ b/tests/arm64/common/basic/arm_irq.c
@@ -0,0 +1,122 @@
+/**
+ * Copyright (c) 2010 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_irq.c
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief source code for handling ARM test code interrupts
+ */
+
+#include <arm_board.h>
+#include <arm_mmu.h>
+#include <arm_irq.h>
+#include <arm_stdio.h>
+
+#define MAX_NR_IRQS 1024
+
+arm_irq_handler_t irq_hndls[MAX_NR_IRQS];
+
+#define PIC_NR_IRQS ((arm_board_pic_nr_irqs() < MAX_NR_IRQS) ? \
+ arm_board_pic_nr_irqs() : MAX_NR_IRQS)
+
+void do_bad_mode(struct pt_regs *regs)
+{
+ arm_puts("Bad exception\n");
+ while(1);
+}
+
+void do_sync(struct pt_regs *regs)
+{
+ arm_sync_abort(regs);
+}
+
+void do_irq(struct pt_regs *regs)
+{
+ int rc = 0;
+ int irq = arm_board_pic_active_irq();
+
+ if (-1 < irq) {
+ rc = arm_board_pic_ack_irq(irq);
+ if (rc) {
+ while (1);
+ }
+ if (irq_hndls[irq]) {
+ rc = irq_hndls[irq](irq, regs);
+ if (rc) {
+ while (1);
+ }
+ }
+ rc = arm_board_pic_eoi_irq(irq);
+ if (rc) {
+ while (1);
+ }
+ }
+}
+
+void do_fiq(struct pt_regs *regs)
+{
+}
+
+void arm_irq_setup(void)
+{
+ int vec;
+
+ /*
+ * Reset irq handlers
+ */
+ for (vec = 0; vec < PIC_NR_IRQS; vec++) {
+ irq_hndls[vec] = NULL;
+ }
+
+ /*
+ * Initialize board PIC
+ */
+ vec = arm_board_pic_init();
+ if (vec) {
+ while (1);
+ }
+}
+
+void arm_irq_register(u32 irq, arm_irq_handler_t hndl)
+{
+ int rc = 0;
+ if (irq < PIC_NR_IRQS) {
+ irq_hndls[irq] = hndl;
+ if (irq_hndls[irq]) {
+ rc = arm_board_pic_unmask(irq);
+ if (rc) {
+ while (1);
+ }
+ }
+ }
+}
+
+void arm_irq_enable(void)
+{
+ asm volatile("msr daifclr, #2":::"memory");
+}
+
+void arm_irq_disable(void)
+{
+ asm volatile("msr daifset, #2":::"memory");
+}
+
+void arm_irq_wfi(void)
+{
+ __asm ("wfi\n");
+}
+
diff --git a/tests/arm64/common/basic/arm_irq.h b/tests/arm64/common/basic/arm_irq.h
new file mode 100644
index 0000000..26580eb
--- /dev/null
+++ b/tests/arm64/common/basic/arm_irq.h
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2010 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_irq.h
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief header file for ARM interrupts
+ */
+#ifndef _ARM_IRQ_H__
+#define _ARM_IRQ_H__
+
+#include <arm_types.h>
+
+typedef int (*arm_irq_handler_t) (u32 irq_no, struct pt_regs * regs);
+
+#define CPU_IRQ_NR 8
+
+/** IRQ Numbers */
+#define ARM_RESET_IRQ 0
+#define ARM_UNDEF_INST_IRQ 1
+#define ARM_SOFT_IRQ 2
+#define ARM_PREFETCH_ABORT_IRQ 3
+#define ARM_DATA_ABORT_IRQ 4
+#define ARM_NOT_USED_IRQ 5
+#define ARM_EXTERNAL_IRQ 6
+#define ARM_EXTERNAL_FIQ 7
+
+void arm_irq_setup(void);
+void arm_irq_register(u32 irq_no, arm_irq_handler_t hndl);
+void arm_irq_enable(void);
+void arm_irq_disable(void);
+void arm_irq_wfi(void);
+
+#endif
diff --git a/tests/arm64/common/basic/arm_main.c b/tests/arm64/common/basic/arm_main.c
new file mode 100644
index 0000000..6e5725e
--- /dev/null
+++ b/tests/arm64/common/basic/arm_main.c
@@ -0,0 +1,675 @@
+/**
+ * Copyright (c) 2012 Jean-Christophe Dubois.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_main.c
+ * @author Jean-Christophe Dubois (j...@tribudubois.net)
+ * @brief Basic firmware main file
+ */
+
+#include <arm_io.h>
+#include <arm_heap.h>
+#include <arm_mmu.h>
+#include <arm_irq.h>
+#include <arm_string.h>
+#include <arm_stdio.h>
+#include <arm_board.h>
+#include <dhry.h>
+#include <libfdt/libfdt.h>
+#include <libfdt/fdt_support.h>
+
+static unsigned long memory_size = 0x0;
+
+unsigned long arm_linux_memory_size(void)
+{
+ return memory_size;
+}
+
+/* Works in supervisor mode */
+void arm_init(void)
+{
+ arm_heap_init();
+
+ arm_irq_disable();
+
+ arm_irq_setup();
+
+ arm_stdio_init();
+
+ arm_board_timer_init(10000);
+
+ memory_size = arm_board_ram_size();
+
+ arm_board_timer_enable();
+
+ arm_irq_enable();
+}
+
+void arm_cmd_help(int argc, char **argv)
+{
+ arm_puts("help - List commands and their usage\n");
+ arm_puts("\n");
+ arm_puts("hi - Say hi to ARM test code\n");
+ arm_puts("\n");
+ arm_puts("hello - Say hello to ARM test code\n");
+ arm_puts("\n");
+ arm_puts("wfi_test - Run wait for irq instruction test for ARM test code\n");
+ arm_puts(" Usage: wfi_test [<msecs>]\n");
+ arm_puts(" <msecs> = delay in milliseconds to wait for\n");
+ arm_puts("\n");
+ arm_puts("mmu_setup - Setup MMU for ARM test code\n");
+ arm_puts("\n");
+ arm_puts("mmu_state - MMU is enabled/disabled for ARM test code\n");
+ arm_puts("\n");
+ arm_puts("mmu_test - Run MMU test suite for ARM test code\n");
+ arm_puts("\n");
+ arm_puts("mmu_cleanup - Cleanup MMU for ARM test code\n");
+ arm_puts("\n");
+ arm_puts("timer - Display timer information\n");
+ arm_puts("\n");
+ arm_puts("dhrystone - Dhrystone 2.1 benchmark\n");
+ arm_puts(" Usage: dhrystone [<iterations>]\n");
+ arm_puts("\n");
+ arm_puts("hexdump - Dump memory contents in hex format\n");
+ arm_puts(" Usage: hexdump <addr> <count>\n");
+ arm_puts(" <addr> = memory address in hex\n");
+ arm_puts(" <count> = byte count in hex\n");
+ arm_puts("\n");
+ arm_puts("copy - Copy to target memory from source memory\n");
+ arm_puts(" Usage: copy <dest> <src> <count>\n");
+ arm_puts(" <dest> = destination address in hex\n");
+ arm_puts(" <src> = source address in hex\n");
+ arm_puts(" <count> = byte count in hex\n");
+ arm_puts("\n");
+ arm_puts("start_linux - Start linux kernel\n");
+ arm_puts(" Usage: start_linux <kernel_addr> <initrd_addr> <initrd_size>\n");
+ arm_puts(" <kernel_addr> = kernel load address\n");
+ arm_puts(" <initrd_addr> = initrd load address\n");
+ arm_puts(" <initrd_size> = initrd size\n");
+ arm_puts("\n");
+ arm_puts("linux_cmdline - Show/Update linux command line\n");
+ arm_puts(" Usage: linux_cmdline <new_linux_cmdline> \n");
+ arm_puts(" <new_linux_cmdline> = linux command line\n");
+ arm_puts("\n");
+ arm_puts("linux_memory_size - Show/Update linux memory size\n");
+ arm_puts(" Usage: linux_memory_size <memory_size> \n");
+ arm_puts(" <memory_size> = memory size in hex\n");
+ arm_puts("\n");
+ arm_puts("autoexec - autoexec command list from flash\n");
+ arm_puts(" Usage: autoexec\n");
+ arm_puts("\n");
+ arm_puts("go - Jump to a given address\n");
+ arm_puts(" Usage: go <addr>\n");
+ arm_puts(" <addr> = jump address in hex\n");
+ arm_puts("\n");
+ arm_puts("reset - Reset the system\n");
+ arm_puts("\n");
+}
+
+void arm_cmd_hi(int argc, char **argv)
+{
+ if (argc != 1) {
+ arm_puts ("hi: no parameters required\n");
+ return;
+ }
+
+ arm_puts("hello\n");
+}
+
+void arm_cmd_hello(int argc, char **argv)
+{
+ if (argc != 1) {
+ arm_puts ("hello: no parameters required\n");
+ return;
+ }
+
+ arm_puts("hi\n");
+}
+
+void arm_cmd_wfi_test(int argc, char **argv)
+{
+ u64 tstamp;
+ char time[256];
+ int delay = 1000;
+
+ if (argc > 2) {
+ arm_puts ("wfi_test: could provide only <delay>\n");
+ return;
+ } else if (argc == 2) {
+ delay = arm_str2int(argv[1]);
+ }
+
+ arm_puts("Executing WFI instruction\n");
+ arm_board_timer_disable();
+ arm_board_timer_change_period(delay*1000);
+ arm_board_timer_enable();
+ tstamp = arm_board_timer_timestamp();
+ arm_irq_wfi();
+ tstamp = arm_board_timer_timestamp() - tstamp;
+ arm_board_timer_disable();
+ arm_board_timer_change_period(10000);
+ arm_board_timer_enable();
+ arm_puts("Resumed from WFI instruction\n");
+ arm_puts("Time spent in WFI: ");
+ arm_ulonglong2str(time, tstamp);
+ arm_puts(time);
+ arm_puts(" nsecs\n");
+}
+
+#if 0
+void arm_cmd_mmu_setup(int argc, char **argv)
+{
+ if (argc != 1) {
+ arm_puts ("mmu_setup: no parameters required\n");
+ return;
+ }
+
+ arm_mmu_setup();
+}
+#endif
+
+void arm_cmd_mmu_state(int argc, char **argv)
+{
+ if (argc != 1) {
+ arm_puts ("mmu_state: no parameters required\n");
+ return;
+ }
+
+ if (arm_mmu_is_enabled()) {
+ arm_puts("MMU Enabled\n");
+ } else {
+ arm_puts("MMU Disabled\n");
+ }
+}
+
+#if 0
+void arm_cmd_mmu_test(int argc, char **argv)
+{
+ char str[32];
+ u32 total = 0x0, pass = 0x0, fail = 0x0;
+
+ if (argc != 1) {
+ arm_puts ("mmu_test: no parameters required\n");
+ return;
+ }
+
+ arm_puts("MMU Section Test Suite ...\n");
+ total = 0x0;
+ pass = 0x0;
+ fail = 0x0;
+ arm_mmu_section_test(&total, &pass, &fail);
+ arm_puts(" Total: ");
+ arm_int2str(str, total);
+ arm_puts(str);
+ arm_puts("\n");
+ arm_puts(" Pass : ");
+ arm_int2str(str, pass);
+ arm_puts(str);
+ arm_puts("\n");
+ arm_puts(" Fail : ");
+ arm_int2str(str, fail);
+ arm_puts(str);
+ arm_puts("\n");
+ arm_puts("MMU Page Test Suite ...\n");
+ total = 0x0;
+ pass = 0x0;
+ fail = 0x0;
+ arm_mmu_page_test(&total, &pass, &fail);
+ arm_puts(" Total: ");
+ arm_int2str(str, total);
+ arm_puts(str);
+ arm_puts("\n");
+ arm_puts(" Pass : ");
+ arm_int2str(str, pass);
+ arm_puts(str);
+ arm_puts("\n");
+ arm_puts(" Fail : ");
+ arm_int2str(str, fail);
+ arm_puts(str);
+ arm_puts("\n");
+}
+#endif
+
+void arm_cmd_mmu_cleanup(int argc, char **argv)
+{
+ if (argc != 1) {
+ arm_puts ("mmu_cleanup: no parameters required\n");
+ return;
+ }
+
+ arm_mmu_cleanup();
+}
+
+void arm_cmd_timer(int argc, char **argv)
+{
+ char str[32];
+ u64 irq_count, irq_delay, tstamp;
+
+ if (argc != 1) {
+ arm_puts ("timer: no parameters required\n");
+ return;
+ }
+
+ irq_count = arm_board_timer_irqcount();
+ irq_delay = arm_board_timer_irqdelay();
+ tstamp = arm_board_timer_timestamp();
+ arm_puts("Timer Information ...\n");
+ arm_puts(" IRQ Count: 0x");
+ arm_ulonglong2hexstr(str, irq_count);
+ arm_puts(str);
+ arm_puts("\n");
+ arm_puts(" IRQ Delay: 0x");
+ arm_ulonglong2hexstr(str, irq_delay);
+ arm_puts(str);
+ arm_puts("\n");
+ arm_puts(" Time Stamp: 0x");
+ arm_ulonglong2hexstr(str, tstamp);
+ arm_puts(str);
+ arm_puts("\n");
+}
+
+void arm_cmd_dhrystone(int argc, char **argv)
+{
+ char str[32];
+ int iters = 1000000;
+ if (argc > 2) {
+ arm_puts ("dhrystone: could provide only <iter_number>\n");
+ return;
+ } else if (argc == 2) {
+ iters = arm_str2int(argv[1]);
+ } else {
+ arm_puts ("dhrystone: number of iterations not provided\n");
+ arm_puts ("dhrystone: using default ");
+ arm_int2str (str, iters);
+ arm_puts (str);
+ arm_puts (" iterations\n");
+ }
+ arm_board_timer_disable();
+ dhry_main(iters);
+ arm_board_timer_enable();
+}
+
+void arm_cmd_hexdump(int argc, char **argv)
+{
+ char str[32];
+ u32 *addr;
+ u32 i, count, len;
+ if (argc != 3) {
+ arm_puts ("hexdump: must provide <addr> and <count>\n");
+ return;
+ }
+ addr = (u32 *)arm_hexstr2ulonglong(argv[1]);
+ count = arm_hexstr2uint(argv[2]);
+ for (i = 0; i < (count / 4); i++) {
+ if (i % 4 == 0) {
+ arm_ulonglong2hexstr(str, (u64)&addr[i]);
+ len = arm_strlen(str);
+ while (len < 8) {
+ arm_puts("0");
+ len++;
+ }
+ arm_puts(str);
+ arm_puts(": ");
+ }
+ arm_uint2hexstr(str, addr[i]);
+ len = arm_strlen(str);
+ while (len < 8) {
+ arm_puts("0");
+ len++;
+ }
+ arm_puts(str);
+ if (i % 4 == 3) {
+ arm_puts("\n");
+ } else {
+ arm_puts(" ");
+ }
+ }
+ arm_puts("\n");
+}
+
+void arm_cmd_copy(int argc, char **argv)
+{
+ u64 tstamp;
+ char time[256];
+ u64 *dest, *src;
+ u32 i, count;
+ if (argc != 4) {
+ arm_puts ("copy: must provide <dest>, <src>, and <count>\n");
+ return;
+ }
+ dest = (u64 *)arm_hexstr2ulonglong(argv[1]);
+ src = (u64 *)arm_hexstr2ulonglong(argv[2]);
+ count = arm_hexstr2uint(argv[3]);
+ arm_board_timer_disable();
+ tstamp = arm_board_timer_timestamp();
+ for (i = 0; i < (count/sizeof(*dest)); i++) {
+ dest[i] = src[i];
+ }
+ tstamp = arm_board_timer_timestamp() - tstamp;
+ arm_board_timer_enable();
+ arm_ulonglong2str(time, tstamp);
+ arm_puts("copy took ");
+ arm_puts(time);
+ arm_puts(" ns for ");
+ arm_puts(argv[3]);
+ arm_puts(" bytes\n");
+}
+
+#define CONFIG_RAM_SIZE (arm_linux_memory_size() >> 20)
+#define CONFIG_NR_CPUS 2
+char linux_cmdline[1024];
+
+typedef void (* linux_entry_t) (u64 fdt_addr);
+extern void *__jump_addr;
+
+void dump_fdt(void *);
+
+void arm_cmd_start_linux(int argc, char **argv)
+{
+ u64 kernel_addr, fdt_addr;
+ u64 initrd_addr, initrd_size;
+ u64 release_addr;
+ int err;
+ char cfg_str[10];
+ u64 meminfo[2];
+
+ if (argc != 5) {
+ arm_puts ("start_linux: must provide <kernel_addr>, <initrd_addr>, <initrd_size> and <fdt_addr>\n");
+ return;
+ }
+
+ /* Parse the arguments from command line */
+ kernel_addr = arm_hexstr2ulonglong(argv[1]);
+ initrd_addr = arm_hexstr2ulonglong(argv[2]);
+ initrd_size = arm_hexstr2ulonglong(argv[3]);
+ fdt_addr = arm_hexstr2ulonglong(argv[4]);
+
+ meminfo[0] = arm_board_ram_start();
+ meminfo[1] = arm_board_ram_size();
+ /* Fillup/fixup the fdt blob with following:
+ * - initrd start, end
+ * - kernel cmd line
+ * - number of cpus */
+ if ((err = fdt_fixup_memory_banks((void *)fdt_addr, (&meminfo[0]),
+ (&meminfo[1]), 1))) {
+ arm_printf("%s: fdt_fixup_memory_banks() failed: %s\n", __func__,
+ fdt_strerror(err));
+ return;
+ }
+ sprintf(cfg_str, " mem=%dM maxcpus=%d",
+ (int)(meminfo[1] >> 20), CONFIG_NR_CPUS);
+ arm_strcat(linux_cmdline, cfg_str);
+ if ((err = fdt_chosen((void *)fdt_addr, 1))) {
+ arm_printf("%s: fdt_chosen() failed: %s\n", __func__,
+ fdt_strerror(err));
+ return;
+ }
+ if ((err = fdt_initrd((void *)fdt_addr, initrd_addr,
+ initrd_addr + initrd_size, 1))) {
+ arm_printf("%s: fdt_initrd() failed: %s\n", __func__,
+ fdt_strerror(err));
+ return;
+ }
+ release_addr = cpu_to_be64(((u64)(__jump_addr)));
+ do_fixup_by_compat((void *)fdt_addr, "arm,armv8", "cpu-release-addr",
+ &release_addr, sizeof(release_addr), 1);
+
+ /* Disable interrupts and timer */
+ arm_board_timer_disable();
+ arm_irq_disable();
+ arm_mmu_cleanup();
+
+ /* Jump to Linux Kernel
+ * r0 -> dtb address
+ */
+ arm_puts("Jumping into linux ...\n");
+ ((linux_entry_t)kernel_addr)(fdt_addr);
+
+ /* We should never reach here */
+ while (1);
+
+ return;
+}
+
+void arm_cmd_linux_cmdline(int argc, char **argv)
+{
+ if (argc >= 2) {
+ int cnt = 1;
+ linux_cmdline[0] = 0;
+
+ while (cnt < argc) {
+ arm_strcat(linux_cmdline, argv[cnt]);
+ arm_strcat(linux_cmdline, " ");
+ cnt++;
+ }
+ }
+
+ arm_puts ("linux_cmdline = \"");
+ arm_puts(linux_cmdline);
+ arm_puts ("\"\n");
+
+ return;
+}
+
+void arm_cmd_linux_memory_size(int argc, char **argv)
+{
+ char str[32];
+
+ if (argc == 2) {
+ memory_size = (u32)arm_hexstr2uint(argv[1]);
+ }
+
+ arm_puts ("linux_memory_size = 0x");
+ arm_uint2hexstr(str, memory_size);
+ arm_puts(str);
+ arm_puts (" Bytes\n");
+
+ return;
+}
+
+void arm_exec(char *line);
+
+void arm_cmd_autoexec(int argc, char **argv)
+{
+ static int lock = 0;
+ int len;
+ /* commands to execute are stored in NOR flash */
+ char *ptr = (char *)(arm_board_flash_addr() + 0xFF000);
+ char buffer[4096];
+
+ if (argc != 1) {
+ arm_puts ("autoexec: no parameters required\n");
+ return;
+ }
+
+ /* autoexec is not recursive */
+ if (lock) {
+ arm_puts("ignoring autoexec calling autoexec\n");
+ return;
+ }
+
+ lock = 1;
+
+ if ((len = arm_strlen(ptr))) {
+ int pos = 0;
+
+ /* copy commands from NOR flash */
+ arm_strcpy(buffer, ptr);
+
+ /* now we process them */
+ while (pos < len) {
+ ptr = &buffer[pos];
+
+ /* We need to separate the commands */
+ while ((buffer[pos] != '\r') &&
+ (buffer[pos] != '\n') &&
+ (buffer[pos] != 0)) {
+ pos++;
+ }
+ buffer[pos] = '\0';
+ pos++;
+
+ /* print the command */
+ arm_puts("autoexec(");
+ arm_puts(ptr);
+ arm_puts(")\n");
+ /* execute it */
+ arm_exec(ptr);
+ }
+
+ }
+
+ lock = 0;
+
+ return;
+}
+
+void arm_cmd_go(int argc, char **argv)
+{
+ char str[32];
+ void (* jump)(void);
+
+ if (argc != 2) {
+ arm_puts ("go: must provide destination address\n");
+ return;
+ }
+
+ arm_board_timer_disable();
+
+ jump = (void (*)(void))arm_hexstr2ulonglong(argv[1]);
+ arm_ulonglong2hexstr(str, (u64)jump);
+ arm_puts("Jumping to location 0x");
+ arm_puts(str);
+ arm_puts(" ...\n");
+ jump ();
+
+ arm_board_timer_enable();
+}
+
+void arm_cmd_reset(int argc, char **argv)
+{
+ if (argc != 1) {
+ arm_puts ("reset: no parameters required\n");
+ return;
+ }
+
+ arm_puts("System reset ...\n\n");
+
+ arm_board_reset();
+
+ while (1);
+}
+
+#define ARM_MAX_ARG_SIZE 32
+
+void arm_exec(char *line)
+{
+ int argc = 0, pos = 0, cnt = 0;
+ char *argv[ARM_MAX_ARG_SIZE];
+
+ while (line[pos] && (argc < ARM_MAX_ARG_SIZE)) {
+ if ((line[pos] == '\r') ||
+ (line[pos] == '\n')) {
+ line[pos] = '\0';
+ break;
+ }
+ if (line[pos] == ' ') {
+ if (cnt > 0) {
+ line[pos] = '\0';
+ cnt = 0;
+ }
+ } else {
+ if (cnt == 0) {
+ argv[argc] = &line[pos];
+ argc++;
+ }
+ cnt++;
+ }
+ pos++;
+ }
+
+ if (argc) {
+ if (arm_strcmp(argv[0], "help") == 0) {
+ arm_cmd_help(argc, argv);
+ } else if (arm_strcmp(argv[0], "hi") == 0) {
+ arm_cmd_hi(argc, argv);
+ } else if (arm_strcmp(argv[0], "hello") == 0) {
+ arm_cmd_hello(argc, argv);
+ } else if (arm_strcmp(argv[0], "wfi_test") == 0) {
+ arm_cmd_wfi_test(argc, argv);
+#if 0
+ } else if (arm_strcmp(argv[0], "mmu_setup") == 0) {
+ arm_cmd_mmu_setup(argc, argv);
+#endif
+ } else if (arm_strcmp(argv[0], "mmu_state") == 0) {
+ arm_cmd_mmu_state(argc, argv);
+#if 0
+ } else if (arm_strcmp(argv[0], "mmu_test") == 0) {
+ arm_cmd_mmu_test(argc, argv);
+#endif
+ } else if (arm_strcmp(argv[0], "mmu_cleanup") == 0) {
+ arm_cmd_mmu_cleanup(argc, argv);
+ } else if (arm_strcmp(argv[0], "timer") == 0) {
+ arm_cmd_timer(argc, argv);
+ } else if (arm_strcmp(argv[0], "dhrystone") == 0) {
+ arm_cmd_dhrystone(argc, argv);
+ } else if (arm_strcmp(argv[0], "hexdump") == 0) {
+ arm_cmd_hexdump(argc, argv);
+ } else if (arm_strcmp(argv[0], "copy") == 0) {
+ arm_cmd_copy(argc, argv);
+ } else if (arm_strcmp(argv[0], "start_linux") == 0) {
+ arm_cmd_start_linux(argc, argv);
+ } else if (arm_strcmp(argv[0], "linux_cmdline") == 0) {
+ arm_cmd_linux_cmdline(argc, argv);
+ } else if (arm_strcmp(argv[0], "linux_memory_size") == 0) {
+ arm_cmd_linux_memory_size(argc, argv);
+ } else if (arm_strcmp(argv[0], "autoexec") == 0) {
+ arm_cmd_autoexec(argc, argv);
+ } else if (arm_strcmp(argv[0], "go") == 0) {
+ arm_cmd_go(argc, argv);
+ } else if (arm_strcmp(argv[0], "reset") == 0) {
+ arm_cmd_reset(argc, argv);
+ } else {
+ arm_puts("Unknown command\n");
+ }
+ }
+}
+
+#define ARM_MAX_CMD_STR_SIZE 256
+
+/* Works in user mode */
+void arm_main(void)
+{
+ char line[ARM_MAX_CMD_STR_SIZE];
+
+ /* Setup board specific linux default cmdline */
+ arm_board_linux_default_cmdline(linux_cmdline,
+ sizeof(linux_cmdline));
+
+ arm_puts(arm_board_name());
+ arm_puts(" Basic Firmware\n\n");
+
+ arm_board_init();
+
+ while(1) {
+ arm_puts("basic# ");
+
+ arm_gets(line, ARM_MAX_CMD_STR_SIZE, '\n');
+
+ arm_exec(line);
+ }
+}
diff --git a/tests/arm64/common/basic/arm_math.c b/tests/arm64/common/basic/arm_math.c
new file mode 100644
index 0000000..0fbbf87
--- /dev/null
+++ b/tests/arm64/common/basic/arm_math.c
@@ -0,0 +1,117 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_math.c
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief commonly required math operations
+ */
+
+#include <arm_math.h>
+
+static const unsigned char byte_reverse_table[] =
+{
+ 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
+ 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
+ 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
+ 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
+ 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
+ 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
+ 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
+ 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
+ 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
+ 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
+ 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
+ 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
+ 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
+ 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
+ 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
+ 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
+};
+
+static inline u32 do_fls64(u64 value)
+{
+ u32 num_bits = 0;
+ if (value & 0xFFFF000000000000ULL) {
+ num_bits += 16;
+ value = value >> 16;
+ }
+ if (value & 0x0000FFFF00000000ULL) {
+ num_bits += 16;
+ value = value >> 16;
+ }
+ if (value & 0x00000000FFFF0000ULL) {
+ num_bits += 16;
+ value = value >> 16;
+ }
+ if (value & 0x000000000000FF00ULL) {
+ num_bits += 8;
+ value = value >> 8;
+ }
+ if (value & 0x00000000000000F0ULL) {
+ num_bits += 4;
+ value = value >> 4;
+ }
+ if (value & 0x000000000000000CULL) {
+ num_bits += 2;
+ value = value >> 2;
+ }
+ if (value & 0x0000000000000003ULL) {
+ num_bits += 2;
+ value = value >> 2;
+ }
+ return num_bits;
+}
+
+u64 do_udiv64(u64 dividend, u64 divisor, u64 * remainder)
+{
+ *remainder = (dividend % divisor);
+ return (dividend / divisor);
+}
+
+static inline u32 do_fls32(u32 value)
+{
+ u32 num_bits = 0;
+ if (value & 0xFFFF0000) {
+ num_bits += 16;
+ value = value >> 16;
+ }
+ if (value & 0x0000FF00) {
+ num_bits += 8;
+ value = value >> 8;
+ }
+ if (value & 0x000000F0) {
+ num_bits += 4;
+ value = value >> 4;
+ }
+ if (value & 0x0000000C) {
+ num_bits += 2;
+ value = value >> 2;
+ }
+ if (value & 0x00000003) {
+ num_bits += 2;
+ value = value >> 2;
+ }
+ return num_bits;
+}
+
+u32 do_udiv32(u32 dividend, u32 divisor, u32 * remainder)
+{
+ *remainder = (dividend % divisor);
+ return (dividend / divisor);
+}
+
diff --git a/tests/arm64/common/basic/arm_math.h b/tests/arm64/common/basic/arm_math.h
new file mode 100644
index 0000000..f0e1304
--- /dev/null
+++ b/tests/arm64/common/basic/arm_math.h
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_math.h
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief commonly required math operations
+ */
+
+#ifndef __ARM_MATH_H_
+#define __ARM_MATH_H_
+
+#include <arm_types.h>
+
+#define do_abs(x) ((x) < 0 ? -(x) : (x))
+
+static inline u64 arm_udiv64(u64 value, u64 divisor)
+{
+ return (value / divisor);
+}
+
+static inline u64 arm_umod64(u64 value, u64 divisor)
+{
+ return (value % divisor);
+}
+
+static inline u32 arm_udiv32(u32 value, u32 divisor)
+{
+ return (value / divisor);
+}
+
+static inline u32 arm_umod32(u32 value, u32 divisor)
+{
+ return (value % divisor);
+}
+
+static inline s32 arm_sdiv32(s32 value, s32 divisor)
+{
+ if ((value * divisor) < 0) {
+ return -(do_abs(value) / do_abs(divisor));
+ } else { /* positive value */
+ return (do_abs(value) / do_abs(divisor));
+ }
+}
+
+#endif /* __ARM_MATH_H_ */
diff --git a/tests/arm64/common/basic/arm_mmu.c b/tests/arm64/common/basic/arm_mmu.c
new file mode 100644
index 0000000..78cde71
--- /dev/null
+++ b/tests/arm64/common/basic/arm_mmu.c
@@ -0,0 +1,235 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_mmu_v7.c
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief source file for MMU functions
+ */
+
+#include <arm_board.h>
+#include <arm_inline_asm.h>
+#include <arm_defines.h>
+#include <arm_mmu.h>
+#include <arm_stdio.h>
+
+#if 0
+u32 __attribute__((aligned(TTBL_L1TBL_SIZE))) l1[TTBL_L1TBL_SIZE / 4];
+u32 __attribute__((aligned(TTBL_L2TBL_SIZE))) l2[TTBL_L2TBL_SIZE / 4];
+u32 l2_mapva;
+#endif
+
+u32 test_area_pa;
+u32 test_area_size;
+
+extern void _switch_to_user_mode (u32, u32);
+
+#define ARM_MMU_TEST_SWITCH_TO_USER() _switch_to_user_mode(0x0, 0x0)
+#define ARM_MMU_TEST_SWITCH_TO_SUPER() asm volatile("svc 0x1":::"memory", "cc")
+
+u64 test_data_abort_fsc;
+u64 test_data_abort_far;
+u64 test_data_abort_wnr;
+u64 test_data_abort_dom;
+u32 test_data_abort_result;
+
+void arm_sync_abort(struct pt_regs *regs)
+{
+ u64 esr, far, ec, iss, wnr;
+ u64 fsc;
+
+ esr = mrs(esr_el1);
+ far = mrs(far_el1);
+
+ ec = (esr & ESR_EC_MASK) >> ESR_EC_SHIFT;
+ iss = (esr & ESR_ISS_MASK) >> ESR_ISS_SHIFT;
+
+ switch (ec) {
+ case EC_TRAP_SVC_A64:
+ if((iss & 0xffff) == 1) {
+ /* Request to switch to supervisor mode */
+ regs->pstate &= ~PSR_MODE_MASK;
+ regs->pstate |= PSR_MODE_EL1t;
+ regs->pc += 4;
+ return;
+ }
+ break;
+ case EC_TRAP_LWREL_DATA_ABORT:
+ fsc = (iss & ISS_ABORT_FSC_MASK) >> ISS_ABORT_FSC_SHIFT;
+ wnr = (iss & ISS_ABORT_WNR_MASK) >> ISS_ABORT_WNR_SHIFT;
+ if ((fsc == test_data_abort_fsc) &&
+ (far == test_data_abort_far) &&
+ (wnr == test_data_abort_wnr)) {
+ test_data_abort_result = 1;
+ regs->pc += 4;
+ return;
+ }
+ break;
+ }
+ arm_printf("Bad synchronous exception @ PC: 0x%X\n", regs->pc);
+ arm_printf("ESR: 0x%08X (EC:0x%X, ISS:0x%X)\n", esr, ec, iss);
+ arm_printf("LR: 0x%X, FAR: 0x%X, PSTATE: 0x%X\n", regs->lr, far, regs->pstate);
+ arm_printf(" General Purpose Registers");
+ {
+ int ite;
+ for (ite = 0; ite < 30; ite++) {
+ if (ite % 2 == 0)
+ arm_printf("\n");
+ arm_printf(" X%02d=0x%016x ", ite, regs->gpr[ite]);
+ }
+ }
+ arm_printf("\n");
+ while(1);
+}
+
+bool arm_mmu_is_enabled(void)
+{
+ u32 sctlr = mrs(sctlr_el1);
+
+ if (sctlr & SCTLR_M_MASK) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+extern u8 _code_start;
+extern u8 _code_end;
+
+void arm_mmu_setup(void)
+{
+ u64 *l1;
+ u64 val, sec_tmpl = 0x0;
+ u32 sctlr = mrs(sctlr_el1);
+
+ /* If MMU already enabled then return */
+ if (sctlr & SCTLR_M_MASK) {
+ return;
+ }
+
+ /* We place the L1 page table at a page-aligned address after _code_end */
+ l1 = (u64 *)(((u64)&_code_end + TTBL_TABLE_SIZE) & ~(TTBL_TABLE_SIZE - 1));
+
+ /* Reset memory for L1 */
+ for (val = 0; val < (TTBL_TABLE_ENTCNT); val++) {
+ l1[val] = 0x0;
+ }
+
+ /* SuperSection entry template for code */
+ sec_tmpl = (TTBL_STAGE1_LOWER_AF_MASK | TTBL_VALID_MASK);
+ sec_tmpl |= (TTBL_AP_SRW_U << TTBL_STAGE1_LOWER_AP_SHIFT);
+ sec_tmpl |= (1 << 11);
+
+ /* Create 1GB super-section entry for Device Region from 0x00_0000_0000 */
+ val = ((AINDEX_SO << TTBL_STAGE1_LOWER_AINDEX_SHIFT) & TTBL_STAGE1_LOWER_AINDEX_MASK);
+ val |= (0x0 << TTBL_STAGE1_LOWER_SH_SHIFT) | 0x00000000; /* Non-shareable */
+ l1[0x00000000/(1 << 30)] = (sec_tmpl | val);
+
+ /* Create 1GB super-section entry for RAM from 0x00_8000_0000 */
+ val = ((AINDEX_NORMAL_WB << TTBL_STAGE1_LOWER_AINDEX_SHIFT) & TTBL_STAGE1_LOWER_AINDEX_MASK);
+ val |= (0x3 << TTBL_STAGE1_LOWER_SH_SHIFT) | 0x80000000; /* Inner-shareable */
+ l1[0x80000000/(1 << 30)] = (sec_tmpl | val);
+
+ /* Setup Translation Control Register */
+ val = 0;
+ /* Upto 39bits of VA will allow us to continue with 3 levels of stage-1 page-tables
+ * so we program TCR_EL1[T0SZ] = 0x19 */
+ val &= (~TCR_T0SZ_MASK);
+ val |= (0x19 << TCR_T0SZ_SHIFT);
+ val &= (~TCR_PS_MASK);
+ val |= (0x2 << TCR_PS_SHIFT); /* PASize: 0x2 => PA[39:0] */
+ val &= (~TCR_SH0_MASK);
+ val |= (0x3 << TCR_SH0_SHIFT); /* Shareability: 0x3 - inner-shareable */
+ val &= (~TCR_ORGN0_MASK);
+ val |= (0x1 << TCR_ORGN0_SHIFT); /* Cacheability: 0x1 - write-back */
+ val &= (~TCR_IRGN0_MASK);
+ val |= (0x1 << TCR_IRGN0_SHIFT); /* Cacheability: 0x1 - write-back */
+ msr(tcr_el1, val);
+
+ /* Initialize MAIR */
+ msr(mair_el1, MAIR_INITVAL);
+
+ /* Write TTBR0 */
+ msr(ttbr0_el1, (u64)l1);
+
+ /* Enable MMU */
+ sctlr |= SCTLR_I_MASK | SCTLR_C_MASK | SCTLR_M_MASK | SCTLR_AFE_MASK;
+ msr(sctlr_el1, sctlr);
+
+ asm("dsb sy\n\tisb\n\t":::"memory", "cc");
+
+ return;
+}
+
+void data_cache_flush_all(void)
+{
+ register u32 val, set, way, line, i, j;
+ register int slog, wlog, llog, loc;
+ int clevel = 0, clidr;
+
+ dsb();
+ isb();
+ clidr = mrs(CLIDR_EL1);
+ loc = ((clidr >> 24) & 0x7);
+
+ while(clevel < loc) {
+ /* Select the cache-level in CCSELR_EL1 */
+ val = (clevel << 1);
+ msr(CSSELR_EL1, val);
+ isb();
+ /* Read the Cache Sized ID Register */
+ val = mrs(CCSIDR_EL1);
+ set = ((val & 0x0FFFE000) >> 13) + 1;
+ way = ((val & 0x00001FF8) >> 3) + 1;
+ line = (1 << (((val & 0x7) >> 0) + 2)) * sizeof(unsigned int);
+
+#define log2n(n, val) { asm("clz %0, %1":"=r"(val):"r"(n)); val = (63 - val); }
+
+ log2n(set, slog);
+ log2n(way, wlog);
+ log2n(line, llog);
+
+ for (i=0; i<set; i++) {
+ for (j=0; j<way; j++) {
+ val = (j << (32-wlog)) | (i << llog) | (clevel << 1);
+ asm volatile("dc cisw, %0"::"r"(val):"memory","cc");
+ }
+ }
+
+ dsb();
+ isb();
+ clevel++;
+ }
+}
+
+void arm_mmu_cleanup(void)
+{
+ u32 sctlr = mrs(sctlr_el1);
+
+ /* If MMU already disabled then return */
+ if (!(sctlr & SCTLR_M_MASK)) {
+ return;
+ }
+
+ data_cache_flush_all();
+ /* Disable MMU */
+ sctlr &= ~SCTLR_M_MASK;
+ msr_sync(sctlr_el1, sctlr);
+
+ return;
+}
+
diff --git a/tests/arm64/common/basic/arm_mmu.h b/tests/arm64/common/basic/arm_mmu.h
new file mode 100644
index 0000000..9fbea7d
--- /dev/null
+++ b/tests/arm64/common/basic/arm_mmu.h
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_mmu.h
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief Header file for MMU functions
+ */
+
+#ifndef __ARM_MMU_H_
+#define __ARM_MMU_H_
+
+#include <arm_types.h>
+
+void arm_sync_abort(struct pt_regs *regs);
+void arm_mmu_section_test(u32 * total, u32 * pass, u32 * fail);
+void arm_mmu_page_test(u32 * total, u32 * pass, u32 * fail);
+bool arm_mmu_is_enabled(void);
+void arm_mmu_setup(void);
+void arm_mmu_cleanup(void);
+
+#endif /* __ARM_MMU_H_ */
diff --git a/tests/arm64/common/basic/arm_stdio.c b/tests/arm64/common/basic/arm_stdio.c
new file mode 100644
index 0000000..a65d2b0
--- /dev/null
+++ b/tests/arm64/common/basic/arm_stdio.c
@@ -0,0 +1,360 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_stdio.c
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief source file for common input/output functions
+ */
+
+#include <arm_board.h>
+#include <arm_stdio.h>
+
+void arm_stdio_init(void)
+{
+ int rc;
+
+ rc = arm_board_serial_init();
+ if (rc) {
+ while (1);
+ }
+}
+
+void arm_puts(const char * str)
+{
+ while (*str) {
+ arm_board_serial_putc(*str);
+ str++;
+ }
+}
+
+void arm_gets(char *s, int maxwidth, char endchar)
+{
+ char *retval;
+ char ch;
+ retval = s;
+ ch = arm_board_serial_getc();
+ while (ch != endchar && maxwidth > 0) {
+ *retval = ch;
+ retval++;
+ maxwidth--;
+ if (maxwidth == 0)
+ break;
+ ch = arm_board_serial_getc();
+ }
+ *retval = '\0';
+ return;
+}
+
+#define PAD_RIGHT 1
+#define PAD_ZERO 2
+#define PAD_ALTERNATE 4
+#define PRINT_BUF_LEN 64
+
+#define va_start(v,l) __builtin_va_start((v),l)
+#define va_end __builtin_va_end
+#define va_arg __builtin_va_arg
+typedef __builtin_va_list va_list;
+
+static void printc(char **out, u32 *out_len, char ch)
+{
+ if (out) {
+ if (*out) {
+ if (out_len && (0 < *out_len)) {
+ **out = ch;
+ ++(*out);
+ (*out_len)--;
+ } else {
+ **out = ch;
+ ++(*out);
+ }
+ }
+ } else {
+ arm_board_serial_putc(ch);
+ }
+}
+
+static int prints(char **out, u32 *out_len, const char *string, int width, int flags)
+{
+ int pc = 0;
+ char padchar = ' ';
+
+ if (width > 0) {
+ int len = 0;
+ const char *ptr;
+ for (ptr = string; *ptr; ++ptr)
+ ++len;
+ if (len >= width)
+ width = 0;
+ else
+ width -= len;
+ if (flags & PAD_ZERO)
+ padchar = '0';
+ }
+ if (!(flags & PAD_RIGHT)) {
+ for (; width > 0; --width) {
+ printc(out, out_len, padchar);
+ ++pc;
+ }
+ }
+ for (; *string; ++string) {
+ printc(out, out_len, *string);
+ ++pc;
+ }
+ for (; width > 0; --width) {
+ printc(out, out_len, padchar);
+ ++pc;
+ }
+
+ return pc;
+}
+
+static int printi(char **out, u32 *out_len, long long i, int b, int sg,
+ int width, int flags, int letbase)
+{
+ char print_buf[PRINT_BUF_LEN];
+ char *s;
+ int t, neg = 0, pc = 0;
+ unsigned long long u = i;
+
+ if (sg && b == 10 && i < 0) {
+ neg = 1;
+ u = -i;
+ }
+
+ s = print_buf + PRINT_BUF_LEN - 1;
+ *s = '\0';
+
+ if (!u) {
+ *--s = '0';
+ } else {
+ while (u) {
+ t = (u % b);
+ if (t >= 10)
+ t += letbase - '0' - 10;
+ *--s = t + '0';
+ u = (u / b);
+ }
+ }
+
+ if (flags & PAD_ALTERNATE) {
+ if ((b == 16) && (letbase == 'A')) {
+ *--s = 'X';
+ } else if ((b == 16) && (letbase == 'a')) {
+ *--s = 'x';
+ }
+ *--s = '0';
+ }
+
+ if (neg) {
+ if (width && (flags & PAD_ZERO)) {
+ printc(out, out_len, '-');
+ ++pc;
+ --width;
+ } else {
+ *--s = '-';
+ }
+ }
+
+ return pc + prints(out, out_len, s, width, flags);
+}
+
+static int print(char **out, u32 *out_len, const char *format, va_list args)
+{
+ int width, flags, acnt = 0;
+ int pc = 0;
+ char scr[2];
+ unsigned long long tmp;
+
+ for (; *format != 0; ++format) {
+ if (*format == '%') {
+ ++format;
+ width = flags = 0;
+ if (*format == '\0')
+ break;
+ if (*format == '%')
+ goto out;
+ /* Get flags */
+ if (*format == '-') {
+ ++format;
+ flags = PAD_RIGHT;
+ }
+ if (*format == '#') {
+ ++format;
+ flags |= PAD_ALTERNATE;
+ }
+ while (*format == '0') {
+ ++format;
+ flags |= PAD_ZERO;
+ }
+ /* Get width */
+ for (; *format >= '0' && *format <= '9'; ++format) {
+ width *= 10;
+ width += *format - '0';
+ }
+ if (*format == 's') {
+ char *s = va_arg(args, char *);
+ acnt += sizeof(char *);
+ pc += prints(out, out_len,
+ s ? s : "(null)", width, flags);
+ continue;
+ }
+ if (*format == 'd') {
+ pc += printi(out, out_len,
+ va_arg(args, int),
+ 10, 1, width, flags, '0');
+ acnt += sizeof(int);
+ continue;
+ }
+ if (*format == 'x') {
+ pc += printi(out, out_len,
+ va_arg(args, unsigned int),
+ 16, 0, width, flags, 'a');
+ acnt += sizeof(unsigned int);
+ continue;
+ }
+ if (*format == 'X') {
+ pc += printi(out, out_len,
+ va_arg(args, unsigned int),
+ 16, 0, width, flags, 'A');
+ acnt += sizeof(unsigned int);
+ continue;
+ }
+ if (*format == 'u') {
+ pc += printi(out, out_len,
+ va_arg(args, unsigned int),
+ 10, 0, width, flags, 'a');
+ acnt += sizeof(unsigned int);
+ continue;
+ }
+ if (*format == 'p') {
+ pc += printi(out, out_len,
+ va_arg(args, unsigned long),
+ 16, 0, width, flags, 'a');
+ acnt += sizeof(unsigned long);
+ continue;
+ }
+ if (*format == 'P') {
+ pc += printi(out, out_len,
+ va_arg(args, unsigned long),
+ 16, 0, width, flags, 'A');
+ acnt += sizeof(unsigned long);
+ continue;
+ }
+ if (*format == 'l' && *(format + 1) == 'l') {
+ while (acnt & (sizeof(unsigned long long)-1)) {
+ va_arg(args, int);
+ acnt += sizeof(int);
+ }
+ if (sizeof(unsigned long long) ==
+ sizeof(unsigned long)) {
+ tmp = va_arg(args, unsigned long long);
+ acnt += sizeof(unsigned long long);
+ } else {
+ ((unsigned long *)&tmp)[0] =
+ va_arg(args, unsigned long);
+ ((unsigned long *)&tmp)[1] =
+ va_arg(args, unsigned long);
+ acnt += 2*sizeof(unsigned long);
+ }
+ if (*(format + 2) == 'u') {
+ format += 2;
+ pc += printi(out, out_len, tmp,
+ 10, 0, width, flags, 'a');
+ } else if (*(format + 2) == 'x') {
+ format += 2;
+ pc += printi(out, out_len, tmp,
+ 16, 0, width, flags, 'a');
+ } else if (*(format + 2) == 'X') {
+ format += 2;
+ pc += printi(out, out_len, tmp,
+ 16, 0, width, flags, 'A');
+ } else {
+ format += 1;
+ pc += printi(out, out_len, tmp,
+ 10, 1, width, flags, '0');
+ }
+ continue;
+ } else if (*format == 'l') {
+ if (*(format + 1) == 'x') {
+ format += 1;
+ pc += printi(out, out_len,
+ va_arg(args, unsigned long),
+ 16, 0, width, flags, 'a');
+ acnt += sizeof(unsigned long);
+ } else if (*(format + 1) == 'X') {
+ format += 1;
+ pc += printi(out, out_len,
+ va_arg(args, unsigned long),
+ 16, 0, width, flags, 'A');
+ acnt += sizeof(unsigned long);
+ } else {
+ pc += printi(out, out_len,
+ va_arg(args, long),
+ 10, 1, width, flags, '0');
+ acnt += sizeof(long);
+ }
+ }
+ if (*format == 'c') {
+ /* char are converted to int then pushed on the stack */
+ scr[0] = va_arg(args, int);
+ scr[1] = '\0';
+ pc += prints(out, out_len, scr, width, flags);
+ acnt += sizeof(int);
+ continue;
+ }
+ } else {
+out:
+ printc(out, out_len, *format);
+ ++pc;
+ }
+ }
+ if (out)
+ **out = '\0';
+ return pc;
+}
+
+int arm_sprintf(char *out, const char *format, ...)
+{
+ va_list args;
+ int retval;
+ va_start(args, format);
+ retval = print(&out, NULL, format, args);
+ va_end(args);
+ return retval;
+}
+
+int arm_snprintf(char *out, u32 out_sz, const char *format, ...)
+{
+ va_list args;
+ int retval;
+ va_start(args, format);
+ retval = print(&out, &out_sz, format, args);
+ va_end(args);
+ return retval;
+}
+
+int arm_printf(const char *format, ...)
+{
+ va_list args;
+ int retval;
+ va_start(args, format);
+ retval = print(NULL, NULL, format, args);
+ va_end(args);
+ return retval;
+}
+
diff --git a/tests/arm64/common/basic/arm_stdio.h b/tests/arm64/common/basic/arm_stdio.h
new file mode 100644
index 0000000..2e29165
--- /dev/null
+++ b/tests/arm64/common/basic/arm_stdio.h
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_stdio.h
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief Header file for common input/output functions
+ */
+
+#ifndef __ARM_STDIO_H_
+#define __ARM_STDIO_H_
+
+#include <arm_types.h>
+
+void arm_putc(char ch);
+char arm_getc(void);
+void arm_stdio_init(void);
+void arm_puts(const char * str);
+void arm_gets(char *s, int maxwidth, char endchar);
+int arm_sprintf(char *out, const char *format, ...);
+int arm_snprintf(char *out, u32 out_sz, const char *format, ...);
+int arm_printf(const char *format, ...);
+
+#endif /* __ARM_STDIO_H_ */
diff --git a/tests/arm64/common/basic/arm_string.c b/tests/arm64/common/basic/arm_string.c
new file mode 100644
index 0000000..dc8beca
--- /dev/null
+++ b/tests/arm64/common/basic/arm_string.c
@@ -0,0 +1,357 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_string.c
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief source file for common string functions
+ */
+
+#include <arm_string.h>
+#include <arm_math.h>
+
+void *arm_memcpy(void *dest, const void *src, unsigned int count)
+{
+ u8 *dst8 = (u8 *) dest;
+ u8 *src8 = (u8 *) src;
+
+ if (count & 1) {
+ dst8[0] = src8[0];
+ dst8 += 1;
+ src8 += 1;
+ }
+
+ count /= 2;
+ while (count--) {
+ dst8[0] = src8[0];
+ dst8[1] = src8[1];
+
+ dst8 += 2;
+ src8 += 2;
+ }
+
+ return dest;
+}
+
+void *arm_memmove(void *dest, const void *src, unsigned int count)
+{
+ u8 *dst8 = (u8 *) dest;
+ const u8 *src8 = (u8 *) src;
+
+ if(dest == src)
+ return dest;
+
+ if (src8 > dst8) {
+ if (count & 1) {
+ dst8[0] = src8[0];
+ dst8 += 1;
+ src8 += 1;
+ }
+
+ count /= 2;
+ while (count--) {
+ dst8[0] = src8[0];
+ dst8[1] = src8[1];
+
+ dst8 += 2;
+ src8 += 2;
+ }
+ } else {
+ dst8 += count;
+ src8 += count;
+
+ if (count & 1) {
+ dst8 -= 1;
+ src8 -= 1;
+ dst8[0] = src8[0];
+ }
+
+ count /= 2;
+ while (count--) {
+ dst8 -= 2;
+ src8 -= 2;
+
+ dst8[0] = src8[0];
+ dst8[1] = src8[1];
+ }
+ }
+
+ return dest;
+}
+
+void *arm_memset(void *dest, int c, unsigned int count)
+{
+ u8 *dst8 = (u8 *) dest;
+ u8 ch = (u8) c;
+
+ if (count & 1) {
+ dst8[0] = ch;
+ dst8 += 1;
+ }
+
+ count /= 2;
+ while (count--) {
+ dst8[0] = ch;
+ dst8[1] = ch;
+ dst8 += 2;
+ }
+
+ return dest;
+}
+
+int arm_memcmp(const void *s1, const void *s2, unsigned int count)
+{
+ u8 *p1 = (u8 *) s1;
+ u8 *p2 = (u8 *) s2;
+ if (count != 0) {
+ do {
+ if (*p1++ != *p2++)
+ return (*--p1 - *--p2);
+ } while (--count != 0);
+ }
+ return (0);
+}
+
+char *arm_memchr(const char *p, int ch, int count)
+{
+ int i;
+ for(i=0; i<count; i++) {
+ if ((*p)==ch) {
+ return((char *)p);
+ }
+ p++;
+ }
+ return((char *)NULL);
+}
+
+char *arm_strchr(const char *p, int ch)
+{
+ do {
+ if ((*p)==ch) {
+ return((char *)p);
+ }
+ } while((*p++)!='\0');
+ return((char *)NULL);
+}
+
+unsigned int arm_strlen(const char *s)
+{
+ unsigned int ret = 0;
+ while (s[ret]) {
+ ret++;
+ }
+ return ret;
+}
+
+char *arm_strcpy(char *dest, const char *src)
+{
+ u32 i;
+ for (i = 0; src[i] != '\0'; ++i)
+ dest[i] = src[i];
+ dest[i] = '\0';
+ return dest;
+}
+
+char *arm_strcat(char *dest, const char *src)
+{
+ arm_strcpy(&dest[arm_strlen(dest)], src);
+
+ return dest;
+}
+
+int arm_strcmp(const char *a, const char *b)
+{
+ while (*a == *b) {
+ if (*a == '\0' || *b == '\0') {
+ return (unsigned char)*a - (unsigned char)*b;
+ }
+ ++a;
+ ++b;
+ }
+ return (unsigned char)*a - (unsigned char)*b;
+}
+
+int arm_str2int(char *src)
+{
+ int val = 0, pos = 0, minus = 0;
+
+ if (src[pos] == '-') {
+ minus = 1;
+ pos++;
+ }
+
+ while (src[pos]) {
+ val = 10 * val + (src[pos] - '0');
+ pos++;
+ }
+
+ return (minus) ? -val : val;
+}
+
+void arm_int2str(char *dst, int src)
+{
+ int val, count = 0, pos = 0;
+ static const char intchars[] = "0123456789";
+
+ val = src;
+ while (val) {
+ count++;
+ val = val / 10;
+ }
+ if (src < 0) {
+ count++;
+ }
+
+ val = (src < 0) ? -src : src;
+ while (val) {
+ dst[count - pos - 1] = intchars[val % 10];
+ val = val / 10;
+ pos++;
+ }
+ if (src < 0) {
+ dst[0] = '-';
+ }
+
+ if (count == 0) {
+ dst[count] = '0';
+ count++;
+ }
+
+ dst[count] = '\0';
+}
+
+void arm_ulonglong2str(char *dst, unsigned long long src)
+{
+ unsigned long long val;
+ int count = 0, pos = 0;
+ static const char intchars[] = "0123456789";
+
+ val = src;
+ while (val) {
+ count++;
+ val = val / 10;
+ }
+ if (src < 0) {
+ count++;
+ }
+
+ val = (src < 0) ? -src : src;
+ while (val) {
+ dst[count - pos - 1] = intchars[val % 10];
+ val = val / 10;
+ pos++;
+ }
+ if (src < 0) {
+ dst[0] = '-';
+ }
+
+ if (count == 0) {
+ dst[count] = '0';
+ count++;
+ }
+
+ dst[count] = '\0';
+}
+
+unsigned int arm_hexstr2uint(char * src)
+{
+ unsigned int val = 0x0;
+ int pos = 0;
+
+ if ((src[0] == '0') && (src[1] == 'x')) {
+ pos = 2;
+ }
+
+ while (src[pos]) {
+ if (('0' <= src[pos]) && (src[pos] <= '9')) {
+ val = val * 16 + (src[pos] - '0');
+ } else if (('A' <= src[pos]) && (src[pos] <= 'F')) {
+ val = val * 16 + (src[pos] - 'A' + 10);
+ } else if (('a' <= src[pos]) && (src[pos] <= 'f')) {
+ val = val * 16 + (src[pos] - 'a' + 10);
+ }
+ pos++;
+ }
+
+ return val;
+}
+
+unsigned long long arm_hexstr2ulonglong(char * src)
+{
+ unsigned long long val = 0x0;
+ int pos = 0;
+
+ if ((src[0] == '0') && (src[1] == 'x')) {
+ pos = 2;
+ }
+
+ while (src[pos]) {
+ if (('0' <= src[pos]) && (src[pos] <= '9')) {
+ val = val * 16 + (src[pos] - '0');
+ } else if (('A' <= src[pos]) && (src[pos] <= 'F')) {
+ val = val * 16 + (src[pos] - 'A' + 10);
+ } else if (('a' <= src[pos]) && (src[pos] <= 'f')) {
+ val = val * 16 + (src[pos] - 'a' + 10);
+ }
+ pos++;
+ }
+
+ return val;
+}
+
+void arm_uint2hexstr(char *dst, unsigned int src)
+{
+ int ite, pos = 0;
+ static const char hexchars[] = "0123456789ABCDEF";
+
+ for (ite = 0; ite < 8; ite++) {
+ if ((pos == 0) && !((src >> (4 * (8 - ite - 1))) & 0xF)) {
+ continue;
+ }
+ dst[pos] = hexchars[(src >> (4 * (8 - ite - 1))) & 0xF];
+ pos++;
+ }
+
+ if (pos == 0) {
+ dst[pos] = '0';
+ pos++;
+ }
+
+ dst[pos] = '\0';
+}
+
+void arm_ulonglong2hexstr(char *dst, unsigned long long src)
+{
+ int ite, pos = 0;
+ static const char hexchars[] = "0123456789ABCDEF";
+
+ for (ite = 0; ite < 16; ite++) {
+ if ((pos == 0) && !((src >> (4 * (16 - ite - 1))) & 0xF)) {
+ continue;
+ }
+ dst[pos] = hexchars[(src >> (4 * (16 - ite - 1))) & 0xF];
+ pos++;
+ }
+
+ if (pos == 0) {
+ dst[pos] = '0';
+ pos++;
+ }
+
+ dst[pos] = '\0';
+}
+
diff --git a/tests/arm64/common/basic/arm_string.h b/tests/arm64/common/basic/arm_string.h
new file mode 100644
index 0000000..ea391ad
--- /dev/null
+++ b/tests/arm64/common/basic/arm_string.h
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_string.h
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief Header file for common string functions
+ */
+
+#ifndef __ARM_STRING_H_
+#define __ARM_STRING_H_
+
+#include <arm_types.h>
+
+void *arm_memcpy(void *dest, const void *src, unsigned int count);
+void *arm_memmove(void *dest, const void *src, unsigned int count);
+void *arm_memset(void *dest, int c, unsigned int count);
+int arm_memcmp(const void *s1, const void *s2, unsigned int count);
+char *arm_memchr(const char *p, int ch, int count);
+char *arm_strchr(const char *p, int ch);
+char *arm_strcpy(char *dest, const char *src);
+char *arm_strcat(char *dest, const char *src);
+int arm_strcmp(const char *a, const char *b);
+size_t arm_strlen(const char *s);
+int arm_str2int(char * src);
+void arm_int2str(char * dst, int src);
+void arm_ulonglong2str(char * dst, unsigned long long src);
+unsigned int arm_hexstr2uint(char * src);
+unsigned long long arm_hexstr2ulonglong(char * src);
+void arm_uint2hexstr(char * dst, unsigned int src);
+void arm_ulonglong2hexstr(char * dst, unsigned long long src);
+
+#endif /* __ARM_STRING_H_ */
diff --git a/tests/arm64/common/basic/arm_types.h b/tests/arm64/common/basic/arm_types.h
new file mode 100644
index 0000000..b266fd0
--- /dev/null
+++ b/tests/arm64/common/basic/arm_types.h
@@ -0,0 +1,88 @@
+/**
+ * Copyright (c) 2010 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_types.h
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief common header file for typedefs
+ */
+#ifndef _ARM_TYPES_H__
+#define _ARM_TYPES_H__
+
+typedef char s8;
+typedef short s16;
+typedef int s32;
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned int size_t;
+typedef unsigned int bool;
+typedef unsigned int ulong;
+
+/** Boolean macros */
+#define TRUE 1
+#define FALSE 0
+#define NULL ((void *)0)
+
+#define stringify(s) tostring(s)
+#define tostring(s) #s
+
+typedef long long s64;
+typedef unsigned long long u64;
+typedef unsigned int irq_flags_t;
+typedef unsigned long virtual_addr_t;
+typedef unsigned long virtual_size_t;
+typedef unsigned long physical_addr_t;
+typedef unsigned long physical_size_t;
+
+typedef struct {
+ volatile long counter;
+} atomic_t;
+
+struct pt_regs {
+ u64 gpr[30]; /* X0 - X29 */
+ u64 lr;
+ u64 sp; /* Stack Pointer */
+ u64 pc; /* Program Counter */
+ u64 pstate; /* PState/SPSR */
+} __attribute ((packed)) ;
+
+#define _swab32(x) ((u32)( \
+ (((u32)(x) & (u32)0x000000ffU) << 24) | \
+ (((u32)(x) & (u32)0x0000ff00U) << 8) | \
+ (((u32)(x) & (u32)0x00ff0000U) >> 8) | \
+ (((u32)(x) & (u32)0xff000000U) >> 24)))
+
+#define _swab64(x) ((u64)( \
+ (((u64)(x) & (u64)0x00000000000000ffULL) << 56) | \
+ (((u64)(x) & (u64)0x000000000000ff00ULL) << 40) | \
+ (((u64)(x) & (u64)0x0000000000ff0000ULL) << 24) | \
+ (((u64)(x) & (u64)0x00000000ff000000ULL) << 8) | \
+ (((u64)(x) & (u64)0x000000ff00000000ULL) >> 8) | \
+ (((u64)(x) & (u64)0x0000ff0000000000ULL) >> 24) | \
+ (((u64)(x) & (u64)0x00ff000000000000ULL) >> 40) | \
+ (((u64)(x) & (u64)0xff00000000000000ULL) >> 56)))
+
+#define cpu_to_be32(x) _swab32(x)
+#define cpu_to_be64(x) _swab64(x)
+#define be32_to_cpu(x) _swab32(x)
+#define be64_to_cpu(x) _swab64(x)
+#define be32_to_cpup(x) _swab32(*(x))
+
+#define max(a,b) ((a) < (b) ? (b) : (a))
+
+#endif /* __ARM_TYPES_H__ */
diff --git a/tests/arm64/common/basic/dhry.h b/tests/arm64/common/basic/dhry.h
new file mode 100644
index 0000000..25f8f50
--- /dev/null
+++ b/tests/arm64/common/basic/dhry.h
@@ -0,0 +1,395 @@
+/*
+ ****************************************************************************
+ *
+ * "DHRYSTONE" Benchmark Program
+ * -----------------------------
+ *
+ * Version: C, Version 2.1
+ *
+ * File: dhry.h (part 1 of 3)
+ *
+ * Date: May 25, 1988
+ *
+ * Updated By: Anup Patel (an...@brainfault.org) for portablity.
+ *
+ * Author: Reinhold P. Weicker
+ * Siemens AG, E STE 35
+ * Postfach 3240
+ * 8520 Erlangen
+ * Germany (West)
+ * Phone: [xxx-49]-9131-7-20330
+ * (8-17 Central European Time)
+ * Usenet: ..!mcvax!unido!estevax!weicker
+ *
+ * Original Version (in Ada) published in
+ * "Communications of the ACM" vol. 27., no. 10 (Oct. 1984),
+ * pp. 1013 - 1030, together with the statistics
+ * on which the distribution of statements etc. is based.
+ *
+ * In this C version, the following C library functions are used:
+ * - strcpy, strcmp (inside the measurement loop)
+ * - printf, scanf (outside the measurement loop)
+ * In addition, Berkeley UNIX system calls "times ()" or "time ()"
+ * are used for execution time measurement. For measurements
+ * on other systems, these calls have to be changed.
+ *
+ * Collection of Results:
+ * Reinhold Weicker (address see above) and
+ *
+ * Rick Richardson
+ * PC Research. Inc.
+ * 94 Apple Orchard Drive
+ * Tinton Falls, NJ 07724
+ * Phone: (201) 389-8963 (9-17 EST)
+ * Usenet: ...!uunet!pcrat!rick
+ *
+ * Please send results to Rick Richardson and/or Reinhold Weicker.
+ * Complete information should be given on hardware and software used.
+ * Hardware information includes: Machine type, CPU, type and size
+ * of caches; for microprocessors: clock frequency, memory speed
+ * (number of wait states).
+ * Software information includes: Compiler (and runtime library)
+ * manufacturer and version, compilation switches, OS version.
+ * The Operating System version may give an indication about the
+ * compiler; Dhrystone itself performs no OS calls in the measurement loop.
+ *
+ * The complete output generated by the program should be mailed
+ * such that at least some checks for correctness can be made.
+ *
+ ***************************************************************************
+ *
+ * History: This version C/2.1 has been made for two reasons:
+ *
+ * 1) There is an obvious need for a common C version of
+ * Dhrystone, since C is at present the most popular system
+ * programming language for the class of processors
+ * (microcomputers, minicomputers) where Dhrystone is used most.
+ * There should be, as far as possible, only one C version of
+ * Dhrystone such that results can be compared without
+ * restrictions. In the past, the C versions distributed
+ * by Rick Richardson (Version 1.1) and by Reinhold Weicker
+ * had small (though not significant) differences.
+ *
+ * 2) As far as it is possible without changes to the Dhrystone
+ * statistics, optimizing compilers should be prevented from
+ * removing significant statements.
+ *
+ * This C version has been developed in cooperation with
+ * Rick Richardson (Tinton Falls, NJ), it incorporates many
+ * ideas from the "Version 1.1" distributed previously by
+ * him over the UNIX network Usenet.
+ * I also thank Chaim Benedelac (National Semiconductor),
+ * David Ditzel (SUN), Earl Killian and John Mashey (MIPS),
+ * Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley)
+ * for their help with comments on earlier versions of the
+ * benchmark.
+ *
+ * Changes: In the initialization part, this version follows mostly
+ * Rick Richardson's version distributed via Usenet, not the
+ * version distributed earlier via floppy disk by Reinhold Weicker.
+ * As a concession to older compilers, names have been made
+ * unique within the first 8 characters.
+ * Inside the measurement loop, this version follows the
+ * version previously distributed by Reinhold Weicker.
+ *
+ * At several places in the benchmark, code has been added,
+ * but within the measurement loop only in branches that
+ * are not executed. The intention is that optimizing compilers
+ * should be prevented from moving code out of the measurement
+ * loop, or from removing code altogether. Since the statements
+ * that are executed within the measurement loop have NOT been
+ * changed, the numbers defining the "Dhrystone distribution"
+ * (distribution of statements, operand types and locality)
+ * still hold. Except for sophisticated optimizing compilers,
+ * execution times for this version should be the same as
+ * for previous versions.
+ *
+ * Since it has proven difficult to subtract the time for the
+ * measurement loop overhead in a correct way, the loop check
+ * has been made a part of the benchmark. This does have
+ * an impact - though a very minor one - on the distribution
+ * statistics which have been updated for this version.
+ *
+ * All changes within the measurement loop are described
+ * and discussed in the companion paper "Rationale for
+ * Dhrystone version 2".
+ *
+ * Because of the self-imposed limitation that the order and
+ * distribution of the executed statements should not be
+ * changed, there are still cases where optimizing compilers
+ * may not generate code for some statements. To a certain
+ * degree, this is unavoidable for small synthetic benchmarks.
+ * Users of the benchmark are advised to check code listings
+ * whether code is generated for all statements of Dhrystone.
+ *
+ * Version 2.1 is identical to version 2.0 distributed via
+ * the UNIX network Usenet in March 1988 except that it corrects
+ * some minor deficiencies that were found by users of version 2.0.
+ * The only change within the measurement loop is that a
+ * non-executed "else" part was added to the "if" statement in
+ * Func_3, and a non-executed "else" part removed from Proc_3.
+ *
+ ***************************************************************************
+ *
+ * Defines: The following "Defines" are possible:
+ * -DREG=register (default: Not defined)
+ * As an approximation to what an average C programmer
+ * might do, the "register" storage class is applied
+ * (if enabled by -DREG=register)
+ * - for local variables, if they are used (dynamically)
+ * five or more times
+ * - for parameters if they are used (dynamically)
+ * six or more times
+ * Note that an optimal "register" strategy is
+ * compiler-dependent, and that "register" declarations
+ * do not necessarily lead to faster execution.
+ * -DNOSTRUCTASSIGN (default: Not defined)
+ * Define if the C compiler does not support
+ * assignment of structures.
+ * -DNOENUMS (default: Not defined)
+ * Define if the C compiler does not support
+ * enumeration types.
+ *
+ ***************************************************************************
+ *
+ * Compilation model and measurement (IMPORTANT):
+ *
+ * This C version of Dhrystone consists of three files:
+ * - dhry.h (this file, containing global definitions and comments)
+ * - dhry_1.c (containing the code corresponding to Ada package Pack_1)
+ * - dhry_2.c (containing the code corresponding to Ada package Pack_2)
+ *
+ * The following "ground rules" apply for measurements:
+ * - Separate compilation
+ * - No procedure merging
+ * - Otherwise, compiler optimizations are allowed but should be indicated
+ * - Default results are those without register declarations
+ * See the companion paper "Rationale for Dhrystone Version 2" for a more
+ * detailed discussion of these ground rules.
+ *
+ * For 16-Bit processors (e.g. 80186, 80286), times for all compilation
+ * models ("small", "medium", "large" etc.) should be given if possible,
+ * together with a definition of these models for the compiler system used.
+ *
+ **************************************************************************
+ *
+ * Dhrystone (C version) statistics:
+ *
+ * [Comment from the first distribution, updated for version 2.
+ * Note that because of language differences, the numbers are slightly
+ * different from the Ada version.]
+ *
+ * The following program contains statements of a high level programming
+ * language (here: C) in a distribution considered representative:
+ *
+ * assignments 52 (51.0 %)
+ * control statements 33 (32.4 %)
+ * procedure, function calls 17 (16.7 %)
+ *
+ * 103 statements are dynamically executed. The program is balanced with
+ * respect to the three aspects:
+ *
+ * - statement type
+ * - operand type
+ * - operand locality
+ * operand global, local, parameter, or constant.
+ *
+ * The combination of these three aspects is balanced only approximately.
+ *
+ * 1. Statement Type:
+ * ----------------- number
+ *
+ * V1 = V2 9
+ * (incl. V1 = F(..)
+ * V = Constant 12
+ * Assignment, 7
+ * with array element
+ * Assignment, 6
+ * with record component
+ * --
+ * 34 34
+ *
+ * X = Y +|-|"&&"|"|" Z 5
+ * X = Y +|-|"==" Constant 6
+ * X = X +|- 1 3
+ * X = Y *|/ Z 2
+ * X = Expression, 1
+ * two operators
+ * X = Expression, 1
+ * three operators
+ * --
+ * 18 18
+ *
+ * if .... 14
+ * with "else" 7
+ * without "else" 7
+ * executed 3
+ * not executed 4
+ * for ... 7 | counted every time
+ * while ... 4 | the loop condition
+ * do ... while 1 | is evaluated
+ * switch ... 1
+ * break 1
+ * declaration with 1
+ * initialization
+ * --
+ * 34 34
+ *
+ * P (...) procedure call 11
+ * user procedure 10
+ * library procedure 1
+ * X = F (...)
+ * function call 6
+ * user function 5
+ * library function 1
+ * --
+ * 17 17
+ * ---
+ * 103
+ *
+ * The average number of parameters in procedure or function calls
+ * is 1.82 (not counting the function values aX *
+ *
+ * 2. Operators
+ * ------------
+ * number approximate
+ * percentage
+ *
+ * Arithmetic 32 50.8
+ *
+ * + 21 33.3
+ * - 7 11.1
+ * * 3 4.8
+ * / (int div) 1 1.6
+ *
+ * Comparison 27 42.8
+ *
+ * == 9 14.3
+ * /= 4 6.3
+ * > 1 1.6
+ * < 3 4.8
+ * >= 1 1.6
+ * <= 9 14.3
+ *
+ * Logic 4 6.3
+ *
+ * && (AND-THEN) 1 1.6
+ * | (OR) 1 1.6
+ * ! (NOT) 2 3.2
+ *
+ * -- -----
+ * 63 100.1
+ *
+ *
+ * 3. Operand Type (counted once per operand reference):
+ * ---------------
+ * number approximate
+ * percentage
+ *
+ * Integer 175 72.3 %
+ * Character 45 18.6 %
+ * Pointer 12 5.0 %
+ * String30 6 2.5 %
+ * Array 2 0.8 %
+ * Record 2 0.8 %
+ * --- -------
+ * 242 100.0 %
+ *
+ * When there is an access path leading to the final operand (e.g. a record
+ * component), only the final data type on the access path is counted.
+ *
+ *
+ * 4. Operand Locality:
+ * -------------------
+ * number approximate
+ * percentage
+ *
+ * local variable 114 47.1 %
+ * global variable 22 9.1 %
+ * parameter 45 18.6 %
+ * value 23 9.5 %
+ * reference 22 9.1 %
+ * function result 6 2.5 %
+ * constant 55 22.7 %
+ * --- -------
+ * 242 100.0 %
+ *
+ *
+ * The program does not compute anything meaningful, but it is syntactically
+ * and semantically correct. All variables have a value assigned to them
+ * before they are used as a source operand.
+ *
+ * There has been no explicit effort to account for the effects of a
+ * cache, or to balance the use of long or short displacements for code or
+ * data.
+ *
+ ***************************************************************************
+ */
+
+#ifndef __DHRY_H_
+#define __DHRY_H_
+
+/* Compiler and system dependent definitions: */
+
+/* Berkeley UNIX C returns process times in seconds/HZ */
+
+#ifdef NOSTRUCTASSIGN
+#define structassign(d, s) memcpy(&(d), &(s), sizeof(d))
+#else
+#define structassign(d, s) d = s
+#endif
+
+#ifdef NOENUM
+#define Ident_1 0
+#define Ident_2 1
+#define Ident_3 2
+#define Ident_4 3
+#define Ident_5 4
+ typedef int Enumeration;
+#else
+ typedef enum {Ident_1, Ident_2, Ident_3, Ident_4, Ident_5}
+ Enumeration;
+#endif
+ /* for boolean and enumeration types in Ada, Pascal */
+
+/* General definitions: */
+
+ /* for strcpy, strcmp */
+
+#define Null 0
+ /* Value of a Null pointer */
+#define true 1
+#define false 0
+
+typedef int One_Thirty;
+typedef int One_Fifty;
+typedef char Capital_Letter;
+typedef int Boolean;
+typedef char Str_30 [31];
+typedef int Arr_1_Dim [50];
+typedef int Arr_2_Dim [50] [50];
+
+typedef struct record
+ {
+ struct record *Ptr_Comp;
+ Enumeration Discr;
+ union {
+ struct {
+ Enumeration Enum_Comp;
+ int Int_Comp;
+ char Str_Comp [31];
+ } var_1;
+ struct {
+ Enumeration E_Comp_2;
+ char Str_2_Comp [31];
+ } var_2;
+ struct {
+ char Ch_1_Comp;
+ char Ch_2_Comp;
+ } var_3;
+ } variant;
+ } Rec_Type, *Rec_Pointer;
+
+void dhry_main (int iterations);
+
+#endif /* __DHRY_H_ */
diff --git a/tests/arm64/common/basic/dhry_1.c b/tests/arm64/common/basic/dhry_1.c
new file mode 100644
index 0000000..7fff307
--- /dev/null
+++ b/tests/arm64/common/basic/dhry_1.c
@@ -0,0 +1,431 @@
+/*
+ ****************************************************************************
+ *
+ * "DHRYSTONE" Benchmark Program
+ * -----------------------------
+ *
+ * Version: C, Version 2.1
+ *
+ * File: dhry_1.c (part 2 of 3)
+ *
+ * Date: May 25, 1988
+ *
+ * Updated By: Anup Patel (an...@brainfault.org) for portablity.
+ *
+ * Author: Reinhold P. Weicker
+ *
+ ****************************************************************************
+ */
+
+#include "dhry.h"
+#include "dhry_port.h"
+
+/* Global Variables: */
+
+Rec_Pointer Ptr_Glob,
+ Next_Ptr_Glob;
+int Int_Glob;
+Boolean Bool_Glob;
+char Ch_1_Glob,
+ Ch_2_Glob;
+int Arr_1_Glob [50];
+int Arr_2_Glob [50] [50];
+
+
+#ifndef REG
+ Boolean Reg = false;
+#define REG
+ /* REG becomes defined as empty */
+ /* i.e. no register variables */
+#else
+ Boolean Reg = true;
+#endif
+
+TimeStamp Begin_Time,
+ End_Time,
+ User_Time;
+long Microseconds,
+ Dhrystones_Per_Second;
+
+/* end of variables for time measurement */
+
+/* forward declaration necessary */
+void Proc_1 (REG Rec_Pointer Ptr_Val_Par);
+void Proc_2 (One_Fifty *Int_Par_Ref);
+void Proc_3 (Rec_Pointer *Ptr_Ref_Par);
+void Proc_4 ();
+void Proc_5 ();
+void Proc_6 (Enumeration Enum_Val_Par, Enumeration *Enum_Ref_Par);
+void Proc_7 (One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val, One_Fifty *Int_Par_Ref);
+void Proc_8 (Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref, int Int_1_Par_Val, int Int_2_Par_Val);
+Enumeration Func_1 (Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val);
+Boolean Func_2 (Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref);
+
+
+void dhry_main (int iterations)
+/*****/
+
+ /* main program, corresponds to procedures */
+ /* Main and Proc_0 in the Ada version */
+{
+ One_Fifty Int_1_Loc;
+ REG One_Fifty Int_2_Loc;
+ One_Fifty Int_3_Loc;
+ REG char Ch_Index;
+ Enumeration Enum_Loc;
+ Str_30 Str_1_Loc;
+ Str_30 Str_2_Loc;
+ REG int Run_Index;
+ REG int Number_Of_Runs;
+
+ /* Initializations */
+ Number_Of_Runs = iterations;
+ Next_Ptr_Glob = (Rec_Pointer) dhry_malloc (sizeof (Rec_Type));
+ Ptr_Glob = (Rec_Pointer) dhry_malloc (sizeof (Rec_Type));
+
+ Ptr_Glob->Ptr_Comp = Next_Ptr_Glob;
+ Ptr_Glob->Discr = Ident_1;
+ Ptr_Glob->variant.var_1.Enum_Comp = Ident_3;
+ Ptr_Glob->variant.var_1.Int_Comp = 40;
+ dhry_strcpy (Ptr_Glob->variant.var_1.Str_Comp,
+ "DHRYSTONE PROGRAM, SOME STRING");
+ dhry_strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
+
+ Arr_2_Glob [8][7] = 10;
+ /* Was missing in published program. Without this statement, */
+ /* Arr_2_Glob [8][7] would have an undefined value. */
+ /* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */
+ /* overflow may occur for this array element. */
+
+ dhry_prints ("\n");
+ dhry_prints ("Dhrystone Benchmark, Version 2.1 (Language: C)\n");
+ dhry_prints ("\n");
+ if (Reg)
+ {
+ dhry_prints ("Program compiled with 'register' attribute\n");
+ dhry_prints ("\n");
+ }
+ else
+ {
+ dhry_prints ("Program compiled without 'register' attribute\n");
+ dhry_prints ("\n");
+ }
+
+ dhry_prints ("Execution starts, ");
+ dhry_printi (Number_Of_Runs);
+ dhry_prints (" runs through Dhrystone\n");
+
+ /***************/
+ /* Start timer */
+ /***************/
+
+ Begin_Time = dhry_timestamp();
+
+ for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index)
+ {
+
+ Proc_5();
+ Proc_4();
+ /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
+ Int_1_Loc = 2;
+ Int_2_Loc = 3;
+ dhry_strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
+ Enum_Loc = Ident_2;
+ Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc);
+ /* Bool_Glob == 1 */
+ while (Int_1_Loc < Int_2_Loc) /* loop body executed once */
+ {
+ Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
+ /* Int_3_Loc == 7 */
+ Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc);
+ /* Int_3_Loc == 7 */
+ Int_1_Loc += 1;
+ } /* while */
+ /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
+ Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
+ /* Int_Glob == 5 */
+ Proc_1 (Ptr_Glob);
+ for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index)
+ /* loop body executed twice */
+ {
+ if (Enum_Loc == Func_1 (Ch_Index, 'C'))
+ /* then, not executed */
+ {
+ Proc_6 (Ident_1, &Enum_Loc);
+ dhry_strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
+ Int_2_Loc = Run_Index;
+ Int_Glob = Run_Index;
+ }
+ }
+ /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
+ Int_2_Loc = Int_2_Loc * Int_1_Loc;
+ Int_1_Loc = dhry_sdiv32(Int_2_Loc, Int_3_Loc);
+ Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
+ /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
+ Proc_2 (&Int_1_Loc);
+ /* Int_1_Loc == 5 */
+
+ } /* loop "for Run_Index" */
+
+ /**************/
+ /* Stop timer */
+ /**************/
+
+ End_Time = dhry_timestamp();
+
+ dhry_prints ("Execution ends\n");
+ dhry_prints ("\n");
+ dhry_prints ("Final values of the variables used in the benchmark:\n");
+ dhry_prints ("\n");
+ dhry_prints ("Int_Glob: ");
+ dhry_printi (Int_Glob);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (5);
+ dhry_prints ("\n");
+ dhry_prints ("Bool_Glob: ");
+ dhry_printi (Bool_Glob);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (1);
+ dhry_prints ("\n");
+ dhry_prints ("Ch_1_Glob: ");
+ dhry_printc (Ch_1_Glob);
+ dhry_prints ("\n");
+ dhry_prints (" should be: A\n");
+ dhry_prints ("Ch_2_Glob: ");
+ dhry_printc (Ch_2_Glob);
+ dhry_prints ("\n");
+ dhry_prints (" should be: B\n");
+ dhry_prints ("Arr_1_Glob[8]: ");
+ dhry_printi (Arr_1_Glob[8]);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (7);
+ dhry_prints ("\n");
+ dhry_prints ("Arr_2_Glob[8][7]: ");
+ dhry_printi (Arr_2_Glob[8][7]);
+ dhry_prints ("\n");
+ dhry_prints (" should be: Number_Of_Runs + 10\n");
+ dhry_prints ("Ptr_Glob->\n");
+ dhry_prints (" Ptr_Comp: ");
+ dhry_printll ((unsigned long long) Ptr_Glob->Ptr_Comp);
+ dhry_prints ("\n");
+ dhry_prints (" should be: (implementation-dependent)\n");
+ dhry_prints (" Discr: ");
+ dhry_printi (Ptr_Glob->Discr);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (0);
+ dhry_prints ("\n");
+ dhry_prints (" Enum_Comp: ");
+ dhry_printi (Ptr_Glob->variant.var_1.Enum_Comp);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (2);
+ dhry_prints ("\n");
+ dhry_prints (" Int_Comp: ");
+ dhry_printi (Ptr_Glob->variant.var_1.Int_Comp);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (17);
+ dhry_prints ("\n");
+ dhry_prints (" Str_Comp: ");
+ dhry_prints (Ptr_Glob->variant.var_1.Str_Comp);
+ dhry_prints ("\n");
+ dhry_prints (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
+ dhry_prints ("Next_Ptr_Glob->\n");
+ dhry_prints (" Ptr_Comp: ");
+ dhry_printll ((unsigned long long) Next_Ptr_Glob->Ptr_Comp);
+ dhry_prints ("\n");
+ dhry_prints (" should be: (implementation-dependent), same as above\n");
+ dhry_prints (" Discr: ");
+ dhry_printi (Next_Ptr_Glob->Discr);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (0);
+ dhry_prints ("\n");
+ dhry_prints (" Enum_Comp: ");
+ dhry_printi (Next_Ptr_Glob->variant.var_1.Enum_Comp);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (1);
+ dhry_prints ("\n");
+ dhry_prints (" Int_Comp: ");
+ dhry_printi (Next_Ptr_Glob->variant.var_1.Int_Comp);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (18);
+ dhry_prints ("\n");
+ dhry_prints (" Str_Comp: ");
+ dhry_prints (Next_Ptr_Glob->variant.var_1.Str_Comp);
+ dhry_prints ("\n");
+ dhry_prints (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
+ dhry_prints ("Int_1_Loc: ");
+ dhry_printi (Int_1_Loc);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (5);
+ dhry_prints ("\n");
+ dhry_prints ("Int_2_Loc: ");
+ dhry_printi (Int_2_Loc);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (13);
+ dhry_prints ("\n");
+ dhry_prints ("Int_3_Loc: ");
+ dhry_printi (Int_3_Loc);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (7);
+ dhry_prints ("\n");
+ dhry_prints ("Enum_Loc: ");
+ dhry_printi (Enum_Loc);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (1);
+ dhry_prints ("\n");
+ dhry_prints ("Str_1_Loc: ");
+ dhry_prints (Str_1_Loc);
+ dhry_prints ("\n");
+ dhry_prints (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n");
+ dhry_prints ("Str_2_Loc: ");
+ dhry_prints (Str_2_Loc);
+ dhry_prints ("\n");
+ dhry_prints (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n");
+ dhry_prints ("\n");
+
+ User_Time = End_Time - Begin_Time;
+
+ if (User_Time < Too_Small_Time)
+ {
+ dhry_prints ("Measured time too small to obtain meaningful results\n");
+ dhry_prints ("Please increase number of runs\n");
+ dhry_prints ("\n");
+ }
+ else
+ {
+ Microseconds = dhry_to_microsecs(User_Time);
+ Dhrystones_Per_Second = dhry_iter_per_sec(User_Time, Number_Of_Runs);
+ dhry_prints ("Microseconds for one run through Dhrystone: ");
+ dhry_printi (Microseconds);
+ dhry_prints (" \n");
+ dhry_prints ("Dhrystones per Second: ");
+ dhry_printi (Dhrystones_Per_Second);
+ dhry_prints (" \n");
+ dhry_prints ("Dhrystones MIPS: ");
+ dhry_printi (arm_sdiv32(Dhrystones_Per_Second, 1757));
+ dhry_prints (" \n");
+ dhry_prints ("\n");
+ }
+
+}
+
+
+void Proc_1 (Ptr_Val_Par)
+/******************/
+
+REG Rec_Pointer Ptr_Val_Par;
+ /* executed once */
+{
+ REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp;
+ /* == Ptr_Glob_Next */
+ /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */
+ /* corresponds to "rename" in Ada, "with" in Pascal */
+
+ structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob);
+ Ptr_Val_Par->variant.var_1.Int_Comp = 5;
+ Next_Record->variant.var_1.Int_Comp
+ = Ptr_Val_Par->variant.var_1.Int_Comp;
+ Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
+ Proc_3 (&Next_Record->Ptr_Comp);
+ /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp
+ == Ptr_Glob->Ptr_Comp */
+ if (Next_Record->Discr == Ident_1)
+ /* then, executed */
+ {
+ Next_Record->variant.var_1.Int_Comp = 6;
+ Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp,
+ &Next_Record->variant.var_1.Enum_Comp);
+ Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
+ Proc_7 (Next_Record->variant.var_1.Int_Comp, 10,
+ &Next_Record->variant.var_1.Int_Comp);
+ }
+ else /* not executed */
+ structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp);
+} /* Proc_1 */
+
+
+void Proc_2 (Int_Par_Ref)
+/******************/
+ /* executed once */
+ /* *Int_Par_Ref == 1, becomes 4 */
+
+One_Fifty *Int_Par_Ref;
+{
+ One_Fifty Int_Loc;
+ Enumeration Enum_Loc;
+
+ Int_Loc = *Int_Par_Ref + 10;
+ do /* executed once */
+ if (Ch_1_Glob == 'A')
+ /* then, executed */
+ {
+ Int_Loc -= 1;
+ *Int_Par_Ref = Int_Loc - Int_Glob;
+ Enum_Loc = Ident_1;
+ } /* if */
+ while (Enum_Loc != Ident_1); /* true */
+} /* Proc_2 */
+
+
+void Proc_3 (Ptr_Ref_Par)
+/******************/
+ /* executed once */
+ /* Ptr_Ref_Par becomes Ptr_Glob */
+
+Rec_Pointer *Ptr_Ref_Par;
+
+{
+ if (Ptr_Glob != Null)
+ /* then, executed */
+ *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
+ Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
+} /* Proc_3 */
+
+
+void Proc_4 () /* without parameters */
+/*******/
+ /* executed once */
+{
+ Boolean Bool_Loc;
+
+ Bool_Loc = Ch_1_Glob == 'A';
+ Bool_Glob = Bool_Loc | Bool_Glob;
+ Ch_2_Glob = 'B';
+} /* Proc_4 */
+
+
+void Proc_5 () /* without parameters */
+/*******/
+ /* executed once */
+{
+ Ch_1_Glob = 'A';
+ Bool_Glob = false;
+} /* Proc_5 */
+
+
+ /* Procedure for the assignment of structures, */
+ /* if the C compiler doesn't support this feature */
+#ifdef NOSTRUCTASSIGN
+memcpy (d, s, l)
+register char *d;
+register char *s;
+register int l;
+{
+ while (l--) *d++ = *s++;
+}
+#endif
+
+
+
diff --git a/tests/arm64/common/basic/dhry_2.c b/tests/arm64/common/basic/dhry_2.c
new file mode 100644
index 0000000..8063db9
--- /dev/null
+++ b/tests/arm64/common/basic/dhry_2.c
@@ -0,0 +1,197 @@
+/*
+ ****************************************************************************
+ *
+ * "DHRYSTONE" Benchmark Program
+ * -----------------------------
+ *
+ * Version: C, Version 2.1
+ *
+ * File: dhry_2.c (part 3 of 3)
+ *
+ * Date: May 25, 1988
+ *
+ * Author: Reinhold P. Weicker
+ *
+ ****************************************************************************
+ */
+
+#include "dhry.h"
+#include "dhry_port.h"
+
+#ifndef REG
+#define REG
+ /* REG becomes defined as empty */
+ /* i.e. no register variables */
+#endif
+
+extern int Int_Glob;
+extern char Ch_1_Glob;
+
+/* forward declaration necessary */
+Boolean Func_3 (Enumeration Enum_Par_Val);
+
+
+void Proc_6 (Enum_Val_Par, Enum_Ref_Par)
+/*********************************/
+ /* executed once */
+ /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */
+
+Enumeration Enum_Val_Par;
+Enumeration *Enum_Ref_Par;
+{
+ *Enum_Ref_Par = Enum_Val_Par;
+ if (! Func_3 (Enum_Val_Par))
+ /* then, not executed */
+ *Enum_Ref_Par = Ident_4;
+ switch (Enum_Val_Par)
+ {
+ case Ident_1:
+ *Enum_Ref_Par = Ident_1;
+ break;
+ case Ident_2:
+ if (Int_Glob > 100)
+ /* then */
+ *Enum_Ref_Par = Ident_1;
+ else *Enum_Ref_Par = Ident_4;
+ break;
+ case Ident_3: /* executed */
+ *Enum_Ref_Par = Ident_2;
+ break;
+ case Ident_4: break;
+ case Ident_5:
+ *Enum_Ref_Par = Ident_3;
+ break;
+ } /* switch */
+} /* Proc_6 */
+
+
+void Proc_7 (Int_1_Par_Val, Int_2_Par_Val, Int_Par_Ref)
+/**********************************************/
+ /* executed three times */
+ /* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */
+ /* Int_Par_Ref becomes 7 */
+ /* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */
+ /* Int_Par_Ref becomes 17 */
+ /* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */
+ /* Int_Par_Ref becomes 18 */
+One_Fifty Int_1_Par_Val;
+One_Fifty Int_2_Par_Val;
+One_Fifty *Int_Par_Ref;
+{
+ One_Fifty Int_Loc;
+
+ Int_Loc = Int_1_Par_Val + 2;
+ *Int_Par_Ref = Int_2_Par_Val + Int_Loc;
+} /* Proc_7 */
+
+
+void Proc_8 (Arr_1_Par_Ref, Arr_2_Par_Ref, Int_1_Par_Val, Int_2_Par_Val)
+/*********************************************************************/
+ /* executed once */
+ /* Int_Par_Val_1 == 3 */
+ /* Int_Par_Val_2 == 7 */
+Arr_1_Dim Arr_1_Par_Ref;
+Arr_2_Dim Arr_2_Par_Ref;
+int Int_1_Par_Val;
+int Int_2_Par_Val;
+{
+ REG One_Fifty Int_Index;
+ REG One_Fifty Int_Loc;
+
+ Int_Loc = Int_1_Par_Val + 5;
+ Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val;
+ Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc];
+ Arr_1_Par_Ref [Int_Loc+30] = Int_Loc;
+ for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index)
+ Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc;
+ Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1;
+ Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc];
+ Int_Glob = 5;
+} /* Proc_8 */
+
+
+Enumeration Func_1 (Ch_1_Par_Val, Ch_2_Par_Val)
+/*************************************************/
+ /* executed three times */
+ /* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */
+ /* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */
+ /* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */
+
+Capital_Letter Ch_1_Par_Val;
+Capital_Letter Ch_2_Par_Val;
+{
+ Capital_Letter Ch_1_Loc;
+ Capital_Letter Ch_2_Loc;
+
+ Ch_1_Loc = Ch_1_Par_Val;
+ Ch_2_Loc = Ch_1_Loc;
+ if (Ch_2_Loc != Ch_2_Par_Val)
+ /* then, executed */
+ return (Ident_1);
+ else /* not executed */
+ {
+ Ch_1_Glob = Ch_1_Loc;
+ return (Ident_2);
+ }
+} /* Func_1 */
+
+
+Boolean Func_2 (Str_1_Par_Ref, Str_2_Par_Ref)
+/*************************************************/
+ /* executed once */
+ /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */
+ /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */
+
+Str_30 Str_1_Par_Ref;
+Str_30 Str_2_Par_Ref;
+{
+ REG One_Thirty Int_Loc;
+ Capital_Letter Ch_Loc;
+
+ Int_Loc = 2;
+ while (Int_Loc <= 2) /* loop body executed once */
+ if (Func_1 (Str_1_Par_Ref[Int_Loc],
+ Str_2_Par_Ref[Int_Loc+1]) == Ident_1)
+ /* then, executed */
+ {
+ Ch_Loc = 'A';
+ Int_Loc += 1;
+ } /* if, while */
+ if (Ch_Loc >= 'W' && Ch_Loc < 'Z')
+ /* then, not executed */
+ Int_Loc = 7;
+ if (Ch_Loc == 'R')
+ /* then, not executed */
+ return (true);
+ else /* executed */
+ {
+ if (dhry_strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0)
+ /* then, not executed */
+ {
+ Int_Loc += 7;
+ Int_Glob = Int_Loc;
+ return (true);
+ }
+ else /* executed */
+ return (false);
+ } /* if Ch_Loc */
+} /* Func_2 */
+
+
+Boolean Func_3 (Enum_Par_Val)
+/***************************/
+ /* executed once */
+ /* Enum_Par_Val == Ident_3 */
+Enumeration Enum_Par_Val;
+{
+ Enumeration Enum_Loc;
+
+ Enum_Loc = Enum_Par_Val;
+ if (Enum_Loc == Ident_3)
+ /* then, executed */
+ return (true);
+ else /* not executed */
+ return (false);
+} /* Func_3 */
+
+
diff --git a/tests/arm64/common/basic/dhry_port.c b/tests/arm64/common/basic/dhry_port.c
new file mode 100644
index 0000000..946c27e
--- /dev/null
+++ b/tests/arm64/common/basic/dhry_port.c
@@ -0,0 +1,83 @@
+/*
+ ****************************************************************************
+ *
+ * "DHRYSTONE" Portability Section
+ * -------------------------------
+ *
+ * Version: C, Version 2.1
+ *
+ * File: dhry_port.c (for portability)
+ *
+ * Date: Aug 15, 2011
+ *
+ * Author: Anup Patel (an...@brainfault.org)
+ *
+ ****************************************************************************
+ */
+
+#include <arm_heap.h>
+#include <arm_stdio.h>
+#include <arm_string.h>
+#include <arm_board.h>
+#include "dhry_port.h"
+
+extern u8 _heap_start;
+
+void * dhry_malloc(unsigned int size)
+{
+ return arm_malloc(size);
+}
+
+TimeStamp dhry_timestamp(void)
+{
+ return arm_udiv64(arm_board_timer_timestamp(), 1000);
+}
+
+long dhry_to_microsecs(TimeStamp UserTime)
+{
+ return UserTime;
+}
+
+long dhry_iter_per_sec(TimeStamp UserTime, int Number_Of_Runs)
+{
+ return arm_udiv64(((TimeStamp)Number_Of_Runs * (TimeStamp)1000000),
+ UserTime);
+}
+
+int dhry_strcmp(char *dst, char *src)
+{
+ return arm_strcmp(dst, src);
+}
+
+void dhry_strcpy(char *dst, char *src)
+{
+ arm_strcpy(dst, src);
+}
+
+void dhry_printc(char ch)
+{
+ char tmp[2];
+ tmp[0] = ch;
+ tmp[1] = '\0';
+ arm_puts(tmp);
+}
+
+void dhry_prints(char *str)
+{
+ arm_puts(str);
+}
+
+void dhry_printi(int val)
+{
+ char tmp[128];
+ arm_int2str(tmp, val);
+ arm_puts(tmp);
+}
+
+void dhry_printll(unsigned long long val)
+{
+ char tmp[128];
+ arm_ulonglong2str(tmp, val);
+ arm_puts(tmp);
+}
+
diff --git a/tests/arm64/common/basic/dhry_port.h b/tests/arm64/common/basic/dhry_port.h
new file mode 100644
index 0000000..f21ccf4
--- /dev/null
+++ b/tests/arm64/common/basic/dhry_port.h
@@ -0,0 +1,42 @@
+/*
+ ****************************************************************************
+ *
+ * "DHRYSTONE" Portability Section
+ * -------------------------------
+ *
+ * Version: C, Version 2.1
+ *
+ * File: dhry_port.h (for portability)
+ *
+ * Date: Aug 15, 2011
+ *
+ * Author: Anup Patel (an...@brainfault.org)
+ *
+ ****************************************************************************
+ */
+
+#ifndef __DHRY_PORT_H_
+#define __DHRY_PORT_H_
+
+#include <arm_math.h>
+
+#define REG register
+
+typedef unsigned long long TimeStamp;
+
+#define Too_Small_Time (TimeStamp)1000000
+
+#define dhry_sdiv32(v, d) arm_sdiv32((v), (d))
+
+void * dhry_malloc(unsigned int size);
+TimeStamp dhry_timestamp(void);
+long dhry_to_microsecs(TimeStamp UserTime);
+long dhry_iter_per_sec(TimeStamp UserTime, int Number_Of_Runs);
+int dhry_strcmp(char *dst, char *src);
+void dhry_strcpy(char *dst, char *src);
+void dhry_printc(char ch);
+void dhry_prints(char *str);
+void dhry_printi(int val);
+void dhry_printll(unsigned long long val);
+
+#endif /* __DHRY_PORT_H_ */
diff --git a/tests/arm64/common/basic/firmware.ld b/tests/arm64/common/basic/firmware.ld
new file mode 100755
index 0000000..2b201cd
--- /dev/null
+++ b/tests/arm64/common/basic/firmware.ld
@@ -0,0 +1,97 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file firmware.ld
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief Linker script for basic firmware
+ */
+
+OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
+OUTPUT_ARCH("aarch64")
+ENTRY(_start)
+
+SECTIONS
+{
+ . = TEXT_START;
+
+ PROVIDE(_code_start = .);
+ PROVIDE(_reloc_region_start = .);
+
+ .text :
+ {
+ *(.expvect)
+ *(.text)
+ _etext = .;
+ }
+
+ .data :
+ {
+ . = ALIGN(8);
+ *(.data)
+ _edata = .;
+ }
+
+ .rodata :
+ {
+ . = ALIGN(8);
+ *(.rodata .rodata.*)
+ _erodata = .;
+ }
+
+ PROVIDE(_reloc_region_end = .);
+
+ PROVIDE(_zero_region_start = .);
+
+ .bss :
+ {
+ . = ALIGN(8);
+ PROVIDE(_bss_start = .);
+ *(.bss)
+ _ebss = .;
+ PROVIDE(_bss_end = .);
+ }
+
+ .heap :
+ {
+ . = ALIGN(8);
+ PROVIDE(_heap_start = .);
+ *(.heap)
+ . = . + 4096;
+ PROVIDE(_heap_end = .);
+ }
+
+ PROVIDE(_zero_region_end = .);
+
+ .svc_stack :
+ {
+ PROVIDE(_svc_stack_start = .);
+ . = . + 4096;
+ . = ALIGN(8);
+ PROVIDE(_svc_stack_end = .);
+ }
+
+ .usr_stack :
+ {
+ PROVIDE(_usr_stack_start = .);
+ . = . + 4096;
+ . = ALIGN(8);
+ PROVIDE(_usr_stack_end = .);
+ }
+
+ PROVIDE(_code_end = .);
+}
diff --git a/tests/arm64/common/basic/libfdt/cmd_fdt.c b/tests/arm64/common/basic/libfdt/cmd_fdt.c
new file mode 100644
index 0000000..447febd
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/cmd_fdt.c
@@ -0,0 +1,443 @@
+/*
+ * (C) Copyright 2007
+ * Gerald Van Baren, Custom IDEAS, vanb...@cideas.com
+ * Based on code written by:
+ * Pantelis Antoniou <pantelis...@gmail.com> and
+ * Matthew McClintock <m...@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <arm_string.h>
+#include <arm_stdio.h>
+#include <ctype.h>
+#include <arm_types.h>
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt.h>
+#include <libfdt/fdt_support.h>
+
+#define MAX_LEVEL 32 /* how deeply nested we will go */
+#define SCRATCHPAD 1024 /* bytes of scratchpad memory */
+
+//static int fdt_valid(void);
+//static int fdt_parse_prop(char *const*newval, int count, char *data, int *len);
+static int fdt_print(const char *pathp, char *prop, int depth);
+
+/*
+ * The working_fdt points to our working flattened device tree.
+ */
+struct fdt_header *working_fdt;
+
+#if 0
+static void usage(void)
+{
+ printf("Usage: fdt addr <addr> [<length>] - Set the fdt location to <addr>\n"
+ "fdt move <fdt> <newaddr> <length> - Copy the fdt to <addr> and make it active\n"
+ "fdt resize - Resize fdt to size + padding to 4k addr\n"
+ "fdt print <path> [<prop>] - Recursive print starting at <path>\n"
+ "fdt list <path> [<prop>] - Print one level starting at <path>\n"
+ "fdt set <path> <prop> [<val>] - Set <property> [to <val>]\n"
+ "fdt mknode <path> <node> - Create a new node after <path>\n"
+ "fdt rm <path> [<prop>] - Delete the node or <property>\n"
+ "fdt header - Display header info\n"
+ "fdt bootcpu <id> - Set boot cpuid\n"
+ "fdt memory <addr> <size> - Add/Update memory node\n"
+ "fdt rsvmem print - Show current mem reserves\n"
+ "fdt rsvmem add <addr> <size> - Add a mem reserve\n"
+ "fdt rsvmem delete <index> - Delete a mem reserves\n"
+ "fdt chosen [<start> <end>] - Add/update the /chosen branch in the tree\n"
+ " <start>/<end> - initrd start/end addr\n"
+ "NOTE: Dereference aliases by omiting the leading '/', "
+ "e.g. fdt print ethernet0.");
+}
+#endif
+
+void set_working_fdt_addr(void *addr)
+{
+ working_fdt = addr;
+}
+
+void dump_fdt(unsigned long fdt_addr)
+{
+ set_working_fdt_addr((void *)fdt_addr);
+ fdt_print("/", NULL, 32);
+}
+/****************************************************************************/
+
+#if 0
+static int fdt_valid(void)
+{
+ int err;
+
+ if (working_fdt == NULL) {
+ printf ("The address of the fdt is invalid (NULL).\n");
+ return 0;
+ }
+
+ err = fdt_check_header(working_fdt);
+ if (err == 0)
+ return 1; /* valid */
+
+ if (err < 0) {
+ printf("libfdt fdt_check_header(): %s", fdt_strerror(err));
+ /*
+ * Be more informative on bad version.
+ */
+ if (err == -FDT_ERR_BADVERSION) {
+ if (fdt_version(working_fdt) <
+ FDT_FIRST_SUPPORTED_VERSION) {
+ printf (" - too old, fdt %d < %d",
+ fdt_version(working_fdt),
+ FDT_FIRST_SUPPORTED_VERSION);
+ working_fdt = NULL;
+ }
+ if (fdt_last_comp_version(working_fdt) >
+ FDT_LAST_SUPPORTED_VERSION) {
+ printf (" - too new, fdt %d > %d",
+ fdt_version(working_fdt),
+ FDT_LAST_SUPPORTED_VERSION);
+ working_fdt = NULL;
+ }
+ return 0;
+ }
+ printf("\n");
+ return 0;
+ }
+ return 1;
+}
+#endif
+
+/****************************************************************************/
+
+#if 0
+/*
+ * Parse the user's input, partially heuristic. Valid formats:
+ * <0x00112233 4 05> - an array of cells. Numbers follow standard
+ * C conventions.
+ * [00 11 22 .. nn] - byte stream
+ * "string" - If the the value doesn't start with "<" or "[", it is
+ * treated as a string. Note that the quotes are
+ * stripped by the parser before we get the string.
+ * newval: An array of strings containing the new property as specified
+ * on the command line
+ * count: The number of strings in the array
+ * data: A bytestream to be placed in the property
+ * len: The length of the resulting bytestream
+ */
+static int fdt_parse_prop(char * const *newval, int count, char *data, int *len)
+{
+ char *cp; /* temporary char pointer */
+ char *newp; /* temporary newval char pointer */
+ unsigned long tmp; /* holds converted values */
+ int stridx = 0;
+
+ *len = 0;
+ newp = newval[0];
+
+ /* An array of cells */
+ if (*newp == '<') {
+ newp++;
+ while ((*newp != '>') && (stridx < count)) {
+ /*
+ * Keep searching until we find that last ">"
+ * That way users don't have to escape the spaces
+ */
+ if (*newp == '\0') {
+ newp = newval[++stridx];
+ continue;
+ }
+
+ cp = newp;
+ strtoul(cp, &newp, 0, &tmp);
+ *(u32 *)data = cpu_to_be32(tmp);
+ data += 4;
+ *len += 4;
+
+ /* If the ptr didn't advance, something went wrong */
+ if ((newp - cp) <= 0) {
+ printf("Sorry, I could not convert \"%s\"\n",
+ cp);
+ return 1;
+ }
+
+ while (*newp == ' ')
+ newp++;
+ }
+
+ if (*newp != '>') {
+ printf("Unexpected character '%c'\n", *newp);
+ return 1;
+ }
+ } else if (*newp == '[') {
+ /*
+ * Byte stream. Convert the values.
+ */
+ newp++;
+ while ((stridx < count) && (*newp != ']')) {
+ while (*newp == ' ')
+ newp++;
+ if (*newp == '\0') {
+ newp = newval[++stridx];
+ continue;
+ }
+ if (!isxdigit(*newp))
+ break;
+ strtoul(newp, &newp, 0, &tmp);
+ *data++ = tmp & 0xFF;
+ *len = *len + 1;
+ }
+ if (*newp != ']') {
+ printf("Unexpected character '%c'\n", *newp);
+ return 1;
+ }
+ } else {
+ /*
+ * Assume it is one or more strings. Copy it into our
+ * data area for convenience (including the
+ * terminating '\0's).
+ */
+ while (stridx < count) {
+ size_t length = strlen(newp) + 1;
+ strcpy(data, newp);
+ data += length;
+ *len += length;
+ newp = newval[++stridx];
+ }
+ }
+ return 0;
+}
+#endif
+
+/****************************************************************************/
+
+/*
+ * Heuristic to guess if this is a string or concatenated strings.
+ */
+
+#define in_range(c, lo, up) ((u8)c >= lo && (u8)c <= up)
+#define arm_isprint(c) in_range(c, 0x20, 0x7f)
+
+static int is_printable_string(const void *data, int len)
+{
+ const char *s = data;
+
+ /* zero length is not */
+ if (len == 0)
+ return 0;
+
+ /* must terminate with zero */
+ if (s[len - 1] != '\0')
+ return 0;
+
+ /* printable or a null byte (concatenated strings) */
+ while (((*s == '\0') || arm_isprint(*s)) && (len > 0)) {
+ /*
+ * If we see a null, there are three possibilities:
+ * 1) If len == 1, it is the end of the string, printable
+ * 2) Next character also a null, not printable.
+ * 3) Next character not a null, continue to check.
+ */
+ if (s[0] == '\0') {
+ if (len == 1)
+ return 1;
+ if (s[1] == '\0')
+ return 0;
+ }
+ s++;
+ len--;
+ }
+
+ /* Not the null termination, or not done yet: not printable */
+ if (*s != '\0' || (len != 0))
+ return 0;
+
+ return 1;
+}
+
+
+/*
+ * Print the property in the best format, a heuristic guess. Print as
+ * a string, concatenated strings, a byte, word, double word, or (if all
+ * else fails) it is printed as a stream of bytes.
+ */
+static void print_data(const void *data, int len)
+{
+ int j;
+
+ /* no data, don't print */
+ if (len == 0)
+ return;
+
+ /*
+ * It is a string, but it may have multiple strings (embedded '\0's).
+ */
+ if (is_printable_string(data, len)) {
+ printf("\"");
+ j = 0;
+ while (j < len) {
+ if (j > 0)
+ printf("\", \"");
+ printf(data);
+ j += strlen(data) + 1;
+ data += strlen(data) + 1;
+ }
+ printf("\"");
+ return;
+ }
+
+ if ((len %4) == 0) {
+ const u32 *p;
+
+ printf("<");
+ for (j = 0, p = data; j < len/4; j ++)
+ printf("0x%x%s", fdt32_to_cpu(p[j]), j < (len/4 - 1) ? " " : "");
+ printf(">");
+ } else { /* anything else... hexdump */
+ const u8 *s;
+
+ printf("[");
+ for (j = 0, s = data; j < len; j++)
+ printf("%02x%s", s[j], j < len - 1 ? " " : "");
+ printf("]");
+ }
+}
+
+/****************************************************************************/
+
+/*
+ * Recursively print (a portion of) the working_fdt. The depth parameter
+ * determines how deeply nested the fdt is printed.
+ */
+static int fdt_print(const char *pathp, char *prop, int depth)
+{
+ static char tabs[MAX_LEVEL+1] =
+ "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
+ "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
+ const void *nodep; /* property node pointer */
+ int nodeoffset; /* node offset from libfdt */
+ int nextoffset; /* next node offset from libfdt */
+ u32 tag; /* tag */
+ int len; /* length of the property */
+ int level = 0; /* keep track of nesting level */
+ const struct fdt_property *fdt_prop;
+
+ nodeoffset = fdt_path_offset (working_fdt, pathp);
+ if (nodeoffset < 0) {
+ /*
+ * Not found or something else bad happened.
+ */
+ printf ("libfdt fdt_path_offset() returned %s\n",
+ fdt_strerror(nodeoffset));
+ return 1;
+ }
+ /*
+ * The user passed in a property as well as node path.
+ * Print only the given property and then return.
+ */
+ if (prop) {
+ nodep = fdt_getprop (working_fdt, nodeoffset, prop, &len);
+ if (len == 0) {
+ /* no property value */
+ printf("%s %s\n", pathp, prop);
+ return 0;
+ } else if (len > 0) {
+ printf("%s = ", prop);
+ print_data (nodep, len);
+ printf("\n");
+ return 0;
+ } else {
+ printf ("libfdt fdt_getprop(): %s\n",
+ fdt_strerror(len));
+ return 1;
+ }
+ }
+
+ /*
+ * The user passed in a node path and no property,
+ * print the node and all subnodes.
+ */
+ while(level >= 0) {
+ tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset);
+ switch(tag) {
+ case FDT_BEGIN_NODE:
+ pathp = fdt_get_name(working_fdt, nodeoffset, NULL);
+ if (level <= depth) {
+ if (pathp == NULL)
+ pathp = "/* NULL pointer error */";
+ if (*pathp == '\0')
+ pathp = "/"; /* root is nameless */
+ printf("%s%s {\n",
+ &tabs[MAX_LEVEL - level], pathp);
+ }
+ level++;
+ if (level >= MAX_LEVEL) {
+ printf("Nested too deep, aborting.\n");
+ return 1;
+ }
+ break;
+ case FDT_END_NODE:
+ level--;
+ if (level <= depth)
+ printf("%s};\n", &tabs[MAX_LEVEL - level]);
+ if (level == 0) {
+ level = -1; /* exit the loop */
+ }
+ break;
+ case FDT_PROP:
+ fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset,
+ sizeof(*fdt_prop));
+ pathp = fdt_string(working_fdt,
+ fdt32_to_cpu(fdt_prop->nameoff));
+ len = fdt32_to_cpu(fdt_prop->len);
+ nodep = fdt_prop->data;
+ if (len < 0) {
+ printf ("libfdt fdt_getprop(): %s\n",
+ fdt_strerror(len));
+ return 1;
+ } else if (len == 0) {
+ /* the property has no value */
+ if (level <= depth)
+ printf("%s%s;\n",
+ &tabs[MAX_LEVEL - level],
+ pathp);
+ } else {
+ if (level <= depth) {
+ printf("%s%s = ",
+ &tabs[MAX_LEVEL - level],
+ pathp);
+ print_data (nodep, len);
+ printf(";\n");
+ }
+ }
+ break;
+ case FDT_NOP:
+ printf("%s/* NOP */\n", &tabs[MAX_LEVEL - level]);
+ break;
+ case FDT_END:
+ return 1;
+ default:
+ if (level <= depth)
+ printf("Unknown tag 0x%08X\n", tag);
+ return 1;
+ }
+ nodeoffset = nextoffset;
+ }
+ return 0;
+}
+
diff --git a/tests/arm64/common/basic/libfdt/fdt.c b/tests/arm64/common/basic/libfdt/fdt.c
new file mode 100644
index 0000000..a160ef9
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt.c
@@ -0,0 +1,222 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <libfdt/libfdt_env.h>
+
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_check_header(const void *fdt)
+{
+ if (fdt_magic(fdt) == FDT_MAGIC) {
+ /* Complete tree */
+ if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+ return -FDT_ERR_BADVERSION;
+ if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
+ return -FDT_ERR_BADVERSION;
+ } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
+ /* Unfinished sequential-write blob */
+ if (fdt_size_dt_struct(fdt) == 0)
+ return -FDT_ERR_BADSTATE;
+ } else {
+ return -FDT_ERR_BADMAGIC;
+ }
+
+ return 0;
+}
+
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
+{
+ const char *p;
+
+ if (fdt_version(fdt) >= 0x11)
+ if (((offset + len) < offset)
+ || ((offset + len) > fdt_size_dt_struct(fdt)))
+ return NULL;
+
+ p = _fdt_offset_ptr(fdt, offset);
+
+ if (p + len < p)
+ return NULL;
+ return p;
+}
+
+u32 fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
+{
+ const u32 *tagp, *lenp;
+ u32 tag;
+ int offset = startoffset;
+ const char *p;
+
+ *nextoffset = -FDT_ERR_TRUNCATED;
+ tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
+ if (!tagp)
+ return FDT_END; /* premature end */
+ tag = fdt32_to_cpu(*tagp);
+ offset += FDT_TAGSIZE;
+
+ *nextoffset = -FDT_ERR_BADSTRUCTURE;
+ switch (tag) {
+ case FDT_BEGIN_NODE:
+ /* skip name */
+ do {
+ p = fdt_offset_ptr(fdt, offset++, 1);
+ } while (p && (*p != '\0'));
+ if (!p)
+ return FDT_END; /* premature end */
+ break;
+
+ case FDT_PROP:
+ lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
+ if (!lenp)
+ return FDT_END; /* premature end */
+ /* skip-name offset, length and value */
+ offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+ + fdt32_to_cpu(*lenp);
+ break;
+
+ case FDT_END:
+ case FDT_END_NODE:
+ case FDT_NOP:
+ break;
+
+ default:
+ return FDT_END;
+ }
+
+ if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
+ return FDT_END; /* premature end */
+
+ *nextoffset = FDT_TAGALIGN(offset);
+ return tag;
+}
+
+int _fdt_check_node_offset(const void *fdt, int offset)
+{
+ if ((offset < 0) || (offset % FDT_TAGSIZE)
+ || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
+ return -FDT_ERR_BADOFFSET;
+
+ return offset;
+}
+
+int _fdt_check_prop_offset(const void *fdt, int offset)
+{
+ if ((offset < 0) || (offset % FDT_TAGSIZE)
+ || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
+ return -FDT_ERR_BADOFFSET;
+
+ return offset;
+}
+
+int fdt_next_node(const void *fdt, int offset, int *depth)
+{
+ int nextoffset = 0;
+ u32 tag;
+
+ if (offset >= 0)
+ if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
+ return nextoffset;
+
+ do {
+ offset = nextoffset;
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+ switch (tag) {
+ case FDT_PROP:
+ case FDT_NOP:
+ break;
+
+ case FDT_BEGIN_NODE:
+ if (depth)
+ (*depth)++;
+ break;
+
+ case FDT_END_NODE:
+ if (depth && ((--(*depth)) < 0))
+ return nextoffset;
+ break;
+
+ case FDT_END:
+ if ((nextoffset >= 0)
+ || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth))
+ return -FDT_ERR_NOTFOUND;
+ else
+ return nextoffset;
+ }
+ } while (tag != FDT_BEGIN_NODE);
+
+ return offset;
+}
+
+const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
+{
+ int len = strlen(s) + 1;
+ const char *last = strtab + tabsize - len;
+ const char *p;
+
+ for (p = strtab; p <= last; p++)
+ if (memcmp(p, s, len) == 0)
+ return p;
+ return NULL;
+}
+
+int fdt_move(const void *fdt, void *buf, int bufsize)
+{
+ FDT_CHECK_HEADER(fdt);
+
+ if (fdt_totalsize(fdt) > bufsize)
+ return -FDT_ERR_NOSPACE;
+
+ memmove(buf, fdt, fdt_totalsize(fdt));
+ return 0;
+}
diff --git a/tests/arm64/common/basic/libfdt/fdt.h b/tests/arm64/common/basic/libfdt/fdt.h
new file mode 100644
index 0000000..2a0552c
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt.h
@@ -0,0 +1,62 @@
+#ifndef _FDT_H
+#define _FDT_H
+
+#ifndef __ASSEMBLY__
+
+struct fdt_header {
+ u32 magic; /* magic word FDT_MAGIC */
+ u32 totalsize; /* total size of DT block */
+ u32 off_dt_struct; /* offset to structure */
+ u32 off_dt_strings; /* offset to strings */
+ u32 off_mem_rsvmap; /* offset to memory reserve map */
+ u32 version; /* format version */
+ u32 last_comp_version; /* last compatible version */
+
+ /* version 2 fields below */
+ u32 boot_cpuid_phys; /* Which physical CPU id we're
+ booting on */
+ /* version 3 fields below */
+ u32 size_dt_strings; /* size of the strings block */
+
+ /* version 17 fields below */
+ u32 size_dt_struct; /* size of the structure block */
+};
+
+struct fdt_reserve_entry {
+ u64 address;
+ u64 size;
+};
+
+struct fdt_node_header {
+ u32 tag;
+ char name[0];
+};
+
+struct fdt_property {
+ u32 tag;
+ u32 len;
+ u32 nameoff;
+ char data[0];
+};
+
+#endif /* !__ASSEMBLY */
+
+#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
+#define FDT_TAGSIZE sizeof(u32)
+
+#define FDT_BEGIN_NODE 0x1 /* Start node: full name */
+#define FDT_END_NODE 0x2 /* End node */
+#define FDT_PROP 0x3 /* Property: name off,
+ size, content */
+#define FDT_NOP 0x4 /* nop */
+#define FDT_END 0x9
+
+#define FDT_V1_SIZE (7*sizeof(u32))
+#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(u32))
+#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(u32))
+#define FDT_V16_SIZE FDT_V3_SIZE
+#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(u32))
+
+/* adding a ramdisk needs 0x44 bytes in version 2008.10 */
+#define FDT_RAMDISK_OVERHEAD 0x80
+#endif /* _FDT_H */
diff --git a/tests/arm64/common/basic/libfdt/fdt_ro.c b/tests/arm64/common/basic/libfdt/fdt_ro.c
new file mode 100644
index 0000000..0b1f934
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt_ro.c
@@ -0,0 +1,574 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <libfdt/libfdt_env.h>
+
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int _fdt_nodename_eq(const void *fdt, int offset,
+ const char *s, int len)
+{
+ const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
+
+ if (! p)
+ /* short match */
+ return 0;
+
+ if (memcmp(p, s, len) != 0)
+ return 0;
+
+ if (p[len] == '\0')
+ return 1;
+ else if (!memchr(s, '@', len) && (p[len] == '@'))
+ return 1;
+ else
+ return 0;
+}
+
+const char *fdt_string(const void *fdt, int stroffset)
+{
+ return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+}
+
+static int _fdt_string_eq(const void *fdt, int stroffset,
+ const char *s, int len)
+{
+ const char *p = fdt_string(fdt, stroffset);
+
+ return (strlen(p) == len) && (memcmp(p, s, len) == 0);
+}
+
+int fdt_get_mem_rsv(const void *fdt, int n, u64 *address, u64 *size)
+{
+ FDT_CHECK_HEADER(fdt);
+ *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
+ *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
+ return 0;
+}
+
+int fdt_num_mem_rsv(const void *fdt)
+{
+ int i = 0;
+
+ while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
+ i++;
+ return i;
+}
+
+static int _nextprop(const void *fdt, int offset)
+{
+ u32 tag;
+ int nextoffset;
+
+ do {
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+ switch (tag) {
+ case FDT_END:
+ if (nextoffset >= 0)
+ return -FDT_ERR_BADSTRUCTURE;
+ else
+ return nextoffset;
+
+ case FDT_PROP:
+ return offset;
+ }
+ offset = nextoffset;
+ } while (tag == FDT_NOP);
+
+ return -FDT_ERR_NOTFOUND;
+}
+
+int fdt_subnode_offset_namelen(const void *fdt, int offset,
+ const char *name, int namelen)
+{
+ int depth;
+
+ FDT_CHECK_HEADER(fdt);
+
+ for (depth = 0;
+ (offset >= 0) && (depth >= 0);
+ offset = fdt_next_node(fdt, offset, &depth))
+ if ((depth == 1)
+ && _fdt_nodename_eq(fdt, offset, name, namelen))
+ return offset;
+
+ if (depth < 0)
+ return -FDT_ERR_NOTFOUND;
+ return offset; /* error */
+}
+
+int fdt_subnode_offset(const void *fdt, int parentoffset,
+ const char *name)
+{
+ return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
+}
+
+int fdt_path_offset(const void *fdt, const char *path)
+{
+ const char *end = path + strlen(path);
+ const char *p = path;
+ int offset = 0;
+
+ FDT_CHECK_HEADER(fdt);
+
+ /* see if we have an alias */
+ if (*path != '/') {
+ const char *q = strchr(path, '/');
+
+ if (!q)
+ q = end;
+
+ p = fdt_get_alias_namelen(fdt, p, q - p);
+ if (!p)
+ return -FDT_ERR_BADPATH;
+ offset = fdt_path_offset(fdt, p);
+
+ p = q;
+ }
+
+ while (*p) {
+ const char *q;
+
+ while (*p == '/')
+ p++;
+ if (! *p)
+ return offset;
+ q = strchr(p, '/');
+ if (! q)
+ q = end;
+
+ offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
+ if (offset < 0)
+ return offset;
+
+ p = q;
+ }
+
+ return offset;
+}
+
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
+{
+ const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
+ int err;
+
+ if (((err = fdt_check_header(fdt)) != 0)
+ || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
+ goto fail;
+
+ if (len)
+ *len = strlen(nh->name);
+
+ return nh->name;
+
+ fail:
+ if (len)
+ *len = err;
+ return NULL;
+}
+
+int fdt_first_property_offset(const void *fdt, int nodeoffset)
+{
+ int offset;
+
+ if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+ return offset;
+
+ return _nextprop(fdt, offset);
+}
+
+int fdt_next_property_offset(const void *fdt, int offset)
+{
+ if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
+ return offset;
+
+ return _nextprop(fdt, offset);
+}
+
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+ int offset,
+ int *lenp)
+{
+ int err;
+ const struct fdt_property *prop;
+
+ if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
+ if (lenp)
+ *lenp = err;
+ return NULL;
+ }
+
+ prop = _fdt_offset_ptr(fdt, offset);
+
+ if (lenp)
+ *lenp = fdt32_to_cpu(prop->len);
+
+ return prop;
+}
+
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+ int offset,
+ const char *name,
+ int namelen, int *lenp)
+{
+ for (offset = fdt_first_property_offset(fdt, offset);
+ (offset >= 0);
+ (offset = fdt_next_property_offset(fdt, offset))) {
+ const struct fdt_property *prop;
+
+ if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
+ offset = -FDT_ERR_INTERNAL;
+ break;
+ }
+ if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
+ name, namelen))
+ return prop;
+ }
+
+ if (lenp)
+ *lenp = offset;
+ return NULL;
+}
+
+const struct fdt_property *fdt_get_property(const void *fdt,
+ int nodeoffset,
+ const char *name, int *lenp)
+{
+ return fdt_get_property_namelen(fdt, nodeoffset, name,
+ strlen(name), lenp);
+}
+
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+ const char *name, int namelen, int *lenp)
+{
+ const struct fdt_property *prop;
+
+ prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
+ if (! prop)
+ return NULL;
+
+ return prop->data;
+}
+
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+ const char **namep, int *lenp)
+{
+ const struct fdt_property *prop;
+
+ prop = fdt_get_property_by_offset(fdt, offset, lenp);
+ if (!prop)
+ return NULL;
+ if (namep)
+ *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+ return prop->data;
+}
+
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+ const char *name, int *lenp)
+{
+ return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);
+}
+
+u32 fdt_get_phandle(const void *fdt, int nodeoffset)
+{
+ const u32 *php;
+ int len;
+
+ /* FIXME: This is a bit sub-optimal, since we potentially scan
+ * over all the properties twice. */
+ php = fdt_getprop(fdt, nodeoffset, "phandle", &len);
+ if (!php || (len != sizeof(*php))) {
+ php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
+ if (!php || (len != sizeof(*php)))
+ return 0;
+ }
+
+ return fdt32_to_cpu(*php);
+}
+
+const char *fdt_get_alias_namelen(const void *fdt,
+ const char *name, int namelen)
+{
+ int aliasoffset;
+
+ aliasoffset = fdt_path_offset(fdt, "/aliases");
+ if (aliasoffset < 0)
+ return NULL;
+
+ return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
+}
+
+const char *fdt_get_alias(const void *fdt, const char *name)
+{
+ return fdt_get_alias_namelen(fdt, name, strlen(name));
+}
+
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
+{
+ int pdepth = 0, p = 0;
+ int offset, depth, namelen;
+ const char *name;
+
+ FDT_CHECK_HEADER(fdt);
+
+ if (buflen < 2)
+ return -FDT_ERR_NOSPACE;
+
+ for (offset = 0, depth = 0;
+ (offset >= 0) && (offset <= nodeoffset);
+ offset = fdt_next_node(fdt, offset, &depth)) {
+ while (pdepth > depth) {
+ do {
+ p--;
+ } while (buf[p-1] != '/');
+ pdepth--;
+ }
+
+ if (pdepth >= depth) {
+ name = fdt_get_name(fdt, offset, &namelen);
+ if (!name)
+ return namelen;
+ if ((p + namelen + 1) <= buflen) {
+ memcpy(buf + p, name, namelen);
+ p += namelen;
+ buf[p++] = '/';
+ pdepth++;
+ }
+ }
+
+ if (offset == nodeoffset) {
+ if (pdepth < (depth + 1))
+ return -FDT_ERR_NOSPACE;
+
+ if (p > 1) /* special case so that root path is "/", not "" */
+ p--;
+ buf[p] = '\0';
+ return 0;
+ }
+ }
+
+ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+ return -FDT_ERR_BADOFFSET;
+ else if (offset == -FDT_ERR_BADOFFSET)
+ return -FDT_ERR_BADSTRUCTURE;
+
+ return offset; /* error from fdt_next_node() */
+}
+
+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
+ int supernodedepth, int *nodedepth)
+{
+ int offset, depth;
+ int supernodeoffset = -FDT_ERR_INTERNAL;
+
+ FDT_CHECK_HEADER(fdt);
+
+ if (supernodedepth < 0)
+ return -FDT_ERR_NOTFOUND;
+
+ for (offset = 0, depth = 0;
+ (offset >= 0) && (offset <= nodeoffset);
+ offset = fdt_next_node(fdt, offset, &depth)) {
+ if (depth == supernodedepth)
+ supernodeoffset = offset;
+
+ if (offset == nodeoffset) {
+ if (nodedepth)
+ *nodedepth = depth;
+
+ if (supernodedepth > depth)
+ return -FDT_ERR_NOTFOUND;
+ else
+ return supernodeoffset;
+ }
+ }
+
+ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+ return -FDT_ERR_BADOFFSET;
+ else if (offset == -FDT_ERR_BADOFFSET)
+ return -FDT_ERR_BADSTRUCTURE;
+
+ return offset; /* error from fdt_next_node() */
+}
+
+int fdt_node_depth(const void *fdt, int nodeoffset)
+{
+ int nodedepth;
+ int err;
+
+ err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
+ if (err)
+ return (err < 0) ? err : -FDT_ERR_INTERNAL;
+ return nodedepth;
+}
+
+int fdt_parent_offset(const void *fdt, int nodeoffset)
+{
+ int nodedepth = fdt_node_depth(fdt, nodeoffset);
+
+ if (nodedepth < 0)
+ return nodedepth;
+ return fdt_supernode_atdepth_offset(fdt, nodeoffset,
+ nodedepth - 1, NULL);
+}
+
+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
+ const char *propname,
+ const void *propval, int proplen)
+{
+ int offset;
+ const void *val;
+ int len;
+
+ FDT_CHECK_HEADER(fdt);
+
+ /* FIXME: The algorithm here is pretty horrible: we scan each
+ * property of a node in fdt_getprop(), then if that didn't
+ * find what we want, we scan over them again making our way
+ * to the next node. Still it's the easiest to implement
+ * approach; performance can come later. */
+ for (offset = fdt_next_node(fdt, startoffset, NULL);
+ offset >= 0;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ val = fdt_getprop(fdt, offset, propname, &len);
+ if (val && (len == proplen)
+ && (memcmp(val, propval, len) == 0))
+ return offset;
+ }
+
+ return offset; /* error from fdt_next_node() */
+}
+
+int fdt_node_offset_by_phandle(const void *fdt, u32 phandle)
+{
+ int offset;
+
+ if ((phandle == 0) || (phandle == -1))
+ return -FDT_ERR_BADPHANDLE;
+
+ FDT_CHECK_HEADER(fdt);
+
+ /* FIXME: The algorithm here is pretty horrible: we
+ * potentially scan each property of a node in
+ * fdt_get_phandle(), then if that didn't find what
+ * we want, we scan over them again making our way to the next
+ * node. Still it's the easiest to implement approach;
+ * performance can come later. */
+ for (offset = fdt_next_node(fdt, -1, NULL);
+ offset >= 0;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ if (fdt_get_phandle(fdt, offset) == phandle)
+ return offset;
+ }
+
+ return offset; /* error from fdt_next_node() */
+}
+
+static int _fdt_stringlist_contains(const char *strlist, int listlen,
+ const char *str)
+{
+ int len = strlen(str);
+ const char *p;
+
+ while (listlen >= len) {
+ if (memcmp(str, strlist, len+1) == 0)
+ return 1;
+ p = memchr(strlist, '\0', listlen);
+ if (!p)
+ return 0; /* malformed strlist.. */
+ listlen -= (p-strlist) + 1;
+ strlist = p + 1;
+ }
+ return 0;
+}
+
+int fdt_node_check_compatible(const void *fdt, int nodeoffset,
+ const char *compatible)
+{
+ const void *prop;
+ int len;
+
+ prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
+ if (!prop)
+ return len;
+ if (_fdt_stringlist_contains(prop, len, compatible))
+ return 0;
+ else
+ return 1;
+}
+
+int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
+ const char *compatible)
+{
+ int offset, err;
+
+ FDT_CHECK_HEADER(fdt);
+
+ /* FIXME: The algorithm here is pretty horrible: we scan each
+ * property of a node in fdt_node_check_compatible(), then if
+ * that didn't find what we want, we scan over them again
+ * making our way to the next node. Still it's the easiest to
+ * implement approach; performance can come later. */
+ for (offset = fdt_next_node(fdt, startoffset, NULL);
+ offset >= 0;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ err = fdt_node_check_compatible(fdt, offset, compatible);
+ if ((err < 0) && (err != -FDT_ERR_NOTFOUND))
+ return err;
+ else if (err == 0)
+ return offset;
+ }
+
+ return offset; /* error from fdt_next_node() */
+}
diff --git a/tests/arm64/common/basic/libfdt/fdt_rw.c b/tests/arm64/common/basic/libfdt/fdt_rw.c
new file mode 100644
index 0000000..589084e
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt_rw.c
@@ -0,0 +1,465 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <libfdt/libfdt_env.h>
+
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int _fdt_blocks_misordered(const void *fdt,
+ int mem_rsv_size, int struct_size)
+{
+ return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
+ || (fdt_off_dt_struct(fdt) <
+ (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
+ || (fdt_off_dt_strings(fdt) <
+ (fdt_off_dt_struct(fdt) + struct_size))
+ || (fdt_totalsize(fdt) <
+ (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
+}
+
+static int _fdt_rw_check_header(void *fdt)
+{
+ FDT_CHECK_HEADER(fdt);
+
+ if (fdt_version(fdt) < 17)
+ return -FDT_ERR_BADVERSION;
+ if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
+ fdt_size_dt_struct(fdt)))
+ return -FDT_ERR_BADLAYOUT;
+ if (fdt_version(fdt) > 17)
+ fdt_set_version(fdt, 17);
+
+ return 0;
+}
+
+#define FDT_RW_CHECK_HEADER(fdt) \
+ { \
+ int err; \
+ if ((err = _fdt_rw_check_header(fdt)) != 0) \
+ return err; \
+ }
+
+static inline int _fdt_data_size(void *fdt)
+{
+ return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
+}
+
+static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
+{
+ char *p = splicepoint;
+ char *end = (char *)fdt + _fdt_data_size(fdt);
+
+ if (((p + oldlen) < p) || ((p + oldlen) > end))
+ return -FDT_ERR_BADOFFSET;
+ if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
+ return -FDT_ERR_NOSPACE;
+ memmove(p + newlen, p + oldlen, end - p - oldlen);
+ return 0;
+}
+
+static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
+ int oldn, int newn)
+{
+ int delta = (newn - oldn) * sizeof(*p);
+ int err;
+ err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
+ if (err)
+ return err;
+ fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
+ fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
+ return 0;
+}
+
+static int _fdt_splice_struct(void *fdt, void *p,
+ int oldlen, int newlen)
+{
+ int delta = newlen - oldlen;
+ int err;
+
+ if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
+ return err;
+
+ fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
+ fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
+ return 0;
+}
+
+static int _fdt_splice_string(void *fdt, int newlen)
+{
+ void *p = (char *)fdt
+ + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
+ int err;
+
+ if ((err = _fdt_splice(fdt, p, 0, newlen)))
+ return err;
+
+ fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
+ return 0;
+}
+
+static int _fdt_find_add_string(void *fdt, const char *s)
+{
+ char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
+ const char *p;
+ char *new;
+ int len = strlen(s) + 1;
+ int err;
+
+ p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
+ if (p)
+ /* found it */
+ return (p - strtab);
+
+ new = strtab + fdt_size_dt_strings(fdt);
+ err = _fdt_splice_string(fdt, len);
+ if (err)
+ return err;
+
+ memcpy(new, s, len);
+ return (new - strtab);
+}
+
+int fdt_add_mem_rsv(void *fdt, u64 address, u64 size)
+{
+ struct fdt_reserve_entry *re;
+ int err;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
+ err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
+ if (err)
+ return err;
+
+ re->address = cpu_to_fdt64(address);
+ re->size = cpu_to_fdt64(size);
+ return 0;
+}
+
+int fdt_del_mem_rsv(void *fdt, int n)
+{
+ struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
+ int err;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ if (n >= fdt_num_mem_rsv(fdt))
+ return -FDT_ERR_NOTFOUND;
+
+ err = _fdt_splice_mem_rsv(fdt, re, 1, 0);
+ if (err)
+ return err;
+ return 0;
+}
+
+static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
+ int len, struct fdt_property **prop)
+{
+ int oldlen;
+ int err;
+
+ *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
+ if (! (*prop))
+ return oldlen;
+
+ if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
+ FDT_TAGALIGN(len))))
+ return err;
+
+ (*prop)->len = cpu_to_fdt32(len);
+ return 0;
+}
+
+static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
+ int len, struct fdt_property **prop)
+{
+ int proplen;
+ int nextoffset;
+ int namestroff;
+ int err;
+
+ if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+ return nextoffset;
+
+ namestroff = _fdt_find_add_string(fdt, name);
+ if (namestroff < 0)
+ return namestroff;
+
+ *prop = _fdt_offset_ptr_w(fdt, nextoffset);
+ proplen = sizeof(**prop) + FDT_TAGALIGN(len);
+
+ err = _fdt_splice_struct(fdt, *prop, 0, proplen);
+ if (err)
+ return err;
+
+ (*prop)->tag = cpu_to_fdt32(FDT_PROP);
+ (*prop)->nameoff = cpu_to_fdt32(namestroff);
+ (*prop)->len = cpu_to_fdt32(len);
+ return 0;
+}
+
+int fdt_set_name(void *fdt, int nodeoffset, const char *name)
+{
+ char *namep;
+ int oldlen, newlen;
+ int err;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
+ if (!namep)
+ return oldlen;
+
+ newlen = strlen(name);
+
+ err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
+ FDT_TAGALIGN(newlen+1));
+ if (err)
+ return err;
+
+ memcpy(namep, name, newlen+1);
+ return 0;
+}
+
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len)
+{
+ struct fdt_property *prop;
+ int err;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
+ if (err == -FDT_ERR_NOTFOUND)
+ err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
+ if (err)
+ return err;
+
+ memcpy(prop->data, val, len);
+ return 0;
+}
+
+int fdt_delprop(void *fdt, int nodeoffset, const char *name)
+{
+ struct fdt_property *prop;
+ int len, proplen;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
+ if (! prop)
+ return len;
+
+ proplen = sizeof(*prop) + FDT_TAGALIGN(len);
+ return _fdt_splice_struct(fdt, prop, proplen, 0);
+}
+
+int fdt_add_subnode_namelen(void *fdt, int parentoffset,
+ const char *name, int namelen)
+{
+ struct fdt_node_header *nh;
+ int offset, nextoffset;
+ int nodelen;
+ int err;
+ u32 tag;
+ u32 *endtag;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
+ if (offset >= 0)
+ return -FDT_ERR_EXISTS;
+ else if (offset != -FDT_ERR_NOTFOUND)
+ return offset;
+
+ /* Try to place the new node after the parent's properties */
+ fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
+ do {
+ offset = nextoffset;
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+ } while ((tag == FDT_PROP) || (tag == FDT_NOP));
+
+ nh = _fdt_offset_ptr_w(fdt, offset);
+ nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
+
+ err = _fdt_splice_struct(fdt, nh, 0, nodelen);
+ if (err)
+ return err;
+
+ nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
+ memset(nh->name, 0, FDT_TAGALIGN(namelen+1));
+ memcpy(nh->name, name, namelen);
+ endtag = (u32 *)((char *)nh + nodelen - FDT_TAGSIZE);
+ *endtag = cpu_to_fdt32(FDT_END_NODE);
+
+ return offset;
+}
+
+int fdt_add_subnode(void *fdt, int parentoffset, const char *name)
+{
+ return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name));
+}
+
+int fdt_del_node(void *fdt, int nodeoffset)
+{
+ int endoffset;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+ if (endoffset < 0)
+ return endoffset;
+
+ return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
+ endoffset - nodeoffset, 0);
+}
+
+static void _fdt_packblocks(const char *old, char *new,
+ int mem_rsv_size, int struct_size)
+{
+ int mem_rsv_off, struct_off, strings_off;
+
+ mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8);
+ struct_off = mem_rsv_off + mem_rsv_size;
+ strings_off = struct_off + struct_size;
+
+ memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size);
+ fdt_set_off_mem_rsvmap(new, mem_rsv_off);
+
+ memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size);
+ fdt_set_off_dt_struct(new, struct_off);
+ fdt_set_size_dt_struct(new, struct_size);
+
+ memmove(new + strings_off, old + fdt_off_dt_strings(old),
+ fdt_size_dt_strings(old));
+ fdt_set_off_dt_strings(new, strings_off);
+ fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
+}
+
+int fdt_open_into(const void *fdt, void *buf, int bufsize)
+{
+ int err;
+ int mem_rsv_size, struct_size;
+ int newsize;
+ const char *fdtstart = fdt;
+ const char *fdtend = fdtstart + fdt_totalsize(fdt);
+ char *tmp;
+
+ FDT_CHECK_HEADER(fdt);
+
+ mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
+ * sizeof(struct fdt_reserve_entry);
+
+ if (fdt_version(fdt) >= 17) {
+ struct_size = fdt_size_dt_struct(fdt);
+ } else {
+ struct_size = 0;
+ while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
+ ;
+ if (struct_size < 0)
+ return struct_size;
+ }
+
+ if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
+ /* no further work necessary */
+ err = fdt_move(fdt, buf, bufsize);
+ if (err)
+ return err;
+ fdt_set_version(buf, 17);
+ fdt_set_size_dt_struct(buf, struct_size);
+ fdt_set_totalsize(buf, bufsize);
+ return 0;
+ }
+
+ /* Need to reorder */
+ newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
+ + struct_size + fdt_size_dt_strings(fdt);
+
+ if (bufsize < newsize)
+ return -FDT_ERR_NOSPACE;
+
+ /* First attempt to build converted tree at beginning of buffer */
+ tmp = buf;
+ /* But if that overlaps with the old tree... */
+ if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) {
+ /* Try right after the old tree instead */
+ tmp = (char *)(uintptr_t)fdtend;
+ if ((tmp + newsize) > ((char *)buf + bufsize))
+ return -FDT_ERR_NOSPACE;
+ }
+
+ _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size);
+ memmove(buf, tmp, newsize);
+
+ fdt_set_magic(buf, FDT_MAGIC);
+ fdt_set_totalsize(buf, bufsize);
+ fdt_set_version(buf, 17);
+ fdt_set_last_comp_version(buf, 16);
+ fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt));
+
+ return 0;
+}
+
+int fdt_pack(void *fdt)
+{
+ int mem_rsv_size;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
+ * sizeof(struct fdt_reserve_entry);
+ _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
+ fdt_set_totalsize(fdt, _fdt_data_size(fdt));
+
+ return 0;
+}
diff --git a/tests/arm64/common/basic/libfdt/fdt_strerror.c b/tests/arm64/common/basic/libfdt/fdt_strerror.c
new file mode 100644
index 0000000..6aa0a46
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt_strerror.c
@@ -0,0 +1,96 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <libfdt/libfdt_env.h>
+
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt.h>
+
+#include "libfdt_internal.h"
+
+struct fdt_errtabent {
+ const char *str;
+};
+
+#define FDT_ERRTABENT(val) \
+ [(val)] = { .str = #val, }
+
+static struct fdt_errtabent fdt_errtable[] = {
+ FDT_ERRTABENT(FDT_ERR_NOTFOUND),
+ FDT_ERRTABENT(FDT_ERR_EXISTS),
+ FDT_ERRTABENT(FDT_ERR_NOSPACE),
+
+ FDT_ERRTABENT(FDT_ERR_BADOFFSET),
+ FDT_ERRTABENT(FDT_ERR_BADPATH),
+ FDT_ERRTABENT(FDT_ERR_BADSTATE),
+
+ FDT_ERRTABENT(FDT_ERR_TRUNCATED),
+ FDT_ERRTABENT(FDT_ERR_BADMAGIC),
+ FDT_ERRTABENT(FDT_ERR_BADVERSION),
+ FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
+ FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
+};
+#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
+
+const char *fdt_strerror(int errval)
+{
+ if (errval > 0)
+ return "<valid offset/length>";
+ else if (errval == 0)
+ return "<no error>";
+ else if (errval > -FDT_ERRTABSIZE) {
+ const char *s = fdt_errtable[-errval].str;
+
+ if (s)
+ return s;
+ }
+
+ return "<unknown error>";
+}
diff --git a/tests/arm64/common/basic/libfdt/fdt_support.c b/tests/arm64/common/basic/libfdt/fdt_support.c
new file mode 100644
index 0000000..3547865
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt_support.c
@@ -0,0 +1,1318 @@
+/*
+ * (C) Copyright 2007
+ * Gerald Van Baren, Custom IDEAS, vanb...@cideas.com
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#undef DEBUG
+#define debug_printf(...)
+
+#include <arm_stdio.h>
+#include <arm_string.h>
+//#include <ctype.h>
+#include <arm_types.h>
+//#include <smp.h>
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt.h>
+#include <libfdt/fdt_support.h>
+
+unsigned long arm_linux_memory_size(void);
+
+#define ALIGN(x, a) (x & ~a)
+
+/**
+ * fdt_getprop_u32_default - Find a node and return it's property or a default
+ *
+ * @fdt: ptr to device tree
+ * @path: path of node
+ * @prop: property name
+ * @dflt: default value if the property isn't found
+ *
+ * Convenience function to find a node and return it's property or a
+ * default value if it doesn't exist.
+ */
+u32 fdt_getprop_u32_default(const void *fdt, const char *path,
+ const char *prop, const u32 dflt)
+{
+ const u32 *val;
+ int off;
+
+ off = fdt_path_offset(fdt, path);
+ if (off < 0)
+ return dflt;
+
+ val = fdt_getprop(fdt, off, prop, NULL);
+ if (val)
+ return fdt32_to_cpu(*val);
+ else
+ return dflt;
+}
+
+/**
+ * fdt_find_and_setprop: Find a node and set it's property
+ *
+ * @fdt: ptr to device tree
+ * @node: path of node
+ * @prop: property name
+ * @val: ptr to new value
+ * @len: length of new property value
+ * @create: flag to create the property if it doesn't exist
+ *
+ * Convenience function to directly set a property given the path to the node.
+ */
+int fdt_find_and_setprop(void *fdt, const char *node, const char *prop,
+ const void *val, int len, int create)
+{
+ int nodeoff = fdt_path_offset(fdt, node);
+
+ if (nodeoff < 0)
+ return nodeoff;
+
+ if ((!create) && (fdt_get_property(fdt, nodeoff, prop, 0) == NULL))
+ return 0; /* create flag not set; so exit quietly */
+
+ return fdt_setprop(fdt, nodeoff, prop, val, len);
+}
+
+#ifdef CONFIG_OF_STDOUT_VIA_ALIAS
+
+#ifdef CONFIG_SERIAL_MULTI
+static void fdt_fill_multisername(char *sername, size_t maxlen)
+{
+ const char *outname = stdio_devices[stdout]->name;
+
+ if (strcmp(outname, "serial") > 0)
+ strncpy(sername, outname, maxlen);
+
+ /* eserial? */
+ if (strcmp(outname + 1, "serial") > 0)
+ strncpy(sername, outname + 1, maxlen);
+}
+#else
+static inline void fdt_fill_multisername(char *sername, size_t maxlen) {}
+#endif /* CONFIG_SERIAL_MULTI */
+
+static int fdt_fixup_stdout(void *fdt, int chosenoff)
+{
+ int err = 0;
+#ifdef CONFIG_CONS_INDEX
+ int node;
+ char sername[9] = { 0 };
+ const char *path;
+
+ fdt_fill_multisername(sername, sizeof(sername) - 1);
+ if (!sername[0])
+ sprintf(sername, "serial%d", CONFIG_CONS_INDEX - 1);
+
+ err = node = fdt_path_offset(fdt, "/aliases");
+ if (node >= 0) {
+ int len;
+ path = fdt_getprop(fdt, node, sername, &len);
+ if (path) {
+ char *p = malloc(len);
+ err = -FDT_ERR_NOSPACE;
+ if (p) {
+ memcpy(p, path, len);
+ err = fdt_setprop(fdt, chosenoff,
+ "linux,stdout-path", p, len);
+ free(p);
+ }
+ } else {
+ err = len;
+ }
+ }
+#endif
+ if (err < 0)
+ printf("WARNING: could not set linux,stdout-path %s.\n",
+ fdt_strerror(err));
+
+ return err;
+}
+#endif
+
+int fdt_initrd(void *fdt, unsigned long initrd_start, unsigned long initrd_end, int force)
+{
+ int nodeoffset;
+ int err, j, total;
+ u64 tmp;
+ const char *path;
+ u64 addr, size;
+
+ /* Find the "chosen" node. */
+ nodeoffset = fdt_path_offset (fdt, "/chosen");
+
+ /* If there is no "chosen" node in the blob return */
+ if (nodeoffset < 0) {
+ printf("fdt_initrd: %s\n", fdt_strerror(nodeoffset));
+ return nodeoffset;
+ }
+
+ /* just return if initrd_start/end aren't valid */
+ if ((initrd_start == 0) || (initrd_end == 0))
+ return 0;
+
+ total = fdt_num_mem_rsv(fdt);
+
+ /*
+ * Look for an existing entry and update it. If we don't find
+ * the entry, we will j be the next available slot.
+ */
+ for (j = 0; j < total; j++) {
+ err = fdt_get_mem_rsv(fdt, j, &addr, &size);
+ if (addr == initrd_start) {
+ fdt_del_mem_rsv(fdt, j);
+ break;
+ }
+ }
+
+#if 0
+ err = fdt_add_mem_rsv(fdt, initrd_start, initrd_end - initrd_start);
+ if (err < 0) {
+ printf("fdt_initrd: %s\n", fdt_strerror(err));
+ return err;
+ }
+#endif
+
+ path = fdt_getprop(fdt, nodeoffset, "linux,initrd-start", NULL);
+ if ((path == NULL) || force) {
+ tmp = cpu_to_be64(initrd_start);
+ err = fdt_setprop(fdt, nodeoffset,
+ "linux,initrd-start", &tmp, sizeof(tmp));
+ if (err < 0) {
+ printf("WARNING: "
+ "could not set linux,initrd-start %s.\n",
+ fdt_strerror(err));
+ return err;
+ }
+ tmp = cpu_to_be64(initrd_end);
+ err = fdt_setprop(fdt, nodeoffset,
+ "linux,initrd-end", &tmp, sizeof(tmp));
+ if (err < 0) {
+ printf("WARNING: could not set linux,initrd-end %s.\n",
+ fdt_strerror(err));
+
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+extern char linux_cmdline[];
+
+int fdt_chosen(void *fdt, int force)
+{
+ int nodeoffset;
+ int err;
+// char* str; /* used to set string properties */
+ const char *path;
+
+ err = fdt_check_header(fdt);
+ if (err < 0) {
+ printf("fdt_chosen: %s\n", fdt_strerror(err));
+ return err;
+ }
+
+ /*
+ * Find the "chosen" node.
+ */
+ nodeoffset = fdt_path_offset (fdt, "/chosen");
+
+ /*
+ * If there is no "chosen" node in the blob, create it.
+ */
+ if (nodeoffset < 0) {
+ /*
+ * Create a new node "/chosen" (offset 0 is root level)
+ */
+ nodeoffset = fdt_add_subnode(fdt, 0, "chosen");
+ if (nodeoffset < 0) {
+ printf("WARNING: could not create /chosen %s.\n",
+ fdt_strerror(nodeoffset));
+ return nodeoffset;
+ }
+ }
+
+ /*
+ * Create /chosen properites that don't exist in the fdt.
+ * If the property exists, update it only if the "force" parameter
+ * is true.
+ */
+// str = getenv("bootargs");
+// if (str != NULL)
+ {
+ printf("Trying to set new bootargs: %s\n", linux_cmdline);
+ path = fdt_getprop(fdt, nodeoffset, "bootargs", NULL);
+ if ((path == NULL) || force) {
+ err = fdt_setprop(fdt, nodeoffset,
+ "bootargs", linux_cmdline, strlen(linux_cmdline)+1);
+ if (err < 0)
+ printf("WARNING: could not set bootargs %s.\n",
+ fdt_strerror(err));
+ }
+ }
+
+#ifdef CONFIG_OF_STDOUT_VIA_ALIAS
+ path = fdt_getprop(fdt, nodeoffset, "linux,stdout-path", NULL);
+ if ((path == NULL) || force)
+ err = fdt_fixup_stdout(fdt, nodeoffset);
+#endif
+
+#ifdef OF_STDOUT_PATH
+ path = fdt_getprop(fdt, nodeoffset, "linux,stdout-path", NULL);
+ if ((path == NULL) || force) {
+ err = fdt_setprop(fdt, nodeoffset,
+ "linux,stdout-path", OF_STDOUT_PATH, strlen(OF_STDOUT_PATH)+1);
+ if (err < 0)
+ printf("WARNING: could not set linux,stdout-path %s.\n",
+ fdt_strerror(err));
+ }
+#endif
+
+ return err;
+}
+
+void do_fixup_by_path(void *fdt, const char *path, const char *prop,
+ const void *val, int len, int create)
+{
+#if defined(DEBUG)
+ int i;
+ debug_printf("Updating property '%s/%s' = ", path, prop);
+ for (i = 0; i < len; i++)
+ debug_printf(" %.2x", *(u8*)(val+i));
+ debug_printf("\n");
+#endif
+ int rc = fdt_find_and_setprop(fdt, path, prop, val, len, create);
+ if (rc)
+ printf("Unable to update property %s:%s, err=%s\n",
+ path, prop, fdt_strerror(rc));
+}
+
+void do_fixup_by_path_u32(void *fdt, const char *path, const char *prop,
+ u32 val, int create)
+{
+ val = cpu_to_fdt32(val);
+ do_fixup_by_path(fdt, path, prop, &val, sizeof(val), create);
+}
+
+void do_fixup_by_prop(void *fdt,
+ const char *pname, const void *pval, int plen,
+ const char *prop, const void *val, int len,
+ int create)
+{
+ int off;
+#if defined(DEBUG)
+ int i;
+ debug_printf("Updating property '%s' = ", prop);
+ for (i = 0; i < len; i++)
+ debug_printf(" %.2x", *(u8*)(val+i));
+ debug_printf("\n");
+#endif
+ off = fdt_node_offset_by_prop_value(fdt, -1, pname, pval, plen);
+ while (off != -FDT_ERR_NOTFOUND) {
+ if (create || (fdt_get_property(fdt, off, prop, 0) != NULL))
+ fdt_setprop(fdt, off, prop, val, len);
+ off = fdt_node_offset_by_prop_value(fdt, off, pname, pval, plen);
+ }
+}
+
+void do_fixup_by_prop_u32(void *fdt,
+ const char *pname, const void *pval, int plen,
+ const char *prop, u32 val, int create)
+{
+ val = cpu_to_fdt32(val);
+ do_fixup_by_prop(fdt, pname, pval, plen, prop, &val, 4, create);
+}
+
+void do_fixup_by_compat(void *fdt, const char *compat,
+ const char *prop, const void *val, int len, int create)
+{
+ int off = -1;
+#if defined(DEBUG)
+ int i;
+ debug_printf("Updating property '%s' = ", prop);
+ for (i = 0; i < len; i++)
+ debug_printf(" %.2x", *(u8*)(val+i));
+ debug_printf("\n");
+#endif
+ off = fdt_node_offset_by_compatible(fdt, -1, compat);
+ while (off != -FDT_ERR_NOTFOUND) {
+ if (create || (fdt_get_property(fdt, off, prop, 0) != NULL))
+ fdt_setprop(fdt, off, prop, val, len);
+ off = fdt_node_offset_by_compatible(fdt, off, compat);
+ }
+}
+
+void do_fixup_by_compat_u32(void *fdt, const char *compat,
+ const char *prop, u32 val, int create)
+{
+ val = cpu_to_fdt32(val);
+ do_fixup_by_compat(fdt, compat, prop, &val, 4, create);
+}
+
+/*
+ * Get cells len in bytes
+ * if #NNNN-cells property is 2 then len is 8
+ * otherwise len is 4
+ */
+static int get_cells_len(void *blob, char *nr_cells_name)
+{
+ const u32 *cell;
+
+ cell = fdt_getprop(blob, 0, nr_cells_name, NULL);
+ if (cell && fdt32_to_cpu(*cell) == 2)
+ return 8;
+
+ return 4;
+}
+
+/*
+ * Write a 4 or 8 byte big endian cell
+ */
+static void write_cell(u8 *addr, u64 val, int size)
+{
+ int shift = (size - 1) * 8;
+ while (size-- > 0) {
+ *addr++ = (val >> shift) & 0xff;
+ shift -= 8;
+ }
+}
+
+int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks)
+{
+ int err, nodeoffset;
+ int addr_cell_len, size_cell_len, len;
+ u8 tmp[banks * 16]; /* Up to 64-bit address + 64-bit size */
+ int bank;
+
+ err = fdt_check_header(blob);
+ if (err < 0) {
+ printf("%s: %s\n", __FUNCTION__, fdt_strerror(err));
+ return err;
+ }
+
+ /* update, or add and update /memory node */
+ nodeoffset = fdt_path_offset(blob, "/memory");
+ if (nodeoffset < 0) {
+ nodeoffset = fdt_add_subnode(blob, 0, "memory");
+ if (nodeoffset < 0)
+ printf("WARNING: could not create /memory: %s.\n",
+ fdt_strerror(nodeoffset));
+ return nodeoffset;
+ }
+ err = fdt_setprop(blob, nodeoffset, "device_type", "memory",
+ sizeof("memory"));
+ if (err < 0) {
+ printf("WARNING: could not set %s %s.\n", "device_type",
+ fdt_strerror(err));
+ return err;
+ }
+
+ addr_cell_len = get_cells_len(blob, "#address-cells");
+ size_cell_len = get_cells_len(blob, "#size-cells");
+
+ for (bank = 0, len = 0; bank < banks; bank++) {
+ write_cell(tmp + len, start[bank], addr_cell_len);
+ len += addr_cell_len;
+
+ write_cell(tmp + len, size[bank], size_cell_len);
+ len += size_cell_len;
+ }
+
+ err = fdt_setprop(blob, nodeoffset, "reg", tmp, len);
+ if (err < 0) {
+ printf("WARNING: could not set %s %s.\n",
+ "reg", fdt_strerror(err));
+ return err;
+ }
+ return 0;
+}
+
+int fdt_fixup_memory(void *blob, u64 start, u64 size)
+{
+ return fdt_fixup_memory_banks(blob, &start, &size, 1);
+}
+
+/* Resize the fdt to its actual size + a bit of padding */
+int fdt_resize(void *blob)
+{
+ int i;
+ u64 addr, size;
+ int total, ret;
+ unsigned int actualsize;
+
+ if (!blob)
+ return 0;
+
+ total = fdt_num_mem_rsv(blob);
+ for (i = 0; i < total; i++) {
+ fdt_get_mem_rsv(blob, i, &addr, &size);
+ if (addr == (unsigned long)blob) {
+ fdt_del_mem_rsv(blob, i);
+ break;
+ }
+ }
+
+ /*
+ * Calculate the actual size of the fdt
+ * plus the size needed for 5 fdt_add_mem_rsv, one
+ * for the fdt itself and 4 for a possible initrd
+ * ((initrd-start + initrd-end) * 2 (name & value))
+ */
+ actualsize = fdt_off_dt_strings(blob) +
+ fdt_size_dt_strings(blob) + 5 * sizeof(struct fdt_reserve_entry);
+
+ /* Make it so the fdt ends on a page boundary */
+ actualsize = ALIGN((actualsize + (((unsigned long)blob) & 0xfff)), 0x1000);
+ actualsize = actualsize - ((unsigned long)blob & 0xfff);
+
+ /* Change the fdt header to reflect the correct size */
+ fdt_set_totalsize(blob, actualsize);
+
+ /* Add the new reservation */
+ ret = fdt_add_mem_rsv(blob, (unsigned long)blob, actualsize);
+ if (ret < 0)
+ return ret;
+
+ return actualsize;
+}
+
+#ifdef CONFIG_FDT_FIXUP_NOR_FLASH_SIZE
+/*
+ * Provide a weak default function to return the flash bank size.
+ * There might be multiple non-identical flash chips connected to one
+ * chip-select, so we need to pass an index as well.
+ */
+u32 __flash_get_bank_size(int cs, int idx)
+{
+ extern flash_info_t flash_info[];
+
+ /*
+ * As default, a simple 1:1 mapping is provided. Boards with
+ * a different mapping need to supply a board specific mapping
+ * routine.
+ */
+ return flash_info[cs].size;
+}
+u32 flash_get_bank_size(int cs, int idx)
+ __attribute__((weak, alias("__flash_get_bank_size")));
+
+/*
+ * This function can be used to update the size in the "reg" property
+ * of all NOR FLASH device nodes. This is necessary for boards with
+ * non-fixed NOR FLASH sizes.
+ */
+int fdt_fixup_nor_flash_size(void *blob)
+{
+ char compat[][16] = { "cfi-flash", "jedec-flash" };
+ int off;
+ int len;
+ struct fdt_property *prop;
+ u32 *reg, *reg2;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ off = fdt_node_offset_by_compatible(blob, -1, compat[i]);
+ while (off != -FDT_ERR_NOTFOUND) {
+ int idx;
+
+ /*
+ * Found one compatible node, so fixup the size
+ * int its reg properties
+ */
+ prop = fdt_get_property_w(blob, off, "reg", &len);
+ if (prop) {
+ int tuple_size = 3 * sizeof(reg);
+
+ /*
+ * There might be multiple reg-tuples,
+ * so loop through them all
+ */
+ reg = reg2 = (u32 *)&prop->data[0];
+ for (idx = 0; idx < (len / tuple_size); idx++) {
+ /*
+ * Update size in reg property
+ */
+ reg[2] = flash_get_bank_size(reg[0],
+ idx);
+
+ /*
+ * Point to next reg tuple
+ */
+ reg += 3;
+ }
+
+ fdt_setprop(blob, off, "reg", reg2, len);
+ }
+
+ /* Move to next compatible node */
+ off = fdt_node_offset_by_compatible(blob, off,
+ compat[i]);
+ }
+ }
+
+ return 0;
+}
+#endif
+
+int fdt_increase_size(void *fdt, int add_len)
+{
+ int newlen;
+
+ newlen = fdt_totalsize(fdt) + add_len;
+
+ /* Open in place with a new len */
+ return fdt_open_into(fdt, fdt, newlen);
+}
+
+#ifdef CONFIG_FDT_FIXUP_PARTITIONS
+#include <jffs2/load_kernel.h>
+#include <mtd_node.h>
+
+struct reg_cell {
+ unsigned int r0;
+ unsigned int r1;
+};
+
+int fdt_del_subnodes(const void *blob, int parent_offset)
+{
+ int off, ndepth;
+ int ret;
+
+ for (ndepth = 0, off = fdt_next_node(blob, parent_offset, &ndepth);
+ (off >= 0) && (ndepth > 0);
+ off = fdt_next_node(blob, off, &ndepth)) {
+ if (ndepth == 1) {
+ debug_printf("delete %s: offset: %x\n",
+ fdt_get_name(blob, off, 0), off);
+ ret = fdt_del_node((void *)blob, off);
+ if (ret < 0) {
+ printf("Can't delete node: %s\n",
+ fdt_strerror(ret));
+ return ret;
+ } else {
+ ndepth = 0;
+ off = parent_offset;
+ }
+ }
+ }
+ return 0;
+}
+
+int fdt_del_partitions(void *blob, int parent_offset)
+{
+ const void *prop;
+ int ndepth = 0;
+ int off;
+ int ret;
+
+ off = fdt_next_node(blob, parent_offset, &ndepth);
+ if (off > 0 && ndepth == 1) {
+ prop = fdt_getprop(blob, off, "label", NULL);
+ if (prop == NULL) {
+ /*
+ * Could not find label property, nand {}; node?
+ * Check subnode, delete partitions there if any.
+ */
+ return fdt_del_partitions(blob, off);
+ } else {
+ ret = fdt_del_subnodes(blob, parent_offset);
+ if (ret < 0) {
+ printf("Can't remove subnodes: %s\n",
+ fdt_strerror(ret));
+ return ret;
+ }
+ }
+ }
+ return 0;
+}
+
+int fdt_node_set_part_info(void *blob, int parent_offset,
+ struct mtd_device *dev)
+{
+ struct list_head *pentry;
+ struct part_info *part;
+ struct reg_cell cell;
+ int off, ndepth = 0;
+ int part_num, ret;
+ char buf[64];
+
+ ret = fdt_del_partitions(blob, parent_offset);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Check if it is nand {}; subnode, adjust
+ * the offset in this case
+ */
+ off = fdt_next_node(blob, parent_offset, &ndepth);
+ if (off > 0 && ndepth == 1)
+ parent_offset = off;
+
+ part_num = 0;
+ list_for_each_prev(pentry, &dev->parts) {
+ int newoff;
+
+ part = list_entry(pentry, struct part_info, link);
+
+ debug_printf("%2d: %-20s0x%08x\t0x%08x\t%d\n",
+ part_num, part->name, part->size,
+ part->offset, part->mask_flags);
+
+ sprintf(buf, "partition@%x", part->offset);
+add_sub:
+ ret = fdt_add_subnode(blob, parent_offset, buf);
+ if (ret == -FDT_ERR_NOSPACE) {
+ ret = fdt_increase_size(blob, 512);
+ if (!ret)
+ goto add_sub;
+ else
+ goto err_size;
+ } else if (ret < 0) {
+ printf("Can't add partition node: %s\n",
+ fdt_strerror(ret));
+ return ret;
+ }
+ newoff = ret;
+
+ /* Check MTD_WRITEABLE_CMD flag */
+ if (part->mask_flags & 1) {
+add_ro:
+ ret = fdt_setprop(blob, newoff, "read_only", NULL, 0);
+ if (ret == -FDT_ERR_NOSPACE) {
+ ret = fdt_increase_size(blob, 512);
+ if (!ret)
+ goto add_ro;
+ else
+ goto err_size;
+ } else if (ret < 0)
+ goto err_prop;
+ }
+
+ cell.r0 = cpu_to_fdt32(part->offset);
+ cell.r1 = cpu_to_fdt32(part->size);
+add_reg:
+ ret = fdt_setprop(blob, newoff, "reg", &cell, sizeof(cell));
+ if (ret == -FDT_ERR_NOSPACE) {
+ ret = fdt_increase_size(blob, 512);
+ if (!ret)
+ goto add_reg;
+ else
+ goto err_size;
+ } else if (ret < 0)
+ goto err_prop;
+
+add_label:
+ ret = fdt_setprop_string(blob, newoff, "label", part->name);
+ if (ret == -FDT_ERR_NOSPACE) {
+ ret = fdt_increase_size(blob, 512);
+ if (!ret)
+ goto add_label;
+ else
+ goto err_size;
+ } else if (ret < 0)
+ goto err_prop;
+
+ part_num++;
+ }
+ return 0;
+err_size:
+ printf("Can't increase blob size: %s\n", fdt_strerror(ret));
+ return ret;
+err_prop:
+ printf("Can't add property: %s\n", fdt_strerror(ret));
+ return ret;
+}
+
+/*
+ * Update partitions in nor/nand nodes using info from
+ * mtdparts environment variable. The nodes to update are
+ * specified by node_info structure which contains mtd device
+ * type and compatible string: E. g. the board code in
+ * ft_board_setup() could use:
+ *
+ * struct node_info nodes[] = {
+ * { "fsl,mpc5121-nfc", MTD_DEV_TYPE_NAND, },
+ * { "cfi-flash", MTD_DEV_TYPE_NOR, },
+ * };
+ *
+ * fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
+ */
+void fdt_fixup_mtdparts(void *blob, void *node_info, int node_info_size)
+{
+ struct node_info *ni = node_info;
+ struct mtd_device *dev;
+ char *parts;
+ int i, idx;
+ int noff;
+
+ parts = getenv("mtdparts");
+ if (!parts)
+ return;
+
+ if (mtdparts_init() != 0)
+ return;
+
+ for (i = 0; i < node_info_size; i++) {
+ idx = 0;
+ noff = fdt_node_offset_by_compatible(blob, -1, ni[i].compat);
+ while (noff != -FDT_ERR_NOTFOUND) {
+ debug_printf("%s: %s, mtd dev type %d\n",
+ fdt_get_name(blob, noff, 0),
+ ni[i].compat, ni[i].type);
+ dev = device_find(ni[i].type, idx++);
+ if (dev) {
+ if (fdt_node_set_part_info(blob, noff, dev))
+ return; /* return on error */
+ }
+
+ /* Jump to next flash node */
+ noff = fdt_node_offset_by_compatible(blob, noff,
+ ni[i].compat);
+ }
+ }
+}
+#endif
+
+void fdt_del_node_and_alias(void *blob, const char *alias)
+{
+ int off = fdt_path_offset(blob, alias);
+
+ if (off < 0)
+ return;
+
+ fdt_del_node(blob, off);
+
+ off = fdt_path_offset(blob, "/aliases");
+ fdt_delprop(blob, off, alias);
+}
+
+/* Helper to read a big number; size is in cells (not bytes) */
+static inline u64 of_read_number(const u32 *cell, int size)
+{
+ u64 r = 0;
+ while (size--) {
+ r = (r << 32) | be32_to_cpu(*cell);
+ cell++;
+ }
+ return r;
+}
+
+#define PRu64 "%llx"
+
+/* Max address size we deal with */
+#define OF_MAX_ADDR_CELLS 4
+#define OF_BAD_ADDR ((u64)-1)
+#define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
+ (ns) > 0)
+
+/* Debug utility */
+#ifdef DEBUG
+static void of_dump_addr(const char *s, const u32 *addr, int na)
+{
+ printf("%s", s);
+ while(na--)
+ printf(" %08x", *(addr++));
+ printf("\n");
+}
+#else
+static void of_dump_addr(const char *s, const u32 *addr, int na) { }
+#endif
+
+/* Callbacks for bus specific translators */
+struct of_bus {
+ const char *name;
+ const char *addresses;
+ void (*count_cells)(void *blob, int parentoffset,
+ int *addrc, int *sizec);
+ u64 (*map)(u32 *addr, const u32 *range,
+ int na, int ns, int pna);
+ int (*translate)(u32 *addr, u64 offset, int na);
+};
+
+/* Default translator (generic bus) */
+static void of_bus_default_count_cells(void *blob, int parentoffset,
+ int *addrc, int *sizec)
+{
+ const u32 *prop;
+
+ if (addrc) {
+ prop = fdt_getprop(blob, parentoffset, "#address-cells", NULL);
+ if (prop)
+ *addrc = be32_to_cpup((u32 *)prop);
+ else
+ *addrc = 2;
+ }
+
+ if (sizec) {
+ prop = fdt_getprop(blob, parentoffset, "#size-cells", NULL);
+ if (prop)
+ *sizec = be32_to_cpup((u32 *)prop);
+ else
+ *sizec = 1;
+ }
+}
+
+static u64 of_bus_default_map(u32 *addr, const u32 *range,
+ int na, int ns, int pna)
+{
+ u64 cp, s, da;
+
+ cp = of_read_number(range, na);
+ s = of_read_number(range + na + pna, ns);
+ da = of_read_number(addr, na);
+
+ debug_printf("OF: default map, cp="PRu64", s="PRu64", da="PRu64"\n",
+ cp, s, da);
+
+ if (da < cp || da >= (cp + s))
+ return OF_BAD_ADDR;
+ return da - cp;
+}
+
+static int of_bus_default_translate(u32 *addr, u64 offset, int na)
+{
+ u64 a = of_read_number(addr, na);
+ memset(addr, 0, na * 4);
+ a += offset;
+ if (na > 1)
+ addr[na - 2] = a >> 32;
+ addr[na - 1] = a & 0xffffffffu;
+
+ return 0;
+}
+
+/* Array of bus specific translators */
+static struct of_bus of_busses[] = {
+ /* Default */
+ {
+ .name = "default",
+ .addresses = "reg",
+ .count_cells = of_bus_default_count_cells,
+ .map = of_bus_default_map,
+ .translate = of_bus_default_translate,
+ },
+};
+
+static int of_translate_one(void * blob, int parent, struct of_bus *bus,
+ struct of_bus *pbus, u32 *addr,
+ int na, int ns, int pna, const char *rprop)
+{
+ const u32 *ranges;
+ int rlen;
+ int rone;
+ u64 offset = OF_BAD_ADDR;
+
+ /* Normally, an absence of a "ranges" property means we are
+ * crossing a non-translatable boundary, and thus the addresses
+ * below the current not cannot be converted to CPU physical ones.
+ * Unfortunately, while this is very clear in the spec, it's not
+ * what Apple understood, and they do have things like /uni-n or
+ * /ht nodes with no "ranges" property and a lot of perfectly
+ * useable mapped devices below them. Thus we treat the absence of
+ * "ranges" as equivalent to an empty "ranges" property which means
+ * a 1:1 translation at that level. It's up to the caller not to try
+ * to translate addresses that aren't supposed to be translated in
+ * the first place. --BenH.
+ */
+ ranges = (u32 *)fdt_getprop(blob, parent, rprop, &rlen);
+ if (ranges == NULL || rlen == 0) {
+ offset = of_read_number(addr, na);
+ memset(addr, 0, pna * 4);
+ debug_printf("OF: no ranges, 1:1 translation\n");
+ goto finish;
+ }
+
+ debug_printf("OF: walking ranges...\n");
+
+ /* Now walk through the ranges */
+ rlen /= 4;
+ rone = na + pna + ns;
+ for (; rlen >= rone; rlen -= rone, ranges += rone) {
+ offset = bus->map(addr, ranges, na, ns, pna);
+ if (offset != OF_BAD_ADDR)
+ break;
+ }
+ if (offset == OF_BAD_ADDR) {
+ debug_printf("OF: not found !\n");
+ return 1;
+ }
+ memcpy(addr, ranges + na, 4 * pna);
+
+ finish:
+ of_dump_addr("OF: parent translation for:", addr, pna);
+ debug_printf("OF: with offset: "PRu64"\n", offset);
+
+ /* Translate it into parent bus space */
+ return pbus->translate(addr, offset, pna);
+}
+
+/*
+ * Translate an address from the device-tree into a CPU physical address,
+ * this walks up the tree and applies the various bus mappings on the
+ * way.
+ *
+ * Note: We consider that crossing any level with #size-cells == 0 to mean
+ * that translation is impossible (that is we are not dealing with a value
+ * that can be mapped to a cpu physical address). This is not really specified
+ * that way, but this is traditionally the way IBM at least do things
+ */
+u64 __of_translate_address(void *blob, int node_offset, const u32 *in_addr,
+ const char *rprop)
+{
+ int parent;
+ struct of_bus *bus, *pbus;
+ u32 addr[OF_MAX_ADDR_CELLS];
+ int na, ns, pna, pns;
+ u64 result = OF_BAD_ADDR;
+
+ debug_printf("OF: ** translation for device %s **\n",
+ fdt_get_name(blob, node_offset, NULL));
+
+ /* Get parent & match bus type */
+ parent = fdt_parent_offset(blob, node_offset);
+ if (parent < 0)
+ goto bail;
+ bus = &of_busses[0];
+
+ /* Cound address cells & copy address locally */
+ bus->count_cells(blob, parent, &na, &ns);
+ if (!OF_CHECK_COUNTS(na, ns)) {
+ printf("%s: Bad cell count for %s\n", __FUNCTION__,
+ fdt_get_name(blob, node_offset, NULL));
+ goto bail;
+ }
+ memcpy(addr, in_addr, na * 4);
+
+ debug_printf("OF: bus is %s (na=%d, ns=%d) on %s\n",
+ bus->name, na, ns, fdt_get_name(blob, parent, NULL));
+ of_dump_addr("OF: translating address:", addr, na);
+
+ /* Translate */
+ for (;;) {
+ /* Switch to parent bus */
+ node_offset = parent;
+ parent = fdt_parent_offset(blob, node_offset);
+
+ /* If root, we have finished */
+ if (parent < 0) {
+ debug_printf("OF: reached root node\n");
+ result = of_read_number(addr, na);
+ break;
+ }
+
+ /* Get new parent bus and counts */
+ pbus = &of_busses[0];
+ pbus->count_cells(blob, parent, &pna, &pns);
+ if (!OF_CHECK_COUNTS(pna, pns)) {
+ printf("%s: Bad cell count for %s\n", __FUNCTION__,
+ fdt_get_name(blob, node_offset, NULL));
+ break;
+ }
+
+ debug_printf("OF: parent bus is %s (na=%d, ns=%d) on %s\n",
+ pbus->name, pna, pns, fdt_get_name(blob, parent, NULL));
+
+ /* Apply bus translation */
+ if (of_translate_one(blob, node_offset, bus, pbus,
+ addr, na, ns, pna, rprop))
+ break;
+
+ /* Complete the move up one level */
+ na = pna;
+ ns = pns;
+ bus = pbus;
+
+ of_dump_addr("OF: one level translation:", addr, na);
+ }
+ bail:
+
+ return result;
+}
+
+u64 fdt_translate_address(void *blob, int node_offset, const u32 *in_addr)
+{
+ return __of_translate_address(blob, node_offset, in_addr, "ranges");
+}
+
+/**
+ * fdt_node_offset_by_compat_reg: Find a node that matches compatiable and
+ * who's reg property matches a physical cpu address
+ *
+ * @blob: ptr to device tree
+ * @compat: compatiable string to match
+ * @compat_off: property name
+ *
+ */
+int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
+ unsigned long compat_off)
+{
+ int len, off = fdt_node_offset_by_compatible(blob, -1, compat);
+ while (off != -FDT_ERR_NOTFOUND) {
+ u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", &len);
+ if (reg) {
+ if (compat_off == fdt_translate_address(blob, off, reg))
+ return off;
+ }
+ off = fdt_node_offset_by_compatible(blob, off, compat);
+ }
+
+ return -FDT_ERR_NOTFOUND;
+}
+
+/**
+ * fdt_alloc_phandle: Return next free phandle value
+ *
+ * @blob: ptr to device tree
+ */
+int fdt_alloc_phandle(void *blob)
+{
+ int offset, phandle = 0;
+
+ for (offset = fdt_next_node(blob, -1, NULL); offset >= 0;
+ offset = fdt_next_node(blob, offset, NULL)) {
+ phandle = max(phandle, fdt_get_phandle(blob, offset));
+ }
+
+ return phandle + 1;
+}
+
+/*
+ * fdt_set_phandle: Create a phandle property for the given node
+ *
+ * @fdt: ptr to device tree
+ * @nodeoffset: node to update
+ * @phandle: phandle value to set (must be unique)
+ */
+int fdt_set_phandle(void *fdt, int nodeoffset, u32 phandle)
+{
+ int ret;
+
+#ifdef DEBUG
+ int off = fdt_node_offset_by_phandle(fdt, phandle);
+
+ if ((off >= 0) && (off != nodeoffset)) {
+ char buf[64];
+
+ fdt_get_path(fdt, nodeoffset, buf, sizeof(buf));
+ printf("Trying to update node %s with phandle %u ",
+ buf, phandle);
+
+ fdt_get_path(fdt, off, buf, sizeof(buf));
+ printf("that already exists in node %s.\n", buf);
+ return -FDT_ERR_BADPHANDLE;
+ }
+#endif
+
+ ret = fdt_setprop_cell(fdt, nodeoffset, "phandle", phandle);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * For now, also set the deprecated "linux,phandle" property, so that we
+ * don't break older kernels.
+ */
+ ret = fdt_setprop_cell(fdt, nodeoffset, "linux,phandle", phandle);
+
+ return ret;
+}
+
+/*
+ * fdt_create_phandle: Create a phandle property for the given node
+ *
+ * @fdt: ptr to device tree
+ * @nodeoffset: node to update
+ */
+unsigned int fdt_create_phandle(void *fdt, int nodeoffset)
+{
+ /* see if there is a phandle already */
+ int phandle = fdt_get_phandle(fdt, nodeoffset);
+
+ /* if we got 0, means no phandle so create one */
+ if (phandle == 0) {
+ int ret;
+
+ phandle = fdt_alloc_phandle(fdt);
+ ret = fdt_set_phandle(fdt, nodeoffset, phandle);
+ if (ret < 0) {
+ printf("Can't set phandle %u: %s\n", phandle,
+ fdt_strerror(ret));
+ return 0;
+ }
+ }
+
+ return phandle;
+}
+
+/*
+ * fdt_set_node_status: Set status for the given node
+ *
+ * @fdt: ptr to device tree
+ * @nodeoffset: node to update
+ * @status: FDT_STATUS_OKAY, FDT_STATUS_DISABLED,
+ * FDT_STATUS_FAIL, FDT_STATUS_FAIL_ERROR_CODE
+ * @error_code: optional, only used if status is FDT_STATUS_FAIL_ERROR_CODE
+ */
+int fdt_set_node_status(void *fdt, int nodeoffset,
+ enum fdt_status status, unsigned int error_code)
+{
+ char buf[16];
+ int ret = 0;
+
+ if (nodeoffset < 0)
+ return nodeoffset;
+
+ switch (status) {
+ case FDT_STATUS_OKAY:
+ ret = fdt_setprop_string(fdt, nodeoffset, "status", "okay");
+ break;
+ case FDT_STATUS_DISABLED:
+ ret = fdt_setprop_string(fdt, nodeoffset, "status", "disabled");
+ break;
+ case FDT_STATUS_FAIL:
+ ret = fdt_setprop_string(fdt, nodeoffset, "status", "fail");
+ break;
+ case FDT_STATUS_FAIL_ERROR_CODE:
+ sprintf(buf, "fail-%d", error_code);
+ ret = fdt_setprop_string(fdt, nodeoffset, "status", buf);
+ break;
+ default:
+ printf("Invalid fdt status: %x\n", status);
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * fdt_set_status_by_alias: Set status for the given node given an alias
+ *
+ * @fdt: ptr to device tree
+ * @alias: alias of node to update
+ * @status: FDT_STATUS_OKAY, FDT_STATUS_DISABLED,
+ * FDT_STATUS_FAIL, FDT_STATUS_FAIL_ERROR_CODE
+ * @error_code: optional, only used if status is FDT_STATUS_FAIL_ERROR_CODE
+ */
+int fdt_set_status_by_alias(void *fdt, const char* alias,
+ enum fdt_status status, unsigned int error_code)
+{
+ int offset = fdt_path_offset(fdt, alias);
+
+ return fdt_set_node_status(fdt, offset, status, error_code);
+}
+
+#if defined(CONFIG_VIDEO)
+int fdt_add_edid(void *blob, const char *compat, unsigned char *edid_buf)
+{
+ int noff;
+ int ret;
+
+ noff = fdt_node_offset_by_compatible(blob, -1, compat);
+ if (noff != -FDT_ERR_NOTFOUND) {
+ debug_printf("%s: %s\n", fdt_get_name(blob, noff, 0), compat);
+add_edid:
+ ret = fdt_setprop(blob, noff, "edid", edid_buf, 128);
+ if (ret == -FDT_ERR_NOSPACE) {
+ ret = fdt_increase_size(blob, 512);
+ if (!ret)
+ goto add_edid;
+ else
+ goto err_size;
+ } else if (ret < 0) {
+ printf("Can't add property: %s\n", fdt_strerror(ret));
+ return ret;
+ }
+ }
+ return 0;
+err_size:
+ printf("Can't increase blob size: %s\n", fdt_strerror(ret));
+ return ret;
+}
+#endif
+
+/*
+ * Verify the physical address of device tree node for a given alias
+ *
+ * This function locates the device tree node of a given alias, and then
+ * verifies that the physical address of that device matches the given
+ * parameter. It displays a message if there is a mismatch.
+ *
+ * Returns 1 on success, 0 on failure
+ */
+int fdt_verify_alias_address(void *fdt, int anode, const char *alias, u64 addr)
+{
+ const char *path;
+ const u32 *reg;
+ int node, len;
+ u64 dt_addr;
+
+ path = fdt_getprop(fdt, anode, alias, NULL);
+ if (!path) {
+ /* If there's no such alias, then it's not a failure */
+ return 1;
+ }
+
+ node = fdt_path_offset(fdt, path);
+ if (node < 0) {
+ printf("Warning: device tree alias '%s' points to invalid "
+ "node %s.\n", alias, path);
+ return 0;
+ }
+
+ reg = fdt_getprop(fdt, node, "reg", &len);
+ if (!reg) {
+ printf("Warning: device tree node '%s' has no address.\n",
+ path);
+ return 0;
+ }
+
+ dt_addr = fdt_translate_address(fdt, node, reg);
+ if (addr != dt_addr) {
+ printf("Warning: U-Boot configured device %s at address %llx,\n"
+ " but the device tree has it address %llx.\n",
+ alias, addr, dt_addr);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Returns the base address of an SOC or PCI node
+ */
+u64 fdt_get_base_address(void *fdt, int node)
+{
+ int size;
+ u32 naddr;
+ const u32 *prop;
+
+ prop = fdt_getprop(fdt, node, "#address-cells", &size);
+ if (prop && size == 4)
+ naddr = *prop;
+ else
+ naddr = 2;
+
+ prop = fdt_getprop(fdt, node, "ranges", &size);
+
+ return prop ? fdt_translate_address(fdt, node, prop + naddr) : 0;
+}
diff --git a/tests/arm64/common/basic/libfdt/fdt_support.h b/tests/arm64/common/basic/libfdt/fdt_support.h
new file mode 100644
index 0000000..d32ec6c
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt_support.h
@@ -0,0 +1,123 @@
+/*
+ * (C) Copyright 2007
+ * Gerald Van Baren, Custom IDEAS, vanb...@cideas.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __FDT_SUPPORT_H
+#define __FDT_SUPPORT_H
+
+#include <arm_string.h>
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt_env.h>
+
+static void inline strtoul(char *s, void *ptr, int ign, unsigned long *value)
+{
+ *value = arm_hexstr2ulonglong(s);
+}
+
+u32 fdt_getprop_u32_default(const void *fdt, const char *path,
+ const char *prop, const u32 dflt);
+int fdt_chosen(void *fdt, int force);
+int fdt_initrd(void *fdt, unsigned long initrd_start, unsigned long initrd_end, int force);
+void do_fixup_by_path(void *fdt, const char *path, const char *prop,
+ const void *val, int len, int create);
+void do_fixup_by_path_u32(void *fdt, const char *path, const char *prop,
+ u32 val, int create);
+
+static inline void do_fixup_by_path_string(void *fdt, const char *path,
+ const char *prop, const char *status)
+{
+ do_fixup_by_path(fdt, path, prop, status, strlen(status) + 1, 1);
+}
+
+void do_fixup_by_prop(void *fdt,
+ const char *pname, const void *pval, int plen,
+ const char *prop, const void *val, int len,
+ int create);
+void do_fixup_by_prop_u32(void *fdt,
+ const char *pname, const void *pval, int plen,
+ const char *prop, u32 val, int create);
+void do_fixup_by_compat(void *fdt, const char *compat,
+ const char *prop, const void *val, int len, int create);
+void do_fixup_by_compat_u32(void *fdt, const char *compat,
+ const char *prop, u32 val, int create);
+int fdt_fixup_memory(void *blob, u64 start, u64 size);
+int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks);
+void fdt_fixup_ethernet(void *fdt);
+int fdt_find_and_setprop(void *fdt, const char *node, const char *prop,
+ const void *val, int len, int create);
+void fdt_fixup_qe_firmware(void *fdt);
+
+#ifdef CONFIG_OF_BOARD_SETUP
+void ft_board_setup(void *blob, bd_t *bd);
+void ft_cpu_setup(void *blob, bd_t *bd);
+void ft_pci_setup(void *blob, bd_t *bd);
+#endif
+
+void set_working_fdt_addr(void *addr);
+int fdt_resize(void *blob);
+int fdt_increase_size(void *fdt, int add_len);
+
+int fdt_fixup_nor_flash_size(void *blob);
+
+void fdt_fixup_mtdparts(void *fdt, void *node_info, int node_info_size);
+void fdt_del_node_and_alias(void *blob, const char *alias);
+u64 fdt_translate_address(void *blob, int node_offset, const u32 *in_addr);
+int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
+ unsigned long compat_off);
+int fdt_alloc_phandle(void *blob);
+int fdt_set_phandle(void *fdt, int nodeoffset, u32 phandle);
+unsigned int fdt_create_phandle(void *fdt, int nodeoffset);
+int fdt_add_edid(void *blob, const char *compat, unsigned char *buf);
+
+int fdt_verify_alias_address(void *fdt, int anode, const char *alias,
+ u64 addr);
+u64 fdt_get_base_address(void *fdt, int node);
+
+enum fdt_status {
+ FDT_STATUS_OKAY,
+ FDT_STATUS_DISABLED,
+ FDT_STATUS_FAIL,
+ FDT_STATUS_FAIL_ERROR_CODE,
+};
+int fdt_set_node_status(void *fdt, int nodeoffset,
+ enum fdt_status status, unsigned int error_code);
+static inline int fdt_status_okay(void *fdt, int nodeoffset)
+{
+ return fdt_set_node_status(fdt, nodeoffset, FDT_STATUS_OKAY, 0);
+}
+static inline int fdt_status_disabled(void *fdt, int nodeoffset)
+{
+ return fdt_set_node_status(fdt, nodeoffset, FDT_STATUS_DISABLED, 0);
+}
+
+int fdt_set_status_by_alias(void *fdt, const char* alias,
+ enum fdt_status status, unsigned int error_code);
+static inline int fdt_status_okay_by_alias(void *fdt, const char* alias)
+{
+ return fdt_set_status_by_alias(fdt, alias, FDT_STATUS_OKAY, 0);
+}
+static inline int fdt_status_disabled_by_alias(void *fdt, const char* alias)
+{
+ return fdt_set_status_by_alias(fdt, alias, FDT_STATUS_DISABLED, 0);
+}
+
+#endif /* ifndef __FDT_SUPPORT_H */
diff --git a/tests/arm64/common/basic/libfdt/fdt_sw.c b/tests/arm64/common/basic/libfdt/fdt_sw.c
new file mode 100644
index 0000000..69bc572
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt_sw.c
@@ -0,0 +1,256 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <libfdt/libfdt_env.h>
+
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int _fdt_sw_check_header(void *fdt)
+{
+ if (fdt_magic(fdt) != FDT_SW_MAGIC)
+ return -FDT_ERR_BADMAGIC;
+ /* FIXME: should check more details about the header state */
+ return 0;
+}
+
+#define FDT_SW_CHECK_HEADER(fdt) \
+ { \
+ int err; \
+ if ((err = _fdt_sw_check_header(fdt)) != 0) \
+ return err; \
+ }
+
+static void *_fdt_grab_space(void *fdt, size_t len)
+{
+ int offset = fdt_size_dt_struct(fdt);
+ int spaceleft;
+
+ spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
+ - fdt_size_dt_strings(fdt);
+
+ if ((offset + len < offset) || (offset + len > spaceleft))
+ return NULL;
+
+ fdt_set_size_dt_struct(fdt, offset + len);
+ return _fdt_offset_ptr_w(fdt, offset);
+}
+
+int fdt_create(void *buf, int bufsize)
+{
+ void *fdt = buf;
+
+ if (bufsize < sizeof(struct fdt_header))
+ return -FDT_ERR_NOSPACE;
+
+ memset(buf, 0, bufsize);
+
+ fdt_set_magic(fdt, FDT_SW_MAGIC);
+ fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
+ fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+ fdt_set_totalsize(fdt, bufsize);
+
+ fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
+ sizeof(struct fdt_reserve_entry)));
+ fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
+ fdt_set_off_dt_strings(fdt, bufsize);
+
+ return 0;
+}
+
+int fdt_add_reservemap_entry(void *fdt, u64 addr, u64 size)
+{
+ struct fdt_reserve_entry *re;
+ int offset;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ if (fdt_size_dt_struct(fdt))
+ return -FDT_ERR_BADSTATE;
+
+ offset = fdt_off_dt_struct(fdt);
+ if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
+ return -FDT_ERR_NOSPACE;
+
+ re = (struct fdt_reserve_entry *)((char *)fdt + offset);
+ re->address = cpu_to_fdt64(addr);
+ re->size = cpu_to_fdt64(size);
+
+ fdt_set_off_dt_struct(fdt, offset + sizeof(*re));
+
+ return 0;
+}
+
+int fdt_finish_reservemap(void *fdt)
+{
+ return fdt_add_reservemap_entry(fdt, 0, 0);
+}
+
+int fdt_begin_node(void *fdt, const char *name)
+{
+ struct fdt_node_header *nh;
+ int namelen = strlen(name) + 1;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
+ if (! nh)
+ return -FDT_ERR_NOSPACE;
+
+ nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
+ memcpy(nh->name, name, namelen);
+ return 0;
+}
+
+int fdt_end_node(void *fdt)
+{
+ u32 *en;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ en = _fdt_grab_space(fdt, FDT_TAGSIZE);
+ if (! en)
+ return -FDT_ERR_NOSPACE;
+
+ *en = cpu_to_fdt32(FDT_END_NODE);
+ return 0;
+}
+
+static int _fdt_find_add_string(void *fdt, const char *s)
+{
+ char *strtab = (char *)fdt + fdt_totalsize(fdt);
+ const char *p;
+ int strtabsize = fdt_size_dt_strings(fdt);
+ int len = strlen(s) + 1;
+ int struct_top, offset;
+
+ p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
+ if (p)
+ return p - strtab;
+
+ /* Add it */
+ offset = -strtabsize - len;
+ struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
+ if (fdt_totalsize(fdt) + offset < struct_top)
+ return 0; /* no more room :( */
+
+ memcpy(strtab + offset, s, len);
+ fdt_set_size_dt_strings(fdt, strtabsize + len);
+ return offset;
+}
+
+int fdt_property(void *fdt, const char *name, const void *val, int len)
+{
+ struct fdt_property *prop;
+ int nameoff;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ nameoff = _fdt_find_add_string(fdt, name);
+ if (nameoff == 0)
+ return -FDT_ERR_NOSPACE;
+
+ prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
+ if (! prop)
+ return -FDT_ERR_NOSPACE;
+
+ prop->tag = cpu_to_fdt32(FDT_PROP);
+ prop->nameoff = cpu_to_fdt32(nameoff);
+ prop->len = cpu_to_fdt32(len);
+ memcpy(prop->data, val, len);
+ return 0;
+}
+
+int fdt_finish(void *fdt)
+{
+ char *p = (char *)fdt;
+ u32 *end;
+ int oldstroffset, newstroffset;
+ u32 tag;
+ int offset, nextoffset;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ /* Add terminator */
+ end = _fdt_grab_space(fdt, sizeof(*end));
+ if (! end)
+ return -FDT_ERR_NOSPACE;
+ *end = cpu_to_fdt32(FDT_END);
+
+ /* Relocate the string table */
+ oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
+ newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
+ memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
+ fdt_set_off_dt_strings(fdt, newstroffset);
+
+ /* Walk the structure, correcting string offsets */
+ offset = 0;
+ while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
+ if (tag == FDT_PROP) {
+ struct fdt_property *prop =
+ _fdt_offset_ptr_w(fdt, offset);
+ int nameoff;
+
+ nameoff = fdt32_to_cpu(prop->nameoff);
+ nameoff += fdt_size_dt_strings(fdt);
+ prop->nameoff = cpu_to_fdt32(nameoff);
+ }
+ offset = nextoffset;
+ }
+ if (nextoffset < 0)
+ return nextoffset;
+
+ /* Finally, adjust the header */
+ fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
+ fdt_set_magic(fdt, FDT_MAGIC);
+ return 0;
+}
diff --git a/tests/arm64/common/basic/libfdt/fdt_wip.c b/tests/arm64/common/basic/libfdt/fdt_wip.c
new file mode 100644
index 0000000..d0e4bc9
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt_wip.c
@@ -0,0 +1,118 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <libfdt/libfdt_env.h>
+
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len)
+{
+ void *propval;
+ int proplen;
+
+ propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
+ if (! propval)
+ return proplen;
+
+ if (proplen != len)
+ return -FDT_ERR_NOSPACE;
+
+ memcpy(propval, val, len);
+ return 0;
+}
+
+static void _fdt_nop_region(void *start, int len)
+{
+ u32 *p;
+
+ for (p = start; (char *)p < ((char *)start + len); p++)
+ *p = cpu_to_fdt32(FDT_NOP);
+}
+
+int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
+{
+ struct fdt_property *prop;
+ int len;
+
+ prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
+ if (! prop)
+ return len;
+
+ _fdt_nop_region(prop, len + sizeof(*prop));
+
+ return 0;
+}
+
+int _fdt_node_end_offset(void *fdt, int offset)
+{
+ int depth = 0;
+
+ while ((offset >= 0) && (depth >= 0))
+ offset = fdt_next_node(fdt, offset, &depth);
+
+ return offset;
+}
+
+int fdt_nop_node(void *fdt, int nodeoffset)
+{
+ int endoffset;
+
+ endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+ if (endoffset < 0)
+ return endoffset;
+
+ _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
+ endoffset - nodeoffset);
+ return 0;
+}
diff --git a/tests/arm64/common/basic/libfdt/libfdt.h b/tests/arm64/common/basic/libfdt/libfdt.h
new file mode 100644
index 0000000..f74b3e3
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/libfdt.h
@@ -0,0 +1,1237 @@
+#ifndef _LIBFDT_H
+#define _LIBFDT_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <libfdt/libfdt_env.h>
+#include <libfdt/fdt.h>
+
+typedef unsigned long int uintptr_t;
+
+#define FDT_FIRST_SUPPORTED_VERSION 0x10
+#define FDT_LAST_SUPPORTED_VERSION 0x11
+
+/* Error codes: informative error codes */
+#define FDT_ERR_NOTFOUND 1
+ /* FDT_ERR_NOTFOUND: The requested node or property does not exist */
+#define FDT_ERR_EXISTS 2
+ /* FDT_ERR_EXISTS: Attemped to create a node or property which
+ * already exists */
+#define FDT_ERR_NOSPACE 3
+ /* FDT_ERR_NOSPACE: Operation needed to expand the device
+ * tree, but its buffer did not have sufficient space to
+ * contain the expanded tree. Use fdt_open_into() to move the
+ * device tree to a buffer with more space. */
+
+/* Error codes: codes for bad parameters */
+#define FDT_ERR_BADOFFSET 4
+ /* FDT_ERR_BADOFFSET: Function was passed a structure block
+ * offset which is out-of-bounds, or which points to an
+ * unsuitable part of the structure for the operation. */
+#define FDT_ERR_BADPATH 5
+ /* FDT_ERR_BADPATH: Function was passed a badly formatted path
+ * (e.g. missing a leading / for a function which requires an
+ * absolute path) */
+#define FDT_ERR_BADPHANDLE 6
+ /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle
+ * value. phandle values of 0 and -1 are not permitted. */
+#define FDT_ERR_BADSTATE 7
+ /* FDT_ERR_BADSTATE: Function was passed an incomplete device
+ * tree created by the sequential-write functions, which is
+ * not sufficiently complete for the requested operation. */
+
+/* Error codes: codes for bad device tree blobs */
+#define FDT_ERR_TRUNCATED 8
+ /* FDT_ERR_TRUNCATED: Structure block of the given device tree
+ * ends without an FDT_END tag. */
+#define FDT_ERR_BADMAGIC 9
+ /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
+ * device tree at all - it is missing the flattened device
+ * tree magic number. */
+#define FDT_ERR_BADVERSION 10
+ /* FDT_ERR_BADVERSION: Given device tree has a version which
+ * can't be handled by the requested operation. For
+ * read-write functions, this may mean that fdt_open_into() is
+ * required to convert the tree to the expected version. */
+#define FDT_ERR_BADSTRUCTURE 11
+ /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt
+ * structure block or other serious error (e.g. misnested
+ * nodes, or subnodes preceding properties). */
+#define FDT_ERR_BADLAYOUT 12
+ /* FDT_ERR_BADLAYOUT: For read-write functions, the given
+ * device tree has it's sub-blocks in an order that the
+ * function can't handle (memory reserve map, then structure,
+ * then strings). Use fdt_open_into() to reorganize the tree
+ * into a form suitable for the read-write operations. */
+
+/* "Can't happen" error indicating a bug in libfdt */
+#define FDT_ERR_INTERNAL 13
+ /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion.
+ * Should never be returned, if it is, it indicates a bug in
+ * libfdt itself. */
+
+#define FDT_ERR_MAX 13
+
+/**********************************************************************/
+/* Low-level functions (you probably don't need these) */
+/**********************************************************************/
+
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
+static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
+{
+ return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
+}
+
+u32 fdt_next_tag(const void *fdt, int offset, int *nextoffset);
+
+/**********************************************************************/
+/* Traversal functions */
+/**********************************************************************/
+
+int fdt_next_node(const void *fdt, int offset, int *depth);
+
+/**********************************************************************/
+/* General functions */
+/**********************************************************************/
+
+#define fdt_get_header(fdt, field) \
+ (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
+#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
+#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
+#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
+#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings))
+#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap))
+#define fdt_version(fdt) (fdt_get_header(fdt, version))
+#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version))
+#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys))
+#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
+#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct))
+
+#define __fdt_set_hdr(name) \
+ static inline void fdt_set_##name(void *fdt, u32 val) \
+ { \
+ struct fdt_header *fdth = (struct fdt_header*)fdt; \
+ fdth->name = cpu_to_fdt32(val); \
+ }
+__fdt_set_hdr(magic);
+__fdt_set_hdr(totalsize);
+__fdt_set_hdr(off_dt_struct);
+__fdt_set_hdr(off_dt_strings);
+__fdt_set_hdr(off_mem_rsvmap);
+__fdt_set_hdr(version);
+__fdt_set_hdr(last_comp_version);
+__fdt_set_hdr(boot_cpuid_phys);
+__fdt_set_hdr(size_dt_strings);
+__fdt_set_hdr(size_dt_struct);
+#undef __fdt_set_hdr
+
+/**
+ * fdt_check_header - sanity check a device tree or possible device tree
+ * @fdt: pointer to data which might be a flattened device tree
+ *
+ * fdt_check_header() checks that the given buffer contains what
+ * appears to be a flattened device tree with sane information in its
+ * header.
+ *
+ * returns:
+ * 0, if the buffer appears to contain a valid device tree
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE, standard meanings, as above
+ */
+int fdt_check_header(const void *fdt);
+
+/**
+ * fdt_move - move a device tree around in memory
+ * @fdt: pointer to the device tree to move
+ * @buf: pointer to memory where the device is to be moved
+ * @bufsize: size of the memory space at buf
+ *
+ * fdt_move() relocates, if possible, the device tree blob located at
+ * fdt to the buffer at buf of size bufsize. The buffer may overlap
+ * with the existing device tree blob at fdt. Therefore,
+ * fdt_move(fdt, fdt, fdt_totalsize(fdt))
+ * should always succeed.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_move(const void *fdt, void *buf, int bufsize);
+
+/**********************************************************************/
+/* Read-only functions */
+/**********************************************************************/
+
+/**
+ * fdt_string - retrieve a string from the strings block of a device tree
+ * @fdt: pointer to the device tree blob
+ * @stroffset: offset of the string within the strings block (native endian)
+ *
+ * fdt_string() retrieves a pointer to a single string from the
+ * strings block of the device tree blob at fdt.
+ *
+ * returns:
+ * a pointer to the string, on success
+ * NULL, if stroffset is out of bounds
+ */
+const char *fdt_string(const void *fdt, int stroffset);
+
+/**
+ * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
+ * @fdt: pointer to the device tree blob
+ *
+ * Returns the number of entries in the device tree blob's memory
+ * reservation map. This does not include the terminating 0,0 entry
+ * or any other (0,0) entries reserved for expansion.
+ *
+ * returns:
+ * the number of entries
+ */
+int fdt_num_mem_rsv(const void *fdt);
+
+/**
+ * fdt_get_mem_rsv - retrieve one memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @address, @size: pointers to 64-bit variables
+ *
+ * On success, *address and *size will contain the address and size of
+ * the n-th reserve map entry from the device tree blob, in
+ * native-endian format.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_get_mem_rsv(const void *fdt, int n, u64 *address, u64 *size);
+
+/**
+ * fdt_subnode_offset_namelen - find a subnode based on substring
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_subnode_offset(), but only examine the first
+ * namelen characters of name for matching the subnode name. This is
+ * useful for finding subnodes based on a portion of a larger string,
+ * such as a full path.
+ */
+int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
+ const char *name, int namelen);
+/**
+ * fdt_subnode_offset - find a subnode of a given node
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ *
+ * fdt_subnode_offset() finds a subnode of the node at structure block
+ * offset parentoffset with the given name. name may include a unit
+ * address, in which case fdt_subnode_offset() will find the subnode
+ * with that unit address, or the unit address may be omitted, in
+ * which case fdt_subnode_offset() will find an arbitrary subnode
+ * whose name excluding unit address matches the given name.
+ *
+ * returns:
+ * structure block offset of the requested subnode (>=0), on success
+ * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
+ * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
+
+/**
+ * fdt_path_offset - find a tree node by its full path
+ * @fdt: pointer to the device tree blob
+ * @path: full path of the node to locate
+ *
+ * fdt_path_offset() finds a node of a given path in the device tree.
+ * Each path component may omit the unit address portion, but the
+ * results of this are undefined if any such path component is
+ * ambiguous (that is if there are multiple nodes at the relevant
+ * level matching the given component, differentiated only by unit
+ * address).
+ *
+ * returns:
+ * structure block offset of the node with the requested path (>=0), on success
+ * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
+ * -FDT_ERR_NOTFOUND, if the requested node does not exist
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_path_offset(const void *fdt, const char *path);
+
+/**
+ * fdt_get_name - retrieve the name of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of the starting node
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_name() retrieves the name (including unit address) of the
+ * device tree node at structure block offset nodeoffset. If lenp is
+ * non-NULL, the length of this name is also returned, in the integer
+ * pointed to by lenp.
+ *
+ * returns:
+ * pointer to the node's name, on success
+ * If lenp is non-NULL, *lenp contains the length of that name (>=0)
+ * NULL, on error
+ * if lenp is non-NULL *lenp contains an error code (<0):
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE, standard meanings
+ */
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
+
+/**
+ * fdt_first_property_offset - find the offset of a node's first property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of a node
+ *
+ * fdt_first_property_offset() finds the first property of the node at
+ * the given structure block offset.
+ *
+ * returns:
+ * structure block offset of the property (>=0), on success
+ * -FDT_ERR_NOTFOUND, if the requested node has no properties
+ * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_first_property_offset(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_next_property_offset - step through a node's properties
+ * @fdt: pointer to the device tree blob
+ * @offset: structure block offset of a property
+ *
+ * fdt_next_property_offset() finds the property immediately after the
+ * one at the given structure block offset. This will be a property
+ * of the same node as the given property.
+ *
+ * returns:
+ * structure block offset of the next property (>=0), on success
+ * -FDT_ERR_NOTFOUND, if the given property is the last in its node
+ * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_next_property_offset(const void *fdt, int offset);
+
+/**
+ * fdt_get_property_by_offset - retrieve the property at a given offset
+ * @fdt: pointer to the device tree blob
+ * @offset: offset of the property to retrieve
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_property_by_offset() retrieves a pointer to the
+ * fdt_property structure within the device tree blob at the given
+ * offset. If lenp is non-NULL, the length of the property value is
+ * also returned, in the integer pointed to by lenp.
+ *
+ * returns:
+ * pointer to the structure representing the property
+ * if lenp is non-NULL, *lenp contains the length of the property
+ * value (>=0)
+ * NULL, on error
+ * if lenp is non-NULL, *lenp contains an error code (<0):
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+ int offset,
+ int *lenp);
+
+/**
+ * fdt_get_property_namelen - find a property based on substring
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @namelen: number of characters of name to consider
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * Identical to fdt_get_property_namelen(), but only examine the first
+ * namelen characters of name for matching the property name.
+ */
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+ int nodeoffset,
+ const char *name,
+ int namelen, int *lenp);
+
+/**
+ * fdt_get_property - find a given property in a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_property() retrieves a pointer to the fdt_property
+ * structure within the device tree blob corresponding to the property
+ * named 'name' of the node at offset nodeoffset. If lenp is
+ * non-NULL, the length of the property value is also returned, in the
+ * integer pointed to by lenp.
+ *
+ * returns:
+ * pointer to the structure representing the property
+ * if lenp is non-NULL, *lenp contains the length of the property
+ * value (>=0)
+ * NULL, on error
+ * if lenp is non-NULL, *lenp contains an error code (<0):
+ * -FDT_ERR_NOTFOUND, node does not have named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,
+ const char *name, int *lenp);
+static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
+ const char *name,
+ int *lenp)
+{
+ return (struct fdt_property *)(uintptr_t)
+ fdt_get_property(fdt, nodeoffset, name, lenp);
+}
+
+/**
+ * fdt_getprop_by_offset - retrieve the value of a property at a given offset
+ * @fdt: pointer to the device tree blob
+ * @ffset: offset of the property to read
+ * @namep: pointer to a string variable (will be overwritten) or NULL
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_getprop_by_offset() retrieves a pointer to the value of the
+ * property at structure block offset 'offset' (this will be a pointer
+ * to within the device blob itself, not a copy of the value). If
+ * lenp is non-NULL, the length of the property value is also
+ * returned, in the integer pointed to by lenp. If namep is non-NULL,
+ * the property's namne will also be returned in the char * pointed to
+ * by namep (this will be a pointer to within the device tree's string
+ * block, not a new copy of the name).
+ *
+ * returns:
+ * pointer to the property's value
+ * if lenp is non-NULL, *lenp contains the length of the property
+ * value (>=0)
+ * if namep is non-NULL *namep contiains a pointer to the property
+ * name.
+ * NULL, on error
+ * if lenp is non-NULL, *lenp contains an error code (<0):
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+ const char **namep, int *lenp);
+
+/**
+ * fdt_getprop_namelen - get property value based on substring
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @namelen: number of characters of name to consider
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * Identical to fdt_getprop(), but only examine the first namelen
+ * characters of name for matching the property name.
+ */
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+ const char *name, int namelen, int *lenp);
+
+/**
+ * fdt_getprop - retrieve the value of a given property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_getprop() retrieves a pointer to the value of the property
+ * named 'name' of the node at offset nodeoffset (this will be a
+ * pointer to within the device blob itself, not a copy of the value).
+ * If lenp is non-NULL, the length of the property value is also
+ * returned, in the integer pointed to by lenp.
+ *
+ * returns:
+ * pointer to the property's value
+ * if lenp is non-NULL, *lenp contains the length of the property
+ * value (>=0)
+ * NULL, on error
+ * if lenp is non-NULL, *lenp contains an error code (<0):
+ * -FDT_ERR_NOTFOUND, node does not have named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+ const char *name, int *lenp);
+static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
+ const char *name, int *lenp)
+{
+ return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp);
+}
+
+/**
+ * fdt_get_phandle - retrieve the phandle of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of the node
+ *
+ * fdt_get_phandle() retrieves the phandle of the device tree node at
+ * structure block offset nodeoffset.
+ *
+ * returns:
+ * the phandle of the node at nodeoffset, on success (!= 0, != -1)
+ * 0, if the node has no phandle, or another error occurs
+ */
+u32 fdt_get_phandle(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_get_alias_namelen - get alias based on substring
+ * @fdt: pointer to the device tree blob
+ * @name: name of the alias th look up
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_get_alias(), but only examine the first namelen
+ * characters of name for matching the alias name.
+ */
+const char *fdt_get_alias_namelen(const void *fdt,
+ const char *name, int namelen);
+
+/**
+ * fdt_get_alias - retreive the path referenced by a given alias
+ * @fdt: pointer to the device tree blob
+ * @name: name of the alias th look up
+ *
+ * fdt_get_alias() retrieves the value of a given alias. That is, the
+ * value of the property named 'name' in the node /aliases.
+ *
+ * returns:
+ * a pointer to the expansion of the alias named 'name', of it exists
+ * NULL, if the given alias or the /aliases node does not exist
+ */
+const char *fdt_get_alias(const void *fdt, const char *name);
+
+/**
+ * fdt_get_path - determine the full path of a node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose path to find
+ * @buf: character buffer to contain the returned path (will be overwritten)
+ * @buflen: size of the character buffer at buf
+ *
+ * fdt_get_path() computes the full path of the node at offset
+ * nodeoffset, and records that path in the buffer at buf.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+ * 0, on success
+ * buf contains the absolute path of the node at
+ * nodeoffset, as a NUL-terminated string.
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)
+ * characters and will not fit in the given buffer.
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
+
+/**
+ * fdt_supernode_atdepth_offset - find a specific ancestor of a node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ * @supernodedepth: depth of the ancestor to find
+ * @nodedepth: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_supernode_atdepth_offset() finds an ancestor of the given node
+ * at a specific depth from the root (where the root itself has depth
+ * 0, its immediate subnodes depth 1 and so forth). So
+ * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL);
+ * will always return 0, the offset of the root node. If the node at
+ * nodeoffset has depth D, then:
+ * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL);
+ * will return nodeoffset itself.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+
+ * structure block offset of the node at node offset's ancestor
+ * of depth supernodedepth (>=0), on success
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+* -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
+ int supernodedepth, int *nodedepth);
+
+/**
+ * fdt_node_depth - find the depth of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ *
+ * fdt_node_depth() finds the depth of a given node. The root node
+ * has depth 0, its immediate subnodes depth 1 and so forth.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+ * depth of the node at nodeoffset (>=0), on success
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_depth(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_parent_offset - find the parent of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ *
+ * fdt_parent_offset() locates the parent node of a given node (that
+ * is, it finds the offset of the node which contains the node at
+ * nodeoffset as a subnode).
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset, *twice*.
+ *
+ * returns:
+ * structure block offset of the parent of the node at nodeoffset
+ * (>=0), on success
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_parent_offset(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_node_offset_by_prop_value - find nodes with a given property value
+ * @fdt: pointer to the device tree blob
+ * @startoffset: only find nodes after this offset
+ * @propname: property name to check
+ * @propval: property value to search for
+ * @proplen: length of the value in propval
+ *
+ * fdt_node_offset_by_prop_value() returns the offset of the first
+ * node after startoffset, which has a property named propname whose
+ * value is of length proplen and has value equal to propval; or if
+ * startoffset is -1, the very first such node in the tree.
+ *
+ * To iterate through all nodes matching the criterion, the following
+ * idiom can be used:
+ * offset = fdt_node_offset_by_prop_value(fdt, -1, propname,
+ * propval, proplen);
+ * while (offset != -FDT_ERR_NOTFOUND) {
+ * ... other code here ...
+ * offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
+ * propval, proplen);
+ * }
+ *
+ * Note the -1 in the first call to the function, if 0 is used here
+ * instead, the function will never locate the root node, even if it
+ * matches the criterion.
+ *
+ * returns:
+ * structure block offset of the located node (>= 0, >startoffset),
+ * on success
+ * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
+ * tree after startoffset
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
+ const char *propname,
+ const void *propval, int proplen);
+
+/**
+ * fdt_node_offset_by_phandle - find the node with a given phandle
+ * @fdt: pointer to the device tree blob
+ * @phandle: phandle value
+ *
+ * fdt_node_offset_by_phandle() returns the offset of the node
+ * which has the given phandle value. If there is more than one node
+ * in the tree with the given phandle (an invalid tree), results are
+ * undefined.
+ *
+ * returns:
+ * structure block offset of the located node (>= 0), on success
+ * -FDT_ERR_NOTFOUND, no node with that phandle exists
+ * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1)
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_phandle(const void *fdt, u32 phandle);
+
+/**
+ * fdt_node_check_compatible: check a node's compatible property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @compatible: string to match against
+ *
+ *
+ * fdt_node_check_compatible() returns 0 if the given node contains a
+ * 'compatible' property with the given string as one of its elements,
+ * it returns non-zero otherwise, or on error.
+ *
+ * returns:
+ * 0, if the node has a 'compatible' property listing the given string
+ * 1, if the node has a 'compatible' property, but it does not list
+ * the given string
+ * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
+ * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_check_compatible(const void *fdt, int nodeoffset,
+ const char *compatible);
+
+/**
+ * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value
+ * @fdt: pointer to the device tree blob
+ * @startoffset: only find nodes after this offset
+ * @compatible: 'compatible' string to match against
+ *
+ * fdt_node_offset_by_compatible() returns the offset of the first
+ * node after startoffset, which has a 'compatible' property which
+ * lists the given compatible string; or if startoffset is -1, the
+ * very first such node in the tree.
+ *
+ * To iterate through all nodes matching the criterion, the following
+ * idiom can be used:
+ * offset = fdt_node_offset_by_compatible(fdt, -1, compatible);
+ * while (offset != -FDT_ERR_NOTFOUND) {
+ * ... other code here ...
+ * offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
+ * }
+ *
+ * Note the -1 in the first call to the function, if 0 is used here
+ * instead, the function will never locate the root node, even if it
+ * matches the criterion.
+ *
+ * returns:
+ * structure block offset of the located node (>= 0, >startoffset),
+ * on success
+ * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
+ * tree after startoffset
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
+ const char *compatible);
+
+/**********************************************************************/
+/* Write-in-place functions */
+/**********************************************************************/
+
+/**
+ * fdt_setprop_inplace - change a property's value, but not its size
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: pointer to data to replace the property value with
+ * @len: length of the property value
+ *
+ * fdt_setprop_inplace() replaces the value of a given property with
+ * the data in val, of length len. This function cannot change the
+ * size of a property, and so will only work if len is equal to the
+ * current length of the property.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, if len is not equal to the property's current length
+ * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len);
+
+/**
+ * fdt_setprop_inplace_cell - change the value of a single-cell property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: cell (32-bit integer) value to replace the property with
+ *
+ * fdt_setprop_inplace_cell() replaces the value of a given property
+ * with the 32-bit integer cell value in val, converting val to
+ * big-endian if necessary. This function cannot change the size of a
+ * property, and so will only work if the property already exists and
+ * has length 4.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, if the property's length is not equal to 4
+ * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
+ const char *name, u32 val)
+{
+ val = cpu_to_fdt32(val);
+ return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_nop_property - replace a property with nop tags
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to nop
+ * @name: name of the property to nop
+ *
+ * fdt_nop_property() will replace a given property's representation
+ * in the blob with FDT_NOP tags, effectively removing it from the
+ * tree.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the property, and will not alter or move any other part of the
+ * tree.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_nop_property(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_nop_node - replace a node (subtree) with nop tags
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node to nop
+ *
+ * fdt_nop_node() will replace a given node's representation in the
+ * blob, including all its subnodes, if any, with FDT_NOP tags,
+ * effectively removing it from the tree.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the node and its properties and subnodes, and will not alter or
+ * move any other part of the tree.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_nop_node(void *fdt, int nodeoffset);
+
+/**********************************************************************/
+/* Sequential write functions */
+/**********************************************************************/
+
+int fdt_create(void *buf, int bufsize);
+int fdt_add_reservemap_entry(void *fdt, u64 addr, u64 size);
+int fdt_finish_reservemap(void *fdt);
+int fdt_begin_node(void *fdt, const char *name);
+int fdt_property(void *fdt, const char *name, const void *val, int len);
+static inline int fdt_property_cell(void *fdt, const char *name, u32 val)
+{
+ val = cpu_to_fdt32(val);
+ return fdt_property(fdt, name, &val, sizeof(val));
+}
+#define fdt_property_string(fdt, name, str) \
+ fdt_property(fdt, name, str, strlen(str)+1)
+int fdt_end_node(void *fdt);
+int fdt_finish(void *fdt);
+
+/**********************************************************************/
+/* Read-write functions */
+/**********************************************************************/
+
+int fdt_open_into(const void *fdt, void *buf, int bufsize);
+int fdt_pack(void *fdt);
+
+/**
+ * fdt_add_mem_rsv - add one memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @address, @size: 64-bit values (native endian)
+ *
+ * Adds a reserve map entry to the given blob reserving a region at
+ * address address of length size.
+ *
+ * This function will insert data into the reserve map and will
+ * therefore change the indexes of some entries in the table.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new reservation entry
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_add_mem_rsv(void *fdt, u64 address, u64 size);
+
+/**
+ * fdt_del_mem_rsv - remove a memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @n: entry to remove
+ *
+ * fdt_del_mem_rsv() removes the n-th memory reserve map entry from
+ * the blob.
+ *
+ * This function will delete data from the reservation table and will
+ * therefore change the indexes of some entries in the table.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there
+ * are less than n+1 reserve map entries)
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_del_mem_rsv(void *fdt, int n);
+
+/**
+ * fdt_set_name - change the name of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of a node
+ * @name: name to give the node
+ *
+ * fdt_set_name() replaces the name (including unit address, if any)
+ * of the given node with the given string. NOTE: this function can't
+ * efficiently check if the new name is unique amongst the given
+ * node's siblings; results are undefined if this function is invoked
+ * with a name equal to one of the given node's siblings.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob
+ * to contain the new name
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_set_name(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_setprop - create or change a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: pointer to data to set the property value to
+ * @len: length of the property value
+ *
+ * fdt_setprop() sets the value of the named property in the given
+ * node to the given value and length, creating the property if it
+ * does not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len);
+
+/**
+ * fdt_setprop_cell - set a property to a single cell value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value for the property (native endian)
+ *
+ * fdt_setprop_cell() sets the value of the named property in the
+ * given node to the given cell value (converting to big-endian if
+ * necessary), or creates a new property with that value if it does
+ * not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
+ u32 val)
+{
+ val = cpu_to_fdt32(val);
+ return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_setprop_string - set a property to a string value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @str: string value for the property
+ *
+ * fdt_setprop_string() sets the value of the named property in the
+ * given node to the given string value (using the length of the
+ * string to determine the new length of the property), or creates a
+ * new property with that value if it does not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+#define fdt_setprop_string(fdt, nodeoffset, name, str) \
+ fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+
+/**
+ * fdt_delprop - delete a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to nop
+ * @name: name of the property to nop
+ *
+ * fdt_del_property() will delete the given property.
+ *
+ * This function will delete data from the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_delprop(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_add_subnode_namelen - creates a new node based on substring
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_add_subnode(), but use only the first namelen
+ * characters of name as the name of the new node. This is useful for
+ * creating subnodes based on a portion of a larger string, such as a
+ * full path.
+ */
+int fdt_add_subnode_namelen(void *fdt, int parentoffset,
+ const char *name, int namelen);
+
+/**
+ * fdt_add_subnode - creates a new node
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ *
+ * fdt_add_subnode() creates a new node as a subnode of the node at
+ * structure block offset parentoffset, with the given name (which
+ * should include the unit address, if any).
+ *
+ * This function will insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+
+ * returns:
+ * structure block offset of the created nodeequested subnode (>=0), on success
+ * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
+ * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
+ * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of
+ * the given name
+ * -FDT_ERR_NOSPACE, if there is insufficient free space in the
+ * blob to contain the new node
+ * -FDT_ERR_NOSPACE
+ * -FDT_ERR_BADLAYOUT
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
+
+/**
+ * fdt_del_node - delete a node (subtree)
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node to nop
+ *
+ * fdt_del_node() will remove the given node, including all its
+ * subnodes if any, from the blob.
+ *
+ * This function will delete data from the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_del_node(void *fdt, int nodeoffset);
+
+/**********************************************************************/
+/* Debugging / informational functions */
+/**********************************************************************/
+
+const char *fdt_strerror(int errval);
+
+#endif /* _LIBFDT_H */
diff --git a/tests/arm64/common/basic/libfdt/libfdt_env.h b/tests/arm64/common/basic/libfdt/libfdt_env.h
new file mode 100644
index 0000000..18eec23
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/libfdt_env.h
@@ -0,0 +1,49 @@
+/*
+ * libfdt - Flat Device Tree manipulation (build/run environment adaptation)
+ * Copyright (C) 2007 Gerald Van Baren, Custom IDEAS, vanb...@cideas.com
+ * Original version written by David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _LIBFDT_ENV_H
+#define _LIBFDT_ENV_H
+
+#include <arm_types.h>
+#include <arm_stdio.h>
+#include <arm_string.h>
+
+extern struct fdt_header *working_fdt; /* Pointer to the working fdt */
+
+#define fdt32_to_cpu(x) be32_to_cpu(x)
+#define cpu_to_fdt32(x) cpu_to_be32(x)
+#define fdt64_to_cpu(x) be64_to_cpu(x)
+#define cpu_to_fdt64(x) cpu_to_be64(x)
+
+#define memmove arm_memmove
+#define memcpy arm_memcpy
+#define memcmp arm_memcmp
+#define memchr arm_memchr
+#define memset arm_memset
+#define strchr arm_strchr
+#define strcpy arm_strcpy
+#define strcmp arm_strcmp
+#define strlen arm_strlen
+
+#define printf arm_printf
+#define sprintf arm_sprintf
+#define snprintf arm_snprintf
+
+#endif /* _LIBFDT_ENV_H */
diff --git a/tests/arm64/common/basic/libfdt/libfdt_internal.h b/tests/arm64/common/basic/libfdt/libfdt_internal.h
new file mode 100644
index 0000000..2a5e120
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/libfdt_internal.h
@@ -0,0 +1,95 @@
+#ifndef _LIBFDT_INTERNAL_H
+#define _LIBFDT_INTERNAL_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <libfdt/fdt.h>
+
+#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
+#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
+
+#define FDT_CHECK_HEADER(fdt) \
+ { \
+ int err; \
+ if ((err = fdt_check_header(fdt)) != 0) \
+ return err; \
+ }
+
+int _fdt_check_node_offset(const void *fdt, int offset);
+int _fdt_check_prop_offset(const void *fdt, int offset);
+const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
+int _fdt_node_end_offset(void *fdt, int nodeoffset);
+
+static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
+{
+ return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
+}
+
+static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
+{
+ return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
+}
+
+static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
+{
+ const struct fdt_reserve_entry *rsv_table =
+ (const struct fdt_reserve_entry *)
+ ((const char *)fdt + fdt_off_mem_rsvmap(fdt));
+
+ return rsv_table + n;
+}
+static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
+{
+ return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
+}
+
+#define FDT_SW_MAGIC (~FDT_MAGIC)
+
+#endif /* _LIBFDT_INTERNAL_H */
diff --git a/tests/arm64/common/basic/pic/gic.c b/tests/arm64/common/basic/pic/gic.c
new file mode 100644
index 0000000..d5596e8
--- /dev/null
+++ b/tests/arm64/common/basic/pic/gic.c
@@ -0,0 +1,225 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file gic.c
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief ARM Generic Interrupt Controller
+ */
+
+#include <arm_io.h>
+#include <arm_stdio.h>
+#include <gic_config.h>
+#include <pic/gic.h>
+
+#define max(a,b) ((a) < (b) ? (b) : (a))
+
+struct gic_chip_data {
+ u32 irq_offset;
+ virtual_addr_t dist_base;
+ virtual_addr_t cpu_base;
+};
+
+static struct gic_chip_data gic_data[GIC_MAX_NR];
+
+static inline void gic_write(u32 val, virtual_addr_t addr)
+{
+ arm_writel(val, (void *)(addr));
+}
+
+static inline u32 gic_read(virtual_addr_t addr)
+{
+ return arm_readl((void *)(addr));
+}
+
+int gic_active_irq(u32 gic_nr)
+{
+ int ret = -1;
+
+ if (GIC_MAX_NR <= gic_nr) {
+ return -1;
+ }
+
+ ret = gic_read(gic_data[gic_nr].cpu_base +
+ GIC_CPU_INTACK) & 0x3FF;
+ ret += gic_data[gic_nr].irq_offset;
+
+ return ret;
+}
+
+int gic_eoi_irq(u32 gic_nr, u32 irq)
+{
+// u32 mask = 1 << (irq % 32);
+ u32 gic_irq;
+
+ if (GIC_MAX_NR <= gic_nr) {
+ return -1;
+ }
+
+ if (irq < gic_data[gic_nr].irq_offset) {
+ return -1;
+ }
+
+ gic_irq = irq - gic_data[gic_nr].irq_offset;
+
+ /*
+ *gic_write(mask, gic_data[gic_nr].dist_base +
+ * GIC_DIST_ENABLE_CLEAR + (gic_irq / 32) * 4);
+ */
+ gic_write(gic_irq, gic_data[gic_nr].cpu_base + GIC_CPU_EOI);
+ /*
+ *gic_write(mask, gic_data[gic_nr].dist_base +
+ * GIC_DIST_ENABLE_SET + (gic_irq / 32) * 4);
+ */
+
+ return 0;
+}
+
+int gic_mask(u32 gic_nr, u32 irq)
+{
+ u32 mask = 1 << (irq % 32);
+ u32 gic_irq;
+
+ if (GIC_MAX_NR <= gic_nr) {
+ return -1;
+ }
+
+ if (irq < gic_data[gic_nr].irq_offset) {
+ return -1;
+ }
+
+ gic_irq = irq - gic_data[gic_nr].irq_offset;
+
+ gic_write(mask, gic_data[gic_nr].dist_base +
+ GIC_DIST_ENABLE_CLEAR + (gic_irq / 32) * 4);
+
+ return 0;
+}
+
+int gic_unmask(u32 gic_nr, u32 irq)
+{
+ u32 mask = 1 << (irq % 32);
+ u32 gic_irq;
+
+ if (GIC_MAX_NR <= gic_nr) {
+ return -1;
+ }
+
+ if (irq < gic_data[gic_nr].irq_offset) {
+ return -1;
+ }
+
+ gic_irq = irq - gic_data[gic_nr].irq_offset;
+
+ gic_write(mask, gic_data[gic_nr].dist_base +
+ GIC_DIST_ENABLE_SET + (gic_irq / 32) * 4);
+
+ return 0;
+}
+
+int gic_dist_init(u32 gic_nr, virtual_addr_t base, u32 irq_start)
+{
+ unsigned int max_irq, i;
+ u32 cpumask = 1 << 0; /*smp_processor_id(); */
+
+ if (GIC_MAX_NR <= gic_nr) {
+ return -1;
+ }
+
+ cpumask |= cpumask << 8;
+ cpumask |= cpumask << 16;
+
+ gic_data[gic_nr].dist_base = base;
+ gic_data[gic_nr].irq_offset = (irq_start - 1) & ~31;
+
+ gic_write(0, base + GIC_DIST_CTRL);
+
+ /*
+ * Find out how many interrupts are supported.
+ */
+ max_irq = gic_read(base + GIC_DIST_CTR) & 0x1f;
+ max_irq = (max_irq + 1) * 32;
+
+ /*
+ * The GIC only supports up to 1020 interrupt sources.
+ * Limit this to either the architected maximum, or the
+ * platform maximum.
+ */
+ if (max_irq > max(1020, GIC_NR_IRQS))
+ max_irq = max(1020, GIC_NR_IRQS);
+
+ /*
+ * Set all global interrupts to be level triggered, active low.
+ */
+ for (i = 32; i < max_irq; i += 16)
+ gic_write(0, base + GIC_DIST_CONFIG + i * 4 / 16);
+
+ /*
+ * Set all global interrupts to this CPU only.
+ */
+ for (i = 32; i < max_irq; i += 4)
+ gic_write(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
+
+ /*
+ * Set priority on all interrupts.
+ */
+ for (i = 0; i < max_irq; i += 4)
+ gic_write(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
+
+ /*
+ * Disable all interrupts.
+ */
+ for (i = 0; i < max_irq; i += 32)
+ gic_write(0xffffffff,
+ base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
+
+ gic_write(1, base + GIC_DIST_CTRL);
+
+ return 0;
+}
+
+int gic_cpu_init(u32 gic_nr, virtual_addr_t base)
+{
+ int i;
+
+ if (GIC_MAX_NR <= gic_nr) {
+ return -1;
+ }
+
+ gic_data[gic_nr].cpu_base = base;
+
+ /*
+ * Deal with the banked PPI and SGI interrupts - disable all
+ * PPI interrupts, ensure all SGI interrupts are enabled.
+ */
+ gic_write(0xffff0000, gic_data[gic_nr].dist_base + GIC_DIST_ENABLE_CLEAR);
+ gic_write(0x0000ffff, gic_data[gic_nr].dist_base + GIC_DIST_ENABLE_SET);
+
+ /*
+ * Set priority on PPI and SGI interrupts
+ */
+ for (i = 0; i < 32; i += 4) {
+ gic_write(0xa0a0a0a0,
+ gic_data[gic_nr].dist_base + GIC_DIST_PRI + i * 4 / 4);
+ }
+
+
+ gic_write(0xf0, base + GIC_CPU_PRIMASK);
+ gic_write(1, base + GIC_CPU_CTRL);
+
+ return 0;
+}
diff --git a/tests/arm64/common/basic/pic/gic.h b/tests/arm64/common/basic/pic/gic.h
new file mode 100644
index 0000000..7f6e6d0
--- /dev/null
+++ b/tests/arm64/common/basic/pic/gic.h
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file gic.h
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief ARM Generic Interrupt Controller header
+ */
+#ifndef _GIC_H__
+#define _GIC_H__
+
+#include <arm_types.h>
+#include <arm_plat.h>
+
+#define GIC_CPU_CTRL 0x00
+#define GIC_CPU_PRIMASK 0x04
+#define GIC_CPU_BINPOINT 0x08
+#define GIC_CPU_INTACK 0x0c
+#define GIC_CPU_EOI 0x10
+#define GIC_CPU_RUNNINGPRI 0x14
+#define GIC_CPU_HIGHPRI 0x18
+
+#define GIC_DIST_CTRL 0x000
+#define GIC_DIST_CTR 0x004
+#define GIC_DIST_ENABLE_SET 0x100
+#define GIC_DIST_ENABLE_CLEAR 0x180
+#define GIC_DIST_PENDING_SET 0x200
+#define GIC_DIST_PENDING_CLEAR 0x280
+#define GIC_DIST_ACTIVE_BIT 0x300
+#define GIC_DIST_PRI 0x400
+#define GIC_DIST_TARGET 0x800
+#define GIC_DIST_CONFIG 0xc00
+#define GIC_DIST_SOFTINT 0xf00
+
+int gic_active_irq(u32 gic_nr);
+int gic_eoi_irq(u32 gic_nr, u32 irq);
+int gic_mask(u32 gic_nr, u32 irq);
+int gic_unmask(u32 gic_nr, u32 irq);
+int gic_dist_init(u32 gic_nr, virtual_addr_t base, u32 irq_start);
+int gic_cpu_init(u32 gic_nr, virtual_addr_t base);
+
+#endif
diff --git a/tests/arm64/common/basic/serial/pl01x.c b/tests/arm64/common/basic/serial/pl01x.c
new file mode 100644
index 0000000..fa6cee3
--- /dev/null
+++ b/tests/arm64/common/basic/serial/pl01x.c
@@ -0,0 +1,138 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file pl01x.c
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief source file for PrimeCell PL011/PL010 serial port driver.
+ */
+
+#include <arm_io.h>
+#include <arm_math.h>
+#include <serial/pl01x.h>
+
+void pl01x_putc(u64 base, u32 type, char ch)
+{
+ /* Wait until there is space in the FIFO */
+ while (arm_readl((void*)(base + UART_PL01x_FR)) & UART_PL01x_FR_TXFF);
+
+ /* Send the character */
+ arm_writel(ch, (void*)(base + UART_PL01x_DR));
+}
+
+char pl01x_getc(u64 base, u32 type)
+{
+ char data;
+
+ /* Wait until there is data in the FIFO */
+ while (arm_readl((void*)(base + UART_PL01x_FR)) & UART_PL01x_FR_RXFE);
+
+ data = arm_readl((void*)(base + UART_PL01x_DR));
+
+ /* Check for an error flag */
+ if (data & 0xFFFFFF00) {
+ /* Clear the error */
+ arm_writel(0xFFFFFFFF, (void*)(base + UART_PL01x_ECR));
+ return -1;
+ }
+
+ return data;
+}
+
+void pl01x_init(u64 base, u32 type, u32 baudrate, u32 input_clock)
+{
+ unsigned int divider;
+ unsigned int temp;
+ unsigned int remainder;
+ unsigned int fraction;
+
+ if(type==PL01X_TYPE_1) {
+ /* First, disable everything */
+ arm_writel(0x0, (void*)(base + UART_PL011_CR));
+
+ /*
+ * Set baud rate
+ *
+ * IBRD = UART_CLK / (16 * BAUD_RATE)
+ * FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE)))
+ * / (16 * BAUD_RATE))
+ */
+ temp = 16 * baudrate;
+ divider = arm_udiv32(input_clock, temp);
+ remainder = arm_umod32(input_clock, temp);
+ temp = arm_udiv32((8 * remainder), baudrate);
+ fraction = (temp >> 1) + (temp & 1);
+
+ arm_writel(divider, (void*)(base + UART_PL011_IBRD));
+ arm_writel(fraction, (void*)(base + UART_PL011_FBRD));
+
+ /* Set the UART to be 8 bits, 1 stop bit,
+ * no parity, fifo enabled
+ */
+ arm_writel((UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN),
+ (void*)(base + UART_PL011_LCRH));
+
+ /* Finally, enable the UART */
+ arm_writel((UART_PL011_CR_UARTEN |
+ UART_PL011_CR_TXE |
+ UART_PL011_CR_RXE),
+ (void*)(base + UART_PL011_CR));
+ } else {
+ /* First, disable everything */
+ arm_writel(0x0, (void*)(base + UART_PL010_CR));
+
+ /* Set baud rate */
+ switch (baudrate) {
+ case 9600:
+ divider = UART_PL010_BAUD_9600;
+ break;
+
+ case 19200:
+ divider = UART_PL010_BAUD_9600;
+ break;
+
+ case 38400:
+ divider = UART_PL010_BAUD_38400;
+ break;
+
+ case 57600:
+ divider = UART_PL010_BAUD_57600;
+ break;
+
+ case 115200:
+ divider = UART_PL010_BAUD_115200;
+ break;
+
+ default:
+ divider = UART_PL010_BAUD_38400;
+ }
+
+ arm_writel(((divider & 0xf00) >> 8),
+ (void*)(base + UART_PL010_LCRM));
+ arm_writel((divider & 0xff), (void*)(base + UART_PL010_LCRL));
+
+ /* Set the UART to be 8 bits, 1 stop bit,
+ * no parity, fifo enabled */
+ arm_writel((UART_PL010_LCRH_WLEN_8 | UART_PL010_LCRH_FEN),
+ (void*)(base + UART_PL010_LCRH));
+
+ /* Finally, enable the UART */
+ arm_writel((UART_PL010_CR_UARTEN),
+ (void*)(base + UART_PL010_CR));
+ }
+}
+
diff --git a/tests/arm64/common/basic/serial/pl01x.h b/tests/arm64/common/basic/serial/pl01x.h
new file mode 100644
index 0000000..39b6f77
--- /dev/null
+++ b/tests/arm64/common/basic/serial/pl01x.h
@@ -0,0 +1,150 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file pl01x.h
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief Header file for PrimeCell PL011/PL010 serial port driver.
+ */
+
+#ifndef __PL01X_H_
+#define __PL01X_H_
+
+#include <arm_types.h>
+
+#define PL01X_TYPE_0 0
+#define PL01X_TYPE_1 1
+
+/*
+ * ARM PrimeCell UART's (PL010 & PL011)
+ * ------------------------------------
+ *
+ * Definitions common to both PL010 & PL011
+ *
+ */
+#define UART_PL01x_DR 0x00 /* Data read or written from the interface. */
+#define UART_PL01x_RSR 0x04 /* Receive status register (Read). */
+#define UART_PL01x_ECR 0x04 /* Error clear register (Write). */
+#define UART_PL01x_FR 0x18 /* Flag register (Read only). */
+
+#define UART_PL01x_RSR_OE 0x08
+#define UART_PL01x_RSR_BE 0x04
+#define UART_PL01x_RSR_PE 0x02
+#define UART_PL01x_RSR_FE 0x01
+
+#define UART_PL01x_FR_TXFE 0x80
+#define UART_PL01x_FR_RXFF 0x40
+#define UART_PL01x_FR_TXFF 0x20
+#define UART_PL01x_FR_RXFE 0x10
+#define UART_PL01x_FR_BUSY 0x08
+#define UART_PL01x_FR_TMSK (UART_PL01x_FR_TXFF + UART_PL01x_FR_BUSY)
+
+/*
+ * PL010 definitions
+ *
+ */
+#define UART_PL010_LCRH 0x08 /* Line control register, high byte. */
+#define UART_PL010_LCRM 0x0C /* Line control register, middle byte. */
+#define UART_PL010_LCRL 0x10 /* Line control register, low byte. */
+#define UART_PL010_CR 0x14 /* Control register. */
+#define UART_PL010_IIR 0x1C /* Interrupt indentification register (Read). */
+#define UART_PL010_ICR 0x1C /* Interrupt clear register (Write). */
+#define UART_PL010_ILPR 0x20 /* IrDA low power counter register. */
+
+#define UART_PL010_CR_LPE (1 << 7)
+#define UART_PL010_CR_RTIE (1 << 6)
+#define UART_PL010_CR_TIE (1 << 5)
+#define UART_PL010_CR_RIE (1 << 4)
+#define UART_PL010_CR_MSIE (1 << 3)
+#define UART_PL010_CR_IIRLP (1 << 2)
+#define UART_PL010_CR_SIREN (1 << 1)
+#define UART_PL010_CR_UARTEN (1 << 0)
+
+#define UART_PL010_LCRH_WLEN_8 (3 << 5)
+#define UART_PL010_LCRH_WLEN_7 (2 << 5)
+#define UART_PL010_LCRH_WLEN_6 (1 << 5)
+#define UART_PL010_LCRH_WLEN_5 (0 << 5)
+#define UART_PL010_LCRH_FEN (1 << 4)
+#define UART_PL010_LCRH_STP2 (1 << 3)
+#define UART_PL010_LCRH_EPS (1 << 2)
+#define UART_PL010_LCRH_PEN (1 << 1)
+#define UART_PL010_LCRH_BRK (1 << 0)
+
+
+#define UART_PL010_BAUD_460800 1
+#define UART_PL010_BAUD_230400 3
+#define UART_PL010_BAUD_115200 7
+#define UART_PL010_BAUD_57600 15
+#define UART_PL010_BAUD_38400 23
+#define UART_PL010_BAUD_19200 47
+#define UART_PL010_BAUD_14400 63
+#define UART_PL010_BAUD_9600 95
+#define UART_PL010_BAUD_4800 191
+#define UART_PL010_BAUD_2400 383
+#define UART_PL010_BAUD_1200 767
+/*
+ * PL011 definitions
+ *
+ */
+#define UART_PL011_IBRD 0x24
+#define UART_PL011_FBRD 0x28
+#define UART_PL011_LCRH 0x2C
+#define UART_PL011_CR 0x30
+#define UART_PL011_IMSC 0x38
+#define UART_PL011_PERIPH_ID0 0xFE0
+
+#define UART_PL011_LCRH_SPS (1 << 7)
+#define UART_PL011_LCRH_WLEN_8 (3 << 5)
+#define UART_PL011_LCRH_WLEN_7 (2 << 5)
+#define UART_PL011_LCRH_WLEN_6 (1 << 5)
+#define UART_PL011_LCRH_WLEN_5 (0 << 5)
+#define UART_PL011_LCRH_FEN (1 << 4)
+#define UART_PL011_LCRH_STP2 (1 << 3)
+#define UART_PL011_LCRH_EPS (1 << 2)
+#define UART_PL011_LCRH_PEN (1 << 1)
+#define UART_PL011_LCRH_BRK (1 << 0)
+
+#define UART_PL011_CR_CTSEN (1 << 15)
+#define UART_PL011_CR_RTSEN (1 << 14)
+#define UART_PL011_CR_OUT2 (1 << 13)
+#define UART_PL011_CR_OUT1 (1 << 12)
+#define UART_PL011_CR_RTS (1 << 11)
+#define UART_PL011_CR_DTR (1 << 10)
+#define UART_PL011_CR_RXE (1 << 9)
+#define UART_PL011_CR_TXE (1 << 8)
+#define UART_PL011_CR_LPE (1 << 7)
+#define UART_PL011_CR_IIRLP (1 << 2)
+#define UART_PL011_CR_SIREN (1 << 1)
+#define UART_PL011_CR_UARTEN (1 << 0)
+
+#define UART_PL011_IMSC_OEIM (1 << 10)
+#define UART_PL011_IMSC_BEIM (1 << 9)
+#define UART_PL011_IMSC_PEIM (1 << 8)
+#define UART_PL011_IMSC_FEIM (1 << 7)
+#define UART_PL011_IMSC_RTIM (1 << 6)
+#define UART_PL011_IMSC_TXIM (1 << 5)
+#define UART_PL011_IMSC_RXIM (1 << 4)
+#define UART_PL011_IMSC_DSRMIM (1 << 3)
+#define UART_PL011_IMSC_DCDMIM (1 << 2)
+#define UART_PL011_IMSC_CTSMIM (1 << 1)
+#define UART_PL011_IMSC_RIMIM (1 << 0)
+
+char pl01x_getc(u64 base, u32 type);
+void pl01x_putc(u64 base, u32 type, char ch);
+void pl01x_init(u64 base, u32 type, u32 baudrate, u32 input_clock);
+
+#endif /* __PL01X_H_ */
diff --git a/tests/arm64/common/basic/serial/virtio_console.c b/tests/arm64/common/basic/serial/virtio_console.c
new file mode 100644
index 0000000..7f964f3
--- /dev/null
+++ b/tests/arm64/common/basic/serial/virtio_console.c
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 2013 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file virtio_console.c
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief Source file for Virtio Console serial port driver.
+ */
+
+#include <arm_io.h>
+#include <serial/virtio_console.h>
+
+void virtio_console_printch(physical_addr_t base, char ch)
+{
+ u32 tmp;
+ struct virtio_console_config *p = (void *)base + VIRTIO_MMIO_CONFIG;
+
+ tmp = arm_readl((void *)(base + VIRTIO_MMIO_DEVICE_ID));
+ if (tmp != VIRTIO_ID_CONSOLE) {
+ return;
+ }
+
+ tmp = arm_readl((void *)(base + VIRTIO_MMIO_HOST_FEATURES));
+ if (!(tmp & (1 << VIRTIO_CONSOLE_F_EMERG_WRITE))) {
+ return;
+ }
+
+ arm_writel(ch, &p->emerg_wr);
+}
+
+char virtio_console_getch(physical_addr_t base)
+{
+ u32 tmp;
+ struct virtio_console_config *p = (void *)base + VIRTIO_MMIO_CONFIG;
+
+ tmp = arm_readl((void *)(base + VIRTIO_MMIO_DEVICE_ID));
+ if (tmp != VIRTIO_ID_CONSOLE) {
+ return 0;
+ }
+
+ tmp = arm_readl((void *)(base + VIRTIO_MMIO_HOST_FEATURES));
+ if (!(tmp & (1 << VIRTIO_CONSOLE_F_EMERG_WRITE))) {
+ return 0;
+ }
+
+ while (!((tmp = arm_readl(&p->emerg_wr)) & (1 << 31))) ;
+
+ return (char)(tmp & 0xFFU);
+}
+
+int virtio_console_init(physical_addr_t base)
+{
+ /* Nothing to do here. */
+ return 0;
+}
+
diff --git a/tests/arm64/common/basic/serial/virtio_console.h b/tests/arm64/common/basic/serial/virtio_console.h
new file mode 100644
index 0000000..9f05992
--- /dev/null
+++ b/tests/arm64/common/basic/serial/virtio_console.h
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2013 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file virtio_console.h
+ * @author Anup Patel (an...@brainfault.org)
+ * @brief Header file for Virtio Console serial port driver.
+ */
+
+#ifndef __VIRTIO_CONSOLE_H_
+#define __VIRTIO_CONSOLE_H_
+
+#include <arm_types.h>
+
+/* VirtIO MMIO */
+#define VIRTIO_MMIO_DEVICE_ID 0x008
+#define VIRTIO_MMIO_HOST_FEATURES 0x010
+#define VIRTIO_MMIO_CONFIG 0x100
+
+/* VirtIO Console */
+#define VIRTIO_ID_CONSOLE 3
+
+/* VirtIO Console Feature bits */
+#define VIRTIO_CONSOLE_F_SIZE 0
+#define VIRTIO_CONSOLE_F_MULTIPORT 1
+#define VIRTIO_CONSOLE_F_EMERG_WRITE 2
+
+struct virtio_console_config {
+ /* colums of the screens */
+ u16 cols;
+ /* rows of the screens */
+ u16 rows;
+ /* max. number of ports this device can hold */
+ u32 max_nr_ports;
+ /* emergency write register */
+ u32 emerg_wr;
+} __attribute__((packed));
+
+void virtio_console_printch(physical_addr_t base, char ch);
+char virtio_console_getch(physical_addr_t base);
+int virtio_console_init(physical_addr_t base);
+
+#endif /* __VIRTIO_CONSOLE_H_ */
diff --git a/tests/arm64/common/basic/timer/generic_timer.c b/tests/arm64/common/basic/timer/generic_timer.c
new file mode 100644
index 0000000..0d4e9af
--- /dev/null
+++ b/tests/arm64/common/basic/timer/generic_timer.c
@@ -0,0 +1,166 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file generic_timer.c
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief ARMv8 Generic Timer driver source
+ *
+ */
+
+#include <arm_irq.h>
+#include <arm_math.h>
+#include <arm_stdio.h>
+#include <arm_inline_asm.h>
+#include <timer/generic_timer.h>
+
+#define GENERIC_TIMER_CTRL_ENABLE (1 << 0)
+#define GENERIC_TIMER_CTRL_IT_MASK (1 << 1)
+#define GENERIC_TIMER_CTRL_IT_STAT (1 << 2)
+
+static u64 timer_irq_count;
+static u64 timer_irq_tcount;
+static u64 timer_irq_delay;
+static u64 timer_irq_tstamp;
+static u64 timer_freq;
+static u64 timer_period_ticks;
+static u64 timer_mult;
+static u32 timer_shift;
+
+void generic_timer_enable(void)
+{
+ unsigned long ctrl;
+
+ ctrl = mrs(cntv_ctl_el0);
+ ctrl |= GENERIC_TIMER_CTRL_ENABLE;
+ ctrl &= ~GENERIC_TIMER_CTRL_IT_MASK;
+ msr(cntv_ctl_el0, ctrl);
+}
+
+void generic_timer_disable(void)
+{
+ unsigned long ctrl;
+
+ ctrl = mrs(cntv_ctl_el0);
+ ctrl &= ~GENERIC_TIMER_CTRL_ENABLE;
+ msr(cntv_ctl_el0, ctrl);
+}
+
+void generic_timer_change_period(u32 usec)
+{
+ timer_period_ticks = ((timer_freq / 1000000) * usec);
+
+ msr(cntv_tval_el0, timer_period_ticks);
+}
+
+u64 generic_timer_irqcount(void)
+{
+ return timer_irq_count;
+}
+
+u64 generic_timer_irqdelay(void)
+{
+ return timer_irq_delay;
+}
+
+u64 generic_timer_timestamp(void)
+{
+ return (mrs(cntvct_el0) * timer_mult) >> timer_shift;
+}
+
+int generic_timer_irqhndl(u32 irq_no, struct pt_regs *regs)
+{
+ unsigned long ctrl;
+ u64 tstamp;
+
+ ctrl = mrs(cntv_ctl_el0);
+ if (ctrl & GENERIC_TIMER_CTRL_IT_STAT) {
+ ctrl |= GENERIC_TIMER_CTRL_IT_MASK;
+ msr(cntv_ctl_el0, ctrl);
+ }
+
+ timer_irq_count++;
+ timer_irq_tcount++;
+
+ tstamp = generic_timer_timestamp();
+ if (!timer_irq_tstamp) {
+ timer_irq_tstamp = tstamp;
+ }
+ if (timer_irq_tcount == 128) {
+ timer_irq_delay = (tstamp - timer_irq_tstamp) >> 7;
+ timer_irq_tcount = 0;
+ timer_irq_tstamp = tstamp;
+ }
+
+ ctrl = mrs(cntv_ctl_el0);
+ ctrl |= GENERIC_TIMER_CTRL_ENABLE;
+ ctrl &= ~GENERIC_TIMER_CTRL_IT_MASK;
+
+ msr(cntv_tval_el0, timer_period_ticks);
+ msr(cntv_ctl_el0, GENERIC_TIMER_CTRL_ENABLE);
+
+ return 0;
+}
+
+static void calc_mult_shift(u64 *mult, u32 *shift,
+ u32 from, u32 to, u32 maxsec)
+{
+ u64 tmp;
+ u32 sft, sftacc= 32;
+
+ /* Calculate the shift factor which is limiting
+ * the conversion range:
+ */
+ tmp = ((u64)maxsec * from) >> 32;
+ while (tmp) {
+ tmp >>=1;
+ sftacc--;
+ }
+
+ /* Find the conversion shift/mult pair which has the best
+ * accuracy and fits the maxsec conversion range:
+ */
+ for (sft = 32; sft > 0; sft--) {
+ tmp = (u64) to << sft;
+ tmp += from / 2;
+ tmp /= from;
+ if ((tmp >> sftacc) == 0)
+ break;
+ }
+ *mult = tmp;
+ *shift = sft;
+}
+
+int generic_timer_init(u32 usecs, u32 irq)
+{
+ timer_freq = mrs(cntfrq_el0);
+ if (timer_freq == 0) {
+ /* Assume 100 Mhz clock if cntfrq_el0 not programmed */
+ timer_freq = 100000000;
+ }
+
+ calc_mult_shift(&timer_mult, &timer_shift, timer_freq, 1000000000, 1);
+
+ timer_period_ticks = ((timer_freq / 1000000) * usecs);
+
+ arm_irq_register(irq, &generic_timer_irqhndl);
+
+ msr(cntv_tval_el0, timer_period_ticks);
+ msr(cntv_ctl_el0, GENERIC_TIMER_CTRL_IT_MASK);
+
+ return 0;
+}
diff --git a/tests/arm64/common/basic/timer/generic_timer.h b/tests/arm64/common/basic/timer/generic_timer.h
new file mode 100644
index 0000000..471048b
--- /dev/null
+++ b/tests/arm64/common/basic/timer/generic_timer.h
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file generic_timer.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief ARMv8 Generic Timer Header
+ */
+#ifndef _ARM_GENERIC_TIMER_H__
+#define _ARM_GENERIC_TIMER_H__
+
+#include <arm_types.h>
+
+void generic_timer_enable(void);
+void generic_timer_disable(void);
+u64 generic_timer_irqcount(void);
+u64 generic_timer_irqdelay(void);
+u64 generic_timer_timestamp(void);
+void generic_timer_change_period(u32 usecs);
+int generic_timer_init(u32 usecs, u32 irq);
+
+#endif
diff --git a/tests/arm64/common/busybox/README b/tests/arm64/common/busybox/README
new file mode 100644
index 0000000..9e72798
--- /dev/null
+++ b/tests/arm64/common/busybox/README
@@ -0,0 +1,38 @@
+ BusyBox RootFS for ARM64 Guest
+
+BusyBox provides several stripped-down Unix tools in a single executable. It
+runs in a variety of POSIX environments such as Linux, Android,[6] FreeBSD[7]
+and others, such as proprietary kernels, although many of the tools it provides
+are designed to work with interfaces provided by the Linux kernel. It was
+created for embedded operating systems with very limited resources. It is
+released under the terms of the GNU General Public License. For more info
+read the BusyBox wiki page http://en.wikipedia.org/wiki/BusyBox
+
+Please follow the steps below to build a RAMDISK using BusyBox, to be used as
+RootFS for ARM64 Linux guest:
+
+ [1. Build environment for Xvisor]
+ # CROSS_COMPILE=aarch64-linux-gnu-
+
+ [2. GoTo Busybox source directory]
+ # cd <busybox_source_directory>
+
+ [3. Copy defconfig to Busybox source directory]
+ # cp <xvisor_source_directory>/tests/arm64/busybox/busybox-<busybox_version>_defconfig .config
+
+ [4. Configure Busybox source]
+ # make oldconfig
+
+ [5. Build Busybox RootFS]
+ # make install
+
+ [6. Change ownership of installed RootFS]
+ # sudo chown -R root:root ./_install
+
+ [7. Create RootFS image]
+ # fakeroot /bin/bash -c "genext2fs -b 5120 -N 1024 -D <xvisor_source_directory>/tests/arm64/common/busybox/busybox_dev.txt -d ./_install <busybox_rootfs_directory>/rootfs64.img"
+
+ (Note: <busybox_rootfs_directory>/rootfs64.img is our final RAMDISK)
+ (Note: replace all <> brackets based on your workspace)
+ (Note: you are free to the change ordering of above steps based on your workspace)
+
diff --git a/tests/arm64/common/busybox/busybox-1.21.0_defconfig b/tests/arm64/common/busybox/busybox-1.21.0_defconfig
new file mode 100644
index 0000000..9aacf0c
--- /dev/null
+++ b/tests/arm64/common/busybox/busybox-1.21.0_defconfig
@@ -0,0 +1,1034 @@
+#
+# Automatically generated make config: don't edit
+# Busybox version: 1.21.0
+# Sun Sep 1 20:28:08 2013
+#
+CONFIG_HAVE_DOT_CONFIG=y
+
+#
+# Busybox Settings
+#
+
+#
+# General Configuration
+#
+# CONFIG_DESKTOP is not set
+CONFIG_EXTRA_COMPAT=y
+CONFIG_INCLUDE_SUSv2=y
+# CONFIG_USE_PORTABLE_CODE is not set
+CONFIG_PLATFORM_LINUX=y
+CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
+# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
+# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
+CONFIG_SHOW_USAGE=y
+CONFIG_FEATURE_VERBOSE_USAGE=y
+CONFIG_FEATURE_COMPRESS_USAGE=y
+CONFIG_FEATURE_INSTALLER=y
+# CONFIG_INSTALL_NO_USR is not set
+# CONFIG_LOCALE_SUPPORT is not set
+# CONFIG_UNICODE_SUPPORT is not set
+# CONFIG_UNICODE_USING_LOCALE is not set
+# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set
+CONFIG_SUBST_WCHAR=0
+CONFIG_LAST_SUPPORTED_WCHAR=0
+# CONFIG_UNICODE_COMBINING_WCHARS is not set
+# CONFIG_UNICODE_WIDE_WCHARS is not set
+# CONFIG_UNICODE_BIDI_SUPPORT is not set
+# CONFIG_UNICODE_NEUTRAL_TABLE is not set
+# CONFIG_UNICODE_PRESERVE_BROKEN is not set
+CONFIG_LONG_OPTS=y
+CONFIG_FEATURE_DEVPTS=y
+# CONFIG_FEATURE_CLEAN_UP is not set
+CONFIG_FEATURE_UTMP=y
+CONFIG_FEATURE_WTMP=y
+# CONFIG_FEATURE_PIDFILE is not set
+CONFIG_PID_FILE_PATH=""
+CONFIG_FEATURE_SUID=y
+CONFIG_FEATURE_SUID_CONFIG=y
+CONFIG_FEATURE_SUID_CONFIG_QUIET=y
+# CONFIG_SELINUX is not set
+CONFIG_FEATURE_PREFER_APPLETS=y
+CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe"
+CONFIG_FEATURE_SYSLOG=y
+# CONFIG_FEATURE_HAVE_RPC is not set
+
+#
+# Build Options
+#
+CONFIG_STATIC=y
+# CONFIG_PIE is not set
+# CONFIG_NOMMU is not set
+# CONFIG_BUILD_LIBBUSYBOX is not set
+# CONFIG_FEATURE_INDIVIDUAL is not set
+# CONFIG_FEATURE_SHARED_BUSYBOX is not set
+CONFIG_LFS=y
+CONFIG_CROSS_COMPILER_PREFIX="aarch64-linux-gnu-"
+CONFIG_SYSROOT=""
+CONFIG_EXTRA_CFLAGS="-mlittle-endian"
+CONFIG_EXTRA_LDFLAGS=""
+CONFIG_EXTRA_LDLIBS=""
+
+#
+# Debugging Options
+#
+# CONFIG_DEBUG is not set
+# CONFIG_DEBUG_PESSIMIZE is not set
+# CONFIG_WERROR is not set
+CONFIG_NO_DEBUG_LIB=y
+# CONFIG_DMALLOC is not set
+# CONFIG_EFENCE is not set
+
+#
+# Installation Options ("make install" behavior)
+#
+CONFIG_INSTALL_APPLET_SYMLINKS=y
+# CONFIG_INSTALL_APPLET_HARDLINKS is not set
+# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set
+# CONFIG_INSTALL_APPLET_DONT is not set
+# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set
+# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set
+# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set
+CONFIG_PREFIX="./_install"
+
+#
+# Busybox Library Tuning
+#
+CONFIG_FEATURE_SYSTEMD=y
+CONFIG_FEATURE_RTMINMAX=y
+CONFIG_PASSWORD_MINLEN=6
+CONFIG_MD5_SMALL=1
+CONFIG_SHA3_SMALL=1
+CONFIG_FEATURE_FAST_TOP=y
+CONFIG_FEATURE_ETC_NETWORKS=y
+CONFIG_FEATURE_USE_TERMIOS=y
+CONFIG_FEATURE_EDITING=y
+CONFIG_FEATURE_EDITING_MAX_LEN=1024
+CONFIG_FEATURE_EDITING_VI=y
+CONFIG_FEATURE_EDITING_HISTORY=15
+# CONFIG_FEATURE_EDITING_SAVEHISTORY is not set
+# CONFIG_FEATURE_EDITING_SAVE_ON_EXIT is not set
+# CONFIG_FEATURE_REVERSE_SEARCH is not set
+CONFIG_FEATURE_TAB_COMPLETION=y
+CONFIG_FEATURE_USERNAME_COMPLETION=y
+CONFIG_FEATURE_EDITING_FANCY_PROMPT=y
+CONFIG_FEATURE_EDITING_ASK_TERMINAL=y
+CONFIG_FEATURE_NON_POSIX_CP=y
+CONFIG_FEATURE_VERBOSE_CP_MESSAGE=y
+CONFIG_FEATURE_COPYBUF_KB=4
+CONFIG_FEATURE_SKIP_ROOTFS=y
+CONFIG_MONOTONIC_SYSCALL=y
+CONFIG_IOCTL_HEX2STR_ERROR=y
+CONFIG_FEATURE_HWIB=y
+
+#
+# Applets
+#
+
+#
+# Archival Utilities
+#
+# CONFIG_FEATURE_SEAMLESS_XZ is not set
+# CONFIG_FEATURE_SEAMLESS_LZMA is not set
+# CONFIG_FEATURE_SEAMLESS_BZ2 is not set
+# CONFIG_FEATURE_SEAMLESS_GZ is not set
+# CONFIG_FEATURE_SEAMLESS_Z is not set
+# CONFIG_AR is not set
+# CONFIG_FEATURE_AR_LONG_FILENAMES is not set
+# CONFIG_FEATURE_AR_CREATE is not set
+# CONFIG_BUNZIP2 is not set
+# CONFIG_BZIP2 is not set
+# CONFIG_CPIO is not set
+# CONFIG_FEATURE_CPIO_O is not set
+# CONFIG_FEATURE_CPIO_P is not set
+# CONFIG_DPKG is not set
+# CONFIG_DPKG_DEB is not set
+# CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set
+# CONFIG_GUNZIP is not set
+# CONFIG_GZIP is not set
+# CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set
+CONFIG_GZIP_FAST=0
+# CONFIG_LZOP is not set
+# CONFIG_LZOP_COMPR_HIGH is not set
+# CONFIG_RPM2CPIO is not set
+# CONFIG_RPM is not set
+# CONFIG_TAR is not set
+# CONFIG_FEATURE_TAR_CREATE is not set
+# CONFIG_FEATURE_TAR_AUTODETECT is not set
+# CONFIG_FEATURE_TAR_FROM is not set
+# CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set
+# CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set
+# CONFIG_FEATURE_TAR_GNU_EXTENSIONS is not set
+# CONFIG_FEATURE_TAR_LONG_OPTIONS is not set
+# CONFIG_FEATURE_TAR_TO_COMMAND is not set
+# CONFIG_FEATURE_TAR_UNAME_GNAME is not set
+# CONFIG_FEATURE_TAR_NOPRESERVE_TIME is not set
+# CONFIG_FEATURE_TAR_SELINUX is not set
+# CONFIG_UNCOMPRESS is not set
+# CONFIG_UNLZMA is not set
+# CONFIG_FEATURE_LZMA_FAST is not set
+# CONFIG_LZMA is not set
+# CONFIG_UNXZ is not set
+# CONFIG_XZ is not set
+# CONFIG_UNZIP is not set
+
+#
+# Coreutils
+#
+CONFIG_BASENAME=y
+CONFIG_CAT=y
+CONFIG_DATE=y
+CONFIG_FEATURE_DATE_ISOFMT=y
+# CONFIG_FEATURE_DATE_NANO is not set
+CONFIG_FEATURE_DATE_COMPAT=y
+CONFIG_HOSTID=y
+CONFIG_ID=y
+CONFIG_GROUPS=y
+CONFIG_TEST=y
+CONFIG_FEATURE_TEST_64=y
+CONFIG_TOUCH=y
+CONFIG_FEATURE_TOUCH_SUSV3=y
+CONFIG_TR=y
+CONFIG_FEATURE_TR_CLASSES=y
+CONFIG_FEATURE_TR_EQUIV=y
+CONFIG_BASE64=y
+CONFIG_WHO=y
+CONFIG_USERS=y
+CONFIG_CAL=y
+CONFIG_CATV=y
+CONFIG_CHGRP=y
+CONFIG_CHMOD=y
+CONFIG_CHOWN=y
+CONFIG_FEATURE_CHOWN_LONG_OPTIONS=y
+CONFIG_CHROOT=y
+CONFIG_CKSUM=y
+CONFIG_COMM=y
+CONFIG_CP=y
+CONFIG_FEATURE_CP_LONG_OPTIONS=y
+CONFIG_CUT=y
+CONFIG_DD=y
+CONFIG_FEATURE_DD_SIGNAL_HANDLING=y
+CONFIG_FEATURE_DD_THIRD_STATUS_LINE=y
+CONFIG_FEATURE_DD_IBS_OBS=y
+CONFIG_DF=y
+CONFIG_FEATURE_DF_FANCY=y
+CONFIG_DIRNAME=y
+CONFIG_DOS2UNIX=y
+CONFIG_UNIX2DOS=y
+CONFIG_DU=y
+CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y
+CONFIG_ECHO=y
+CONFIG_FEATURE_FANCY_ECHO=y
+CONFIG_ENV=y
+CONFIG_FEATURE_ENV_LONG_OPTIONS=y
+CONFIG_EXPAND=y
+CONFIG_FEATURE_EXPAND_LONG_OPTIONS=y
+CONFIG_EXPR=y
+CONFIG_EXPR_MATH_SUPPORT_64=y
+CONFIG_FALSE=y
+CONFIG_FOLD=y
+CONFIG_FSYNC=y
+CONFIG_HEAD=y
+CONFIG_FEATURE_FANCY_HEAD=y
+CONFIG_INSTALL=y
+CONFIG_FEATURE_INSTALL_LONG_OPTIONS=y
+CONFIG_LN=y
+CONFIG_LOGNAME=y
+CONFIG_LS=y
+CONFIG_FEATURE_LS_FILETYPES=y
+CONFIG_FEATURE_LS_FOLLOWLINKS=y
+CONFIG_FEATURE_LS_RECURSIVE=y
+CONFIG_FEATURE_LS_SORTFILES=y
+CONFIG_FEATURE_LS_TIMESTAMPS=y
+CONFIG_FEATURE_LS_USERNAME=y
+CONFIG_FEATURE_LS_COLOR=y
+CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y
+CONFIG_MD5SUM=y
+CONFIG_MKDIR=y
+CONFIG_FEATURE_MKDIR_LONG_OPTIONS=y
+CONFIG_MKFIFO=y
+CONFIG_MKNOD=y
+CONFIG_MV=y
+CONFIG_FEATURE_MV_LONG_OPTIONS=y
+CONFIG_NICE=y
+CONFIG_NOHUP=y
+CONFIG_OD=y
+CONFIG_PRINTENV=y
+CONFIG_PRINTF=y
+CONFIG_PWD=y
+CONFIG_READLINK=y
+CONFIG_FEATURE_READLINK_FOLLOW=y
+CONFIG_REALPATH=y
+CONFIG_RM=y
+CONFIG_RMDIR=y
+CONFIG_FEATURE_RMDIR_LONG_OPTIONS=y
+CONFIG_SEQ=y
+CONFIG_SHA1SUM=y
+CONFIG_SHA256SUM=y
+CONFIG_SHA512SUM=y
+CONFIG_SHA3SUM=y
+CONFIG_SLEEP=y
+CONFIG_FEATURE_FANCY_SLEEP=y
+CONFIG_FEATURE_FLOAT_SLEEP=y
+CONFIG_SORT=y
+CONFIG_FEATURE_SORT_BIG=y
+CONFIG_SPLIT=y
+CONFIG_FEATURE_SPLIT_FANCY=y
+CONFIG_STAT=y
+CONFIG_FEATURE_STAT_FORMAT=y
+CONFIG_STTY=y
+CONFIG_SUM=y
+CONFIG_SYNC=y
+CONFIG_TAC=y
+CONFIG_TAIL=y
+CONFIG_FEATURE_FANCY_TAIL=y
+CONFIG_TEE=y
+CONFIG_FEATURE_TEE_USE_BLOCK_IO=y
+CONFIG_TRUE=y
+CONFIG_TTY=y
+CONFIG_UNAME=y
+CONFIG_UNEXPAND=y
+CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS=y
+CONFIG_UNIQ=y
+CONFIG_USLEEP=y
+CONFIG_UUDECODE=y
+CONFIG_UUENCODE=y
+CONFIG_WC=y
+CONFIG_FEATURE_WC_LARGE=y
+CONFIG_WHOAMI=y
+CONFIG_YES=y
+
+#
+# Common options for cp and mv
+#
+CONFIG_FEATURE_PRESERVE_HARDLINKS=y
+
+#
+# Common options for ls, more and telnet
+#
+CONFIG_FEATURE_AUTOWIDTH=y
+
+#
+# Common options for df, du, ls
+#
+CONFIG_FEATURE_HUMAN_READABLE=y
+
+#
+# Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum
+#
+CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y
+
+#
+# Console Utilities
+#
+CONFIG_CHVT=y
+CONFIG_FGCONSOLE=y
+CONFIG_CLEAR=y
+CONFIG_DEALLOCVT=y
+CONFIG_DUMPKMAP=y
+CONFIG_KBD_MODE=y
+CONFIG_LOADFONT=y
+CONFIG_LOADKMAP=y
+CONFIG_OPENVT=y
+CONFIG_RESET=y
+CONFIG_RESIZE=y
+CONFIG_FEATURE_RESIZE_PRINT=y
+CONFIG_SETCONSOLE=y
+CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS=y
+CONFIG_SETFONT=y
+CONFIG_FEATURE_SETFONT_TEXTUAL_MAP=y
+CONFIG_DEFAULT_SETFONT_DIR=""
+CONFIG_SETKEYCODES=y
+CONFIG_SETLOGCONS=y
+CONFIG_SHOWKEY=y
+
+#
+# Common options for loadfont and setfont
+#
+CONFIG_FEATURE_LOADFONT_PSF2=y
+CONFIG_FEATURE_LOADFONT_RAW=y
+
+#
+# Debian Utilities
+#
+# CONFIG_MKTEMP is not set
+# CONFIG_PIPE_PROGRESS is not set
+# CONFIG_RUN_PARTS is not set
+# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set
+# CONFIG_FEATURE_RUN_PARTS_FANCY is not set
+# CONFIG_START_STOP_DAEMON is not set
+# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set
+# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set
+CONFIG_WHICH=y
+
+#
+# Editors
+#
+CONFIG_PATCH=y
+CONFIG_VI=y
+CONFIG_FEATURE_VI_MAX_LEN=4096
+CONFIG_FEATURE_VI_8BIT=y
+CONFIG_FEATURE_VI_COLON=y
+CONFIG_FEATURE_VI_YANKMARK=y
+CONFIG_FEATURE_VI_SEARCH=y
+# CONFIG_FEATURE_VI_REGEX_SEARCH is not set
+CONFIG_FEATURE_VI_USE_SIGNALS=y
+CONFIG_FEATURE_VI_DOT_CMD=y
+CONFIG_FEATURE_VI_READONLY=y
+CONFIG_FEATURE_VI_SETOPTS=y
+CONFIG_FEATURE_VI_SET=y
+CONFIG_FEATURE_VI_WIN_RESIZE=y
+CONFIG_FEATURE_VI_ASK_TERMINAL=y
+CONFIG_AWK=y
+CONFIG_FEATURE_AWK_LIBM=y
+CONFIG_CMP=y
+CONFIG_DIFF=y
+CONFIG_FEATURE_DIFF_LONG_OPTIONS=y
+CONFIG_FEATURE_DIFF_DIR=y
+CONFIG_ED=y
+CONFIG_SED=y
+CONFIG_FEATURE_ALLOW_EXEC=y
+
+#
+# Finding Utilities
+#
+CONFIG_FIND=y
+CONFIG_FEATURE_FIND_PRINT0=y
+CONFIG_FEATURE_FIND_MTIME=y
+CONFIG_FEATURE_FIND_MMIN=y
+CONFIG_FEATURE_FIND_PERM=y
+CONFIG_FEATURE_FIND_TYPE=y
+CONFIG_FEATURE_FIND_XDEV=y
+CONFIG_FEATURE_FIND_MAXDEPTH=y
+CONFIG_FEATURE_FIND_NEWER=y
+CONFIG_FEATURE_FIND_INUM=y
+CONFIG_FEATURE_FIND_EXEC=y
+CONFIG_FEATURE_FIND_USER=y
+CONFIG_FEATURE_FIND_GROUP=y
+CONFIG_FEATURE_FIND_NOT=y
+CONFIG_FEATURE_FIND_DEPTH=y
+CONFIG_FEATURE_FIND_PAREN=y
+CONFIG_FEATURE_FIND_SIZE=y
+CONFIG_FEATURE_FIND_PRUNE=y
+CONFIG_FEATURE_FIND_DELETE=y
+CONFIG_FEATURE_FIND_PATH=y
+CONFIG_FEATURE_FIND_REGEX=y
+# CONFIG_FEATURE_FIND_CONTEXT is not set
+CONFIG_FEATURE_FIND_LINKS=y
+CONFIG_GREP=y
+CONFIG_FEATURE_GREP_EGREP_ALIAS=y
+CONFIG_FEATURE_GREP_FGREP_ALIAS=y
+CONFIG_FEATURE_GREP_CONTEXT=y
+CONFIG_XARGS=y
+CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y
+CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y
+CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y
+CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y
+
+#
+# Init Utilities
+#
+CONFIG_BOOTCHARTD=y
+CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER=y
+CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE=y
+CONFIG_HALT=y
+# CONFIG_FEATURE_CALL_TELINIT is not set
+CONFIG_TELINIT_PATH=""
+CONFIG_INIT=y
+CONFIG_FEATURE_USE_INITTAB=y
+CONFIG_FEATURE_KILL_REMOVED=y
+CONFIG_FEATURE_KILL_DELAY=1
+CONFIG_FEATURE_INIT_SCTTY=y
+CONFIG_FEATURE_INIT_SYSLOG=y
+CONFIG_FEATURE_EXTRA_QUIET=y
+CONFIG_FEATURE_INIT_COREDUMPS=y
+CONFIG_FEATURE_INITRD=y
+CONFIG_INIT_TERMINAL_TYPE="linux"
+CONFIG_MESG=y
+CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y
+
+#
+# Login/Password Management Utilities
+#
+CONFIG_ADD_SHELL=y
+CONFIG_REMOVE_SHELL=y
+CONFIG_FEATURE_SHADOWPASSWDS=y
+CONFIG_USE_BB_PWD_GRP=y
+CONFIG_USE_BB_SHADOW=y
+CONFIG_USE_BB_CRYPT=y
+CONFIG_USE_BB_CRYPT_SHA=y
+CONFIG_ADDUSER=y
+CONFIG_FEATURE_ADDUSER_LONG_OPTIONS=y
+CONFIG_FEATURE_CHECK_NAMES=y
+CONFIG_FIRST_SYSTEM_ID=100
+CONFIG_LAST_SYSTEM_ID=999
+CONFIG_ADDGROUP=y
+CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS=y
+CONFIG_FEATURE_ADDUSER_TO_GROUP=y
+CONFIG_DELUSER=y
+CONFIG_DELGROUP=y
+CONFIG_FEATURE_DEL_USER_FROM_GROUP=y
+CONFIG_GETTY=y
+CONFIG_LOGIN=y
+# CONFIG_LOGIN_SESSION_AS_CHILD is not set
+# CONFIG_PAM is not set
+CONFIG_LOGIN_SCRIPTS=y
+CONFIG_FEATURE_NOLOGIN=y
+CONFIG_FEATURE_SECURETTY=y
+CONFIG_PASSWD=y
+CONFIG_FEATURE_PASSWD_WEAK_CHECK=y
+CONFIG_CRYPTPW=y
+CONFIG_CHPASSWD=y
+CONFIG_FEATURE_DEFAULT_PASSWD_ALGO="des"
+CONFIG_SU=y
+CONFIG_FEATURE_SU_SYSLOG=y
+CONFIG_FEATURE_SU_CHECKS_SHELLS=y
+CONFIG_SULOGIN=y
+CONFIG_VLOCK=y
+
+#
+# Linux Ext2 FS Progs
+#
+CONFIG_CHATTR=y
+CONFIG_FSCK=y
+CONFIG_LSATTR=y
+# CONFIG_TUNE2FS is not set
+
+#
+# Linux Module Utilities
+#
+CONFIG_MODINFO=y
+CONFIG_MODPROBE_SMALL=y
+CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE=y
+CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y
+# CONFIG_INSMOD is not set
+# CONFIG_RMMOD is not set
+# CONFIG_LSMOD is not set
+# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set
+# CONFIG_MODPROBE is not set
+# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set
+# CONFIG_DEPMOD is not set
+
+#
+# Options common to multiple modutils
+#
+# CONFIG_FEATURE_2_4_MODULES is not set
+CONFIG_FEATURE_INSMOD_TRY_MMAP=y
+# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
+# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
+# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
+# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
+# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
+# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set
+# CONFIG_FEATURE_MODUTILS_ALIAS is not set
+# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set
+CONFIG_DEFAULT_MODULES_DIR="/lib/modules"
+CONFIG_DEFAULT_DEPMOD_FILE="modules.dep"
+
+#
+# Linux System Utilities
+#
+# CONFIG_BLOCKDEV is not set
+# CONFIG_MDEV is not set
+# CONFIG_FEATURE_MDEV_CONF is not set
+# CONFIG_FEATURE_MDEV_RENAME is not set
+# CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set
+# CONFIG_FEATURE_MDEV_EXEC is not set
+# CONFIG_FEATURE_MDEV_LOAD_FIRMWARE is not set
+# CONFIG_REV is not set
+# CONFIG_ACPID is not set
+# CONFIG_FEATURE_ACPID_COMPAT is not set
+# CONFIG_BLKID is not set
+# CONFIG_FEATURE_BLKID_TYPE is not set
+CONFIG_DMESG=y
+CONFIG_FEATURE_DMESG_PRETTY=y
+# CONFIG_FBSET is not set
+# CONFIG_FEATURE_FBSET_FANCY is not set
+# CONFIG_FEATURE_FBSET_READMODE is not set
+# CONFIG_FDFLUSH is not set
+# CONFIG_FDFORMAT is not set
+# CONFIG_FDISK is not set
+# CONFIG_FDISK_SUPPORT_LARGE_DISKS is not set
+# CONFIG_FEATURE_FDISK_WRITABLE is not set
+# CONFIG_FEATURE_AIX_LABEL is not set
+# CONFIG_FEATURE_SGI_LABEL is not set
+# CONFIG_FEATURE_SUN_LABEL is not set
+# CONFIG_FEATURE_OSF_LABEL is not set
+# CONFIG_FEATURE_GPT_LABEL is not set
+# CONFIG_FEATURE_FDISK_ADVANCED is not set
+# CONFIG_FINDFS is not set
+# CONFIG_FLOCK is not set
+# CONFIG_FREERAMDISK is not set
+# CONFIG_FSCK_MINIX is not set
+CONFIG_MKFS_EXT2=y
+# CONFIG_MKFS_MINIX is not set
+# CONFIG_FEATURE_MINIX2 is not set
+# CONFIG_MKFS_REISER is not set
+# CONFIG_MKFS_VFAT is not set
+# CONFIG_GETOPT is not set
+# CONFIG_FEATURE_GETOPT_LONG is not set
+CONFIG_HEXDUMP=y
+CONFIG_FEATURE_HEXDUMP_REVERSE=y
+CONFIG_HD=y
+# CONFIG_HWCLOCK is not set
+# CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS is not set
+# CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set
+# CONFIG_IPCRM is not set
+# CONFIG_IPCS is not set
+# CONFIG_LOSETUP is not set
+# CONFIG_LSPCI is not set
+# CONFIG_LSUSB is not set
+# CONFIG_MKSWAP is not set
+# CONFIG_FEATURE_MKSWAP_UUID is not set
+# CONFIG_MORE is not set
+CONFIG_MOUNT=y
+CONFIG_FEATURE_MOUNT_FAKE=y
+CONFIG_FEATURE_MOUNT_VERBOSE=y
+# CONFIG_FEATURE_MOUNT_HELPERS is not set
+CONFIG_FEATURE_MOUNT_LABEL=y
+# CONFIG_FEATURE_MOUNT_NFS is not set
+CONFIG_FEATURE_MOUNT_CIFS=y
+CONFIG_FEATURE_MOUNT_FLAGS=y
+CONFIG_FEATURE_MOUNT_FSTAB=y
+# CONFIG_PIVOT_ROOT is not set
+# CONFIG_RDATE is not set
+# CONFIG_RDEV is not set
+# CONFIG_READPROFILE is not set
+# CONFIG_RTCWAKE is not set
+# CONFIG_SCRIPT is not set
+# CONFIG_SCRIPTREPLAY is not set
+# CONFIG_SETARCH is not set
+# CONFIG_SWAPONOFF is not set
+# CONFIG_FEATURE_SWAPON_PRI is not set
+CONFIG_SWITCH_ROOT=y
+CONFIG_UMOUNT=y
+CONFIG_FEATURE_UMOUNT_ALL=y
+
+#
+# Common options for mount/umount
+#
+CONFIG_FEATURE_MOUNT_LOOP=y
+CONFIG_FEATURE_MOUNT_LOOP_CREATE=y
+# CONFIG_FEATURE_MTAB_SUPPORT is not set
+CONFIG_VOLUMEID=y
+
+#
+# Filesystem/Volume identification
+#
+CONFIG_FEATURE_VOLUMEID_EXT=y
+CONFIG_FEATURE_VOLUMEID_BTRFS=y
+CONFIG_FEATURE_VOLUMEID_REISERFS=y
+CONFIG_FEATURE_VOLUMEID_FAT=y
+CONFIG_FEATURE_VOLUMEID_EXFAT=y
+CONFIG_FEATURE_VOLUMEID_HFS=y
+CONFIG_FEATURE_VOLUMEID_JFS=y
+CONFIG_FEATURE_VOLUMEID_XFS=y
+CONFIG_FEATURE_VOLUMEID_NILFS=y
+CONFIG_FEATURE_VOLUMEID_NTFS=y
+CONFIG_FEATURE_VOLUMEID_ISO9660=y
+CONFIG_FEATURE_VOLUMEID_UDF=y
+CONFIG_FEATURE_VOLUMEID_LUKS=y
+CONFIG_FEATURE_VOLUMEID_LINUXSWAP=y
+CONFIG_FEATURE_VOLUMEID_CRAMFS=y
+CONFIG_FEATURE_VOLUMEID_ROMFS=y
+# CONFIG_FEATURE_VOLUMEID_SQUASHFS is not set
+CONFIG_FEATURE_VOLUMEID_SYSV=y
+CONFIG_FEATURE_VOLUMEID_OCFS2=y
+CONFIG_FEATURE_VOLUMEID_LINUXRAID=y
+
+#
+# Miscellaneous Utilities
+#
+# CONFIG_CONSPY is not set
+CONFIG_LESS=y
+CONFIG_FEATURE_LESS_MAXLINES=9999999
+CONFIG_FEATURE_LESS_BRACKETS=y
+CONFIG_FEATURE_LESS_FLAGS=y
+CONFIG_FEATURE_LESS_MARKS=y
+CONFIG_FEATURE_LESS_REGEXP=y
+CONFIG_FEATURE_LESS_WINCH=y
+CONFIG_FEATURE_LESS_ASK_TERMINAL=y
+CONFIG_FEATURE_LESS_DASHCMD=y
+CONFIG_FEATURE_LESS_LINENUMS=y
+# CONFIG_NANDWRITE is not set
+# CONFIG_NANDDUMP is not set
+CONFIG_SETSERIAL=y
+# CONFIG_UBIATTACH is not set
+# CONFIG_UBIDETACH is not set
+# CONFIG_UBIMKVOL is not set
+# CONFIG_UBIRMVOL is not set
+# CONFIG_UBIRSVOL is not set
+# CONFIG_UBIUPDATEVOL is not set
+# CONFIG_ADJTIMEX is not set
+# CONFIG_BBCONFIG is not set
+# CONFIG_FEATURE_COMPRESS_BBCONFIG is not set
+# CONFIG_BEEP is not set
+CONFIG_FEATURE_BEEP_FREQ=0
+CONFIG_FEATURE_BEEP_LENGTH_MS=0
+# CONFIG_CHAT is not set
+# CONFIG_FEATURE_CHAT_NOFAIL is not set
+# CONFIG_FEATURE_CHAT_TTY_HIFI is not set
+# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set
+# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set
+# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set
+# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set
+# CONFIG_FEATURE_CHAT_CLR_ABORT is not set
+# CONFIG_CHRT is not set
+# CONFIG_CROND is not set
+# CONFIG_FEATURE_CROND_D is not set
+# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set
+CONFIG_FEATURE_CROND_DIR=""
+# CONFIG_CRONTAB is not set
+# CONFIG_DC is not set
+# CONFIG_FEATURE_DC_LIBM is not set
+# CONFIG_DEVFSD is not set
+# CONFIG_DEVFSD_MODLOAD is not set
+# CONFIG_DEVFSD_FG_NP is not set
+# CONFIG_DEVFSD_VERBOSE is not set
+# CONFIG_FEATURE_DEVFS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_EJECT is not set
+# CONFIG_FEATURE_EJECT_SCSI is not set
+# CONFIG_FBSPLASH is not set
+# CONFIG_FLASHCP is not set
+# CONFIG_FLASH_LOCK is not set
+# CONFIG_FLASH_UNLOCK is not set
+# CONFIG_FLASH_ERASEALL is not set
+# CONFIG_IONICE is not set
+# CONFIG_INOTIFYD is not set
+# CONFIG_LAST is not set
+# CONFIG_FEATURE_LAST_SMALL is not set
+# CONFIG_FEATURE_LAST_FANCY is not set
+# CONFIG_HDPARM is not set
+# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set
+# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set
+# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set
+CONFIG_MAKEDEVS=y
+# CONFIG_FEATURE_MAKEDEVS_LEAF is not set
+CONFIG_FEATURE_MAKEDEVS_TABLE=y
+# CONFIG_MAN is not set
+# CONFIG_MICROCOM is not set
+# CONFIG_MOUNTPOINT is not set
+# CONFIG_MT is not set
+# CONFIG_RAIDAUTORUN is not set
+# CONFIG_READAHEAD is not set
+# CONFIG_RFKILL is not set
+# CONFIG_RUNLEVEL is not set
+# CONFIG_RX is not set
+# CONFIG_SETSID is not set
+# CONFIG_STRINGS is not set
+# CONFIG_TASKSET is not set
+# CONFIG_FEATURE_TASKSET_FANCY is not set
+CONFIG_TIME=y
+# CONFIG_TIMEOUT is not set
+# CONFIG_TTYSIZE is not set
+# CONFIG_VOLNAME is not set
+# CONFIG_WALL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Networking Utilities
+#
+# CONFIG_NAMEIF is not set
+# CONFIG_FEATURE_NAMEIF_EXTENDED is not set
+# CONFIG_NBDCLIENT is not set
+# CONFIG_NC is not set
+# CONFIG_NC_SERVER is not set
+# CONFIG_NC_EXTRA is not set
+# CONFIG_NC_110_COMPAT is not set
+CONFIG_PING=y
+# CONFIG_PING6 is not set
+CONFIG_FEATURE_FANCY_PING=y
+# CONFIG_WHOIS is not set
+# CONFIG_FEATURE_IPV6 is not set
+# CONFIG_FEATURE_UNIX_LOCAL is not set
+# CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set
+# CONFIG_VERBOSE_RESOLUTION_ERRORS is not set
+CONFIG_ARP=y
+CONFIG_ARPING=y
+# CONFIG_BRCTL is not set
+# CONFIG_FEATURE_BRCTL_FANCY is not set
+# CONFIG_FEATURE_BRCTL_SHOW is not set
+# CONFIG_DNSD is not set
+# CONFIG_ETHER_WAKE is not set
+# CONFIG_FAKEIDENTD is not set
+# CONFIG_FTPD is not set
+# CONFIG_FEATURE_FTP_WRITE is not set
+# CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set
+# CONFIG_FTPGET is not set
+# CONFIG_FTPPUT is not set
+# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set
+CONFIG_HOSTNAME=y
+# CONFIG_HTTPD is not set
+# CONFIG_FEATURE_HTTPD_RANGES is not set
+# CONFIG_FEATURE_HTTPD_USE_SENDFILE is not set
+# CONFIG_FEATURE_HTTPD_SETUID is not set
+# CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set
+# CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set
+# CONFIG_FEATURE_HTTPD_CGI is not set
+# CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set
+# CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set
+# CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set
+# CONFIG_FEATURE_HTTPD_ERROR_PAGES is not set
+# CONFIG_FEATURE_HTTPD_PROXY is not set
+# CONFIG_FEATURE_HTTPD_GZIP is not set
+CONFIG_IFCONFIG=y
+CONFIG_FEATURE_IFCONFIG_STATUS=y
+CONFIG_FEATURE_IFCONFIG_SLIP=y
+CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ=y
+CONFIG_FEATURE_IFCONFIG_HW=y
+CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS=y
+# CONFIG_IFENSLAVE is not set
+# CONFIG_IFPLUGD is not set
+# CONFIG_IFUPDOWN is not set
+CONFIG_IFUPDOWN_IFSTATE_PATH=""
+# CONFIG_FEATURE_IFUPDOWN_IP is not set
+# CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN is not set
+# CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN is not set
+# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set
+# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set
+# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set
+# CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set
+# CONFIG_INETD is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set
+# CONFIG_FEATURE_INETD_RPC is not set
+CONFIG_IP=y
+CONFIG_FEATURE_IP_ADDRESS=y
+CONFIG_FEATURE_IP_LINK=y
+CONFIG_FEATURE_IP_ROUTE=y
+CONFIG_FEATURE_IP_TUNNEL=y
+CONFIG_FEATURE_IP_RULE=y
+CONFIG_FEATURE_IP_SHORT_FORMS=y
+# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set
+CONFIG_IPADDR=y
+CONFIG_IPLINK=y
+CONFIG_IPROUTE=y
+CONFIG_IPTUNNEL=y
+CONFIG_IPRULE=y
+# CONFIG_IPCALC is not set
+# CONFIG_FEATURE_IPCALC_FANCY is not set
+# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set
+# CONFIG_NETSTAT is not set
+# CONFIG_FEATURE_NETSTAT_WIDE is not set
+# CONFIG_FEATURE_NETSTAT_PRG is not set
+CONFIG_NSLOOKUP=y
+# CONFIG_NTPD is not set
+# CONFIG_FEATURE_NTPD_SERVER is not set
+# CONFIG_PSCAN is not set
+CONFIG_ROUTE=y
+# CONFIG_SLATTACH is not set
+# CONFIG_TCPSVD is not set
+CONFIG_TELNET=y
+CONFIG_FEATURE_TELNET_TTYPE=y
+CONFIG_FEATURE_TELNET_AUTOLOGIN=y
+CONFIG_TELNETD=y
+CONFIG_FEATURE_TELNETD_STANDALONE=y
+CONFIG_FEATURE_TELNETD_INETD_WAIT=y
+CONFIG_TFTP=y
+# CONFIG_TFTPD is not set
+
+#
+# Common options for tftp/tftpd
+#
+CONFIG_FEATURE_TFTP_GET=y
+CONFIG_FEATURE_TFTP_PUT=y
+CONFIG_FEATURE_TFTP_BLOCKSIZE=y
+CONFIG_FEATURE_TFTP_PROGRESS_BAR=y
+# CONFIG_TFTP_DEBUG is not set
+# CONFIG_TRACEROUTE is not set
+# CONFIG_TRACEROUTE6 is not set
+# CONFIG_FEATURE_TRACEROUTE_VERBOSE is not set
+# CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE is not set
+# CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set
+# CONFIG_TUNCTL is not set
+# CONFIG_FEATURE_TUNCTL_UG is not set
+# CONFIG_UDHCPC6 is not set
+# CONFIG_UDHCPD is not set
+# CONFIG_DHCPRELAY is not set
+# CONFIG_DUMPLEASES is not set
+# CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set
+# CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC is not set
+CONFIG_DHCPD_LEASES_FILE=""
+# CONFIG_UDHCPC is not set
+# CONFIG_FEATURE_UDHCPC_ARPING is not set
+# CONFIG_FEATURE_UDHCP_PORT is not set
+CONFIG_UDHCP_DEBUG=0
+# CONFIG_FEATURE_UDHCP_RFC3397 is not set
+# CONFIG_FEATURE_UDHCP_8021Q is not set
+CONFIG_UDHCPC_DEFAULT_SCRIPT=""
+CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=0
+CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS=""
+# CONFIG_UDPSVD is not set
+# CONFIG_VCONFIG is not set
+CONFIG_WGET=y
+CONFIG_FEATURE_WGET_STATUSBAR=y
+CONFIG_FEATURE_WGET_AUTHENTICATION=y
+CONFIG_FEATURE_WGET_LONG_OPTIONS=y
+CONFIG_FEATURE_WGET_TIMEOUT=y
+# CONFIG_ZCIP is not set
+
+#
+# Print Utilities
+#
+# CONFIG_LPD is not set
+# CONFIG_LPR is not set
+# CONFIG_LPQ is not set
+
+#
+# Mail Utilities
+#
+# CONFIG_MAKEMIME is not set
+CONFIG_FEATURE_MIME_CHARSET=""
+# CONFIG_POPMAILDIR is not set
+# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set
+# CONFIG_REFORMIME is not set
+# CONFIG_FEATURE_REFORMIME_COMPAT is not set
+# CONFIG_SENDMAIL is not set
+
+#
+# Process Utilities
+#
+CONFIG_IOSTAT=y
+CONFIG_LSOF=y
+CONFIG_MPSTAT=y
+CONFIG_NMETER=y
+CONFIG_PMAP=y
+CONFIG_POWERTOP=y
+CONFIG_PSTREE=y
+CONFIG_PWDX=y
+CONFIG_SMEMCAP=y
+CONFIG_TOP=y
+CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y
+CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y
+CONFIG_FEATURE_TOP_SMP_CPU=y
+CONFIG_FEATURE_TOP_DECIMALS=y
+CONFIG_FEATURE_TOP_SMP_PROCESS=y
+CONFIG_FEATURE_TOPMEM=y
+CONFIG_UPTIME=y
+CONFIG_FEATURE_UPTIME_UTMP_SUPPORT=y
+CONFIG_FREE=y
+CONFIG_FUSER=y
+CONFIG_KILL=y
+CONFIG_KILLALL=y
+CONFIG_KILLALL5=y
+CONFIG_PGREP=y
+CONFIG_PIDOF=y
+CONFIG_FEATURE_PIDOF_SINGLE=y
+CONFIG_FEATURE_PIDOF_OMIT=y
+CONFIG_PKILL=y
+CONFIG_PS=y
+CONFIG_FEATURE_PS_WIDE=y
+CONFIG_FEATURE_PS_LONG=y
+# CONFIG_FEATURE_PS_TIME is not set
+# CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set
+# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set
+# CONFIG_RENICE is not set
+CONFIG_BB_SYSCTL=y
+CONFIG_FEATURE_SHOW_THREADS=y
+CONFIG_WATCH=y
+
+#
+# Runit Utilities
+#
+CONFIG_RUNSV=y
+CONFIG_RUNSVDIR=y
+CONFIG_FEATURE_RUNSVDIR_LOG=y
+CONFIG_SV=y
+CONFIG_SV_DEFAULT_SERVICE_DIR="/var/service"
+CONFIG_SVLOGD=y
+CONFIG_CHPST=y
+CONFIG_SETUIDGID=y
+CONFIG_ENVUIDGID=y
+CONFIG_ENVDIR=y
+CONFIG_SOFTLIMIT=y
+# CONFIG_CHCON is not set
+# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set
+# CONFIG_GETENFORCE is not set
+# CONFIG_GETSEBOOL is not set
+# CONFIG_LOAD_POLICY is not set
+# CONFIG_MATCHPATHCON is not set
+# CONFIG_RESTORECON is not set
+# CONFIG_RUNCON is not set
+# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set
+# CONFIG_SELINUXENABLED is not set
+# CONFIG_SETENFORCE is not set
+# CONFIG_SETFILES is not set
+# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set
+# CONFIG_SETSEBOOL is not set
+# CONFIG_SESTATUS is not set
+
+#
+# Shells
+#
+CONFIG_ASH=y
+CONFIG_ASH_BASH_COMPAT=y
+# CONFIG_ASH_IDLE_TIMEOUT is not set
+CONFIG_ASH_JOB_CONTROL=y
+CONFIG_ASH_ALIAS=y
+CONFIG_ASH_GETOPTS=y
+CONFIG_ASH_BUILTIN_ECHO=y
+CONFIG_ASH_BUILTIN_PRINTF=y
+CONFIG_ASH_BUILTIN_TEST=y
+CONFIG_ASH_CMDCMD=y
+# CONFIG_ASH_MAIL is not set
+CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
+CONFIG_ASH_RANDOM_SUPPORT=y
+CONFIG_ASH_EXPAND_PRMT=y
+CONFIG_CTTYHACK=y
+CONFIG_HUSH=y
+CONFIG_HUSH_BASH_COMPAT=y
+CONFIG_HUSH_BRACE_EXPANSION=y
+CONFIG_HUSH_HELP=y
+CONFIG_HUSH_INTERACTIVE=y
+# CONFIG_HUSH_SAVEHISTORY is not set
+CONFIG_HUSH_JOB=y
+CONFIG_HUSH_TICK=y
+CONFIG_HUSH_IF=y
+CONFIG_HUSH_LOOPS=y
+CONFIG_HUSH_CASE=y
+CONFIG_HUSH_FUNCTIONS=y
+CONFIG_HUSH_LOCAL=y
+CONFIG_HUSH_RANDOM_SUPPORT=y
+CONFIG_HUSH_EXPORT_N=y
+CONFIG_HUSH_MODE_X=y
+CONFIG_MSH=y
+# CONFIG_FEATURE_SH_IS_ASH is not set
+CONFIG_FEATURE_SH_IS_HUSH=y
+# CONFIG_FEATURE_SH_IS_NONE is not set
+# CONFIG_FEATURE_BASH_IS_ASH is not set
+# CONFIG_FEATURE_BASH_IS_HUSH is not set
+CONFIG_FEATURE_BASH_IS_NONE=y
+CONFIG_SH_MATH_SUPPORT=y
+CONFIG_SH_MATH_SUPPORT_64=y
+CONFIG_FEATURE_SH_EXTRA_QUIET=y
+CONFIG_FEATURE_SH_STANDALONE=y
+CONFIG_FEATURE_SH_NOFORK=y
+CONFIG_FEATURE_SH_HISTFILESIZE=y
+
+#
+# System Logging Utilities
+#
+CONFIG_SYSLOGD=y
+CONFIG_FEATURE_ROTATE_LOGFILE=y
+CONFIG_FEATURE_REMOTE_LOG=y
+CONFIG_FEATURE_SYSLOGD_DUP=y
+CONFIG_FEATURE_SYSLOGD_CFG=y
+CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=256
+CONFIG_FEATURE_IPC_SYSLOG=y
+CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=16
+CONFIG_LOGREAD=y
+CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING=y
+CONFIG_FEATURE_KMSG_SYSLOG=y
+CONFIG_KLOGD=y
+
+#
+# klogd should not be used together with syslog to kernel printk buffer
+#
+CONFIG_FEATURE_KLOGD_KLOGCTL=y
+CONFIG_LOGGER=y
diff --git a/tests/arm64/common/busybox/busybox_dev.txt b/tests/arm64/common/busybox/busybox_dev.txt
new file mode 100644
index 0000000..91c0b6a
--- /dev/null
+++ b/tests/arm64/common/busybox/busybox_dev.txt
@@ -0,0 +1,70 @@
+# name type mode uid gid major minor start inc count
+/dev d 755 0 0 - - - - -
+/dev/pts d 755 0 0 - - - - -
+/dev/initctl p 400 0 0 0 0 0 0 -
+/dev/console c 620 0 0 5 1 0 0 -
+/dev/fb0 c 600 0 0 29 0 0 0 -
+/dev/flasha c 755 0 0 60 0 0 0 -
+/dev/flasha c 755 0 0 60 1 1 1 8
+/dev/flashb c 755 0 0 60 8 0 0 -
+/dev/flashb c 755 0 0 60 9 1 1 8
+/dev/full c 666 0 0 1 7 0 0 -
+/dev/hda b 660 0 0 3 0 0 0 -
+/dev/hda b 660 0 0 3 1 1 1 16
+/dev/hdb b 660 0 0 3 64 0 0 -
+/dev/hdb b 660 0 0 3 65 1 1 16
+/dev/hvc c 620 0 0 229 0 0 1 4
+/dev/sda b 660 0 0 8 0 0 0 -
+/dev/sda b 660 0 0 8 1 1 1 16
+/dev/sdb b 660 0 0 8 16 0 0 -
+/dev/sdb b 660 0 0 8 17 1 1 16
+/dev/sdc b 660 0 0 8 32 0 0 -
+/dev/sdc b 660 0 0 8 33 1 1 16
+/dev/kmem c 640 0 0 1 2 0 0 -
+/dev/mem c 640 0 0 1 1 0 0 -
+/dev/mtd c 664 0 0 90 0 0 2 17
+/dev/mtdblock b 664 0 0 31 0 0 1 17
+/dev/mtdchar c 755 0 0 90 0 0 1 8
+/dev/mtdr0 c 664 0 0 90 1 0 1 17
+/dev/mmcblk0 b 664 0 0 179 0 0 0 -
+/dev/mmcblk0p b 664 0 0 179 1 1 1 8
+/dev/mmcblk1 b 664 0 0 179 8 0 0 -
+/dev/mmcblk1p b 664 0 0 179 9 1 1 8
+/dev/nftla b 755 0 0 93 0 0 0 -
+/dev/nftla1 b 755 0 0 93 1 1 1 16
+/dev/nftlb b 755 0 0 93 16 0 0 -
+/dev/nftlb1 b 755 0 0 93 17 1 1 16
+/dev/null c 666 0 0 1 3 0 0 -
+/dev/psaux c 600 0 0 10 1 0 0 -
+/dev/ptmx c 666 0 0 5 2 0 0 -
+/dev/ptyp c 666 0 0 2 0 0 1 10
+/dev/ptypa c 666 0 0 2 10 0 0 -
+/dev/ptypb c 666 0 0 2 11 0 0 -
+/dev/ptypc c 666 0 0 2 12 0 0 -
+/dev/ptypd c 666 0 0 2 13 0 0 -
+/dev/ptype c 666 0 0 2 14 0 0 -
+/dev/ptypf c 666 0 0 2 15 0 0 -
+/dev/ram b 640 0 0 1 1 0 0 -
+/dev/ram0 b 660 0 0 1 0 0 0 -
+/dev/ram1 b 660 0 0 1 1 0 0 -
+/dev/rtc c 644 0 0 10 135 0 0 -
+/dev/tty c 666 0 0 5 0 0 0 -
+/dev/tty c 620 0 0 4 0 0 1 10
+/dev/ttyCPM c 620 0 0 204 46 0 1 6
+/dev/ttyAMA c 620 0 0 204 64 0 1 4
+/dev/ttyp c 620 0 0 3 0 0 1 10
+/dev/ttypa c 620 0 0 3 10 0 0 -
+/dev/ttypb c 620 0 0 3 11 0 0 -
+/dev/ttypc c 620 0 0 3 12 0 0 -
+/dev/ttypd c 620 0 0 3 13 0 0 -
+/dev/ttype c 620 0 0 3 14 0 0 -
+/dev/ttypf c 620 0 0 3 15 0 0 -
+/dev/ttyS c 660 0 0 4 64 0 1 8
+/dev/vda b 660 0 0 254 0 0 0 -
+/dev/vda b 660 0 0 254 1 1 1 16
+/dev/vdb b 660 0 0 254 16 0 0 -
+/dev/vdb b 660 0 0 254 17 1 1 16
+/dev/watchdog c 666 0 0 10 130 0 0 -
+/dev/zero c 666 0 0 1 5 0 0 -
+/dev/random c 644 0 0 1 8 0 0 -
+/dev/urandom c 644 0 0 1 9 0 0 -
diff --git a/tests/arm64/virt-v8/README b/tests/arm64/virt-v8/README
new file mode 100644
index 0000000..bade6a3
--- /dev/null
+++ b/tests/arm64/virt-v8/README
@@ -0,0 +1,29 @@
+ Virt-v8 Guest
+
+The Virt-v8 is a fully para-virtualized guest with ARMv8 CPUs.
+
+We only have memory mapped VirtIO devices for IO and this makes the
+Guest as fully para-virtualized.
+
+The memory map and irqs in Virt-v8 guest is as follows:
+0x0000000000000000-0x0000000000FFFFFF (16M) (NOR Flash)
+0x000000002C001000–0x000000002C001FFF (4K) (GIC Distributor Interface)
+0x000000002C002000–0x000000002C002FFF (4K) (GIC CPU Interface)
+0x0000000040200000–0x0000000040200FFF (4K) (IRQ=40) (VirtIO Network Device)
+0x0000000040400000–0x0000000040400FFF (4K) (IRQ=41) (VirtIO Block Device)
+0x0000000040600000–0x0000000040600FFF (4K) (IRQ=42) (VirtIO Console Device)
+0x0000000080000000-0xFFFFFFFFFFFFFFFF (---) (RAM)
+
+In addition, we also have ARMv8 generic timer accessible to all VCPUs
+of the Guest with virtual timer irq 27 and physical timer irq 30.
+
+
+ Virt-v8 Guest OSes
+
+We have tested following guest OSes for this guest:
+
+ 1. basic - Basic firmware/bootloader
+ 2. linux - Linux Kernel
+
+Please follow the README under specific guest OS directory for detailed
+steps to configure, compile and run.
diff --git a/tests/arm64/virt-v8/basic/Makefile b/tests/arm64/virt-v8/basic/Makefile
new file mode 100644
index 0000000..3db2006
--- /dev/null
+++ b/tests/arm64/virt-v8/basic/Makefile
@@ -0,0 +1,43 @@
+#/**
+# Copyright (c) 2013 Sukanto Ghosh.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# @file Makefile
+# @author Sukanto Ghosh (sukant...@gmail.com)
+# @brief toplevel makefile to build ARM test code
+# */
+
+# Determine the build directory
+top_dir=$(CURDIR)/../../../..
+ifdef O
+ build_dir=$(shell readlink -f $(O))
+else
+ build_dir=$(top_dir)/build
+endif
+
+obj_dir=$(build_dir)/tests/arm64/virt-v8/basic
+common_dir=$(top_dir)/tests/arm64/common/basic
+
+board_text_start = 0x81000000
+board_objs = $(obj_dir)/arm_board.o \
+ $(obj_dir)/pic/gic.o \
+ $(obj_dir)/timer/generic_timer.o \
+ $(obj_dir)/serial/virtio_console.o
+
+# Include common makefile for basic test
+include $(common_dir)/Makefile.inc
+
diff --git a/tests/arm64/virt-v8/basic/README b/tests/arm64/virt-v8/basic/README
new file mode 100644
index 0000000..0ca69263
--- /dev/null
+++ b/tests/arm64/virt-v8/basic/README
@@ -0,0 +1,61 @@
+ Basic Firmware on Virt-v8 Guest
+
+The basic firmware currently sets up PIC, Timer, and UART and emulates
+a dummy terminal which reponds to various commands. It also includes an
+extensive MMU test suite and dhrystone benchmark.
+
+Hardware features tested by Basic Firmware:
+ - Crucial EL1 instructions
+ - Virtual IRQs
+ - Generic Interrupt Controller (GIC)
+ - ARMv8 Generic Timers
+ - VirtIO console emergency write
+
+Please follow the steps below to build & run Basic Firmware on Virt-v8
+Guest with Xvisor running on Foundation v8 Model:
+
+ [1. Build environment for Xvisor]
+ # CROSS_COMPILE=aarch64-none-linux-gnu-
+
+ [2. GoTo Xvisor source directory]
+ # cd <xvisor_source_directory>
+
+ [3. Configure Xvisor with Generic-v8 default settings]
+ # make ARCH=arm generic-v8-defconfig
+
+ [4. Build Xvisor]
+ # make
+
+ [5. Build Xvisor DTBs for Generic-v8]
+ # make dtbs
+
+ [6. Build Basic Firmware]
+ # make -C tests/arm64/virt-v8/basic
+
+ [7. Create foundation_v8_boot.axf for running it on Foundation v8 Model]
+ # ./tools/scripts/memimg.py -a 0x80010000 -o ./build/foundation_v8_boot.img ./build/vmm.bin@0x80010000 ./build/tests/arm64/virt-v8/basic/firmware.bin@0x81000000
+ # ${CROSS_COMPILE}gcc -nostdlib -nostdinc -e _start -Wl,-Ttext=0x80000000 -DGENTIMER_FREQ=100000000 -DGIC_DIST_BASE=0x2c001000 -DGIC_CPU_BASE=0x2c002000 -DSPIN_LOOP_ADDR=0x84000000 -DIMAGE=./build/foundation_v8_boot.img -DDTB=./build/arch/arm/board/generic-v8/dts/foundation-v8/one_guest_virt_v8.dtb ./docs/arm/foundation_v8_boot.S -o ./build/foundation_v8_boot.axf
+
+ [8. Launch Foundation v8 Model]
+ # <foundation_v8_install_directory>/models/Linux64_GCC-4.1/Foundation_v8 --image ./build/foundation_v8_boot.axf --network=nat
+
+ [9. Kick Guest0 for starting Basic Firmware]
+ XVisor# guest kick guest0
+
+ [10. Bind to VirtIO Console]
+ XVisor# vserial bind guest0/virtio-con0
+
+ [11. Say 'hi' to Basic Firmware]
+ [guest0/uart0] basic# hi
+
+ [12. Say 'hello' to Basic Firmware]
+ [guest0/uart0] basic# hello
+
+ [13. Check various commands of Basic Firmware]
+ [guest0/uart0] basic# help
+
+ [14. Enter character seqence 'ESCAPE+x+q" return to Xvisor prompt]
+ [guest0/uart0] basic#
+
+ (Note: replace all <> brackets based on your workspace)
+
diff --git a/tests/arm64/virt-v8/basic/arm_board.c b/tests/arm64/virt-v8/basic/arm_board.c
new file mode 100644
index 0000000..db981df
--- /dev/null
+++ b/tests/arm64/virt-v8/basic/arm_board.c
@@ -0,0 +1,214 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_board.c
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief various platform specific functions
+ */
+
+#include <arm_types.h>
+#include <arm_string.h>
+#include <arm_board.h>
+#include <arm_plat.h>
+#include <pic/gic.h>
+#include <timer/generic_timer.h>
+#include <serial/virtio_console.h>
+
+void arm_board_reset(void)
+{
+ /* Nothing to do */
+}
+
+void arm_board_init(void)
+{
+ /* Nothing to do */
+}
+
+char *arm_board_name(void)
+{
+ return "Virt-v8";
+}
+
+physical_addr_t arm_board_ram_start(void)
+{
+ return VIRT_V8_RAM0;
+}
+
+physical_size_t arm_board_ram_size(void)
+{
+ return VIRT_V8_RAM0_SIZE;
+}
+
+void arm_board_linux_default_cmdline(char *cmdline, u32 cmdline_sz)
+{
+ arm_strcpy(cmdline, "root=/dev/ram rw "
+ "earlyprintk=virtio-console,0x40600000 "
+ "console=hvc0");
+}
+
+physical_addr_t arm_board_flash_addr(void)
+{
+ return VIRT_V8_NOR_FLASH_0;
+}
+
+u32 arm_board_iosection_count(void)
+{
+ return 5;
+}
+
+physical_addr_t arm_board_iosection_addr(int num)
+{
+ physical_addr_t ret = 0;
+
+ switch (num) {
+ case 0:
+ /* nor-flash */
+ ret = VIRT_V8_NOR_FLASH_0;
+ break;
+ case 1:
+ /* gic */
+ ret = VIRT_V8_GIC;
+ break;
+ case 2:
+ /* virtio-net */
+ ret = VIRT_V8_VIRTIO_NET;
+ break;
+ case 3:
+ /* virtio-blk */
+ ret = VIRT_V8_VIRTIO_BLK;
+ break;
+ case 4:
+ /* virtio-con */
+ ret = VIRT_V8_VIRTIO_CON;
+ break;
+ default:
+ while (1);
+ break;
+ }
+
+ return ret;
+}
+
+u32 arm_board_pic_nr_irqs(void)
+{
+ return NR_IRQS_VIRT_V8;
+}
+
+int arm_board_pic_init(void)
+{
+ int rc;
+
+ /*
+ * Initialize Generic Interrupt Controller
+ */
+ rc = gic_dist_init(0, VIRT_V8_GIC_DIST, IRQ_VIRT_V8_GIC_START);
+ if (rc) {
+ return rc;
+ }
+ rc = gic_cpu_init(0, VIRT_V8_GIC_CPU);
+ if (rc) {
+ return rc;
+ }
+
+ return 0;
+}
+
+u32 arm_board_pic_active_irq(void)
+{
+ return gic_active_irq(0);
+}
+
+int arm_board_pic_ack_irq(u32 irq)
+{
+ return 0;
+}
+
+int arm_board_pic_eoi_irq(u32 irq)
+{
+ return gic_eoi_irq(0, irq);
+}
+
+int arm_board_pic_mask(u32 irq)
+{
+ return gic_mask(0, irq);
+}
+
+int arm_board_pic_unmask(u32 irq)
+{
+ return gic_unmask(0, irq);
+}
+
+void arm_board_timer_enable(void)
+{
+ return generic_timer_enable();
+}
+
+void arm_board_timer_disable(void)
+{
+ return generic_timer_disable();
+}
+
+u64 arm_board_timer_irqcount(void)
+{
+ return generic_timer_irqcount();
+}
+
+u64 arm_board_timer_irqdelay(void)
+{
+ return generic_timer_irqdelay();
+}
+
+u64 arm_board_timer_timestamp(void)
+{
+ return generic_timer_timestamp();
+}
+
+void arm_board_timer_change_period(u32 usecs)
+{
+ return generic_timer_change_period(usecs);
+}
+
+int arm_board_timer_init(u32 usecs)
+{
+ return generic_timer_init(usecs, IRQ_VIRT_V8_VIRT_TIMER);
+}
+
+int arm_board_serial_init(void)
+{
+ return virtio_console_init(VIRT_V8_VIRTIO_CON);
+}
+
+void arm_board_serial_putc(char ch)
+{
+ if (ch == '\n') {
+ virtio_console_printch(VIRT_V8_VIRTIO_CON, '\r');
+ }
+ virtio_console_printch(VIRT_V8_VIRTIO_CON, ch);
+}
+
+char arm_board_serial_getc(void)
+{
+ char ch = virtio_console_getch(VIRT_V8_VIRTIO_CON);
+ if (ch == '\r') {
+ ch = '\n';
+ }
+ virtio_console_printch(VIRT_V8_VIRTIO_CON, ch);
+ return ch;
+}
+
+
diff --git a/tests/arm64/virt-v8/basic/arm_plat.h b/tests/arm64/virt-v8/basic/arm_plat.h
new file mode 100644
index 0000000..76dfd98
--- /dev/null
+++ b/tests/arm64/virt-v8/basic/arm_plat.h
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_plat.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief Platform Configuration for virt-v8 board
+ */
+#ifndef __ARM_PLAT_H__
+#define __ARM_PLAT_H__
+
+#define VIRT_V8_NOR_FLASH_0 (0x000000000)
+#define VIRT_V8_NOR_FLASH_0_SIZE (0x001000000)
+#define VIRT_V8_GIC (0x02c000000)
+#define VIRT_V8_GIC_SIZE (0x000003000)
+#define VIRT_V8_VIRTIO_NET (0x040200000)
+#define VIRT_V8_VIRTIO_NET_SIZE (0x000001000)
+#define VIRT_V8_VIRTIO_BLK (0x040400000)
+#define VIRT_V8_VIRTIO_BLK_SIZE (0x000001000)
+#define VIRT_V8_VIRTIO_CON (0x040600000)
+#define VIRT_V8_VIRTIO_CON_SIZE (0x000001000)
+#define VIRT_V8_RAM0 (0x080000000)
+#define VIRT_V8_RAM0_SIZE (0x006000000)
+
+#define VIRT_V8_GIC_DIST (VIRT_V8_GIC + 0x1000)
+#define VIRT_V8_GIC_CPU (VIRT_V8_GIC + 0x2000)
+
+/*
+ * Interrupts.
+ */
+#define IRQ_VIRT_V8_VIRT_TIMER 27
+#define IRQ_VIRT_V8_PHYS_TIMER 30
+
+#define IRQ_VIRT_V8_VIRTIO_NET 40
+#define IRQ_VIRT_V8_VIRTIO_BLK 41
+#define IRQ_VIRT_V8_VIRTIO_CON 42
+
+#define IRQ_VIRT_V8_GIC_START 16
+#define NR_IRQS_VIRT_V8 128
+#define NR_GIC_VIRT_V8 1
+
+#define IRQ_VIRT_TIMER IRQ_VIRT_V8_VIRT_TIMER
+
+/*
+ * Defines required by common code
+ */
+#define ARM_PLAT_SPIN_ADDR 0x80000100
+
+#endif
diff --git a/tests/arm64/virt-v8/basic/gic_config.h b/tests/arm64/virt-v8/basic/gic_config.h
new file mode 100644
index 0000000..8f95c27
--- /dev/null
+++ b/tests/arm64/virt-v8/basic/gic_config.h
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file gic_config.h
+ * @author Sukanto Ghosh (sukant...@gmail.com)
+ * @brief ARM Generic Interrupt Controller configuration header
+ */
+#ifndef _GIC_CONFIG_H__
+#define _GIC_CONFIG_H__
+
+#include <arm_plat.h>
+
+#define GIC_CPU_BASE VIRT_V8_GIC_CPU
+#define GIC_DIST_BASE VIRT_V8_GIC_DIST
+
+#if !defined(GIC_NR_IRQS) || (GIC_NR_IRQS < NR_IRQS_CA15X4)
+#undef GIC_NR_IRQS
+#define GIC_NR_IRQS NR_IRQS_VIRT_V8
+#endif
+
+#if !defined(GIC_MAX_NR) || (GIC_MAX_NR < NR_GIC_CA15X4)
+#undef GIC_MAX_NR
+#define GIC_MAX_NR NR_GIC_VIRT_V8
+#endif
+
+#endif
diff --git a/tests/arm64/virt-v8/linux/README b/tests/arm64/virt-v8/linux/README
new file mode 100644
index 0000000..a7091ff
--- /dev/null
+++ b/tests/arm64/virt-v8/linux/README
@@ -0,0 +1,95 @@
+ Linux on Xvisor Virt-v8 SMP Guest
+
+Linux is a computer operating system which is based on free and open source
+software. the underlying source code can be used, freely modified, and
+redistributed, both commercially and non-commercially, by anyone under
+licenses such as the GNU General Public License. For more information on
+Linux read the wiki page http://en.wikipedia.org/wiki/Linux
+
+Linux already contains a support for device-tree based boards. We can use
+this kernel unmodified to run it as a xvisor guest. We have also provide
+a defconfig for building kernel. To obtain Linux kernel sources visit the
+following url: http://www.kernel.org
+
+Please follow the steps below to build & run Linux kernel with Busybox
+RootFS on Virt-v8 (paravirtualized ARMv8) Guest with Xvisor running on
+Foundation v8 model:
+
+ [1. Build environment for Xvisor]
+ # CROSS_COMPILE=aarch64-linux-gnu-
+
+ [2. GoTo Xvisor source directory]
+ # cd <xvisor_source_directory>
+
+ [3. Configure Xvisor with Generic-V8 default settings]
+ # make ARCH=arm generic-v8-defconfig
+
+ [4. Build Xvisor]
+ # make
+
+ [5. Build DTBs]
+ # make dtbs
+
+ [6. Build Basic Firmware]
+ # make -C tests/arm64/virt-v8/basic
+
+ [7. Copy Linux defconfig to Linux build directory]
+ # cp tests/arm64/virt-v8/linux/linux-<linux_version>_virt_v8_defconfig <linux_build_directory>/.config
+
+ [8. GoTo Linux source directory]
+ # cd <linux_source_directory>
+
+ [9. Apply patch for virtio-console earlyprintk support]
+ # patch -p1 < <xvisor_source_directory>/tests/arm64/virt-v8/linux/linux-3.11-virtio-console-earlyprintk.patch
+ (Note: This is an optional but recommended step. Without this earlyprintks will not work on virtio-console)
+
+ [10. Configure Linux in build directory]
+ # make O=<linux_build_directory> ARCH=arm64 oldconfig
+
+ [11. Build Linux in build directory to reflect changes in kernel image]
+ # make O=<linux_build_directory> ARCH=arm64 Image
+
+ [12. Create BusyBox RAMDISK to be used as RootFS for Linux kernel]
+ (Note: For subsequent steps, we will assume that your RAMDISK is located at <busybox_rootfs_directory>/rootfs64.img)
+ (Note: Please refer tests/arm64/common/busybox/README for creating rootfs64.img using BusyBox)
+
+ [13. GoTo Linux build directory]
+ # cd <linux_build_directory>
+
+ [14. Build virt-v8.dtb for guest linux]
+ # ./scripts/dtc/dtc -I dts -O dtb -p 0x800 -o virt-v8.dtb <xvisor_source_directory>/tests/arm64/virt-v8/linux/virt-v8.dts
+
+ [15. Create foundation_v8_boot.axf for running it on Foundation v8 model]
+ # <xvisor_source_directory>/tools/scripts/memimg.py -a 0x80010000 -o foundation_v8_boot.img <xvisor_source_directory>/build/vmm.bin@0x80010000 <xvisor_source_directory>/build/tests/arm64/virt-v8/basic/firmware.bin@0x81000000 <xvisor_source_directory>/tests/arm64/virt-v8/linux/cmdlist@0x810FF000 <linux_build_directory>/arch/arm64/boot/Image@0x81100000 <linux_build_directory>/virt-v8.dtb@0x81600000 <busybox_rootfs_directory>/rootfs64.img@0x81700000
+ # ${CROSS_COMPILE}gcc -nostdlib -nostdinc -e _start -Wl,-Ttext=0x80000000 -DGENTIMER_FREQ=100000000 -DGIC_DIST_BASE=0x2c001000 -DGIC_CPU_BASE=0x2c002000 -DSPIN_LOOP_ADDR=0x84000000 -DIMAGE=foundation_v8_boot.img -DDTB=<xvisor_source_directory>/build/arch/arm/board/generic-v8/dts/foundation-v8/one_guest_virt_v8.dtb <xvisor_source_directory>/docs/arm/foundation_v8_boot.S -o foundation_v8_boot.axf
+
+ [16. Launch Foundation v8 Model]
+ # <foundation_v8_install_directory>/models/Linux64_GCC-4.1/Foundation_v8 --image foundation_v8_boot.axf --network=nat
+
+ [17. Kick Guest0 to start Basic Firmware]
+ XVisor# guest kick guest0
+
+ [18. Bind to VirtIO Console]
+ XVisor# vserial bind guest0/virtio-con0
+
+ [19. Copy linux from NOR flash to RAM and start linux booting from RAM]
+ [guest0/virtio-con0] basic# copy 0x80080000 0x00100000 0x500000
+ (Note: This command will copy Image to RAM)
+ [guest0/virtio-con0] basic# copy 0x80F00000 0x00600000 0x004000
+ (Note: This command will copy virt-v8.dtb to RAM)
+ [guest0/virtio-con0] basic# copy 0x82000000 0x00700000 0x600000
+ (Note: This command will copy rootfs64.img to RAM)
+ [guest0/virtio-con0] basic# start_linux 0x80080000 0x82000000 0x600000 0x80F00000
+ (Note: This command will start linux booting)
+ OR
+ [guest0/virtio-con0] basic# autoexec
+ (Note: "autoexec" is a short-cut command)
+
+ [20. Wait for Linux prompt to come-up and then try out some commands]
+ [guest0/virtio-con0] / # ls
+
+ [21. Enter character seqence 'ESCAPE+x+q" return to Xvisor prompt]
+ [guest0/virtio-con0] / #
+
+ (Note: replace all <> brackets based on your workspace)
+
diff --git a/tests/arm64/virt-v8/linux/cmdlist b/tests/arm64/virt-v8/linux/cmdlist
new file mode 100644
index 0000000..a7cbefb
--- /dev/null
+++ b/tests/arm64/virt-v8/linux/cmdlist
@@ -0,0 +1,5 @@
+copy 0x80080000 0x00100000 0x500000
+copy 0x80F00000 0x00600000 0x004000
+copy 0x82000000 0x00700000 0x600000
+start_linux 0x80080000 0x82000000 0x600000 0x80F00000
+
diff --git a/tests/arm64/virt-v8/linux/linux-3.11-virtio-console-earlyprintk.patch b/tests/arm64/virt-v8/linux/linux-3.11-virtio-console-earlyprintk.patch
new file mode 100644
index 0000000..6886110
--- /dev/null
+++ b/tests/arm64/virt-v8/linux/linux-3.11-virtio-console-earlyprintk.patch
@@ -0,0 +1,61 @@
+diff --git a/arch/arm64/kernel/early_printk.c b/arch/arm64/kernel/early_printk.c
+index fbb6e18..7ac8efd 100644
+--- a/arch/arm64/kernel/early_printk.c
++++ b/arch/arm64/kernel/early_printk.c
+@@ -25,6 +25,9 @@
+
+ #include <linux/amba/serial.h>
+ #include <linux/serial_reg.h>
++#include <linux/virtio_ids.h>
++#include <linux/virtio_mmio.h>
++#include <linux/virtio_console.h>
+
+ static void __iomem *early_base;
+ static void (*printch)(char ch);
+@@ -53,6 +56,37 @@ static void smh_printch(char ch)
+ }
+
+ /*
++ * VIRTIO MMIO console single character Tx.
++ */
++static void virtio_console_printch(char ch)
++{
++ u32 tmp;
++ static u32 init_done;
++ static u32 can_write;
++ struct virtio_console_config *p = early_base + VIRTIO_MMIO_CONFIG;
++
++ if (!init_done) {
++ tmp = readl_relaxed(early_base + VIRTIO_MMIO_DEVICE_ID);
++ if (tmp != VIRTIO_ID_CONSOLE) {
++ init_done = 1;
++ return;
++ }
++
++ tmp = readl_relaxed(early_base + VIRTIO_MMIO_HOST_FEATURES);
++ if (!(tmp & (1 << VIRTIO_CONSOLE_F_EMERG_WRITE))) {
++ init_done = 1;
++ return;
++ }
++
++ init_done = 1;
++ can_write = 1;
++ }
++
++ if (can_write)
++ writeb_relaxed(ch, &p->emerg_wr);
++}
++
++/*
+ * 8250/16550 (8-bit aligned registers) single character TX.
+ */
+ static void uart8250_8bit_printch(char ch)
+@@ -82,6 +116,7 @@ static const struct earlycon_match earlycon_match[] __initconst = {
+ { .name = "smh", .printch = smh_printch, },
+ { .name = "uart8250-8bit", .printch = uart8250_8bit_printch, },
+ { .name = "uart8250-32bit", .printch = uart8250_32bit_printch, },
++ { .name = "virtio-console", .printch = virtio_console_printch, },
+ {}
+ };
+
+
diff --git a/tests/arm64/virt-v8/linux/linux-3.11_virt_v8_defconfig b/tests/arm64/virt-v8/linux/linux-3.11_virt_v8_defconfig
new file mode 100644
index 0000000..96348a1
--- /dev/null
+++ b/tests/arm64/virt-v8/linux/linux-3.11_virt_v8_defconfig
@@ -0,0 +1,1399 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm64 3.11.0-rc7 Kernel Configuration
+#
+CONFIG_ARM64=y
+CONFIG_64BIT=y
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_MMU=y
+CONFIG_NO_IOPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CSUM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA32=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_FHANDLE is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+# CONFIG_IRQ_DOMAIN_DEBUG is not set
+CONFIG_SPARSE_IRQ=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+CONFIG_RCU_STALL_COMMON=y
+CONFIG_RCU_FANOUT=64
+CONFIG_RCU_FANOUT_LEAF=16
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_NOCB_CPU is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CGROUP_FREEZER is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_RESOURCE_COUNTERS is not set
+# CONFIG_CGROUP_PERF is not set
+CONFIG_CGROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_CFS_BANDWIDTH is not set
+# CONFIG_RT_GROUP_SCHED is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_UIDGID_CONVERTED=y
+# CONFIG_UIDGID_STRICT_TYPE_CHECKS is not set
+CONFIG_SCHED_AUTOGROUP=y
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_XZ=y
+CONFIG_RD_LZO=y
+CONFIG_RD_LZ4=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+# CONFIG_EXPERT is not set
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+CONFIG_SLUB_CPU_PARTIAL=y
+CONFIG_PROFILING=y
+CONFIG_HAVE_64BIT_ALIGNED_ACCESS=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
+CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_COMPAT_OLD_SIGACTION=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_BLOCK_COMPAT=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+# CONFIG_FREEZER is not set
+
+#
+# Platform selection
+#
+CONFIG_ARCH_VEXPRESS=y
+CONFIG_ARCH_XGENE=y
+
+#
+# Bus support
+#
+CONFIG_ARM_AMBA=y
+
+#
+# Kernel Features
+#
+# CONFIG_ARM64_64K_PAGES is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=8
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HW_PERF_EVENTS=y
+CONFIG_SYS_SUPPORTS_HUGETLBFS=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=0
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_TRANSPARENT_HUGEPAGE is not set
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_ZBUD is not set
+# CONFIG_XEN is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+
+#
+# Boot options
+#
+CONFIG_CMDLINE="console=ttyAMA0"
+# CONFIG_CMDLINE_FORCE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_COMPAT_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_NET_IP_TUNNEL is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_MMAP is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_NET_MPLS_GSO is not set
+CONFIG_RPS=y
+CONFIG_RFS_ACCEL=y
+CONFIG_XPS=y
+# CONFIG_NETPRIO_CGROUP is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+CONFIG_NET_FLOW_LIMIT=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+# CONFIG_DEVTMPFS_MOUNT is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+CONFIG_FW_LOADER_USER_HELPER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+
+#
+# Device Tree and Open Firmware support
+#
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_OF_SELFTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=10240
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_VIRTIO_BLK=y
+# CONFIG_BLK_DEV_RBD is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_ATMEL_PWM is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ATMEL_SSC is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+
+#
+# Altera FPGA firmware download module
+#
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_VIRTIO_NET=y
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+# CONFIG_NET_DSA_MV88E6XXX is not set
+# CONFIG_NET_DSA_MV88E6060 is not set
+# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
+# CONFIG_NET_DSA_MV88E6131 is not set
+# CONFIG_NET_DSA_MV88E6123_61_65 is not set
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_ARC=y
+# CONFIG_ARC_EMAC is not set
+CONFIG_NET_CADENCE=y
+# CONFIG_ARM_AT91_ETHER is not set
+# CONFIG_MACB is not set
+CONFIG_NET_VENDOR_BROADCOM=y
+# CONFIG_B44 is not set
+# CONFIG_NET_CALXEDA_XGMAC is not set
+# CONFIG_DNET is not set
+CONFIG_NET_VENDOR_INTEL=y
+CONFIG_NET_VENDOR_I825XX=y
+CONFIG_NET_VENDOR_MARVELL=y
+# CONFIG_MVMDIO is not set
+CONFIG_NET_VENDOR_MICREL=y
+# CONFIG_KS8851_MLL is not set
+CONFIG_NET_VENDOR_NATSEMI=y
+CONFIG_NET_VENDOR_8390=y
+# CONFIG_ETHOC is not set
+# CONFIG_SH_ETH is not set
+CONFIG_NET_VENDOR_SEEQ=y
+CONFIG_NET_VENDOR_SMSC=y
+CONFIG_SMC91X=y
+# CONFIG_SMSC911X is not set
+CONFIG_NET_VENDOR_STMICRO=y
+# CONFIG_STMMAC_ETH is not set
+CONFIG_NET_VENDOR_VIA=y
+CONFIG_NET_VENDOR_WIZNET=y
+# CONFIG_WIZNET_W5100 is not set
+# CONFIG_WIZNET_W5300 is not set
+# CONFIG_PHYLIB is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_CYPRESS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_AMBAKMI is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_SERIO_APBPS2 is not set
+# CONFIG_SERIO_OLPC_APSP is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVKMEM=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_DW is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+CONFIG_HVC_DRIVER=y
+CONFIG_VIRTIO_CONSOLE=y
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIO_DEVRES=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO drivers:
+#
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_TS5500 is not set
+# CONFIG_GPIO_GRGPIO is not set
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+
+#
+# USB GPIO expanders:
+#
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_GPIO is not set
+# CONFIG_BATTERY_GOLDFISH is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_GPIO is not set
+CONFIG_POWER_RESET_VEXPRESS=y
+# CONFIG_POWER_AVS is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_TPS65912 is not set
+# CONFIG_MFD_TMIO is not set
+CONFIG_VEXPRESS_CONFIG=y
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_GOLDFISH is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_EXYNOS_VIDEO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=y
+# CONFIG_HID_ACRUX is not set
+CONFIG_HID_APPLE=y
+# CONFIG_HID_AUREAL is not set
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+CONFIG_HID_EZKEY=y
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+CONFIG_HID_KENSINGTON=y
+# CONFIG_HID_LCPOWER is not set
+CONFIG_HID_LOGITECH=y
+# CONFIG_HID_LOGITECH_DJ is not set
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+# CONFIG_LOGIG940_FF is not set
+# CONFIG_LOGIWHEELS_FF is not set
+# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+CONFIG_VIRT_DRIVERS=y
+CONFIG_VIRTIO=y
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_BALLOON is not set
+CONFIG_VIRTIO_MMIO=y
+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_DEBUG is not set
+CONFIG_COMMON_CLK_VERSATILE=y
+
+#
+# Hardware Spinlock drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_ARM_ARCH_TIMER=y
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_PWM is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC=y
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_VIRTUALIZATION is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_INFO_REDUCED is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=2048
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_HAVE_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=21
+# CONFIG_RCU_CPU_STALL_INFO is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_LKDTM is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+CONFIG_ATOMIC64_SELFTEST=y
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_EARLY_PRINTK=y
+# CONFIG_PID_IN_CONTEXTIDR is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=m
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_USER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_PCRYPT is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_IO=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+# CONFIG_XZ_DEC_X86 is not set
+# CONFIG_XZ_DEC_POWERPC is not set
+# CONFIG_XZ_DEC_IA64 is not set
+# CONFIG_XZ_DEC_ARM is not set
+# CONFIG_XZ_DEC_ARMTHUMB is not set
+# CONFIG_XZ_DEC_SPARC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_DECOMPRESS_LZ4=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
+CONFIG_CPU_RMAP=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+# CONFIG_AVERAGE is not set
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+CONFIG_FONT_SUPPORT=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
diff --git a/tests/arm64/virt-v8/linux/virt-v8.dts b/tests/arm64/virt-v8/linux/virt-v8.dts
new file mode 100644
index 0000000..d2158fb
--- /dev/null
+++ b/tests/arm64/virt-v8/linux/virt-v8.dts
@@ -0,0 +1,153 @@
+
+/dts-v1/;
+
+/ {
+ model = "Virt-v8";
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ chosen { };
+
+ aliases { };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x0>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x8000fff8>;
+ };
+ cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x1>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x8000fff8>;
+ };
+ cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x2>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x8000fff8>;
+ };
+ cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x3>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x8000fff8>;
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x00000000 0x80000000 0 0x06000000>;
+ };
+
+ gic: interrupt-controller@2c001000 {
+ compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0x0 0x2c001000 0 0x1000>,
+ <0x0 0x2c002000 0 0x1000>,
+ <0x0 0x2c004000 0 0x2000>,
+ <0x0 0x2c006000 0 0x2000>;
+ interrupts = <1 9 0xf04>;
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <1 13 0xff01>,
+ <1 14 0xff01>,
+ <1 11 0xff01>,
+ <1 10 0xff01>;
+ clock-frequency = <100000000>;
+ };
+
+ pmu {
+ compatible = "arm,armv8-pmuv3";
+ interrupts = <0 60 4>,
+ <0 61 4>,
+ <0 62 4>,
+ <0 63 4>;
+ };
+
+ smb {
+ compatible = "simple-bus";
+ #address-cells = <2>; /* SMB chipselect number and offset */
+ #size-cells = <1>;
+
+ ranges = <0 0 0 0x40000000 0x04000000>;
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 63>;
+ interrupt-map = <0 0 0 &gic 0 0 4>,
+ <0 0 1 &gic 0 1 4>,
+ <0 0 2 &gic 0 2 4>,
+ <0 0 3 &gic 0 3 4>,
+ <0 0 4 &gic 0 4 4>,
+ <0 0 5 &gic 0 5 4>,
+ <0 0 6 &gic 0 6 4>,
+ <0 0 7 &gic 0 7 4>,
+ <0 0 8 &gic 0 8 4>,
+ <0 0 9 &gic 0 9 4>,
+ <0 0 10 &gic 0 10 4>,
+ <0 0 11 &gic 0 11 4>,
+ <0 0 12 &gic 0 12 4>,
+ <0 0 13 &gic 0 13 4>,
+ <0 0 14 &gic 0 14 4>,
+ <0 0 15 &gic 0 15 4>,
+ <0 0 16 &gic 0 16 4>,
+ <0 0 17 &gic 0 17 4>,
+ <0 0 18 &gic 0 18 4>,
+ <0 0 19 &gic 0 19 4>,
+ <0 0 20 &gic 0 20 4>,
+ <0 0 21 &gic 0 21 4>,
+ <0 0 22 &gic 0 22 4>,
+ <0 0 23 &gic 0 23 4>,
+ <0 0 24 &gic 0 24 4>,
+ <0 0 25 &gic 0 25 4>,
+ <0 0 26 &gic 0 26 4>,
+ <0 0 27 &gic 0 27 4>,
+ <0 0 28 &gic 0 28 4>,
+ <0 0 29 &gic 0 29 4>,
+ <0 0 30 &gic 0 30 4>,
+ <0 0 31 &gic 0 31 4>,
+ <0 0 32 &gic 0 32 4>,
+ <0 0 33 &gic 0 33 4>,
+ <0 0 34 &gic 0 34 4>,
+ <0 0 35 &gic 0 35 4>,
+ <0 0 36 &gic 0 36 4>,
+ <0 0 37 &gic 0 37 4>,
+ <0 0 38 &gic 0 38 4>,
+ <0 0 39 &gic 0 39 4>,
+ <0 0 40 &gic 0 40 4>,
+ <0 0 41 &gic 0 41 4>,
+ <0 0 42 &gic 0 42 4>;
+
+ virtio_net@0200000 {
+ compatible = "virtio,mmio";
+ reg = <0 0x00200000 0x10000>;
+ interrupts = <8>;
+ };
+
+ virtio_block@0400000 {
+ compatible = "virtio,mmio";
+ reg = <0 0x00400000 0x10000>;
+ interrupts = <9>;
+ };
+
+ virtio_console@0600000 {
+ compatible = "virtio,mmio";
+ reg = <0 0x00600000 0x10000>;
+ interrupts = <10>;

Anup Patel

unread,
Sep 15, 2013, 4:20:38 AM9/15/13
to Sukanto Ghosh, Xvisor Devel
Hi All,

Sukanto has already got this patches pre-reviewed from me.

I will merge the pull request soon.

Best Regards,
Anup
Reply all
Reply to author
Forward
0 new messages