Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef PAGE_FLAGS_LAYOUT_H
0003 #define PAGE_FLAGS_LAYOUT_H
0004 
0005 #include <linux/numa.h>
0006 #include <generated/bounds.h>
0007 
0008 /*
0009  * When a memory allocation must conform to specific limitations (such
0010  * as being suitable for DMA) the caller will pass in hints to the
0011  * allocator in the gfp_mask, in the zone modifier bits.  These bits
0012  * are used to select a priority ordered list of memory zones which
0013  * match the requested limits. See gfp_zone() in include/linux/gfp.h
0014  */
0015 #if MAX_NR_ZONES < 2
0016 #define ZONES_SHIFT 0
0017 #elif MAX_NR_ZONES <= 2
0018 #define ZONES_SHIFT 1
0019 #elif MAX_NR_ZONES <= 4
0020 #define ZONES_SHIFT 2
0021 #elif MAX_NR_ZONES <= 8
0022 #define ZONES_SHIFT 3
0023 #else
0024 #error ZONES_SHIFT "Too many zones configured"
0025 #endif
0026 
0027 #define ZONES_WIDTH     ZONES_SHIFT
0028 
0029 #ifdef CONFIG_SPARSEMEM
0030 #include <asm/sparsemem.h>
0031 #define SECTIONS_SHIFT  (MAX_PHYSMEM_BITS - SECTION_SIZE_BITS)
0032 #else
0033 #define SECTIONS_SHIFT  0
0034 #endif
0035 
0036 #ifndef BUILD_VDSO32_64
0037 /*
0038  * page->flags layout:
0039  *
0040  * There are five possibilities for how page->flags get laid out.  The first
0041  * pair is for the normal case without sparsemem. The second pair is for
0042  * sparsemem when there is plenty of space for node and section information.
0043  * The last is when there is insufficient space in page->flags and a separate
0044  * lookup is necessary.
0045  *
0046  * No sparsemem or sparsemem vmemmap: |       NODE     | ZONE |             ... | FLAGS |
0047  *      " plus space for last_cpupid: |       NODE     | ZONE | LAST_CPUPID ... | FLAGS |
0048  * classic sparse with space for node:| SECTION | NODE | ZONE |             ... | FLAGS |
0049  *      " plus space for last_cpupid: | SECTION | NODE | ZONE | LAST_CPUPID ... | FLAGS |
0050  * classic sparse no space for node:  | SECTION |     ZONE    | ... | FLAGS |
0051  */
0052 #if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
0053 #define SECTIONS_WIDTH      SECTIONS_SHIFT
0054 #else
0055 #define SECTIONS_WIDTH      0
0056 #endif
0057 
0058 #if ZONES_WIDTH + SECTIONS_WIDTH + NODES_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS
0059 #define NODES_WIDTH     NODES_SHIFT
0060 #elif defined(CONFIG_SPARSEMEM_VMEMMAP)
0061 #error "Vmemmap: No space for nodes field in page flags"
0062 #else
0063 #define NODES_WIDTH     0
0064 #endif
0065 
0066 /*
0067  * Note that this #define MUST have a value so that it can be tested with
0068  * the IS_ENABLED() macro.
0069  */
0070 #if NODES_SHIFT != 0 && NODES_WIDTH == 0
0071 #define NODE_NOT_IN_PAGE_FLAGS  1
0072 #endif
0073 
0074 #if defined(CONFIG_KASAN_SW_TAGS) || defined(CONFIG_KASAN_HW_TAGS)
0075 #define KASAN_TAG_WIDTH 8
0076 #else
0077 #define KASAN_TAG_WIDTH 0
0078 #endif
0079 
0080 #ifdef CONFIG_NUMA_BALANCING
0081 #define LAST__PID_SHIFT 8
0082 #define LAST__PID_MASK  ((1 << LAST__PID_SHIFT)-1)
0083 
0084 #define LAST__CPU_SHIFT NR_CPUS_BITS
0085 #define LAST__CPU_MASK  ((1 << LAST__CPU_SHIFT)-1)
0086 
0087 #define LAST_CPUPID_SHIFT (LAST__PID_SHIFT+LAST__CPU_SHIFT)
0088 #else
0089 #define LAST_CPUPID_SHIFT 0
0090 #endif
0091 
0092 #if ZONES_WIDTH + SECTIONS_WIDTH + NODES_WIDTH + KASAN_TAG_WIDTH + LAST_CPUPID_SHIFT \
0093     <= BITS_PER_LONG - NR_PAGEFLAGS
0094 #define LAST_CPUPID_WIDTH LAST_CPUPID_SHIFT
0095 #else
0096 #define LAST_CPUPID_WIDTH 0
0097 #endif
0098 
0099 #if LAST_CPUPID_SHIFT != 0 && LAST_CPUPID_WIDTH == 0
0100 #define LAST_CPUPID_NOT_IN_PAGE_FLAGS
0101 #endif
0102 
0103 #if ZONES_WIDTH + SECTIONS_WIDTH + NODES_WIDTH + KASAN_TAG_WIDTH + LAST_CPUPID_WIDTH \
0104     > BITS_PER_LONG - NR_PAGEFLAGS
0105 #error "Not enough bits in page flags"
0106 #endif
0107 
0108 #endif
0109 #endif /* _LINUX_PAGE_FLAGS_LAYOUT */