lkml.org 
[lkml]   [2016]   [Jun]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 3/9] kexec_file: Factor out kexec_locate_mem_hole from kexec_add_buffer.
    Date
    kexec_locate_mem_hole will be used by the PowerPC kexec_file_load
    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
    ---
    include/linux/kexec.h | 4 +++
    kernel/kexec_file.c | 88 +++++++++++++++++++++++++++++++++++----------------
    2 files changed, 64 insertions(+), 28 deletions(-)

    diff --git a/include/linux/kexec.h b/include/linux/kexec.h
    index 7321043aa65a..a08cd986b5a1 100644
    --- a/include/linux/kexec.h
    +++ b/include/linux/kexec.h
    @@ -210,6 +210,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,
    diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
    index a3ca7cfe070e..3e494261d32a 100644
    --- a/kernel/kexec_file.c
    +++ b/kernel/kexec_file.c
    @@ -453,6 +453,57 @@ int __weak arch_kexec_walk_mem(unsigned int image_type, unsigned long start,
    return walk_system_ram_res(start, end, data, func);
    }

    +/**
    + * 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.
    + *
    + * 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 ret;
    + struct kexec_buf buf;
    + unsigned long start, end;
    +
    + memset(&buf, 0, sizeof(struct kexec_buf));
    + buf.image = image;
    +
    + buf.memsz = size;
    + buf.buf_align = align;
    + buf.buf_min = min_addr;
    + buf.buf_max = max_addr;
    + buf.top_down = top_down;
    +
    + /* Walk the RAM ranges and allocate a suitable range for the buffer */
    + if (image->type == KEXEC_TYPE_CRASH) {
    + start = crashk_res.start;
    + end = crashk_res.end;
    + } else {
    + start = 0;
    + end = ULONG_MAX;
    + }
    +
    + ret = arch_kexec_walk_mem(image->type, start, end, top_down, &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;
    +}
    +
    /*
    * Helper function for placing a buffer in a kexec segment. This assumes
    * that kexec_mutex is held.
    @@ -464,9 +515,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 start, end;
    + unsigned long addr, align, size;

    /* Currently adding segment this way is allowed only in file mode */
    if (!image->file_mode)
    @@ -487,38 +537,20 @@ 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);

    - /* Walk the RAM ranges and allocate a suitable range for the buffer */
    - if (image->type == KEXEC_TYPE_CRASH) {
    - start = crashk_res.start;
    - end = crashk_res.end;
    - } else {
    - start = 0;
    - end = ULONG_MAX;
    - }
    -
    - ret = arch_kexec_walk_mem(image->type, start, end, top_down, kbuf,
    - locate_mem_hole_callback);
    - if (ret != 1) {
    - /* 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);
    + 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;
    --
    1.9.1
    \
     
     \ /
      Last update: 2016-06-14 17:41    [W:3.991 / U:0.248 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site