1
From 7717831c207318babaaf511fecb12298766592c7 Mon Sep 17 00:00:00 2001
2
From: "Mian M. Hamayun" <m.hamayun@virtualopensystems.com>
3
Date: Tue, 17 Dec 2013 19:42:30 +0000
4
Subject: [PATCH 22/49] hw/arm/boot: Add boot support for AArch64 processor
6
This commit adds support for booting a single AArch64 CPU by setting
7
appropriate registers. The bootloader includes placeholders for Board-ID
8
that are used to implement uniform indexing across different bootloaders.
10
Signed-off-by: Mian M. Hamayun <m.hamayun@virtualopensystems.com>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 1385645602-18662-7-git-send-email-peter.maydell@linaro.org
14
* updated to use ARMInsnFixup style bootloader fragments
15
* dropped virt.c additions
16
* use runtime checks for "is this an AArch64 core" rather than ifdefs
17
* drop some unnecessary setting of registers in reset hook
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
22
hw/arm/boot.c | 43 ++++++++++++++++++++++++++++++++++++++-----
23
1 file changed, 38 insertions(+), 5 deletions(-)
25
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
26
index 0c05a64..90e9534 100644
30
#include "sysemu/device_tree.h"
31
#include "qemu/config-file.h"
33
+/* Kernel boot protocol is specified in the kernel docs
34
+ * Documentation/arm/Booting and Documentation/arm64/booting.txt
35
+ * They have different preferred image load offsets from system RAM base.
37
#define KERNEL_ARGS_ADDR 0x100
38
#define KERNEL_LOAD_ADDR 0x00010000
39
+#define KERNEL64_LOAD_ADDR 0x00080000
42
FIXUP_NONE = 0, /* do nothing */
43
@@ -37,6 +42,20 @@ typedef struct ARMInsnFixup {
47
+static const ARMInsnFixup bootloader_aarch64[] = {
48
+ { 0x580000c0 }, /* ldr x0, arg ; Load the lower 32-bits of DTB */
49
+ { 0xaa1f03e1 }, /* mov x1, xzr */
50
+ { 0xaa1f03e2 }, /* mov x2, xzr */
51
+ { 0xaa1f03e3 }, /* mov x3, xzr */
52
+ { 0x58000084 }, /* ldr x4, entry ; Load the lower 32-bits of kernel entry */
53
+ { 0xd61f0080 }, /* br x4 ; Jump to the kernel entry point */
54
+ { 0, FIXUP_ARGPTR }, /* arg: .word @DTB Lower 32-bits */
55
+ { 0 }, /* .word @DTB Higher 32-bits */
56
+ { 0, FIXUP_ENTRYPOINT }, /* entry: .word @Kernel Entry Lower 32-bits */
57
+ { 0 }, /* .word @Kernel Entry Higher 32-bits */
58
+ { 0, FIXUP_TERMINATOR }
61
/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */
62
static const ARMInsnFixup bootloader[] = {
63
{ 0xe3a00000 }, /* mov r0, #0 */
64
@@ -396,7 +415,12 @@ static void do_cpu_reset(void *opaque)
65
env->thumb = info->entry & 1;
67
if (CPU(cpu) == first_cpu) {
68
- env->regs[15] = info->loader_start;
70
+ env->pc = info->loader_start;
72
+ env->regs[15] = info->loader_start;
75
if (!info->dtb_filename) {
77
set_kernel_args_old(info);
78
@@ -418,8 +442,9 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
83
+ hwaddr entry, kernel_load_offset;
85
+ static const ARMInsnFixup *primary_loader;
87
/* Load the kernel. */
88
if (!info->kernel_filename) {
89
@@ -429,6 +454,14 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
93
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
94
+ primary_loader = bootloader_aarch64;
95
+ kernel_load_offset = KERNEL64_LOAD_ADDR;
97
+ primary_loader = bootloader;
98
+ kernel_load_offset = KERNEL_LOAD_ADDR;
101
info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
103
if (!info->secondary_cpu_reset_hook) {
104
@@ -469,9 +502,9 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
107
if (kernel_size < 0) {
108
- entry = info->loader_start + KERNEL_LOAD_ADDR;
109
+ entry = info->loader_start + kernel_load_offset;
110
kernel_size = load_image_targphys(info->kernel_filename, entry,
111
- info->ram_size - KERNEL_LOAD_ADDR);
112
+ info->ram_size - kernel_load_offset);
115
if (kernel_size < 0) {
116
@@ -532,7 +565,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
117
fixupcontext[FIXUP_ENTRYPOINT] = entry;
119
write_bootloader("bootloader", info->loader_start,
120
- bootloader, fixupcontext);
121
+ primary_loader, fixupcontext);
123
if (info->nb_cpus > 1) {
124
info->write_secondary_boot(cpu, info);