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