[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC v1 2/2] arm: boot: Add EL jump-down code for Linux
From: |
Peter Crosthwaite |
Subject: |
[Qemu-devel] [RFC v1 2/2] arm: boot: Add EL jump-down code for Linux |
Date: |
Mon, 18 Aug 2014 17:54:26 -0700 |
Linux should boot in EL2 or EL1. If in EL3, jump down before handing
off to Linux.
Signed-off-by: Peter Crosthwaite <address@hidden>
---
hw/arm/boot.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 840f5da..f1f6365 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -35,6 +35,7 @@ typedef enum {
FIXUP_GIC_CPU_IF, /* overwrite with GIC CPU interface address */
FIXUP_BOOTREG, /* overwrite with boot register address */
FIXUP_DSB, /* overwrite with correct DSB insn for cpu */
+ FIXUP_EL, /* overwrite with kernel entry EL */
FIXUP_MAX,
} FixupType;
@@ -46,6 +47,20 @@ typedef struct ARMInsnFixup {
} ARMInsnFixup;
static const ARMInsnFixup bootloader_aarch64[] = {
+ { 0xd5384240 }, /* mrs x0, currentel */
+ { 0x7100301f }, /* cmp w0, #0xc */
+ { 0x54000001 + (9 << 5) }, /* b.ne ELx_start */
+/* Jump down from EL3 to ELx */
+ { 0x10000001 + (9 << 5) }, /* adr x1, ELx_start */
+ { 0xd53e1100 }, /* mrs x0, scr_el3 */
+ { 0xb2400000 }, /* orr x0, x0, #0x1 - SCR.NS */
+ { 0xb2780000 }, /* orr x0, x0, #0x80 - SCR.HCE */
+ { 0xd51e1100 }, /* msr scr_el3, x0 */
+ { 0xd2807820, FIXUP_EL, 7, 2 }, /* movz x0, 0x3c1 (+ EL<<2) */
+ { 0xd51e4000 }, /* msr spsr_el3, x0 */
+ { 0xd51e4021 }, /* msr elr_el3, x1 */
+ { 0xd69f03e0 }, /* eret */
+/* ELx_start: */
{ 0x580000c0 }, /* ldr x0, arg ; Load the lower 32-bits of DTB */
{ 0xaa1f03e1 }, /* mov x1, xzr */
{ 0xaa1f03e2 }, /* mov x2, xzr */
@@ -141,6 +156,7 @@ static void write_bootloader(const char *name, hwaddr addr,
case FIXUP_GIC_CPU_IF:
case FIXUP_BOOTREG:
case FIXUP_DSB:
+ case FIXUP_EL:
insn = deposit32(insn, shift, length, fixupcontext[fixup]);
break;
default:
@@ -583,6 +599,11 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info
*info)
}
fixupcontext[FIXUP_ENTRYPOINT] = entry;
+ fixupcontext[FIXUP_EL] = 1;
+ if (arm_feature(&cpu->env, ARM_FEATURE_EL2)) {
+ fixupcontext[FIXUP_EL] = 2;
+ }
+
write_bootloader("bootloader", info->loader_start,
primary_loader, fixupcontext);
--
2.0.1.1.gfbfc394