Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/kexec: set end-of-ipl flag in last diag308 call

If the facility IPL-complete-control is present then the last diag308
call made by kexec shall set the end-of-ipl flag in the subcode register
to signal the hypervisor that this is the last diag308 call made by Linux.
Only the diag308 calls made during a regular kexec need to set
the end-of-ipl flag, in all other cases the hypervisor will ignore it.

Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>

authored by

Alexander Egorenkov and committed by
Heiko Carstens
2ba24343 1b553839

+16 -3
+6
arch/s390/include/asm/ipl.h
··· 133 133 * DIAG 308 support 134 134 */ 135 135 enum diag308_subcode { 136 + DIAG308_CLEAR_RESET = 0, 137 + DIAG308_LOAD_NORMAL_RESET = 1, 136 138 DIAG308_REL_HSA = 2, 137 139 DIAG308_LOAD_CLEAR = 3, 138 140 DIAG308_LOAD_NORMAL_DUMP = 4, 139 141 DIAG308_SET = 5, 140 142 DIAG308_STORE = 6, 141 143 DIAG308_LOAD_NORMAL = 7, 144 + }; 145 + 146 + enum diag308_subcode_flags { 147 + DIAG308_FLAG_EI = 1UL << 16, 142 148 }; 143 149 144 150 enum diag308_rc {
+8 -2
arch/s390/kernel/machine_kexec.c
··· 26 26 #include <asm/stacktrace.h> 27 27 #include <asm/switch_to.h> 28 28 #include <asm/nmi.h> 29 + #include <asm/sclp.h> 29 30 30 - typedef void (*relocate_kernel_t)(kimage_entry_t *, unsigned long); 31 + typedef void (*relocate_kernel_t)(kimage_entry_t *, unsigned long, 32 + unsigned long); 31 33 32 34 extern const unsigned char relocate_kernel[]; 33 35 extern const unsigned long long relocate_kernel_len; ··· 245 243 */ 246 244 static void __do_machine_kexec(void *data) 247 245 { 246 + unsigned long diag308_subcode; 248 247 relocate_kernel_t data_mover; 249 248 struct kimage *image = data; 250 249 ··· 254 251 255 252 __arch_local_irq_stnsm(0xfb); /* disable DAT - avoid no-execute */ 256 253 /* Call the moving routine */ 257 - (*data_mover)(&image->head, image->start); 254 + diag308_subcode = DIAG308_CLEAR_RESET; 255 + if (sclp.has_iplcc) 256 + diag308_subcode |= DIAG308_FLAG_EI; 257 + (*data_mover)(&image->head, image->start, diag308_subcode); 258 258 259 259 /* Die if kexec returns */ 260 260 disabled_wait();
+2 -1
arch/s390/kernel/relocate_kernel.S
··· 14 14 * moves the new kernel to its destination... 15 15 * %r2 = pointer to first kimage_entry_t 16 16 * %r3 = start address - where to jump to after the job is done... 17 + * %r4 = subcode 17 18 * 18 19 * %r5 will be used as temp. storage 19 20 * %r6 holds the destination address ··· 57 56 jo 0b 58 57 j .base 59 58 .done: 60 - sgr %r0,%r0 # clear register r0 59 + lgr %r0,%r4 # subcode 61 60 cghi %r3,0 62 61 je .diag 63 62 la %r4,load_psw-.base(%r13) # load psw-address into the register