Commit 2ba24343 authored by Alexander Egorenkov's avatar Alexander Egorenkov Committed by Heiko Carstens
Browse files

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: default avatarAlexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent 1b553839
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -133,6 +133,8 @@ int ipl_report_add_certificate(struct ipl_report *report, void *key,
 * DIAG 308 support
 */
enum diag308_subcode  {
	DIAG308_CLEAR_RESET = 0,
	DIAG308_LOAD_NORMAL_RESET = 1,
	DIAG308_REL_HSA = 2,
	DIAG308_LOAD_CLEAR = 3,
	DIAG308_LOAD_NORMAL_DUMP = 4,
@@ -141,6 +143,10 @@ enum diag308_subcode {
	DIAG308_LOAD_NORMAL = 7,
};

enum diag308_subcode_flags {
	DIAG308_FLAG_EI = 1UL << 16,
};

enum diag308_rc {
	DIAG308_RC_OK		= 0x0001,
	DIAG308_RC_NOCONFIG	= 0x0102,
+8 −2
Original line number Diff line number Diff line
@@ -26,8 +26,10 @@
#include <asm/stacktrace.h>
#include <asm/switch_to.h>
#include <asm/nmi.h>
#include <asm/sclp.h>

typedef void (*relocate_kernel_t)(kimage_entry_t *, unsigned long);
typedef void (*relocate_kernel_t)(kimage_entry_t *, unsigned long,
				  unsigned long);

extern const unsigned char relocate_kernel[];
extern const unsigned long long relocate_kernel_len;
@@ -243,6 +245,7 @@ void machine_crash_shutdown(struct pt_regs *regs)
 */
static void __do_machine_kexec(void *data)
{
	unsigned long diag308_subcode;
	relocate_kernel_t data_mover;
	struct kimage *image = data;

@@ -251,7 +254,10 @@ static void __do_machine_kexec(void *data)

	__arch_local_irq_stnsm(0xfb); /* disable DAT - avoid no-execute */
	/* Call the moving routine */
	(*data_mover)(&image->head, image->start);
	diag308_subcode = DIAG308_CLEAR_RESET;
	if (sclp.has_iplcc)
		diag308_subcode |= DIAG308_FLAG_EI;
	(*data_mover)(&image->head, image->start, diag308_subcode);

	/* Die if kexec returns */
	disabled_wait();
+2 −1
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
 * moves the new kernel to its destination...
 * %r2 = pointer to first kimage_entry_t
 * %r3 = start address - where to jump to after the job is done...
 * %r4 = subcode
 *
 * %r5 will be used as temp. storage
 * %r6 holds the destination address
@@ -56,7 +57,7 @@ ENTRY(relocate_kernel)
		jo	0b
		j	.base
	.done:
		sgr	%r0,%r0		# clear register r0
		lgr	%r0,%r4		# subcode
		cghi	%r3,0
		je	.diag
		la	%r4,load_psw-.base(%r13)	# load psw-address into the register