Commit | Line | Data |
---|---|---|
fc697dc0 SS |
1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #include <linux/linkage.h> | |
3 | #include <linux/kexec.h> | |
4 | ||
5 | #include <asm/assembly.h> | |
6 | #include <asm/asm-offsets.h> | |
7 | #include <asm/page.h> | |
8 | #include <asm/setup.h> | |
9 | #include <asm/psw.h> | |
10 | ||
11 | .level PA_ASM_LEVEL | |
12 | ||
13 | .macro kexec_param name | |
14 | .align 8 | |
15 | ENTRY(kexec\()_\name) | |
16 | #ifdef CONFIG_64BIT | |
17 | .dword 0 | |
18 | #else | |
19 | .word 0 | |
20 | #endif | |
21 | ||
22 | ENTRY(kexec\()_\name\()_offset) | |
23 | .word kexec\()_\name - relocate_new_kernel | |
24 | .endm | |
25 | ||
26 | .text | |
27 | ||
28 | /* args: | |
29 | * r26 - kimage->head | |
30 | * r25 - start address of kernel | |
31 | * r24 - physical address of relocate code | |
32 | */ | |
33 | ||
34 | ENTRY_CFI(relocate_new_kernel) | |
35 | 0: copy %arg1, %rp | |
36 | /* disable I and Q bit, so we are allowed to execute RFI */ | |
37 | rsm PSW_SM_I, %r0 | |
38 | nop | |
39 | nop | |
40 | nop | |
41 | nop | |
42 | nop | |
43 | nop | |
44 | nop | |
45 | ||
46 | rsm PSW_SM_Q, %r0 | |
47 | nop | |
48 | nop | |
49 | nop | |
50 | nop | |
51 | nop | |
52 | nop | |
53 | nop | |
54 | ||
55 | /* | |
56 | * After return-from-interrupt, we want to run without Code/Data | |
57 | * translation enabled just like on a normal boot. | |
58 | */ | |
59 | ||
60 | /* calculate new physical execution address */ | |
61 | ldo 1f-0b(%arg2), %r1 | |
62 | mtctl %r0, %cr17 /* IIASQ */ | |
63 | mtctl %r0, %cr17 /* IIASQ */ | |
64 | mtctl %r1, %cr18 /* IIAOQ */ | |
65 | ldo 4(%r1),%r1 | |
66 | mtctl %r1, %cr18 /* IIAOQ */ | |
67 | #ifdef CONFIG_64BIT | |
68 | depdi,z 1, PSW_W_BIT, 1, %r1 | |
69 | mtctl %r1, %cr22 /* IPSW */ | |
70 | #else | |
71 | mtctl %r0, %cr22 /* IPSW */ | |
72 | #endif | |
73 | /* lets go... */ | |
74 | rfi | |
75 | 1: nop | |
76 | nop | |
77 | ||
78 | .Lloop: | |
79 | LDREG,ma REG_SZ(%arg0), %r3 | |
80 | /* If crash kernel, no copy needed */ | |
81 | cmpib,COND(=),n 0,%r3,boot | |
82 | ||
83 | bb,<,n %r3, 31 - IND_DONE_BIT, boot | |
84 | bb,>=,n %r3, 31 - IND_INDIRECTION_BIT, .Lnotind | |
85 | /* indirection, load and restart */ | |
86 | movb %r3, %arg0, .Lloop | |
87 | depi 0, 31, PAGE_SHIFT, %arg0 | |
88 | ||
89 | .Lnotind: | |
90 | bb,>=,n %r3, 31 - IND_DESTINATION_BIT, .Lnotdest | |
91 | b .Lloop | |
92 | copy %r3, %r20 | |
93 | ||
94 | .Lnotdest: | |
95 | bb,>= %r3, 31 - IND_SOURCE_BIT, .Lloop | |
96 | depi 0, 31, PAGE_SHIFT, %r3 | |
97 | copy %r3, %r21 | |
98 | ||
99 | /* copy page */ | |
100 | copy %r0, %r18 | |
101 | zdepi 1, 31 - PAGE_SHIFT, 1, %r18 | |
102 | add %r20, %r18, %r17 | |
103 | ||
104 | depi 0, 31, PAGE_SHIFT, %r20 | |
105 | .Lcopy: | |
106 | copy %r20, %r12 | |
107 | LDREG,ma REG_SZ(%r21), %r8 | |
108 | LDREG,ma REG_SZ(%r21), %r9 | |
109 | LDREG,ma REG_SZ(%r21), %r10 | |
110 | LDREG,ma REG_SZ(%r21), %r11 | |
111 | STREG,ma %r8, REG_SZ(%r20) | |
112 | STREG,ma %r9, REG_SZ(%r20) | |
113 | STREG,ma %r10, REG_SZ(%r20) | |
114 | STREG,ma %r11, REG_SZ(%r20) | |
115 | ||
116 | #ifndef CONFIG_64BIT | |
117 | LDREG,ma REG_SZ(%r21), %r8 | |
118 | LDREG,ma REG_SZ(%r21), %r9 | |
119 | LDREG,ma REG_SZ(%r21), %r10 | |
120 | LDREG,ma REG_SZ(%r21), %r11 | |
121 | STREG,ma %r8, REG_SZ(%r20) | |
122 | STREG,ma %r9, REG_SZ(%r20) | |
123 | STREG,ma %r10, REG_SZ(%r20) | |
124 | STREG,ma %r11, REG_SZ(%r20) | |
125 | #endif | |
126 | ||
127 | fdc %r0(%r12) | |
128 | cmpb,COND(<<) %r20,%r17,.Lcopy | |
129 | fic (%sr4, %r12) | |
130 | b,n .Lloop | |
131 | ||
132 | boot: | |
133 | mtctl %r0, %cr15 | |
134 | ||
135 | LDREG kexec_free_mem-0b(%arg2), %arg0 | |
136 | LDREG kexec_cmdline-0b(%arg2), %arg1 | |
137 | LDREG kexec_initrd_end-0b(%arg2), %arg3 | |
138 | LDREG kexec_initrd_start-0b(%arg2), %arg2 | |
139 | bv,n %r0(%rp) | |
140 | ||
141 | ENDPROC_CFI(relocate_new_kernel); | |
142 | ||
143 | ENTRY(relocate_new_kernel_size) | |
144 | .word relocate_new_kernel_size - relocate_new_kernel | |
145 | ||
146 | kexec_param cmdline | |
147 | kexec_param initrd_start | |
148 | kexec_param initrd_end | |
149 | kexec_param free_mem |