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