/* SPDX-License-Identifier: GPL-2.0 */#include <linux/linkage.h>#include <linux/kexec.h> #include <asm/assembly.h>#include <asm/asm-offsets.h>#include <asm/page.h>#include <asm/setup.h>#include <asm/psw.h> .level PA_ASM_LEVEL .macro kexec_param name.align 8ENTRY(kexec\()_\name)#ifdef CONFIG_64BIT .dword 0#else .word 0#endif ENTRY(kexec\()_\name\()_offset) .word kexec\()_\name - relocate_new_kernel.endm .text /* args: * r26 - kimage->head * r25 - start address of kernel * r24 - physical address of relocate code */ ENTRY_CFI(relocate_new_kernel)0: copy %arg1, %rp /* disable I and Q bit, so we are allowed to execute RFI */ rsm PSW_SM_I, %r0 nop nop nop nop nop nop nop rsm PSW_SM_Q, %r0 nop nop nop nop nop nop nop /* * After return-from-interrupt, we want to run without Code/Data * translation enabled just like on a normal boot. */ /* calculate new physical execution address */ ldo 1f-0b(%arg2), %r1 mtctl %r0, %cr17 /* IIASQ */ mtctl %r0, %cr17 /* IIASQ */ mtctl %r1, %cr18 /* IIAOQ */ ldo 4(%r1),%r1 mtctl %r1, %cr18 /* IIAOQ */#ifdef CONFIG_64BIT depdi,z 1, PSW_W_BIT, 1, %r1 mtctl %r1, %cr22 /* IPSW */#else mtctl %r0, %cr22 /* IPSW */#endif /* lets go... */ rfi1: nop nop .Lloop: LDREG,ma REG_SZ(%arg0), %r3 /* If crash kernel, no copy needed */ cmpib,COND(=),n 0,%r3,boot bb,<,n %r3, 31 - IND_DONE_BIT, boot bb,>=,n %r3, 31 - IND_INDIRECTION_BIT, .Lnotind /* indirection, load and restart */ movb %r3, %arg0, .Lloop depi 0, 31, PAGE_SHIFT, %arg0 .Lnotind: bb,>=,n %r3, 31 - IND_DESTINATION_BIT, .Lnotdest b .Lloop copy %r3, %r20 .Lnotdest: bb,>= %r3, 31 - IND_SOURCE_BIT, .Lloop depi 0, 31, PAGE_SHIFT, %r3 copy %r3, %r21 /* copy page */ copy %r0, %r18 zdepi 1, 31 - PAGE_SHIFT, 1, %r18 add %r20, %r18, %r17 depi 0, 31, PAGE_SHIFT, %r20.Lcopy: copy %r20, %r12 LDREG,ma REG_SZ(%r21), %r8 LDREG,ma REG_SZ(%r21), %r9 LDREG,ma REG_SZ(%r21), %r10 LDREG,ma REG_SZ(%r21), %r11 STREG,ma %r8, REG_SZ(%r20) STREG,ma %r9, REG_SZ(%r20) STREG,ma %r10, REG_SZ(%r20) STREG,ma %r11, REG_SZ(%r20) #ifndef CONFIG_64BIT LDREG,ma REG_SZ(%r21), %r8 LDREG,ma REG_SZ(%r21), %r9 LDREG,ma REG_SZ(%r21), %r10 LDREG,ma REG_SZ(%r21), %r11 STREG,ma %r8, REG_SZ(%r20) STREG,ma %r9, REG_SZ(%r20) STREG,ma %r10, REG_SZ(%r20) STREG,ma %r11, REG_SZ(%r20)#endif fdc %r0(%r12) cmpb,COND(<<) %r20,%r17,.Lcopy fic (%sr4, %r12) b,n .Lloop boot: mtctl %r0, %cr15 LDREG kexec_free_mem-0b(%arg2), %arg0 LDREG kexec_cmdline-0b(%arg2), %arg1 LDREG kexec_initrd_end-0b(%arg2), %arg3 LDREG kexec_initrd_start-0b(%arg2), %arg2 bv,n %r0(%rp) ENDPROC_CFI(relocate_new_kernel); ENTRY(relocate_new_kernel_size) .word relocate_new_kernel_size - relocate_new_kernel kexec_param cmdlinekexec_param initrd_startkexec_param initrd_endkexec_param free_mem
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/linkage.h>
#include <linux/kexec.h>
#include <asm/assembly.h>
#include <asm/asm-offsets.h>
#include <asm/page.h>
#include <asm/setup.h>
#include <asm/psw.h>
.level PA_ASM_LEVEL
.macro kexec_param name
.align 8
ENTRY(kexec\()_\name)
#ifdef CONFIG_64BIT
.dword 0
#else
.word 0
#endif
ENTRY(kexec\()_\name\()_offset)
.word kexec\()_\name - relocate_new_kernel
.endm
.text
/* args:
* r26 - kimage->head
* r25 - start address of kernel
* r24 - physical address of relocate code
*/
ENTRY_CFI(relocate_new_kernel)
0: copy %arg1, %rp
/* disable I and Q bit, so we are allowed to execute RFI */
rsm PSW_SM_I, %r0
nop
nop
nop
nop
nop
nop
nop
rsm PSW_SM_Q, %r0
nop
nop
nop
nop
nop
nop
nop
/*
* After return-from-interrupt, we want to run without Code/Data
* translation enabled just like on a normal boot.
*/
/* calculate new physical execution address */
ldo 1f-0b(%arg2), %r1
mtctl %r0, %cr17 /* IIASQ */
mtctl %r0, %cr17 /* IIASQ */
mtctl %r1, %cr18 /* IIAOQ */
ldo 4(%r1),%r1
mtctl %r1, %cr18 /* IIAOQ */
#ifdef CONFIG_64BIT
depdi,z 1, PSW_W_BIT, 1, %r1
mtctl %r1, %cr22 /* IPSW */
#else
mtctl %r0, %cr22 /* IPSW */
#endif
/* lets go... */
rfi
1: nop
nop
.Lloop:
LDREG,ma REG_SZ(%arg0), %r3
/* If crash kernel, no copy needed */
cmpib,COND(=),n 0,%r3,boot
bb,<,n %r3, 31 - IND_DONE_BIT, boot
bb,>=,n %r3, 31 - IND_INDIRECTION_BIT, .Lnotind
/* indirection, load and restart */
movb %r3, %arg0, .Lloop
depi 0, 31, PAGE_SHIFT, %arg0
.Lnotind:
bb,>=,n %r3, 31 - IND_DESTINATION_BIT, .Lnotdest
b .Lloop
copy %r3, %r20
.Lnotdest:
bb,>= %r3, 31 - IND_SOURCE_BIT, .Lloop
depi 0, 31, PAGE_SHIFT, %r3
copy %r3, %r21
/* copy page */
copy %r0, %r18
zdepi 1, 31 - PAGE_SHIFT, 1, %r18
add %r20, %r18, %r17
depi 0, 31, PAGE_SHIFT, %r20
.Lcopy:
copy %r20, %r12
LDREG,ma REG_SZ(%r21), %r8
LDREG,ma REG_SZ(%r21), %r9
LDREG,ma REG_SZ(%r21), %r10
LDREG,ma REG_SZ(%r21), %r11
STREG,ma %r8, REG_SZ(%r20)
STREG,ma %r9, REG_SZ(%r20)
STREG,ma %r10, REG_SZ(%r20)
STREG,ma %r11, REG_SZ(%r20)
#ifndef CONFIG_64BIT
LDREG,ma REG_SZ(%r21), %r8
LDREG,ma REG_SZ(%r21), %r9
LDREG,ma REG_SZ(%r21), %r10
LDREG,ma REG_SZ(%r21), %r11
STREG,ma %r8, REG_SZ(%r20)
STREG,ma %r9, REG_SZ(%r20)
STREG,ma %r10, REG_SZ(%r20)
STREG,ma %r11, REG_SZ(%r20)
#endif
fdc %r0(%r12)
cmpb,COND(<<) %r20,%r17,.Lcopy
fic (%sr4, %r12)
b,n .Lloop
boot:
mtctl %r0, %cr15
LDREG kexec_free_mem-0b(%arg2), %arg0
LDREG kexec_cmdline-0b(%arg2), %arg1
LDREG kexec_initrd_end-0b(%arg2), %arg3
LDREG kexec_initrd_start-0b(%arg2), %arg2
bv,n %r0(%rp)
ENDPROC_CFI(relocate_new_kernel);
ENTRY(relocate_new_kernel_size)
.word relocate_new_kernel_size - relocate_new_kernel
kexec_param cmdline
kexec_param initrd_start
kexec_param initrd_end
kexec_param free_mem