1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * sparse.h: 4 * 5 * mm/ internal sparse and sparse-vmemmap declarations 6 */ 7 8 #ifndef __MM_SPARSE_H 9 #define __MM_SPARSE_H 10 11 #include <linux/mmzone.h> 12 #include <linux/vmemmap-optimization.h> 13 14 /* 15 * mm/sparse.c 16 */ 17 #ifdef CONFIG_SPARSEMEM 18 void sparse_init(void); 19 void sparse_sections_init(void); 20 int sparse_index_init(unsigned long section_nr, int nid); 21 22 static inline void sparse_init_one_section(struct mem_section *ms, 23 unsigned long pnum, struct page *mem_map, 24 struct mem_section_usage *usage, unsigned long flags) 25 { 26 unsigned long coded_mem_map; 27 28 BUILD_BUG_ON(SECTION_MAP_LAST_BIT > PFN_SECTION_SHIFT); 29 30 /* 31 * We encode the start PFN of the section into the mem_map such that 32 * page_to_pfn() on !CONFIG_SPARSEMEM_VMEMMAP can simply subtract it 33 * from the page pointer to obtain the PFN. 34 */ 35 coded_mem_map = (unsigned long)(mem_map - section_nr_to_pfn(pnum)); 36 VM_WARN_ON_ONCE(coded_mem_map & ~SECTION_MAP_MASK); 37 38 ms->section_mem_map &= ~SECTION_MAP_MASK; 39 ms->section_mem_map |= coded_mem_map; 40 ms->section_mem_map |= flags | SECTION_HAS_MEM_MAP; 41 ms->usage = usage; 42 } 43 44 static inline void __section_mark_present(struct mem_section *ms, 45 unsigned long section_nr) 46 { 47 if (section_nr > __highest_present_section_nr) 48 __highest_present_section_nr = section_nr; 49 50 ms->section_mem_map |= SECTION_MARKED_PRESENT; 51 } 52 53 static inline size_t mem_section_usage_size(void) 54 { 55 return struct_size_t(struct mem_section_usage, pageblock_flags, 56 BITS_TO_LONGS(SECTION_BLOCKFLAGS_BITS)); 57 } 58 59 static inline bool section_vmemmap_optimizable(const struct mem_section *ms) 60 { 61 return vmemmap_optimizable_order(section_compound_order(ms)); 62 } 63 #else 64 static inline void sparse_init(void) {} 65 static inline void sparse_sections_init(void) {} 66 #endif /* CONFIG_SPARSEMEM */ 67 68 /* 69 * mm/sparse-vmemmap.c 70 */ 71 #ifdef CONFIG_SPARSEMEM_VMEMMAP 72 void sparse_init_subsection_map(void); 73 int section_nr_vmemmap_pages(unsigned long pfn, unsigned long nr_pages); 74 #else 75 static inline void sparse_init_subsection_map(void) {} 76 static inline int section_nr_vmemmap_pages(unsigned long pfn, unsigned long nr_pages) 77 { 78 return DIV_ROUND_UP(nr_pages * sizeof(struct page), PAGE_SIZE); 79 } 80 #endif /* CONFIG_SPARSEMEM_VMEMMAP */ 81 82 #endif /* __MM_SPARSE_H */ 83