Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/loongarch/kernel/relocate_kernel.S
26439 views
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, .quad relocate_new_kernel_end - relocate_new_kernel)
113
114