root/arch/mips/kernel/relocate_kernel.S

/* [<][>][^][v][top][bottom][index][help] */
   1 /* SPDX-License-Identifier: GPL-2.0-only */
   2 /*
   3  * relocate_kernel.S for kexec
   4  * Created by <nschichan@corp.free.fr> on Thu Oct 12 17:49:57 2006
   5  */
   6 
   7 #include <asm/asm.h>
   8 #include <asm/asmmacro.h>
   9 #include <asm/regdef.h>
  10 #include <asm/mipsregs.h>
  11 #include <asm/stackframe.h>
  12 #include <asm/addrspace.h>
  13 
  14 LEAF(relocate_new_kernel)
  15         PTR_L a0,       arg0
  16         PTR_L a1,       arg1
  17         PTR_L a2,       arg2
  18         PTR_L a3,       arg3
  19 
  20         PTR_L           s0, kexec_indirection_page
  21         PTR_L           s1, kexec_start_address
  22 
  23 process_entry:
  24         PTR_L           s2, (s0)
  25         PTR_ADDIU       s0, s0, SZREG
  26 
  27         /*
  28          * In case of a kdump/crash kernel, the indirection page is not
  29          * populated as the kernel is directly copied to a reserved location
  30          */
  31         beqz            s2, done
  32 
  33         /* destination page */
  34         and             s3, s2, 0x1
  35         beq             s3, zero, 1f
  36         and             s4, s2, ~0x1    /* store destination addr in s4 */
  37         b               process_entry
  38 
  39 1:
  40         /* indirection page, update s0  */
  41         and             s3, s2, 0x2
  42         beq             s3, zero, 1f
  43         and             s0, s2, ~0x2
  44         b               process_entry
  45 
  46 1:
  47         /* done page */
  48         and             s3, s2, 0x4
  49         beq             s3, zero, 1f
  50         b               done
  51 1:
  52         /* source page */
  53         and             s3, s2, 0x8
  54         beq             s3, zero, process_entry
  55         and             s2, s2, ~0x8
  56         li              s6, (1 << _PAGE_SHIFT) / SZREG
  57 
  58 copy_word:
  59         /* copy page word by word */
  60         REG_L           s5, (s2)
  61         REG_S           s5, (s4)
  62         PTR_ADDIU       s4, s4, SZREG
  63         PTR_ADDIU       s2, s2, SZREG
  64         LONG_ADDIU      s6, s6, -1
  65         beq             s6, zero, process_entry
  66         b               copy_word
  67         b               process_entry
  68 
  69 done:
  70 #ifdef CONFIG_SMP
  71         /* kexec_flag reset is signal to other CPUs what kernel
  72            was moved to it's location. Note - we need relocated address
  73            of kexec_flag.  */
  74 
  75         bal             1f
  76  1:     move            t1,ra;
  77         PTR_LA          t2,1b
  78         PTR_LA          t0,kexec_flag
  79         PTR_SUB         t0,t0,t2;
  80         PTR_ADD         t0,t1,t0;
  81         LONG_S          zero,(t0)
  82 #endif
  83 
  84 #ifdef CONFIG_CPU_CAVIUM_OCTEON
  85         /* We need to flush I-cache before jumping to new kernel.
  86          * Unfortunately, this code is cpu-specific.
  87          */
  88         .set push
  89         .set noreorder
  90         syncw
  91         syncw
  92         synci           0($0)
  93         .set pop
  94 #else
  95         sync
  96 #endif
  97         /* jump to kexec_start_address */
  98         j               s1
  99         END(relocate_new_kernel)
 100 
 101 #ifdef CONFIG_SMP
 102 /*
 103  * Other CPUs should wait until code is relocated and
 104  * then start at entry (?) point.
 105  */
 106 LEAF(kexec_smp_wait)
 107         PTR_L           a0, s_arg0
 108         PTR_L           a1, s_arg1
 109         PTR_L           a2, s_arg2
 110         PTR_L           a3, s_arg3
 111         PTR_L           s1, kexec_start_address
 112 
 113         /* Non-relocated address works for args and kexec_start_address ( old
 114          * kernel is not overwritten). But we need relocated address of
 115          * kexec_flag.
 116          */
 117 
 118         bal             1f
 119 1:      move            t1,ra;
 120         PTR_LA          t2,1b
 121         PTR_LA          t0,kexec_flag
 122         PTR_SUB         t0,t0,t2;
 123         PTR_ADD         t0,t1,t0;
 124 
 125 1:      LONG_L          s0, (t0)
 126         bne             s0, zero,1b
 127 
 128 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 129         .set push
 130         .set noreorder
 131         synci           0($0)
 132         .set pop
 133 #else
 134         sync
 135 #endif
 136         j               s1
 137         END(kexec_smp_wait)
 138 #endif
 139 
 140 #ifdef __mips64
 141        /* all PTR's must be aligned to 8 byte in 64-bit mode */
 142        .align  3
 143 #endif
 144 
 145 /* All parameters to new kernel are passed in registers a0-a3.
 146  * kexec_args[0..3] are used to prepare register values.
 147  */
 148 
 149 kexec_args:
 150         EXPORT(kexec_args)
 151 arg0:   PTR             0x0
 152 arg1:   PTR             0x0
 153 arg2:   PTR             0x0
 154 arg3:   PTR             0x0
 155         .size   kexec_args,PTRSIZE*4
 156 
 157 #ifdef CONFIG_SMP
 158 /*
 159  * Secondary CPUs may have different kernel parameters in
 160  * their registers a0-a3. secondary_kexec_args[0..3] are used
 161  * to prepare register values.
 162  */
 163 secondary_kexec_args:
 164         EXPORT(secondary_kexec_args)
 165 s_arg0: PTR             0x0
 166 s_arg1: PTR             0x0
 167 s_arg2: PTR             0x0
 168 s_arg3: PTR             0x0
 169         .size   secondary_kexec_args,PTRSIZE*4
 170 kexec_flag:
 171         LONG            0x1
 172 
 173 #endif
 174 
 175 kexec_start_address:
 176         EXPORT(kexec_start_address)
 177         PTR             0x0
 178         .size           kexec_start_address, PTRSIZE
 179 
 180 kexec_indirection_page:
 181         EXPORT(kexec_indirection_page)
 182         PTR             0
 183         .size           kexec_indirection_page, PTRSIZE
 184 
 185 relocate_new_kernel_end:
 186 
 187 relocate_new_kernel_size:
 188         EXPORT(relocate_new_kernel_size)
 189         PTR             relocate_new_kernel_end - relocate_new_kernel
 190         .size           relocate_new_kernel_size, PTRSIZE

/* [<][>][^][v][top][bottom][index][help] */