1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * DAMON Code for Virtual Address Spaces 4 */ 5 6 #define pr_fmt(fmt) "damon-va: " fmt 7 8 #include <linux/highmem.h> 9 #include <linux/hugetlb.h> 10 #include <linux/mman.h> 11 #include <linux/mmu_notifier.h> 12 #include <linux/page_idle.h> 13 #include <linux/pagemap.h> 14 #include <linux/pagewalk.h> 15 #include <linux/sched/mm.h> 16 17 #include "../internal.h" 18 #include "ops-common.h" 19 20 #ifdef CONFIG_DAMON_VADDR_KUNIT_TEST 21 #undef DAMON_MIN_REGION_SZ 22 #define DAMON_MIN_REGION_SZ 1 23 #endif 24 25 /* 26 * 't->pid' should be the pointer to the relevant 'struct pid' having reference 27 * count. Caller must put the returned task, unless it is NULL. 28 */ 29 static inline struct task_struct *damon_get_task_struct(struct damon_target *t) 30 { 31 return get_pid_task(t->pid, PIDTYPE_PID); 32 } 33 34 /* 35 * Get the mm_struct of the given target 36 * 37 * Caller _must_ put the mm_struct after use, unless it is NULL. 38 * 39 * Returns the mm_struct of the target on success, NULL on failure 40 */ 41 static struct mm_struct *damon_get_mm(struct damon_target *t) 42 { 43 struct task_struct *task; 44 struct mm_struct *mm; 45 46 task = damon_get_task_struct(t); 47 if (!task) 48 return NULL; 49 50 mm = get_task_mm(task); 51 put_task_struct(task); 52 return mm; 53 } 54 55 static unsigned long sz_range(struct damon_addr_range *r) 56 { 57 return r->end - r->start; 58 } 59 60 /* 61 * Find three regions separated by two biggest unmapped regions 62 * 63 * vma the head vma of the target address space 64 * regions an array of three address ranges that results will be saved 65 * 66 * This function receives an address space and finds three regions in it which 67 * separated by the two biggest unmapped regions in the space. Please refer to 68 * below comments of '__damon_va_init_regions()' function to know why this is 69 * necessary. 70 * 71 * Returns 0 if success, or negative error code otherwise. 72 */ 73 static int __damon_va_three_regions(struct mm_struct *mm, 74 struct damon_addr_range regions[3]) 75 { 76 struct damon_addr_range first_gap = {0}, second_gap = {0}; 77 VMA_ITERATOR(vmi, mm, 0); 78 struct vm_area_struct *vma, *prev = NULL; 79 unsigned long start; 80 81 /* 82 * Find the two biggest gaps so that first_gap > second_gap > others. 83 * If this is too slow, it can be optimised to examine the maple 84 * tree gaps. 85 */ 86 rcu_read_lock(); 87 for_each_vma(vmi, vma) { 88 unsigned long gap; 89 90 if (!prev) { 91 start = vma->vm_start; 92 goto next; 93 } 94 gap = vma->vm_start - prev->vm_end; 95 96 if (gap > sz_range(&first_gap)) { 97 second_gap = first_gap; 98 first_gap.start = prev->vm_end; 99 first_gap.end = vma->vm_start; 100 } else if (gap > sz_range(&second_gap)) { 101 second_gap.start = prev->vm_end; 102 second_gap.end = vma->vm_start; 103 } 104 next: 105 prev = vma; 106 } 107 rcu_read_unlock(); 108 109 if (!sz_range(&second_gap) || !sz_range(&first_gap)) 110 return -EINVAL; 111 112 /* Sort the two biggest gaps by address */ 113 if (first_gap.start > second_gap.start) 114 swap(first_gap, second_gap); 115 116 /* Store the result */ 117 regions[0].start = ALIGN(start, DAMON_MIN_REGION_SZ); 118 regions[0].end = ALIGN(first_gap.start, DAMON_MIN_REGION_SZ); 119 regions[1].start = ALIGN(first_gap.end, DAMON_MIN_REGION_SZ); 120 regions[1].end = ALIGN(second_gap.start, DAMON_MIN_REGION_SZ); 121 regions[2].start = ALIGN(second_gap.end, DAMON_MIN_REGION_SZ); 122 regions[2].end = ALIGN(prev->vm_end, DAMON_MIN_REGION_SZ); 123 124 return 0; 125 } 126 127 /* 128 * Get the three regions in the given target (task) 129 * 130 * Returns 0 on success, negative error code otherwise. 131 */ 132 static int damon_va_three_regions(struct damon_target *t, 133 struct damon_addr_range regions[3]) 134 { 135 struct mm_struct *mm; 136 int rc; 137 138 mm = damon_get_mm(t); 139 if (!mm) 140 return -EINVAL; 141 142 mmap_read_lock(mm); 143 rc = __damon_va_three_regions(mm, regions); 144 mmap_read_unlock(mm); 145 146 mmput(mm); 147 return rc; 148 } 149 150 /* 151 * Initialize the monitoring target regions for the given target (task) 152 * 153 * t the given target 154 * 155 * Because only a number of small portions of the entire address space 156 * is actually mapped to the memory and accessed, monitoring the unmapped 157 * regions is wasteful. That said, because we can deal with small noises, 158 * tracking every mapping is not strictly required but could even incur a high 159 * overhead if the mapping frequently changes or the number of mappings is 160 * high. The adaptive regions adjustment mechanism will further help to deal 161 * with the noise by simply identifying the unmapped areas as a region that 162 * has no access. Moreover, applying the real mappings that would have many 163 * unmapped areas inside will make the adaptive mechanism quite complex. That 164 * said, too huge unmapped areas inside the monitoring target should be removed 165 * to not take the time for the adaptive mechanism. 166 * 167 * For the reason, we convert the complex mappings to three distinct regions 168 * that cover every mapped area of the address space. Also the two gaps 169 * between the three regions are the two biggest unmapped areas in the given 170 * address space. In detail, this function first identifies the start and the 171 * end of the mappings and the two biggest unmapped areas of the address space. 172 * Then, it constructs the three regions as below: 173 * 174 * [mappings[0]->start, big_two_unmapped_areas[0]->start) 175 * [big_two_unmapped_areas[0]->end, big_two_unmapped_areas[1]->start) 176 * [big_two_unmapped_areas[1]->end, mappings[nr_mappings - 1]->end) 177 * 178 * As usual memory map of processes is as below, the gap between the heap and 179 * the uppermost mmap()-ed region, and the gap between the lowermost mmap()-ed 180 * region and the stack will be two biggest unmapped regions. Because these 181 * gaps are exceptionally huge areas in usual address space, excluding these 182 * two biggest unmapped regions will be sufficient to make a trade-off. 183 * 184 * <heap> 185 * <BIG UNMAPPED REGION 1> 186 * <uppermost mmap()-ed region> 187 * (other mmap()-ed regions and small unmapped regions) 188 * <lowermost mmap()-ed region> 189 * <BIG UNMAPPED REGION 2> 190 * <stack> 191 */ 192 static void __damon_va_init_regions(struct damon_ctx *ctx, 193 struct damon_target *t) 194 { 195 struct damon_target *ti; 196 struct damon_addr_range regions[3]; 197 int tidx = 0; 198 199 if (damon_va_three_regions(t, regions)) { 200 damon_for_each_target(ti, ctx) { 201 if (ti == t) 202 break; 203 tidx++; 204 } 205 pr_debug("Failed to get three regions of %dth target\n", tidx); 206 return; 207 } 208 209 damon_set_regions(t, regions, 3, DAMON_MIN_REGION_SZ); 210 } 211 212 /* Initialize '->regions_list' of every target (task) */ 213 static void damon_va_init(struct damon_ctx *ctx) 214 { 215 struct damon_target *t; 216 217 damon_for_each_target(t, ctx) { 218 /* the user may set the target regions as they want */ 219 if (!damon_nr_regions(t)) 220 __damon_va_init_regions(ctx, t); 221 } 222 } 223 224 /* 225 * Update regions for current memory mappings 226 */ 227 static void damon_va_update(struct damon_ctx *ctx) 228 { 229 struct damon_addr_range three_regions[3]; 230 struct damon_target *t; 231 232 damon_for_each_target(t, ctx) { 233 if (damon_va_three_regions(t, three_regions)) 234 continue; 235 damon_set_regions(t, three_regions, 3, DAMON_MIN_REGION_SZ); 236 } 237 } 238 239 static void damon_va_walk_page_range(struct mm_struct *mm, unsigned long start, 240 unsigned long end, struct mm_walk_ops *ops, void *private) 241 { 242 struct vm_area_struct *vma; 243 244 vma = lock_vma_under_rcu(mm, start); 245 if (!vma) 246 goto lock_mmap; 247 248 if (end > vma->vm_end) { 249 vma_end_read(vma); 250 goto lock_mmap; 251 } 252 253 if (!(vma->vm_flags & VM_PFNMAP)) { 254 ops->walk_lock = PGWALK_VMA_RDLOCK_VERIFY; 255 walk_page_range_vma(vma, start, end, ops, private); 256 } 257 258 vma_end_read(vma); 259 return; 260 261 lock_mmap: 262 mmap_read_lock(mm); 263 ops->walk_lock = PGWALK_RDLOCK; 264 walk_page_range(mm, start, end, ops, private); 265 mmap_read_unlock(mm); 266 } 267 268 static int damon_mkold_pmd_entry(pmd_t *pmd, unsigned long addr, 269 unsigned long next, struct mm_walk *walk) 270 { 271 pte_t *pte; 272 spinlock_t *ptl; 273 274 ptl = pmd_trans_huge_lock(pmd, walk->vma); 275 if (ptl) { 276 pmd_t pmde = pmdp_get(pmd); 277 278 if (pmd_present(pmde)) 279 damon_pmdp_mkold(pmd, walk->vma, addr); 280 spin_unlock(ptl); 281 return 0; 282 } 283 284 pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); 285 if (!pte) 286 return 0; 287 if (!pte_present(ptep_get(pte))) 288 goto out; 289 damon_ptep_mkold(pte, walk->vma, addr); 290 out: 291 pte_unmap_unlock(pte, ptl); 292 return 0; 293 } 294 295 #ifdef CONFIG_HUGETLB_PAGE 296 static bool damon_hugetlb_ptep_mkold(pte_t *pte, struct mm_struct *mm, 297 struct vm_area_struct *vma, unsigned long addr, pte_t *entry) 298 { 299 unsigned long psize = huge_page_size(hstate_vma(vma)); 300 301 if (!pte_young(*entry)) 302 return false; 303 *entry = huge_ptep_get_and_clear(mm, addr, pte, psize); 304 *entry = pte_mkold(*entry); 305 set_huge_pte_at(mm, addr, pte, *entry, psize); 306 return true; 307 } 308 309 static void damon_hugetlb_mkold(pte_t *pte, struct mm_struct *mm, 310 struct vm_area_struct *vma, unsigned long addr) 311 { 312 bool referenced = false; 313 pte_t entry = huge_ptep_get(mm, addr, pte); 314 struct folio *folio = pfn_folio(pte_pfn(entry)); 315 316 folio_get(folio); 317 318 referenced = damon_hugetlb_ptep_mkold(pte, mm, vma, addr, &entry); 319 if (mmu_notifier_clear_young(mm, addr, 320 addr + huge_page_size(hstate_vma(vma)))) 321 referenced = true; 322 323 if (referenced) 324 folio_set_young(folio); 325 326 folio_set_idle(folio); 327 folio_put(folio); 328 } 329 330 static int damon_mkold_hugetlb_entry(pte_t *pte, unsigned long hmask, 331 unsigned long addr, unsigned long end, 332 struct mm_walk *walk) 333 { 334 struct hstate *h = hstate_vma(walk->vma); 335 spinlock_t *ptl; 336 pte_t entry; 337 338 ptl = huge_pte_lock(h, walk->mm, pte); 339 entry = huge_ptep_get(walk->mm, addr, pte); 340 if (!pte_present(entry)) 341 goto out; 342 343 damon_hugetlb_mkold(pte, walk->mm, walk->vma, addr); 344 345 out: 346 spin_unlock(ptl); 347 return 0; 348 } 349 #else 350 #define damon_mkold_hugetlb_entry NULL 351 #endif /* CONFIG_HUGETLB_PAGE */ 352 353 static void damon_va_mkold(struct mm_struct *mm, unsigned long addr) 354 { 355 struct mm_walk_ops damon_mkold_ops = { 356 .pmd_entry = damon_mkold_pmd_entry, 357 .hugetlb_entry = damon_mkold_hugetlb_entry, 358 }; 359 360 damon_va_walk_page_range(mm, addr, addr + 1, &damon_mkold_ops, NULL); 361 } 362 363 /* 364 * Functions for the access checking of the regions 365 */ 366 367 static void __damon_va_prepare_access_check(struct mm_struct *mm, 368 struct damon_region *r, 369 struct damon_ctx *ctx) 370 { 371 r->sampling_addr = damon_rand(ctx, r->ar.start, r->ar.end); 372 373 damon_va_mkold(mm, r->sampling_addr); 374 } 375 376 static void damon_va_prepare_access_checks(struct damon_ctx *ctx) 377 { 378 struct damon_target *t; 379 struct mm_struct *mm; 380 struct damon_region *r; 381 382 damon_for_each_target(t, ctx) { 383 mm = damon_get_mm(t); 384 if (!mm) 385 continue; 386 damon_for_each_region(r, t) 387 __damon_va_prepare_access_check(mm, r, ctx); 388 mmput(mm); 389 } 390 } 391 392 struct damon_young_walk_private { 393 bool young; 394 }; 395 396 static int damon_young_pmd_entry(pmd_t *pmd, unsigned long addr, 397 unsigned long next, struct mm_walk *walk) 398 { 399 pte_t *pte; 400 pte_t ptent; 401 spinlock_t *ptl; 402 struct folio *folio; 403 struct damon_young_walk_private *priv = walk->private; 404 405 #ifdef CONFIG_TRANSPARENT_HUGEPAGE 406 ptl = pmd_trans_huge_lock(pmd, walk->vma); 407 if (ptl) { 408 pmd_t pmde = pmdp_get(pmd); 409 410 if (!pmd_present(pmde)) 411 goto huge_out; 412 folio = vm_normal_folio_pmd(walk->vma, addr, pmde); 413 if (!folio) 414 goto huge_out; 415 if (pmd_young(pmde) || !folio_test_idle(folio) || 416 mmu_notifier_test_young(walk->mm, 417 addr)) 418 priv->young = true; 419 huge_out: 420 spin_unlock(ptl); 421 return 0; 422 } 423 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ 424 425 pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); 426 if (!pte) 427 return 0; 428 ptent = ptep_get(pte); 429 if (!pte_present(ptent)) 430 goto out; 431 folio = vm_normal_folio(walk->vma, addr, ptent); 432 if (!folio) 433 goto out; 434 if (pte_young(ptent) || !folio_test_idle(folio) || 435 mmu_notifier_test_young(walk->mm, addr)) 436 priv->young = true; 437 out: 438 pte_unmap_unlock(pte, ptl); 439 return 0; 440 } 441 442 #ifdef CONFIG_HUGETLB_PAGE 443 static int damon_young_hugetlb_entry(pte_t *pte, unsigned long hmask, 444 unsigned long addr, unsigned long end, 445 struct mm_walk *walk) 446 { 447 struct damon_young_walk_private *priv = walk->private; 448 struct hstate *h = hstate_vma(walk->vma); 449 struct folio *folio; 450 spinlock_t *ptl; 451 pte_t entry; 452 453 ptl = huge_pte_lock(h, walk->mm, pte); 454 entry = huge_ptep_get(walk->mm, addr, pte); 455 if (!pte_present(entry)) 456 goto out; 457 458 folio = pfn_folio(pte_pfn(entry)); 459 folio_get(folio); 460 461 if (pte_young(entry) || !folio_test_idle(folio) || 462 mmu_notifier_test_young(walk->mm, addr)) 463 priv->young = true; 464 465 folio_put(folio); 466 467 out: 468 spin_unlock(ptl); 469 return 0; 470 } 471 #else 472 #define damon_young_hugetlb_entry NULL 473 #endif /* CONFIG_HUGETLB_PAGE */ 474 475 static bool damon_va_young(struct mm_struct *mm, unsigned long addr) 476 { 477 struct damon_young_walk_private arg = { 478 .young = false, 479 }; 480 481 struct mm_walk_ops damon_young_ops = { 482 .pmd_entry = damon_young_pmd_entry, 483 .hugetlb_entry = damon_young_hugetlb_entry, 484 }; 485 486 damon_va_walk_page_range(mm, addr, addr + 1, &damon_young_ops, &arg); 487 return arg.young; 488 } 489 490 /* 491 * Check whether the region was accessed after the last preparation 492 * 493 * mm 'mm_struct' for the given virtual address space 494 * r the region to be checked 495 */ 496 static void __damon_va_check_access(struct mm_struct *mm, 497 struct damon_region *r) 498 { 499 bool accessed; 500 501 if (!mm) { 502 damon_update_region_access_rate(r, false); 503 return; 504 } 505 506 accessed = damon_va_young(mm, r->sampling_addr); 507 damon_update_region_access_rate(r, accessed); 508 } 509 510 static unsigned int damon_va_check_accesses(struct damon_ctx *ctx) 511 { 512 struct damon_target *t; 513 struct mm_struct *mm; 514 struct damon_region *r; 515 unsigned int max_nr_accesses = 0; 516 517 damon_for_each_target(t, ctx) { 518 mm = damon_get_mm(t); 519 damon_for_each_region(r, t) { 520 __damon_va_check_access(mm, r); 521 max_nr_accesses = max(r->nr_accesses, max_nr_accesses); 522 } 523 if (mm) 524 mmput(mm); 525 } 526 527 return max_nr_accesses; 528 } 529 530 static bool damos_va_filter_young_match(struct damos_filter *filter, 531 struct folio *folio, struct vm_area_struct *vma, 532 unsigned long addr, pte_t *ptep, pmd_t *pmdp) 533 { 534 bool young = false; 535 536 if (ptep) 537 young = pte_young(ptep_get(ptep)); 538 else if (pmdp) 539 young = pmd_young(pmdp_get(pmdp)); 540 541 young = young || !folio_test_idle(folio) || 542 mmu_notifier_test_young(vma->vm_mm, addr); 543 544 if (young && ptep) 545 damon_ptep_mkold(ptep, vma, addr); 546 else if (young && pmdp) 547 damon_pmdp_mkold(pmdp, vma, addr); 548 549 return young == filter->matching; 550 } 551 552 static bool damos_va_filter_out(struct damos *scheme, struct folio *folio, 553 struct vm_area_struct *vma, unsigned long addr, 554 pte_t *ptep, pmd_t *pmdp) 555 { 556 struct damos_filter *filter; 557 bool matched; 558 559 if (scheme->core_filters_allowed) 560 return false; 561 562 damos_for_each_ops_filter(filter, scheme) { 563 /* 564 * damos_folio_filter_match checks the young filter by doing an 565 * rmap on the folio to find its page table. However, being the 566 * vaddr scheme, we have direct access to the page tables, so 567 * use that instead. 568 */ 569 if (filter->type == DAMOS_FILTER_TYPE_YOUNG) 570 matched = damos_va_filter_young_match(filter, folio, 571 vma, addr, ptep, pmdp); 572 else 573 matched = damos_folio_filter_match(filter, folio); 574 575 if (matched) 576 return !filter->allow; 577 } 578 return scheme->ops_filters_default_reject; 579 } 580 581 struct damos_va_migrate_private { 582 struct list_head *migration_lists; 583 struct damos *scheme; 584 }; 585 586 /* 587 * Place the given folio in the migration_list corresponding to where the folio 588 * should be migrated. 589 * 590 * The algorithm used here is similar to weighted_interleave_nid() 591 */ 592 static void damos_va_migrate_dests_add(struct folio *folio, 593 struct vm_area_struct *vma, unsigned long addr, 594 struct damos_migrate_dests *dests, 595 struct list_head *migration_lists) 596 { 597 pgoff_t ilx; 598 int order; 599 unsigned int target; 600 unsigned int weight_total = 0; 601 int i; 602 603 /* 604 * If dests is empty, there is only one migration list corresponding 605 * to s->target_nid. 606 */ 607 if (!dests->nr_dests) { 608 i = 0; 609 goto isolate; 610 } 611 612 order = folio_order(folio); 613 ilx = vma_start_pgoff(vma) >> order; 614 ilx += linear_page_delta(vma, addr) >> order; 615 616 for (i = 0; i < dests->nr_dests; i++) 617 weight_total += dests->weight_arr[i]; 618 619 /* If the total weights are somehow 0, don't migrate at all */ 620 if (!weight_total) 621 return; 622 623 target = ilx % weight_total; 624 for (i = 0; i < dests->nr_dests; i++) { 625 if (target < dests->weight_arr[i]) 626 break; 627 target -= dests->weight_arr[i]; 628 } 629 630 /* If the folio is already in the right node, don't do anything */ 631 if (folio_nid(folio) == dests->node_id_arr[i]) 632 return; 633 634 isolate: 635 if (!folio_isolate_lru(folio)) 636 return; 637 node_stat_add_folio(folio, NR_ISOLATED_ANON + 638 folio_is_file_lru(folio)); 639 list_add(&folio->lru, &migration_lists[i]); 640 } 641 642 static int damos_va_migrate_pmd_entry(pmd_t *pmd, unsigned long addr, 643 unsigned long next, struct mm_walk *walk) 644 { 645 struct damos_va_migrate_private *priv = walk->private; 646 struct list_head *migration_lists = priv->migration_lists; 647 struct damos *s = priv->scheme; 648 struct damos_migrate_dests *dests = &s->migrate_dests; 649 struct folio *folio; 650 spinlock_t *ptl; 651 pte_t *start_pte, *pte, ptent; 652 int nr; 653 654 #ifdef CONFIG_TRANSPARENT_HUGEPAGE 655 ptl = pmd_trans_huge_lock(pmd, walk->vma); 656 if (ptl) { 657 pmd_t pmde = pmdp_get(pmd); 658 659 if (!pmd_present(pmde)) 660 goto huge_out; 661 folio = vm_normal_folio_pmd(walk->vma, addr, pmde); 662 if (!folio) 663 goto huge_out; 664 if (damos_va_filter_out(s, folio, walk->vma, addr, NULL, pmd)) 665 goto huge_out; 666 damos_va_migrate_dests_add(folio, walk->vma, addr, dests, 667 migration_lists); 668 huge_out: 669 spin_unlock(ptl); 670 return 0; 671 } 672 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ 673 674 start_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); 675 if (!pte) 676 return 0; 677 678 for (; addr < next; pte += nr, addr += nr * PAGE_SIZE) { 679 nr = 1; 680 ptent = ptep_get(pte); 681 682 if (pte_none(ptent) || !pte_present(ptent)) 683 continue; 684 folio = vm_normal_folio(walk->vma, addr, ptent); 685 if (!folio) 686 continue; 687 if (damos_va_filter_out(s, folio, walk->vma, addr, pte, NULL)) 688 continue; 689 damos_va_migrate_dests_add(folio, walk->vma, addr, dests, 690 migration_lists); 691 nr = folio_nr_pages(folio); 692 } 693 pte_unmap_unlock(start_pte, ptl); 694 return 0; 695 } 696 697 /* 698 * Functions for the target validity check and cleanup 699 */ 700 701 static bool damon_va_target_valid(struct damon_target *t) 702 { 703 struct task_struct *task; 704 705 task = damon_get_task_struct(t); 706 if (task) { 707 put_task_struct(task); 708 return true; 709 } 710 711 return false; 712 } 713 714 static void damon_va_cleanup_target(struct damon_target *t) 715 { 716 put_pid(t->pid); 717 } 718 719 #ifndef CONFIG_ADVISE_SYSCALLS 720 static unsigned long damos_madvise(struct damon_target *target, 721 struct damon_region *r, int behavior) 722 { 723 return 0; 724 } 725 #else 726 static unsigned long damos_madvise(struct damon_target *target, 727 struct damon_region *r, int behavior) 728 { 729 struct mm_struct *mm; 730 unsigned long start = PAGE_ALIGN(r->ar.start); 731 unsigned long len = PAGE_ALIGN(damon_sz_region(r)); 732 unsigned long applied; 733 734 mm = damon_get_mm(target); 735 if (!mm) 736 return 0; 737 738 applied = do_madvise(mm, start, len, behavior) ? 0 : len; 739 mmput(mm); 740 741 return applied; 742 } 743 #endif /* CONFIG_ADVISE_SYSCALLS */ 744 745 static unsigned long damos_va_migrate(struct damon_target *target, 746 struct damon_region *r, struct damos *s, 747 unsigned long *sz_filter_passed) 748 { 749 LIST_HEAD(folio_list); 750 struct damos_va_migrate_private priv; 751 struct mm_struct *mm; 752 int nr_dests; 753 int nid; 754 bool use_target_nid; 755 unsigned long applied = 0; 756 struct damos_migrate_dests *dests = &s->migrate_dests; 757 struct mm_walk_ops walk_ops = { 758 .pmd_entry = damos_va_migrate_pmd_entry, 759 .pte_entry = NULL, 760 }; 761 762 use_target_nid = dests->nr_dests == 0; 763 nr_dests = use_target_nid ? 1 : dests->nr_dests; 764 priv.scheme = s; 765 priv.migration_lists = kmalloc_objs(*priv.migration_lists, nr_dests); 766 if (!priv.migration_lists) 767 return 0; 768 769 for (int i = 0; i < nr_dests; i++) 770 INIT_LIST_HEAD(&priv.migration_lists[i]); 771 772 773 mm = damon_get_mm(target); 774 if (!mm) 775 goto free_lists; 776 777 damon_va_walk_page_range(mm, r->ar.start, r->ar.end, &walk_ops, &priv); 778 mmput(mm); 779 780 for (int i = 0; i < nr_dests; i++) { 781 nid = use_target_nid ? s->target_nid : dests->node_id_arr[i]; 782 applied += damon_migrate_pages(&priv.migration_lists[i], nid); 783 cond_resched(); 784 } 785 786 free_lists: 787 kfree(priv.migration_lists); 788 return applied * PAGE_SIZE; 789 } 790 791 struct damos_va_stat_private { 792 struct damos *scheme; 793 unsigned long *sz_filter_passed; 794 }; 795 796 static inline bool damos_va_invalid_folio(struct folio *folio, 797 struct damos *s) 798 { 799 return !folio || folio == s->last_applied; 800 } 801 802 static int damos_va_stat_pmd_entry(pmd_t *pmd, unsigned long addr, 803 unsigned long next, struct mm_walk *walk) 804 { 805 struct damos_va_stat_private *priv = walk->private; 806 struct damos *s = priv->scheme; 807 unsigned long *sz_filter_passed = priv->sz_filter_passed; 808 struct vm_area_struct *vma = walk->vma; 809 struct folio *folio; 810 spinlock_t *ptl; 811 pte_t *start_pte, *pte, ptent; 812 int nr; 813 814 #ifdef CONFIG_TRANSPARENT_HUGEPAGE 815 ptl = pmd_trans_huge_lock(pmd, vma); 816 if (ptl) { 817 pmd_t pmde = pmdp_get(pmd); 818 819 if (!pmd_present(pmde)) 820 goto huge_unlock; 821 822 folio = vm_normal_folio_pmd(vma, addr, pmde); 823 824 if (damos_va_invalid_folio(folio, s)) 825 goto huge_unlock; 826 827 if (!damos_va_filter_out(s, folio, vma, addr, NULL, pmd)) 828 *sz_filter_passed += folio_size(folio); 829 s->last_applied = folio; 830 831 huge_unlock: 832 spin_unlock(ptl); 833 return 0; 834 } 835 #endif 836 start_pte = pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); 837 if (!start_pte) 838 return 0; 839 840 for (; addr < next; pte += nr, addr += nr * PAGE_SIZE) { 841 nr = 1; 842 ptent = ptep_get(pte); 843 844 if (pte_none(ptent) || !pte_present(ptent)) 845 continue; 846 847 folio = vm_normal_folio(vma, addr, ptent); 848 849 if (damos_va_invalid_folio(folio, s)) 850 continue; 851 852 if (!damos_va_filter_out(s, folio, vma, addr, pte, NULL)) 853 *sz_filter_passed += folio_size(folio); 854 nr = folio_nr_pages(folio); 855 s->last_applied = folio; 856 } 857 pte_unmap_unlock(start_pte, ptl); 858 return 0; 859 } 860 861 static unsigned long damos_va_stat(struct damon_target *target, 862 struct damon_region *r, struct damos *s, 863 unsigned long *sz_filter_passed) 864 { 865 struct damos_va_stat_private priv; 866 struct mm_struct *mm; 867 struct mm_walk_ops walk_ops = { 868 .pmd_entry = damos_va_stat_pmd_entry, 869 }; 870 871 priv.scheme = s; 872 priv.sz_filter_passed = sz_filter_passed; 873 874 if (!damos_ops_has_filter(s)) 875 return 0; 876 877 mm = damon_get_mm(target); 878 if (!mm) 879 return 0; 880 881 damon_va_walk_page_range(mm, r->ar.start, r->ar.end, &walk_ops, &priv); 882 mmput(mm); 883 return 0; 884 } 885 886 static unsigned long damon_va_apply_scheme(struct damon_ctx *ctx, 887 struct damon_target *t, struct damon_region *r, 888 struct damos *scheme, unsigned long *sz_filter_passed) 889 { 890 int madv_action; 891 892 switch (scheme->action) { 893 case DAMOS_WILLNEED: 894 madv_action = MADV_WILLNEED; 895 break; 896 case DAMOS_COLD: 897 madv_action = MADV_COLD; 898 break; 899 case DAMOS_PAGEOUT: 900 madv_action = MADV_PAGEOUT; 901 break; 902 case DAMOS_HUGEPAGE: 903 madv_action = MADV_HUGEPAGE; 904 break; 905 case DAMOS_NOHUGEPAGE: 906 madv_action = MADV_NOHUGEPAGE; 907 break; 908 case DAMOS_COLLAPSE: 909 madv_action = MADV_COLLAPSE; 910 break; 911 case DAMOS_MIGRATE_HOT: 912 case DAMOS_MIGRATE_COLD: 913 return damos_va_migrate(t, r, scheme, sz_filter_passed); 914 case DAMOS_STAT: 915 return damos_va_stat(t, r, scheme, sz_filter_passed); 916 default: 917 /* 918 * DAMOS actions that are not yet supported by 'vaddr'. 919 */ 920 return 0; 921 } 922 923 return damos_madvise(t, r, madv_action); 924 } 925 926 static int damon_va_scheme_score(struct damon_ctx *context, 927 struct damon_region *r, struct damos *scheme) 928 { 929 930 switch (scheme->action) { 931 case DAMOS_PAGEOUT: 932 return damon_cold_score(context, r, scheme); 933 case DAMOS_MIGRATE_HOT: 934 return damon_hot_score(context, r, scheme); 935 case DAMOS_MIGRATE_COLD: 936 return damon_cold_score(context, r, scheme); 937 default: 938 break; 939 } 940 941 return DAMOS_MAX_SCORE; 942 } 943 944 static int __init damon_va_initcall(void) 945 { 946 struct damon_operations ops = { 947 .id = DAMON_OPS_VADDR, 948 .init = damon_va_init, 949 .update = damon_va_update, 950 .prepare_access_checks = damon_va_prepare_access_checks, 951 .check_accesses = damon_va_check_accesses, 952 .target_valid = damon_va_target_valid, 953 .cleanup_target = damon_va_cleanup_target, 954 .apply_scheme = damon_va_apply_scheme, 955 .get_scheme_score = damon_va_scheme_score, 956 }; 957 /* ops for fixed virtual address ranges */ 958 struct damon_operations ops_fvaddr = ops; 959 int err; 960 961 /* Don't set the monitoring target regions for the entire mapping */ 962 ops_fvaddr.id = DAMON_OPS_FVADDR; 963 ops_fvaddr.init = NULL; 964 ops_fvaddr.update = NULL; 965 966 err = damon_register_ops(&ops); 967 if (err) 968 return err; 969 return damon_register_ops(&ops_fvaddr); 970 } 971 972 subsys_initcall(damon_va_initcall); 973 974 #include "tests/vaddr-kunit.h" 975