Commit 255aedd9 authored by Vivek Goyal's avatar Vivek Goyal Committed by Linus Torvalds

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: default avatarVivek 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: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent dabe7862
...@@ -261,12 +261,20 @@ static struct kimage *do_kimage_alloc_init(void) ...@@ -261,12 +261,20 @@ static struct kimage *do_kimage_alloc_init(void)
static void kimage_free_page_list(struct list_head *list); static void kimage_free_page_list(struct list_head *list);
static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry, static int kimage_alloc_init(struct kimage **rimage, unsigned long entry,
unsigned long nr_segments, unsigned long nr_segments,
struct kexec_segment __user *segments) struct kexec_segment __user *segments,
unsigned long flags)
{ {
int result; int ret;
struct kimage *image; struct kimage *image;
bool kexec_on_panic = flags & KEXEC_ON_CRASH;
if (kexec_on_panic) {
/* Verify we have a valid entry point */
if ((entry < crashk_res.start) || (entry > crashk_res.end))
return -EADDRNOTAVAIL;
}
/* Allocate and initialize a controlling structure */ /* Allocate and initialize a controlling structure */
image = do_kimage_alloc_init(); image = do_kimage_alloc_init();
...@@ -275,20 +283,26 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry, ...@@ -275,20 +283,26 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
image->start = entry; image->start = entry;
result = copy_user_segment_list(image, nr_segments, segments); ret = copy_user_segment_list(image, nr_segments, segments);
if (result) if (ret)
goto out_free_image; goto out_free_image;
result = sanity_check_segment_list(image); ret = sanity_check_segment_list(image);
if (result) if (ret)
goto out_free_image; goto out_free_image;
/* Enable the special crash kernel control page allocation policy. */
if (kexec_on_panic) {
image->control_page = crashk_res.start;
image->type = KEXEC_TYPE_CRASH;
}
/* /*
* Find a location for the control code buffer, and add it * Find a location for the control code buffer, and add it
* the vector of segments so that it's pages will also be * the vector of segments so that it's pages will also be
* counted as destination pages. * counted as destination pages.
*/ */
result = -ENOMEM; ret = -ENOMEM;
image->control_code_page = kimage_alloc_control_pages(image, image->control_code_page = kimage_alloc_control_pages(image,
get_order(KEXEC_CONTROL_PAGE_SIZE)); get_order(KEXEC_CONTROL_PAGE_SIZE));
if (!image->control_code_page) { if (!image->control_code_page) {
...@@ -296,10 +310,12 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry, ...@@ -296,10 +310,12 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
goto out_free_image; goto out_free_image;
} }
image->swap_page = kimage_alloc_control_pages(image, 0); if (!kexec_on_panic) {
if (!image->swap_page) { image->swap_page = kimage_alloc_control_pages(image, 0);
pr_err("Could not allocate swap buffer\n"); if (!image->swap_page) {
goto out_free_control_pages; pr_err("Could not allocate swap buffer\n");
goto out_free_control_pages;
}
} }
*rimage = image; *rimage = image;
...@@ -308,60 +324,7 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry, ...@@ -308,60 +324,7 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
kimage_free_page_list(&image->control_pages); kimage_free_page_list(&image->control_pages);
out_free_image: out_free_image:
kfree(image); kfree(image);
return result; return ret;
}
static int kimage_crash_alloc(struct kimage **rimage, unsigned long entry,
unsigned long nr_segments,
struct kexec_segment __user *segments)
{
int result;
struct kimage *image;
/* Verify we have a valid entry point */
if ((entry < crashk_res.start) || (entry > crashk_res.end))
return -EADDRNOTAVAIL;
/* Allocate and initialize a controlling structure */
image = do_kimage_alloc_init();
if (!image)
return -ENOMEM;
image->start = entry;
/* Enable the special crash kernel control page
* allocation policy.
*/
image->control_page = crashk_res.start;
image->type = KEXEC_TYPE_CRASH;
result = copy_user_segment_list(image, nr_segments, segments);
if (result)
goto out_free_image;
result = sanity_check_segment_list(image);
if (result)
goto out_free_image;
/*
* Find a location for the control code buffer, and add
* the vector of segments so that it's pages will also be
* counted as destination pages.
*/
result = -ENOMEM;
image->control_code_page = kimage_alloc_control_pages(image,
get_order(KEXEC_CONTROL_PAGE_SIZE));
if (!image->control_code_page) {
pr_err("Could not allocate control_code_buffer\n");
goto out_free_image;
}
*rimage = image;
return 0;
out_free_image:
kfree(image);
return result;
} }
static int kimage_is_destination_range(struct kimage *image, 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,16 +967,16 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
/* Loading another kernel to reboot into */ /* Loading another kernel to reboot into */
if ((flags & KEXEC_ON_CRASH) == 0) if ((flags & KEXEC_ON_CRASH) == 0)
result = kimage_normal_alloc(&image, entry, result = kimage_alloc_init(&image, entry, nr_segments,
nr_segments, segments); segments, flags);
/* Loading another kernel to switch to if this one crashes */ /* Loading another kernel to switch to if this one crashes */
else if (flags & KEXEC_ON_CRASH) { else if (flags & KEXEC_ON_CRASH) {
/* Free any current crash dump kernel before /* Free any current crash dump kernel before
* we corrupt it. * we corrupt it.
*/ */
kimage_free(xchg(&kexec_crash_image, NULL)); kimage_free(xchg(&kexec_crash_image, NULL));
result = kimage_crash_alloc(&image, entry, result = kimage_alloc_init(&image, entry, nr_segments,
nr_segments, segments); segments, flags);
crash_map_reserved_pages(); crash_map_reserved_pages();
} }
if (result) if (result)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment