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
15ENTRY(kexec\()_\name)
16#ifdef CONFIG_64BIT
17 .dword 0
18#else
19 .word 0
20#endif
21
22ENTRY(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
34ENTRY_CFI(relocate_new_kernel)
350: 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
751: 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
132boot:
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
141ENDPROC_CFI(relocate_new_kernel);
142
143ENTRY(relocate_new_kernel_size)
144 .word relocate_new_kernel_size - relocate_new_kernel
145
146kexec_param cmdline
147kexec_param initrd_start
148kexec_param initrd_end
149kexec_param free_mem
150

source code of linux/arch/parisc/kernel/relocate_kernel.S