qemu-devel
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]