History

cma: factor out minimum alignment requirement

Patch series "mm: enforce pageblock_order < MAX_ORDER". Having pageblock_order >= MAX_ORDER seems to be able to happen in corner cases and some parts of the kernel are not prepared for it. For example, Aneesh has shown [1] that such kernels can be compiled on ppc64 with 64k base pages by setting FORCE_MAX_ZONEORDER=8, which will run into a WARN_ON_ONCE(order >= MAX_ORDER) in comapction code right during boot. We can get pageblock_order >= MAX_ORDER when the default hugetlb size is bigger than the maximum allocation granularity of the buddy, in which case we are no longer talking about huge pages but instead gigantic pages. Having pageblock_order >= MAX_ORDER can only make alloc_contig_range() of such gigantic pages more likely to succeed. Reliable use of gigantic pages either requires boot time allcoation or CMA, no need to overcomplicate some places in the kernel to optimize for corner cases that are broken in other areas of the kernel. This patch (of 2): Let's enforce pageblock_order < MAX_ORDER and simplify. Especially patch #1 can be regarded a cleanup before: [PATCH v5 0/6] Use pageblock_order for cma and alloc_contig_range alignment. [2] [1] https://lkml.kernel.org/r/87r189a2ks.fsf@linux.ibm.com [2] https://lkml.kernel.org/r/20220211164135.1803616-1-zi.yan@sent.com Link: https://lkml.kernel.org/r/20220214174132.219303-2-david@redhat.com Signed-off-by: David Hildenbrand <david@redhat.com> Reviewed-by: Zi Yan <ziy@nvidia.com> Acked-by: Rob Herring <robh@kernel.org> Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Frank Rowand <frowand.list@gmail.com> Cc: Michael S. Tsirkin <mst@redhat.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Marek Szyprowski <m.szyprowski@samsung.com> Cc: Robin Murphy <robin.murphy@arm.com> Cc: Minchan Kim <minchan@kernel.org> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: John Garry via iommu <iommu@lists.linux-foundation.org>

David Hildenbrand committed 4 years ago

Commit e16faf21 parent 56651376 files · +19 −30Browse files

Unified · Split

6 files
  1. arch/powerpc/include/asm/fadump-internal.h +0 −5
  2. arch/powerpc/kernel/fadump.c +1 −1
  3. drivers/of/of_reserved_mem.c +3 −6
  4. include/linux/cma.h +9 −0
  5. kernel/dma/contiguous.c +1 −3
  6. mm/cma.c +5 −15
arch/powerpc/include/asm/fadump-internal.h+0−5
@@ -19,11 +19,6 @@ · 18 unmodified lines
19 19
20#define memblock_num_regions(memblock_type) (memblock.memblock_type.cnt)20#define memblock_num_regions(memblock_type) (memblock.memblock_type.cnt)
21 21
22/* Alignment per CMA requirement. */
23#define FADUMP_CMA_ALIGNMENT (PAGE_SIZE << \
24 max_t(unsigned long, MAX_ORDER - 1, \
25 pageblock_order))
26
27/* FAD commands */22/* FAD commands */
28#define FADUMP_REGISTER 123#define FADUMP_REGISTER 1
29#define FADUMP_UNREGISTER 224#define FADUMP_UNREGISTER 2
arch/powerpc/kernel/fadump.c+1−1
@@ -544,7 +544,7 @@ int __init fadump_reserve_mem(void) · 543 unmodified lines
544 if (!fw_dump.nocma) {544 if (!fw_dump.nocma) {
545 fw_dump.boot_memory_size =545 fw_dump.boot_memory_size =
546 ALIGN(fw_dump.boot_memory_size,546 ALIGN(fw_dump.boot_memory_size,
547 FADUMP_CMA_ALIGNMENT);547 CMA_MIN_ALIGNMENT_BYTES);
548 }548 }
549#endif549#endif
550 550
drivers/of/of_reserved_mem.c+3−6
@@ -22,6 +22,7 @@ · 21 unmodified lines
22#include <linux/slab.h>22#include <linux/slab.h>
23#include <linux/memblock.h>23#include <linux/memblock.h>
24#include <linux/kmemleak.h>24#include <linux/kmemleak.h>
25#include <linux/cma.h>
25 26
26#include "of_private.h"27#include "of_private.h"
27 28
@@ -116,12 +117,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node, · 88 unmodified lines
116 if (IS_ENABLED(CONFIG_CMA)117 if (IS_ENABLED(CONFIG_CMA)
117 && of_flat_dt_is_compatible(node, "shared-dma-pool")118 && of_flat_dt_is_compatible(node, "shared-dma-pool")
118 && of_get_flat_dt_prop(node, "reusable", NULL)119 && of_get_flat_dt_prop(node, "reusable", NULL)
119 && !nomap) {120 && !nomap)
120 unsigned long order =121 align = max_t(phys_addr_t, align, CMA_MIN_ALIGNMENT_BYTES);
121 max_t(unsigned long, MAX_ORDER - 1, pageblock_order);
122
123 align = max(align, (phys_addr_t)PAGE_SIZE << order);
124 }
125 122
126 prop = of_get_flat_dt_prop(node, "alloc-ranges", &len);123 prop = of_get_flat_dt_prop(node, "alloc-ranges", &len);
127 if (prop) {124 if (prop) {
include/linux/cma.h+9−0
@@ -20,6 +20,15 @@ · 19 unmodified lines
20 20
21#define CMA_MAX_NAME 6421#define CMA_MAX_NAME 64
22 22
23/*
24 * TODO: once the buddy -- especially pageblock merging and alloc_contig_range()
25 * -- can deal with only some pageblocks of a higher-order page being
26 * MIGRATE_CMA, we can use pageblock_nr_pages.
27 */
28#define CMA_MIN_ALIGNMENT_PAGES max_t(phys_addr_t, MAX_ORDER_NR_PAGES, \
29 pageblock_nr_pages)
30#define CMA_MIN_ALIGNMENT_BYTES (PAGE_SIZE * CMA_MIN_ALIGNMENT_PAGES)
31
23struct cma;32struct cma;
24 33
25extern unsigned long totalcma_pages;34extern unsigned long totalcma_pages;
kernel/dma/contiguous.c+1−3
@@ -399,8 +399,6 @@ static const struct reserved_mem_ops rmem_cma_ops = { · 398 unmodified lines
399 399
400static int __init rmem_cma_setup(struct reserved_mem *rmem)400static int __init rmem_cma_setup(struct reserved_mem *rmem)
401{401{
402 phys_addr_t align = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
403 phys_addr_t mask = align - 1;
404 unsigned long node = rmem->fdt_node;402 unsigned long node = rmem->fdt_node;
405 bool default_cma = of_get_flat_dt_prop(node, "linux,cma-default", NULL);403 bool default_cma = of_get_flat_dt_prop(node, "linux,cma-default", NULL);
406 struct cma *cma;404 struct cma *cma;
@@ -416,7 +414,7 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem) · 9 unmodified lines
416 of_get_flat_dt_prop(node, "no-map", NULL))414 of_get_flat_dt_prop(node, "no-map", NULL))
417 return -EINVAL;415 return -EINVAL;
418 416
419 if ((rmem->base & mask) || (rmem->size & mask)) {417 if (!IS_ALIGNED(rmem->base | rmem->size, CMA_MIN_ALIGNMENT_BYTES)) {
420 pr_err("Reserved memory: incorrect alignment of CMA region\n");418 pr_err("Reserved memory: incorrect alignment of CMA region\n");
421 return -EINVAL;419 return -EINVAL;
422 }420 }
mm/cma.c+5−15
@@ -168,7 +168,6 @@ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size, · 167 unmodified lines
168 struct cma **res_cma)168 struct cma **res_cma)
169{169{
170 struct cma *cma;170 struct cma *cma;
171 phys_addr_t alignment;
172 171
173 /* Sanity checks */172 /* Sanity checks */
174 if (cma_area_count == ARRAY_SIZE(cma_areas)) {173 if (cma_area_count == ARRAY_SIZE(cma_areas)) {
@@ -179,15 +178,12 @@ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size, · 4 unmodified lines
179 if (!size || !memblock_is_region_reserved(base, size))178 if (!size || !memblock_is_region_reserved(base, size))
180 return -EINVAL;179 return -EINVAL;
181 180
182 /* ensure minimal alignment required by mm core */
183 alignment = PAGE_SIZE <<
184 max_t(unsigned long, MAX_ORDER - 1, pageblock_order);
185
186 /* alignment should be aligned with order_per_bit */181 /* alignment should be aligned with order_per_bit */
187 if (!IS_ALIGNED(alignment >> PAGE_SHIFT, 1 << order_per_bit))182 if (!IS_ALIGNED(CMA_MIN_ALIGNMENT_PAGES, 1 << order_per_bit))
188 return -EINVAL;183 return -EINVAL;
189 184
190 if (ALIGN(base, alignment) != base || ALIGN(size, alignment) != size)185 /* ensure minimal alignment required by mm core */
186 if (!IS_ALIGNED(base | size, CMA_MIN_ALIGNMENT_BYTES))
191 return -EINVAL;187 return -EINVAL;
192 188
193 /*189 /*
@@ -262,14 +258,8 @@ int __init cma_declare_contiguous_nid(phys_addr_t base, · 68 unmodified lines
262 if (alignment && !is_power_of_2(alignment))258 if (alignment && !is_power_of_2(alignment))
263 return -EINVAL;259 return -EINVAL;
264 260
265 /*261 /* Sanitise input arguments. */
266 * Sanitise input arguments.262 alignment = max_t(phys_addr_t, alignment, CMA_MIN_ALIGNMENT_BYTES);
267 * Pages both ends in CMA area could be merged into adjacent unmovable
268 * migratetype page by page allocator's buddy algorithm. In the case,
269 * you couldn't get a contiguous memory, which is not what we want.
270 */
271 alignment = max(alignment, (phys_addr_t)PAGE_SIZE <<
272 max_t(unsigned long, MAX_ORDER - 1, pageblock_order));
273 if (fixed && base & (alignment - 1)) {263 if (fixed && base & (alignment - 1)) {
274 ret = -EINVAL;264 ret = -EINVAL;
275 pr_err("Region at %pa must be aligned to %pa bytes\n",265 pr_err("Region at %pa must be aligned to %pa bytes\n",