diff options
Diffstat (limited to 'kernel/kexec.c')
-rw-r--r-- | kernel/kexec.c | 78 |
1 files changed, 53 insertions, 25 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c index 5e4bd7864c5d..bddd3d7a74b6 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
@@ -54,6 +54,12 @@ struct resource crashk_res = { | |||
54 | .end = 0, | 54 | .end = 0, |
55 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM | 55 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM |
56 | }; | 56 | }; |
57 | struct resource crashk_low_res = { | ||
58 | .name = "Crash kernel low", | ||
59 | .start = 0, | ||
60 | .end = 0, | ||
61 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM | ||
62 | }; | ||
57 | 63 | ||
58 | int kexec_should_crash(struct task_struct *p) | 64 | int kexec_should_crash(struct task_struct *p) |
59 | { | 65 | { |
@@ -223,6 +229,8 @@ out: | |||
223 | 229 | ||
224 | } | 230 | } |
225 | 231 | ||
232 | static void kimage_free_page_list(struct list_head *list); | ||
233 | |||
226 | static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry, | 234 | static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry, |
227 | unsigned long nr_segments, | 235 | unsigned long nr_segments, |
228 | struct kexec_segment __user *segments) | 236 | struct kexec_segment __user *segments) |
@@ -236,8 +244,6 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry, | |||
236 | if (result) | 244 | if (result) |
237 | goto out; | 245 | goto out; |
238 | 246 | ||
239 | *rimage = image; | ||
240 | |||
241 | /* | 247 | /* |
242 | * Find a location for the control code buffer, and add it | 248 | * Find a location for the control code buffer, and add it |
243 | * the vector of segments so that it's pages will also be | 249 | * the vector of segments so that it's pages will also be |
@@ -248,22 +254,22 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry, | |||
248 | get_order(KEXEC_CONTROL_PAGE_SIZE)); | 254 | get_order(KEXEC_CONTROL_PAGE_SIZE)); |
249 | if (!image->control_code_page) { | 255 | if (!image->control_code_page) { |
250 | printk(KERN_ERR "Could not allocate control_code_buffer\n"); | 256 | printk(KERN_ERR "Could not allocate control_code_buffer\n"); |
251 | goto out; | 257 | goto out_free; |
252 | } | 258 | } |
253 | 259 | ||
254 | image->swap_page = kimage_alloc_control_pages(image, 0); | 260 | image->swap_page = kimage_alloc_control_pages(image, 0); |
255 | if (!image->swap_page) { | 261 | if (!image->swap_page) { |
256 | printk(KERN_ERR "Could not allocate swap buffer\n"); | 262 | printk(KERN_ERR "Could not allocate swap buffer\n"); |
257 | goto out; | 263 | goto out_free; |
258 | } | 264 | } |
259 | 265 | ||
260 | result = 0; | 266 | *rimage = image; |
261 | out: | 267 | return 0; |
262 | if (result == 0) | ||
263 | *rimage = image; | ||
264 | else | ||
265 | kfree(image); | ||
266 | 268 | ||
269 | out_free: | ||
270 | kimage_free_page_list(&image->control_pages); | ||
271 | kfree(image); | ||
272 | out: | ||
267 | return result; | 273 | return result; |
268 | } | 274 | } |
269 | 275 | ||
@@ -310,7 +316,7 @@ static int kimage_crash_alloc(struct kimage **rimage, unsigned long entry, | |||
310 | mend = mstart + image->segment[i].memsz - 1; | 316 | mend = mstart + image->segment[i].memsz - 1; |
311 | /* Ensure we are within the crash kernel limits */ | 317 | /* Ensure we are within the crash kernel limits */ |
312 | if ((mstart < crashk_res.start) || (mend > crashk_res.end)) | 318 | if ((mstart < crashk_res.start) || (mend > crashk_res.end)) |
313 | goto out; | 319 | goto out_free; |
314 | } | 320 | } |
315 | 321 | ||
316 | /* | 322 | /* |
@@ -323,16 +329,15 @@ static int kimage_crash_alloc(struct kimage **rimage, unsigned long entry, | |||
323 | get_order(KEXEC_CONTROL_PAGE_SIZE)); | 329 | get_order(KEXEC_CONTROL_PAGE_SIZE)); |
324 | if (!image->control_code_page) { | 330 | if (!image->control_code_page) { |
325 | printk(KERN_ERR "Could not allocate control_code_buffer\n"); | 331 | printk(KERN_ERR "Could not allocate control_code_buffer\n"); |
326 | goto out; | 332 | goto out_free; |
327 | } | 333 | } |
328 | 334 | ||
329 | result = 0; | 335 | *rimage = image; |
330 | out: | 336 | return 0; |
331 | if (result == 0) | ||
332 | *rimage = image; | ||
333 | else | ||
334 | kfree(image); | ||
335 | 337 | ||
338 | out_free: | ||
339 | kfree(image); | ||
340 | out: | ||
336 | return result; | 341 | return result; |
337 | } | 342 | } |
338 | 343 | ||
@@ -497,8 +502,6 @@ static struct page *kimage_alloc_crash_control_pages(struct kimage *image, | |||
497 | 502 | ||
498 | if (hole_end > KEXEC_CRASH_CONTROL_MEMORY_LIMIT) | 503 | if (hole_end > KEXEC_CRASH_CONTROL_MEMORY_LIMIT) |
499 | break; | 504 | break; |
500 | if (hole_end > crashk_res.end) | ||
501 | break; | ||
502 | /* See if I overlap any of the segments */ | 505 | /* See if I overlap any of the segments */ |
503 | for (i = 0; i < image->nr_segments; i++) { | 506 | for (i = 0; i < image->nr_segments; i++) { |
504 | unsigned long mstart, mend; | 507 | unsigned long mstart, mend; |
@@ -1369,10 +1372,11 @@ static int __init parse_crashkernel_simple(char *cmdline, | |||
1369 | * That function is the entry point for command line parsing and should be | 1372 | * That function is the entry point for command line parsing and should be |
1370 | * called from the arch-specific code. | 1373 | * called from the arch-specific code. |
1371 | */ | 1374 | */ |
1372 | int __init parse_crashkernel(char *cmdline, | 1375 | static int __init __parse_crashkernel(char *cmdline, |
1373 | unsigned long long system_ram, | 1376 | unsigned long long system_ram, |
1374 | unsigned long long *crash_size, | 1377 | unsigned long long *crash_size, |
1375 | unsigned long long *crash_base) | 1378 | unsigned long long *crash_base, |
1379 | const char *name) | ||
1376 | { | 1380 | { |
1377 | char *p = cmdline, *ck_cmdline = NULL; | 1381 | char *p = cmdline, *ck_cmdline = NULL; |
1378 | char *first_colon, *first_space; | 1382 | char *first_colon, *first_space; |
@@ -1382,16 +1386,16 @@ int __init parse_crashkernel(char *cmdline, | |||
1382 | *crash_base = 0; | 1386 | *crash_base = 0; |
1383 | 1387 | ||
1384 | /* find crashkernel and use the last one if there are more */ | 1388 | /* find crashkernel and use the last one if there are more */ |
1385 | p = strstr(p, "crashkernel="); | 1389 | p = strstr(p, name); |
1386 | while (p) { | 1390 | while (p) { |
1387 | ck_cmdline = p; | 1391 | ck_cmdline = p; |
1388 | p = strstr(p+1, "crashkernel="); | 1392 | p = strstr(p+1, name); |
1389 | } | 1393 | } |
1390 | 1394 | ||
1391 | if (!ck_cmdline) | 1395 | if (!ck_cmdline) |
1392 | return -EINVAL; | 1396 | return -EINVAL; |
1393 | 1397 | ||
1394 | ck_cmdline += 12; /* strlen("crashkernel=") */ | 1398 | ck_cmdline += strlen(name); |
1395 | 1399 | ||
1396 | /* | 1400 | /* |
1397 | * if the commandline contains a ':', then that's the extended | 1401 | * if the commandline contains a ':', then that's the extended |
@@ -1409,6 +1413,23 @@ int __init parse_crashkernel(char *cmdline, | |||
1409 | return 0; | 1413 | return 0; |
1410 | } | 1414 | } |
1411 | 1415 | ||
1416 | int __init parse_crashkernel(char *cmdline, | ||
1417 | unsigned long long system_ram, | ||
1418 | unsigned long long *crash_size, | ||
1419 | unsigned long long *crash_base) | ||
1420 | { | ||
1421 | return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base, | ||
1422 | "crashkernel="); | ||
1423 | } | ||
1424 | |||
1425 | int __init parse_crashkernel_low(char *cmdline, | ||
1426 | unsigned long long system_ram, | ||
1427 | unsigned long long *crash_size, | ||
1428 | unsigned long long *crash_base) | ||
1429 | { | ||
1430 | return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base, | ||
1431 | "crashkernel_low="); | ||
1432 | } | ||
1412 | 1433 | ||
1413 | static void update_vmcoreinfo_note(void) | 1434 | static void update_vmcoreinfo_note(void) |
1414 | { | 1435 | { |
@@ -1490,6 +1511,8 @@ static int __init crash_save_vmcoreinfo_init(void) | |||
1490 | VMCOREINFO_OFFSET(page, _count); | 1511 | VMCOREINFO_OFFSET(page, _count); |
1491 | VMCOREINFO_OFFSET(page, mapping); | 1512 | VMCOREINFO_OFFSET(page, mapping); |
1492 | VMCOREINFO_OFFSET(page, lru); | 1513 | VMCOREINFO_OFFSET(page, lru); |
1514 | VMCOREINFO_OFFSET(page, _mapcount); | ||
1515 | VMCOREINFO_OFFSET(page, private); | ||
1493 | VMCOREINFO_OFFSET(pglist_data, node_zones); | 1516 | VMCOREINFO_OFFSET(pglist_data, node_zones); |
1494 | VMCOREINFO_OFFSET(pglist_data, nr_zones); | 1517 | VMCOREINFO_OFFSET(pglist_data, nr_zones); |
1495 | #ifdef CONFIG_FLAT_NODE_MEM_MAP | 1518 | #ifdef CONFIG_FLAT_NODE_MEM_MAP |
@@ -1512,6 +1535,11 @@ static int __init crash_save_vmcoreinfo_init(void) | |||
1512 | VMCOREINFO_NUMBER(PG_lru); | 1535 | VMCOREINFO_NUMBER(PG_lru); |
1513 | VMCOREINFO_NUMBER(PG_private); | 1536 | VMCOREINFO_NUMBER(PG_private); |
1514 | VMCOREINFO_NUMBER(PG_swapcache); | 1537 | VMCOREINFO_NUMBER(PG_swapcache); |
1538 | VMCOREINFO_NUMBER(PG_slab); | ||
1539 | #ifdef CONFIG_MEMORY_FAILURE | ||
1540 | VMCOREINFO_NUMBER(PG_hwpoison); | ||
1541 | #endif | ||
1542 | VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE); | ||
1515 | 1543 | ||
1516 | arch_crash_save_vmcoreinfo(); | 1544 | arch_crash_save_vmcoreinfo(); |
1517 | update_vmcoreinfo_note(); | 1545 | update_vmcoreinfo_note(); |