1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Data Access Monitor Unit Tests 4 * 5 * Copyright 2019 Amazon.com, Inc. or its affiliates. All rights reserved. 6 * 7 * Author: SeongJae Park <sjpark@amazon.de> 8 */ 9 10 #ifdef CONFIG_DAMON_KUNIT_TEST 11 12 #ifndef _DAMON_CORE_TEST_H 13 #define _DAMON_CORE_TEST_H 14 15 #include <kunit/test.h> 16 17 static void damon_test_regions(struct kunit *test) 18 { 19 struct damon_region *r; 20 struct damon_target *t; 21 22 r = damon_new_region(1, 2); 23 KUNIT_EXPECT_EQ(test, 1ul, r->ar.start); 24 KUNIT_EXPECT_EQ(test, 2ul, r->ar.end); 25 KUNIT_EXPECT_EQ(test, 0u, r->nr_accesses); 26 27 t = damon_new_target(); 28 KUNIT_EXPECT_EQ(test, 0u, damon_nr_regions(t)); 29 30 damon_add_region(r, t); 31 KUNIT_EXPECT_EQ(test, 1u, damon_nr_regions(t)); 32 33 damon_del_region(r, t); 34 KUNIT_EXPECT_EQ(test, 0u, damon_nr_regions(t)); 35 36 damon_free_target(t); 37 } 38 39 static unsigned int nr_damon_targets(struct damon_ctx *ctx) 40 { 41 struct damon_target *t; 42 unsigned int nr_targets = 0; 43 44 damon_for_each_target(t, ctx) 45 nr_targets++; 46 47 return nr_targets; 48 } 49 50 static void damon_test_target(struct kunit *test) 51 { 52 struct damon_ctx *c = damon_new_ctx(); 53 struct damon_target *t; 54 55 t = damon_new_target(); 56 KUNIT_EXPECT_EQ(test, 0u, nr_damon_targets(c)); 57 58 damon_add_target(c, t); 59 KUNIT_EXPECT_EQ(test, 1u, nr_damon_targets(c)); 60 61 damon_destroy_target(t); 62 KUNIT_EXPECT_EQ(test, 0u, nr_damon_targets(c)); 63 64 damon_destroy_ctx(c); 65 } 66 67 /* 68 * Test kdamond_reset_aggregated() 69 * 70 * DAMON checks access to each region and aggregates this information as the 71 * access frequency of each region. In detail, it increases '->nr_accesses' of 72 * regions that an access has confirmed. 'kdamond_reset_aggregated()' flushes 73 * the aggregated information ('->nr_accesses' of each regions) to the result 74 * buffer. As a result of the flushing, the '->nr_accesses' of regions are 75 * initialized to zero. 76 */ 77 static void damon_test_aggregate(struct kunit *test) 78 { 79 struct damon_ctx *ctx = damon_new_ctx(); 80 unsigned long saddr[][3] = {{10, 20, 30}, {5, 42, 49}, {13, 33, 55} }; 81 unsigned long eaddr[][3] = {{15, 27, 40}, {31, 45, 55}, {23, 44, 66} }; 82 unsigned long accesses[][3] = {{42, 95, 84}, {10, 20, 30}, {0, 1, 2} }; 83 struct damon_target *t; 84 struct damon_region *r; 85 int it, ir; 86 87 for (it = 0; it < 3; it++) { 88 t = damon_new_target(); 89 damon_add_target(ctx, t); 90 } 91 92 it = 0; 93 damon_for_each_target(t, ctx) { 94 for (ir = 0; ir < 3; ir++) { 95 r = damon_new_region(saddr[it][ir], eaddr[it][ir]); 96 r->nr_accesses = accesses[it][ir]; 97 damon_add_region(r, t); 98 } 99 it++; 100 } 101 kdamond_reset_aggregated(ctx); 102 it = 0; 103 damon_for_each_target(t, ctx) { 104 ir = 0; 105 /* '->nr_accesses' should be zeroed */ 106 damon_for_each_region(r, t) { 107 KUNIT_EXPECT_EQ(test, 0u, r->nr_accesses); 108 ir++; 109 } 110 /* regions should be preserved */ 111 KUNIT_EXPECT_EQ(test, 3, ir); 112 it++; 113 } 114 /* targets also should be preserved */ 115 KUNIT_EXPECT_EQ(test, 3, it); 116 117 damon_destroy_ctx(ctx); 118 } 119 120 static void damon_test_split_at(struct kunit *test) 121 { 122 struct damon_ctx *c = damon_new_ctx(); 123 struct damon_target *t; 124 struct damon_region *r; 125 126 t = damon_new_target(); 127 r = damon_new_region(0, 100); 128 damon_add_region(r, t); 129 damon_split_region_at(t, r, 25); 130 KUNIT_EXPECT_EQ(test, r->ar.start, 0ul); 131 KUNIT_EXPECT_EQ(test, r->ar.end, 25ul); 132 133 r = damon_next_region(r); 134 KUNIT_EXPECT_EQ(test, r->ar.start, 25ul); 135 KUNIT_EXPECT_EQ(test, r->ar.end, 100ul); 136 137 damon_free_target(t); 138 damon_destroy_ctx(c); 139 } 140 141 static void damon_test_merge_two(struct kunit *test) 142 { 143 struct damon_target *t; 144 struct damon_region *r, *r2, *r3; 145 int i; 146 147 t = damon_new_target(); 148 r = damon_new_region(0, 100); 149 r->nr_accesses = 10; 150 damon_add_region(r, t); 151 r2 = damon_new_region(100, 300); 152 r2->nr_accesses = 20; 153 damon_add_region(r2, t); 154 155 damon_merge_two_regions(t, r, r2); 156 KUNIT_EXPECT_EQ(test, r->ar.start, 0ul); 157 KUNIT_EXPECT_EQ(test, r->ar.end, 300ul); 158 KUNIT_EXPECT_EQ(test, r->nr_accesses, 16u); 159 160 i = 0; 161 damon_for_each_region(r3, t) { 162 KUNIT_EXPECT_PTR_EQ(test, r, r3); 163 i++; 164 } 165 KUNIT_EXPECT_EQ(test, i, 1); 166 167 damon_free_target(t); 168 } 169 170 static struct damon_region *__nth_region_of(struct damon_target *t, int idx) 171 { 172 struct damon_region *r; 173 unsigned int i = 0; 174 175 damon_for_each_region(r, t) { 176 if (i++ == idx) 177 return r; 178 } 179 180 return NULL; 181 } 182 183 static void damon_test_merge_regions_of(struct kunit *test) 184 { 185 struct damon_target *t; 186 struct damon_region *r; 187 unsigned long sa[] = {0, 100, 114, 122, 130, 156, 170, 184}; 188 unsigned long ea[] = {100, 112, 122, 130, 156, 170, 184, 230}; 189 unsigned int nrs[] = {0, 0, 10, 10, 20, 30, 1, 2}; 190 191 unsigned long saddrs[] = {0, 114, 130, 156, 170}; 192 unsigned long eaddrs[] = {112, 130, 156, 170, 230}; 193 int i; 194 195 t = damon_new_target(); 196 for (i = 0; i < ARRAY_SIZE(sa); i++) { 197 r = damon_new_region(sa[i], ea[i]); 198 r->nr_accesses = nrs[i]; 199 damon_add_region(r, t); 200 } 201 202 damon_merge_regions_of(t, 9, 9999); 203 /* 0-112, 114-130, 130-156, 156-170 */ 204 KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 5u); 205 for (i = 0; i < 5; i++) { 206 r = __nth_region_of(t, i); 207 KUNIT_EXPECT_EQ(test, r->ar.start, saddrs[i]); 208 KUNIT_EXPECT_EQ(test, r->ar.end, eaddrs[i]); 209 } 210 damon_free_target(t); 211 } 212 213 static void damon_test_split_regions_of(struct kunit *test) 214 { 215 struct damon_ctx *c = damon_new_ctx(); 216 struct damon_target *t; 217 struct damon_region *r; 218 219 t = damon_new_target(); 220 r = damon_new_region(0, 22); 221 damon_add_region(r, t); 222 damon_split_regions_of(t, 2); 223 KUNIT_EXPECT_LE(test, damon_nr_regions(t), 2u); 224 damon_free_target(t); 225 226 t = damon_new_target(); 227 r = damon_new_region(0, 220); 228 damon_add_region(r, t); 229 damon_split_regions_of(t, 4); 230 KUNIT_EXPECT_LE(test, damon_nr_regions(t), 4u); 231 damon_free_target(t); 232 damon_destroy_ctx(c); 233 } 234 235 static void damon_test_ops_registration(struct kunit *test) 236 { 237 struct damon_ctx *c = damon_new_ctx(); 238 struct damon_operations ops, bak; 239 240 /* DAMON_OPS_{V,P}ADDR are registered on subsys_initcall */ 241 KUNIT_EXPECT_EQ(test, damon_select_ops(c, DAMON_OPS_VADDR), 0); 242 KUNIT_EXPECT_EQ(test, damon_select_ops(c, DAMON_OPS_PADDR), 0); 243 244 /* Double-registration is prohibited */ 245 ops.id = DAMON_OPS_VADDR; 246 KUNIT_EXPECT_EQ(test, damon_register_ops(&ops), -EINVAL); 247 ops.id = DAMON_OPS_PADDR; 248 KUNIT_EXPECT_EQ(test, damon_register_ops(&ops), -EINVAL); 249 250 /* Unknown ops id cannot be registered */ 251 KUNIT_EXPECT_EQ(test, damon_select_ops(c, NR_DAMON_OPS), -EINVAL); 252 253 /* Registration should success after unregistration */ 254 mutex_lock(&damon_ops_lock); 255 bak = damon_registered_ops[DAMON_OPS_VADDR]; 256 damon_registered_ops[DAMON_OPS_VADDR] = (struct damon_operations){}; 257 mutex_unlock(&damon_ops_lock); 258 259 ops.id = DAMON_OPS_VADDR; 260 KUNIT_EXPECT_EQ(test, damon_register_ops(&ops), 0); 261 262 mutex_lock(&damon_ops_lock); 263 damon_registered_ops[DAMON_OPS_VADDR] = bak; 264 mutex_unlock(&damon_ops_lock); 265 266 /* Check double-registration failure again */ 267 KUNIT_EXPECT_EQ(test, damon_register_ops(&ops), -EINVAL); 268 } 269 270 static void damon_test_set_regions(struct kunit *test) 271 { 272 struct damon_target *t = damon_new_target(); 273 struct damon_region *r1 = damon_new_region(4, 16); 274 struct damon_region *r2 = damon_new_region(24, 32); 275 struct damon_addr_range range = {.start = 8, .end = 28}; 276 unsigned long expects[] = {8, 16, 16, 24, 24, 28}; 277 int expect_idx = 0; 278 struct damon_region *r; 279 280 damon_add_region(r1, t); 281 damon_add_region(r2, t); 282 damon_set_regions(t, &range, 1); 283 284 KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 3); 285 damon_for_each_region(r, t) { 286 KUNIT_EXPECT_EQ(test, r->ar.start, expects[expect_idx++]); 287 KUNIT_EXPECT_EQ(test, r->ar.end, expects[expect_idx++]); 288 } 289 damon_destroy_target(t); 290 } 291 292 static void damon_test_update_monitoring_result(struct kunit *test) 293 { 294 struct damon_attrs old_attrs = { 295 .sample_interval = 10, .aggr_interval = 1000,}; 296 struct damon_attrs new_attrs; 297 struct damon_region *r = damon_new_region(3, 7); 298 299 r->nr_accesses = 15; 300 r->age = 20; 301 302 new_attrs = (struct damon_attrs){ 303 .sample_interval = 100, .aggr_interval = 10000,}; 304 damon_update_monitoring_result(r, &old_attrs, &new_attrs); 305 KUNIT_EXPECT_EQ(test, r->nr_accesses, 15); 306 KUNIT_EXPECT_EQ(test, r->age, 2); 307 308 new_attrs = (struct damon_attrs){ 309 .sample_interval = 1, .aggr_interval = 1000}; 310 damon_update_monitoring_result(r, &old_attrs, &new_attrs); 311 KUNIT_EXPECT_EQ(test, r->nr_accesses, 150); 312 KUNIT_EXPECT_EQ(test, r->age, 2); 313 314 new_attrs = (struct damon_attrs){ 315 .sample_interval = 1, .aggr_interval = 100}; 316 damon_update_monitoring_result(r, &old_attrs, &new_attrs); 317 KUNIT_EXPECT_EQ(test, r->nr_accesses, 150); 318 KUNIT_EXPECT_EQ(test, r->age, 20); 319 } 320 321 static void damon_test_set_attrs(struct kunit *test) 322 { 323 struct damon_ctx *c = damon_new_ctx(); 324 struct damon_attrs valid_attrs = { 325 .min_nr_regions = 10, .max_nr_regions = 1000, 326 .sample_interval = 5000, .aggr_interval = 100000,}; 327 struct damon_attrs invalid_attrs; 328 329 KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &valid_attrs), 0); 330 331 invalid_attrs = valid_attrs; 332 invalid_attrs.min_nr_regions = 1; 333 KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &invalid_attrs), -EINVAL); 334 335 invalid_attrs = valid_attrs; 336 invalid_attrs.max_nr_regions = 9; 337 KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &invalid_attrs), -EINVAL); 338 339 invalid_attrs = valid_attrs; 340 invalid_attrs.aggr_interval = 4999; 341 KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &invalid_attrs), -EINVAL); 342 } 343 344 static void damos_test_new_filter(struct kunit *test) 345 { 346 struct damos_filter *filter; 347 348 filter = damos_new_filter(DAMOS_FILTER_TYPE_ANON, true); 349 KUNIT_EXPECT_EQ(test, filter->type, DAMOS_FILTER_TYPE_ANON); 350 KUNIT_EXPECT_EQ(test, filter->matching, true); 351 KUNIT_EXPECT_PTR_EQ(test, filter->list.prev, &filter->list); 352 KUNIT_EXPECT_PTR_EQ(test, filter->list.next, &filter->list); 353 damos_destroy_filter(filter); 354 } 355 356 static void damos_test_filter_out(struct kunit *test) 357 { 358 struct damon_target *t; 359 struct damon_region *r, *r2; 360 struct damos_filter *f; 361 362 f = damos_new_filter(DAMOS_FILTER_TYPE_ADDR, true); 363 f->addr_range = (struct damon_addr_range){ 364 .start = DAMON_MIN_REGION * 2, .end = DAMON_MIN_REGION * 6}; 365 366 t = damon_new_target(); 367 r = damon_new_region(DAMON_MIN_REGION * 3, DAMON_MIN_REGION * 5); 368 damon_add_region(r, t); 369 370 /* region in the range */ 371 KUNIT_EXPECT_TRUE(test, __damos_filter_out(NULL, t, r, f)); 372 KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1); 373 374 /* region before the range */ 375 r->ar.start = DAMON_MIN_REGION * 1; 376 r->ar.end = DAMON_MIN_REGION * 2; 377 KUNIT_EXPECT_FALSE(test, __damos_filter_out(NULL, t, r, f)); 378 KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1); 379 380 /* region after the range */ 381 r->ar.start = DAMON_MIN_REGION * 6; 382 r->ar.end = DAMON_MIN_REGION * 8; 383 KUNIT_EXPECT_FALSE(test, __damos_filter_out(NULL, t, r, f)); 384 KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1); 385 386 /* region started before the range */ 387 r->ar.start = DAMON_MIN_REGION * 1; 388 r->ar.end = DAMON_MIN_REGION * 4; 389 KUNIT_EXPECT_FALSE(test, __damos_filter_out(NULL, t, r, f)); 390 /* filter should have split the region */ 391 KUNIT_EXPECT_EQ(test, r->ar.start, DAMON_MIN_REGION * 1); 392 KUNIT_EXPECT_EQ(test, r->ar.end, DAMON_MIN_REGION * 2); 393 KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2); 394 r2 = damon_next_region(r); 395 KUNIT_EXPECT_EQ(test, r2->ar.start, DAMON_MIN_REGION * 2); 396 KUNIT_EXPECT_EQ(test, r2->ar.end, DAMON_MIN_REGION * 4); 397 damon_destroy_region(r2, t); 398 399 /* region started in the range */ 400 r->ar.start = DAMON_MIN_REGION * 2; 401 r->ar.end = DAMON_MIN_REGION * 8; 402 KUNIT_EXPECT_TRUE(test, __damos_filter_out(NULL, t, r, f)); 403 /* filter should have split the region */ 404 KUNIT_EXPECT_EQ(test, r->ar.start, DAMON_MIN_REGION * 2); 405 KUNIT_EXPECT_EQ(test, r->ar.end, DAMON_MIN_REGION * 6); 406 KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2); 407 r2 = damon_next_region(r); 408 KUNIT_EXPECT_EQ(test, r2->ar.start, DAMON_MIN_REGION * 6); 409 KUNIT_EXPECT_EQ(test, r2->ar.end, DAMON_MIN_REGION * 8); 410 damon_destroy_region(r2, t); 411 412 damon_free_target(t); 413 damos_free_filter(f); 414 } 415 416 static struct kunit_case damon_test_cases[] = { 417 KUNIT_CASE(damon_test_target), 418 KUNIT_CASE(damon_test_regions), 419 KUNIT_CASE(damon_test_aggregate), 420 KUNIT_CASE(damon_test_split_at), 421 KUNIT_CASE(damon_test_merge_two), 422 KUNIT_CASE(damon_test_merge_regions_of), 423 KUNIT_CASE(damon_test_split_regions_of), 424 KUNIT_CASE(damon_test_ops_registration), 425 KUNIT_CASE(damon_test_set_regions), 426 KUNIT_CASE(damon_test_update_monitoring_result), 427 KUNIT_CASE(damon_test_set_attrs), 428 KUNIT_CASE(damos_test_new_filter), 429 KUNIT_CASE(damos_test_filter_out), 430 {}, 431 }; 432 433 static struct kunit_suite damon_test_suite = { 434 .name = "damon", 435 .test_cases = damon_test_cases, 436 }; 437 kunit_test_suite(damon_test_suite); 438 439 #endif /* _DAMON_CORE_TEST_H */ 440 441 #endif /* CONFIG_DAMON_KUNIT_TEST */ 442