1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
6 * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
7 * and Cort Dougan (PReP) (cort@cs.nmt.edu)
8 * Copyright (C) 1996 Paul Mackerras
10 * Derived from "arch/i386/mm/init.c"
11 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
13 * Dave Engebretsen <engebret@us.ibm.com>
14 * Rework for PPC64 port.
19 #include <linux/signal.h>
20 #include <linux/sched.h>
21 #include <linux/kernel.h>
22 #include <linux/errno.h>
23 #include <linux/string.h>
24 #include <linux/types.h>
25 #include <linux/mman.h>
27 #include <linux/swap.h>
28 #include <linux/stddef.h>
29 #include <linux/vmalloc.h>
30 #include <linux/init.h>
31 #include <linux/delay.h>
32 #include <linux/highmem.h>
33 #include <linux/idr.h>
34 #include <linux/nodemask.h>
35 #include <linux/module.h>
36 #include <linux/poison.h>
37 #include <linux/memblock.h>
38 #include <linux/hugetlb.h>
39 #include <linux/slab.h>
40 #include <linux/of_fdt.h>
41 #include <linux/libfdt.h>
42 #include <linux/memremap.h>
44 #include <asm/pgalloc.h>
49 #include <asm/mmu_context.h>
50 #include <asm/pgtable.h>
52 #include <linux/uaccess.h>
54 #include <asm/machdep.h>
57 #include <asm/processor.h>
58 #include <asm/mmzone.h>
59 #include <asm/cputable.h>
60 #include <asm/sections.h>
61 #include <asm/iommu.h>
64 #include <mm/mmu_decl.h>
66 #ifdef CONFIG_SPARSEMEM_VMEMMAP
68 * Given an address within the vmemmap, determine the page that
69 * represents the start of the subsection it is within. Note that we have to
70 * do this by hand as the proffered address may not be correctly aligned.
71 * Subtraction of non-aligned pointers produces undefined results.
73 static struct page
* __meminit
vmemmap_subsection_start(unsigned long vmemmap_addr
)
75 unsigned long start_pfn
;
76 unsigned long offset
= vmemmap_addr
- ((unsigned long)(vmemmap
));
78 /* Return the pfn of the start of the section. */
79 start_pfn
= (offset
/ sizeof(struct page
)) & PAGE_SUBSECTION_MASK
;
80 return pfn_to_page(start_pfn
);
84 * Since memory is added in sub-section chunks, before creating a new vmemmap
85 * mapping, the kernel should check whether there is an existing memmap mapping
86 * covering the new subsection added. This is needed because kernel can map
87 * vmemmap area using 16MB pages which will cover a memory range of 16G. Such
88 * a range covers multiple subsections (2M)
90 * If any subsection in the 16G range mapped by vmemmap is valid we consider the
91 * vmemmap populated (There is a page table entry already present). We can't do
92 * a page table lookup here because with the hash translation we don't keep
93 * vmemmap details in linux page table.
95 static int __meminit
vmemmap_populated(unsigned long vmemmap_addr
, int vmemmap_map_size
)
98 unsigned long vmemmap_end
= vmemmap_addr
+ vmemmap_map_size
;
99 start
= vmemmap_subsection_start(vmemmap_addr
);
101 for (; (unsigned long)start
< vmemmap_end
; start
+= PAGES_PER_SUBSECTION
)
103 * pfn valid check here is intended to really check
104 * whether we have any subsection already initialized
107 if (pfn_valid(page_to_pfn(start
)))
114 * vmemmap virtual address space management does not have a traditonal page
115 * table to track which virtual struct pages are backed by physical mapping.
116 * The virtual to physical mappings are tracked in a simple linked list
117 * format. 'vmemmap_list' maintains the entire vmemmap physical mapping at
118 * all times where as the 'next' list maintains the available
119 * vmemmap_backing structures which have been deleted from the
120 * 'vmemmap_global' list during system runtime (memory hotplug remove
121 * operation). The freed 'vmemmap_backing' structures are reused later when
122 * new requests come in without allocating fresh memory. This pointer also
123 * tracks the allocated 'vmemmap_backing' structures as we allocate one
124 * full page memory at a time when we dont have any.
126 struct vmemmap_backing
*vmemmap_list
;
127 static struct vmemmap_backing
*next
;
130 * The same pointer 'next' tracks individual chunks inside the allocated
131 * full page during the boot time and again tracks the freeed nodes during
132 * runtime. It is racy but it does not happen as they are separated by the
133 * boot process. Will create problem if some how we have memory hotplug
134 * operation during boot !!
137 static int num_freed
;
139 static __meminit
struct vmemmap_backing
* vmemmap_list_alloc(int node
)
141 struct vmemmap_backing
*vmem_back
;
142 /* get from freed entries first */
151 /* allocate a page when required and hand out chunks */
153 next
= vmemmap_alloc_block(PAGE_SIZE
, node
);
154 if (unlikely(!next
)) {
158 num_left
= PAGE_SIZE
/ sizeof(struct vmemmap_backing
);
166 static __meminit
void vmemmap_list_populate(unsigned long phys
,
170 struct vmemmap_backing
*vmem_back
;
172 vmem_back
= vmemmap_list_alloc(node
);
173 if (unlikely(!vmem_back
)) {
178 vmem_back
->phys
= phys
;
179 vmem_back
->virt_addr
= start
;
180 vmem_back
->list
= vmemmap_list
;
182 vmemmap_list
= vmem_back
;
185 static bool altmap_cross_boundary(struct vmem_altmap
*altmap
, unsigned long start
,
186 unsigned long page_size
)
188 unsigned long nr_pfn
= page_size
/ sizeof(struct page
);
189 unsigned long start_pfn
= page_to_pfn((struct page
*)start
);
191 if ((start_pfn
+ nr_pfn
) > altmap
->end_pfn
)
194 if (start_pfn
< altmap
->base_pfn
)
200 int __meminit
vmemmap_populate(unsigned long start
, unsigned long end
, int node
,
201 struct vmem_altmap
*altmap
)
203 unsigned long page_size
= 1 << mmu_psize_defs
[mmu_vmemmap_psize
].shift
;
205 /* Align to the page size of the linear mapping. */
206 start
= _ALIGN_DOWN(start
, page_size
);
208 pr_debug("vmemmap_populate %lx..%lx, node %d\n", start
, end
, node
);
210 for (; start
< end
; start
+= page_size
) {
215 * This vmemmap range is backing different subsections. If any
216 * of that subsection is marked valid, that means we already
217 * have initialized a page table covering this range and hence
218 * the vmemmap range is populated.
220 if (vmemmap_populated(start
, page_size
))
224 * Allocate from the altmap first if we have one. This may
225 * fail due to alignment issues when using 16MB hugepages, so
226 * fall back to system memory if the altmap allocation fail.
228 if (altmap
&& !altmap_cross_boundary(altmap
, start
, page_size
)) {
229 p
= altmap_alloc_block_buf(page_size
, altmap
);
231 pr_debug("altmap block allocation failed, falling back to system memory");
234 p
= vmemmap_alloc_block_buf(page_size
, node
);
238 vmemmap_list_populate(__pa(p
), start
, node
);
240 pr_debug(" * %016lx..%016lx allocated at %p\n",
241 start
, start
+ page_size
, p
);
243 rc
= vmemmap_create_mapping(start
, page_size
, __pa(p
));
245 pr_warn("%s: Unable to create vmemmap mapping: %d\n",
254 #ifdef CONFIG_MEMORY_HOTPLUG
255 static unsigned long vmemmap_list_free(unsigned long start
)
257 struct vmemmap_backing
*vmem_back
, *vmem_back_prev
;
259 vmem_back_prev
= vmem_back
= vmemmap_list
;
261 /* look for it with prev pointer recorded */
262 for (; vmem_back
; vmem_back
= vmem_back
->list
) {
263 if (vmem_back
->virt_addr
== start
)
265 vmem_back_prev
= vmem_back
;
268 if (unlikely(!vmem_back
)) {
273 /* remove it from vmemmap_list */
274 if (vmem_back
== vmemmap_list
) /* remove head */
275 vmemmap_list
= vmem_back
->list
;
277 vmem_back_prev
->list
= vmem_back
->list
;
279 /* next point to this freed entry */
280 vmem_back
->list
= next
;
284 return vmem_back
->phys
;
287 void __ref
vmemmap_free(unsigned long start
, unsigned long end
,
288 struct vmem_altmap
*altmap
)
290 unsigned long page_size
= 1 << mmu_psize_defs
[mmu_vmemmap_psize
].shift
;
291 unsigned long page_order
= get_order(page_size
);
292 unsigned long alt_start
= ~0, alt_end
= ~0;
293 unsigned long base_pfn
;
295 start
= _ALIGN_DOWN(start
, page_size
);
297 alt_start
= altmap
->base_pfn
;
298 alt_end
= altmap
->base_pfn
+ altmap
->reserve
+
299 altmap
->free
+ altmap
->alloc
+ altmap
->align
;
302 pr_debug("vmemmap_free %lx...%lx\n", start
, end
);
304 for (; start
< end
; start
+= page_size
) {
305 unsigned long nr_pages
, addr
;
309 * We have already marked the subsection we are trying to remove
310 * invalid. So if we want to remove the vmemmap range, we
311 * need to make sure there is no subsection marked valid
314 if (vmemmap_populated(start
, page_size
))
317 addr
= vmemmap_list_free(start
);
321 page
= pfn_to_page(addr
>> PAGE_SHIFT
);
322 nr_pages
= 1 << page_order
;
323 base_pfn
= PHYS_PFN(addr
);
325 if (base_pfn
>= alt_start
&& base_pfn
< alt_end
) {
326 vmem_altmap_free(altmap
, nr_pages
);
327 } else if (PageReserved(page
)) {
328 /* allocated from bootmem */
329 if (page_size
< PAGE_SIZE
) {
331 * this shouldn't happen, but if it is
332 * the case, leave the memory there
337 free_reserved_page(page
++);
340 free_pages((unsigned long)(__va(addr
)), page_order
);
343 vmemmap_remove_mapping(start
, page_size
);
347 void register_page_bootmem_memmap(unsigned long section_nr
,
348 struct page
*start_page
, unsigned long size
)
352 #endif /* CONFIG_SPARSEMEM_VMEMMAP */
354 #ifdef CONFIG_PPC_BOOK3S_64
355 static bool disable_radix
= !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT
);
357 static int __init
parse_disable_radix(char *p
)
363 else if (kstrtobool(p
, &val
))
370 early_param("disable_radix", parse_disable_radix
);
373 * If we're running under a hypervisor, we need to check the contents of
374 * /chosen/ibm,architecture-vec-5 to see if the hypervisor is willing to do
375 * radix. If not, we clear the radix feature bit so we fall back to hash.
377 static void __init
early_check_vec5(void)
379 unsigned long root
, chosen
;
384 root
= of_get_flat_dt_root();
385 chosen
= of_get_flat_dt_subnode_by_name(root
, "chosen");
386 if (chosen
== -FDT_ERR_NOTFOUND
) {
387 cur_cpu_spec
->mmu_features
&= ~MMU_FTR_TYPE_RADIX
;
390 vec5
= of_get_flat_dt_prop(chosen
, "ibm,architecture-vec-5", &size
);
392 cur_cpu_spec
->mmu_features
&= ~MMU_FTR_TYPE_RADIX
;
395 if (size
<= OV5_INDX(OV5_MMU_SUPPORT
)) {
396 cur_cpu_spec
->mmu_features
&= ~MMU_FTR_TYPE_RADIX
;
400 /* Check for supported configuration */
401 mmu_supported
= vec5
[OV5_INDX(OV5_MMU_SUPPORT
)] &
402 OV5_FEAT(OV5_MMU_SUPPORT
);
403 if (mmu_supported
== OV5_FEAT(OV5_MMU_RADIX
)) {
404 /* Hypervisor only supports radix - check enabled && GTSE */
405 if (!early_radix_enabled()) {
406 pr_warn("WARNING: Ignoring cmdline option disable_radix\n");
408 if (!(vec5
[OV5_INDX(OV5_RADIX_GTSE
)] &
409 OV5_FEAT(OV5_RADIX_GTSE
))) {
410 pr_warn("WARNING: Hypervisor doesn't support RADIX with GTSE\n");
412 /* Do radix anyway - the hypervisor said we had to */
413 cur_cpu_spec
->mmu_features
|= MMU_FTR_TYPE_RADIX
;
414 } else if (mmu_supported
== OV5_FEAT(OV5_MMU_HASH
)) {
415 /* Hypervisor only supports hash - disable radix */
416 cur_cpu_spec
->mmu_features
&= ~MMU_FTR_TYPE_RADIX
;
420 void __init
mmu_early_init_devtree(void)
422 /* Disable radix mode based on kernel command line. */
424 cur_cpu_spec
->mmu_features
&= ~MMU_FTR_TYPE_RADIX
;
427 * Check /chosen/ibm,architecture-vec-5 if running as a guest.
428 * When running bare-metal, we can use radix if we like
429 * even though the ibm,architecture-vec-5 property created by
430 * skiboot doesn't have the necessary bits set.
432 if (!(mfmsr() & MSR_HV
))
435 if (early_radix_enabled())
436 radix__early_init_devtree();
438 hash__early_init_devtree();
440 #endif /* CONFIG_PPC_BOOK3S_64 */