xref: /openbmc/linux/arch/powerpc/mm/nohash/tlb.c (revision ed05c71a)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
227e23b5fSChristophe Leroy /*
327e23b5fSChristophe Leroy  * This file contains the routines for TLB flushing.
427e23b5fSChristophe Leroy  * On machines where the MMU does not use a hash table to store virtual to
527e23b5fSChristophe Leroy  * physical translations (ie, SW loaded TLBs or Book3E compilant processors,
627e23b5fSChristophe Leroy  * this does -not- include 603 however which shares the implementation with
727e23b5fSChristophe Leroy  * hash based processors)
827e23b5fSChristophe Leroy  *
927e23b5fSChristophe Leroy  *  -- BenH
1027e23b5fSChristophe Leroy  *
1127e23b5fSChristophe Leroy  * Copyright 2008,2009 Ben Herrenschmidt <benh@kernel.crashing.org>
1227e23b5fSChristophe Leroy  *                     IBM Corp.
1327e23b5fSChristophe Leroy  *
1427e23b5fSChristophe Leroy  *  Derived from arch/ppc/mm/init.c:
1527e23b5fSChristophe Leroy  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
1627e23b5fSChristophe Leroy  *
1727e23b5fSChristophe Leroy  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
1827e23b5fSChristophe Leroy  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
1927e23b5fSChristophe Leroy  *    Copyright (C) 1996 Paul Mackerras
2027e23b5fSChristophe Leroy  *
2127e23b5fSChristophe Leroy  *  Derived from "arch/i386/mm/init.c"
2227e23b5fSChristophe Leroy  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
2327e23b5fSChristophe Leroy  */
2427e23b5fSChristophe Leroy 
2527e23b5fSChristophe Leroy #include <linux/kernel.h>
2627e23b5fSChristophe Leroy #include <linux/export.h>
2727e23b5fSChristophe Leroy #include <linux/mm.h>
2827e23b5fSChristophe Leroy #include <linux/init.h>
2927e23b5fSChristophe Leroy #include <linux/highmem.h>
3027e23b5fSChristophe Leroy #include <linux/pagemap.h>
3127e23b5fSChristophe Leroy #include <linux/preempt.h>
3227e23b5fSChristophe Leroy #include <linux/spinlock.h>
3327e23b5fSChristophe Leroy #include <linux/memblock.h>
3427e23b5fSChristophe Leroy #include <linux/of_fdt.h>
3527e23b5fSChristophe Leroy #include <linux/hugetlb.h>
3627e23b5fSChristophe Leroy 
37ca15ca40SMike Rapoport #include <asm/pgalloc.h>
3827e23b5fSChristophe Leroy #include <asm/tlbflush.h>
3927e23b5fSChristophe Leroy #include <asm/tlb.h>
4027e23b5fSChristophe Leroy #include <asm/code-patching.h>
4127e23b5fSChristophe Leroy #include <asm/cputhreads.h>
4227e23b5fSChristophe Leroy #include <asm/hugetlb.h>
4327e23b5fSChristophe Leroy #include <asm/paca.h>
4427e23b5fSChristophe Leroy 
4527e23b5fSChristophe Leroy #include <mm/mmu_decl.h>
4627e23b5fSChristophe Leroy 
4727e23b5fSChristophe Leroy /*
4827e23b5fSChristophe Leroy  * This struct lists the sw-supported page sizes.  The hardawre MMU may support
4927e23b5fSChristophe Leroy  * other sizes not listed here.   The .ind field is only used on MMUs that have
5027e23b5fSChristophe Leroy  * indirect page table entries.
5127e23b5fSChristophe Leroy  */
523e731858SChristophe Leroy #ifdef CONFIG_PPC_E500
5327e23b5fSChristophe Leroy struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
5427e23b5fSChristophe Leroy 	[MMU_PAGE_4K] = {
5527e23b5fSChristophe Leroy 		.shift	= 12,
5627e23b5fSChristophe Leroy 		.enc	= BOOK3E_PAGESZ_4K,
5727e23b5fSChristophe Leroy 	},
5827e23b5fSChristophe Leroy 	[MMU_PAGE_2M] = {
5927e23b5fSChristophe Leroy 		.shift	= 21,
6027e23b5fSChristophe Leroy 		.enc	= BOOK3E_PAGESZ_2M,
6127e23b5fSChristophe Leroy 	},
6227e23b5fSChristophe Leroy 	[MMU_PAGE_4M] = {
6327e23b5fSChristophe Leroy 		.shift	= 22,
6427e23b5fSChristophe Leroy 		.enc	= BOOK3E_PAGESZ_4M,
6527e23b5fSChristophe Leroy 	},
6627e23b5fSChristophe Leroy 	[MMU_PAGE_16M] = {
6727e23b5fSChristophe Leroy 		.shift	= 24,
6827e23b5fSChristophe Leroy 		.enc	= BOOK3E_PAGESZ_16M,
6927e23b5fSChristophe Leroy 	},
7027e23b5fSChristophe Leroy 	[MMU_PAGE_64M] = {
7127e23b5fSChristophe Leroy 		.shift	= 26,
7227e23b5fSChristophe Leroy 		.enc	= BOOK3E_PAGESZ_64M,
7327e23b5fSChristophe Leroy 	},
7427e23b5fSChristophe Leroy 	[MMU_PAGE_256M] = {
7527e23b5fSChristophe Leroy 		.shift	= 28,
7627e23b5fSChristophe Leroy 		.enc	= BOOK3E_PAGESZ_256M,
7727e23b5fSChristophe Leroy 	},
7827e23b5fSChristophe Leroy 	[MMU_PAGE_1G] = {
7927e23b5fSChristophe Leroy 		.shift	= 30,
8027e23b5fSChristophe Leroy 		.enc	= BOOK3E_PAGESZ_1GB,
8127e23b5fSChristophe Leroy 	},
8227e23b5fSChristophe Leroy };
83605ba9eeSChristophe Leroy 
mmu_get_tsize(int psize)84605ba9eeSChristophe Leroy static inline int mmu_get_tsize(int psize)
85605ba9eeSChristophe Leroy {
86605ba9eeSChristophe Leroy 	return mmu_psize_defs[psize].enc;
87605ba9eeSChristophe Leroy }
88605ba9eeSChristophe Leroy #else
mmu_get_tsize(int psize)89605ba9eeSChristophe Leroy static inline int mmu_get_tsize(int psize)
90605ba9eeSChristophe Leroy {
91605ba9eeSChristophe Leroy 	/* This isn't used on !Book3E for now */
92605ba9eeSChristophe Leroy 	return 0;
93605ba9eeSChristophe Leroy }
94605ba9eeSChristophe Leroy #endif
95605ba9eeSChristophe Leroy 
96605ba9eeSChristophe Leroy #ifdef CONFIG_PPC_8xx
9727e23b5fSChristophe Leroy struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
9827e23b5fSChristophe Leroy 	[MMU_PAGE_4K] = {
9927e23b5fSChristophe Leroy 		.shift	= 12,
10027e23b5fSChristophe Leroy 	},
10127e23b5fSChristophe Leroy 	[MMU_PAGE_16K] = {
10227e23b5fSChristophe Leroy 		.shift	= 14,
10327e23b5fSChristophe Leroy 	},
10427e23b5fSChristophe Leroy 	[MMU_PAGE_512K] = {
10527e23b5fSChristophe Leroy 		.shift	= 19,
10627e23b5fSChristophe Leroy 	},
10727e23b5fSChristophe Leroy 	[MMU_PAGE_8M] = {
10827e23b5fSChristophe Leroy 		.shift	= 23,
10927e23b5fSChristophe Leroy 	},
11027e23b5fSChristophe Leroy };
111605ba9eeSChristophe Leroy #endif
11227e23b5fSChristophe Leroy 
11327e23b5fSChristophe Leroy /* The variables below are currently only used on 64-bit Book3E
11427e23b5fSChristophe Leroy  * though this will probably be made common with other nohash
11527e23b5fSChristophe Leroy  * implementations at some point
11627e23b5fSChristophe Leroy  */
11727e23b5fSChristophe Leroy #ifdef CONFIG_PPC64
11827e23b5fSChristophe Leroy 
11927e23b5fSChristophe Leroy int mmu_pte_psize;		/* Page size used for PTE pages */
12027e23b5fSChristophe Leroy int mmu_vmemmap_psize;		/* Page size used for the virtual mem map */
12127e23b5fSChristophe Leroy int book3e_htw_mode;		/* HW tablewalk?  Value is PPC_HTW_* */
12227e23b5fSChristophe Leroy unsigned long linear_map_top;	/* Top of linear mapping */
12327e23b5fSChristophe Leroy 
12427e23b5fSChristophe Leroy 
12527e23b5fSChristophe Leroy /*
12627e23b5fSChristophe Leroy  * Number of bytes to add to SPRN_SPRG_TLB_EXFRAME on crit/mcheck/debug
12727e23b5fSChristophe Leroy  * exceptions.  This is used for bolted and e6500 TLB miss handlers which
12827e23b5fSChristophe Leroy  * do not modify this SPRG in the TLB miss code; for other TLB miss handlers,
12927e23b5fSChristophe Leroy  * this is set to zero.
13027e23b5fSChristophe Leroy  */
13127e23b5fSChristophe Leroy int extlb_level_exc;
13227e23b5fSChristophe Leroy 
13327e23b5fSChristophe Leroy #endif /* CONFIG_PPC64 */
13427e23b5fSChristophe Leroy 
1353e731858SChristophe Leroy #ifdef CONFIG_PPC_E500
13627e23b5fSChristophe Leroy /* next_tlbcam_idx is used to round-robin tlbcam entry assignment */
13727e23b5fSChristophe Leroy DEFINE_PER_CPU(int, next_tlbcam_idx);
13827e23b5fSChristophe Leroy EXPORT_PER_CPU_SYMBOL(next_tlbcam_idx);
13927e23b5fSChristophe Leroy #endif
14027e23b5fSChristophe Leroy 
14127e23b5fSChristophe Leroy /*
14227e23b5fSChristophe Leroy  * Base TLB flushing operations:
14327e23b5fSChristophe Leroy  *
14427e23b5fSChristophe Leroy  *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
14527e23b5fSChristophe Leroy  *  - flush_tlb_page(vma, vmaddr) flushes one page
14627e23b5fSChristophe Leroy  *  - flush_tlb_range(vma, start, end) flushes a range of pages
14727e23b5fSChristophe Leroy  *  - flush_tlb_kernel_range(start, end) flushes kernel pages
14827e23b5fSChristophe Leroy  *
14927e23b5fSChristophe Leroy  *  - local_* variants of page and mm only apply to the current
15027e23b5fSChristophe Leroy  *    processor
15127e23b5fSChristophe Leroy  */
15227e23b5fSChristophe Leroy 
15363f501e0SChristophe Leroy #ifndef CONFIG_PPC_8xx
15427e23b5fSChristophe Leroy /*
15527e23b5fSChristophe Leroy  * These are the base non-SMP variants of page and mm flushing
15627e23b5fSChristophe Leroy  */
local_flush_tlb_mm(struct mm_struct * mm)15727e23b5fSChristophe Leroy void local_flush_tlb_mm(struct mm_struct *mm)
15827e23b5fSChristophe Leroy {
15927e23b5fSChristophe Leroy 	unsigned int pid;
16027e23b5fSChristophe Leroy 
16127e23b5fSChristophe Leroy 	preempt_disable();
16227e23b5fSChristophe Leroy 	pid = mm->context.id;
16327e23b5fSChristophe Leroy 	if (pid != MMU_NO_CONTEXT)
16427e23b5fSChristophe Leroy 		_tlbil_pid(pid);
16527e23b5fSChristophe Leroy 	preempt_enable();
16627e23b5fSChristophe Leroy }
16727e23b5fSChristophe Leroy EXPORT_SYMBOL(local_flush_tlb_mm);
16827e23b5fSChristophe Leroy 
__local_flush_tlb_page(struct mm_struct * mm,unsigned long vmaddr,int tsize,int ind)16927e23b5fSChristophe Leroy void __local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
17027e23b5fSChristophe Leroy 			    int tsize, int ind)
17127e23b5fSChristophe Leroy {
17227e23b5fSChristophe Leroy 	unsigned int pid;
17327e23b5fSChristophe Leroy 
17427e23b5fSChristophe Leroy 	preempt_disable();
17527e23b5fSChristophe Leroy 	pid = mm ? mm->context.id : 0;
17627e23b5fSChristophe Leroy 	if (pid != MMU_NO_CONTEXT)
17727e23b5fSChristophe Leroy 		_tlbil_va(vmaddr, pid, tsize, ind);
17827e23b5fSChristophe Leroy 	preempt_enable();
17927e23b5fSChristophe Leroy }
18027e23b5fSChristophe Leroy 
local_flush_tlb_page(struct vm_area_struct * vma,unsigned long vmaddr)18127e23b5fSChristophe Leroy void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
18227e23b5fSChristophe Leroy {
18327e23b5fSChristophe Leroy 	__local_flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr,
18427e23b5fSChristophe Leroy 			       mmu_get_tsize(mmu_virtual_psize), 0);
18527e23b5fSChristophe Leroy }
18627e23b5fSChristophe Leroy EXPORT_SYMBOL(local_flush_tlb_page);
187274d842fSBenjamin Gray 
local_flush_tlb_page_psize(struct mm_struct * mm,unsigned long vmaddr,int psize)188274d842fSBenjamin Gray void local_flush_tlb_page_psize(struct mm_struct *mm,
189274d842fSBenjamin Gray 				unsigned long vmaddr, int psize)
190274d842fSBenjamin Gray {
191274d842fSBenjamin Gray 	__local_flush_tlb_page(mm, vmaddr, mmu_get_tsize(psize), 0);
192274d842fSBenjamin Gray }
193274d842fSBenjamin Gray EXPORT_SYMBOL(local_flush_tlb_page_psize);
194274d842fSBenjamin Gray 
19563f501e0SChristophe Leroy #endif
19627e23b5fSChristophe Leroy 
19727e23b5fSChristophe Leroy /*
19827e23b5fSChristophe Leroy  * And here are the SMP non-local implementations
19927e23b5fSChristophe Leroy  */
20027e23b5fSChristophe Leroy #ifdef CONFIG_SMP
20127e23b5fSChristophe Leroy 
20227e23b5fSChristophe Leroy static DEFINE_RAW_SPINLOCK(tlbivax_lock);
20327e23b5fSChristophe Leroy 
20427e23b5fSChristophe Leroy struct tlb_flush_param {
20527e23b5fSChristophe Leroy 	unsigned long addr;
20627e23b5fSChristophe Leroy 	unsigned int pid;
20727e23b5fSChristophe Leroy 	unsigned int tsize;
20827e23b5fSChristophe Leroy 	unsigned int ind;
20927e23b5fSChristophe Leroy };
21027e23b5fSChristophe Leroy 
do_flush_tlb_mm_ipi(void * param)21127e23b5fSChristophe Leroy static void do_flush_tlb_mm_ipi(void *param)
21227e23b5fSChristophe Leroy {
21327e23b5fSChristophe Leroy 	struct tlb_flush_param *p = param;
21427e23b5fSChristophe Leroy 
21527e23b5fSChristophe Leroy 	_tlbil_pid(p ? p->pid : 0);
21627e23b5fSChristophe Leroy }
21727e23b5fSChristophe Leroy 
do_flush_tlb_page_ipi(void * param)21827e23b5fSChristophe Leroy static void do_flush_tlb_page_ipi(void *param)
21927e23b5fSChristophe Leroy {
22027e23b5fSChristophe Leroy 	struct tlb_flush_param *p = param;
22127e23b5fSChristophe Leroy 
22227e23b5fSChristophe Leroy 	_tlbil_va(p->addr, p->pid, p->tsize, p->ind);
22327e23b5fSChristophe Leroy }
22427e23b5fSChristophe Leroy 
22527e23b5fSChristophe Leroy 
22627e23b5fSChristophe Leroy /* Note on invalidations and PID:
22727e23b5fSChristophe Leroy  *
22827e23b5fSChristophe Leroy  * We snapshot the PID with preempt disabled. At this point, it can still
22927e23b5fSChristophe Leroy  * change either because:
23027e23b5fSChristophe Leroy  * - our context is being stolen (PID -> NO_CONTEXT) on another CPU
23127e23b5fSChristophe Leroy  * - we are invaliating some target that isn't currently running here
23227e23b5fSChristophe Leroy  *   and is concurrently acquiring a new PID on another CPU
23327e23b5fSChristophe Leroy  * - some other CPU is re-acquiring a lost PID for this mm
23427e23b5fSChristophe Leroy  * etc...
23527e23b5fSChristophe Leroy  *
23627e23b5fSChristophe Leroy  * However, this shouldn't be a problem as we only guarantee
23727e23b5fSChristophe Leroy  * invalidation of TLB entries present prior to this call, so we
23827e23b5fSChristophe Leroy  * don't care about the PID changing, and invalidating a stale PID
23927e23b5fSChristophe Leroy  * is generally harmless.
24027e23b5fSChristophe Leroy  */
24127e23b5fSChristophe Leroy 
flush_tlb_mm(struct mm_struct * mm)24227e23b5fSChristophe Leroy void flush_tlb_mm(struct mm_struct *mm)
24327e23b5fSChristophe Leroy {
24427e23b5fSChristophe Leroy 	unsigned int pid;
24527e23b5fSChristophe Leroy 
24627e23b5fSChristophe Leroy 	preempt_disable();
24727e23b5fSChristophe Leroy 	pid = mm->context.id;
24827e23b5fSChristophe Leroy 	if (unlikely(pid == MMU_NO_CONTEXT))
24927e23b5fSChristophe Leroy 		goto no_context;
25027e23b5fSChristophe Leroy 	if (!mm_is_core_local(mm)) {
25127e23b5fSChristophe Leroy 		struct tlb_flush_param p = { .pid = pid };
25227e23b5fSChristophe Leroy 		/* Ignores smp_processor_id() even if set. */
25327e23b5fSChristophe Leroy 		smp_call_function_many(mm_cpumask(mm),
25427e23b5fSChristophe Leroy 				       do_flush_tlb_mm_ipi, &p, 1);
25527e23b5fSChristophe Leroy 	}
25627e23b5fSChristophe Leroy 	_tlbil_pid(pid);
25727e23b5fSChristophe Leroy  no_context:
25827e23b5fSChristophe Leroy 	preempt_enable();
25927e23b5fSChristophe Leroy }
26027e23b5fSChristophe Leroy EXPORT_SYMBOL(flush_tlb_mm);
26127e23b5fSChristophe Leroy 
__flush_tlb_page(struct mm_struct * mm,unsigned long vmaddr,int tsize,int ind)26227e23b5fSChristophe Leroy void __flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
26327e23b5fSChristophe Leroy 		      int tsize, int ind)
26427e23b5fSChristophe Leroy {
26527e23b5fSChristophe Leroy 	struct cpumask *cpu_mask;
26627e23b5fSChristophe Leroy 	unsigned int pid;
26727e23b5fSChristophe Leroy 
26827e23b5fSChristophe Leroy 	/*
26927e23b5fSChristophe Leroy 	 * This function as well as __local_flush_tlb_page() must only be called
27027e23b5fSChristophe Leroy 	 * for user contexts.
27127e23b5fSChristophe Leroy 	 */
27227e23b5fSChristophe Leroy 	if (WARN_ON(!mm))
27327e23b5fSChristophe Leroy 		return;
27427e23b5fSChristophe Leroy 
27527e23b5fSChristophe Leroy 	preempt_disable();
27627e23b5fSChristophe Leroy 	pid = mm->context.id;
27727e23b5fSChristophe Leroy 	if (unlikely(pid == MMU_NO_CONTEXT))
27827e23b5fSChristophe Leroy 		goto bail;
27927e23b5fSChristophe Leroy 	cpu_mask = mm_cpumask(mm);
28027e23b5fSChristophe Leroy 	if (!mm_is_core_local(mm)) {
28127e23b5fSChristophe Leroy 		/* If broadcast tlbivax is supported, use it */
28227e23b5fSChristophe Leroy 		if (mmu_has_feature(MMU_FTR_USE_TLBIVAX_BCAST)) {
28327e23b5fSChristophe Leroy 			int lock = mmu_has_feature(MMU_FTR_LOCK_BCAST_INVAL);
28427e23b5fSChristophe Leroy 			if (lock)
28527e23b5fSChristophe Leroy 				raw_spin_lock(&tlbivax_lock);
28627e23b5fSChristophe Leroy 			_tlbivax_bcast(vmaddr, pid, tsize, ind);
28727e23b5fSChristophe Leroy 			if (lock)
28827e23b5fSChristophe Leroy 				raw_spin_unlock(&tlbivax_lock);
28927e23b5fSChristophe Leroy 			goto bail;
29027e23b5fSChristophe Leroy 		} else {
29127e23b5fSChristophe Leroy 			struct tlb_flush_param p = {
29227e23b5fSChristophe Leroy 				.pid = pid,
29327e23b5fSChristophe Leroy 				.addr = vmaddr,
29427e23b5fSChristophe Leroy 				.tsize = tsize,
29527e23b5fSChristophe Leroy 				.ind = ind,
29627e23b5fSChristophe Leroy 			};
29727e23b5fSChristophe Leroy 			/* Ignores smp_processor_id() even if set in cpu_mask */
29827e23b5fSChristophe Leroy 			smp_call_function_many(cpu_mask,
29927e23b5fSChristophe Leroy 					       do_flush_tlb_page_ipi, &p, 1);
30027e23b5fSChristophe Leroy 		}
30127e23b5fSChristophe Leroy 	}
30227e23b5fSChristophe Leroy 	_tlbil_va(vmaddr, pid, tsize, ind);
30327e23b5fSChristophe Leroy  bail:
30427e23b5fSChristophe Leroy 	preempt_enable();
30527e23b5fSChristophe Leroy }
30627e23b5fSChristophe Leroy 
flush_tlb_page(struct vm_area_struct * vma,unsigned long vmaddr)30727e23b5fSChristophe Leroy void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
30827e23b5fSChristophe Leroy {
30927e23b5fSChristophe Leroy #ifdef CONFIG_HUGETLB_PAGE
31027e23b5fSChristophe Leroy 	if (vma && is_vm_hugetlb_page(vma))
31127e23b5fSChristophe Leroy 		flush_hugetlb_page(vma, vmaddr);
31227e23b5fSChristophe Leroy #endif
31327e23b5fSChristophe Leroy 
31427e23b5fSChristophe Leroy 	__flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr,
31527e23b5fSChristophe Leroy 			 mmu_get_tsize(mmu_virtual_psize), 0);
31627e23b5fSChristophe Leroy }
31727e23b5fSChristophe Leroy EXPORT_SYMBOL(flush_tlb_page);
31827e23b5fSChristophe Leroy 
31927e23b5fSChristophe Leroy #endif /* CONFIG_SMP */
32027e23b5fSChristophe Leroy 
32127e23b5fSChristophe Leroy /*
32227e23b5fSChristophe Leroy  * Flush kernel TLB entries in the given range
32327e23b5fSChristophe Leroy  */
3249290c379SChristophe Leroy #ifndef CONFIG_PPC_8xx
flush_tlb_kernel_range(unsigned long start,unsigned long end)32527e23b5fSChristophe Leroy void flush_tlb_kernel_range(unsigned long start, unsigned long end)
32627e23b5fSChristophe Leroy {
32727e23b5fSChristophe Leroy #ifdef CONFIG_SMP
32827e23b5fSChristophe Leroy 	preempt_disable();
32927e23b5fSChristophe Leroy 	smp_call_function(do_flush_tlb_mm_ipi, NULL, 1);
33027e23b5fSChristophe Leroy 	_tlbil_pid(0);
33127e23b5fSChristophe Leroy 	preempt_enable();
33227e23b5fSChristophe Leroy #else
33327e23b5fSChristophe Leroy 	_tlbil_pid(0);
33427e23b5fSChristophe Leroy #endif
33527e23b5fSChristophe Leroy }
33627e23b5fSChristophe Leroy EXPORT_SYMBOL(flush_tlb_kernel_range);
3379290c379SChristophe Leroy #endif
33827e23b5fSChristophe Leroy 
33927e23b5fSChristophe Leroy /*
34027e23b5fSChristophe Leroy  * Currently, for range flushing, we just do a full mm flush. This should
34127e23b5fSChristophe Leroy  * be optimized based on a threshold on the size of the range, since
34227e23b5fSChristophe Leroy  * some implementation can stack multiple tlbivax before a tlbsync but
34327e23b5fSChristophe Leroy  * for now, we keep it that way
34427e23b5fSChristophe Leroy  */
flush_tlb_range(struct vm_area_struct * vma,unsigned long start,unsigned long end)34527e23b5fSChristophe Leroy void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
34627e23b5fSChristophe Leroy 		     unsigned long end)
34727e23b5fSChristophe Leroy 
34827e23b5fSChristophe Leroy {
34927e23b5fSChristophe Leroy 	if (end - start == PAGE_SIZE && !(start & ~PAGE_MASK))
35027e23b5fSChristophe Leroy 		flush_tlb_page(vma, start);
35127e23b5fSChristophe Leroy 	else
35227e23b5fSChristophe Leroy 		flush_tlb_mm(vma->vm_mm);
35327e23b5fSChristophe Leroy }
35427e23b5fSChristophe Leroy EXPORT_SYMBOL(flush_tlb_range);
35527e23b5fSChristophe Leroy 
tlb_flush(struct mmu_gather * tlb)35627e23b5fSChristophe Leroy void tlb_flush(struct mmu_gather *tlb)
35727e23b5fSChristophe Leroy {
35827e23b5fSChristophe Leroy 	flush_tlb_mm(tlb->mm);
35927e23b5fSChristophe Leroy }
36027e23b5fSChristophe Leroy 
36127e23b5fSChristophe Leroy /*
36227e23b5fSChristophe Leroy  * Below are functions specific to the 64-bit variant of Book3E though that
36327e23b5fSChristophe Leroy  * may change in the future
36427e23b5fSChristophe Leroy  */
36527e23b5fSChristophe Leroy 
36627e23b5fSChristophe Leroy #ifdef CONFIG_PPC64
36727e23b5fSChristophe Leroy 
36827e23b5fSChristophe Leroy /*
36927e23b5fSChristophe Leroy  * Handling of virtual linear page tables or indirect TLB entries
37027e23b5fSChristophe Leroy  * flushing when PTE pages are freed
37127e23b5fSChristophe Leroy  */
tlb_flush_pgtable(struct mmu_gather * tlb,unsigned long address)37227e23b5fSChristophe Leroy void tlb_flush_pgtable(struct mmu_gather *tlb, unsigned long address)
37327e23b5fSChristophe Leroy {
37427e23b5fSChristophe Leroy 	int tsize = mmu_psize_defs[mmu_pte_psize].enc;
37527e23b5fSChristophe Leroy 
37627e23b5fSChristophe Leroy 	if (book3e_htw_mode != PPC_HTW_NONE) {
37727e23b5fSChristophe Leroy 		unsigned long start = address & PMD_MASK;
37827e23b5fSChristophe Leroy 		unsigned long end = address + PMD_SIZE;
37927e23b5fSChristophe Leroy 		unsigned long size = 1UL << mmu_psize_defs[mmu_pte_psize].shift;
38027e23b5fSChristophe Leroy 
38127e23b5fSChristophe Leroy 		/* This isn't the most optimal, ideally we would factor out the
38227e23b5fSChristophe Leroy 		 * while preempt & CPU mask mucking around, or even the IPI but
38327e23b5fSChristophe Leroy 		 * it will do for now
38427e23b5fSChristophe Leroy 		 */
38527e23b5fSChristophe Leroy 		while (start < end) {
38627e23b5fSChristophe Leroy 			__flush_tlb_page(tlb->mm, start, tsize, 1);
38727e23b5fSChristophe Leroy 			start += size;
38827e23b5fSChristophe Leroy 		}
38927e23b5fSChristophe Leroy 	} else {
39027e23b5fSChristophe Leroy 		unsigned long rmask = 0xf000000000000000ul;
39127e23b5fSChristophe Leroy 		unsigned long rid = (address & rmask) | 0x1000000000000000ul;
39227e23b5fSChristophe Leroy 		unsigned long vpte = address & ~rmask;
39327e23b5fSChristophe Leroy 
39427e23b5fSChristophe Leroy 		vpte = (vpte >> (PAGE_SHIFT - 3)) & ~0xffful;
39527e23b5fSChristophe Leroy 		vpte |= rid;
39627e23b5fSChristophe Leroy 		__flush_tlb_page(tlb->mm, vpte, tsize, 0);
39727e23b5fSChristophe Leroy 	}
39827e23b5fSChristophe Leroy }
39927e23b5fSChristophe Leroy 
setup_page_sizes(void)400c13f2b2bSNick Child static void __init setup_page_sizes(void)
40127e23b5fSChristophe Leroy {
40227e23b5fSChristophe Leroy 	unsigned int tlb0cfg;
40327e23b5fSChristophe Leroy 	unsigned int tlb0ps;
40427e23b5fSChristophe Leroy 	unsigned int eptcfg;
40527e23b5fSChristophe Leroy 	int i, psize;
40627e23b5fSChristophe Leroy 
4073e731858SChristophe Leroy #ifdef CONFIG_PPC_E500
40827e23b5fSChristophe Leroy 	unsigned int mmucfg = mfspr(SPRN_MMUCFG);
40927e23b5fSChristophe Leroy 	int fsl_mmu = mmu_has_feature(MMU_FTR_TYPE_FSL_E);
41027e23b5fSChristophe Leroy 
41127e23b5fSChristophe Leroy 	if (fsl_mmu && (mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V1) {
41227e23b5fSChristophe Leroy 		unsigned int tlb1cfg = mfspr(SPRN_TLB1CFG);
41327e23b5fSChristophe Leroy 		unsigned int min_pg, max_pg;
41427e23b5fSChristophe Leroy 
41527e23b5fSChristophe Leroy 		min_pg = (tlb1cfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT;
41627e23b5fSChristophe Leroy 		max_pg = (tlb1cfg & TLBnCFG_MAXSIZE) >> TLBnCFG_MAXSIZE_SHIFT;
41727e23b5fSChristophe Leroy 
41827e23b5fSChristophe Leroy 		for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
41927e23b5fSChristophe Leroy 			struct mmu_psize_def *def;
42027e23b5fSChristophe Leroy 			unsigned int shift;
42127e23b5fSChristophe Leroy 
42227e23b5fSChristophe Leroy 			def = &mmu_psize_defs[psize];
42327e23b5fSChristophe Leroy 			shift = def->shift;
42427e23b5fSChristophe Leroy 
42527e23b5fSChristophe Leroy 			if (shift == 0 || shift & 1)
42627e23b5fSChristophe Leroy 				continue;
42727e23b5fSChristophe Leroy 
42827e23b5fSChristophe Leroy 			/* adjust to be in terms of 4^shift Kb */
42927e23b5fSChristophe Leroy 			shift = (shift - 10) >> 1;
43027e23b5fSChristophe Leroy 
43127e23b5fSChristophe Leroy 			if ((shift >= min_pg) && (shift <= max_pg))
43227e23b5fSChristophe Leroy 				def->flags |= MMU_PAGE_SIZE_DIRECT;
43327e23b5fSChristophe Leroy 		}
43427e23b5fSChristophe Leroy 
43527e23b5fSChristophe Leroy 		goto out;
43627e23b5fSChristophe Leroy 	}
43727e23b5fSChristophe Leroy 
43827e23b5fSChristophe Leroy 	if (fsl_mmu && (mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V2) {
43927e23b5fSChristophe Leroy 		u32 tlb1cfg, tlb1ps;
44027e23b5fSChristophe Leroy 
44127e23b5fSChristophe Leroy 		tlb0cfg = mfspr(SPRN_TLB0CFG);
44227e23b5fSChristophe Leroy 		tlb1cfg = mfspr(SPRN_TLB1CFG);
44327e23b5fSChristophe Leroy 		tlb1ps = mfspr(SPRN_TLB1PS);
44427e23b5fSChristophe Leroy 		eptcfg = mfspr(SPRN_EPTCFG);
44527e23b5fSChristophe Leroy 
44627e23b5fSChristophe Leroy 		if ((tlb1cfg & TLBnCFG_IND) && (tlb0cfg & TLBnCFG_PT))
44727e23b5fSChristophe Leroy 			book3e_htw_mode = PPC_HTW_E6500;
44827e23b5fSChristophe Leroy 
44927e23b5fSChristophe Leroy 		/*
45027e23b5fSChristophe Leroy 		 * We expect 4K subpage size and unrestricted indirect size.
45127e23b5fSChristophe Leroy 		 * The lack of a restriction on indirect size is a Freescale
45227e23b5fSChristophe Leroy 		 * extension, indicated by PSn = 0 but SPSn != 0.
45327e23b5fSChristophe Leroy 		 */
45427e23b5fSChristophe Leroy 		if (eptcfg != 2)
45527e23b5fSChristophe Leroy 			book3e_htw_mode = PPC_HTW_NONE;
45627e23b5fSChristophe Leroy 
45727e23b5fSChristophe Leroy 		for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
45827e23b5fSChristophe Leroy 			struct mmu_psize_def *def = &mmu_psize_defs[psize];
45927e23b5fSChristophe Leroy 
46027e23b5fSChristophe Leroy 			if (!def->shift)
46127e23b5fSChristophe Leroy 				continue;
46227e23b5fSChristophe Leroy 
46327e23b5fSChristophe Leroy 			if (tlb1ps & (1U << (def->shift - 10))) {
46427e23b5fSChristophe Leroy 				def->flags |= MMU_PAGE_SIZE_DIRECT;
46527e23b5fSChristophe Leroy 
46627e23b5fSChristophe Leroy 				if (book3e_htw_mode && psize == MMU_PAGE_2M)
46727e23b5fSChristophe Leroy 					def->flags |= MMU_PAGE_SIZE_INDIRECT;
46827e23b5fSChristophe Leroy 			}
46927e23b5fSChristophe Leroy 		}
47027e23b5fSChristophe Leroy 
47127e23b5fSChristophe Leroy 		goto out;
47227e23b5fSChristophe Leroy 	}
47327e23b5fSChristophe Leroy #endif
47427e23b5fSChristophe Leroy 
47527e23b5fSChristophe Leroy 	tlb0cfg = mfspr(SPRN_TLB0CFG);
47627e23b5fSChristophe Leroy 	tlb0ps = mfspr(SPRN_TLB0PS);
47727e23b5fSChristophe Leroy 	eptcfg = mfspr(SPRN_EPTCFG);
47827e23b5fSChristophe Leroy 
47927e23b5fSChristophe Leroy 	/* Look for supported direct sizes */
48027e23b5fSChristophe Leroy 	for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
48127e23b5fSChristophe Leroy 		struct mmu_psize_def *def = &mmu_psize_defs[psize];
48227e23b5fSChristophe Leroy 
48327e23b5fSChristophe Leroy 		if (tlb0ps & (1U << (def->shift - 10)))
48427e23b5fSChristophe Leroy 			def->flags |= MMU_PAGE_SIZE_DIRECT;
48527e23b5fSChristophe Leroy 	}
48627e23b5fSChristophe Leroy 
48727e23b5fSChristophe Leroy 	/* Indirect page sizes supported ? */
48827e23b5fSChristophe Leroy 	if ((tlb0cfg & TLBnCFG_IND) == 0 ||
48927e23b5fSChristophe Leroy 	    (tlb0cfg & TLBnCFG_PT) == 0)
49027e23b5fSChristophe Leroy 		goto out;
49127e23b5fSChristophe Leroy 
49227e23b5fSChristophe Leroy 	book3e_htw_mode = PPC_HTW_IBM;
49327e23b5fSChristophe Leroy 
49427e23b5fSChristophe Leroy 	/* Now, we only deal with one IND page size for each
49527e23b5fSChristophe Leroy 	 * direct size. Hopefully all implementations today are
49627e23b5fSChristophe Leroy 	 * unambiguous, but we might want to be careful in the
49727e23b5fSChristophe Leroy 	 * future.
49827e23b5fSChristophe Leroy 	 */
49927e23b5fSChristophe Leroy 	for (i = 0; i < 3; i++) {
50027e23b5fSChristophe Leroy 		unsigned int ps, sps;
50127e23b5fSChristophe Leroy 
50227e23b5fSChristophe Leroy 		sps = eptcfg & 0x1f;
50327e23b5fSChristophe Leroy 		eptcfg >>= 5;
50427e23b5fSChristophe Leroy 		ps = eptcfg & 0x1f;
50527e23b5fSChristophe Leroy 		eptcfg >>= 5;
50627e23b5fSChristophe Leroy 		if (!ps || !sps)
50727e23b5fSChristophe Leroy 			continue;
50827e23b5fSChristophe Leroy 		for (psize = 0; psize < MMU_PAGE_COUNT; psize++) {
50927e23b5fSChristophe Leroy 			struct mmu_psize_def *def = &mmu_psize_defs[psize];
51027e23b5fSChristophe Leroy 
51127e23b5fSChristophe Leroy 			if (ps == (def->shift - 10))
51227e23b5fSChristophe Leroy 				def->flags |= MMU_PAGE_SIZE_INDIRECT;
51327e23b5fSChristophe Leroy 			if (sps == (def->shift - 10))
51427e23b5fSChristophe Leroy 				def->ind = ps + 10;
51527e23b5fSChristophe Leroy 		}
51627e23b5fSChristophe Leroy 	}
51727e23b5fSChristophe Leroy 
51827e23b5fSChristophe Leroy out:
51927e23b5fSChristophe Leroy 	/* Cleanup array and print summary */
52027e23b5fSChristophe Leroy 	pr_info("MMU: Supported page sizes\n");
52127e23b5fSChristophe Leroy 	for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
52227e23b5fSChristophe Leroy 		struct mmu_psize_def *def = &mmu_psize_defs[psize];
52327e23b5fSChristophe Leroy 		const char *__page_type_names[] = {
52427e23b5fSChristophe Leroy 			"unsupported",
52527e23b5fSChristophe Leroy 			"direct",
52627e23b5fSChristophe Leroy 			"indirect",
52727e23b5fSChristophe Leroy 			"direct & indirect"
52827e23b5fSChristophe Leroy 		};
52927e23b5fSChristophe Leroy 		if (def->flags == 0) {
53027e23b5fSChristophe Leroy 			def->shift = 0;
53127e23b5fSChristophe Leroy 			continue;
53227e23b5fSChristophe Leroy 		}
53327e23b5fSChristophe Leroy 		pr_info("  %8ld KB as %s\n", 1ul << (def->shift - 10),
53427e23b5fSChristophe Leroy 			__page_type_names[def->flags & 0x3]);
53527e23b5fSChristophe Leroy 	}
53627e23b5fSChristophe Leroy }
53727e23b5fSChristophe Leroy 
setup_mmu_htw(void)538c13f2b2bSNick Child static void __init setup_mmu_htw(void)
53927e23b5fSChristophe Leroy {
54027e23b5fSChristophe Leroy 	/*
54127e23b5fSChristophe Leroy 	 * If we want to use HW tablewalk, enable it by patching the TLB miss
54227e23b5fSChristophe Leroy 	 * handlers to branch to the one dedicated to it.
54327e23b5fSChristophe Leroy 	 */
54427e23b5fSChristophe Leroy 
54527e23b5fSChristophe Leroy 	switch (book3e_htw_mode) {
54627e23b5fSChristophe Leroy 	case PPC_HTW_IBM:
54727e23b5fSChristophe Leroy 		patch_exception(0x1c0, exc_data_tlb_miss_htw_book3e);
54827e23b5fSChristophe Leroy 		patch_exception(0x1e0, exc_instruction_tlb_miss_htw_book3e);
54927e23b5fSChristophe Leroy 		break;
5503e731858SChristophe Leroy #ifdef CONFIG_PPC_E500
55127e23b5fSChristophe Leroy 	case PPC_HTW_E6500:
55227e23b5fSChristophe Leroy 		extlb_level_exc = EX_TLB_SIZE;
55327e23b5fSChristophe Leroy 		patch_exception(0x1c0, exc_data_tlb_miss_e6500_book3e);
55427e23b5fSChristophe Leroy 		patch_exception(0x1e0, exc_instruction_tlb_miss_e6500_book3e);
55527e23b5fSChristophe Leroy 		break;
55627e23b5fSChristophe Leroy #endif
55727e23b5fSChristophe Leroy 	}
55827e23b5fSChristophe Leroy 	pr_info("MMU: Book3E HW tablewalk %s\n",
55927e23b5fSChristophe Leroy 		book3e_htw_mode != PPC_HTW_NONE ? "enabled" : "not supported");
56027e23b5fSChristophe Leroy }
56127e23b5fSChristophe Leroy 
56227e23b5fSChristophe Leroy /*
56327e23b5fSChristophe Leroy  * Early initialization of the MMU TLB code
56427e23b5fSChristophe Leroy  */
early_init_this_mmu(void)56527e23b5fSChristophe Leroy static void early_init_this_mmu(void)
56627e23b5fSChristophe Leroy {
56727e23b5fSChristophe Leroy 	unsigned int mas4;
56827e23b5fSChristophe Leroy 
56927e23b5fSChristophe Leroy 	/* Set MAS4 based on page table setting */
57027e23b5fSChristophe Leroy 
57127e23b5fSChristophe Leroy 	mas4 = 0x4 << MAS4_WIMGED_SHIFT;
57227e23b5fSChristophe Leroy 	switch (book3e_htw_mode) {
57327e23b5fSChristophe Leroy 	case PPC_HTW_E6500:
57427e23b5fSChristophe Leroy 		mas4 |= MAS4_INDD;
57527e23b5fSChristophe Leroy 		mas4 |= BOOK3E_PAGESZ_2M << MAS4_TSIZED_SHIFT;
57627e23b5fSChristophe Leroy 		mas4 |= MAS4_TLBSELD(1);
57727e23b5fSChristophe Leroy 		mmu_pte_psize = MMU_PAGE_2M;
57827e23b5fSChristophe Leroy 		break;
57927e23b5fSChristophe Leroy 
58027e23b5fSChristophe Leroy 	case PPC_HTW_IBM:
58127e23b5fSChristophe Leroy 		mas4 |= MAS4_INDD;
58227e23b5fSChristophe Leroy 		mas4 |=	BOOK3E_PAGESZ_1M << MAS4_TSIZED_SHIFT;
58327e23b5fSChristophe Leroy 		mmu_pte_psize = MMU_PAGE_1M;
58427e23b5fSChristophe Leroy 		break;
58527e23b5fSChristophe Leroy 
58627e23b5fSChristophe Leroy 	case PPC_HTW_NONE:
58727e23b5fSChristophe Leroy 		mas4 |=	BOOK3E_PAGESZ_4K << MAS4_TSIZED_SHIFT;
58827e23b5fSChristophe Leroy 		mmu_pte_psize = mmu_virtual_psize;
58927e23b5fSChristophe Leroy 		break;
59027e23b5fSChristophe Leroy 	}
59127e23b5fSChristophe Leroy 	mtspr(SPRN_MAS4, mas4);
59227e23b5fSChristophe Leroy 
5933e731858SChristophe Leroy #ifdef CONFIG_PPC_E500
59427e23b5fSChristophe Leroy 	if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
59527e23b5fSChristophe Leroy 		unsigned int num_cams;
59627e23b5fSChristophe Leroy 		bool map = true;
59727e23b5fSChristophe Leroy 
59827e23b5fSChristophe Leroy 		/* use a quarter of the TLBCAM for bolted linear map */
59927e23b5fSChristophe Leroy 		num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4;
60027e23b5fSChristophe Leroy 
60127e23b5fSChristophe Leroy 		/*
60227e23b5fSChristophe Leroy 		 * Only do the mapping once per core, or else the
60327e23b5fSChristophe Leroy 		 * transient mapping would cause problems.
60427e23b5fSChristophe Leroy 		 */
60527e23b5fSChristophe Leroy #ifdef CONFIG_SMP
60627e23b5fSChristophe Leroy 		if (hweight32(get_tensr()) > 1)
60727e23b5fSChristophe Leroy 			map = false;
60827e23b5fSChristophe Leroy #endif
60927e23b5fSChristophe Leroy 
61027e23b5fSChristophe Leroy 		if (map)
61127e23b5fSChristophe Leroy 			linear_map_top = map_mem_in_cams(linear_map_top,
6125b548609SChristophe Leroy 							 num_cams, false, true);
61327e23b5fSChristophe Leroy 	}
61427e23b5fSChristophe Leroy #endif
61527e23b5fSChristophe Leroy 
61627e23b5fSChristophe Leroy 	/* A sync won't hurt us after mucking around with
61727e23b5fSChristophe Leroy 	 * the MMU configuration
61827e23b5fSChristophe Leroy 	 */
61927e23b5fSChristophe Leroy 	mb();
62027e23b5fSChristophe Leroy }
62127e23b5fSChristophe Leroy 
early_init_mmu_global(void)62227e23b5fSChristophe Leroy static void __init early_init_mmu_global(void)
62327e23b5fSChristophe Leroy {
62427e23b5fSChristophe Leroy 	/* XXX This should be decided at runtime based on supported
62527e23b5fSChristophe Leroy 	 * page sizes in the TLB, but for now let's assume 16M is
62627e23b5fSChristophe Leroy 	 * always there and a good fit (which it probably is)
62727e23b5fSChristophe Leroy 	 *
62827e23b5fSChristophe Leroy 	 * Freescale booke only supports 4K pages in TLB0, so use that.
62927e23b5fSChristophe Leroy 	 */
63027e23b5fSChristophe Leroy 	if (mmu_has_feature(MMU_FTR_TYPE_FSL_E))
63127e23b5fSChristophe Leroy 		mmu_vmemmap_psize = MMU_PAGE_4K;
63227e23b5fSChristophe Leroy 	else
63327e23b5fSChristophe Leroy 		mmu_vmemmap_psize = MMU_PAGE_16M;
63427e23b5fSChristophe Leroy 
63527e23b5fSChristophe Leroy 	/* XXX This code only checks for TLB 0 capabilities and doesn't
63627e23b5fSChristophe Leroy 	 *     check what page size combos are supported by the HW. It
63727e23b5fSChristophe Leroy 	 *     also doesn't handle the case where a separate array holds
63827e23b5fSChristophe Leroy 	 *     the IND entries from the array loaded by the PT.
63927e23b5fSChristophe Leroy 	 */
64027e23b5fSChristophe Leroy 	/* Look for supported page sizes */
64127e23b5fSChristophe Leroy 	setup_page_sizes();
64227e23b5fSChristophe Leroy 
64327e23b5fSChristophe Leroy 	/* Look for HW tablewalk support */
64427e23b5fSChristophe Leroy 	setup_mmu_htw();
64527e23b5fSChristophe Leroy 
6463e731858SChristophe Leroy #ifdef CONFIG_PPC_E500
64727e23b5fSChristophe Leroy 	if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
64827e23b5fSChristophe Leroy 		if (book3e_htw_mode == PPC_HTW_NONE) {
64927e23b5fSChristophe Leroy 			extlb_level_exc = EX_TLB_SIZE;
65027e23b5fSChristophe Leroy 			patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e);
65127e23b5fSChristophe Leroy 			patch_exception(0x1e0,
65227e23b5fSChristophe Leroy 				exc_instruction_tlb_miss_bolted_book3e);
65327e23b5fSChristophe Leroy 		}
65427e23b5fSChristophe Leroy 	}
65527e23b5fSChristophe Leroy #endif
65627e23b5fSChristophe Leroy 
65727e23b5fSChristophe Leroy 	/* Set the global containing the top of the linear mapping
65827e23b5fSChristophe Leroy 	 * for use by the TLB miss code
65927e23b5fSChristophe Leroy 	 */
66027e23b5fSChristophe Leroy 	linear_map_top = memblock_end_of_DRAM();
6617cd9b317SChristophe Leroy 
6627cd9b317SChristophe Leroy 	ioremap_bot = IOREMAP_BASE;
66327e23b5fSChristophe Leroy }
66427e23b5fSChristophe Leroy 
early_mmu_set_memory_limit(void)66527e23b5fSChristophe Leroy static void __init early_mmu_set_memory_limit(void)
66627e23b5fSChristophe Leroy {
6673e731858SChristophe Leroy #ifdef CONFIG_PPC_E500
66827e23b5fSChristophe Leroy 	if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
66927e23b5fSChristophe Leroy 		/*
67027e23b5fSChristophe Leroy 		 * Limit memory so we dont have linear faults.
67127e23b5fSChristophe Leroy 		 * Unlike memblock_set_current_limit, which limits
67227e23b5fSChristophe Leroy 		 * memory available during early boot, this permanently
67327e23b5fSChristophe Leroy 		 * reduces the memory available to Linux.  We need to
67427e23b5fSChristophe Leroy 		 * do this because highmem is not supported on 64-bit.
67527e23b5fSChristophe Leroy 		 */
67627e23b5fSChristophe Leroy 		memblock_enforce_memory_limit(linear_map_top);
67727e23b5fSChristophe Leroy 	}
67827e23b5fSChristophe Leroy #endif
67927e23b5fSChristophe Leroy 
68027e23b5fSChristophe Leroy 	memblock_set_current_limit(linear_map_top);
68127e23b5fSChristophe Leroy }
68227e23b5fSChristophe Leroy 
68327e23b5fSChristophe Leroy /* boot cpu only */
early_init_mmu(void)68427e23b5fSChristophe Leroy void __init early_init_mmu(void)
68527e23b5fSChristophe Leroy {
68627e23b5fSChristophe Leroy 	early_init_mmu_global();
68727e23b5fSChristophe Leroy 	early_init_this_mmu();
68827e23b5fSChristophe Leroy 	early_mmu_set_memory_limit();
68927e23b5fSChristophe Leroy }
69027e23b5fSChristophe Leroy 
early_init_mmu_secondary(void)69127e23b5fSChristophe Leroy void early_init_mmu_secondary(void)
69227e23b5fSChristophe Leroy {
69327e23b5fSChristophe Leroy 	early_init_this_mmu();
69427e23b5fSChristophe Leroy }
69527e23b5fSChristophe Leroy 
setup_initial_memory_limit(phys_addr_t first_memblock_base,phys_addr_t first_memblock_size)69627e23b5fSChristophe Leroy void setup_initial_memory_limit(phys_addr_t first_memblock_base,
69727e23b5fSChristophe Leroy 				phys_addr_t first_memblock_size)
69827e23b5fSChristophe Leroy {
69927e23b5fSChristophe Leroy 	/* On non-FSL Embedded 64-bit, we adjust the RMA size to match
70027e23b5fSChristophe Leroy 	 * the bolted TLB entry. We know for now that only 1G
70127e23b5fSChristophe Leroy 	 * entries are supported though that may eventually
70227e23b5fSChristophe Leroy 	 * change.
70327e23b5fSChristophe Leroy 	 *
70427e23b5fSChristophe Leroy 	 * on FSL Embedded 64-bit, usually all RAM is bolted, but with
70527e23b5fSChristophe Leroy 	 * unusual memory sizes it's possible for some RAM to not be mapped
70627e23b5fSChristophe Leroy 	 * (such RAM is not used at all by Linux, since we don't support
70727e23b5fSChristophe Leroy 	 * highmem on 64-bit).  We limit ppc64_rma_size to what would be
70827e23b5fSChristophe Leroy 	 * mappable if this memblock is the only one.  Additional memblocks
70927e23b5fSChristophe Leroy 	 * can only increase, not decrease, the amount that ends up getting
71027e23b5fSChristophe Leroy 	 * mapped.  We still limit max to 1G even if we'll eventually map
71127e23b5fSChristophe Leroy 	 * more.  This is due to what the early init code is set up to do.
71227e23b5fSChristophe Leroy 	 *
71327e23b5fSChristophe Leroy 	 * We crop it to the size of the first MEMBLOCK to
71427e23b5fSChristophe Leroy 	 * avoid going over total available memory just in case...
71527e23b5fSChristophe Leroy 	 */
7163e731858SChristophe Leroy #ifdef CONFIG_PPC_E500
71727e23b5fSChristophe Leroy 	if (early_mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
71827e23b5fSChristophe Leroy 		unsigned long linear_sz;
71927e23b5fSChristophe Leroy 		unsigned int num_cams;
72027e23b5fSChristophe Leroy 
72127e23b5fSChristophe Leroy 		/* use a quarter of the TLBCAM for bolted linear map */
72227e23b5fSChristophe Leroy 		num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4;
72327e23b5fSChristophe Leroy 
72427e23b5fSChristophe Leroy 		linear_sz = map_mem_in_cams(first_memblock_size, num_cams,
7255b548609SChristophe Leroy 					    true, true);
72627e23b5fSChristophe Leroy 
72727e23b5fSChristophe Leroy 		ppc64_rma_size = min_t(u64, linear_sz, 0x40000000);
72827e23b5fSChristophe Leroy 	} else
72927e23b5fSChristophe Leroy #endif
73027e23b5fSChristophe Leroy 		ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
73127e23b5fSChristophe Leroy 
73227e23b5fSChristophe Leroy 	/* Finally limit subsequent allocations */
73327e23b5fSChristophe Leroy 	memblock_set_current_limit(first_memblock_base + ppc64_rma_size);
73427e23b5fSChristophe Leroy }
73527e23b5fSChristophe Leroy #else /* ! CONFIG_PPC64 */
early_init_mmu(void)73627e23b5fSChristophe Leroy void __init early_init_mmu(void)
73727e23b5fSChristophe Leroy {
738*ed05c71aSChristophe Leroy 	unsigned long root = of_get_flat_dt_root();
739*ed05c71aSChristophe Leroy 
740*ed05c71aSChristophe Leroy 	if (IS_ENABLED(CONFIG_PPC_47x) && IS_ENABLED(CONFIG_SMP) &&
741*ed05c71aSChristophe Leroy 	    of_get_flat_dt_prop(root, "cooperative-partition", NULL))
742*ed05c71aSChristophe Leroy 		mmu_clear_feature(MMU_FTR_USE_TLBIVAX_BCAST);
74327e23b5fSChristophe Leroy }
74427e23b5fSChristophe Leroy #endif /* CONFIG_PPC64 */
745