]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
powerpc/crash: use generic APIs to locate memory hole for kdump
authorSourabh Jain <sourabhjain@linux.ibm.com>
Fri, 31 Jan 2025 11:38:27 +0000 (17:08 +0530)
committerAndrew Morton <akpm@linux-foundation.org>
Mon, 17 Mar 2025 05:30:48 +0000 (22:30 -0700)
On PowerPC, the memory reserved for the crashkernel can contain components
like RTAS, TCE, OPAL, etc., which should be avoided when loading kexec
segments into crashkernel memory.  Due to these special components,
PowerPC has its own set of APIs to locate holes in the crashkernel memory
for loading kexec segments for kdump.  However, for loading kexec segments
in the kexec case, PowerPC already uses generic APIs to locate holes.

The previous patch in this series, titled "crash: Let arch decide usable
memory range in reserved area," introduced arch-specific hook to handle
such special regions in the crashkernel area.  So, switch PowerPC to use
the generic APIs to locate memory holes for kdump and remove the redundant
PowerPC-specific APIs.

Link: https://lkml.kernel.org/r/20250131113830.925179-5-sourabhjain@linux.ibm.com
Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Cc: Baoquan he <bhe@redhat.com>
Cc: Hari Bathini <hbathini@linux.ibm.com>
Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
arch/powerpc/include/asm/kexec.h
arch/powerpc/kexec/file_load_64.c

index 601e569303e1bde77d14db0ff7baa73df55e2722..1b800df5eb30dab90978f3499a07913abdf70f41 100644 (file)
@@ -94,8 +94,10 @@ int arch_kexec_kernel_image_probe(struct kimage *image, void *buf, unsigned long
 int arch_kimage_file_post_load_cleanup(struct kimage *image);
 #define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_cleanup
 
-int arch_kexec_locate_mem_hole(struct kexec_buf *kbuf);
-#define arch_kexec_locate_mem_hole arch_kexec_locate_mem_hole
+int arch_check_excluded_range(struct kimage *image, unsigned long start,
+                             unsigned long end);
+#define arch_check_excluded_range  arch_check_excluded_range
+
 
 int load_crashdump_segments_ppc64(struct kimage *image,
                                  struct kexec_buf *kbuf);
index dc65c139115772bc4e19506d03af0e19fa5637ba..e7ef8b2a25546bd82df757d4ed6283a45b139842 100644 (file)
@@ -49,201 +49,18 @@ const struct kexec_file_ops * const kexec_file_loaders[] = {
        NULL
 };
 
-/**
- * __locate_mem_hole_top_down - Looks top down for a large enough memory hole
- *                              in the memory regions between buf_min & buf_max
- *                              for the buffer. If found, sets kbuf->mem.
- * @kbuf:                       Buffer contents and memory parameters.
- * @buf_min:                    Minimum address for the buffer.
- * @buf_max:                    Maximum address for the buffer.
- *
- * Returns 0 on success, negative errno on error.
- */
-static int __locate_mem_hole_top_down(struct kexec_buf *kbuf,
-                                     u64 buf_min, u64 buf_max)
-{
-       int ret = -EADDRNOTAVAIL;
-       phys_addr_t start, end;
-       u64 i;
-
-       for_each_mem_range_rev(i, &start, &end) {
-               /*
-                * memblock uses [start, end) convention while it is
-                * [start, end] here. Fix the off-by-one to have the
-                * same convention.
-                */
-               end -= 1;
-
-               if (start > buf_max)
-                       continue;
-
-               /* Memory hole not found */
-               if (end < buf_min)
-                       break;
-
-               /* Adjust memory region based on the given range */
-               if (start < buf_min)
-                       start = buf_min;
-               if (end > buf_max)
-                       end = buf_max;
-
-               start = ALIGN(start, kbuf->buf_align);
-               if (start < end && (end - start + 1) >= kbuf->memsz) {
-                       /* Suitable memory range found. Set kbuf->mem */
-                       kbuf->mem = ALIGN_DOWN(end - kbuf->memsz + 1,
-                                              kbuf->buf_align);
-                       ret = 0;
-                       break;
-               }
-       }
-
-       return ret;
-}
-
-/**
- * locate_mem_hole_top_down_ppc64 - Skip special memory regions to find a
- *                                  suitable buffer with top down approach.
- * @kbuf:                           Buffer contents and memory parameters.
- * @buf_min:                        Minimum address for the buffer.
- * @buf_max:                        Maximum address for the buffer.
- * @emem:                           Exclude memory ranges.
- *
- * Returns 0 on success, negative errno on error.
- */
-static int locate_mem_hole_top_down_ppc64(struct kexec_buf *kbuf,
-                                         u64 buf_min, u64 buf_max,
-                                         const struct crash_mem *emem)
+int arch_check_excluded_range(struct kimage *image, unsigned long start,
+                             unsigned long end)
 {
-       int i, ret = 0, err = -EADDRNOTAVAIL;
-       u64 start, end, tmin, tmax;
-
-       tmax = buf_max;
-       for (i = (emem->nr_ranges - 1); i >= 0; i--) {
-               start = emem->ranges[i].start;
-               end = emem->ranges[i].end;
-
-               if (start > tmax)
-                       continue;
-
-               if (end < tmax) {
-                       tmin = (end < buf_min ? buf_min : end + 1);
-                       ret = __locate_mem_hole_top_down(kbuf, tmin, tmax);
-                       if (!ret)
-                               return 0;
-               }
-
-               tmax = start - 1;
-
-               if (tmax < buf_min) {
-                       ret = err;
-                       break;
-               }
-               ret = 0;
-       }
-
-       if (!ret) {
-               tmin = buf_min;
-               ret = __locate_mem_hole_top_down(kbuf, tmin, tmax);
-       }
-       return ret;
-}
-
-/**
- * __locate_mem_hole_bottom_up - Looks bottom up for a large enough memory hole
- *                               in the memory regions between buf_min & buf_max
- *                               for the buffer. If found, sets kbuf->mem.
- * @kbuf:                        Buffer contents and memory parameters.
- * @buf_min:                     Minimum address for the buffer.
- * @buf_max:                     Maximum address for the buffer.
- *
- * Returns 0 on success, negative errno on error.
- */
-static int __locate_mem_hole_bottom_up(struct kexec_buf *kbuf,
-                                      u64 buf_min, u64 buf_max)
-{
-       int ret = -EADDRNOTAVAIL;
-       phys_addr_t start, end;
-       u64 i;
-
-       for_each_mem_range(i, &start, &end) {
-               /*
-                * memblock uses [start, end) convention while it is
-                * [start, end] here. Fix the off-by-one to have the
-                * same convention.
-                */
-               end -= 1;
-
-               if (end < buf_min)
-                       continue;
-
-               /* Memory hole not found */
-               if (start > buf_max)
-                       break;
-
-               /* Adjust memory region based on the given range */
-               if (start < buf_min)
-                       start = buf_min;
-               if (end > buf_max)
-                       end = buf_max;
-
-               start = ALIGN(start, kbuf->buf_align);
-               if (start < end && (end - start + 1) >= kbuf->memsz) {
-                       /* Suitable memory range found. Set kbuf->mem */
-                       kbuf->mem = start;
-                       ret = 0;
-                       break;
-               }
-       }
-
-       return ret;
-}
-
-/**
- * locate_mem_hole_bottom_up_ppc64 - Skip special memory regions to find a
- *                                   suitable buffer with bottom up approach.
- * @kbuf:                            Buffer contents and memory parameters.
- * @buf_min:                         Minimum address for the buffer.
- * @buf_max:                         Maximum address for the buffer.
- * @emem:                            Exclude memory ranges.
- *
- * Returns 0 on success, negative errno on error.
- */
-static int locate_mem_hole_bottom_up_ppc64(struct kexec_buf *kbuf,
-                                          u64 buf_min, u64 buf_max,
-                                          const struct crash_mem *emem)
-{
-       int i, ret = 0, err = -EADDRNOTAVAIL;
-       u64 start, end, tmin, tmax;
-
-       tmin = buf_min;
-       for (i = 0; i < emem->nr_ranges; i++) {
-               start = emem->ranges[i].start;
-               end = emem->ranges[i].end;
-
-               if (end < tmin)
-                       continue;
-
-               if (start > tmin) {
-                       tmax = (start > buf_max ? buf_max : start - 1);
-                       ret = __locate_mem_hole_bottom_up(kbuf, tmin, tmax);
-                       if (!ret)
-                               return 0;
-               }
-
-               tmin = end + 1;
+       struct crash_mem *emem;
+       int i;
 
-               if (tmin > buf_max) {
-                       ret = err;
-                       break;
-               }
-               ret = 0;
-       }
+       emem = image->arch.exclude_ranges;
+       for (i = 0; i < emem->nr_ranges; i++)
+               if (start < emem->ranges[i].end && end > emem->ranges[i].start)
+                       return 1;
 
-       if (!ret) {
-               tmax = buf_max;
-               ret = __locate_mem_hole_bottom_up(kbuf, tmin, tmax);
-       }
-       return ret;
+       return 0;
 }
 
 #ifdef CONFIG_CRASH_DUMP
@@ -1004,64 +821,6 @@ out:
        return ret;
 }
 
-/**
- * arch_kexec_locate_mem_hole - Skip special memory regions like rtas, opal,
- *                              tce-table, reserved-ranges & such (exclude
- *                              memory ranges) as they can't be used for kexec
- *                              segment buffer. Sets kbuf->mem when a suitable
- *                              memory hole is found.
- * @kbuf:                       Buffer contents and memory parameters.
- *
- * Assumes minimum of PAGE_SIZE alignment for kbuf->memsz & kbuf->buf_align.
- *
- * Returns 0 on success, negative errno on error.
- */
-int arch_kexec_locate_mem_hole(struct kexec_buf *kbuf)
-{
-       struct crash_mem **emem;
-       u64 buf_min, buf_max;
-       int ret;
-
-       /* Look up the exclude ranges list while locating the memory hole */
-       emem = &(kbuf->image->arch.exclude_ranges);
-       if (!(*emem) || ((*emem)->nr_ranges == 0)) {
-               pr_warn("No exclude range list. Using the default locate mem hole method\n");
-               return kexec_locate_mem_hole(kbuf);
-       }
-
-       buf_min = kbuf->buf_min;
-       buf_max = kbuf->buf_max;
-       /* Segments for kdump kernel should be within crashkernel region */
-       if (IS_ENABLED(CONFIG_CRASH_DUMP) && kbuf->image->type == KEXEC_TYPE_CRASH) {
-               buf_min = (buf_min < crashk_res.start ?
-                          crashk_res.start : buf_min);
-               buf_max = (buf_max > crashk_res.end ?
-                          crashk_res.end : buf_max);
-       }
-
-       if (buf_min > buf_max) {
-               pr_err("Invalid buffer min and/or max values\n");
-               return -EINVAL;
-       }
-
-       if (kbuf->top_down)
-               ret = locate_mem_hole_top_down_ppc64(kbuf, buf_min, buf_max,
-                                                    *emem);
-       else
-               ret = locate_mem_hole_bottom_up_ppc64(kbuf, buf_min, buf_max,
-                                                     *emem);
-
-       /* Add the buffer allocated to the exclude list for the next lookup */
-       if (!ret) {
-               add_mem_range(emem, kbuf->mem, kbuf->memsz);
-               sort_memory_ranges(*emem, true);
-       } else {
-               pr_err("Failed to locate memory buffer of size %lu\n",
-                      kbuf->memsz);
-       }
-       return ret;
-}
-
 /**
  * arch_kexec_kernel_image_probe - Does additional handling needed to setup
  *                                 kexec segments.