Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+34 −71
Original line number Diff line number Diff line
@@ -261,12 +261,20 @@ static struct kimage *do_kimage_alloc_init(void)

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,
				struct kexec_segment __user *segments)
			     struct kexec_segment __user *segments,
			     unsigned long flags)
{
	int result;
	int ret;
	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 */
	image = do_kimage_alloc_init();
@@ -275,20 +283,26 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,

	image->start = entry;

	result = copy_user_segment_list(image, nr_segments, segments);
	if (result)
	ret = copy_user_segment_list(image, nr_segments, segments);
	if (ret)
		goto out_free_image;

	result = sanity_check_segment_list(image);
	if (result)
	ret = sanity_check_segment_list(image);
	if (ret)
		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
	 * the vector of segments so that it's pages will also be
	 * counted as destination pages.
	 */
	result = -ENOMEM;
	ret = -ENOMEM;
	image->control_code_page = kimage_alloc_control_pages(image,
					   get_order(KEXEC_CONTROL_PAGE_SIZE));
	if (!image->control_code_page) {
@@ -296,11 +310,13 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
		goto out_free_image;
	}

	if (!kexec_on_panic) {
		image->swap_page = kimage_alloc_control_pages(image, 0);
		if (!image->swap_page) {
			pr_err("Could not allocate swap buffer\n");
			goto out_free_control_pages;
		}
	}

	*rimage = image;
	return 0;
@@ -308,60 +324,7 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
	kimage_free_page_list(&image->control_pages);
out_free_image:
	kfree(image);
	return result;
}

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;
	return ret;
}

static int kimage_is_destination_range(struct kimage *image,
@@ -1004,16 +967,16 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,

		/* Loading another kernel to reboot into */
		if ((flags & KEXEC_ON_CRASH) == 0)
			result = kimage_normal_alloc(&image, entry,
							nr_segments, segments);
			result = kimage_alloc_init(&image, entry, nr_segments,
						   segments, flags);
		/* Loading another kernel to switch to if this one crashes */
		else if (flags & KEXEC_ON_CRASH) {
			/* Free any current crash dump kernel before
			 * we corrupt it.
			 */
			kimage_free(xchg(&kexec_crash_image, NULL));
			result = kimage_crash_alloc(&image, entry,
						     nr_segments, segments);
			result = kimage_alloc_init(&image, entry, nr_segments,
						   segments, flags);
			crash_map_reserved_pages();
		}
		if (result)