1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 2bbeae5b0SPeter Zijlstra #ifndef PAGE_FLAGS_LAYOUT_H 3bbeae5b0SPeter Zijlstra #define PAGE_FLAGS_LAYOUT_H 4bbeae5b0SPeter Zijlstra 5bbeae5b0SPeter Zijlstra #include <linux/numa.h> 6bbeae5b0SPeter Zijlstra #include <generated/bounds.h> 7bbeae5b0SPeter Zijlstra 8bbeae5b0SPeter Zijlstra /* 9bbeae5b0SPeter Zijlstra * When a memory allocation must conform to specific limitations (such 10bbeae5b0SPeter Zijlstra * as being suitable for DMA) the caller will pass in hints to the 11bbeae5b0SPeter Zijlstra * allocator in the gfp_mask, in the zone modifier bits. These bits 12bbeae5b0SPeter Zijlstra * are used to select a priority ordered list of memory zones which 13bbeae5b0SPeter Zijlstra * match the requested limits. See gfp_zone() in include/linux/gfp.h 14bbeae5b0SPeter Zijlstra */ 15bbeae5b0SPeter Zijlstra #if MAX_NR_ZONES < 2 16bbeae5b0SPeter Zijlstra #define ZONES_SHIFT 0 17bbeae5b0SPeter Zijlstra #elif MAX_NR_ZONES <= 2 18bbeae5b0SPeter Zijlstra #define ZONES_SHIFT 1 19bbeae5b0SPeter Zijlstra #elif MAX_NR_ZONES <= 4 20bbeae5b0SPeter Zijlstra #define ZONES_SHIFT 2 21b11a7b94SDan Williams #elif MAX_NR_ZONES <= 8 22b11a7b94SDan Williams #define ZONES_SHIFT 3 23bbeae5b0SPeter Zijlstra #else 241587db62SYu Zhao #error ZONES_SHIFT "Too many zones configured" 25bbeae5b0SPeter Zijlstra #endif 26bbeae5b0SPeter Zijlstra 271587db62SYu Zhao #define ZONES_WIDTH ZONES_SHIFT 281587db62SYu Zhao 29bbeae5b0SPeter Zijlstra #ifdef CONFIG_SPARSEMEM 30bbeae5b0SPeter Zijlstra #include <asm/sparsemem.h> 31bbeae5b0SPeter Zijlstra #define SECTIONS_SHIFT (MAX_PHYSMEM_BITS - SECTION_SIZE_BITS) 321587db62SYu Zhao #else 331587db62SYu Zhao #define SECTIONS_SHIFT 0 341587db62SYu Zhao #endif 35bbeae5b0SPeter Zijlstra 36ee38d94aSArnd Bergmann #ifndef BUILD_VDSO32_64 37bbeae5b0SPeter Zijlstra /* 38bbeae5b0SPeter Zijlstra * page->flags layout: 39bbeae5b0SPeter Zijlstra * 4075980e97SPeter Zijlstra * There are five possibilities for how page->flags get laid out. The first 4175980e97SPeter Zijlstra * pair is for the normal case without sparsemem. The second pair is for 4275980e97SPeter Zijlstra * sparsemem when there is plenty of space for node and section information. 4375980e97SPeter Zijlstra * The last is when there is insufficient space in page->flags and a separate 4475980e97SPeter Zijlstra * lookup is necessary. 45bbeae5b0SPeter Zijlstra * 46bbeae5b0SPeter Zijlstra * No sparsemem or sparsemem vmemmap: | NODE | ZONE | ... | FLAGS | 4790572890SPeter Zijlstra * " plus space for last_cpupid: | NODE | ZONE | LAST_CPUPID ... | FLAGS | 48bbeae5b0SPeter Zijlstra * classic sparse with space for node:| SECTION | NODE | ZONE | ... | FLAGS | 4990572890SPeter Zijlstra * " plus space for last_cpupid: | SECTION | NODE | ZONE | LAST_CPUPID ... | FLAGS | 50bbeae5b0SPeter Zijlstra * classic sparse no space for node: | SECTION | ZONE | ... | FLAGS | 51bbeae5b0SPeter Zijlstra */ 52bbeae5b0SPeter Zijlstra #if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP) 53bbeae5b0SPeter Zijlstra #define SECTIONS_WIDTH SECTIONS_SHIFT 54bbeae5b0SPeter Zijlstra #else 55bbeae5b0SPeter Zijlstra #define SECTIONS_WIDTH 0 56bbeae5b0SPeter Zijlstra #endif 57bbeae5b0SPeter Zijlstra 58ec1c86b2SYu Zhao #if ZONES_WIDTH + LRU_GEN_WIDTH + SECTIONS_WIDTH + NODES_SHIFT \ 59ec1c86b2SYu Zhao <= BITS_PER_LONG - NR_PAGEFLAGS 60bbeae5b0SPeter Zijlstra #define NODES_WIDTH NODES_SHIFT 611587db62SYu Zhao #elif defined(CONFIG_SPARSEMEM_VMEMMAP) 62bbeae5b0SPeter Zijlstra #error "Vmemmap: No space for nodes field in page flags" 631587db62SYu Zhao #else 64bbeae5b0SPeter Zijlstra #define NODES_WIDTH 0 65bbeae5b0SPeter Zijlstra #endif 66bbeae5b0SPeter Zijlstra 671587db62SYu Zhao /* 681587db62SYu Zhao * Note that this #define MUST have a value so that it can be tested with 691587db62SYu Zhao * the IS_ENABLED() macro. 701587db62SYu Zhao */ 711587db62SYu Zhao #if NODES_SHIFT != 0 && NODES_WIDTH == 0 721587db62SYu Zhao #define NODE_NOT_IN_PAGE_FLAGS 1 731587db62SYu Zhao #endif 741587db62SYu Zhao 751587db62SYu Zhao #if defined(CONFIG_KASAN_SW_TAGS) || defined(CONFIG_KASAN_HW_TAGS) 761587db62SYu Zhao #define KASAN_TAG_WIDTH 8 771587db62SYu Zhao #else 781587db62SYu Zhao #define KASAN_TAG_WIDTH 0 791587db62SYu Zhao #endif 801587db62SYu Zhao 8175980e97SPeter Zijlstra #ifdef CONFIG_NUMA_BALANCING 82b795854bSMel Gorman #define LAST__PID_SHIFT 8 83b795854bSMel Gorman #define LAST__PID_MASK ((1 << LAST__PID_SHIFT)-1) 84b795854bSMel Gorman 8590572890SPeter Zijlstra #define LAST__CPU_SHIFT NR_CPUS_BITS 8690572890SPeter Zijlstra #define LAST__CPU_MASK ((1 << LAST__CPU_SHIFT)-1) 87b795854bSMel Gorman 8890572890SPeter Zijlstra #define LAST_CPUPID_SHIFT (LAST__PID_SHIFT+LAST__CPU_SHIFT) 8975980e97SPeter Zijlstra #else 9090572890SPeter Zijlstra #define LAST_CPUPID_SHIFT 0 9175980e97SPeter Zijlstra #endif 9275980e97SPeter Zijlstra 93ec1c86b2SYu Zhao #if ZONES_WIDTH + LRU_GEN_WIDTH + SECTIONS_WIDTH + NODES_WIDTH + \ 94ec1c86b2SYu Zhao KASAN_TAG_WIDTH + LAST_CPUPID_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS 9590572890SPeter Zijlstra #define LAST_CPUPID_WIDTH LAST_CPUPID_SHIFT 9675980e97SPeter Zijlstra #else 9790572890SPeter Zijlstra #define LAST_CPUPID_WIDTH 0 9875980e97SPeter Zijlstra #endif 9975980e97SPeter Zijlstra 1001587db62SYu Zhao #if LAST_CPUPID_SHIFT != 0 && LAST_CPUPID_WIDTH == 0 1011587db62SYu Zhao #define LAST_CPUPID_NOT_IN_PAGE_FLAGS 1021587db62SYu Zhao #endif 1031587db62SYu Zhao 104ec1c86b2SYu Zhao #if ZONES_WIDTH + LRU_GEN_WIDTH + SECTIONS_WIDTH + NODES_WIDTH + \ 105ec1c86b2SYu Zhao KASAN_TAG_WIDTH + LAST_CPUPID_WIDTH > BITS_PER_LONG - NR_PAGEFLAGS 106ee38d94aSArnd Bergmann #error "Not enough bits in page flags" 1072813b9c0SAndrey Konovalov #endif 1082813b9c0SAndrey Konovalov 109ac35a490SYu Zhao /* see the comment on MAX_NR_TIERS */ 110ac35a490SYu Zhao #define LRU_REFS_WIDTH min(__LRU_REFS_WIDTH, BITS_PER_LONG - NR_PAGEFLAGS - \ 111ac35a490SYu Zhao ZONES_WIDTH - LRU_GEN_WIDTH - SECTIONS_WIDTH - \ 112ac35a490SYu Zhao NODES_WIDTH - KASAN_TAG_WIDTH - LAST_CPUPID_WIDTH) 113ec1c86b2SYu Zhao 114*4835f747SSuren Baghdasaryan #define NR_NON_PAGEFLAG_BITS (SECTIONS_WIDTH + NODES_WIDTH + ZONES_WIDTH + \ 115*4835f747SSuren Baghdasaryan LAST_CPUPID_SHIFT + KASAN_TAG_WIDTH + \ 116*4835f747SSuren Baghdasaryan LRU_GEN_WIDTH + LRU_REFS_WIDTH) 117*4835f747SSuren Baghdasaryan 118*4835f747SSuren Baghdasaryan #define NR_UNUSED_PAGEFLAG_BITS (BITS_PER_LONG - \ 119*4835f747SSuren Baghdasaryan (NR_NON_PAGEFLAG_BITS + NR_PAGEFLAGS)) 120*4835f747SSuren Baghdasaryan 121ee38d94aSArnd Bergmann #endif 122bbeae5b0SPeter Zijlstra #endif /* _LINUX_PAGE_FLAGS_LAYOUT */ 123