Skip to content

Commit 5882e5a

Browse files
Chen Jiahaopalmer-dabbelt
authored andcommitted
riscv: kdump: Implement crashkernel=X,[high,low]
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. Here introduce 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". Signed-off-by: Chen Jiahao <[email protected]> Acked-by: Guo Ren <[email protected]> Acked-by: Baoquan He <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 06c2afb commit 5882e5a

File tree

2 files changed

+91
-7
lines changed

2 files changed

+91
-7
lines changed

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)