Skip to content

Commit b5667d1

Browse files
hbathinimpe
authored andcommitted
powerpc/kexec_file: Fix kexec load failure with lack of memory hole
The kexec purgatory has to run in real mode. Only the first memory block maybe accessible in real mode. And, unlike the case with panic kernel, no memory is set aside for regular kexec load. Another thing to note is, the memory for crashkernel is reserved at an offset of 128MB. So, when crashkernel memory is reserved, the memory ranges to load kexec segments shrink further as the generic code only looks for memblock free memory ranges and in all likelihood only a tiny bit of memory from 0 to 128MB would be available to load kexec segments. With kdump being used by default in general, kexec file load is likely to fail almost always. This can be fixed by changing the memory hole lookup logic for regular kexec to use the same method as kdump. This would mean that most kexec segments will overlap with crashkernel memory region. That should still be ok as the pages, whose destination address isn't available while loading, are placed in an intermediate location till a flush to the actual destination address happens during kexec boot sequence. Signed-off-by: Hari Bathini <[email protected]> Tested-by: Pingfan Liu <[email protected]> Reviewed-by: Thiago Jung Bauermann <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/159602302326.575379.14038896654942043093.stgit@hbathini
1 parent 6ecd016 commit b5667d1

File tree

1 file changed

+14
-19
lines changed

1 file changed

+14
-19
lines changed

arch/powerpc/kexec/file_load_64.c

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,25 +1012,22 @@ int arch_kexec_locate_mem_hole(struct kexec_buf *kbuf)
10121012
u64 buf_min, buf_max;
10131013
int ret;
10141014

1015-
/*
1016-
* Use the generic kexec_locate_mem_hole for regular
1017-
* kexec_file_load syscall
1018-
*/
1019-
if (kbuf->image->type != KEXEC_TYPE_CRASH)
1020-
return kexec_locate_mem_hole(kbuf);
1021-
10221015
/* Look up the exclude ranges list while locating the memory hole */
10231016
emem = &(kbuf->image->arch.exclude_ranges);
10241017
if (!(*emem) || ((*emem)->nr_ranges == 0)) {
10251018
pr_warn("No exclude range list. Using the default locate mem hole method\n");
10261019
return kexec_locate_mem_hole(kbuf);
10271020
}
10281021

1022+
buf_min = kbuf->buf_min;
1023+
buf_max = kbuf->buf_max;
10291024
/* Segments for kdump kernel should be within crashkernel region */
1030-
buf_min = (kbuf->buf_min < crashk_res.start ?
1031-
crashk_res.start : kbuf->buf_min);
1032-
buf_max = (kbuf->buf_max > crashk_res.end ?
1033-
crashk_res.end : kbuf->buf_max);
1025+
if (kbuf->image->type == KEXEC_TYPE_CRASH) {
1026+
buf_min = (buf_min < crashk_res.start ?
1027+
crashk_res.start : buf_min);
1028+
buf_max = (buf_max > crashk_res.end ?
1029+
crashk_res.end : buf_max);
1030+
}
10341031

10351032
if (buf_min > buf_max) {
10361033
pr_err("Invalid buffer min and/or max values\n");
@@ -1067,15 +1064,13 @@ int arch_kexec_locate_mem_hole(struct kexec_buf *kbuf)
10671064
int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
10681065
unsigned long buf_len)
10691066
{
1070-
if (image->type == KEXEC_TYPE_CRASH) {
1071-
int ret;
1067+
int ret;
10721068

1073-
/* Get exclude memory ranges needed for setting up kdump segments */
1074-
ret = get_exclude_memory_ranges(&(image->arch.exclude_ranges));
1075-
if (ret) {
1076-
pr_err("Failed to setup exclude memory ranges for buffer lookup\n");
1077-
return ret;
1078-
}
1069+
/* Get exclude memory ranges needed for setting up kexec segments */
1070+
ret = get_exclude_memory_ranges(&(image->arch.exclude_ranges));
1071+
if (ret) {
1072+
pr_err("Failed to setup exclude memory ranges for buffer lookup\n");
1073+
return ret;
10791074
}
10801075

10811076
return kexec_image_probe_default(image, buf, buf_len);

0 commit comments

Comments
 (0)