Merge tag 'linux-kselftest-kunit-5.15-rc1' of git://git.kernel.org/pub/scm/linux...
[linux-2.6-microblaze.git] / arch / arm64 / kernel / head.S
index 6928cb6..1796245 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/asm_pointer_auth.h>
 #include <asm/assembler.h>
 #include <asm/boot.h>
+#include <asm/bug.h>
 #include <asm/ptrace.h>
 #include <asm/asm-offsets.h>
 #include <asm/cache.h>
@@ -176,7 +177,7 @@ SYM_CODE_END(preserve_boot_args)
  * to be composed of multiple pages. (This effectively scales the end index).
  *
  *     vstart: virtual address of start of range
- *     vend:   virtual address of end of range
+ *     vend:   virtual address of end of range - we map [vstart, vend]
  *     shift:  shift used to transform virtual address into index
  *     ptrs:   number of entries in page table
  *     istart: index in table corresponding to vstart
@@ -195,7 +196,7 @@ SYM_CODE_END(preserve_boot_args)
        and     \iend, \iend, \istart   // iend = (vend >> shift) & (ptrs - 1)
        mov     \istart, \ptrs
        mul     \istart, \istart, \count
-       add     \iend, \iend, \istart   // iend += (count - 1) * ptrs
+       add     \iend, \iend, \istart   // iend += count * ptrs
                                        // our entries span multiple tables
 
        lsr     \istart, \vstart, \shift
@@ -213,17 +214,18 @@ SYM_CODE_END(preserve_boot_args)
  *
  *     tbl:    location of page table
  *     rtbl:   address to be used for first level page table entry (typically tbl + PAGE_SIZE)
- *     vstart: start address to map
- *     vend:   end address to map - we map [vstart, vend]
+ *     vstart: virtual address of start of range
+ *     vend:   virtual address of end of range - we map [vstart, vend - 1]
  *     flags:  flags to use to map last level entries
  *     phys:   physical address corresponding to vstart - physical memory is contiguous
  *     pgds:   the number of pgd entries
  *
  * Temporaries:        istart, iend, tmp, count, sv - these need to be different registers
- * Preserves:  vstart, vend, flags
- * Corrupts:   tbl, rtbl, istart, iend, tmp, count, sv
+ * Preserves:  vstart, flags
+ * Corrupts:   tbl, rtbl, vend, istart, iend, tmp, count, sv
  */
        .macro map_memory, tbl, rtbl, vstart, vend, flags, phys, pgds, istart, iend, tmp, count, sv
+       sub \vend, \vend, #1
        add \rtbl, \tbl, #PAGE_SIZE
        mov \sv, \rtbl
        mov \count, #0
@@ -353,7 +355,6 @@ SYM_FUNC_START_LOCAL(__create_page_tables)
 #endif
 1:
        ldr_l   x4, idmap_ptrs_per_pgd
-       mov     x5, x3                          // __pa(__idmap_text_start)
        adr_l   x6, __idmap_text_end            // __pa(__idmap_text_end)
 
        map_memory x0, x1, x3, x6, x7, x3, x4, x10, x11, x12, x13, x14
@@ -390,28 +391,48 @@ SYM_FUNC_START_LOCAL(__create_page_tables)
        ret     x28
 SYM_FUNC_END(__create_page_tables)
 
+       /*
+        * Initialize CPU registers with task-specific and cpu-specific context.
+        *
+        * Create a final frame record at task_pt_regs(current)->stackframe, so
+        * that the unwinder can identify the final frame record of any task by
+        * its location in the task stack. We reserve the entire pt_regs space
+        * for consistency with user tasks and kthreads.
+        */
+       .macro  init_cpu_task tsk, tmp1, tmp2
+       msr     sp_el0, \tsk
+
+       ldr     \tmp1, [\tsk, #TSK_STACK]
+       add     sp, \tmp1, #THREAD_SIZE
+       sub     sp, sp, #PT_REGS_SIZE
+
+       stp     xzr, xzr, [sp, #S_STACKFRAME]
+       add     x29, sp, #S_STACKFRAME
+
+       scs_load \tsk
+
+       adr_l   \tmp1, __per_cpu_offset
+       ldr     w\tmp2, [\tsk, #TSK_CPU]
+       ldr     \tmp1, [\tmp1, \tmp2, lsl #3]
+       set_this_cpu_offset \tmp1
+       .endm
+
 /*
  * The following fragment of code is executed with the MMU enabled.
  *
  *   x0 = __PHYS_OFFSET
  */
 SYM_FUNC_START_LOCAL(__primary_switched)
-       adrp    x4, init_thread_union
-       add     sp, x4, #THREAD_SIZE
-       adr_l   x5, init_task
-       msr     sp_el0, x5                      // Save thread_info
+       adr_l   x4, init_task
+       init_cpu_task x4, x5, x6
 
        adr_l   x8, vectors                     // load VBAR_EL1 with virtual
        msr     vbar_el1, x8                    // vector table address
        isb
 
-       stp     xzr, x30, [sp, #-16]!
+       stp     x29, x30, [sp, #-16]!
        mov     x29, sp
 
-#ifdef CONFIG_SHADOW_CALL_STACK
-       adr_l   scs_sp, init_shadow_call_stack  // Set shadow call stack
-#endif
-
        str_l   x21, __fdt_pointer, x5          // Save FDT pointer
 
        ldr_l   x4, kimage_vaddr                // Save the offset between
@@ -443,10 +464,9 @@ SYM_FUNC_START_LOCAL(__primary_switched)
 0:
 #endif
        bl      switch_to_vhe                   // Prefer VHE if possible
-       add     sp, sp, #16
-       mov     x29, #0
-       mov     x30, #0
-       b       start_kernel
+       ldp     x29, x30, [sp], #16
+       bl      start_kernel
+       ASM_BUG()
 SYM_FUNC_END(__primary_switched)
 
        .pushsection ".rodata", "a"
@@ -548,7 +568,7 @@ SYM_FUNC_START_LOCAL(set_cpu_boot_mode_flag)
        cmp     w0, #BOOT_CPU_MODE_EL2
        b.ne    1f
        add     x1, x1, #4
-1:     str     w0, [x1]                        // This CPU has booted in EL1
+1:     str     w0, [x1]                        // Save CPU boot mode
        dmb     sy
        dc      ivac, x1                        // Invalidate potentially stale cache line
        ret
@@ -629,21 +649,17 @@ SYM_FUNC_START_LOCAL(__secondary_switched)
        isb
 
        adr_l   x0, secondary_data
-       ldr     x1, [x0, #CPU_BOOT_STACK]       // get secondary_data.stack
-       cbz     x1, __secondary_too_slow
-       mov     sp, x1
        ldr     x2, [x0, #CPU_BOOT_TASK]
        cbz     x2, __secondary_too_slow
-       msr     sp_el0, x2
-       scs_load x2, x3
-       mov     x29, #0
-       mov     x30, #0
+
+       init_cpu_task x2, x1, x3
 
 #ifdef CONFIG_ARM64_PTR_AUTH
        ptrauth_keys_init_cpu x2, x3, x4, x5
 #endif
 
-       b       secondary_start_kernel
+       bl      secondary_start_kernel
+       ASM_BUG()
 SYM_FUNC_END(__secondary_switched)
 
 SYM_FUNC_START_LOCAL(__secondary_too_slow)