]> Git Repo - J-linux.git/blob - arch/loongarch/kernel/relocate_kernel.S
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / arch / loongarch / kernel / relocate_kernel.S
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * relocate_kernel.S for kexec
4  *
5  * Copyright (C) 2022 Loongson Technology Corporation Limited
6  */
7
8 #include <linux/kexec.h>
9
10 #include <asm/asm.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>
16
17 SYM_CODE_START(relocate_new_kernel)
18         UNWIND_HINT_UNDEFINED
19         /*
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
25          */
26         move            s0, a4
27
28         /*
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
31          */
32         beqz            s0, done
33
34 process_entry:
35         PTR_L           s1, s0, 0
36         PTR_ADDI        s0, s0, SZREG
37
38         /* destination page */
39         andi            s2, s1, IND_DESTINATION
40         beqz            s2, 1f
41         li.w            t0, ~0x1
42         and             s3, s1, t0      /* store destination addr in s3 */
43         b               process_entry
44
45 1:
46         /* indirection page, update s0  */
47         andi            s2, s1, IND_INDIRECTION
48         beqz            s2, 1f
49         li.w            t0, ~0x2
50         and             s0, s1, t0
51         b               process_entry
52
53 1:
54         /* done page */
55         andi            s2, s1, IND_DONE
56         beqz            s2, 1f
57         b               done
58
59 1:
60         /* source page */
61         andi            s2, s1, IND_SOURCE
62         beqz            s2, process_entry
63         li.w            t0, ~0x8
64         and             s1, s1, t0
65         li.w            s5, (1 << _PAGE_SHIFT) / SZREG
66
67 copy_word:
68         /* copy page word by word */
69         REG_L           s4, s1, 0
70         REG_S           s4, s3, 0
71         PTR_ADDI        s3, s3, SZREG
72         PTR_ADDI        s1, s1, SZREG
73         LONG_ADDI       s5, s5, -1
74         beqz            s5, process_entry
75         b               copy_word
76
77 done:
78         ibar            0
79         dbar            0
80
81         /*
82          * Jump to the new kernel,
83          * make sure the values of a0, a1, a2 and a3 are not changed.
84          */
85         jr              a3
86 SYM_CODE_END(relocate_new_kernel)
87
88 #ifdef CONFIG_SMP
89 /*
90  * Other CPUs should wait until code is relocated and
91  * then start at the entry point from LOONGARCH_IOCSR_MBUF0.
92  */
93 SYM_CODE_START(kexec_smp_wait)
94         UNWIND_HINT_UNDEFINED
95 1:      li.w            t0, 0x100                       /* wait for init loop */
96 2:      addi.w          t0, t0, -1                      /* limit mailbox access */
97         bnez            t0, 2b
98         li.w            t1, LOONGARCH_IOCSR_MBUF0
99         iocsrrd.w       s0, t1                          /* check PC as an indicator */
100         beqz            s0, 1b
101         iocsrrd.d       s0, t1                          /* get PC via mailbox */
102
103         li.d            t0, CACHE_BASE
104         or              s0, s0, t0                      /* s0 = TO_CACHE(s0) */
105         jr              s0                              /* jump to initial PC */
106 SYM_CODE_END(kexec_smp_wait)
107 #endif
108
109 relocate_new_kernel_end:
110
111         .section ".data"
112 SYM_DATA(relocate_new_kernel_size, .long relocate_new_kernel_end - relocate_new_kernel)
This page took 0.031629 seconds and 4 git commands to generate.