xref: /linux/mm/sparse.h (revision 76df418d2957fc10de866e83a9d5c000e15b25c5)
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