diff options
author | Vivek Goyal <vgoyal@redhat.com> | 2014-08-08 17:25:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-08 18:57:32 -0400 |
commit | 255aedd90e3e804fb52e1a71636a3b22cf12f81b (patch) | |
tree | 5b25989bec463c43a82d159c8b285fdbbb57eb03 /kernel/kexec.c | |
parent | dabe78628dd886c4b71971d1d78f1cecc674b760 (diff) |
kexec: use common function for kimage_normal_alloc() and kimage_crash_alloc()
kimage_normal_alloc() and kimage_crash_alloc() are doing lot of similar
things and differ only little. So instead of having two separate
functions create a common function kimage_alloc_init() and pass it the
"flags" argument which tells whether it is normal kexec or kexec_on_panic.
And this function should be able to deal with both the cases.
This consolidation also helps later where we can use a common function
kimage_file_alloc_init() to handle normal and crash cases for new file
based kexec syscall.
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.c | 105 |
1 files changed, 34 insertions, 71 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c index 062e5567750e..bfdda316697d 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
@@ -261,12 +261,20 @@ static struct kimage *do_kimage_alloc_init(void) | |||
261 | 261 | ||
262 | static void kimage_free_page_list(struct list_head *list); | 262 | static void kimage_free_page_list(struct list_head *list); |
263 | 263 | ||
264 | static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry, | 264 | static int kimage_alloc_init(struct kimage **rimage, unsigned long entry, |
265 | unsigned long nr_segments, | 265 | unsigned long nr_segments, |
266 | struct kexec_segment __user *segments) | 266 | struct kexec_segment __user *segments, |
267 | unsigned long flags) | ||
267 | { | 268 | { |
268 | int result; | 269 | int ret; |
269 | struct kimage *image; | 270 | struct kimage *image; |
271 | bool kexec_on_panic = flags & KEXEC_ON_CRASH; | ||
272 | |||
273 | if (kexec_on_panic) { | ||
274 | /* Verify we have a valid entry point */ | ||
275 | if ((entry < crashk_res.start) || (entry > crashk_res.end)) | ||
276 | return -EADDRNOTAVAIL; | ||
277 | } | ||
270 | 278 | ||
271 | /* Allocate and initialize a controlling structure */ | 279 | /* Allocate and initialize a controlling structure */ |
272 | image = do_kimage_alloc_init(); | 280 | image = do_kimage_alloc_init(); |
@@ -275,20 +283,26 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry, | |||
275 | 283 | ||
276 | image->start = entry; | 284 | image->start = entry; |
277 | 285 | ||
278 | result = copy_user_segment_list(image, nr_segments, segments); | 286 | ret = copy_user_segment_list(image, nr_segments, segments); |
279 | if (result) | 287 | if (ret) |
280 | goto out_free_image; | 288 | goto out_free_image; |
281 | 289 | ||
282 | result = sanity_check_segment_list(image); | 290 | ret = sanity_check_segment_list(image); |
283 | if (result) | 291 | if (ret) |
284 | goto out_free_image; | 292 | goto out_free_image; |
285 | 293 | ||
294 | /* Enable the special crash kernel control page allocation policy. */ | ||
295 | if (kexec_on_panic) { | ||
296 | image->control_page = crashk_res.start; | ||
297 | image->type = KEXEC_TYPE_CRASH; | ||
298 | } | ||
299 | |||
286 | /* | 300 | /* |
287 | * Find a location for the control code buffer, and add it | 301 | * Find a location for the control code buffer, and add it |
288 | * the vector of segments so that it's pages will also be | 302 | * the vector of segments so that it's pages will also be |
289 | * counted as destination pages. | 303 | * counted as destination pages. |
290 | */ | 304 | */ |
291 | result = -ENOMEM; | 305 | ret = -ENOMEM; |
292 | image->control_code_page = kimage_alloc_control_pages(image, | 306 | image->control_code_page = kimage_alloc_control_pages(image, |
293 | get_order(KEXEC_CONTROL_PAGE_SIZE)); | 307 | get_order(KEXEC_CONTROL_PAGE_SIZE)); |
294 | if (!image->control_code_page) { | 308 | if (!image->control_code_page) { |
@@ -296,10 +310,12 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry, | |||
296 | goto out_free_image; | 310 | goto out_free_image; |
297 | } | 311 | } |
298 | 312 | ||
299 | image->swap_page = kimage_alloc_control_pages(image, 0); | 313 | if (!kexec_on_panic) { |
300 | if (!image->swap_page) { | 314 | image->swap_page = kimage_alloc_control_pages(image, 0); |
301 | pr_err("Could not allocate swap buffer\n"); | 315 | if (!image->swap_page) { |
302 | goto out_free_control_pages; | 316 | pr_err("Could not allocate swap buffer\n"); |
317 | goto out_free_control_pages; | ||
318 | } | ||
303 | } | 319 | } |
304 | 320 | ||
305 | *rimage = image; | 321 | *rimage = image; |
@@ -308,60 +324,7 @@ out_free_control_pages: | |||
308 | kimage_free_page_list(&image->control_pages); | 324 | kimage_free_page_list(&image->control_pages); |
309 | out_free_image: | 325 | out_free_image: |
310 | kfree(image); | 326 | kfree(image); |
311 | return result; | 327 | return ret; |
312 | } | ||
313 | |||
314 | static int kimage_crash_alloc(struct kimage **rimage, unsigned long entry, | ||
315 | unsigned long nr_segments, | ||
316 | struct kexec_segment __user *segments) | ||
317 | { | ||
318 | int result; | ||
319 | struct kimage *image; | ||
320 | |||
321 | /* Verify we have a valid entry point */ | ||
322 | if ((entry < crashk_res.start) || (entry > crashk_res.end)) | ||
323 | return -EADDRNOTAVAIL; | ||
324 | |||
325 | /* Allocate and initialize a controlling structure */ | ||
326 | image = do_kimage_alloc_init(); | ||
327 | if (!image) | ||
328 | return -ENOMEM; | ||
329 | |||
330 | image->start = entry; | ||
331 | |||
332 | /* Enable the special crash kernel control page | ||
333 | * allocation policy. | ||
334 | */ | ||
335 | image->control_page = crashk_res.start; | ||
336 | image->type = KEXEC_TYPE_CRASH; | ||
337 | |||
338 | result = copy_user_segment_list(image, nr_segments, segments); | ||
339 | if (result) | ||
340 | goto out_free_image; | ||
341 | |||
342 | result = sanity_check_segment_list(image); | ||
343 | if (result) | ||
344 | goto out_free_image; | ||
345 | |||
346 | /* | ||
347 | * Find a location for the control code buffer, and add | ||
348 | * the vector of segments so that it's pages will also be | ||
349 | * counted as destination pages. | ||
350 | */ | ||
351 | result = -ENOMEM; | ||
352 | image->control_code_page = kimage_alloc_control_pages(image, | ||
353 | get_order(KEXEC_CONTROL_PAGE_SIZE)); | ||
354 | if (!image->control_code_page) { | ||
355 | pr_err("Could not allocate control_code_buffer\n"); | ||
356 | goto out_free_image; | ||
357 | } | ||
358 | |||
359 | *rimage = image; | ||
360 | return 0; | ||
361 | |||
362 | out_free_image: | ||
363 | kfree(image); | ||
364 | return result; | ||
365 | } | 328 | } |
366 | 329 | ||
367 | static int kimage_is_destination_range(struct kimage *image, | 330 | static int kimage_is_destination_range(struct kimage *image, |
@@ -1004,16 +967,16 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, | |||
1004 | 967 | ||
1005 | /* Loading another kernel to reboot into */ | 968 | /* Loading another kernel to reboot into */ |
1006 | if ((flags & KEXEC_ON_CRASH) == 0) | 969 | if ((flags & KEXEC_ON_CRASH) == 0) |
1007 | result = kimage_normal_alloc(&image, entry, | 970 | result = kimage_alloc_init(&image, entry, nr_segments, |
1008 | nr_segments, segments); | 971 | segments, flags); |
1009 | /* Loading another kernel to switch to if this one crashes */ | 972 | /* Loading another kernel to switch to if this one crashes */ |
1010 | else if (flags & KEXEC_ON_CRASH) { | 973 | else if (flags & KEXEC_ON_CRASH) { |
1011 | /* Free any current crash dump kernel before | 974 | /* Free any current crash dump kernel before |
1012 | * we corrupt it. | 975 | * we corrupt it. |
1013 | */ | 976 | */ |
1014 | kimage_free(xchg(&kexec_crash_image, NULL)); | 977 | kimage_free(xchg(&kexec_crash_image, NULL)); |
1015 | result = kimage_crash_alloc(&image, entry, | 978 | result = kimage_alloc_init(&image, entry, nr_segments, |
1016 | nr_segments, segments); | 979 | segments, flags); |
1017 | crash_map_reserved_pages(); | 980 | crash_map_reserved_pages(); |
1018 | } | 981 | } |
1019 | if (result) | 982 | if (result) |