123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- /* 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
|