Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | /* 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 |