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 | |
| 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')
| -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) |
