]> Pileus Git - ~andy/linux/blobdiff - arch/arm64/kernel/head.S
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[~andy/linux] / arch / arm64 / kernel / head.S
index 7090c126797cb27e3db102e830d5de72c14c3310..7009387348b7c416f9dc8732a18c7563eac4af4e 100644 (file)
 
 ENTRY(stext)
        mov     x21, x0                         // x21=FDT
+       bl      el2_setup                       // Drop to EL1, w20=cpu_boot_mode
        bl      __calc_phys_offset              // x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET
-       bl      el2_setup                       // Drop to EL1
+       bl      set_cpu_boot_mode_flag
        mrs     x22, midr_el1                   // x22=cpuid
        mov     x0, x22
        bl      lookup_processor_type
@@ -150,21 +151,30 @@ ENDPROC(stext)
 /*
  * If we're fortunate enough to boot at EL2, ensure that the world is
  * sane before dropping to EL1.
+ *
+ * Returns either BOOT_CPU_MODE_EL1 or BOOT_CPU_MODE_EL2 in x20 if
+ * booted in EL1 or EL2 respectively.
  */
 ENTRY(el2_setup)
        mrs     x0, CurrentEL
        cmp     x0, #PSR_MODE_EL2t
        ccmp    x0, #PSR_MODE_EL2h, #0x4, ne
-       ldr     x0, =__boot_cpu_mode            // Compute __boot_cpu_mode
-       add     x0, x0, x28
-       b.eq    1f
-       str     wzr, [x0]                       // Remember we don't have EL2...
+       b.ne    1f
+       mrs     x0, sctlr_el2
+CPU_BE(        orr     x0, x0, #(1 << 25)      )       // Set the EE bit for EL2
+CPU_LE(        bic     x0, x0, #(1 << 25)      )       // Clear the EE bit for EL2
+       msr     sctlr_el2, x0
+       b       2f
+1:     mrs     x0, sctlr_el1
+CPU_BE(        orr     x0, x0, #(3 << 24)      )       // Set the EE and E0E bits for EL1
+CPU_LE(        bic     x0, x0, #(3 << 24)      )       // Clear the EE and E0E bits for EL1
+       msr     sctlr_el1, x0
+       mov     w20, #BOOT_CPU_MODE_EL1         // This cpu booted in EL1
+       isb
        ret
 
        /* Hyp configuration. */
-1:     ldr     w1, =BOOT_CPU_MODE_EL2
-       str     w1, [x0, #4]                    // This CPU has EL2
-       mov     x0, #(1 << 31)                  // 64-bit EL1
+2:     mov     x0, #(1 << 31)                  // 64-bit EL1
        msr     hcr_el2, x0
 
        /* Generic timers. */
@@ -181,7 +191,8 @@ ENTRY(el2_setup)
 
        /* sctlr_el1 */
        mov     x0, #0x0800                     // Set/clear RES{1,0} bits
-       movk    x0, #0x30d0, lsl #16
+CPU_BE(        movk    x0, #0x33d0, lsl #16    )       // Set EE and E0E on BE systems
+CPU_LE(        movk    x0, #0x30d0, lsl #16    )       // Clear EE and E0E on LE systems
        msr     sctlr_el1, x0
 
        /* Coprocessor traps. */
@@ -204,9 +215,24 @@ ENTRY(el2_setup)
                      PSR_MODE_EL1h)
        msr     spsr_el2, x0
        msr     elr_el2, lr
+       mov     w20, #BOOT_CPU_MODE_EL2         // This CPU booted in EL2
        eret
 ENDPROC(el2_setup)
 
+/*
+ * Sets the __boot_cpu_mode flag depending on the CPU boot mode passed
+ * in x20. See arch/arm64/include/asm/virt.h for more info.
+ */
+ENTRY(set_cpu_boot_mode_flag)
+       ldr     x1, =__boot_cpu_mode            // Compute __boot_cpu_mode
+       add     x1, x1, x28
+       cmp     w20, #BOOT_CPU_MODE_EL2
+       b.ne    1f
+       add     x1, x1, #4
+1:     str     w20, [x1]                       // This CPU has booted in EL1
+       ret
+ENDPROC(set_cpu_boot_mode_flag)
+
 /*
  * We need to find out the CPU boot mode long after boot, so we need to
  * store it in a writable variable.
@@ -225,7 +251,6 @@ ENTRY(__boot_cpu_mode)
        .quad   PAGE_OFFSET
 
 #ifdef CONFIG_SMP
-       .pushsection    .smp.pen.text, "ax"
        .align  3
 1:     .quad   .
        .quad   secondary_holding_pen_release
@@ -235,8 +260,9 @@ ENTRY(__boot_cpu_mode)
         * cores are held until we're ready for them to initialise.
         */
 ENTRY(secondary_holding_pen)
-       bl      __calc_phys_offset              // x24=phys offset
-       bl      el2_setup                       // Drop to EL1
+       bl      el2_setup                       // Drop to EL1, w20=cpu_boot_mode
+       bl      __calc_phys_offset              // x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET
+       bl      set_cpu_boot_mode_flag
        mrs     x0, mpidr_el1
        ldr     x1, =MPIDR_HWID_BITMASK
        and     x0, x0, x1
@@ -250,7 +276,16 @@ pen:       ldr     x4, [x3]
        wfe
        b       pen
 ENDPROC(secondary_holding_pen)
-       .popsection
+
+       /*
+        * Secondary entry point that jumps straight into the kernel. Only to
+        * be used where CPUs are brought online dynamically by the kernel.
+        */
+ENTRY(secondary_entry)
+       bl      __calc_phys_offset              // x2=phys offset
+       bl      el2_setup                       // Drop to EL1
+       b       secondary_startup
+ENDPROC(secondary_entry)
 
 ENTRY(secondary_startup)
        /*