1 // SPDX-License-Identifier: GPL-2.0+
3 * Test cases for API provided by resource.c and ioport.h
6 #include <kunit/test.h>
7 #include <linux/ioport.h>
8 #include <linux/kernel.h>
9 #include <linux/string.h>
10 #include <linux/sizes.h>
13 #define R0_START 0x0000
15 #define R1_START 0x1234
17 #define R2_START 0x4567
19 #define R3_START 0x6789
21 #define R4_START 0x2000
24 static struct resource r0
= { .start
= R0_START
, .end
= R0_END
};
25 static struct resource r1
= { .start
= R1_START
, .end
= R1_END
};
26 static struct resource r2
= { .start
= R2_START
, .end
= R2_END
};
27 static struct resource r3
= { .start
= R3_START
, .end
= R3_END
};
28 static struct resource r4
= { .start
= R4_START
, .end
= R4_END
};
37 static struct result results_for_union
[] = {
39 .r1
= &r1
, .r2
= &r0
, .r
.start
= R0_START
, .r
.end
= R0_END
, .ret
= true,
41 .r1
= &r2
, .r2
= &r0
, .r
.start
= R0_START
, .r
.end
= R0_END
, .ret
= true,
43 .r1
= &r3
, .r2
= &r0
, .r
.start
= R0_START
, .r
.end
= R0_END
, .ret
= true,
45 .r1
= &r4
, .r2
= &r0
, .r
.start
= R0_START
, .r
.end
= R0_END
, .ret
= true,
47 .r1
= &r2
, .r2
= &r1
, .ret
= false,
49 .r1
= &r3
, .r2
= &r1
, .ret
= false,
51 .r1
= &r4
, .r2
= &r1
, .r
.start
= R1_START
, .r
.end
= R4_END
, .ret
= true,
53 .r1
= &r2
, .r2
= &r3
, .ret
= false,
55 .r1
= &r2
, .r2
= &r4
, .r
.start
= R4_START
, .r
.end
= R4_END
, .ret
= true,
57 .r1
= &r3
, .r2
= &r4
, .r
.start
= R4_START
, .r
.end
= R3_END
, .ret
= true,
61 static struct result results_for_intersection
[] = {
63 .r1
= &r1
, .r2
= &r0
, .r
.start
= R1_START
, .r
.end
= R1_END
, .ret
= true,
65 .r1
= &r2
, .r2
= &r0
, .r
.start
= R2_START
, .r
.end
= R2_END
, .ret
= true,
67 .r1
= &r3
, .r2
= &r0
, .r
.start
= R3_START
, .r
.end
= R3_END
, .ret
= true,
69 .r1
= &r4
, .r2
= &r0
, .r
.start
= R4_START
, .r
.end
= R4_END
, .ret
= true,
71 .r1
= &r2
, .r2
= &r1
, .ret
= false,
73 .r1
= &r3
, .r2
= &r1
, .ret
= false,
75 .r1
= &r4
, .r2
= &r1
, .r
.start
= R4_START
, .r
.end
= R1_END
, .ret
= true,
77 .r1
= &r2
, .r2
= &r3
, .ret
= false,
79 .r1
= &r2
, .r2
= &r4
, .r
.start
= R2_START
, .r
.end
= R2_END
, .ret
= true,
81 .r1
= &r3
, .r2
= &r4
, .r
.start
= R3_START
, .r
.end
= R4_END
, .ret
= true,
85 static void resource_do_test(struct kunit
*test
, bool ret
, struct resource
*r
,
86 bool exp_ret
, struct resource
*exp_r
,
87 struct resource
*r1
, struct resource
*r2
)
89 KUNIT_EXPECT_EQ_MSG(test
, ret
, exp_ret
, "Resources %pR %pR", r1
, r2
);
90 KUNIT_EXPECT_EQ_MSG(test
, r
->start
, exp_r
->start
, "Start elements are not equal");
91 KUNIT_EXPECT_EQ_MSG(test
, r
->end
, exp_r
->end
, "End elements are not equal");
94 static void resource_do_union_test(struct kunit
*test
, struct result
*r
)
96 struct resource result
;
99 memset(&result
, 0, sizeof(result
));
100 ret
= resource_union(r
->r1
, r
->r2
, &result
);
101 resource_do_test(test
, ret
, &result
, r
->ret
, &r
->r
, r
->r1
, r
->r2
);
103 memset(&result
, 0, sizeof(result
));
104 ret
= resource_union(r
->r2
, r
->r1
, &result
);
105 resource_do_test(test
, ret
, &result
, r
->ret
, &r
->r
, r
->r2
, r
->r1
);
108 static void resource_test_union(struct kunit
*test
)
110 struct result
*r
= results_for_union
;
114 resource_do_union_test(test
, &r
[i
]);
115 } while (++i
< ARRAY_SIZE(results_for_union
));
118 static void resource_do_intersection_test(struct kunit
*test
, struct result
*r
)
120 struct resource result
;
123 memset(&result
, 0, sizeof(result
));
124 ret
= resource_intersection(r
->r1
, r
->r2
, &result
);
125 resource_do_test(test
, ret
, &result
, r
->ret
, &r
->r
, r
->r1
, r
->r2
);
127 memset(&result
, 0, sizeof(result
));
128 ret
= resource_intersection(r
->r2
, r
->r1
, &result
);
129 resource_do_test(test
, ret
, &result
, r
->ret
, &r
->r
, r
->r2
, r
->r1
);
132 static void resource_test_intersection(struct kunit
*test
)
134 struct result
*r
= results_for_intersection
;
138 resource_do_intersection_test(test
, &r
[i
]);
139 } while (++i
< ARRAY_SIZE(results_for_intersection
));
143 * The test resource tree for region_intersects() test:
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
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))
172 KUNIT_DEFINE_ACTION_WRAPPER(kfree_wrapper
, kfree
, const void *);
174 static void remove_free_resource(void *ctx
)
176 struct resource
*res
= (struct resource
*)ctx
;
178 remove_resource(res
);
182 static void resource_test_add_action_or_abort(
183 struct kunit
*test
, void (*action
)(void *), void *ctx
)
185 KUNIT_ASSERT_EQ_MSG(test
, 0,
186 kunit_add_action_or_reset(test
, action
, ctx
),
187 "Fail to add action");
190 static void resource_test_request_region(struct kunit
*test
, struct resource
*parent
,
191 resource_size_t start
, resource_size_t size
,
192 const char *name
, unsigned long flags
)
194 struct resource
*res
;
196 res
= __request_region(parent
, start
, size
, name
, flags
);
197 KUNIT_ASSERT_NOT_NULL(test
, res
);
198 resource_test_add_action_or_abort(test
, remove_free_resource
, res
);
201 static void resource_test_insert_resource(struct kunit
*test
, struct resource
*parent
,
202 resource_size_t start
, resource_size_t size
,
203 const char *name
, unsigned long flags
)
205 struct resource
*res
;
207 res
= kzalloc(sizeof(*res
), GFP_KERNEL
);
208 KUNIT_ASSERT_NOT_NULL(test
, res
);
212 res
->end
= start
+ size
- 1;
214 if (insert_resource(parent
, res
)) {
215 resource_test_add_action_or_abort(test
, kfree_wrapper
, res
);
216 KUNIT_FAIL_AND_ABORT(test
, "Fail to insert resource %pR\n", res
);
219 resource_test_add_action_or_abort(test
, remove_free_resource
, res
);
222 static void resource_test_region_intersects(struct kunit
*test
)
224 unsigned long flags
= IORESOURCE_SYSTEM_RAM
| IORESOURCE_BUSY
;
225 struct resource
*parent
;
226 resource_size_t start
;
228 /* Find an iomem_resource hole to hold test resources */
229 parent
= alloc_free_mem_region(&iomem_resource
, RES_TEST_TOTAL_SIZE
, SZ_1M
,
231 KUNIT_ASSERT_NOT_ERR_OR_NULL(test
, parent
);
232 start
= parent
->start
;
233 resource_test_add_action_or_abort(test
, remove_free_resource
, parent
);
235 resource_test_request_region(test
, parent
, start
+ RES_TEST_RAM0_OFFSET
,
236 RES_TEST_RAM0_SIZE
, "Test System RAM 0", flags
);
237 resource_test_insert_resource(test
, parent
, start
+ RES_TEST_WIN0_OFFSET
,
238 RES_TEST_WIN0_SIZE
, "Test CXL Window 0",
240 resource_test_request_region(test
, parent
, start
+ RES_TEST_RAM1_OFFSET
,
241 RES_TEST_RAM1_SIZE
, "Test System RAM 1", flags
);
242 resource_test_insert_resource(test
, parent
, start
+ RES_TEST_WIN1_OFFSET
,
243 RES_TEST_WIN1_SIZE
, "Test CXL Window 1",
245 resource_test_request_region(test
, parent
, start
+ RES_TEST_RAM2_OFFSET
,
246 RES_TEST_RAM2_SIZE
, "Test System RAM 2", flags
);
247 resource_test_insert_resource(test
, parent
, start
+ RES_TEST_CODE_OFFSET
,
248 RES_TEST_CODE_SIZE
, "Test Code", flags
);
249 resource_test_request_region(test
, parent
, start
+ RES_TEST_RAM3_OFFSET
,
250 RES_TEST_RAM3_SIZE
, "Test System RAM 3", flags
);
251 kunit_release_action(test
, remove_free_resource
, parent
);
253 KUNIT_EXPECT_EQ(test
, REGION_INTERSECTS
,
254 region_intersects(start
+ RES_TEST_RAM0_OFFSET
, PAGE_SIZE
,
255 IORESOURCE_SYSTEM_RAM
, IORES_DESC_NONE
));
256 KUNIT_EXPECT_EQ(test
, REGION_INTERSECTS
,
257 region_intersects(start
+ RES_TEST_RAM0_OFFSET
+
258 RES_TEST_RAM0_SIZE
- PAGE_SIZE
, 2 * PAGE_SIZE
,
259 IORESOURCE_SYSTEM_RAM
, IORES_DESC_NONE
));
260 KUNIT_EXPECT_EQ(test
, REGION_DISJOINT
,
261 region_intersects(start
+ RES_TEST_HOLE0_OFFSET
, PAGE_SIZE
,
262 IORESOURCE_SYSTEM_RAM
, IORES_DESC_NONE
));
263 KUNIT_EXPECT_EQ(test
, REGION_DISJOINT
,
264 region_intersects(start
+ RES_TEST_HOLE0_OFFSET
+
265 RES_TEST_HOLE0_SIZE
- PAGE_SIZE
, 2 * PAGE_SIZE
,
266 IORESOURCE_SYSTEM_RAM
, IORES_DESC_NONE
));
267 KUNIT_EXPECT_EQ(test
, REGION_MIXED
,
268 region_intersects(start
+ RES_TEST_WIN0_OFFSET
+
269 RES_TEST_WIN0_SIZE
- PAGE_SIZE
, 2 * PAGE_SIZE
,
270 IORESOURCE_SYSTEM_RAM
, IORES_DESC_NONE
));
271 KUNIT_EXPECT_EQ(test
, REGION_INTERSECTS
,
272 region_intersects(start
+ RES_TEST_RAM1_OFFSET
+
273 RES_TEST_RAM1_SIZE
- PAGE_SIZE
, 2 * PAGE_SIZE
,
274 IORESOURCE_SYSTEM_RAM
, IORES_DESC_NONE
));
275 KUNIT_EXPECT_EQ(test
, REGION_INTERSECTS
,
276 region_intersects(start
+ RES_TEST_RAM2_OFFSET
+
277 RES_TEST_RAM2_SIZE
- PAGE_SIZE
, 2 * PAGE_SIZE
,
278 IORESOURCE_SYSTEM_RAM
, IORES_DESC_NONE
));
279 KUNIT_EXPECT_EQ(test
, REGION_INTERSECTS
,
280 region_intersects(start
+ RES_TEST_CODE_OFFSET
, PAGE_SIZE
,
281 IORESOURCE_SYSTEM_RAM
, IORES_DESC_NONE
));
282 KUNIT_EXPECT_EQ(test
, REGION_INTERSECTS
,
283 region_intersects(start
+ RES_TEST_RAM2_OFFSET
,
284 RES_TEST_RAM2_SIZE
+ PAGE_SIZE
,
285 IORESOURCE_SYSTEM_RAM
, IORES_DESC_NONE
));
286 KUNIT_EXPECT_EQ(test
, REGION_MIXED
,
287 region_intersects(start
+ RES_TEST_RAM3_OFFSET
,
288 RES_TEST_RAM3_SIZE
+ PAGE_SIZE
,
289 IORESOURCE_SYSTEM_RAM
, IORES_DESC_NONE
));
292 static struct kunit_case resource_test_cases
[] = {
293 KUNIT_CASE(resource_test_union
),
294 KUNIT_CASE(resource_test_intersection
),
295 KUNIT_CASE(resource_test_region_intersects
),
299 static struct kunit_suite resource_test_suite
= {
301 .test_cases
= resource_test_cases
,
303 kunit_test_suite(resource_test_suite
);
305 MODULE_DESCRIPTION("I/O Port & Memory Resource manager unit tests");
306 MODULE_LICENSE("GPL");