From 92719518d6336db632a00bcfb2ec28a8f82998a8 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 29 Jul 2024 16:53:18 +0100 Subject: [PATCH] numa/emulation: Check emulated zones around the CMA window ... Make sure CMA zones do not straddle the emulated NUMA nodes ... Signed-off-by: Tvrtko Ursulin --- include/linux/cma.h | 6 ++++++ mm/cma.c | 36 ++++++++++++++++++++++++++++++++++++ mm/numa_emulation.c | 6 ++++++ 3 files changed, 48 insertions(+) --- a/include/linux/cma.h +++ b/include/linux/cma.h @@ -56,6 +56,7 @@ extern void cma_reserve_pages_on_error(s #ifdef CONFIG_CMA struct folio *cma_alloc_folio(struct cma *cma, int order, gfp_t gfp); bool cma_free_folio(struct cma *cma, const struct folio *folio); +int cma_check_range(u64 *start, u64 *end); #else static inline struct folio *cma_alloc_folio(struct cma *cma, int order, gfp_t gfp) { @@ -66,6 +67,11 @@ static inline bool cma_free_folio(struct { return false; } + +static inline int cma_check_range(u64 *start, u64 *end) +{ + return 0; +} #endif #endif --- a/mm/cma.c +++ b/mm/cma.c @@ -602,3 +602,39 @@ int cma_for_each_area(int (*it)(struct c return 0; } + +struct cma_check_range_data { + u64 start, end; +}; + +static int check_range(struct cma *cma_, void *data) +{ + struct cma_check_range_data *range = data; + struct cma_check_range_data cma; + bool starts_in_range; + bool ends_in_range; + + cma.start = cma_get_base(cma_); + cma.end = cma.start + cma_get_size(cma_) - 1; + + starts_in_range = cma.start >= range->start && cma.start <= range->end; + ends_in_range = cma.end >= range->start && cma.end <= range->end; + + if (starts_in_range == ends_in_range) + return 0; + + pr_notice("CMA %s [%llx-%llx] straddles range [%llx-%llx]\n", + cma_->name, cma.start, cma.end, range->start, range->end); + + return -EINVAL; +} + +int cma_check_range(u64 *start, u64 *end) +{ + struct cma_check_range_data range = { + .start = *start, + .end = *end, + }; + + return cma_for_each_area(check_range, &range); +} --- a/mm/numa_emulation.c +++ b/mm/numa_emulation.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #define FAKE_NODE_MIN_SIZE ((u64)32 << 20) @@ -51,6 +52,7 @@ static int __init emu_setup_memblk(struc { struct numa_memblk *eb = &ei->blk[ei->nr_blks]; struct numa_memblk *pb = &pi->blk[phys_blk]; + int ret; if (ei->nr_blks >= NR_NODE_MEMBLKS) { pr_err("NUMA: Too many emulated memblks, failing emulation\n"); @@ -62,6 +64,10 @@ static int __init emu_setup_memblk(struc eb->end = pb->start + size; eb->nid = nid; + ret = cma_check_range(&eb->start, &eb->end); + if (ret) + return ret; + if (emu_nid_to_phys[nid] == NUMA_NO_NODE) emu_nid_to_phys[nid] = pb->nid;