--- v3
+++ v10
@@ -2,106 +2,54 @@
implementation to find free memory for the purgatory stack.
Signed-off-by: Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>
-Cc: Eric Biederman <ebiederm@xmission.com>
-Cc: Dave Young <dyoung@redhat.com>
-Cc: kexec@lists.infradead.org
-Cc: linux-kernel@vger.kernel.org
+Acked-by: Dave Young <dyoung@redhat.com>
---
- include/linux/kexec.h | 4 ++++
- kernel/kexec_file.c | 66 ++++++++++++++++++++++++++++++++++++++-------------
- 2 files changed, 53 insertions(+), 17 deletions(-)
+ include/linux/kexec.h | 1 +
+ kernel/kexec_file.c | 25 ++++++++++++++++++++-----
+ 2 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
-index 3d91bcfc180d..4ca6f5f95d66 100644
+index 437ef1b47428..a33f63351f86 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
-@@ -227,6 +227,10 @@ extern asmlinkage long sys_kexec_load(unsigned long entry,
- struct kexec_segment __user *segments,
- unsigned long flags);
- extern int kernel_kexec(void);
-+int kexec_locate_mem_hole(struct kimage *image, unsigned long size,
-+ unsigned long align, unsigned long min_addr,
-+ unsigned long max_addr, bool top_down,
-+ unsigned long *addr);
- extern int kexec_add_buffer(struct kimage *image, char *buffer,
- unsigned long bufsz, unsigned long memsz,
- unsigned long buf_align, unsigned long buf_min,
+@@ -176,6 +176,7 @@ struct kexec_buf {
+ int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf,
+ int (*func)(u64, u64, void *));
+ extern int kexec_add_buffer(struct kexec_buf *kbuf);
++int kexec_locate_mem_hole(struct kexec_buf *kbuf);
+ #endif /* CONFIG_KEXEC_FILE */
+
+ struct kimage {
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
-index b1f1f6402518..85a515511925 100644
+index efd2c094af7e..0c2df7f73792 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
-@@ -449,6 +449,46 @@ int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf,
- return walk_system_ram_res(0, ULONG_MAX, kbuf, func);
+@@ -450,6 +450,23 @@ int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf,
}
-+/**
-+ * kexec_locate_mem_hole - find free memory to load segment or use in purgatory
-+ * @image: kexec image being updated.
-+ * @size: Memory size.
-+ * @align: Minimum alignment needed.
-+ * @min_addr: Minimum starting address.
-+ * @max_addr: Maximum end address.
-+ * @top_down Find the highest free memory region?
-+ * @addr On success, will have start address of the memory region found.
+ /**
++ * kexec_locate_mem_hole - find free memory for the purgatory or the next kernel
++ * @kbuf: Parameters for the memory search.
++ *
++ * On success, kbuf->mem will have the start address of the memory region found.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
-+int kexec_locate_mem_hole(struct kimage *image, unsigned long size,
-+ unsigned long align, unsigned long min_addr,
-+ unsigned long max_addr, bool top_down,
-+ unsigned long *addr)
++int kexec_locate_mem_hole(struct kexec_buf *kbuf)
+{
+ int ret;
-+ struct kexec_buf buf;
+
-+ memset(&buf, 0, sizeof(struct kexec_buf));
-+ buf.image = image;
++ ret = arch_kexec_walk_mem(kbuf, locate_mem_hole_callback);
+
-+ buf.memsz = size;
-+ buf.buf_align = align;
-+ buf.buf_min = min_addr;
-+ buf.buf_max = max_addr;
-+ buf.top_down = top_down;
-+
-+ ret = arch_kexec_walk_mem(&buf, locate_mem_hole_callback);
-+ if (ret != 1) {
-+ /* A suitable memory range could not be found for buffer */
-+ return -EADDRNOTAVAIL;
-+ }
-+
-+ *addr = buf.mem;
-+
-+ return 0;
++ return ret == 1 ? 0 : -EADDRNOTAVAIL;
+}
+
- /*
- * Helper function for placing a buffer in a kexec segment. This assumes
- * that kexec_mutex is held.
-@@ -460,8 +500,8 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
- {
-
- struct kexec_segment *ksegment;
-- struct kexec_buf buf, *kbuf;
- int ret;
-+ unsigned long addr, align, size;
-
- /* Currently adding segment this way is allowed only in file mode */
- if (!image->file_mode)
-@@ -482,29 +522,21 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
- return -EINVAL;
- }
-
-- memset(&buf, 0, sizeof(struct kexec_buf));
-- kbuf = &buf;
-- kbuf->image = image;
--
-- kbuf->memsz = ALIGN(memsz, PAGE_SIZE);
-- kbuf->buf_align = max(buf_align, PAGE_SIZE);
-- kbuf->buf_min = buf_min;
-- kbuf->buf_max = buf_max;
-- kbuf->top_down = top_down;
-+ size = ALIGN(memsz, PAGE_SIZE);
-+ align = max(buf_align, PAGE_SIZE);
++/**
+ * kexec_add_buffer - place a buffer in a kexec segment
+ * @kbuf: Buffer contents and memory parameters.
+ *
+@@ -489,11 +506,9 @@ int kexec_add_buffer(struct kexec_buf *kbuf)
+ kbuf->buf_align = max(kbuf->buf_align, PAGE_SIZE);
/* Walk the RAM ranges and allocate a suitable range for the buffer */
- ret = arch_kexec_walk_mem(kbuf, locate_mem_hole_callback);
@@ -109,21 +57,11 @@
- /* A suitable memory range could not be found for buffer */
- return -EADDRNOTAVAIL;
- }
-+ ret = kexec_locate_mem_hole(image, size, align, buf_min, buf_max,
-+ top_down, &addr);
++ ret = kexec_locate_mem_hole(kbuf);
+ if (ret)
+ return ret;
/* Found a suitable memory range */
- ksegment = &image->segment[image->nr_segments];
- ksegment->kbuf = buffer;
- ksegment->bufsz = bufsz;
-- ksegment->mem = kbuf->mem;
-- ksegment->memsz = kbuf->memsz;
-+ ksegment->mem = addr;
-+ ksegment->memsz = size;
- image->nr_segments++;
- *load_addr = ksegment->mem;
- return 0;
+ ksegment = &kbuf->image->segment[kbuf->image->nr_segments];
--
-1.9.1
+2.7.4