Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 830ac85

Browse files
committed
Merge branch 'x86-kdump-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull kdump fixes from Peter Anvin: "The kexec/kdump people have found several problems with the support for loading over 4 GiB that was introduced in this merge cycle. This is partly due to a number of design problems inherent in the way the various pieces of kdump fit together (it is pretty horrifically manual in many places.) After a *lot* of iterations this is the patchset that was agreed upon, but of course it is now very late in the cycle. However, because it changes both the syntax and semantics of the crashkernel option, it would be desirable to avoid a stable release with the broken interfaces." I'm not happy with the timing, since originally the plan was to release the final 3.9 tomorrow. But apparently I'm doing an -rc8 instead... * 'x86-kdump-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: kexec: use Crash kernel for Crash kernel low x86, kdump: Change crashkernel_high/low= to crashkernel=,high/low x86, kdump: Retore crashkernel= to allocate under 896M x86, kdump: Set crashkernel_low automatically
2 parents db93f8b + 157752d commit 830ac85

File tree

6 files changed

+180
-28
lines changed

6 files changed

+180
-28
lines changed

Documentation/kernel-parameters.txt

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -596,16 +596,33 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
596596
is selected automatically. Check
597597
Documentation/kdump/kdump.txt for further details.
598598

599-
crashkernel_low=size[KMG]
600-
[KNL, x86] parts under 4G.
601-
602599
crashkernel=range1:size1[,range2:size2,...][@offset]
603600
[KNL] Same as above, but depends on the memory
604601
in the running system. The syntax of range is
605602
start-[end] where start and end are both
606603
a memory unit (amount[KMG]). See also
607604
Documentation/kdump/kdump.txt for an example.
608605

606+
crashkernel=size[KMG],high
607+
[KNL, x86_64] range could be above 4G. Allow kernel
608+
to allocate physical memory region from top, so could
609+
be above 4G if system have more than 4G ram installed.
610+
Otherwise memory region will be allocated below 4G, if
611+
available.
612+
It will be ignored if crashkernel=X is specified.
613+
crashkernel=size[KMG],low
614+
[KNL, x86_64] range under 4G. When crashkernel=X,high
615+
is passed, kernel could allocate physical memory region
616+
above 4G, that cause second kernel crash on system
617+
that require some amount of low memory, e.g. swiotlb
618+
requires at least 64M+32K low memory. Kernel would
619+
try to allocate 72M below 4G automatically.
620+
This one let user to specify own low range under 4G
621+
for second kernel instead.
622+
0: to disable low allocation.
623+
It will be ignored when crashkernel=X,high is not used
624+
or memory reserved is below 4G.
625+
609626
cs89x0_dma= [HW,NET]
610627
Format: <dma>
611628

arch/x86/kernel/setup.c

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -507,11 +507,14 @@ static void __init memblock_x86_reserve_range_setup_data(void)
507507
/*
508508
* Keep the crash kernel below this limit. On 32 bits earlier kernels
509509
* would limit the kernel to the low 512 MiB due to mapping restrictions.
510+
* On 64bit, old kexec-tools need to under 896MiB.
510511
*/
511512
#ifdef CONFIG_X86_32
512-
# define CRASH_KERNEL_ADDR_MAX (512 << 20)
513+
# define CRASH_KERNEL_ADDR_LOW_MAX (512 << 20)
514+
# define CRASH_KERNEL_ADDR_HIGH_MAX (512 << 20)
513515
#else
514-
# define CRASH_KERNEL_ADDR_MAX MAXMEM
516+
# define CRASH_KERNEL_ADDR_LOW_MAX (896UL<<20)
517+
# define CRASH_KERNEL_ADDR_HIGH_MAX MAXMEM
515518
#endif
516519

517520
static void __init reserve_crashkernel_low(void)
@@ -521,19 +524,35 @@ static void __init reserve_crashkernel_low(void)
521524
unsigned long long low_base = 0, low_size = 0;
522525
unsigned long total_low_mem;
523526
unsigned long long base;
527+
bool auto_set = false;
524528
int ret;
525529

526530
total_low_mem = memblock_mem_size(1UL<<(32-PAGE_SHIFT));
531+
/* crashkernel=Y,low */
527532
ret = parse_crashkernel_low(boot_command_line, total_low_mem,
528533
&low_size, &base);
529-
if (ret != 0 || low_size <= 0)
530-
return;
534+
if (ret != 0) {
535+
/*
536+
* two parts from lib/swiotlb.c:
537+
* swiotlb size: user specified with swiotlb= or default.
538+
* swiotlb overflow buffer: now is hardcoded to 32k.
539+
* We round it to 8M for other buffers that
540+
* may need to stay low too.
541+
*/
542+
low_size = swiotlb_size_or_default() + (8UL<<20);
543+
auto_set = true;
544+
} else {
545+
/* passed with crashkernel=0,low ? */
546+
if (!low_size)
547+
return;
548+
}
531549

532550
low_base = memblock_find_in_range(low_size, (1ULL<<32),
533551
low_size, alignment);
534552

535553
if (!low_base) {
536-
pr_info("crashkernel low reservation failed - No suitable area found.\n");
554+
if (!auto_set)
555+
pr_info("crashkernel low reservation failed - No suitable area found.\n");
537556

538557
return;
539558
}
@@ -554,22 +573,32 @@ static void __init reserve_crashkernel(void)
554573
const unsigned long long alignment = 16<<20; /* 16M */
555574
unsigned long long total_mem;
556575
unsigned long long crash_size, crash_base;
576+
bool high = false;
557577
int ret;
558578

559579
total_mem = memblock_phys_mem_size();
560580

581+
/* crashkernel=XM */
561582
ret = parse_crashkernel(boot_command_line, total_mem,
562583
&crash_size, &crash_base);
563-
if (ret != 0 || crash_size <= 0)
564-
return;
584+
if (ret != 0 || crash_size <= 0) {
585+
/* crashkernel=X,high */
586+
ret = parse_crashkernel_high(boot_command_line, total_mem,
587+
&crash_size, &crash_base);
588+
if (ret != 0 || crash_size <= 0)
589+
return;
590+
high = true;
591+
}
565592

566593
/* 0 means: find the address automatically */
567594
if (crash_base <= 0) {
568595
/*
569596
* kexec want bzImage is below CRASH_KERNEL_ADDR_MAX
570597
*/
571598
crash_base = memblock_find_in_range(alignment,
572-
CRASH_KERNEL_ADDR_MAX, crash_size, alignment);
599+
high ? CRASH_KERNEL_ADDR_HIGH_MAX :
600+
CRASH_KERNEL_ADDR_LOW_MAX,
601+
crash_size, alignment);
573602

574603
if (!crash_base) {
575604
pr_info("crashkernel reservation failed - No suitable area found.\n");

include/linux/kexec.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ extern size_t vmcoreinfo_max_size;
200200

201201
int __init parse_crashkernel(char *cmdline, unsigned long long system_ram,
202202
unsigned long long *crash_size, unsigned long long *crash_base);
203+
int parse_crashkernel_high(char *cmdline, unsigned long long system_ram,
204+
unsigned long long *crash_size, unsigned long long *crash_base);
203205
int parse_crashkernel_low(char *cmdline, unsigned long long system_ram,
204206
unsigned long long *crash_size, unsigned long long *crash_base);
205207
int crash_shrink_memory(unsigned long new_size);

include/linux/swiotlb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ extern int swiotlb_force;
2525
extern void swiotlb_init(int verbose);
2626
int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
2727
extern unsigned long swiotlb_nr_tbl(void);
28+
unsigned long swiotlb_size_or_default(void);
2829
extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs);
2930

3031
/*

kernel/kexec.c

Lines changed: 105 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ struct resource crashk_res = {
5555
.flags = IORESOURCE_BUSY | IORESOURCE_MEM
5656
};
5757
struct resource crashk_low_res = {
58-
.name = "Crash kernel low",
58+
.name = "Crash kernel",
5959
.start = 0,
6060
.end = 0,
6161
.flags = IORESOURCE_BUSY | IORESOURCE_MEM
@@ -1368,35 +1368,114 @@ static int __init parse_crashkernel_simple(char *cmdline,
13681368
return 0;
13691369
}
13701370

1371+
#define SUFFIX_HIGH 0
1372+
#define SUFFIX_LOW 1
1373+
#define SUFFIX_NULL 2
1374+
static __initdata char *suffix_tbl[] = {
1375+
[SUFFIX_HIGH] = ",high",
1376+
[SUFFIX_LOW] = ",low",
1377+
[SUFFIX_NULL] = NULL,
1378+
};
1379+
13711380
/*
1372-
* That function is the entry point for command line parsing and should be
1373-
* called from the arch-specific code.
1381+
* That function parses "suffix" crashkernel command lines like
1382+
*
1383+
* crashkernel=size,[high|low]
1384+
*
1385+
* It returns 0 on success and -EINVAL on failure.
13741386
*/
1387+
static int __init parse_crashkernel_suffix(char *cmdline,
1388+
unsigned long long *crash_size,
1389+
unsigned long long *crash_base,
1390+
const char *suffix)
1391+
{
1392+
char *cur = cmdline;
1393+
1394+
*crash_size = memparse(cmdline, &cur);
1395+
if (cmdline == cur) {
1396+
pr_warn("crashkernel: memory value expected\n");
1397+
return -EINVAL;
1398+
}
1399+
1400+
/* check with suffix */
1401+
if (strncmp(cur, suffix, strlen(suffix))) {
1402+
pr_warn("crashkernel: unrecognized char\n");
1403+
return -EINVAL;
1404+
}
1405+
cur += strlen(suffix);
1406+
if (*cur != ' ' && *cur != '\0') {
1407+
pr_warn("crashkernel: unrecognized char\n");
1408+
return -EINVAL;
1409+
}
1410+
1411+
return 0;
1412+
}
1413+
1414+
static __init char *get_last_crashkernel(char *cmdline,
1415+
const char *name,
1416+
const char *suffix)
1417+
{
1418+
char *p = cmdline, *ck_cmdline = NULL;
1419+
1420+
/* find crashkernel and use the last one if there are more */
1421+
p = strstr(p, name);
1422+
while (p) {
1423+
char *end_p = strchr(p, ' ');
1424+
char *q;
1425+
1426+
if (!end_p)
1427+
end_p = p + strlen(p);
1428+
1429+
if (!suffix) {
1430+
int i;
1431+
1432+
/* skip the one with any known suffix */
1433+
for (i = 0; suffix_tbl[i]; i++) {
1434+
q = end_p - strlen(suffix_tbl[i]);
1435+
if (!strncmp(q, suffix_tbl[i],
1436+
strlen(suffix_tbl[i])))
1437+
goto next;
1438+
}
1439+
ck_cmdline = p;
1440+
} else {
1441+
q = end_p - strlen(suffix);
1442+
if (!strncmp(q, suffix, strlen(suffix)))
1443+
ck_cmdline = p;
1444+
}
1445+
next:
1446+
p = strstr(p+1, name);
1447+
}
1448+
1449+
if (!ck_cmdline)
1450+
return NULL;
1451+
1452+
return ck_cmdline;
1453+
}
1454+
13751455
static int __init __parse_crashkernel(char *cmdline,
13761456
unsigned long long system_ram,
13771457
unsigned long long *crash_size,
13781458
unsigned long long *crash_base,
1379-
const char *name)
1459+
const char *name,
1460+
const char *suffix)
13801461
{
1381-
char *p = cmdline, *ck_cmdline = NULL;
13821462
char *first_colon, *first_space;
1463+
char *ck_cmdline;
13831464

13841465
BUG_ON(!crash_size || !crash_base);
13851466
*crash_size = 0;
13861467
*crash_base = 0;
13871468

1388-
/* find crashkernel and use the last one if there are more */
1389-
p = strstr(p, name);
1390-
while (p) {
1391-
ck_cmdline = p;
1392-
p = strstr(p+1, name);
1393-
}
1469+
ck_cmdline = get_last_crashkernel(cmdline, name, suffix);
13941470

13951471
if (!ck_cmdline)
13961472
return -EINVAL;
13971473

13981474
ck_cmdline += strlen(name);
13991475

1476+
if (suffix)
1477+
return parse_crashkernel_suffix(ck_cmdline, crash_size,
1478+
crash_base, suffix);
14001479
/*
14011480
* if the commandline contains a ':', then that's the extended
14021481
* syntax -- if not, it must be the classic syntax
@@ -1413,13 +1492,26 @@ static int __init __parse_crashkernel(char *cmdline,
14131492
return 0;
14141493
}
14151494

1495+
/*
1496+
* That function is the entry point for command line parsing and should be
1497+
* called from the arch-specific code.
1498+
*/
14161499
int __init parse_crashkernel(char *cmdline,
14171500
unsigned long long system_ram,
14181501
unsigned long long *crash_size,
14191502
unsigned long long *crash_base)
14201503
{
14211504
return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
1422-
"crashkernel=");
1505+
"crashkernel=", NULL);
1506+
}
1507+
1508+
int __init parse_crashkernel_high(char *cmdline,
1509+
unsigned long long system_ram,
1510+
unsigned long long *crash_size,
1511+
unsigned long long *crash_base)
1512+
{
1513+
return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
1514+
"crashkernel=", suffix_tbl[SUFFIX_HIGH]);
14231515
}
14241516

14251517
int __init parse_crashkernel_low(char *cmdline,
@@ -1428,7 +1520,7 @@ int __init parse_crashkernel_low(char *cmdline,
14281520
unsigned long long *crash_base)
14291521
{
14301522
return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
1431-
"crashkernel_low=");
1523+
"crashkernel=", suffix_tbl[SUFFIX_LOW]);
14321524
}
14331525

14341526
static void update_vmcoreinfo_note(void)

lib/swiotlb.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,16 +105,28 @@ setup_io_tlb_npages(char *str)
105105
if (!strcmp(str, "force"))
106106
swiotlb_force = 1;
107107

108-
return 1;
108+
return 0;
109109
}
110-
__setup("swiotlb=", setup_io_tlb_npages);
110+
early_param("swiotlb", setup_io_tlb_npages);
111111
/* make io_tlb_overflow tunable too? */
112112

113113
unsigned long swiotlb_nr_tbl(void)
114114
{
115115
return io_tlb_nslabs;
116116
}
117117
EXPORT_SYMBOL_GPL(swiotlb_nr_tbl);
118+
119+
/* default to 64MB */
120+
#define IO_TLB_DEFAULT_SIZE (64UL<<20)
121+
unsigned long swiotlb_size_or_default(void)
122+
{
123+
unsigned long size;
124+
125+
size = io_tlb_nslabs << IO_TLB_SHIFT;
126+
127+
return size ? size : (IO_TLB_DEFAULT_SIZE);
128+
}
129+
118130
/* Note that this doesn't work with highmem page */
119131
static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
120132
volatile void *address)
@@ -188,8 +200,7 @@ int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
188200
void __init
189201
swiotlb_init(int verbose)
190202
{
191-
/* default to 64MB */
192-
size_t default_size = 64UL<<20;
203+
size_t default_size = IO_TLB_DEFAULT_SIZE;
193204
unsigned char *vstart;
194205
unsigned long bytes;
195206

0 commit comments

Comments
 (0)