1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Purgatory setup code 4 * 5 * Copyright IBM Corp. 2018 6 * 7 * Author(s): Philipp Rudo <prudo@linux.vnet.ib 8 */ 9 10 #include <linux/linkage.h> 11 #include <asm/asm-offsets.h> 12 #include <asm/page.h> 13 #include <asm/sigp.h> 14 #include <asm/ptrace.h> 15 16 /* The purgatory is the code running between t 17 * is to verify that the next kernel was not c 18 * start it. 19 * 20 * If the next kernel is a crash kernel there 21 * consider: 22 * 23 * First the purgatory is called twice. Once o 24 * sha digest. So if the crash kernel got corr 25 * to trigger a stand-alone dumper. And once t 26 * 27 * Second the purgatory also has to swap the c 28 * destination at address 0. As the purgatory 29 * requires some finesse. The tactic here is t 30 * itself to the end of the destination and th 31 * memory running from there. 32 */ 33 34 #define bufsz purgatory_end-stack 35 36 .macro MEMCPY dst,src,len 37 lgr %r0,\dst 38 lgr %r1,\len 39 lgr %r2,\src 40 lgr %r3,\len 41 42 20: mvcle %r0,%r2,0 43 jo 20b 44 .endm 45 46 .macro MEMSWAP dst,src,buf,len 47 10: larl %r0,purgatory_end 48 larl %r1,stack 49 slgr %r0,%r1 50 cgr \len,%r0 51 jh 11f 52 lgr %r4,\len 53 j 12f 54 11: lgr %r4,%r0 55 56 12: MEMCPY \buf,\dst,%r4 57 MEMCPY \dst,\src,%r4 58 MEMCPY \src,\buf,%r4 59 60 agr \dst,%r4 61 agr \src,%r4 62 sgr \len,%r4 63 64 cghi \len,0 65 jh 10b 66 .endm 67 68 .macro START_NEXT_KERNEL base subcode 69 lg %r4,kernel_entry-\base(%r13) 70 lg %r5,load_psw_mask-\base(%r13) 71 ogr %r4,%r5 72 stg %r4,0(%r0) 73 74 xgr %r0,%r0 75 lghi %r1,\subcode 76 diag %r0,%r1,0x308 77 .endm 78 79 .text 80 .balign PAGE_SIZE 81 SYM_CODE_START(purgatory_start) 82 /* The purgatory might be called after 83 * architecture and addressing mode. 84 */ 85 lhi %r1,1 86 sigp %r1,%r0,SIGP_SET_ARCHITECTURE 87 sam64 88 89 larl %r5,gprregs 90 stmg %r6,%r15,0(%r5) 91 92 basr %r13,0 93 .base_crash: 94 95 /* Setup stack */ 96 larl %r15,purgatory_end-STACK_FRAME 97 98 /* If the next kernel is KEXEC_TYPE_CR 99 * directly with a flag passed in %r2 100 * checksum verification only (%r2 = 0 101 * 102 * Check now and preserve over C funct 103 * %r10 with 104 * 1 -> checksum verification onl 105 * 0 -> load new kernel 106 */ 107 lghi %r10,0 108 lg %r11,kernel_type-.base_crash(% 109 cghi %r11,1 /* KEXEC_TYPE_ 110 jne .do_checksum_verification 111 cghi %r2,0 /* checksum ve 112 jne .do_checksum_verification 113 lghi %r10,1 114 115 .do_checksum_verification: 116 brasl %r14,verify_sha256_digest 117 118 cghi %r10,1 /* checksum ve 119 je .return_old_kernel 120 cghi %r2,0 /* checksum ma 121 jne .disabled_wait 122 123 /* If the next kernel is a crash kerne 124 * the mem regions first. 125 */ 126 cghi %r11,1 /* KEXEC_TYPE_CRASH */ 127 je .start_crash_kernel 128 129 /* start normal kernel */ 130 START_NEXT_KERNEL .base_crash 0 131 132 .return_old_kernel: 133 lmg %r6,%r15,gprregs-.base_crash(% 134 br %r14 135 136 .disabled_wait: 137 lpswe disabled_wait_psw-.base_crash( 138 139 .start_crash_kernel: 140 /* Location of purgatory_start in cras 141 larl %r0,.base_crash 142 larl %r1,purgatory_start 143 slgr %r0,%r1 144 lgr %r8,%r13 145 sgr %r8,%r0 146 147 /* Destination for this code i.e. end 148 larl %r0,purgatory_end 149 larl %r1,purgatory_start 150 slgr %r0,%r1 151 lg %r9,crash_size-.base_crash(%r1 152 sgr %r9,%r0 153 154 /* Destination in crash memory, i.e. s 155 lg %r10,crash_start-.base_crash(% 156 agr %r10,%r9 157 158 /* Buffer location (in crash memory) a 159 * behind the point of no return it ca 160 */ 161 larl %r11,purgatory_end 162 larl %r12,stack 163 slgr %r11,%r12 164 165 MEMCPY %r12,%r9,%r11 /* dst -> (cr 166 MEMCPY %r9,%r8,%r11 /* self -> dst 167 168 /* Jump to new location. */ 169 lgr %r7,%r9 170 larl %r0,.jump_to_dst 171 larl %r1,purgatory_start 172 slgr %r0,%r1 173 agr %r7,%r0 174 br %r7 175 176 .jump_to_dst: 177 basr %r13,0 178 .base_dst: 179 180 /* clear buffer */ 181 MEMCPY %r12,%r10,%r11 /* (crash) buf 182 183 /* Load new buffer location after jump 184 larl %r7,stack 185 lgr %r0,%r7 186 larl %r1,purgatory_start 187 slgr %r0,%r1 188 agr %r10,%r0 189 MEMCPY %r10,%r7,%r11 /* (new) buf - 190 191 /* Now the code is set up to run from 192 * swapping the rest of crash memory n 193 * 194 * The registers will be used as follo 195 * 196 * %r0-%r4 reserved for macros de 197 * %r5-%r6 tmp registers 198 * %r7 pointer to current str 199 * %r8 index to iterate over 200 * %r9 pointer in crash memor 201 * %r10 pointer in old kernel 202 * %r11 total size (still) to 203 * %r12 pointer to buffer 204 */ 205 lgr %r12,%r7 206 lgr %r11,%r9 207 lghi %r10,0 208 lg %r9,crash_start-.base_dst(%r13 209 lghi %r8,16 /* KEXEC_SEGMENTS_MAX 210 larl %r7,purgatory_sha_regions 211 212 j .loop_first 213 214 /* Loop over all purgatory_sha_regions 215 .loop_next: 216 aghi %r8,-1 217 cghi %r8,0 218 je .loop_out 219 220 aghi %r7,__KEXEC_SHA_REGION_SIZE 221 222 .loop_first: 223 lg %r5,__KEXEC_SHA_REGION_START(% 224 cghi %r5,0 225 je .loop_next 226 227 /* Copy [end last sha region, start cu 228 /* Note: kexec_sha_region->start point 229 sgr %r5,%r9 230 MEMCPY %r9,%r10,%r5 231 232 agr %r9,%r5 233 agr %r10,%r5 234 sgr %r11,%r5 235 236 /* Swap sha region */ 237 lg %r6,__KEXEC_SHA_REGION_LEN(%r7 238 MEMSWAP %r9,%r10,%r12,%r6 239 sg %r11,__KEXEC_SHA_REGION_LEN(%r 240 j .loop_next 241 242 .loop_out: 243 /* Copy rest of crash memory */ 244 MEMCPY %r9,%r10,%r11 245 246 /* start crash kernel */ 247 START_NEXT_KERNEL .base_dst 1 248 SYM_CODE_END(purgatory_start) 249 250 SYM_DATA_LOCAL(load_psw_mask, .long 251 .balign 8 252 SYM_DATA_LOCAL(disabled_wait_psw, .quad 253 SYM_DATA_LOCAL(gprregs, .fill 254 SYM_DATA(purgatory_sha256_digest, .skip 255 SYM_DATA(purgatory_sha_regions, .skip 256 SYM_DATA(kernel_entry, .skip 257 SYM_DATA(kernel_type, .skip 258 SYM_DATA(crash_start, .skip 259 SYM_DATA(crash_size, .skip 260 .balign PAGE_SIZE 261 SYM_DATA_START_LOCAL(stack) 262 /* The buffer to move this code must b 263 .skip stack-purgatory_start 264 .balign PAGE_SIZE 265 SYM_DATA_END_LABEL(stack, SYM_L_LOCAL, purgato
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.