162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * This file contains the routines for TLB flushing. 462306a36Sopenharmony_ci * On machines where the MMU does not use a hash table to store virtual to 562306a36Sopenharmony_ci * physical translations (ie, SW loaded TLBs or Book3E compilant processors, 662306a36Sopenharmony_ci * this does -not- include 603 however which shares the implementation with 762306a36Sopenharmony_ci * hash based processors) 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * -- BenH 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Copyright 2008,2009 Ben Herrenschmidt <benh@kernel.crashing.org> 1262306a36Sopenharmony_ci * IBM Corp. 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * Derived from arch/ppc/mm/init.c: 1562306a36Sopenharmony_ci * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) 1862306a36Sopenharmony_ci * and Cort Dougan (PReP) (cort@cs.nmt.edu) 1962306a36Sopenharmony_ci * Copyright (C) 1996 Paul Mackerras 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * Derived from "arch/i386/mm/init.c" 2262306a36Sopenharmony_ci * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds 2362306a36Sopenharmony_ci */ 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include <linux/kernel.h> 2662306a36Sopenharmony_ci#include <linux/export.h> 2762306a36Sopenharmony_ci#include <linux/mm.h> 2862306a36Sopenharmony_ci#include <linux/init.h> 2962306a36Sopenharmony_ci#include <linux/highmem.h> 3062306a36Sopenharmony_ci#include <linux/pagemap.h> 3162306a36Sopenharmony_ci#include <linux/preempt.h> 3262306a36Sopenharmony_ci#include <linux/spinlock.h> 3362306a36Sopenharmony_ci#include <linux/memblock.h> 3462306a36Sopenharmony_ci#include <linux/of_fdt.h> 3562306a36Sopenharmony_ci#include <linux/hugetlb.h> 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#include <asm/pgalloc.h> 3862306a36Sopenharmony_ci#include <asm/tlbflush.h> 3962306a36Sopenharmony_ci#include <asm/tlb.h> 4062306a36Sopenharmony_ci#include <asm/code-patching.h> 4162306a36Sopenharmony_ci#include <asm/cputhreads.h> 4262306a36Sopenharmony_ci#include <asm/hugetlb.h> 4362306a36Sopenharmony_ci#include <asm/paca.h> 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#include <mm/mmu_decl.h> 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/* 4862306a36Sopenharmony_ci * This struct lists the sw-supported page sizes. The hardawre MMU may support 4962306a36Sopenharmony_ci * other sizes not listed here. The .ind field is only used on MMUs that have 5062306a36Sopenharmony_ci * indirect page table entries. 5162306a36Sopenharmony_ci */ 5262306a36Sopenharmony_ci#ifdef CONFIG_PPC_E500 5362306a36Sopenharmony_cistruct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = { 5462306a36Sopenharmony_ci [MMU_PAGE_4K] = { 5562306a36Sopenharmony_ci .shift = 12, 5662306a36Sopenharmony_ci .enc = BOOK3E_PAGESZ_4K, 5762306a36Sopenharmony_ci }, 5862306a36Sopenharmony_ci [MMU_PAGE_2M] = { 5962306a36Sopenharmony_ci .shift = 21, 6062306a36Sopenharmony_ci .enc = BOOK3E_PAGESZ_2M, 6162306a36Sopenharmony_ci }, 6262306a36Sopenharmony_ci [MMU_PAGE_4M] = { 6362306a36Sopenharmony_ci .shift = 22, 6462306a36Sopenharmony_ci .enc = BOOK3E_PAGESZ_4M, 6562306a36Sopenharmony_ci }, 6662306a36Sopenharmony_ci [MMU_PAGE_16M] = { 6762306a36Sopenharmony_ci .shift = 24, 6862306a36Sopenharmony_ci .enc = BOOK3E_PAGESZ_16M, 6962306a36Sopenharmony_ci }, 7062306a36Sopenharmony_ci [MMU_PAGE_64M] = { 7162306a36Sopenharmony_ci .shift = 26, 7262306a36Sopenharmony_ci .enc = BOOK3E_PAGESZ_64M, 7362306a36Sopenharmony_ci }, 7462306a36Sopenharmony_ci [MMU_PAGE_256M] = { 7562306a36Sopenharmony_ci .shift = 28, 7662306a36Sopenharmony_ci .enc = BOOK3E_PAGESZ_256M, 7762306a36Sopenharmony_ci }, 7862306a36Sopenharmony_ci [MMU_PAGE_1G] = { 7962306a36Sopenharmony_ci .shift = 30, 8062306a36Sopenharmony_ci .enc = BOOK3E_PAGESZ_1GB, 8162306a36Sopenharmony_ci }, 8262306a36Sopenharmony_ci}; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic inline int mmu_get_tsize(int psize) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci return mmu_psize_defs[psize].enc; 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci#else 8962306a36Sopenharmony_cistatic inline int mmu_get_tsize(int psize) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci /* This isn't used on !Book3E for now */ 9262306a36Sopenharmony_ci return 0; 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci#endif 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci#ifdef CONFIG_PPC_8xx 9762306a36Sopenharmony_cistruct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = { 9862306a36Sopenharmony_ci [MMU_PAGE_4K] = { 9962306a36Sopenharmony_ci .shift = 12, 10062306a36Sopenharmony_ci }, 10162306a36Sopenharmony_ci [MMU_PAGE_16K] = { 10262306a36Sopenharmony_ci .shift = 14, 10362306a36Sopenharmony_ci }, 10462306a36Sopenharmony_ci [MMU_PAGE_512K] = { 10562306a36Sopenharmony_ci .shift = 19, 10662306a36Sopenharmony_ci }, 10762306a36Sopenharmony_ci [MMU_PAGE_8M] = { 10862306a36Sopenharmony_ci .shift = 23, 10962306a36Sopenharmony_ci }, 11062306a36Sopenharmony_ci}; 11162306a36Sopenharmony_ci#endif 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci/* The variables below are currently only used on 64-bit Book3E 11462306a36Sopenharmony_ci * though this will probably be made common with other nohash 11562306a36Sopenharmony_ci * implementations at some point 11662306a36Sopenharmony_ci */ 11762306a36Sopenharmony_ci#ifdef CONFIG_PPC64 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ciint mmu_pte_psize; /* Page size used for PTE pages */ 12062306a36Sopenharmony_ciint mmu_vmemmap_psize; /* Page size used for the virtual mem map */ 12162306a36Sopenharmony_ciint book3e_htw_mode; /* HW tablewalk? Value is PPC_HTW_* */ 12262306a36Sopenharmony_ciunsigned long linear_map_top; /* Top of linear mapping */ 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci/* 12662306a36Sopenharmony_ci * Number of bytes to add to SPRN_SPRG_TLB_EXFRAME on crit/mcheck/debug 12762306a36Sopenharmony_ci * exceptions. This is used for bolted and e6500 TLB miss handlers which 12862306a36Sopenharmony_ci * do not modify this SPRG in the TLB miss code; for other TLB miss handlers, 12962306a36Sopenharmony_ci * this is set to zero. 13062306a36Sopenharmony_ci */ 13162306a36Sopenharmony_ciint extlb_level_exc; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci#endif /* CONFIG_PPC64 */ 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci#ifdef CONFIG_PPC_E500 13662306a36Sopenharmony_ci/* next_tlbcam_idx is used to round-robin tlbcam entry assignment */ 13762306a36Sopenharmony_ciDEFINE_PER_CPU(int, next_tlbcam_idx); 13862306a36Sopenharmony_ciEXPORT_PER_CPU_SYMBOL(next_tlbcam_idx); 13962306a36Sopenharmony_ci#endif 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci/* 14262306a36Sopenharmony_ci * Base TLB flushing operations: 14362306a36Sopenharmony_ci * 14462306a36Sopenharmony_ci * - flush_tlb_mm(mm) flushes the specified mm context TLB's 14562306a36Sopenharmony_ci * - flush_tlb_page(vma, vmaddr) flushes one page 14662306a36Sopenharmony_ci * - flush_tlb_range(vma, start, end) flushes a range of pages 14762306a36Sopenharmony_ci * - flush_tlb_kernel_range(start, end) flushes kernel pages 14862306a36Sopenharmony_ci * 14962306a36Sopenharmony_ci * - local_* variants of page and mm only apply to the current 15062306a36Sopenharmony_ci * processor 15162306a36Sopenharmony_ci */ 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci#ifndef CONFIG_PPC_8xx 15462306a36Sopenharmony_ci/* 15562306a36Sopenharmony_ci * These are the base non-SMP variants of page and mm flushing 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_civoid local_flush_tlb_mm(struct mm_struct *mm) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci unsigned int pid; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci preempt_disable(); 16262306a36Sopenharmony_ci pid = mm->context.id; 16362306a36Sopenharmony_ci if (pid != MMU_NO_CONTEXT) 16462306a36Sopenharmony_ci _tlbil_pid(pid); 16562306a36Sopenharmony_ci preempt_enable(); 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ciEXPORT_SYMBOL(local_flush_tlb_mm); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_civoid __local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, 17062306a36Sopenharmony_ci int tsize, int ind) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci unsigned int pid; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci preempt_disable(); 17562306a36Sopenharmony_ci pid = mm ? mm->context.id : 0; 17662306a36Sopenharmony_ci if (pid != MMU_NO_CONTEXT) 17762306a36Sopenharmony_ci _tlbil_va(vmaddr, pid, tsize, ind); 17862306a36Sopenharmony_ci preempt_enable(); 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_civoid local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci __local_flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr, 18462306a36Sopenharmony_ci mmu_get_tsize(mmu_virtual_psize), 0); 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ciEXPORT_SYMBOL(local_flush_tlb_page); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_civoid local_flush_tlb_page_psize(struct mm_struct *mm, 18962306a36Sopenharmony_ci unsigned long vmaddr, int psize) 19062306a36Sopenharmony_ci{ 19162306a36Sopenharmony_ci __local_flush_tlb_page(mm, vmaddr, mmu_get_tsize(psize), 0); 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ciEXPORT_SYMBOL(local_flush_tlb_page_psize); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci#endif 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci/* 19862306a36Sopenharmony_ci * And here are the SMP non-local implementations 19962306a36Sopenharmony_ci */ 20062306a36Sopenharmony_ci#ifdef CONFIG_SMP 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_cistatic DEFINE_RAW_SPINLOCK(tlbivax_lock); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistruct tlb_flush_param { 20562306a36Sopenharmony_ci unsigned long addr; 20662306a36Sopenharmony_ci unsigned int pid; 20762306a36Sopenharmony_ci unsigned int tsize; 20862306a36Sopenharmony_ci unsigned int ind; 20962306a36Sopenharmony_ci}; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic void do_flush_tlb_mm_ipi(void *param) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci struct tlb_flush_param *p = param; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci _tlbil_pid(p ? p->pid : 0); 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_cistatic void do_flush_tlb_page_ipi(void *param) 21962306a36Sopenharmony_ci{ 22062306a36Sopenharmony_ci struct tlb_flush_param *p = param; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci _tlbil_va(p->addr, p->pid, p->tsize, p->ind); 22362306a36Sopenharmony_ci} 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci/* Note on invalidations and PID: 22762306a36Sopenharmony_ci * 22862306a36Sopenharmony_ci * We snapshot the PID with preempt disabled. At this point, it can still 22962306a36Sopenharmony_ci * change either because: 23062306a36Sopenharmony_ci * - our context is being stolen (PID -> NO_CONTEXT) on another CPU 23162306a36Sopenharmony_ci * - we are invaliating some target that isn't currently running here 23262306a36Sopenharmony_ci * and is concurrently acquiring a new PID on another CPU 23362306a36Sopenharmony_ci * - some other CPU is re-acquiring a lost PID for this mm 23462306a36Sopenharmony_ci * etc... 23562306a36Sopenharmony_ci * 23662306a36Sopenharmony_ci * However, this shouldn't be a problem as we only guarantee 23762306a36Sopenharmony_ci * invalidation of TLB entries present prior to this call, so we 23862306a36Sopenharmony_ci * don't care about the PID changing, and invalidating a stale PID 23962306a36Sopenharmony_ci * is generally harmless. 24062306a36Sopenharmony_ci */ 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_civoid flush_tlb_mm(struct mm_struct *mm) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci unsigned int pid; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci preempt_disable(); 24762306a36Sopenharmony_ci pid = mm->context.id; 24862306a36Sopenharmony_ci if (unlikely(pid == MMU_NO_CONTEXT)) 24962306a36Sopenharmony_ci goto no_context; 25062306a36Sopenharmony_ci if (!mm_is_core_local(mm)) { 25162306a36Sopenharmony_ci struct tlb_flush_param p = { .pid = pid }; 25262306a36Sopenharmony_ci /* Ignores smp_processor_id() even if set. */ 25362306a36Sopenharmony_ci smp_call_function_many(mm_cpumask(mm), 25462306a36Sopenharmony_ci do_flush_tlb_mm_ipi, &p, 1); 25562306a36Sopenharmony_ci } 25662306a36Sopenharmony_ci _tlbil_pid(pid); 25762306a36Sopenharmony_ci no_context: 25862306a36Sopenharmony_ci preempt_enable(); 25962306a36Sopenharmony_ci} 26062306a36Sopenharmony_ciEXPORT_SYMBOL(flush_tlb_mm); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_civoid __flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, 26362306a36Sopenharmony_ci int tsize, int ind) 26462306a36Sopenharmony_ci{ 26562306a36Sopenharmony_ci struct cpumask *cpu_mask; 26662306a36Sopenharmony_ci unsigned int pid; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci /* 26962306a36Sopenharmony_ci * This function as well as __local_flush_tlb_page() must only be called 27062306a36Sopenharmony_ci * for user contexts. 27162306a36Sopenharmony_ci */ 27262306a36Sopenharmony_ci if (WARN_ON(!mm)) 27362306a36Sopenharmony_ci return; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci preempt_disable(); 27662306a36Sopenharmony_ci pid = mm->context.id; 27762306a36Sopenharmony_ci if (unlikely(pid == MMU_NO_CONTEXT)) 27862306a36Sopenharmony_ci goto bail; 27962306a36Sopenharmony_ci cpu_mask = mm_cpumask(mm); 28062306a36Sopenharmony_ci if (!mm_is_core_local(mm)) { 28162306a36Sopenharmony_ci /* If broadcast tlbivax is supported, use it */ 28262306a36Sopenharmony_ci if (mmu_has_feature(MMU_FTR_USE_TLBIVAX_BCAST)) { 28362306a36Sopenharmony_ci int lock = mmu_has_feature(MMU_FTR_LOCK_BCAST_INVAL); 28462306a36Sopenharmony_ci if (lock) 28562306a36Sopenharmony_ci raw_spin_lock(&tlbivax_lock); 28662306a36Sopenharmony_ci _tlbivax_bcast(vmaddr, pid, tsize, ind); 28762306a36Sopenharmony_ci if (lock) 28862306a36Sopenharmony_ci raw_spin_unlock(&tlbivax_lock); 28962306a36Sopenharmony_ci goto bail; 29062306a36Sopenharmony_ci } else { 29162306a36Sopenharmony_ci struct tlb_flush_param p = { 29262306a36Sopenharmony_ci .pid = pid, 29362306a36Sopenharmony_ci .addr = vmaddr, 29462306a36Sopenharmony_ci .tsize = tsize, 29562306a36Sopenharmony_ci .ind = ind, 29662306a36Sopenharmony_ci }; 29762306a36Sopenharmony_ci /* Ignores smp_processor_id() even if set in cpu_mask */ 29862306a36Sopenharmony_ci smp_call_function_many(cpu_mask, 29962306a36Sopenharmony_ci do_flush_tlb_page_ipi, &p, 1); 30062306a36Sopenharmony_ci } 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci _tlbil_va(vmaddr, pid, tsize, ind); 30362306a36Sopenharmony_ci bail: 30462306a36Sopenharmony_ci preempt_enable(); 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_civoid flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) 30862306a36Sopenharmony_ci{ 30962306a36Sopenharmony_ci#ifdef CONFIG_HUGETLB_PAGE 31062306a36Sopenharmony_ci if (vma && is_vm_hugetlb_page(vma)) 31162306a36Sopenharmony_ci flush_hugetlb_page(vma, vmaddr); 31262306a36Sopenharmony_ci#endif 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci __flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr, 31562306a36Sopenharmony_ci mmu_get_tsize(mmu_virtual_psize), 0); 31662306a36Sopenharmony_ci} 31762306a36Sopenharmony_ciEXPORT_SYMBOL(flush_tlb_page); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci#endif /* CONFIG_SMP */ 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci/* 32262306a36Sopenharmony_ci * Flush kernel TLB entries in the given range 32362306a36Sopenharmony_ci */ 32462306a36Sopenharmony_ci#ifndef CONFIG_PPC_8xx 32562306a36Sopenharmony_civoid flush_tlb_kernel_range(unsigned long start, unsigned long end) 32662306a36Sopenharmony_ci{ 32762306a36Sopenharmony_ci#ifdef CONFIG_SMP 32862306a36Sopenharmony_ci preempt_disable(); 32962306a36Sopenharmony_ci smp_call_function(do_flush_tlb_mm_ipi, NULL, 1); 33062306a36Sopenharmony_ci _tlbil_pid(0); 33162306a36Sopenharmony_ci preempt_enable(); 33262306a36Sopenharmony_ci#else 33362306a36Sopenharmony_ci _tlbil_pid(0); 33462306a36Sopenharmony_ci#endif 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ciEXPORT_SYMBOL(flush_tlb_kernel_range); 33762306a36Sopenharmony_ci#endif 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci/* 34062306a36Sopenharmony_ci * Currently, for range flushing, we just do a full mm flush. This should 34162306a36Sopenharmony_ci * be optimized based on a threshold on the size of the range, since 34262306a36Sopenharmony_ci * some implementation can stack multiple tlbivax before a tlbsync but 34362306a36Sopenharmony_ci * for now, we keep it that way 34462306a36Sopenharmony_ci */ 34562306a36Sopenharmony_civoid flush_tlb_range(struct vm_area_struct *vma, unsigned long start, 34662306a36Sopenharmony_ci unsigned long end) 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci{ 34962306a36Sopenharmony_ci if (end - start == PAGE_SIZE && !(start & ~PAGE_MASK)) 35062306a36Sopenharmony_ci flush_tlb_page(vma, start); 35162306a36Sopenharmony_ci else 35262306a36Sopenharmony_ci flush_tlb_mm(vma->vm_mm); 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ciEXPORT_SYMBOL(flush_tlb_range); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_civoid tlb_flush(struct mmu_gather *tlb) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci flush_tlb_mm(tlb->mm); 35962306a36Sopenharmony_ci} 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci/* 36262306a36Sopenharmony_ci * Below are functions specific to the 64-bit variant of Book3E though that 36362306a36Sopenharmony_ci * may change in the future 36462306a36Sopenharmony_ci */ 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci#ifdef CONFIG_PPC64 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci/* 36962306a36Sopenharmony_ci * Handling of virtual linear page tables or indirect TLB entries 37062306a36Sopenharmony_ci * flushing when PTE pages are freed 37162306a36Sopenharmony_ci */ 37262306a36Sopenharmony_civoid tlb_flush_pgtable(struct mmu_gather *tlb, unsigned long address) 37362306a36Sopenharmony_ci{ 37462306a36Sopenharmony_ci int tsize = mmu_psize_defs[mmu_pte_psize].enc; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci if (book3e_htw_mode != PPC_HTW_NONE) { 37762306a36Sopenharmony_ci unsigned long start = address & PMD_MASK; 37862306a36Sopenharmony_ci unsigned long end = address + PMD_SIZE; 37962306a36Sopenharmony_ci unsigned long size = 1UL << mmu_psize_defs[mmu_pte_psize].shift; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci /* This isn't the most optimal, ideally we would factor out the 38262306a36Sopenharmony_ci * while preempt & CPU mask mucking around, or even the IPI but 38362306a36Sopenharmony_ci * it will do for now 38462306a36Sopenharmony_ci */ 38562306a36Sopenharmony_ci while (start < end) { 38662306a36Sopenharmony_ci __flush_tlb_page(tlb->mm, start, tsize, 1); 38762306a36Sopenharmony_ci start += size; 38862306a36Sopenharmony_ci } 38962306a36Sopenharmony_ci } else { 39062306a36Sopenharmony_ci unsigned long rmask = 0xf000000000000000ul; 39162306a36Sopenharmony_ci unsigned long rid = (address & rmask) | 0x1000000000000000ul; 39262306a36Sopenharmony_ci unsigned long vpte = address & ~rmask; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci vpte = (vpte >> (PAGE_SHIFT - 3)) & ~0xffful; 39562306a36Sopenharmony_ci vpte |= rid; 39662306a36Sopenharmony_ci __flush_tlb_page(tlb->mm, vpte, tsize, 0); 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci} 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_cistatic void __init setup_page_sizes(void) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci unsigned int tlb0cfg; 40362306a36Sopenharmony_ci unsigned int tlb0ps; 40462306a36Sopenharmony_ci unsigned int eptcfg; 40562306a36Sopenharmony_ci int i, psize; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci#ifdef CONFIG_PPC_E500 40862306a36Sopenharmony_ci unsigned int mmucfg = mfspr(SPRN_MMUCFG); 40962306a36Sopenharmony_ci int fsl_mmu = mmu_has_feature(MMU_FTR_TYPE_FSL_E); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci if (fsl_mmu && (mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V1) { 41262306a36Sopenharmony_ci unsigned int tlb1cfg = mfspr(SPRN_TLB1CFG); 41362306a36Sopenharmony_ci unsigned int min_pg, max_pg; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci min_pg = (tlb1cfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT; 41662306a36Sopenharmony_ci max_pg = (tlb1cfg & TLBnCFG_MAXSIZE) >> TLBnCFG_MAXSIZE_SHIFT; 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { 41962306a36Sopenharmony_ci struct mmu_psize_def *def; 42062306a36Sopenharmony_ci unsigned int shift; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci def = &mmu_psize_defs[psize]; 42362306a36Sopenharmony_ci shift = def->shift; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci if (shift == 0 || shift & 1) 42662306a36Sopenharmony_ci continue; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci /* adjust to be in terms of 4^shift Kb */ 42962306a36Sopenharmony_ci shift = (shift - 10) >> 1; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci if ((shift >= min_pg) && (shift <= max_pg)) 43262306a36Sopenharmony_ci def->flags |= MMU_PAGE_SIZE_DIRECT; 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci goto out; 43662306a36Sopenharmony_ci } 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci if (fsl_mmu && (mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V2) { 43962306a36Sopenharmony_ci u32 tlb1cfg, tlb1ps; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci tlb0cfg = mfspr(SPRN_TLB0CFG); 44262306a36Sopenharmony_ci tlb1cfg = mfspr(SPRN_TLB1CFG); 44362306a36Sopenharmony_ci tlb1ps = mfspr(SPRN_TLB1PS); 44462306a36Sopenharmony_ci eptcfg = mfspr(SPRN_EPTCFG); 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci if ((tlb1cfg & TLBnCFG_IND) && (tlb0cfg & TLBnCFG_PT)) 44762306a36Sopenharmony_ci book3e_htw_mode = PPC_HTW_E6500; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci /* 45062306a36Sopenharmony_ci * We expect 4K subpage size and unrestricted indirect size. 45162306a36Sopenharmony_ci * The lack of a restriction on indirect size is a Freescale 45262306a36Sopenharmony_ci * extension, indicated by PSn = 0 but SPSn != 0. 45362306a36Sopenharmony_ci */ 45462306a36Sopenharmony_ci if (eptcfg != 2) 45562306a36Sopenharmony_ci book3e_htw_mode = PPC_HTW_NONE; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { 45862306a36Sopenharmony_ci struct mmu_psize_def *def = &mmu_psize_defs[psize]; 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci if (!def->shift) 46162306a36Sopenharmony_ci continue; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci if (tlb1ps & (1U << (def->shift - 10))) { 46462306a36Sopenharmony_ci def->flags |= MMU_PAGE_SIZE_DIRECT; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci if (book3e_htw_mode && psize == MMU_PAGE_2M) 46762306a36Sopenharmony_ci def->flags |= MMU_PAGE_SIZE_INDIRECT; 46862306a36Sopenharmony_ci } 46962306a36Sopenharmony_ci } 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci goto out; 47262306a36Sopenharmony_ci } 47362306a36Sopenharmony_ci#endif 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci tlb0cfg = mfspr(SPRN_TLB0CFG); 47662306a36Sopenharmony_ci tlb0ps = mfspr(SPRN_TLB0PS); 47762306a36Sopenharmony_ci eptcfg = mfspr(SPRN_EPTCFG); 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci /* Look for supported direct sizes */ 48062306a36Sopenharmony_ci for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { 48162306a36Sopenharmony_ci struct mmu_psize_def *def = &mmu_psize_defs[psize]; 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci if (tlb0ps & (1U << (def->shift - 10))) 48462306a36Sopenharmony_ci def->flags |= MMU_PAGE_SIZE_DIRECT; 48562306a36Sopenharmony_ci } 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci /* Indirect page sizes supported ? */ 48862306a36Sopenharmony_ci if ((tlb0cfg & TLBnCFG_IND) == 0 || 48962306a36Sopenharmony_ci (tlb0cfg & TLBnCFG_PT) == 0) 49062306a36Sopenharmony_ci goto out; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci book3e_htw_mode = PPC_HTW_IBM; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci /* Now, we only deal with one IND page size for each 49562306a36Sopenharmony_ci * direct size. Hopefully all implementations today are 49662306a36Sopenharmony_ci * unambiguous, but we might want to be careful in the 49762306a36Sopenharmony_ci * future. 49862306a36Sopenharmony_ci */ 49962306a36Sopenharmony_ci for (i = 0; i < 3; i++) { 50062306a36Sopenharmony_ci unsigned int ps, sps; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci sps = eptcfg & 0x1f; 50362306a36Sopenharmony_ci eptcfg >>= 5; 50462306a36Sopenharmony_ci ps = eptcfg & 0x1f; 50562306a36Sopenharmony_ci eptcfg >>= 5; 50662306a36Sopenharmony_ci if (!ps || !sps) 50762306a36Sopenharmony_ci continue; 50862306a36Sopenharmony_ci for (psize = 0; psize < MMU_PAGE_COUNT; psize++) { 50962306a36Sopenharmony_ci struct mmu_psize_def *def = &mmu_psize_defs[psize]; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci if (ps == (def->shift - 10)) 51262306a36Sopenharmony_ci def->flags |= MMU_PAGE_SIZE_INDIRECT; 51362306a36Sopenharmony_ci if (sps == (def->shift - 10)) 51462306a36Sopenharmony_ci def->ind = ps + 10; 51562306a36Sopenharmony_ci } 51662306a36Sopenharmony_ci } 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ciout: 51962306a36Sopenharmony_ci /* Cleanup array and print summary */ 52062306a36Sopenharmony_ci pr_info("MMU: Supported page sizes\n"); 52162306a36Sopenharmony_ci for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { 52262306a36Sopenharmony_ci struct mmu_psize_def *def = &mmu_psize_defs[psize]; 52362306a36Sopenharmony_ci const char *__page_type_names[] = { 52462306a36Sopenharmony_ci "unsupported", 52562306a36Sopenharmony_ci "direct", 52662306a36Sopenharmony_ci "indirect", 52762306a36Sopenharmony_ci "direct & indirect" 52862306a36Sopenharmony_ci }; 52962306a36Sopenharmony_ci if (def->flags == 0) { 53062306a36Sopenharmony_ci def->shift = 0; 53162306a36Sopenharmony_ci continue; 53262306a36Sopenharmony_ci } 53362306a36Sopenharmony_ci pr_info(" %8ld KB as %s\n", 1ul << (def->shift - 10), 53462306a36Sopenharmony_ci __page_type_names[def->flags & 0x3]); 53562306a36Sopenharmony_ci } 53662306a36Sopenharmony_ci} 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_cistatic void __init setup_mmu_htw(void) 53962306a36Sopenharmony_ci{ 54062306a36Sopenharmony_ci /* 54162306a36Sopenharmony_ci * If we want to use HW tablewalk, enable it by patching the TLB miss 54262306a36Sopenharmony_ci * handlers to branch to the one dedicated to it. 54362306a36Sopenharmony_ci */ 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci switch (book3e_htw_mode) { 54662306a36Sopenharmony_ci case PPC_HTW_IBM: 54762306a36Sopenharmony_ci patch_exception(0x1c0, exc_data_tlb_miss_htw_book3e); 54862306a36Sopenharmony_ci patch_exception(0x1e0, exc_instruction_tlb_miss_htw_book3e); 54962306a36Sopenharmony_ci break; 55062306a36Sopenharmony_ci#ifdef CONFIG_PPC_E500 55162306a36Sopenharmony_ci case PPC_HTW_E6500: 55262306a36Sopenharmony_ci extlb_level_exc = EX_TLB_SIZE; 55362306a36Sopenharmony_ci patch_exception(0x1c0, exc_data_tlb_miss_e6500_book3e); 55462306a36Sopenharmony_ci patch_exception(0x1e0, exc_instruction_tlb_miss_e6500_book3e); 55562306a36Sopenharmony_ci break; 55662306a36Sopenharmony_ci#endif 55762306a36Sopenharmony_ci } 55862306a36Sopenharmony_ci pr_info("MMU: Book3E HW tablewalk %s\n", 55962306a36Sopenharmony_ci book3e_htw_mode != PPC_HTW_NONE ? "enabled" : "not supported"); 56062306a36Sopenharmony_ci} 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci/* 56362306a36Sopenharmony_ci * Early initialization of the MMU TLB code 56462306a36Sopenharmony_ci */ 56562306a36Sopenharmony_cistatic void early_init_this_mmu(void) 56662306a36Sopenharmony_ci{ 56762306a36Sopenharmony_ci unsigned int mas4; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci /* Set MAS4 based on page table setting */ 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci mas4 = 0x4 << MAS4_WIMGED_SHIFT; 57262306a36Sopenharmony_ci switch (book3e_htw_mode) { 57362306a36Sopenharmony_ci case PPC_HTW_E6500: 57462306a36Sopenharmony_ci mas4 |= MAS4_INDD; 57562306a36Sopenharmony_ci mas4 |= BOOK3E_PAGESZ_2M << MAS4_TSIZED_SHIFT; 57662306a36Sopenharmony_ci mas4 |= MAS4_TLBSELD(1); 57762306a36Sopenharmony_ci mmu_pte_psize = MMU_PAGE_2M; 57862306a36Sopenharmony_ci break; 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci case PPC_HTW_IBM: 58162306a36Sopenharmony_ci mas4 |= MAS4_INDD; 58262306a36Sopenharmony_ci mas4 |= BOOK3E_PAGESZ_1M << MAS4_TSIZED_SHIFT; 58362306a36Sopenharmony_ci mmu_pte_psize = MMU_PAGE_1M; 58462306a36Sopenharmony_ci break; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci case PPC_HTW_NONE: 58762306a36Sopenharmony_ci mas4 |= BOOK3E_PAGESZ_4K << MAS4_TSIZED_SHIFT; 58862306a36Sopenharmony_ci mmu_pte_psize = mmu_virtual_psize; 58962306a36Sopenharmony_ci break; 59062306a36Sopenharmony_ci } 59162306a36Sopenharmony_ci mtspr(SPRN_MAS4, mas4); 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci#ifdef CONFIG_PPC_E500 59462306a36Sopenharmony_ci if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) { 59562306a36Sopenharmony_ci unsigned int num_cams; 59662306a36Sopenharmony_ci bool map = true; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci /* use a quarter of the TLBCAM for bolted linear map */ 59962306a36Sopenharmony_ci num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci /* 60262306a36Sopenharmony_ci * Only do the mapping once per core, or else the 60362306a36Sopenharmony_ci * transient mapping would cause problems. 60462306a36Sopenharmony_ci */ 60562306a36Sopenharmony_ci#ifdef CONFIG_SMP 60662306a36Sopenharmony_ci if (hweight32(get_tensr()) > 1) 60762306a36Sopenharmony_ci map = false; 60862306a36Sopenharmony_ci#endif 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci if (map) 61162306a36Sopenharmony_ci linear_map_top = map_mem_in_cams(linear_map_top, 61262306a36Sopenharmony_ci num_cams, false, true); 61362306a36Sopenharmony_ci } 61462306a36Sopenharmony_ci#endif 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci /* A sync won't hurt us after mucking around with 61762306a36Sopenharmony_ci * the MMU configuration 61862306a36Sopenharmony_ci */ 61962306a36Sopenharmony_ci mb(); 62062306a36Sopenharmony_ci} 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_cistatic void __init early_init_mmu_global(void) 62362306a36Sopenharmony_ci{ 62462306a36Sopenharmony_ci /* XXX This should be decided at runtime based on supported 62562306a36Sopenharmony_ci * page sizes in the TLB, but for now let's assume 16M is 62662306a36Sopenharmony_ci * always there and a good fit (which it probably is) 62762306a36Sopenharmony_ci * 62862306a36Sopenharmony_ci * Freescale booke only supports 4K pages in TLB0, so use that. 62962306a36Sopenharmony_ci */ 63062306a36Sopenharmony_ci if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) 63162306a36Sopenharmony_ci mmu_vmemmap_psize = MMU_PAGE_4K; 63262306a36Sopenharmony_ci else 63362306a36Sopenharmony_ci mmu_vmemmap_psize = MMU_PAGE_16M; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci /* XXX This code only checks for TLB 0 capabilities and doesn't 63662306a36Sopenharmony_ci * check what page size combos are supported by the HW. It 63762306a36Sopenharmony_ci * also doesn't handle the case where a separate array holds 63862306a36Sopenharmony_ci * the IND entries from the array loaded by the PT. 63962306a36Sopenharmony_ci */ 64062306a36Sopenharmony_ci /* Look for supported page sizes */ 64162306a36Sopenharmony_ci setup_page_sizes(); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci /* Look for HW tablewalk support */ 64462306a36Sopenharmony_ci setup_mmu_htw(); 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci#ifdef CONFIG_PPC_E500 64762306a36Sopenharmony_ci if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) { 64862306a36Sopenharmony_ci if (book3e_htw_mode == PPC_HTW_NONE) { 64962306a36Sopenharmony_ci extlb_level_exc = EX_TLB_SIZE; 65062306a36Sopenharmony_ci patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e); 65162306a36Sopenharmony_ci patch_exception(0x1e0, 65262306a36Sopenharmony_ci exc_instruction_tlb_miss_bolted_book3e); 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci } 65562306a36Sopenharmony_ci#endif 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci /* Set the global containing the top of the linear mapping 65862306a36Sopenharmony_ci * for use by the TLB miss code 65962306a36Sopenharmony_ci */ 66062306a36Sopenharmony_ci linear_map_top = memblock_end_of_DRAM(); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci ioremap_bot = IOREMAP_BASE; 66362306a36Sopenharmony_ci} 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_cistatic void __init early_mmu_set_memory_limit(void) 66662306a36Sopenharmony_ci{ 66762306a36Sopenharmony_ci#ifdef CONFIG_PPC_E500 66862306a36Sopenharmony_ci if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) { 66962306a36Sopenharmony_ci /* 67062306a36Sopenharmony_ci * Limit memory so we dont have linear faults. 67162306a36Sopenharmony_ci * Unlike memblock_set_current_limit, which limits 67262306a36Sopenharmony_ci * memory available during early boot, this permanently 67362306a36Sopenharmony_ci * reduces the memory available to Linux. We need to 67462306a36Sopenharmony_ci * do this because highmem is not supported on 64-bit. 67562306a36Sopenharmony_ci */ 67662306a36Sopenharmony_ci memblock_enforce_memory_limit(linear_map_top); 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci#endif 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci memblock_set_current_limit(linear_map_top); 68162306a36Sopenharmony_ci} 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci/* boot cpu only */ 68462306a36Sopenharmony_civoid __init early_init_mmu(void) 68562306a36Sopenharmony_ci{ 68662306a36Sopenharmony_ci early_init_mmu_global(); 68762306a36Sopenharmony_ci early_init_this_mmu(); 68862306a36Sopenharmony_ci early_mmu_set_memory_limit(); 68962306a36Sopenharmony_ci} 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_civoid early_init_mmu_secondary(void) 69262306a36Sopenharmony_ci{ 69362306a36Sopenharmony_ci early_init_this_mmu(); 69462306a36Sopenharmony_ci} 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_civoid setup_initial_memory_limit(phys_addr_t first_memblock_base, 69762306a36Sopenharmony_ci phys_addr_t first_memblock_size) 69862306a36Sopenharmony_ci{ 69962306a36Sopenharmony_ci /* On non-FSL Embedded 64-bit, we adjust the RMA size to match 70062306a36Sopenharmony_ci * the bolted TLB entry. We know for now that only 1G 70162306a36Sopenharmony_ci * entries are supported though that may eventually 70262306a36Sopenharmony_ci * change. 70362306a36Sopenharmony_ci * 70462306a36Sopenharmony_ci * on FSL Embedded 64-bit, usually all RAM is bolted, but with 70562306a36Sopenharmony_ci * unusual memory sizes it's possible for some RAM to not be mapped 70662306a36Sopenharmony_ci * (such RAM is not used at all by Linux, since we don't support 70762306a36Sopenharmony_ci * highmem on 64-bit). We limit ppc64_rma_size to what would be 70862306a36Sopenharmony_ci * mappable if this memblock is the only one. Additional memblocks 70962306a36Sopenharmony_ci * can only increase, not decrease, the amount that ends up getting 71062306a36Sopenharmony_ci * mapped. We still limit max to 1G even if we'll eventually map 71162306a36Sopenharmony_ci * more. This is due to what the early init code is set up to do. 71262306a36Sopenharmony_ci * 71362306a36Sopenharmony_ci * We crop it to the size of the first MEMBLOCK to 71462306a36Sopenharmony_ci * avoid going over total available memory just in case... 71562306a36Sopenharmony_ci */ 71662306a36Sopenharmony_ci#ifdef CONFIG_PPC_E500 71762306a36Sopenharmony_ci if (early_mmu_has_feature(MMU_FTR_TYPE_FSL_E)) { 71862306a36Sopenharmony_ci unsigned long linear_sz; 71962306a36Sopenharmony_ci unsigned int num_cams; 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci /* use a quarter of the TLBCAM for bolted linear map */ 72262306a36Sopenharmony_ci num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4; 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci linear_sz = map_mem_in_cams(first_memblock_size, num_cams, 72562306a36Sopenharmony_ci true, true); 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci ppc64_rma_size = min_t(u64, linear_sz, 0x40000000); 72862306a36Sopenharmony_ci } else 72962306a36Sopenharmony_ci#endif 73062306a36Sopenharmony_ci ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000); 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci /* Finally limit subsequent allocations */ 73362306a36Sopenharmony_ci memblock_set_current_limit(first_memblock_base + ppc64_rma_size); 73462306a36Sopenharmony_ci} 73562306a36Sopenharmony_ci#else /* ! CONFIG_PPC64 */ 73662306a36Sopenharmony_civoid __init early_init_mmu(void) 73762306a36Sopenharmony_ci{ 73862306a36Sopenharmony_ci unsigned long root = of_get_flat_dt_root(); 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_PPC_47x) && IS_ENABLED(CONFIG_SMP) && 74162306a36Sopenharmony_ci of_get_flat_dt_prop(root, "cooperative-partition", NULL)) 74262306a36Sopenharmony_ci mmu_clear_feature(MMU_FTR_USE_TLBIVAX_BCAST); 74362306a36Sopenharmony_ci} 74462306a36Sopenharmony_ci#endif /* CONFIG_PPC64 */ 745