cc459b6a569f35d1fab03bfb6d94bdc2412c35ea
[openwrt/staging/linusw.git] /
1 From a27d76f4517d56a6471def2f76687e83fd2a7923 Mon Sep 17 00:00:00 2001
2 From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
3 Date: Mon, 29 Jul 2024 16:53:18 +0100
4 Subject: [PATCH 1342/1350] numa/emulation: Check emulated zones around the CMA
5 window
6
7 ... Make sure CMA zones do not straddle the emulated NUMA nodes ...
8
9 Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
10 ---
11 drivers/base/numa_emulation.c | 5 +++++
12 include/linux/cma.h | 10 ++++++++++
13 mm/cma.c | 36 +++++++++++++++++++++++++++++++++++
14 3 files changed, 51 insertions(+)
15
16 --- a/drivers/base/numa_emulation.c
17 +++ b/drivers/base/numa_emulation.c
18 @@ -7,6 +7,7 @@
19 * Author: MaĆ­ra Canal <mcanal@igalia.com>
20 * Author: Tvrtko Ursulin <tursulin@igalia.com>
21 */
22 +#include <linux/cma.h>
23 #include <linux/memblock.h>
24
25 #include "numa_emulation.h"
26 @@ -55,6 +56,10 @@ int __init numa_emu_init(void)
27 if (i == (emu_nodes - 1) && e != end)
28 e = end;
29
30 + ret = cma_check_range(&s, &e);
31 + if (ret)
32 + return ret;
33 +
34 pr_info("Faking a node at [mem %pap-%pap]\n", &s, &e);
35 ret = numa_add_memblk(i, s, e + 1);
36 if (ret) {
37 --- a/include/linux/cma.h
38 +++ b/include/linux/cma.h
39 @@ -56,4 +56,14 @@ extern bool cma_release(struct cma *cma,
40 extern int cma_for_each_area(int (*it)(struct cma *cma, void *data), void *data);
41
42 extern void cma_reserve_pages_on_error(struct cma *cma);
43 +
44 +#ifdef CONFIG_CMA
45 +extern int cma_check_range(u64 *start, u64 *end);
46 +#else
47 +static inline int cma_check_range(u64 *start, u64 *end)
48 +{
49 + return 0;
50 +}
51 +#endif
52 +
53 #endif
54 --- a/mm/cma.c
55 +++ b/mm/cma.c
56 @@ -587,3 +587,39 @@ int cma_for_each_area(int (*it)(struct c
57
58 return 0;
59 }
60 +
61 +struct cma_check_range_data {
62 + u64 start, end;
63 +};
64 +
65 +static int check_range(struct cma *cma_, void *data)
66 +{
67 + struct cma_check_range_data *range = data;
68 + struct cma_check_range_data cma;
69 + bool starts_in_range;
70 + bool ends_in_range;
71 +
72 + cma.start = cma_get_base(cma_);
73 + cma.end = cma.start + cma_get_size(cma_) - 1;
74 +
75 + starts_in_range = cma.start >= range->start && cma.start <= range->end;
76 + ends_in_range = cma.end >= range->start && cma.end <= range->end;
77 +
78 + if (starts_in_range == ends_in_range)
79 + return 0;
80 +
81 + pr_notice("CMA %s [%llx-%llx] straddles range [%llx-%llx]\n",
82 + cma_->name, cma.start, cma.end, range->start, range->end);
83 +
84 + return -EINVAL;
85 +}
86 +
87 +int cma_check_range(u64 *start, u64 *end)
88 +{
89 + struct cma_check_range_data range = {
90 + .start = *start,
91 + .end = *end,
92 + };
93 +
94 + return cma_for_each_area(check_range, &range);
95 +}