diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/kexec.c | 46 |
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 | } |
| 1154 | out: | 1175 | out: |
| @@ -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; |
