Skip to content

Commit 4e042af

Browse files
heicarstMartin Schwidefsky
authored and
Martin Schwidefsky
committed
s390/kexec: fix crash on resize of reserved memory
Reducing the size of reserved memory for the crash kernel will result in an immediate crash on s390. Reason for that is that we do not create struct pages for memory that is reserved. If that memory is freed any access to struct pages which correspond to this memory will result in invalid memory accesses and a kernel panic. Fix this by properly creating struct pages when the system gets initialized. Change the code also to make use of set_memory_ro() and set_memory_rw() so page tables will be split if required. Signed-off-by: Heiko Carstens <[email protected]> Signed-off-by: Martin Schwidefsky <[email protected]>
1 parent 2d0af22 commit 4e042af

File tree

2 files changed

+25
-23
lines changed

2 files changed

+25
-23
lines changed

arch/s390/kernel/machine_kexec.c

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <asm/diag.h>
2525
#include <asm/elf.h>
2626
#include <asm/asm-offsets.h>
27+
#include <asm/cacheflush.h>
2728
#include <asm/os_info.h>
2829
#include <asm/switch_to.h>
2930

@@ -60,8 +61,6 @@ static int machine_kdump_pm_cb(struct notifier_block *nb, unsigned long action,
6061
static int __init machine_kdump_pm_init(void)
6162
{
6263
pm_notifier(machine_kdump_pm_cb, 0);
63-
/* Create initial mapping for crashkernel memory */
64-
arch_kexec_unprotect_crashkres();
6564
return 0;
6665
}
6766
arch_initcall(machine_kdump_pm_init);
@@ -163,37 +162,27 @@ void crash_free_reserved_phys_range(unsigned long begin, unsigned long end)
163162
os_info_crashkernel_add(0, 0);
164163
}
165164

166-
/*
167-
* Map or unmap crashkernel memory
168-
*/
169-
static void crash_map_pages(int enable)
165+
static void crash_protect_pages(int protect)
170166
{
171-
unsigned long size = resource_size(&crashk_res);
167+
unsigned long size;
172168

173-
BUG_ON(crashk_res.start % KEXEC_CRASH_MEM_ALIGN ||
174-
size % KEXEC_CRASH_MEM_ALIGN);
175-
if (enable)
176-
vmem_add_mapping(crashk_res.start, size);
169+
if (!crashk_res.end)
170+
return;
171+
size = resource_size(&crashk_res);
172+
if (protect)
173+
set_memory_ro(crashk_res.start, size >> PAGE_SHIFT);
177174
else
178-
vmem_remove_mapping(crashk_res.start, size);
175+
set_memory_rw(crashk_res.start, size >> PAGE_SHIFT);
179176
}
180177

181-
/*
182-
* Unmap crashkernel memory
183-
*/
184178
void arch_kexec_protect_crashkres(void)
185179
{
186-
if (crashk_res.end)
187-
crash_map_pages(0);
180+
crash_protect_pages(1);
188181
}
189182

190-
/*
191-
* Map crashkernel memory
192-
*/
193183
void arch_kexec_unprotect_crashkres(void)
194184
{
195-
if (crashk_res.end)
196-
crash_map_pages(1);
185+
crash_protect_pages(0);
197186
}
198187

199188
#endif

arch/s390/kernel/setup.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,20 @@ static void __init setup_resources(void)
432432
}
433433
}
434434
}
435+
#ifdef CONFIG_CRASH_DUMP
436+
/*
437+
* Re-add removed crash kernel memory as reserved memory. This makes
438+
* sure it will be mapped with the identity mapping and struct pages
439+
* will be created, so it can be resized later on.
440+
* However add it later since the crash kernel resource should not be
441+
* part of the System RAM resource.
442+
*/
443+
if (crashk_res.end) {
444+
memblock_add(crashk_res.start, resource_size(&crashk_res));
445+
memblock_reserve(crashk_res.start, resource_size(&crashk_res));
446+
insert_resource(&iomem_resource, &crashk_res);
447+
}
448+
#endif
435449
}
436450

437451
static void __init setup_memory_end(void)
@@ -602,7 +616,6 @@ static void __init reserve_crashkernel(void)
602616
diag10_range(PFN_DOWN(crash_base), PFN_DOWN(crash_size));
603617
crashk_res.start = crash_base;
604618
crashk_res.end = crash_base + crash_size - 1;
605-
insert_resource(&iomem_resource, &crashk_res);
606619
memblock_remove(crash_base, crash_size);
607620
pr_info("Reserving %lluMB of memory at %lluMB "
608621
"for crashkernel (System RAM: %luMB)\n",

0 commit comments

Comments
 (0)