xref: /linux/arch/powerpc/mm/init-common.c (revision 67d53f30e23ec66aa7bbdd1592d5e64d46876190)
19b081e10SChristophe Leroy /*
29b081e10SChristophe Leroy  *  PowerPC version
39b081e10SChristophe Leroy  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
49b081e10SChristophe Leroy  *
59b081e10SChristophe Leroy  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
69b081e10SChristophe Leroy  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
79b081e10SChristophe Leroy  *    Copyright (C) 1996 Paul Mackerras
89b081e10SChristophe Leroy  *
99b081e10SChristophe Leroy  *  Derived from "arch/i386/mm/init.c"
109b081e10SChristophe Leroy  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
119b081e10SChristophe Leroy  *
129b081e10SChristophe Leroy  *  Dave Engebretsen <engebret@us.ibm.com>
139b081e10SChristophe Leroy  *      Rework for PPC64 port.
149b081e10SChristophe Leroy  *
159b081e10SChristophe Leroy  *  This program is free software; you can redistribute it and/or
169b081e10SChristophe Leroy  *  modify it under the terms of the GNU General Public License
179b081e10SChristophe Leroy  *  as published by the Free Software Foundation; either version
189b081e10SChristophe Leroy  *  2 of the License, or (at your option) any later version.
199b081e10SChristophe Leroy  *
209b081e10SChristophe Leroy  */
219b081e10SChristophe Leroy 
229b081e10SChristophe Leroy #undef DEBUG
239b081e10SChristophe Leroy 
249b081e10SChristophe Leroy #include <linux/string.h>
259b081e10SChristophe Leroy #include <asm/pgalloc.h>
269b081e10SChristophe Leroy #include <asm/pgtable.h>
2769795cabSChristophe Leroy #include <asm/kup.h>
2869795cabSChristophe Leroy 
290fb1c25aSChristophe Leroy static bool disable_kuep = !IS_ENABLED(CONFIG_PPC_KUEP);
30de78a9c4SChristophe Leroy static bool disable_kuap = !IS_ENABLED(CONFIG_PPC_KUAP);
310fb1c25aSChristophe Leroy 
320fb1c25aSChristophe Leroy static int __init parse_nosmep(char *p)
330fb1c25aSChristophe Leroy {
340fb1c25aSChristophe Leroy 	disable_kuep = true;
350fb1c25aSChristophe Leroy 	pr_warn("Disabling Kernel Userspace Execution Prevention\n");
360fb1c25aSChristophe Leroy 	return 0;
370fb1c25aSChristophe Leroy }
380fb1c25aSChristophe Leroy early_param("nosmep", parse_nosmep);
390fb1c25aSChristophe Leroy 
40de78a9c4SChristophe Leroy static int __init parse_nosmap(char *p)
41de78a9c4SChristophe Leroy {
42de78a9c4SChristophe Leroy 	disable_kuap = true;
43de78a9c4SChristophe Leroy 	pr_warn("Disabling Kernel Userspace Access Protection\n");
44de78a9c4SChristophe Leroy 	return 0;
45de78a9c4SChristophe Leroy }
46de78a9c4SChristophe Leroy early_param("nosmap", parse_nosmap);
47de78a9c4SChristophe Leroy 
48*67d53f30SChristophe Leroy void __ref setup_kup(void)
4969795cabSChristophe Leroy {
500fb1c25aSChristophe Leroy 	setup_kuep(disable_kuep);
51de78a9c4SChristophe Leroy 	setup_kuap(disable_kuap);
5269795cabSChristophe Leroy }
539b081e10SChristophe Leroy 
541e03c7e2SChristophe Leroy #define CTOR(shift) static void ctor_##shift(void *addr) \
551e03c7e2SChristophe Leroy {							\
561e03c7e2SChristophe Leroy 	memset(addr, 0, sizeof(void *) << (shift));	\
579b081e10SChristophe Leroy }
589b081e10SChristophe Leroy 
591e03c7e2SChristophe Leroy CTOR(0); CTOR(1); CTOR(2); CTOR(3); CTOR(4); CTOR(5); CTOR(6); CTOR(7);
601e03c7e2SChristophe Leroy CTOR(8); CTOR(9); CTOR(10); CTOR(11); CTOR(12); CTOR(13); CTOR(14); CTOR(15);
619b081e10SChristophe Leroy 
621e03c7e2SChristophe Leroy static inline void (*ctor(int shift))(void *)
639b081e10SChristophe Leroy {
641e03c7e2SChristophe Leroy 	BUILD_BUG_ON(MAX_PGTABLE_INDEX_SIZE != 15);
651e03c7e2SChristophe Leroy 
661e03c7e2SChristophe Leroy 	switch (shift) {
671e03c7e2SChristophe Leroy 	case 0: return ctor_0;
681e03c7e2SChristophe Leroy 	case 1: return ctor_1;
691e03c7e2SChristophe Leroy 	case 2: return ctor_2;
701e03c7e2SChristophe Leroy 	case 3: return ctor_3;
711e03c7e2SChristophe Leroy 	case 4: return ctor_4;
721e03c7e2SChristophe Leroy 	case 5: return ctor_5;
731e03c7e2SChristophe Leroy 	case 6: return ctor_6;
741e03c7e2SChristophe Leroy 	case 7: return ctor_7;
751e03c7e2SChristophe Leroy 	case 8: return ctor_8;
761e03c7e2SChristophe Leroy 	case 9: return ctor_9;
771e03c7e2SChristophe Leroy 	case 10: return ctor_10;
781e03c7e2SChristophe Leroy 	case 11: return ctor_11;
791e03c7e2SChristophe Leroy 	case 12: return ctor_12;
801e03c7e2SChristophe Leroy 	case 13: return ctor_13;
811e03c7e2SChristophe Leroy 	case 14: return ctor_14;
821e03c7e2SChristophe Leroy 	case 15: return ctor_15;
831e03c7e2SChristophe Leroy 	}
841e03c7e2SChristophe Leroy 	return NULL;
859b081e10SChristophe Leroy }
869b081e10SChristophe Leroy 
87129dd323SChristophe Leroy struct kmem_cache *pgtable_cache[MAX_PGTABLE_INDEX_SIZE + 1];
88ba9b399aSPaul Mackerras EXPORT_SYMBOL_GPL(pgtable_cache);	/* used by kvm_hv module */
899b081e10SChristophe Leroy 
909b081e10SChristophe Leroy /*
919b081e10SChristophe Leroy  * Create a kmem_cache() for pagetables.  This is not used for PTE
929b081e10SChristophe Leroy  * pages - they're linked to struct page, come from the normal free
939b081e10SChristophe Leroy  * pages pool and have a different entry size (see real_pte_t) to
949b081e10SChristophe Leroy  * everything else.  Caches created by this function are used for all
959b081e10SChristophe Leroy  * the higher level pagetables, and for hugepage pagetables.
969b081e10SChristophe Leroy  */
971e03c7e2SChristophe Leroy void pgtable_cache_add(unsigned int shift)
989b081e10SChristophe Leroy {
999b081e10SChristophe Leroy 	char *name;
1009b081e10SChristophe Leroy 	unsigned long table_size = sizeof(void *) << shift;
1019b081e10SChristophe Leroy 	unsigned long align = table_size;
1029b081e10SChristophe Leroy 
1039b081e10SChristophe Leroy 	/* When batching pgtable pointers for RCU freeing, we store
1049b081e10SChristophe Leroy 	 * the index size in the low bits.  Table alignment must be
1059b081e10SChristophe Leroy 	 * big enough to fit it.
1069b081e10SChristophe Leroy 	 *
1079b081e10SChristophe Leroy 	 * Likewise, hugeapge pagetable pointers contain a (different)
1089b081e10SChristophe Leroy 	 * shift value in the low bits.  All tables must be aligned so
1099b081e10SChristophe Leroy 	 * as to leave enough 0 bits in the address to contain it. */
1109b081e10SChristophe Leroy 	unsigned long minalign = max(MAX_PGTABLE_INDEX_SIZE + 1,
1119b081e10SChristophe Leroy 				     HUGEPD_SHIFT_MASK + 1);
1129b081e10SChristophe Leroy 	struct kmem_cache *new;
1139b081e10SChristophe Leroy 
1149b081e10SChristophe Leroy 	/* It would be nice if this was a BUILD_BUG_ON(), but at the
1159b081e10SChristophe Leroy 	 * moment, gcc doesn't seem to recognize is_power_of_2 as a
1169b081e10SChristophe Leroy 	 * constant expression, so so much for that. */
1179b081e10SChristophe Leroy 	BUG_ON(!is_power_of_2(minalign));
118129dd323SChristophe Leroy 	BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE);
1199b081e10SChristophe Leroy 
1209b081e10SChristophe Leroy 	if (PGT_CACHE(shift))
1219b081e10SChristophe Leroy 		return; /* Already have a cache of this size */
1229b081e10SChristophe Leroy 
1239b081e10SChristophe Leroy 	align = max_t(unsigned long, align, minalign);
1249b081e10SChristophe Leroy 	name = kasprintf(GFP_KERNEL, "pgtable-2^%d", shift);
1251e03c7e2SChristophe Leroy 	new = kmem_cache_create(name, table_size, align, 0, ctor(shift));
126bf5ca68dSNicholas Piggin 	if (!new)
127bf5ca68dSNicholas Piggin 		panic("Could not allocate pgtable cache for order %d", shift);
128bf5ca68dSNicholas Piggin 
1299b081e10SChristophe Leroy 	kfree(name);
130129dd323SChristophe Leroy 	pgtable_cache[shift] = new;
131bf5ca68dSNicholas Piggin 
1329b081e10SChristophe Leroy 	pr_debug("Allocated pgtable cache for order %d\n", shift);
1339b081e10SChristophe Leroy }
134ba9b399aSPaul Mackerras EXPORT_SYMBOL_GPL(pgtable_cache_add);	/* used by kvm_hv module */
1359b081e10SChristophe Leroy 
1369b081e10SChristophe Leroy void pgtable_cache_init(void)
1379b081e10SChristophe Leroy {
1381e03c7e2SChristophe Leroy 	pgtable_cache_add(PGD_INDEX_SIZE);
1399b081e10SChristophe Leroy 
14032bff4b9SChristophe Leroy 	if (PMD_CACHE_INDEX)
1411e03c7e2SChristophe Leroy 		pgtable_cache_add(PMD_CACHE_INDEX);
1429b081e10SChristophe Leroy 	/*
1439b081e10SChristophe Leroy 	 * In all current configs, when the PUD index exists it's the
1449b081e10SChristophe Leroy 	 * same size as either the pgd or pmd index except with THP enabled
1459b081e10SChristophe Leroy 	 * on book3s 64
1469b081e10SChristophe Leroy 	 */
14732bff4b9SChristophe Leroy 	if (PUD_CACHE_INDEX)
1481e03c7e2SChristophe Leroy 		pgtable_cache_add(PUD_CACHE_INDEX);
1499b081e10SChristophe Leroy }
150