aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/kexec.c
diff options
context:
space:
mode:
authorVivek Goyal <vgoyal@redhat.com>2014-08-08 17:26:09 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-08 18:57:33 -0400
commitdd5f726076cc7639d9713b334c8c133f77c6757a (patch)
tree6b3e88bdf3e764d97eb88464e31abc097dab44f6 /kernel/kexec.c
parent27f48d3e633be23656a097baa3be336e04a82d84 (diff)
kexec: support for kexec on panic using new system call
This patch adds support for loading a kexec on panic (kdump) kernel usning new system call. It prepares ELF headers for memory areas to be dumped and for saved cpu registers. Also prepares the memory map for second kernel and limits its boot to reserved areas only. Signed-off-by: Vivek Goyal <vgoyal@redhat.com> Cc: Borislav Petkov <bp@suse.de> Cc: Michael Kerrisk <mtk.manpages@gmail.com> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Eric Biederman <ebiederm@xmission.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Matthew Garrett <mjg59@srcf.ucam.org> Cc: Greg Kroah-Hartman <greg@kroah.com> Cc: Dave Young <dyoung@redhat.com> Cc: WANG Chao <chaowang@redhat.com> Cc: Baoquan He <bhe@redhat.com> Cc: Andy Lutomirski <luto@amacapital.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/kexec.c')
-rw-r--r--kernel/kexec.c46
1 files changed, 37 insertions, 9 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 0926f2a3ed03..f18c780f9716 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -548,6 +548,7 @@ kimage_file_alloc_init(struct kimage **rimage, int kernel_fd,
548{ 548{
549 int ret; 549 int ret;
550 struct kimage *image; 550 struct kimage *image;
551 bool kexec_on_panic = flags & KEXEC_FILE_ON_CRASH;
551 552
552 image = do_kimage_alloc_init(); 553 image = do_kimage_alloc_init();
553 if (!image) 554 if (!image)
@@ -555,6 +556,12 @@ kimage_file_alloc_init(struct kimage **rimage, int kernel_fd,
555 556
556 image->file_mode = 1; 557 image->file_mode = 1;
557 558
559 if (kexec_on_panic) {
560 /* Enable special crash kernel control page alloc policy. */
561 image->control_page = crashk_res.start;
562 image->type = KEXEC_TYPE_CRASH;
563 }
564
558 ret = kimage_file_prepare_segments(image, kernel_fd, initrd_fd, 565 ret = kimage_file_prepare_segments(image, kernel_fd, initrd_fd,
559 cmdline_ptr, cmdline_len, flags); 566 cmdline_ptr, cmdline_len, flags);
560 if (ret) 567 if (ret)
@@ -572,10 +579,12 @@ kimage_file_alloc_init(struct kimage **rimage, int kernel_fd,
572 goto out_free_post_load_bufs; 579 goto out_free_post_load_bufs;
573 } 580 }
574 581
575 image->swap_page = kimage_alloc_control_pages(image, 0); 582 if (!kexec_on_panic) {
576 if (!image->swap_page) { 583 image->swap_page = kimage_alloc_control_pages(image, 0);
577 pr_err(KERN_ERR "Could not allocate swap buffer\n"); 584 if (!image->swap_page) {
578 goto out_free_control_pages; 585 pr_err(KERN_ERR "Could not allocate swap buffer\n");
586 goto out_free_control_pages;
587 }
579 } 588 }
580 589
581 *rimage = image; 590 *rimage = image;
@@ -1113,10 +1122,14 @@ static int kimage_load_crash_segment(struct kimage *image,
1113 unsigned long maddr; 1122 unsigned long maddr;
1114 size_t ubytes, mbytes; 1123 size_t ubytes, mbytes;
1115 int result; 1124 int result;
1116 unsigned char __user *buf; 1125 unsigned char __user *buf = NULL;
1126 unsigned char *kbuf = NULL;
1117 1127
1118 result = 0; 1128 result = 0;
1119 buf = segment->buf; 1129 if (image->file_mode)
1130 kbuf = segment->kbuf;
1131 else
1132 buf = segment->buf;
1120 ubytes = segment->bufsz; 1133 ubytes = segment->bufsz;
1121 mbytes = segment->memsz; 1134 mbytes = segment->memsz;
1122 maddr = segment->mem; 1135 maddr = segment->mem;
@@ -1139,7 +1152,12 @@ static int kimage_load_crash_segment(struct kimage *image,
1139 /* Zero the trailing part of the page */ 1152 /* Zero the trailing part of the page */
1140 memset(ptr + uchunk, 0, mchunk - uchunk); 1153 memset(ptr + uchunk, 0, mchunk - uchunk);
1141 } 1154 }
1142 result = copy_from_user(ptr, buf, uchunk); 1155
1156 /* For file based kexec, source pages are in kernel memory */
1157 if (image->file_mode)
1158 memcpy(ptr, kbuf, uchunk);
1159 else
1160 result = copy_from_user(ptr, buf, uchunk);
1143 kexec_flush_icache_page(page); 1161 kexec_flush_icache_page(page);
1144 kunmap(page); 1162 kunmap(page);
1145 if (result) { 1163 if (result) {
@@ -1148,7 +1166,10 @@ static int kimage_load_crash_segment(struct kimage *image,
1148 } 1166 }
1149 ubytes -= uchunk; 1167 ubytes -= uchunk;
1150 maddr += mchunk; 1168 maddr += mchunk;
1151 buf += mchunk; 1169 if (image->file_mode)
1170 kbuf += mchunk;
1171 else
1172 buf += mchunk;
1152 mbytes -= mchunk; 1173 mbytes -= mchunk;
1153 } 1174 }
1154out: 1175out:
@@ -2127,7 +2148,14 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
2127 kbuf->top_down = top_down; 2148 kbuf->top_down = top_down;
2128 2149
2129 /* Walk the RAM ranges and allocate a suitable range for the buffer */ 2150 /* Walk the RAM ranges and allocate a suitable range for the buffer */
2130 ret = walk_system_ram_res(0, -1, kbuf, locate_mem_hole_callback); 2151 if (image->type == KEXEC_TYPE_CRASH)
2152 ret = walk_iomem_res("Crash kernel",
2153 IORESOURCE_MEM | IORESOURCE_BUSY,
2154 crashk_res.start, crashk_res.end, kbuf,
2155 locate_mem_hole_callback);
2156 else
2157 ret = walk_system_ram_res(0, -1, kbuf,
2158 locate_mem_hole_callback);
2131 if (ret != 1) { 2159 if (ret != 1) {
2132 /* A suitable memory range could not be found for buffer */ 2160 /* A suitable memory range could not be found for buffer */
2133 return -EADDRNOTAVAIL; 2161 return -EADDRNOTAVAIL;