Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

powerpc/crash: use generic APIs to locate memory hole for kdump

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>

authored by

Sourabh Jain and committed by
Andrew Morton
6e5250ea 9f0552c9

+13 -252
+4 -2
arch/powerpc/include/asm/kexec.h
··· 94 94 int arch_kimage_file_post_load_cleanup(struct kimage *image); 95 95 #define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_cleanup 96 96 97 - int arch_kexec_locate_mem_hole(struct kexec_buf *kbuf); 98 - #define arch_kexec_locate_mem_hole arch_kexec_locate_mem_hole 97 + int arch_check_excluded_range(struct kimage *image, unsigned long start, 98 + unsigned long end); 99 + #define arch_check_excluded_range arch_check_excluded_range 100 + 99 101 100 102 int load_crashdump_segments_ppc64(struct kimage *image, 101 103 struct kexec_buf *kbuf);
+9 -250
arch/powerpc/kexec/file_load_64.c
··· 49 49 NULL 50 50 }; 51 51 52 - /** 53 - * __locate_mem_hole_top_down - Looks top down for a large enough memory hole 54 - * in the memory regions between buf_min & buf_max 55 - * for the buffer. If found, sets kbuf->mem. 56 - * @kbuf: Buffer contents and memory parameters. 57 - * @buf_min: Minimum address for the buffer. 58 - * @buf_max: Maximum address for the buffer. 59 - * 60 - * Returns 0 on success, negative errno on error. 61 - */ 62 - static int __locate_mem_hole_top_down(struct kexec_buf *kbuf, 63 - u64 buf_min, u64 buf_max) 52 + int arch_check_excluded_range(struct kimage *image, unsigned long start, 53 + unsigned long end) 64 54 { 65 - int ret = -EADDRNOTAVAIL; 66 - phys_addr_t start, end; 67 - u64 i; 55 + struct crash_mem *emem; 56 + int i; 68 57 69 - for_each_mem_range_rev(i, &start, &end) { 70 - /* 71 - * memblock uses [start, end) convention while it is 72 - * [start, end] here. Fix the off-by-one to have the 73 - * same convention. 74 - */ 75 - end -= 1; 58 + emem = image->arch.exclude_ranges; 59 + for (i = 0; i < emem->nr_ranges; i++) 60 + if (start < emem->ranges[i].end && end > emem->ranges[i].start) 61 + return 1; 76 62 77 - if (start > buf_max) 78 - continue; 79 - 80 - /* Memory hole not found */ 81 - if (end < buf_min) 82 - break; 83 - 84 - /* Adjust memory region based on the given range */ 85 - if (start < buf_min) 86 - start = buf_min; 87 - if (end > buf_max) 88 - end = buf_max; 89 - 90 - start = ALIGN(start, kbuf->buf_align); 91 - if (start < end && (end - start + 1) >= kbuf->memsz) { 92 - /* Suitable memory range found. Set kbuf->mem */ 93 - kbuf->mem = ALIGN_DOWN(end - kbuf->memsz + 1, 94 - kbuf->buf_align); 95 - ret = 0; 96 - break; 97 - } 98 - } 99 - 100 - return ret; 101 - } 102 - 103 - /** 104 - * locate_mem_hole_top_down_ppc64 - Skip special memory regions to find a 105 - * suitable buffer with top down approach. 106 - * @kbuf: Buffer contents and memory parameters. 107 - * @buf_min: Minimum address for the buffer. 108 - * @buf_max: Maximum address for the buffer. 109 - * @emem: Exclude memory ranges. 110 - * 111 - * Returns 0 on success, negative errno on error. 112 - */ 113 - static int locate_mem_hole_top_down_ppc64(struct kexec_buf *kbuf, 114 - u64 buf_min, u64 buf_max, 115 - const struct crash_mem *emem) 116 - { 117 - int i, ret = 0, err = -EADDRNOTAVAIL; 118 - u64 start, end, tmin, tmax; 119 - 120 - tmax = buf_max; 121 - for (i = (emem->nr_ranges - 1); i >= 0; i--) { 122 - start = emem->ranges[i].start; 123 - end = emem->ranges[i].end; 124 - 125 - if (start > tmax) 126 - continue; 127 - 128 - if (end < tmax) { 129 - tmin = (end < buf_min ? buf_min : end + 1); 130 - ret = __locate_mem_hole_top_down(kbuf, tmin, tmax); 131 - if (!ret) 132 - return 0; 133 - } 134 - 135 - tmax = start - 1; 136 - 137 - if (tmax < buf_min) { 138 - ret = err; 139 - break; 140 - } 141 - ret = 0; 142 - } 143 - 144 - if (!ret) { 145 - tmin = buf_min; 146 - ret = __locate_mem_hole_top_down(kbuf, tmin, tmax); 147 - } 148 - return ret; 149 - } 150 - 151 - /** 152 - * __locate_mem_hole_bottom_up - Looks bottom up for a large enough memory hole 153 - * in the memory regions between buf_min & buf_max 154 - * for the buffer. If found, sets kbuf->mem. 155 - * @kbuf: Buffer contents and memory parameters. 156 - * @buf_min: Minimum address for the buffer. 157 - * @buf_max: Maximum address for the buffer. 158 - * 159 - * Returns 0 on success, negative errno on error. 160 - */ 161 - static int __locate_mem_hole_bottom_up(struct kexec_buf *kbuf, 162 - u64 buf_min, u64 buf_max) 163 - { 164 - int ret = -EADDRNOTAVAIL; 165 - phys_addr_t start, end; 166 - u64 i; 167 - 168 - for_each_mem_range(i, &start, &end) { 169 - /* 170 - * memblock uses [start, end) convention while it is 171 - * [start, end] here. Fix the off-by-one to have the 172 - * same convention. 173 - */ 174 - end -= 1; 175 - 176 - if (end < buf_min) 177 - continue; 178 - 179 - /* Memory hole not found */ 180 - if (start > buf_max) 181 - break; 182 - 183 - /* Adjust memory region based on the given range */ 184 - if (start < buf_min) 185 - start = buf_min; 186 - if (end > buf_max) 187 - end = buf_max; 188 - 189 - start = ALIGN(start, kbuf->buf_align); 190 - if (start < end && (end - start + 1) >= kbuf->memsz) { 191 - /* Suitable memory range found. Set kbuf->mem */ 192 - kbuf->mem = start; 193 - ret = 0; 194 - break; 195 - } 196 - } 197 - 198 - return ret; 199 - } 200 - 201 - /** 202 - * locate_mem_hole_bottom_up_ppc64 - Skip special memory regions to find a 203 - * suitable buffer with bottom up approach. 204 - * @kbuf: Buffer contents and memory parameters. 205 - * @buf_min: Minimum address for the buffer. 206 - * @buf_max: Maximum address for the buffer. 207 - * @emem: Exclude memory ranges. 208 - * 209 - * Returns 0 on success, negative errno on error. 210 - */ 211 - static int locate_mem_hole_bottom_up_ppc64(struct kexec_buf *kbuf, 212 - u64 buf_min, u64 buf_max, 213 - const struct crash_mem *emem) 214 - { 215 - int i, ret = 0, err = -EADDRNOTAVAIL; 216 - u64 start, end, tmin, tmax; 217 - 218 - tmin = buf_min; 219 - for (i = 0; i < emem->nr_ranges; i++) { 220 - start = emem->ranges[i].start; 221 - end = emem->ranges[i].end; 222 - 223 - if (end < tmin) 224 - continue; 225 - 226 - if (start > tmin) { 227 - tmax = (start > buf_max ? buf_max : start - 1); 228 - ret = __locate_mem_hole_bottom_up(kbuf, tmin, tmax); 229 - if (!ret) 230 - return 0; 231 - } 232 - 233 - tmin = end + 1; 234 - 235 - if (tmin > buf_max) { 236 - ret = err; 237 - break; 238 - } 239 - ret = 0; 240 - } 241 - 242 - if (!ret) { 243 - tmax = buf_max; 244 - ret = __locate_mem_hole_bottom_up(kbuf, tmin, tmax); 245 - } 246 - return ret; 63 + return 0; 247 64 } 248 65 249 66 #ifdef CONFIG_CRASH_DUMP ··· 818 1001 819 1002 out: 820 1003 kfree(umem); 821 - return ret; 822 - } 823 - 824 - /** 825 - * arch_kexec_locate_mem_hole - Skip special memory regions like rtas, opal, 826 - * tce-table, reserved-ranges & such (exclude 827 - * memory ranges) as they can't be used for kexec 828 - * segment buffer. Sets kbuf->mem when a suitable 829 - * memory hole is found. 830 - * @kbuf: Buffer contents and memory parameters. 831 - * 832 - * Assumes minimum of PAGE_SIZE alignment for kbuf->memsz & kbuf->buf_align. 833 - * 834 - * Returns 0 on success, negative errno on error. 835 - */ 836 - int arch_kexec_locate_mem_hole(struct kexec_buf *kbuf) 837 - { 838 - struct crash_mem **emem; 839 - u64 buf_min, buf_max; 840 - int ret; 841 - 842 - /* Look up the exclude ranges list while locating the memory hole */ 843 - emem = &(kbuf->image->arch.exclude_ranges); 844 - if (!(*emem) || ((*emem)->nr_ranges == 0)) { 845 - pr_warn("No exclude range list. Using the default locate mem hole method\n"); 846 - return kexec_locate_mem_hole(kbuf); 847 - } 848 - 849 - buf_min = kbuf->buf_min; 850 - buf_max = kbuf->buf_max; 851 - /* Segments for kdump kernel should be within crashkernel region */ 852 - if (IS_ENABLED(CONFIG_CRASH_DUMP) && kbuf->image->type == KEXEC_TYPE_CRASH) { 853 - buf_min = (buf_min < crashk_res.start ? 854 - crashk_res.start : buf_min); 855 - buf_max = (buf_max > crashk_res.end ? 856 - crashk_res.end : buf_max); 857 - } 858 - 859 - if (buf_min > buf_max) { 860 - pr_err("Invalid buffer min and/or max values\n"); 861 - return -EINVAL; 862 - } 863 - 864 - if (kbuf->top_down) 865 - ret = locate_mem_hole_top_down_ppc64(kbuf, buf_min, buf_max, 866 - *emem); 867 - else 868 - ret = locate_mem_hole_bottom_up_ppc64(kbuf, buf_min, buf_max, 869 - *emem); 870 - 871 - /* Add the buffer allocated to the exclude list for the next lookup */ 872 - if (!ret) { 873 - add_mem_range(emem, kbuf->mem, kbuf->memsz); 874 - sort_memory_ranges(*emem, true); 875 - } else { 876 - pr_err("Failed to locate memory buffer of size %lu\n", 877 - kbuf->memsz); 878 - } 879 1004 return ret; 880 1005 } 881 1006