From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33218) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VstYk-0005qP-DL for qemu-devel@nongnu.org; Tue, 17 Dec 2013 07:15:39 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VstYb-0001Xx-Sg for qemu-devel@nongnu.org; Tue, 17 Dec 2013 07:15:34 -0500 Received: from mnementh.archaic.org.uk ([2001:8b0:1d0::1]:43519) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VstYb-0001Xh-Ko for qemu-devel@nongnu.org; Tue, 17 Dec 2013 07:15:25 -0500 From: Peter Maydell Date: Tue, 17 Dec 2013 12:15:21 +0000 Message-Id: <1387282522-11280-7-git-send-email-peter.maydell@linaro.org> In-Reply-To: <1387282522-11280-1-git-send-email-peter.maydell@linaro.org> References: <1387282522-11280-1-git-send-email-peter.maydell@linaro.org> Subject: [Qemu-devel] [PATCH v2 6/7] hw/arm/boot: Add boot support for AArch64 processor List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kvmarm@lists.cs.columbia.edu, Christoffer Dall , patches@linaro.org From: "Mian M. Hamayun" This commit adds support for booting a single AArch64 CPU by setting appropriate registers. The bootloader includes placehoders for Board-ID that are used to implement uniform indexing across different bootloaders. Signed-off-by: Mian M. Hamayun Signed-off-by: Peter Maydell Message-id: 1385645602-18662-7-git-send-email-peter.maydell@linaro.org [PMM: * updated to use ARMInsnFixup style bootloader fragments * dropped virt.c additions * use runtime checks for "is this an AArch64 core" rather than ifdefs * drop some unnecessary setting of registers in reset hook ] Signed-off-by: Peter Maydell Reviewed-by: Christoffer Dall --- hw/arm/boot.c | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 0c05a64..90e9534 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -17,8 +17,13 @@ #include "sysemu/device_tree.h" #include "qemu/config-file.h" +/* Kernel boot protocol is specified in the kernel docs + * Documentation/arm/Booting and Documentation/arm64/booting.txt + * They have different preferred image load offsets from system RAM base. + */ #define KERNEL_ARGS_ADDR 0x100 #define KERNEL_LOAD_ADDR 0x00010000 +#define KERNEL64_LOAD_ADDR 0x00080000 typedef enum { FIXUP_NONE = 0, /* do nothing */ @@ -37,6 +42,20 @@ typedef struct ARMInsnFixup { FixupType fixup; } ARMInsnFixup; +static const ARMInsnFixup bootloader_aarch64[] = { + { 0x580000c0 }, /* ldr x0, arg ; Load the lower 32-bits of DTB */ + { 0xaa1f03e1 }, /* mov x1, xzr */ + { 0xaa1f03e2 }, /* mov x2, xzr */ + { 0xaa1f03e3 }, /* mov x3, xzr */ + { 0x58000084 }, /* ldr x4, entry ; Load the lower 32-bits of kernel entry */ + { 0xd61f0080 }, /* br x4 ; Jump to the kernel entry point */ + { 0, FIXUP_ARGPTR }, /* arg: .word @DTB Lower 32-bits */ + { 0 }, /* .word @DTB Higher 32-bits */ + { 0, FIXUP_ENTRYPOINT }, /* entry: .word @Kernel Entry Lower 32-bits */ + { 0 }, /* .word @Kernel Entry Higher 32-bits */ + { 0, FIXUP_TERMINATOR } +}; + /* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */ static const ARMInsnFixup bootloader[] = { { 0xe3a00000 }, /* mov r0, #0 */ @@ -396,7 +415,12 @@ static void do_cpu_reset(void *opaque) env->thumb = info->entry & 1; } else { if (CPU(cpu) == first_cpu) { - env->regs[15] = info->loader_start; + if (env->aarch64) { + env->pc = info->loader_start; + } else { + env->regs[15] = info->loader_start; + } + if (!info->dtb_filename) { if (old_param) { set_kernel_args_old(info); @@ -418,8 +442,9 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) int initrd_size; int is_linux = 0; uint64_t elf_entry; - hwaddr entry; + hwaddr entry, kernel_load_offset; int big_endian; + static const ARMInsnFixup *primary_loader; /* Load the kernel. */ if (!info->kernel_filename) { @@ -429,6 +454,14 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) return; } + if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { + primary_loader = bootloader_aarch64; + kernel_load_offset = KERNEL64_LOAD_ADDR; + } else { + primary_loader = bootloader; + kernel_load_offset = KERNEL_LOAD_ADDR; + } + info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb"); if (!info->secondary_cpu_reset_hook) { @@ -469,9 +502,9 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) &is_linux); } if (kernel_size < 0) { - entry = info->loader_start + KERNEL_LOAD_ADDR; + entry = info->loader_start + kernel_load_offset; kernel_size = load_image_targphys(info->kernel_filename, entry, - info->ram_size - KERNEL_LOAD_ADDR); + info->ram_size - kernel_load_offset); is_linux = 1; } if (kernel_size < 0) { @@ -532,7 +565,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) fixupcontext[FIXUP_ENTRYPOINT] = entry; write_bootloader("bootloader", info->loader_start, - bootloader, fixupcontext); + primary_loader, fixupcontext); if (info->nb_cpus > 1) { info->write_secondary_boot(cpu, info); -- 1.8.5