Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 653beba2 authored by Philipp Rudo's avatar Philipp Rudo Committed by Martin Schwidefsky
Browse files

s390/kexec_file: Load new kernel to absolute 0



The leading 64 kB of a kernel image doesn't contain any data needed to boot
the new kernel when it was loaded via kexec_file. Thus kexec_file currently
strips them off before loading the image. Keep the leading 64 kB in order
to be able to pass a ipl_report to the next kernel.

Signed-off-by: default avatarPhilipp Rudo <prudo@linux.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 8e496426
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -43,6 +43,9 @@
/* The native architecture */
#define KEXEC_ARCH KEXEC_ARCH_S390

/* Allow kexec_file to load a segment to 0 */
#define KEXEC_BUF_MEM_UNKNOWN -1

/* Provide a dummy definition to avoid build failures. */
static inline void crash_setup_regs(struct pt_regs *newregs,
					struct pt_regs *oldregs) { }
@@ -52,6 +55,9 @@ struct s390_load_data {
	/* Pointer to the kernel buffer. Used to register cmdline etc.. */
	void *kernel_buf;

	/* Load address of the kernel_buf. */
	unsigned long kernel_mem;

	/* Parmarea in the kernel buffer. */
	struct parmarea *parm;

+4 −12
Original line number Diff line number Diff line
@@ -39,28 +39,20 @@ static int kexec_file_add_kernel_elf(struct kimage *image,
		buf.bufsz = phdr->p_filesz;

		buf.mem = ALIGN(phdr->p_paddr, phdr->p_align);
		if (image->type == KEXEC_TYPE_CRASH)
			buf.mem += crashk_res.start;
		buf.memsz = phdr->p_memsz;
		data->memsz = ALIGN(data->memsz, phdr->p_align) + buf.memsz;

		if (entry - phdr->p_paddr < phdr->p_memsz) {
			data->kernel_buf = buf.buffer;
			data->kernel_mem = buf.mem;
			data->parm = buf.buffer + PARMAREA;
			data->memsz += STARTUP_NORMAL_OFFSET;

			buf.buffer += STARTUP_NORMAL_OFFSET;
			buf.bufsz -= STARTUP_NORMAL_OFFSET;

			buf.mem += STARTUP_NORMAL_OFFSET;
			buf.memsz -= STARTUP_NORMAL_OFFSET;
		}

		if (image->type == KEXEC_TYPE_CRASH)
			buf.mem += crashk_res.start;

		ret = kexec_add_buffer(&buf);
		if (ret)
			return ret;

		data->memsz = ALIGN(data->memsz, phdr->p_align) + buf.memsz;
	}

	return data->memsz ? 0 : -EINVAL;
+5 −4
Original line number Diff line number Diff line
@@ -19,17 +19,18 @@ static int kexec_file_add_kernel_image(struct kimage *image,

	buf.image = image;

	buf.buffer = image->kernel_buf + STARTUP_NORMAL_OFFSET;
	buf.bufsz = image->kernel_buf_len - STARTUP_NORMAL_OFFSET;
	buf.buffer = image->kernel_buf;
	buf.bufsz = image->kernel_buf_len;

	buf.mem = STARTUP_NORMAL_OFFSET;
	buf.mem = 0;
	if (image->type == KEXEC_TYPE_CRASH)
		buf.mem += crashk_res.start;
	buf.memsz = buf.bufsz;

	data->kernel_buf = image->kernel_buf;
	data->kernel_mem = buf.mem;
	data->parm = image->kernel_buf + PARMAREA;
	data->memsz += buf.memsz + STARTUP_NORMAL_OFFSET;
	data->memsz += buf.memsz;

	return kexec_add_buffer(&buf);
}
+10 −2
Original line number Diff line number Diff line
@@ -17,7 +17,8 @@ const struct kexec_file_ops * const kexec_file_loaders[] = {
	NULL,
};

static int kexec_file_update_purgatory(struct kimage *image)
static int kexec_file_update_purgatory(struct kimage *image,
				       struct s390_load_data *data)
{
	u64 entry, type;
	int ret;
@@ -76,7 +77,7 @@ static int kexec_file_add_purgatory(struct kimage *image,
	if (ret)
		return ret;

	ret = kexec_file_update_purgatory(image);
	ret = kexec_file_update_purgatory(image, data);
	return ret;
}

@@ -136,6 +137,13 @@ void *kexec_file_add_components(struct kimage *image,
	if (ret)
		return ERR_PTR(ret);

	if (data.kernel_mem == 0) {
		unsigned long restart_psw =  0x0008000080000000UL;
		restart_psw += image->start;
		memcpy(data.kernel_buf, &restart_psw, sizeof(restart_psw));
		image->start = 0;
	}

	return NULL;
}

+3 −0
Original line number Diff line number Diff line
@@ -58,10 +58,13 @@ ENTRY(relocate_kernel)
		j	.base
	.done:
		sgr	%r0,%r0		# clear register r0
		cghi	%r3,0
		je	.diag
		la	%r4,load_psw-.base(%r13)	# load psw-address into the register
		o	%r3,4(%r4)	# or load address into psw
		st	%r3,4(%r4)
		mvc	0(8,%r0),0(%r4)	# copy psw to absolute address 0
	.diag:
		diag	%r0,%r0,0x308

		.align	8