xref: /OK3568_Linux_fs/kernel/include/linux/page-flags-layout.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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