Skip to content

Commit 9389e67

Browse files
Merge patch series "support allocating crashkernel above 4G explicitly on riscv"
Chen Jiahao <[email protected]> says: On riscv, the current crash kernel allocation logic is trying to allocate within 32bit addressible memory region by default, if failed, try to allocate without 4G restriction. In need of saving DMA zone memory while allocating a relatively large crash kernel region, allocating the reserved memory top down in high memory, without overlapping the DMA zone, is a mature solution. Hence this patchset introduces the parameter option crashkernel=X,[high,low]. One can reserve the crash kernel from high memory above DMA zone range by explicitly passing "crashkernel=X,high"; or reserve a memory range below 4G with "crashkernel=X,low". Besides, there are few rules need to take notice: 1. "crashkernel=X,[high,low]" will be ignored if "crashkernel=size" is specified. 2. "crashkernel=X,low" is valid only when "crashkernel=X,high" is passed and there is enough memory to be allocated under 4G. 3. When allocating crashkernel above 4G and no "crashkernel=X,low" is specified, a 128M low memory will be allocated automatically for swiotlb bounce buffer. See Documentation/admin-guide/kernel-parameters.txt for more information. To verify loading the crashkernel, adapted kexec-tools is attached below: https://github.com/chenjh005/kexec-tools/tree/build-test-riscv-v2 Following test cases have been performed as expected: 1) crashkernel=256M //low=256M 2) crashkernel=1G //low=1G 3) crashkernel=4G //high=4G, low=128M(default) 4) crashkernel=4G crashkernel=256M,high //high=4G, low=128M(default), high is ignored 5) crashkernel=4G crashkernel=256M,low //high=4G, low=128M(default), low is ignored 6) crashkernel=4G,high //high=4G, low=128M(default) 7) crashkernel=256M,low //low=0M, invalid 8) crashkernel=4G,high crashkernel=256M,low //high=4G, low=256M 9) crashkernel=4G,high crashkernel=4G,low //high=0M, low=0M, invalid 10) crashkernel=512M@0xd0000000 //low=512M 11) crashkernel=1G,high crashkernel=0M,low //high=1G, low=0M * b4-shazam-merge: docs: kdump: Update the crashkernel description for riscv riscv: kdump: Implement crashkernel=X,[high,low] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
2 parents 82dfb5f + 33f0dd9 commit 9389e67

File tree

3 files changed

+99
-14
lines changed

3 files changed

+99
-14
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,7 @@
862862
memory region [offset, offset + size] for that kernel
863863
image. If '@offset' is omitted, then a suitable offset
864864
is selected automatically.
865-
[KNL, X86-64, ARM64] Select a region under 4G first, and
865+
[KNL, X86-64, ARM64, RISCV] Select a region under 4G first, and
866866
fall back to reserve region above 4G when '@offset'
867867
hasn't been specified.
868868
See Documentation/admin-guide/kdump/kdump.rst for further details.
@@ -875,14 +875,14 @@
875875
Documentation/admin-guide/kdump/kdump.rst for an example.
876876

877877
crashkernel=size[KMG],high
878-
[KNL, X86-64, ARM64] range could be above 4G. Allow kernel
879-
to allocate physical memory region from top, so could
880-
be above 4G if system have more than 4G ram installed.
881-
Otherwise memory region will be allocated below 4G, if
882-
available.
878+
[KNL, X86-64, ARM64, RISCV] range could be above 4G.
879+
Allow kernel to allocate physical memory region from top,
880+
so could be above 4G if system have more than 4G ram
881+
installed. Otherwise memory region will be allocated
882+
below 4G, if available.
883883
It will be ignored if crashkernel=X is specified.
884884
crashkernel=size[KMG],low
885-
[KNL, X86-64, ARM64] range under 4G. When crashkernel=X,high
885+
[KNL, X86-64, ARM64, RISCV] range under 4G. When crashkernel=X,high
886886
is passed, kernel could allocate physical memory region
887887
above 4G, that cause second kernel crash on system
888888
that require some amount of low memory, e.g. swiotlb
@@ -893,6 +893,7 @@
893893
size is platform dependent.
894894
--> x86: max(swiotlb_size_or_default() + 8MiB, 256MiB)
895895
--> arm64: 128MiB
896+
--> riscv: 128MiB
896897
This one lets the user specify own low range under 4G
897898
for second kernel instead.
898899
0: to disable low allocation.

arch/riscv/kernel/setup.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@ static void __init init_resources(void)
178178
if (ret < 0)
179179
goto error;
180180
}
181+
if (crashk_low_res.start != crashk_low_res.end) {
182+
ret = add_resource(&iomem_resource, &crashk_low_res);
183+
if (ret < 0)
184+
goto error;
185+
}
181186
#endif
182187

183188
#ifdef CONFIG_CRASH_DUMP

arch/riscv/mm/init.c

Lines changed: 86 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,6 +1297,28 @@ static inline void setup_vm_final(void)
12971297
}
12981298
#endif /* CONFIG_MMU */
12991299

1300+
/* Reserve 128M low memory by default for swiotlb buffer */
1301+
#define DEFAULT_CRASH_KERNEL_LOW_SIZE (128UL << 20)
1302+
1303+
static int __init reserve_crashkernel_low(unsigned long long low_size)
1304+
{
1305+
unsigned long long low_base;
1306+
1307+
low_base = memblock_phys_alloc_range(low_size, PMD_SIZE, 0, dma32_phys_limit);
1308+
if (!low_base) {
1309+
pr_err("cannot allocate crashkernel low memory (size:0x%llx).\n", low_size);
1310+
return -ENOMEM;
1311+
}
1312+
1313+
pr_info("crashkernel low memory reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
1314+
low_base, low_base + low_size, low_size >> 20);
1315+
1316+
crashk_low_res.start = low_base;
1317+
crashk_low_res.end = low_base + low_size - 1;
1318+
1319+
return 0;
1320+
}
1321+
13001322
/*
13011323
* reserve_crashkernel() - reserves memory for crash kernel
13021324
*
@@ -1308,8 +1330,12 @@ static void __init reserve_crashkernel(void)
13081330
{
13091331
unsigned long long crash_base = 0;
13101332
unsigned long long crash_size = 0;
1333+
unsigned long long crash_low_size = 0;
13111334
unsigned long search_start = memblock_start_of_DRAM();
1312-
unsigned long search_end = memblock_end_of_DRAM();
1335+
unsigned long search_end = (unsigned long)dma32_phys_limit;
1336+
char *cmdline = boot_command_line;
1337+
bool fixed_base = false;
1338+
bool high = false;
13131339

13141340
int ret = 0;
13151341

@@ -1325,14 +1351,36 @@ static void __init reserve_crashkernel(void)
13251351
return;
13261352
}
13271353

1328-
ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),
1354+
ret = parse_crashkernel(cmdline, memblock_phys_mem_size(),
13291355
&crash_size, &crash_base);
1330-
if (ret || !crash_size)
1356+
if (ret == -ENOENT) {
1357+
/* Fallback to crashkernel=X,[high,low] */
1358+
ret = parse_crashkernel_high(cmdline, 0, &crash_size, &crash_base);
1359+
if (ret || !crash_size)
1360+
return;
1361+
1362+
/*
1363+
* crashkernel=Y,low is valid only when crashkernel=X,high
1364+
* is passed.
1365+
*/
1366+
ret = parse_crashkernel_low(cmdline, 0, &crash_low_size, &crash_base);
1367+
if (ret == -ENOENT)
1368+
crash_low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
1369+
else if (ret)
1370+
return;
1371+
1372+
search_start = (unsigned long)dma32_phys_limit;
1373+
search_end = memblock_end_of_DRAM();
1374+
high = true;
1375+
} else if (ret || !crash_size) {
1376+
/* Invalid argument value specified */
13311377
return;
1378+
}
13321379

13331380
crash_size = PAGE_ALIGN(crash_size);
13341381

13351382
if (crash_base) {
1383+
fixed_base = true;
13361384
search_start = crash_base;
13371385
search_end = crash_base + crash_size;
13381386
}
@@ -1345,19 +1393,50 @@ static void __init reserve_crashkernel(void)
13451393
* swiotlb can work on the crash kernel.
13461394
*/
13471395
crash_base = memblock_phys_alloc_range(crash_size, PMD_SIZE,
1348-
search_start,
1349-
min(search_end, (unsigned long) SZ_4G));
1396+
search_start, search_end);
13501397
if (crash_base == 0) {
1351-
/* Try again without restricting region to 32bit addressible memory */
1398+
/*
1399+
* For crashkernel=size[KMG]@offset[KMG], print out failure
1400+
* message if can't reserve the specified region.
1401+
*/
1402+
if (fixed_base) {
1403+
pr_warn("crashkernel: allocating failed with given size@offset\n");
1404+
return;
1405+
}
1406+
1407+
if (high) {
1408+
/*
1409+
* For crashkernel=size[KMG],high, if the first attempt was
1410+
* for high memory, fall back to low memory.
1411+
*/
1412+
search_start = memblock_start_of_DRAM();
1413+
search_end = (unsigned long)dma32_phys_limit;
1414+
} else {
1415+
/*
1416+
* For crashkernel=size[KMG], if the first attempt was for
1417+
* low memory, fall back to high memory, the minimum required
1418+
* low memory will be reserved later.
1419+
*/
1420+
search_start = (unsigned long)dma32_phys_limit;
1421+
search_end = memblock_end_of_DRAM();
1422+
crash_low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
1423+
}
1424+
13521425
crash_base = memblock_phys_alloc_range(crash_size, PMD_SIZE,
1353-
search_start, search_end);
1426+
search_start, search_end);
13541427
if (crash_base == 0) {
13551428
pr_warn("crashkernel: couldn't allocate %lldKB\n",
13561429
crash_size >> 10);
13571430
return;
13581431
}
13591432
}
13601433

1434+
if ((crash_base >= dma32_phys_limit) && crash_low_size &&
1435+
reserve_crashkernel_low(crash_low_size)) {
1436+
memblock_phys_free(crash_base, crash_size);
1437+
return;
1438+
}
1439+
13611440
pr_info("crashkernel: reserved 0x%016llx - 0x%016llx (%lld MB)\n",
13621441
crash_base, crash_base + crash_size, crash_size >> 20);
13631442

0 commit comments

Comments
 (0)