Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * relocate_kernel.S for kexec
0004  * Created by <nschichan@corp.free.fr> on Thu Oct 12 17:49:57 2006
0005  */
0006 
0007 #include <asm/asm.h>
0008 #include <asm/asmmacro.h>
0009 #include <asm/regdef.h>
0010 #include <asm/mipsregs.h>
0011 #include <asm/stackframe.h>
0012 #include <asm/addrspace.h>
0013 
0014 #include <kernel-entry-init.h>
0015 
0016 LEAF(relocate_new_kernel)
0017     PTR_L a0,   arg0
0018     PTR_L a1,   arg1
0019     PTR_L a2,   arg2
0020     PTR_L a3,   arg3
0021 
0022     PTR_L       s0, kexec_indirection_page
0023     PTR_L       s1, kexec_start_address
0024 
0025 process_entry:
0026     PTR_L       s2, (s0)
0027     PTR_ADDIU   s0, s0, SZREG
0028 
0029     /*
0030      * In case of a kdump/crash kernel, the indirection page is not
0031      * populated as the kernel is directly copied to a reserved location
0032      */
0033     beqz        s2, done
0034 
0035     /* destination page */
0036     and     s3, s2, 0x1
0037     beq     s3, zero, 1f
0038     and     s4, s2, ~0x1    /* store destination addr in s4 */
0039     b       process_entry
0040 
0041 1:
0042     /* indirection page, update s0  */
0043     and     s3, s2, 0x2
0044     beq     s3, zero, 1f
0045     and     s0, s2, ~0x2
0046     b       process_entry
0047 
0048 1:
0049     /* done page */
0050     and     s3, s2, 0x4
0051     beq     s3, zero, 1f
0052     b       done
0053 1:
0054     /* source page */
0055     and     s3, s2, 0x8
0056     beq     s3, zero, process_entry
0057     and     s2, s2, ~0x8
0058     li      s6, (1 << _PAGE_SHIFT) / SZREG
0059 
0060 copy_word:
0061     /* copy page word by word */
0062     REG_L       s5, (s2)
0063     REG_S       s5, (s4)
0064     PTR_ADDIU   s4, s4, SZREG
0065     PTR_ADDIU   s2, s2, SZREG
0066     LONG_ADDIU  s6, s6, -1
0067     beq     s6, zero, process_entry
0068     b       copy_word
0069     b       process_entry
0070 
0071 done:
0072 #ifdef CONFIG_SMP
0073     /* kexec_flag reset is signal to other CPUs what kernel
0074        was moved to it's location. Note - we need relocated address
0075        of kexec_flag.  */
0076 
0077     bal     1f
0078  1: move        t1,ra;
0079     PTR_LA      t2,1b
0080     PTR_LA      t0,kexec_flag
0081     PTR_SUB     t0,t0,t2;
0082     PTR_ADD     t0,t1,t0;
0083     LONG_S      zero,(t0)
0084 #endif
0085 
0086 #ifdef CONFIG_CPU_CAVIUM_OCTEON
0087     /* We need to flush I-cache before jumping to new kernel.
0088      * Unfortunately, this code is cpu-specific.
0089      */
0090     .set push
0091     .set noreorder
0092     syncw
0093     syncw
0094     synci       0($0)
0095     .set pop
0096 #else
0097     sync
0098 #endif
0099     /* jump to kexec_start_address */
0100     j       s1
0101     END(relocate_new_kernel)
0102 
0103 #ifdef CONFIG_SMP
0104 /*
0105  * Other CPUs should wait until code is relocated and
0106  * then start at entry (?) point.
0107  */
0108 LEAF(kexec_smp_wait)
0109     PTR_L       a0, s_arg0
0110     PTR_L       a1, s_arg1
0111     PTR_L       a2, s_arg2
0112     PTR_L       a3, s_arg3
0113     PTR_L       s1, kexec_start_address
0114 
0115     /* Non-relocated address works for args and kexec_start_address ( old
0116      * kernel is not overwritten). But we need relocated address of
0117      * kexec_flag.
0118      */
0119 
0120     bal     1f
0121 1:  move        t1,ra;
0122     PTR_LA      t2,1b
0123     PTR_LA      t0,kexec_flag
0124     PTR_SUB     t0,t0,t2;
0125     PTR_ADD     t0,t1,t0;
0126 
0127 1:  LONG_L      s0, (t0)
0128     bne     s0, zero,1b
0129 
0130 #ifdef USE_KEXEC_SMP_WAIT_FINAL
0131     kexec_smp_wait_final
0132 #else
0133     sync
0134 #endif
0135     j       s1
0136     END(kexec_smp_wait)
0137 #endif
0138 
0139 #ifdef __mips64
0140        /* all PTR's must be aligned to 8 byte in 64-bit mode */
0141        .align  3
0142 #endif
0143 
0144 /* All parameters to new kernel are passed in registers a0-a3.
0145  * kexec_args[0..3] are used to prepare register values.
0146  */
0147 
0148 kexec_args:
0149     EXPORT(kexec_args)
0150 arg0:   PTR_WD      0x0
0151 arg1:   PTR_WD      0x0
0152 arg2:   PTR_WD      0x0
0153 arg3:   PTR_WD      0x0
0154     .size   kexec_args,PTRSIZE*4
0155 
0156 #ifdef CONFIG_SMP
0157 /*
0158  * Secondary CPUs may have different kernel parameters in
0159  * their registers a0-a3. secondary_kexec_args[0..3] are used
0160  * to prepare register values.
0161  */
0162 secondary_kexec_args:
0163     EXPORT(secondary_kexec_args)
0164 s_arg0: PTR_WD      0x0
0165 s_arg1: PTR_WD      0x0
0166 s_arg2: PTR_WD      0x0
0167 s_arg3: PTR_WD      0x0
0168     .size   secondary_kexec_args,PTRSIZE*4
0169 kexec_flag:
0170     LONG        0x1
0171 
0172 #endif
0173 
0174 kexec_start_address:
0175     EXPORT(kexec_start_address)
0176     PTR_WD      0x0
0177     .size       kexec_start_address, PTRSIZE
0178 
0179 kexec_indirection_page:
0180     EXPORT(kexec_indirection_page)
0181     PTR_WD      0
0182     .size       kexec_indirection_page, PTRSIZE
0183 
0184 relocate_new_kernel_end:
0185 
0186 relocate_new_kernel_size:
0187     EXPORT(relocate_new_kernel_size)
0188     PTR_WD      relocate_new_kernel_end - relocate_new_kernel
0189     .size       relocate_new_kernel_size, PTRSIZE