| .. | .. |
|---|
| 17 | 17 | /* |
|---|
| 18 | 18 | * Various page->flags bits: |
|---|
| 19 | 19 | * |
|---|
| 20 | | - * PG_reserved is set for special pages, which can never be swapped out. Some |
|---|
| 21 | | - * of them might not even exist... |
|---|
| 20 | + * PG_reserved is set for special pages. The "struct page" of such a page |
|---|
| 21 | + * should in general not be touched (e.g. set dirty) except by its owner. |
|---|
| 22 | + * Pages marked as PG_reserved include: |
|---|
| 23 | + * - Pages part of the kernel image (including vDSO) and similar (e.g. BIOS, |
|---|
| 24 | + * initrd, HW tables) |
|---|
| 25 | + * - Pages reserved or allocated early during boot (before the page allocator |
|---|
| 26 | + * was initialized). This includes (depending on the architecture) the |
|---|
| 27 | + * initial vmemmap, initial page tables, crashkernel, elfcorehdr, and much |
|---|
| 28 | + * much more. Once (if ever) freed, PG_reserved is cleared and they will |
|---|
| 29 | + * be given to the page allocator. |
|---|
| 30 | + * - Pages falling into physical memory gaps - not IORESOURCE_SYSRAM. Trying |
|---|
| 31 | + * to read/write these pages might end badly. Don't touch! |
|---|
| 32 | + * - The zero page(s) |
|---|
| 33 | + * - Pages not added to the page allocator when onlining a section because |
|---|
| 34 | + * they were excluded via the online_page_callback() or because they are |
|---|
| 35 | + * PG_hwpoison. |
|---|
| 36 | + * - Pages allocated in the context of kexec/kdump (loaded kernel image, |
|---|
| 37 | + * control pages, vmcoreinfo) |
|---|
| 38 | + * - MMIO/DMA pages. Some architectures don't allow to ioremap pages that are |
|---|
| 39 | + * not marked PG_reserved (as they might be in use by somebody else who does |
|---|
| 40 | + * not respect the caching strategy). |
|---|
| 41 | + * - Pages part of an offline section (struct pages of offline sections should |
|---|
| 42 | + * not be trusted as they will be initialized when first onlined). |
|---|
| 43 | + * - MCA pages on ia64 |
|---|
| 44 | + * - Pages holding CPU notes for POWER Firmware Assisted Dump |
|---|
| 45 | + * - Device memory (e.g. PMEM, DAX, HMM) |
|---|
| 46 | + * Some PG_reserved pages will be excluded from the hibernation image. |
|---|
| 47 | + * PG_reserved does in general not hinder anybody from dumping or swapping |
|---|
| 48 | + * and is no longer required for remap_pfn_range(). ioremap might require it. |
|---|
| 49 | + * Consequently, PG_reserved for a page mapped into user space can indicate |
|---|
| 50 | + * the zero page, the vDSO, MMIO pages or device memory. |
|---|
| 22 | 51 | * |
|---|
| 23 | 52 | * The PG_private bitflag is set on pagecache pages if they contain filesystem |
|---|
| 24 | 53 | * specific data (which is normally at page->private). It can be used by |
|---|
| .. | .. |
|---|
| 33 | 62 | * |
|---|
| 34 | 63 | * page_waitqueue(page) is a wait queue of all tasks waiting for the page |
|---|
| 35 | 64 | * to become unlocked. |
|---|
| 65 | + * |
|---|
| 66 | + * PG_swapbacked is set when a page uses swap as a backing storage. This are |
|---|
| 67 | + * usually PageAnon or shmem pages but please note that even anonymous pages |
|---|
| 68 | + * might lose their PG_swapbacked flag when they simply can be dropped (e.g. as |
|---|
| 69 | + * a result of MADV_FREE). |
|---|
| 36 | 70 | * |
|---|
| 37 | 71 | * PG_uptodate tells whether the page's contents is valid. When a read |
|---|
| 38 | 72 | * completes, the page becomes uptodate, unless a disk I/O error happened. |
|---|
| .. | .. |
|---|
| 98 | 132 | #ifdef CONFIG_MEMORY_FAILURE |
|---|
| 99 | 133 | PG_hwpoison, /* hardware poisoned page. Don't touch */ |
|---|
| 100 | 134 | #endif |
|---|
| 101 | | -#if defined(CONFIG_IDLE_PAGE_TRACKING) && defined(CONFIG_64BIT) |
|---|
| 135 | +#if defined(CONFIG_PAGE_IDLE_FLAG) && defined(CONFIG_64BIT) |
|---|
| 102 | 136 | PG_young, |
|---|
| 103 | 137 | PG_idle, |
|---|
| 138 | +#endif |
|---|
| 139 | +#ifdef CONFIG_64BIT |
|---|
| 140 | + PG_arch_2, |
|---|
| 141 | +#endif |
|---|
| 142 | +#ifdef CONFIG_KASAN_HW_TAGS |
|---|
| 143 | + PG_skip_kasan_poison, |
|---|
| 104 | 144 | #endif |
|---|
| 105 | 145 | __NR_PAGEFLAGS, |
|---|
| 106 | 146 | |
|---|
| .. | .. |
|---|
| 123 | 163 | PG_savepinned = PG_dirty, |
|---|
| 124 | 164 | /* Has a grant mapping of another (foreign) domain's page. */ |
|---|
| 125 | 165 | PG_foreign = PG_owner_priv_1, |
|---|
| 166 | + /* Remapped by swiotlb-xen. */ |
|---|
| 167 | + PG_xen_remapped = PG_owner_priv_1, |
|---|
| 126 | 168 | |
|---|
| 127 | 169 | /* SLOB */ |
|---|
| 128 | 170 | PG_slob_free = PG_private, |
|---|
| 129 | 171 | |
|---|
| 130 | 172 | /* Compound pages. Stored in first tail page's flags */ |
|---|
| 131 | | - PG_double_map = PG_private_2, |
|---|
| 173 | + PG_double_map = PG_workingset, |
|---|
| 132 | 174 | |
|---|
| 133 | 175 | /* non-lru isolated movable page */ |
|---|
| 134 | 176 | PG_isolated = PG_reclaim, |
|---|
| 177 | + |
|---|
| 178 | + /* Only valid for buddy pages. Used to track pages that are reported */ |
|---|
| 179 | + PG_reported = PG_uptodate, |
|---|
| 135 | 180 | }; |
|---|
| 136 | 181 | |
|---|
| 137 | 182 | #ifndef __GENERATING_BOUNDS_H |
|---|
| .. | .. |
|---|
| 163 | 208 | return page->flags == PAGE_POISON_PATTERN; |
|---|
| 164 | 209 | } |
|---|
| 165 | 210 | |
|---|
| 211 | +#ifdef CONFIG_DEBUG_VM |
|---|
| 212 | +void page_init_poison(struct page *page, size_t size); |
|---|
| 213 | +#else |
|---|
| 214 | +static inline void page_init_poison(struct page *page, size_t size) |
|---|
| 215 | +{ |
|---|
| 216 | +} |
|---|
| 217 | +#endif |
|---|
| 218 | + |
|---|
| 166 | 219 | /* |
|---|
| 167 | 220 | * Page flags policies wrt compound pages |
|---|
| 168 | 221 | * |
|---|
| .. | .. |
|---|
| 185 | 238 | * |
|---|
| 186 | 239 | * PF_NO_COMPOUND: |
|---|
| 187 | 240 | * the page flag is not relevant for compound pages. |
|---|
| 241 | + * |
|---|
| 242 | + * PF_SECOND: |
|---|
| 243 | + * the page flag is stored in the first tail page. |
|---|
| 188 | 244 | */ |
|---|
| 189 | 245 | #define PF_POISONED_CHECK(page) ({ \ |
|---|
| 190 | 246 | VM_BUG_ON_PGFLAGS(PagePoisoned(page), page); \ |
|---|
| .. | .. |
|---|
| 200 | 256 | #define PF_NO_COMPOUND(page, enforce) ({ \ |
|---|
| 201 | 257 | VM_BUG_ON_PGFLAGS(enforce && PageCompound(page), page); \ |
|---|
| 202 | 258 | PF_POISONED_CHECK(page); }) |
|---|
| 259 | +#define PF_SECOND(page, enforce) ({ \ |
|---|
| 260 | + VM_BUG_ON_PGFLAGS(!PageHead(page), page); \ |
|---|
| 261 | + PF_POISONED_CHECK(&page[1]); }) |
|---|
| 203 | 262 | |
|---|
| 204 | 263 | /* |
|---|
| 205 | 264 | * Macros to create function definitions for page flags |
|---|
| .. | .. |
|---|
| 292 | 351 | TESTSCFLAG(Pinned, pinned, PF_NO_COMPOUND) |
|---|
| 293 | 352 | PAGEFLAG(SavePinned, savepinned, PF_NO_COMPOUND); |
|---|
| 294 | 353 | PAGEFLAG(Foreign, foreign, PF_NO_COMPOUND); |
|---|
| 354 | +PAGEFLAG(XenRemapped, xen_remapped, PF_NO_COMPOUND) |
|---|
| 355 | + TESTCLEARFLAG(XenRemapped, xen_remapped, PF_NO_COMPOUND) |
|---|
| 295 | 356 | |
|---|
| 296 | 357 | PAGEFLAG(Reserved, reserved, PF_NO_COMPOUND) |
|---|
| 297 | 358 | __CLEARPAGEFLAG(Reserved, reserved, PF_NO_COMPOUND) |
|---|
| 359 | + __SETPAGEFLAG(Reserved, reserved, PF_NO_COMPOUND) |
|---|
| 298 | 360 | PAGEFLAG(SwapBacked, swapbacked, PF_NO_TAIL) |
|---|
| 299 | 361 | __CLEARPAGEFLAG(SwapBacked, swapbacked, PF_NO_TAIL) |
|---|
| 300 | 362 | __SETPAGEFLAG(SwapBacked, swapbacked, PF_NO_TAIL) |
|---|
| .. | .. |
|---|
| 372 | 434 | PAGEFLAG(HWPoison, hwpoison, PF_ANY) |
|---|
| 373 | 435 | TESTSCFLAG(HWPoison, hwpoison, PF_ANY) |
|---|
| 374 | 436 | #define __PG_HWPOISON (1UL << PG_hwpoison) |
|---|
| 375 | | -extern bool set_hwpoison_free_buddy_page(struct page *page); |
|---|
| 437 | +extern bool take_page_off_buddy(struct page *page); |
|---|
| 376 | 438 | #else |
|---|
| 377 | 439 | PAGEFLAG_FALSE(HWPoison) |
|---|
| 378 | | -static inline bool set_hwpoison_free_buddy_page(struct page *page) |
|---|
| 379 | | -{ |
|---|
| 380 | | - return 0; |
|---|
| 381 | | -} |
|---|
| 382 | 440 | #define __PG_HWPOISON 0 |
|---|
| 383 | 441 | #endif |
|---|
| 384 | 442 | |
|---|
| 385 | | -#if defined(CONFIG_IDLE_PAGE_TRACKING) && defined(CONFIG_64BIT) |
|---|
| 443 | +#if defined(CONFIG_PAGE_IDLE_FLAG) && defined(CONFIG_64BIT) |
|---|
| 386 | 444 | TESTPAGEFLAG(Young, young, PF_ANY) |
|---|
| 387 | 445 | SETPAGEFLAG(Young, young, PF_ANY) |
|---|
| 388 | 446 | TESTCLEARFLAG(Young, young, PF_ANY) |
|---|
| 389 | 447 | PAGEFLAG(Idle, idle, PF_ANY) |
|---|
| 390 | 448 | #endif |
|---|
| 449 | + |
|---|
| 450 | +#ifdef CONFIG_KASAN_HW_TAGS |
|---|
| 451 | +PAGEFLAG(SkipKASanPoison, skip_kasan_poison, PF_HEAD) |
|---|
| 452 | +#else |
|---|
| 453 | +PAGEFLAG_FALSE(SkipKASanPoison) |
|---|
| 454 | +#endif |
|---|
| 455 | + |
|---|
| 456 | +/* |
|---|
| 457 | + * PageReported() is used to track reported free pages within the Buddy |
|---|
| 458 | + * allocator. We can use the non-atomic version of the test and set |
|---|
| 459 | + * operations as both should be shielded with the zone lock to prevent |
|---|
| 460 | + * any possible races on the setting or clearing of the bit. |
|---|
| 461 | + */ |
|---|
| 462 | +__PAGEFLAG(Reported, reported, PF_NO_COMPOUND) |
|---|
| 391 | 463 | |
|---|
| 392 | 464 | /* |
|---|
| 393 | 465 | * On an anonymous page mapped into a user virtual memory area, |
|---|
| .. | .. |
|---|
| 627 | 699 | * |
|---|
| 628 | 700 | * See also __split_huge_pmd_locked() and page_remove_anon_compound_rmap(). |
|---|
| 629 | 701 | */ |
|---|
| 630 | | -static inline int PageDoubleMap(struct page *page) |
|---|
| 631 | | -{ |
|---|
| 632 | | - return PageHead(page) && test_bit(PG_double_map, &page[1].flags); |
|---|
| 633 | | -} |
|---|
| 634 | | - |
|---|
| 635 | | -static inline void SetPageDoubleMap(struct page *page) |
|---|
| 636 | | -{ |
|---|
| 637 | | - VM_BUG_ON_PAGE(!PageHead(page), page); |
|---|
| 638 | | - set_bit(PG_double_map, &page[1].flags); |
|---|
| 639 | | -} |
|---|
| 640 | | - |
|---|
| 641 | | -static inline void ClearPageDoubleMap(struct page *page) |
|---|
| 642 | | -{ |
|---|
| 643 | | - VM_BUG_ON_PAGE(!PageHead(page), page); |
|---|
| 644 | | - clear_bit(PG_double_map, &page[1].flags); |
|---|
| 645 | | -} |
|---|
| 646 | | -static inline int TestSetPageDoubleMap(struct page *page) |
|---|
| 647 | | -{ |
|---|
| 648 | | - VM_BUG_ON_PAGE(!PageHead(page), page); |
|---|
| 649 | | - return test_and_set_bit(PG_double_map, &page[1].flags); |
|---|
| 650 | | -} |
|---|
| 651 | | - |
|---|
| 652 | | -static inline int TestClearPageDoubleMap(struct page *page) |
|---|
| 653 | | -{ |
|---|
| 654 | | - VM_BUG_ON_PAGE(!PageHead(page), page); |
|---|
| 655 | | - return test_and_clear_bit(PG_double_map, &page[1].flags); |
|---|
| 656 | | -} |
|---|
| 657 | | - |
|---|
| 702 | +PAGEFLAG(DoubleMap, double_map, PF_SECOND) |
|---|
| 703 | + TESTSCFLAG(DoubleMap, double_map, PF_SECOND) |
|---|
| 658 | 704 | #else |
|---|
| 659 | 705 | TESTPAGEFLAG_FALSE(TransHuge) |
|---|
| 660 | 706 | TESTPAGEFLAG_FALSE(TransCompound) |
|---|
| 661 | 707 | TESTPAGEFLAG_FALSE(TransCompoundMap) |
|---|
| 662 | 708 | TESTPAGEFLAG_FALSE(TransTail) |
|---|
| 663 | 709 | PAGEFLAG_FALSE(DoubleMap) |
|---|
| 664 | | - TESTSETFLAG_FALSE(DoubleMap) |
|---|
| 665 | | - TESTCLEARFLAG_FALSE(DoubleMap) |
|---|
| 710 | + TESTSCFLAG_FALSE(DoubleMap) |
|---|
| 666 | 711 | #endif |
|---|
| 667 | 712 | |
|---|
| 668 | 713 | /* |
|---|
| .. | .. |
|---|
| 676 | 721 | |
|---|
| 677 | 722 | #define PAGE_TYPE_BASE 0xf0000000 |
|---|
| 678 | 723 | /* Reserve 0x0000007f to catch underflows of page_mapcount */ |
|---|
| 724 | +#define PAGE_MAPCOUNT_RESERVE -128 |
|---|
| 679 | 725 | #define PG_buddy 0x00000080 |
|---|
| 680 | | -#define PG_balloon 0x00000100 |
|---|
| 726 | +#define PG_offline 0x00000100 |
|---|
| 681 | 727 | #define PG_kmemcg 0x00000200 |
|---|
| 682 | 728 | #define PG_table 0x00000400 |
|---|
| 729 | +#define PG_guard 0x00000800 |
|---|
| 683 | 730 | |
|---|
| 684 | 731 | #define PageType(page, flag) \ |
|---|
| 685 | 732 | ((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE) |
|---|
| 733 | + |
|---|
| 734 | +static inline int page_has_type(struct page *page) |
|---|
| 735 | +{ |
|---|
| 736 | + return (int)page->page_type < PAGE_MAPCOUNT_RESERVE; |
|---|
| 737 | +} |
|---|
| 686 | 738 | |
|---|
| 687 | 739 | #define PAGE_TYPE_OPS(uname, lname) \ |
|---|
| 688 | 740 | static __always_inline int Page##uname(struct page *page) \ |
|---|
| .. | .. |
|---|
| 707 | 759 | PAGE_TYPE_OPS(Buddy, buddy) |
|---|
| 708 | 760 | |
|---|
| 709 | 761 | /* |
|---|
| 710 | | - * PageBalloon() is true for pages that are on the balloon page list |
|---|
| 711 | | - * (see mm/balloon_compaction.c). |
|---|
| 762 | + * PageOffline() indicates that the page is logically offline although the |
|---|
| 763 | + * containing section is online. (e.g. inflated in a balloon driver or |
|---|
| 764 | + * not onlined when onlining the section). |
|---|
| 765 | + * The content of these pages is effectively stale. Such pages should not |
|---|
| 766 | + * be touched (read/write/dump/save) except by their owner. |
|---|
| 767 | + * |
|---|
| 768 | + * If a driver wants to allow to offline unmovable PageOffline() pages without |
|---|
| 769 | + * putting them back to the buddy, it can do so via the memory notifier by |
|---|
| 770 | + * decrementing the reference count in MEM_GOING_OFFLINE and incrementing the |
|---|
| 771 | + * reference count in MEM_CANCEL_OFFLINE. When offlining, the PageOffline() |
|---|
| 772 | + * pages (now with a reference count of zero) are treated like free pages, |
|---|
| 773 | + * allowing the containing memory block to get offlined. A driver that |
|---|
| 774 | + * relies on this feature is aware that re-onlining the memory block will |
|---|
| 775 | + * require to re-set the pages PageOffline() and not giving them to the |
|---|
| 776 | + * buddy via online_page_callback_t. |
|---|
| 712 | 777 | */ |
|---|
| 713 | | -PAGE_TYPE_OPS(Balloon, balloon) |
|---|
| 778 | +PAGE_TYPE_OPS(Offline, offline) |
|---|
| 714 | 779 | |
|---|
| 715 | 780 | /* |
|---|
| 716 | 781 | * If kmemcg is enabled, the buddy allocator will set PageKmemcg() on |
|---|
| .. | .. |
|---|
| 723 | 788 | */ |
|---|
| 724 | 789 | PAGE_TYPE_OPS(Table, table) |
|---|
| 725 | 790 | |
|---|
| 791 | +/* |
|---|
| 792 | + * Marks guardpages used with debug_pagealloc. |
|---|
| 793 | + */ |
|---|
| 794 | +PAGE_TYPE_OPS(Guard, guard) |
|---|
| 795 | + |
|---|
| 726 | 796 | extern bool is_free_buddy_page(struct page *page); |
|---|
| 727 | 797 | |
|---|
| 728 | | -__PAGEFLAG(Isolated, isolated, PF_ANY); |
|---|
| 798 | +PAGEFLAG(Isolated, isolated, PF_ANY); |
|---|
| 729 | 799 | |
|---|
| 730 | 800 | /* |
|---|
| 731 | 801 | * If network-based swap is enabled, sl*b must keep track of whether pages |
|---|
| .. | .. |
|---|
| 802 | 872 | #undef PF_ONLY_HEAD |
|---|
| 803 | 873 | #undef PF_NO_TAIL |
|---|
| 804 | 874 | #undef PF_NO_COMPOUND |
|---|
| 875 | +#undef PF_SECOND |
|---|
| 805 | 876 | #endif /* !__GENERATING_BOUNDS_H */ |
|---|
| 806 | 877 | |
|---|
| 807 | 878 | #endif /* PAGE_FLAGS_H */ |
|---|