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

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
...@@ -43,6 +43,9 @@ ...@@ -43,6 +43,9 @@
/* The native architecture */ /* The native architecture */
#define KEXEC_ARCH KEXEC_ARCH_S390 #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. */ /* Provide a dummy definition to avoid build failures. */
static inline void crash_setup_regs(struct pt_regs *newregs, static inline void crash_setup_regs(struct pt_regs *newregs,
struct pt_regs *oldregs) { } struct pt_regs *oldregs) { }
...@@ -52,6 +55,9 @@ struct s390_load_data { ...@@ -52,6 +55,9 @@ struct s390_load_data {
/* Pointer to the kernel buffer. Used to register cmdline etc.. */ /* Pointer to the kernel buffer. Used to register cmdline etc.. */
void *kernel_buf; void *kernel_buf;
/* Load address of the kernel_buf. */
unsigned long kernel_mem;
/* Parmarea in the kernel buffer. */ /* Parmarea in the kernel buffer. */
struct parmarea *parm; struct parmarea *parm;
......
...@@ -39,28 +39,20 @@ static int kexec_file_add_kernel_elf(struct kimage *image, ...@@ -39,28 +39,20 @@ static int kexec_file_add_kernel_elf(struct kimage *image,
buf.bufsz = phdr->p_filesz; buf.bufsz = phdr->p_filesz;
buf.mem = ALIGN(phdr->p_paddr, phdr->p_align); 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; buf.memsz = phdr->p_memsz;
data->memsz = ALIGN(data->memsz, phdr->p_align) + buf.memsz;
if (entry - phdr->p_paddr < phdr->p_memsz) { if (entry - phdr->p_paddr < phdr->p_memsz) {
data->kernel_buf = buf.buffer; data->kernel_buf = buf.buffer;
data->kernel_mem = buf.mem;
data->parm = buf.buffer + PARMAREA; 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); ret = kexec_add_buffer(&buf);
if (ret) if (ret)
return ret; return ret;
data->memsz = ALIGN(data->memsz, phdr->p_align) + buf.memsz;
} }
return data->memsz ? 0 : -EINVAL; return data->memsz ? 0 : -EINVAL;
......
...@@ -19,17 +19,18 @@ static int kexec_file_add_kernel_image(struct kimage *image, ...@@ -19,17 +19,18 @@ static int kexec_file_add_kernel_image(struct kimage *image,
buf.image = image; buf.image = image;
buf.buffer = image->kernel_buf + STARTUP_NORMAL_OFFSET; buf.buffer = image->kernel_buf;
buf.bufsz = image->kernel_buf_len - STARTUP_NORMAL_OFFSET; buf.bufsz = image->kernel_buf_len;
buf.mem = STARTUP_NORMAL_OFFSET; buf.mem = 0;
if (image->type == KEXEC_TYPE_CRASH) if (image->type == KEXEC_TYPE_CRASH)
buf.mem += crashk_res.start; buf.mem += crashk_res.start;
buf.memsz = buf.bufsz; buf.memsz = buf.bufsz;
data->kernel_buf = image->kernel_buf; data->kernel_buf = image->kernel_buf;
data->kernel_mem = buf.mem;
data->parm = image->kernel_buf + PARMAREA; data->parm = image->kernel_buf + PARMAREA;
data->memsz += buf.memsz + STARTUP_NORMAL_OFFSET; data->memsz += buf.memsz;
return kexec_add_buffer(&buf); return kexec_add_buffer(&buf);
} }
......
...@@ -17,7 +17,8 @@ const struct kexec_file_ops * const kexec_file_loaders[] = { ...@@ -17,7 +17,8 @@ const struct kexec_file_ops * const kexec_file_loaders[] = {
NULL, 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; u64 entry, type;
int ret; int ret;
...@@ -76,7 +77,7 @@ static int kexec_file_add_purgatory(struct kimage *image, ...@@ -76,7 +77,7 @@ static int kexec_file_add_purgatory(struct kimage *image,
if (ret) if (ret)
return ret; return ret;
ret = kexec_file_update_purgatory(image); ret = kexec_file_update_purgatory(image, data);
return ret; return ret;
} }
...@@ -136,6 +137,13 @@ void *kexec_file_add_components(struct kimage *image, ...@@ -136,6 +137,13 @@ void *kexec_file_add_components(struct kimage *image,
if (ret) if (ret)
return ERR_PTR(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; return NULL;
} }
......
...@@ -58,10 +58,13 @@ ENTRY(relocate_kernel) ...@@ -58,10 +58,13 @@ ENTRY(relocate_kernel)
j .base j .base
.done: .done:
sgr %r0,%r0 # clear register r0 sgr %r0,%r0 # clear register r0
cghi %r3,0
je .diag
la %r4,load_psw-.base(%r13) # load psw-address into the register la %r4,load_psw-.base(%r13) # load psw-address into the register
o %r3,4(%r4) # or load address into psw o %r3,4(%r4) # or load address into psw
st %r3,4(%r4) st %r3,4(%r4)
mvc 0(8,%r0),0(%r4) # copy psw to absolute address 0 mvc 0(8,%r0),0(%r4) # copy psw to absolute address 0
.diag:
diag %r0,%r0,0x308 diag %r0,%r0,0x308
.align 8 .align 8
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment