1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun #ifndef PAGE_FLAGS_LAYOUT_H 3*4882a593Smuzhiyun #define PAGE_FLAGS_LAYOUT_H 4*4882a593Smuzhiyun 5*4882a593Smuzhiyun #include <linux/numa.h> 6*4882a593Smuzhiyun #include <generated/bounds.h> 7*4882a593Smuzhiyun 8*4882a593Smuzhiyun /* 9*4882a593Smuzhiyun * When a memory allocation must conform to specific limitations (such 10*4882a593Smuzhiyun * as being suitable for DMA) the caller will pass in hints to the 11*4882a593Smuzhiyun * allocator in the gfp_mask, in the zone modifier bits. These bits 12*4882a593Smuzhiyun * are used to select a priority ordered list of memory zones which 13*4882a593Smuzhiyun * match the requested limits. See gfp_zone() in include/linux/gfp.h 14*4882a593Smuzhiyun */ 15*4882a593Smuzhiyun #if MAX_NR_ZONES < 2 16*4882a593Smuzhiyun #define ZONES_SHIFT 0 17*4882a593Smuzhiyun #elif MAX_NR_ZONES <= 2 18*4882a593Smuzhiyun #define ZONES_SHIFT 1 19*4882a593Smuzhiyun #elif MAX_NR_ZONES <= 4 20*4882a593Smuzhiyun #define ZONES_SHIFT 2 21*4882a593Smuzhiyun #elif MAX_NR_ZONES <= 8 22*4882a593Smuzhiyun #define ZONES_SHIFT 3 23*4882a593Smuzhiyun #else 24*4882a593Smuzhiyun #error ZONES_SHIFT -- too many zones configured adjust calculation 25*4882a593Smuzhiyun #endif 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun #ifdef CONFIG_SPARSEMEM 28*4882a593Smuzhiyun #include <asm/sparsemem.h> 29*4882a593Smuzhiyun 30*4882a593Smuzhiyun /* SECTION_SHIFT #bits space required to store a section # */ 31*4882a593Smuzhiyun #define SECTIONS_SHIFT (MAX_PHYSMEM_BITS - SECTION_SIZE_BITS) 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun #endif /* CONFIG_SPARSEMEM */ 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun #ifndef BUILD_VDSO32_64 36*4882a593Smuzhiyun /* 37*4882a593Smuzhiyun * page->flags layout: 38*4882a593Smuzhiyun * 39*4882a593Smuzhiyun * There are five possibilities for how page->flags get laid out. The first 40*4882a593Smuzhiyun * pair is for the normal case without sparsemem. The second pair is for 41*4882a593Smuzhiyun * sparsemem when there is plenty of space for node and section information. 42*4882a593Smuzhiyun * The last is when there is insufficient space in page->flags and a separate 43*4882a593Smuzhiyun * lookup is necessary. 44*4882a593Smuzhiyun * 45*4882a593Smuzhiyun * No sparsemem or sparsemem vmemmap: | NODE | ZONE | ... | FLAGS | 46*4882a593Smuzhiyun * " plus space for last_cpupid: | NODE | ZONE | LAST_CPUPID ... | FLAGS | 47*4882a593Smuzhiyun * classic sparse with space for node:| SECTION | NODE | ZONE | ... | FLAGS | 48*4882a593Smuzhiyun * " plus space for last_cpupid: | SECTION | NODE | ZONE | LAST_CPUPID ... | FLAGS | 49*4882a593Smuzhiyun * classic sparse no space for node: | SECTION | ZONE | ... | FLAGS | 50*4882a593Smuzhiyun */ 51*4882a593Smuzhiyun #if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP) 52*4882a593Smuzhiyun #define SECTIONS_WIDTH SECTIONS_SHIFT 53*4882a593Smuzhiyun #else 54*4882a593Smuzhiyun #define SECTIONS_WIDTH 0 55*4882a593Smuzhiyun #endif 56*4882a593Smuzhiyun 57*4882a593Smuzhiyun #define ZONES_WIDTH ZONES_SHIFT 58*4882a593Smuzhiyun 59*4882a593Smuzhiyun #if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS 60*4882a593Smuzhiyun #define NODES_WIDTH NODES_SHIFT 61*4882a593Smuzhiyun #else 62*4882a593Smuzhiyun #ifdef CONFIG_SPARSEMEM_VMEMMAP 63*4882a593Smuzhiyun #error "Vmemmap: No space for nodes field in page flags" 64*4882a593Smuzhiyun #endif 65*4882a593Smuzhiyun #define NODES_WIDTH 0 66*4882a593Smuzhiyun #endif 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun #ifdef CONFIG_NUMA_BALANCING 69*4882a593Smuzhiyun #define LAST__PID_SHIFT 8 70*4882a593Smuzhiyun #define LAST__PID_MASK ((1 << LAST__PID_SHIFT)-1) 71*4882a593Smuzhiyun 72*4882a593Smuzhiyun #define LAST__CPU_SHIFT NR_CPUS_BITS 73*4882a593Smuzhiyun #define LAST__CPU_MASK ((1 << LAST__CPU_SHIFT)-1) 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun #define LAST_CPUPID_SHIFT (LAST__PID_SHIFT+LAST__CPU_SHIFT) 76*4882a593Smuzhiyun #else 77*4882a593Smuzhiyun #define LAST_CPUPID_SHIFT 0 78*4882a593Smuzhiyun #endif 79*4882a593Smuzhiyun 80*4882a593Smuzhiyun #if defined(CONFIG_KASAN_SW_TAGS) || defined(CONFIG_KASAN_HW_TAGS) 81*4882a593Smuzhiyun #define KASAN_TAG_WIDTH 8 82*4882a593Smuzhiyun #else 83*4882a593Smuzhiyun #define KASAN_TAG_WIDTH 0 84*4882a593Smuzhiyun #endif 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun #if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT+LAST_CPUPID_SHIFT+KASAN_TAG_WIDTH \ 87*4882a593Smuzhiyun <= BITS_PER_LONG - NR_PAGEFLAGS 88*4882a593Smuzhiyun #define LAST_CPUPID_WIDTH LAST_CPUPID_SHIFT 89*4882a593Smuzhiyun #else 90*4882a593Smuzhiyun #define LAST_CPUPID_WIDTH 0 91*4882a593Smuzhiyun #endif 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun #if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH+LAST_CPUPID_WIDTH+KASAN_TAG_WIDTH \ 94*4882a593Smuzhiyun > BITS_PER_LONG - NR_PAGEFLAGS 95*4882a593Smuzhiyun #error "Not enough bits in page flags" 96*4882a593Smuzhiyun #endif 97*4882a593Smuzhiyun 98*4882a593Smuzhiyun /* 99*4882a593Smuzhiyun * We are going to use the flags for the page to node mapping if its in 100*4882a593Smuzhiyun * there. This includes the case where there is no node, so it is implicit. 101*4882a593Smuzhiyun * Note that this #define MUST have a value so that it can be tested with 102*4882a593Smuzhiyun * the IS_ENABLED() macro. 103*4882a593Smuzhiyun */ 104*4882a593Smuzhiyun #if !(NODES_WIDTH > 0 || NODES_SHIFT == 0) 105*4882a593Smuzhiyun #define NODE_NOT_IN_PAGE_FLAGS 1 106*4882a593Smuzhiyun #endif 107*4882a593Smuzhiyun 108*4882a593Smuzhiyun #if defined(CONFIG_NUMA_BALANCING) && LAST_CPUPID_WIDTH == 0 109*4882a593Smuzhiyun #define LAST_CPUPID_NOT_IN_PAGE_FLAGS 110*4882a593Smuzhiyun #endif 111*4882a593Smuzhiyun 112*4882a593Smuzhiyun #endif 113*4882a593Smuzhiyun #endif /* _LINUX_PAGE_FLAGS_LAYOUT */ 114