1 /* SPDX-License-Identifier: GPL-2.0 */
3 * relocate_kernel.S for kexec
5 * Copyright (C) 2022 Loongson Technology Corporation Limited
8 #include <linux/kexec.h>
11 #include <asm/asmmacro.h>
12 #include <asm/regdef.h>
13 #include <asm/loongarch.h>
14 #include <asm/stackframe.h>
15 #include <asm/addrspace.h>
17 SYM_CODE_START(relocate_new_kernel)
20 * a0: EFI boot flag for the new kernel
21 * a1: Command line pointer for the new kernel
22 * a2: System table pointer for the new kernel
23 * a3: Start address to jump to after relocation
24 * a4: Pointer to the current indirection page entry
29 * In case of a kdump/crash kernel, the indirection page is not
30 * populated as the kernel is directly copied to a reserved location
36 PTR_ADDI s0, s0, SZREG
38 /* destination page */
39 andi s2, s1, IND_DESTINATION
42 and s3, s1, t0 /* store destination addr in s3 */
46 /* indirection page, update s0 */
47 andi s2, s1, IND_INDIRECTION
61 andi s2, s1, IND_SOURCE
62 beqz s2, process_entry
65 li.w s5, (1 << _PAGE_SHIFT) / SZREG
68 /* copy page word by word */
71 PTR_ADDI s3, s3, SZREG
72 PTR_ADDI s1, s1, SZREG
74 beqz s5, process_entry
82 * Jump to the new kernel,
83 * make sure the values of a0, a1, a2 and a3 are not changed.
86 SYM_CODE_END(relocate_new_kernel)
90 * Other CPUs should wait until code is relocated and
91 * then start at the entry point from LOONGARCH_IOCSR_MBUF0.
93 SYM_CODE_START(kexec_smp_wait)
95 1: li.w t0, 0x100 /* wait for init loop */
96 2: addi.w t0, t0, -1 /* limit mailbox access */
98 li.w t1, LOONGARCH_IOCSR_MBUF0
99 iocsrrd.w s0, t1 /* check PC as an indicator */
101 iocsrrd.d s0, t1 /* get PC via mailbox */
104 or s0, s0, t0 /* s0 = TO_CACHE(s0) */
105 jr s0 /* jump to initial PC */
106 SYM_CODE_END(kexec_smp_wait)
109 relocate_new_kernel_end:
112 SYM_DATA(relocate_new_kernel_size, .long relocate_new_kernel_end - relocate_new_kernel)