xref: /openbmc/linux/arch/powerpc/mm/pgtable_64.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
270d64ceaSPaul Mackerras /*
3f381d571SChristophe Leroy  *  This file contains pgtable related functions for 64-bit machines.
470d64ceaSPaul Mackerras  *
570d64ceaSPaul Mackerras  *  Derived from arch/ppc64/mm/init.c
670d64ceaSPaul Mackerras  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
770d64ceaSPaul Mackerras  *
870d64ceaSPaul Mackerras  *  Modifications by Paul Mackerras (PowerMac) (paulus@samba.org)
970d64ceaSPaul Mackerras  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
1070d64ceaSPaul Mackerras  *    Copyright (C) 1996 Paul Mackerras
1170d64ceaSPaul Mackerras  *
1270d64ceaSPaul Mackerras  *  Derived from "arch/i386/mm/init.c"
1370d64ceaSPaul Mackerras  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
1470d64ceaSPaul Mackerras  *
1570d64ceaSPaul Mackerras  *  Dave Engebretsen <engebret@us.ibm.com>
1670d64ceaSPaul Mackerras  *      Rework for PPC64 port.
1770d64ceaSPaul Mackerras  */
1870d64ceaSPaul Mackerras 
1970d64ceaSPaul Mackerras #include <linux/signal.h>
2070d64ceaSPaul Mackerras #include <linux/sched.h>
2170d64ceaSPaul Mackerras #include <linux/kernel.h>
2270d64ceaSPaul Mackerras #include <linux/errno.h>
2370d64ceaSPaul Mackerras #include <linux/string.h>
2466b15db6SPaul Gortmaker #include <linux/export.h>
2570d64ceaSPaul Mackerras #include <linux/types.h>
2670d64ceaSPaul Mackerras #include <linux/mman.h>
2770d64ceaSPaul Mackerras #include <linux/mm.h>
2870d64ceaSPaul Mackerras #include <linux/swap.h>
2970d64ceaSPaul Mackerras #include <linux/stddef.h>
3070d64ceaSPaul Mackerras #include <linux/vmalloc.h>
315a0e3ad6STejun Heo #include <linux/slab.h>
3206743521SAneesh Kumar K.V #include <linux/hugetlb.h>
3370d64ceaSPaul Mackerras 
3470d64ceaSPaul Mackerras #include <asm/page.h>
3570d64ceaSPaul Mackerras #include <asm/mmu_context.h>
3670d64ceaSPaul Mackerras #include <asm/mmu.h>
3770d64ceaSPaul Mackerras #include <asm/smp.h>
3870d64ceaSPaul Mackerras #include <asm/machdep.h>
3970d64ceaSPaul Mackerras #include <asm/tlb.h>
4070d64ceaSPaul Mackerras #include <asm/processor.h>
4170d64ceaSPaul Mackerras #include <asm/cputable.h>
4270d64ceaSPaul Mackerras #include <asm/sections.h>
435e203d68SStephen Rothwell #include <asm/firmware.h>
4468cf0d64SAnton Blanchard #include <asm/dma.h>
45800fc3eeSDavid Gibson 
469d9f2cccSChristophe Leroy #include <mm/mmu_decl.h>
4770d64ceaSPaul Mackerras 
4878f1dbdeSAneesh Kumar K.V 
4950de596dSAneesh Kumar K.V #ifdef CONFIG_PPC_BOOK3S_64
5050de596dSAneesh Kumar K.V /*
5150de596dSAneesh Kumar K.V  * partition table and process table for ISA 3.0
5250de596dSAneesh Kumar K.V  */
5350de596dSAneesh Kumar K.V struct prtb_entry *process_tb;
5450de596dSAneesh Kumar K.V struct patb_entry *partition_tb;
55dd1842a2SAneesh Kumar K.V /*
56dd1842a2SAneesh Kumar K.V  * page table size
57dd1842a2SAneesh Kumar K.V  */
58dd1842a2SAneesh Kumar K.V unsigned long __pte_index_size;
59dd1842a2SAneesh Kumar K.V EXPORT_SYMBOL(__pte_index_size);
60dd1842a2SAneesh Kumar K.V unsigned long __pmd_index_size;
61dd1842a2SAneesh Kumar K.V EXPORT_SYMBOL(__pmd_index_size);
62dd1842a2SAneesh Kumar K.V unsigned long __pud_index_size;
63dd1842a2SAneesh Kumar K.V EXPORT_SYMBOL(__pud_index_size);
64dd1842a2SAneesh Kumar K.V unsigned long __pgd_index_size;
65dd1842a2SAneesh Kumar K.V EXPORT_SYMBOL(__pgd_index_size);
66fae22116SAneesh Kumar K.V unsigned long __pud_cache_index;
67fae22116SAneesh Kumar K.V EXPORT_SYMBOL(__pud_cache_index);
68dd1842a2SAneesh Kumar K.V unsigned long __pte_table_size;
69dd1842a2SAneesh Kumar K.V EXPORT_SYMBOL(__pte_table_size);
70dd1842a2SAneesh Kumar K.V unsigned long __pmd_table_size;
71dd1842a2SAneesh Kumar K.V EXPORT_SYMBOL(__pmd_table_size);
72dd1842a2SAneesh Kumar K.V unsigned long __pud_table_size;
73dd1842a2SAneesh Kumar K.V EXPORT_SYMBOL(__pud_table_size);
74dd1842a2SAneesh Kumar K.V unsigned long __pgd_table_size;
75dd1842a2SAneesh Kumar K.V EXPORT_SYMBOL(__pgd_table_size);
76a2f41eb9SAneesh Kumar K.V unsigned long __pmd_val_bits;
77a2f41eb9SAneesh Kumar K.V EXPORT_SYMBOL(__pmd_val_bits);
78a2f41eb9SAneesh Kumar K.V unsigned long __pud_val_bits;
79a2f41eb9SAneesh Kumar K.V EXPORT_SYMBOL(__pud_val_bits);
80a2f41eb9SAneesh Kumar K.V unsigned long __pgd_val_bits;
81a2f41eb9SAneesh Kumar K.V EXPORT_SYMBOL(__pgd_val_bits);
82d6a9996eSAneesh Kumar K.V unsigned long __kernel_virt_start;
83d6a9996eSAneesh Kumar K.V EXPORT_SYMBOL(__kernel_virt_start);
84d6a9996eSAneesh Kumar K.V unsigned long __vmalloc_start;
85d6a9996eSAneesh Kumar K.V EXPORT_SYMBOL(__vmalloc_start);
86d6a9996eSAneesh Kumar K.V unsigned long __vmalloc_end;
87d6a9996eSAneesh Kumar K.V EXPORT_SYMBOL(__vmalloc_end);
8863ee9b2fSMichael Ellerman unsigned long __kernel_io_start;
8963ee9b2fSMichael Ellerman EXPORT_SYMBOL(__kernel_io_start);
90a35a3c6fSAneesh Kumar K.V unsigned long __kernel_io_end;
91d6a9996eSAneesh Kumar K.V struct page *vmemmap;
92d6a9996eSAneesh Kumar K.V EXPORT_SYMBOL(vmemmap);
935ed7ecd0SAneesh Kumar K.V unsigned long __pte_frag_nr;
945ed7ecd0SAneesh Kumar K.V EXPORT_SYMBOL(__pte_frag_nr);
955ed7ecd0SAneesh Kumar K.V unsigned long __pte_frag_size_shift;
965ed7ecd0SAneesh Kumar K.V EXPORT_SYMBOL(__pte_frag_size_shift);
97d6a9996eSAneesh Kumar K.V #endif
98a245067eSBenjamin Herrenschmidt 
9906743521SAneesh Kumar K.V #ifndef __PAGETABLE_PUD_FOLDED
10006743521SAneesh Kumar K.V /* 4 level page table */
p4d_page(p4d_t p4d)1012fb47060SMike Rapoport struct page *p4d_page(p4d_t p4d)
10206743521SAneesh Kumar K.V {
1032fb47060SMike Rapoport 	if (p4d_is_leaf(p4d)) {
104*467ba14eSNicholas Piggin 		if (!IS_ENABLED(CONFIG_HAVE_ARCH_HUGE_VMAP))
1052fb47060SMike Rapoport 			VM_WARN_ON(!p4d_huge(p4d));
1062fb47060SMike Rapoport 		return pte_page(p4d_pte(p4d));
107d6eaceddSAneesh Kumar K.V 	}
108dc4875f0SAneesh Kumar K.V 	return virt_to_page(p4d_pgtable(p4d));
10906743521SAneesh Kumar K.V }
11006743521SAneesh Kumar K.V #endif
11106743521SAneesh Kumar K.V 
pud_page(pud_t pud)11206743521SAneesh Kumar K.V struct page *pud_page(pud_t pud)
11306743521SAneesh Kumar K.V {
114d6eaceddSAneesh Kumar K.V 	if (pud_is_leaf(pud)) {
115*467ba14eSNicholas Piggin 		if (!IS_ENABLED(CONFIG_HAVE_ARCH_HUGE_VMAP))
116d6eaceddSAneesh Kumar K.V 			VM_WARN_ON(!pud_huge(pud));
11706743521SAneesh Kumar K.V 		return pte_page(pud_pte(pud));
118d6eaceddSAneesh Kumar K.V 	}
1199cf6fa24SAneesh Kumar K.V 	return virt_to_page(pud_pgtable(pud));
12006743521SAneesh Kumar K.V }
12106743521SAneesh Kumar K.V 
122074c2eaeSAneesh Kumar K.V /*
123074c2eaeSAneesh Kumar K.V  * For hugepage we have pfn in the pmd, we use PTE_RPN_SHIFT bits for flags
124074c2eaeSAneesh Kumar K.V  * For PTE page, we have a PTE_FRAG_SIZE (4K) aligned virtual address.
125074c2eaeSAneesh Kumar K.V  */
pmd_page(pmd_t pmd)126074c2eaeSAneesh Kumar K.V struct page *pmd_page(pmd_t pmd)
127074c2eaeSAneesh Kumar K.V {
128d6eaceddSAneesh Kumar K.V 	if (pmd_is_leaf(pmd)) {
129*467ba14eSNicholas Piggin 		/*
130*467ba14eSNicholas Piggin 		 * vmalloc_to_page may be called on any vmap address (not only
131*467ba14eSNicholas Piggin 		 * vmalloc), and it uses pmd_page() etc., when huge vmap is
132*467ba14eSNicholas Piggin 		 * enabled so these checks can't be used.
133*467ba14eSNicholas Piggin 		 */
134*467ba14eSNicholas Piggin 		if (!IS_ENABLED(CONFIG_HAVE_ARCH_HUGE_VMAP))
1351ecf2cdcSAneesh Kumar K.V 			VM_WARN_ON(!(pmd_large(pmd) || pmd_huge(pmd)));
136e34aa03cSAneesh Kumar K.V 		return pte_page(pmd_pte(pmd));
137d6eaceddSAneesh Kumar K.V 	}
138074c2eaeSAneesh Kumar K.V 	return virt_to_page(pmd_page_vaddr(pmd));
139074c2eaeSAneesh Kumar K.V }
140074c2eaeSAneesh Kumar K.V 
141cd65d697SBalbir Singh #ifdef CONFIG_STRICT_KERNEL_RWX
mark_rodata_ro(void)142cd65d697SBalbir Singh void mark_rodata_ro(void)
143cd65d697SBalbir Singh {
144cd65d697SBalbir Singh 	if (!mmu_has_feature(MMU_FTR_KERNEL_RO)) {
145cd65d697SBalbir Singh 		pr_warn("Warning: Unable to mark rodata read only on this CPU.\n");
146cd65d697SBalbir Singh 		return;
147cd65d697SBalbir Singh 	}
148cd65d697SBalbir Singh 
1497614ff32SBalbir Singh 	if (radix_enabled())
1507614ff32SBalbir Singh 		radix__mark_rodata_ro();
1517614ff32SBalbir Singh 	else
152cd65d697SBalbir Singh 		hash__mark_rodata_ro();
153453d87f6SRussell Currey 
154453d87f6SRussell Currey 	// mark_initmem_nx() should have already run by now
155453d87f6SRussell Currey 	ptdump_check_wx();
156cd65d697SBalbir Singh }
157029d9252SMichael Ellerman 
mark_initmem_nx(void)158029d9252SMichael Ellerman void mark_initmem_nx(void)
159029d9252SMichael Ellerman {
160029d9252SMichael Ellerman 	if (radix_enabled())
161029d9252SMichael Ellerman 		radix__mark_initmem_nx();
162029d9252SMichael Ellerman 	else
163029d9252SMichael Ellerman 		hash__mark_initmem_nx();
164029d9252SMichael Ellerman }
165cd65d697SBalbir Singh #endif
166