diff options
-rw-r--r-- | include/linux/kernel-page-flags.h | 1 | ||||
-rw-r--r-- | tools/vm/page-types.c | 32 |
2 files changed, 21 insertions, 12 deletions
diff --git a/include/linux/kernel-page-flags.h b/include/linux/kernel-page-flags.h index 546eb6a76934..f65ce09784f1 100644 --- a/include/linux/kernel-page-flags.h +++ b/include/linux/kernel-page-flags.h | |||
@@ -15,5 +15,6 @@ | |||
15 | #define KPF_OWNER_PRIVATE 37 | 15 | #define KPF_OWNER_PRIVATE 37 |
16 | #define KPF_ARCH 38 | 16 | #define KPF_ARCH 38 |
17 | #define KPF_UNCACHED 39 | 17 | #define KPF_UNCACHED 39 |
18 | #define KPF_SOFTDIRTY 40 | ||
18 | 19 | ||
19 | #endif /* LINUX_KERNEL_PAGE_FLAGS_H */ | 20 | #endif /* LINUX_KERNEL_PAGE_FLAGS_H */ |
diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c index 71c9c2511ee7..d5e9d6d185c8 100644 --- a/tools/vm/page-types.c +++ b/tools/vm/page-types.c | |||
@@ -59,12 +59,14 @@ | |||
59 | #define PM_PSHIFT_BITS 6 | 59 | #define PM_PSHIFT_BITS 6 |
60 | #define PM_PSHIFT_OFFSET (PM_STATUS_OFFSET - PM_PSHIFT_BITS) | 60 | #define PM_PSHIFT_OFFSET (PM_STATUS_OFFSET - PM_PSHIFT_BITS) |
61 | #define PM_PSHIFT_MASK (((1LL << PM_PSHIFT_BITS) - 1) << PM_PSHIFT_OFFSET) | 61 | #define PM_PSHIFT_MASK (((1LL << PM_PSHIFT_BITS) - 1) << PM_PSHIFT_OFFSET) |
62 | #define PM_PSHIFT(x) (((u64) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK) | 62 | #define __PM_PSHIFT(x) (((uint64_t) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK) |
63 | #define PM_PFRAME_MASK ((1LL << PM_PSHIFT_OFFSET) - 1) | 63 | #define PM_PFRAME_MASK ((1LL << PM_PSHIFT_OFFSET) - 1) |
64 | #define PM_PFRAME(x) ((x) & PM_PFRAME_MASK) | 64 | #define PM_PFRAME(x) ((x) & PM_PFRAME_MASK) |
65 | 65 | ||
66 | #define __PM_SOFT_DIRTY (1LL) | ||
66 | #define PM_PRESENT PM_STATUS(4LL) | 67 | #define PM_PRESENT PM_STATUS(4LL) |
67 | #define PM_SWAP PM_STATUS(2LL) | 68 | #define PM_SWAP PM_STATUS(2LL) |
69 | #define PM_SOFT_DIRTY __PM_PSHIFT(__PM_SOFT_DIRTY) | ||
68 | 70 | ||
69 | 71 | ||
70 | /* | 72 | /* |
@@ -83,6 +85,7 @@ | |||
83 | #define KPF_OWNER_PRIVATE 37 | 85 | #define KPF_OWNER_PRIVATE 37 |
84 | #define KPF_ARCH 38 | 86 | #define KPF_ARCH 38 |
85 | #define KPF_UNCACHED 39 | 87 | #define KPF_UNCACHED 39 |
88 | #define KPF_SOFTDIRTY 40 | ||
86 | 89 | ||
87 | /* [48-] take some arbitrary free slots for expanding overloaded flags | 90 | /* [48-] take some arbitrary free slots for expanding overloaded flags |
88 | * not part of kernel API | 91 | * not part of kernel API |
@@ -132,6 +135,7 @@ static const char * const page_flag_names[] = { | |||
132 | [KPF_OWNER_PRIVATE] = "O:owner_private", | 135 | [KPF_OWNER_PRIVATE] = "O:owner_private", |
133 | [KPF_ARCH] = "h:arch", | 136 | [KPF_ARCH] = "h:arch", |
134 | [KPF_UNCACHED] = "c:uncached", | 137 | [KPF_UNCACHED] = "c:uncached", |
138 | [KPF_SOFTDIRTY] = "f:softdirty", | ||
135 | 139 | ||
136 | [KPF_READAHEAD] = "I:readahead", | 140 | [KPF_READAHEAD] = "I:readahead", |
137 | [KPF_SLOB_FREE] = "P:slob_free", | 141 | [KPF_SLOB_FREE] = "P:slob_free", |
@@ -417,7 +421,7 @@ static int bit_mask_ok(uint64_t flags) | |||
417 | return 1; | 421 | return 1; |
418 | } | 422 | } |
419 | 423 | ||
420 | static uint64_t expand_overloaded_flags(uint64_t flags) | 424 | static uint64_t expand_overloaded_flags(uint64_t flags, uint64_t pme) |
421 | { | 425 | { |
422 | /* SLOB/SLUB overload several page flags */ | 426 | /* SLOB/SLUB overload several page flags */ |
423 | if (flags & BIT(SLAB)) { | 427 | if (flags & BIT(SLAB)) { |
@@ -433,6 +437,9 @@ static uint64_t expand_overloaded_flags(uint64_t flags) | |||
433 | if ((flags & (BIT(RECLAIM) | BIT(WRITEBACK))) == BIT(RECLAIM)) | 437 | if ((flags & (BIT(RECLAIM) | BIT(WRITEBACK))) == BIT(RECLAIM)) |
434 | flags ^= BIT(RECLAIM) | BIT(READAHEAD); | 438 | flags ^= BIT(RECLAIM) | BIT(READAHEAD); |
435 | 439 | ||
440 | if (pme & PM_SOFT_DIRTY) | ||
441 | flags |= BIT(SOFTDIRTY); | ||
442 | |||
436 | return flags; | 443 | return flags; |
437 | } | 444 | } |
438 | 445 | ||
@@ -448,11 +455,11 @@ static uint64_t well_known_flags(uint64_t flags) | |||
448 | return flags; | 455 | return flags; |
449 | } | 456 | } |
450 | 457 | ||
451 | static uint64_t kpageflags_flags(uint64_t flags) | 458 | static uint64_t kpageflags_flags(uint64_t flags, uint64_t pme) |
452 | { | 459 | { |
453 | flags = expand_overloaded_flags(flags); | 460 | if (opt_raw) |
454 | 461 | flags = expand_overloaded_flags(flags, pme); | |
455 | if (!opt_raw) | 462 | else |
456 | flags = well_known_flags(flags); | 463 | flags = well_known_flags(flags); |
457 | 464 | ||
458 | return flags; | 465 | return flags; |
@@ -545,9 +552,9 @@ static size_t hash_slot(uint64_t flags) | |||
545 | } | 552 | } |
546 | 553 | ||
547 | static void add_page(unsigned long voffset, | 554 | static void add_page(unsigned long voffset, |
548 | unsigned long offset, uint64_t flags) | 555 | unsigned long offset, uint64_t flags, uint64_t pme) |
549 | { | 556 | { |
550 | flags = kpageflags_flags(flags); | 557 | flags = kpageflags_flags(flags, pme); |
551 | 558 | ||
552 | if (!bit_mask_ok(flags)) | 559 | if (!bit_mask_ok(flags)) |
553 | return; | 560 | return; |
@@ -569,7 +576,8 @@ static void add_page(unsigned long voffset, | |||
569 | #define KPAGEFLAGS_BATCH (64 << 10) /* 64k pages */ | 576 | #define KPAGEFLAGS_BATCH (64 << 10) /* 64k pages */ |
570 | static void walk_pfn(unsigned long voffset, | 577 | static void walk_pfn(unsigned long voffset, |
571 | unsigned long index, | 578 | unsigned long index, |
572 | unsigned long count) | 579 | unsigned long count, |
580 | uint64_t pme) | ||
573 | { | 581 | { |
574 | uint64_t buf[KPAGEFLAGS_BATCH]; | 582 | uint64_t buf[KPAGEFLAGS_BATCH]; |
575 | unsigned long batch; | 583 | unsigned long batch; |
@@ -583,7 +591,7 @@ static void walk_pfn(unsigned long voffset, | |||
583 | break; | 591 | break; |
584 | 592 | ||
585 | for (i = 0; i < pages; i++) | 593 | for (i = 0; i < pages; i++) |
586 | add_page(voffset + i, index + i, buf[i]); | 594 | add_page(voffset + i, index + i, buf[i], pme); |
587 | 595 | ||
588 | index += pages; | 596 | index += pages; |
589 | count -= pages; | 597 | count -= pages; |
@@ -608,7 +616,7 @@ static void walk_vma(unsigned long index, unsigned long count) | |||
608 | for (i = 0; i < pages; i++) { | 616 | for (i = 0; i < pages; i++) { |
609 | pfn = pagemap_pfn(buf[i]); | 617 | pfn = pagemap_pfn(buf[i]); |
610 | if (pfn) | 618 | if (pfn) |
611 | walk_pfn(index + i, pfn, 1); | 619 | walk_pfn(index + i, pfn, 1, buf[i]); |
612 | } | 620 | } |
613 | 621 | ||
614 | index += pages; | 622 | index += pages; |
@@ -659,7 +667,7 @@ static void walk_addr_ranges(void) | |||
659 | 667 | ||
660 | for (i = 0; i < nr_addr_ranges; i++) | 668 | for (i = 0; i < nr_addr_ranges; i++) |
661 | if (!opt_pid) | 669 | if (!opt_pid) |
662 | walk_pfn(0, opt_offset[i], opt_size[i]); | 670 | walk_pfn(0, opt_offset[i], opt_size[i], 0); |
663 | else | 671 | else |
664 | walk_task(opt_offset[i], opt_size[i]); | 672 | walk_task(opt_offset[i], opt_size[i]); |
665 | 673 | ||