@@ -1297,6 +1297,28 @@ static inline void setup_vm_final(void)
1297
1297
}
1298
1298
#endif /* CONFIG_MMU */
1299
1299
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
+
1300
1322
/*
1301
1323
* reserve_crashkernel() - reserves memory for crash kernel
1302
1324
*
@@ -1308,8 +1330,12 @@ static void __init reserve_crashkernel(void)
1308
1330
{
1309
1331
unsigned long long crash_base = 0 ;
1310
1332
unsigned long long crash_size = 0 ;
1333
+ unsigned long long crash_low_size = 0 ;
1311
1334
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;
1313
1339
1314
1340
int ret = 0 ;
1315
1341
@@ -1325,14 +1351,36 @@ static void __init reserve_crashkernel(void)
1325
1351
return ;
1326
1352
}
1327
1353
1328
- ret = parse_crashkernel (boot_command_line , memblock_phys_mem_size (),
1354
+ ret = parse_crashkernel (cmdline , memblock_phys_mem_size (),
1329
1355
& 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 */
1331
1377
return ;
1378
+ }
1332
1379
1333
1380
crash_size = PAGE_ALIGN (crash_size );
1334
1381
1335
1382
if (crash_base ) {
1383
+ fixed_base = true;
1336
1384
search_start = crash_base ;
1337
1385
search_end = crash_base + crash_size ;
1338
1386
}
@@ -1345,19 +1393,50 @@ static void __init reserve_crashkernel(void)
1345
1393
* swiotlb can work on the crash kernel.
1346
1394
*/
1347
1395
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 );
1350
1397
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
+
1352
1425
crash_base = memblock_phys_alloc_range (crash_size , PMD_SIZE ,
1353
- search_start , search_end );
1426
+ search_start , search_end );
1354
1427
if (crash_base == 0 ) {
1355
1428
pr_warn ("crashkernel: couldn't allocate %lldKB\n" ,
1356
1429
crash_size >> 10 );
1357
1430
return ;
1358
1431
}
1359
1432
}
1360
1433
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
+
1361
1440
pr_info ("crashkernel: reserved 0x%016llx - 0x%016llx (%lld MB)\n" ,
1362
1441
crash_base , crash_base + crash_size , crash_size >> 20 );
1363
1442
0 commit comments