Skip to content

Commit 99185c1

Browse files
yhuang-intelakpm00
authored andcommitted
resource, kunit: add test case for region_intersects()
Patch series "resource: Fix region_intersects() vs add_memory_driver_managed()", v3. The patchset fixes a bug of region_intersects() for systems with CXL memory. The details of the bug can be found in [1/3]. To avoid similar bugs in the future. A kunit test case for region_intersects() is added in [3/3]. [2/3] is a preparation patch for [3/3]. This patch (of 3): region_intersects() is important because it's used for /dev/mem permission checking. To avoid possible bug of region_intersects() in the future, a kunit test case for region_intersects() is added. Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: "Huang, Ying" <[email protected]> Cc: Dan Williams <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Davidlohr Bueso <[email protected]> Cc: Jonathan Cameron <[email protected]> Cc: Dave Jiang <[email protected]> Cc: Alison Schofield <[email protected]> Cc: Vishal Verma <[email protected]> Cc: Ira Weiny <[email protected]> Cc: Alistair Popple <[email protected]> Cc: Andy Shevchenko <[email protected]> Cc: Bjorn Helgaas <[email protected]> Cc: Baoquan He <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent bacf9c3 commit 99185c1

File tree

3 files changed

+158
-6
lines changed

3 files changed

+158
-6
lines changed

kernel/resource.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,16 +1817,25 @@ EXPORT_SYMBOL(resource_list_free);
18171817
#ifdef CONFIG_GET_FREE_REGION
18181818
#define GFR_DESCENDING (1UL << 0)
18191819
#define GFR_REQUEST_REGION (1UL << 1)
1820-
#define GFR_DEFAULT_ALIGN (1UL << PA_SECTION_SHIFT)
1820+
#ifdef PA_SECTION_SHIFT
1821+
#define GFR_DEFAULT_ALIGN (1UL << PA_SECTION_SHIFT)
1822+
#else
1823+
#define GFR_DEFAULT_ALIGN PAGE_SIZE
1824+
#endif
1825+
1826+
#ifdef MAX_PHYSMEM_BITS
1827+
#define MAX_PHYS_ADDR ((1ULL << MAX_PHYSMEM_BITS) - 1)
1828+
#else
1829+
#define MAX_PHYS_ADDR (-1ULL)
1830+
#endif
18211831

18221832
static resource_size_t gfr_start(struct resource *base, resource_size_t size,
18231833
resource_size_t align, unsigned long flags)
18241834
{
18251835
if (flags & GFR_DESCENDING) {
18261836
resource_size_t end;
18271837

1828-
end = min_t(resource_size_t, base->end,
1829-
(1ULL << MAX_PHYSMEM_BITS) - 1);
1838+
end = min_t(resource_size_t, base->end, MAX_PHYS_ADDR);
18301839
return end - size + 1;
18311840
}
18321841

@@ -1843,8 +1852,7 @@ static bool gfr_continue(struct resource *base, resource_size_t addr,
18431852
* @size did not wrap 0.
18441853
*/
18451854
return addr > addr - size &&
1846-
addr <= min_t(resource_size_t, base->end,
1847-
(1ULL << MAX_PHYSMEM_BITS) - 1);
1855+
addr <= min_t(resource_size_t, base->end, MAX_PHYS_ADDR);
18481856
}
18491857

18501858
static resource_size_t gfr_next(resource_size_t addr, resource_size_t size,
@@ -2005,7 +2013,7 @@ struct resource *alloc_free_mem_region(struct resource *base,
20052013
return get_free_mem_region(NULL, base, size, align, name,
20062014
IORES_DESC_NONE, flags);
20072015
}
2008-
EXPORT_SYMBOL_NS_GPL(alloc_free_mem_region, CXL);
2016+
EXPORT_SYMBOL_GPL(alloc_free_mem_region);
20092017
#endif /* CONFIG_GET_FREE_REGION */
20102018

20112019
static int __init strict_iomem(char *str)

kernel/resource_kunit.c

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include <linux/ioport.h>
88
#include <linux/kernel.h>
99
#include <linux/string.h>
10+
#include <linux/sizes.h>
11+
#include <linux/mm.h>
1012

1113
#define R0_START 0x0000
1214
#define R0_END 0xffff
@@ -137,9 +139,150 @@ static void resource_test_intersection(struct kunit *test)
137139
} while (++i < ARRAY_SIZE(results_for_intersection));
138140
}
139141

142+
/*
143+
* The test resource tree for region_intersects() test:
144+
*
145+
* BASE-BASE+1M-1 : Test System RAM 0
146+
* # hole 0 (BASE+1M-BASE+2M)
147+
* BASE+2M-BASE+3M-1 : Test CXL Window 0
148+
* BASE+3M-BASE+4M-1 : Test System RAM 1
149+
* BASE+4M-BASE+7M-1 : Test CXL Window 1
150+
* BASE+4M-BASE+5M-1 : Test System RAM 2
151+
* BASE+4M+128K-BASE+4M+256K-1: Test Code
152+
* BASE+5M-BASE+6M-1 : Test System RAM 3
153+
*/
154+
#define RES_TEST_RAM0_OFFSET 0
155+
#define RES_TEST_RAM0_SIZE SZ_1M
156+
#define RES_TEST_HOLE0_OFFSET (RES_TEST_RAM0_OFFSET + RES_TEST_RAM0_SIZE)
157+
#define RES_TEST_HOLE0_SIZE SZ_1M
158+
#define RES_TEST_WIN0_OFFSET (RES_TEST_HOLE0_OFFSET + RES_TEST_HOLE0_SIZE)
159+
#define RES_TEST_WIN0_SIZE SZ_1M
160+
#define RES_TEST_RAM1_OFFSET (RES_TEST_WIN0_OFFSET + RES_TEST_WIN0_SIZE)
161+
#define RES_TEST_RAM1_SIZE SZ_1M
162+
#define RES_TEST_WIN1_OFFSET (RES_TEST_RAM1_OFFSET + RES_TEST_RAM1_SIZE)
163+
#define RES_TEST_WIN1_SIZE (SZ_1M * 3)
164+
#define RES_TEST_RAM2_OFFSET RES_TEST_WIN1_OFFSET
165+
#define RES_TEST_RAM2_SIZE SZ_1M
166+
#define RES_TEST_CODE_OFFSET (RES_TEST_RAM2_OFFSET + SZ_128K)
167+
#define RES_TEST_CODE_SIZE SZ_128K
168+
#define RES_TEST_RAM3_OFFSET (RES_TEST_RAM2_OFFSET + RES_TEST_RAM2_SIZE)
169+
#define RES_TEST_RAM3_SIZE SZ_1M
170+
#define RES_TEST_TOTAL_SIZE ((RES_TEST_WIN1_OFFSET + RES_TEST_WIN1_SIZE))
171+
172+
static void remove_free_resource(void *ctx)
173+
{
174+
struct resource *res = (struct resource *)ctx;
175+
176+
remove_resource(res);
177+
kfree(res);
178+
}
179+
180+
static void resource_test_request_region(struct kunit *test, struct resource *parent,
181+
resource_size_t start, resource_size_t size,
182+
const char *name, unsigned long flags)
183+
{
184+
struct resource *res;
185+
186+
res = __request_region(parent, start, size, name, flags);
187+
KUNIT_ASSERT_NOT_NULL(test, res);
188+
kunit_add_action_or_reset(test, remove_free_resource, res);
189+
}
190+
191+
static void resource_test_insert_resource(struct kunit *test, struct resource *parent,
192+
resource_size_t start, resource_size_t size,
193+
const char *name, unsigned long flags)
194+
{
195+
struct resource *res;
196+
197+
res = kzalloc(sizeof(*res), GFP_KERNEL);
198+
KUNIT_ASSERT_NOT_NULL(test, res);
199+
200+
res->name = name;
201+
res->start = start;
202+
res->end = start + size - 1;
203+
res->flags = flags;
204+
if (insert_resource(parent, res)) {
205+
kfree(res);
206+
KUNIT_FAIL_AND_ABORT(test, "Fail to insert resource %pR\n", res);
207+
}
208+
209+
kunit_add_action_or_reset(test, remove_free_resource, res);
210+
}
211+
212+
static void resource_test_region_intersects(struct kunit *test)
213+
{
214+
unsigned long flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
215+
struct resource *parent;
216+
resource_size_t start;
217+
218+
/* Find an iomem_resource hole to hold test resources */
219+
parent = alloc_free_mem_region(&iomem_resource, RES_TEST_TOTAL_SIZE, SZ_1M,
220+
"test resources");
221+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
222+
start = parent->start;
223+
kunit_add_action_or_reset(test, remove_free_resource, parent);
224+
225+
resource_test_request_region(test, parent, start + RES_TEST_RAM0_OFFSET,
226+
RES_TEST_RAM0_SIZE, "Test System RAM 0", flags);
227+
resource_test_insert_resource(test, parent, start + RES_TEST_WIN0_OFFSET,
228+
RES_TEST_WIN0_SIZE, "Test CXL Window 0",
229+
IORESOURCE_MEM);
230+
resource_test_request_region(test, parent, start + RES_TEST_RAM1_OFFSET,
231+
RES_TEST_RAM1_SIZE, "Test System RAM 1", flags);
232+
resource_test_insert_resource(test, parent, start + RES_TEST_WIN1_OFFSET,
233+
RES_TEST_WIN1_SIZE, "Test CXL Window 1",
234+
IORESOURCE_MEM);
235+
resource_test_request_region(test, parent, start + RES_TEST_RAM2_OFFSET,
236+
RES_TEST_RAM2_SIZE, "Test System RAM 2", flags);
237+
resource_test_insert_resource(test, parent, start + RES_TEST_CODE_OFFSET,
238+
RES_TEST_CODE_SIZE, "Test Code", flags);
239+
resource_test_request_region(test, parent, start + RES_TEST_RAM3_OFFSET,
240+
RES_TEST_RAM3_SIZE, "Test System RAM 3", flags);
241+
kunit_release_action(test, remove_free_resource, parent);
242+
243+
KUNIT_EXPECT_EQ(test, REGION_INTERSECTS,
244+
region_intersects(start + RES_TEST_RAM0_OFFSET, PAGE_SIZE,
245+
IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE));
246+
KUNIT_EXPECT_EQ(test, REGION_INTERSECTS,
247+
region_intersects(start + RES_TEST_RAM0_OFFSET +
248+
RES_TEST_RAM0_SIZE - PAGE_SIZE, 2 * PAGE_SIZE,
249+
IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE));
250+
KUNIT_EXPECT_EQ(test, REGION_DISJOINT,
251+
region_intersects(start + RES_TEST_HOLE0_OFFSET, PAGE_SIZE,
252+
IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE));
253+
KUNIT_EXPECT_EQ(test, REGION_DISJOINT,
254+
region_intersects(start + RES_TEST_HOLE0_OFFSET +
255+
RES_TEST_HOLE0_SIZE - PAGE_SIZE, 2 * PAGE_SIZE,
256+
IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE));
257+
KUNIT_EXPECT_EQ(test, REGION_MIXED,
258+
region_intersects(start + RES_TEST_WIN0_OFFSET +
259+
RES_TEST_WIN0_SIZE - PAGE_SIZE, 2 * PAGE_SIZE,
260+
IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE));
261+
KUNIT_EXPECT_EQ(test, REGION_INTERSECTS,
262+
region_intersects(start + RES_TEST_RAM1_OFFSET +
263+
RES_TEST_RAM1_SIZE - PAGE_SIZE, 2 * PAGE_SIZE,
264+
IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE));
265+
KUNIT_EXPECT_EQ(test, REGION_INTERSECTS,
266+
region_intersects(start + RES_TEST_RAM2_OFFSET +
267+
RES_TEST_RAM2_SIZE - PAGE_SIZE, 2 * PAGE_SIZE,
268+
IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE));
269+
KUNIT_EXPECT_EQ(test, REGION_INTERSECTS,
270+
region_intersects(start + RES_TEST_CODE_OFFSET, PAGE_SIZE,
271+
IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE));
272+
KUNIT_EXPECT_EQ(test, REGION_INTERSECTS,
273+
region_intersects(start + RES_TEST_RAM2_OFFSET,
274+
RES_TEST_RAM2_SIZE + PAGE_SIZE,
275+
IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE));
276+
KUNIT_EXPECT_EQ(test, REGION_MIXED,
277+
region_intersects(start + RES_TEST_RAM3_OFFSET,
278+
RES_TEST_RAM3_SIZE + PAGE_SIZE,
279+
IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE));
280+
}
281+
140282
static struct kunit_case resource_test_cases[] = {
141283
KUNIT_CASE(resource_test_union),
142284
KUNIT_CASE(resource_test_intersection),
285+
KUNIT_CASE(resource_test_region_intersects),
143286
{}
144287
};
145288

lib/Kconfig.debug

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2616,6 +2616,7 @@ config RESOURCE_KUNIT_TEST
26162616
tristate "KUnit test for resource API" if !KUNIT_ALL_TESTS
26172617
depends on KUNIT
26182618
default KUNIT_ALL_TESTS
2619+
select GET_FREE_REGION
26192620
help
26202621
This builds the resource API unit test.
26212622
Tests the logic of API provided by resource.c and ioport.h.

0 commit comments

Comments
 (0)