18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * This file contains the routines for TLB flushing. 48c2ecf20Sopenharmony_ci * On machines where the MMU does not use a hash table to store virtual to 58c2ecf20Sopenharmony_ci * physical translations (ie, SW loaded TLBs or Book3E compilant processors, 68c2ecf20Sopenharmony_ci * this does -not- include 603 however which shares the implementation with 78c2ecf20Sopenharmony_ci * hash based processors) 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * -- BenH 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Copyright 2008,2009 Ben Herrenschmidt <benh@kernel.crashing.org> 128c2ecf20Sopenharmony_ci * IBM Corp. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Derived from arch/ppc/mm/init.c: 158c2ecf20Sopenharmony_ci * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) 188c2ecf20Sopenharmony_ci * and Cort Dougan (PReP) (cort@cs.nmt.edu) 198c2ecf20Sopenharmony_ci * Copyright (C) 1996 Paul Mackerras 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * Derived from "arch/i386/mm/init.c" 228c2ecf20Sopenharmony_ci * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds 238c2ecf20Sopenharmony_ci */ 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include <linux/kernel.h> 268c2ecf20Sopenharmony_ci#include <linux/export.h> 278c2ecf20Sopenharmony_ci#include <linux/mm.h> 288c2ecf20Sopenharmony_ci#include <linux/init.h> 298c2ecf20Sopenharmony_ci#include <linux/highmem.h> 308c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 318c2ecf20Sopenharmony_ci#include <linux/preempt.h> 328c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 338c2ecf20Sopenharmony_ci#include <linux/memblock.h> 348c2ecf20Sopenharmony_ci#include <linux/of_fdt.h> 358c2ecf20Sopenharmony_ci#include <linux/hugetlb.h> 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#include <asm/pgalloc.h> 388c2ecf20Sopenharmony_ci#include <asm/tlbflush.h> 398c2ecf20Sopenharmony_ci#include <asm/tlb.h> 408c2ecf20Sopenharmony_ci#include <asm/code-patching.h> 418c2ecf20Sopenharmony_ci#include <asm/cputhreads.h> 428c2ecf20Sopenharmony_ci#include <asm/hugetlb.h> 438c2ecf20Sopenharmony_ci#include <asm/paca.h> 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#include <mm/mmu_decl.h> 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci/* 488c2ecf20Sopenharmony_ci * This struct lists the sw-supported page sizes. The hardawre MMU may support 498c2ecf20Sopenharmony_ci * other sizes not listed here. The .ind field is only used on MMUs that have 508c2ecf20Sopenharmony_ci * indirect page table entries. 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_ci#if defined(CONFIG_PPC_BOOK3E_MMU) || defined(CONFIG_PPC_8xx) 538c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_FSL_BOOK3E 548c2ecf20Sopenharmony_cistruct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = { 558c2ecf20Sopenharmony_ci [MMU_PAGE_4K] = { 568c2ecf20Sopenharmony_ci .shift = 12, 578c2ecf20Sopenharmony_ci .enc = BOOK3E_PAGESZ_4K, 588c2ecf20Sopenharmony_ci }, 598c2ecf20Sopenharmony_ci [MMU_PAGE_2M] = { 608c2ecf20Sopenharmony_ci .shift = 21, 618c2ecf20Sopenharmony_ci .enc = BOOK3E_PAGESZ_2M, 628c2ecf20Sopenharmony_ci }, 638c2ecf20Sopenharmony_ci [MMU_PAGE_4M] = { 648c2ecf20Sopenharmony_ci .shift = 22, 658c2ecf20Sopenharmony_ci .enc = BOOK3E_PAGESZ_4M, 668c2ecf20Sopenharmony_ci }, 678c2ecf20Sopenharmony_ci [MMU_PAGE_16M] = { 688c2ecf20Sopenharmony_ci .shift = 24, 698c2ecf20Sopenharmony_ci .enc = BOOK3E_PAGESZ_16M, 708c2ecf20Sopenharmony_ci }, 718c2ecf20Sopenharmony_ci [MMU_PAGE_64M] = { 728c2ecf20Sopenharmony_ci .shift = 26, 738c2ecf20Sopenharmony_ci .enc = BOOK3E_PAGESZ_64M, 748c2ecf20Sopenharmony_ci }, 758c2ecf20Sopenharmony_ci [MMU_PAGE_256M] = { 768c2ecf20Sopenharmony_ci .shift = 28, 778c2ecf20Sopenharmony_ci .enc = BOOK3E_PAGESZ_256M, 788c2ecf20Sopenharmony_ci }, 798c2ecf20Sopenharmony_ci [MMU_PAGE_1G] = { 808c2ecf20Sopenharmony_ci .shift = 30, 818c2ecf20Sopenharmony_ci .enc = BOOK3E_PAGESZ_1GB, 828c2ecf20Sopenharmony_ci }, 838c2ecf20Sopenharmony_ci}; 848c2ecf20Sopenharmony_ci#elif defined(CONFIG_PPC_8xx) 858c2ecf20Sopenharmony_cistruct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = { 868c2ecf20Sopenharmony_ci [MMU_PAGE_4K] = { 878c2ecf20Sopenharmony_ci .shift = 12, 888c2ecf20Sopenharmony_ci }, 898c2ecf20Sopenharmony_ci [MMU_PAGE_16K] = { 908c2ecf20Sopenharmony_ci .shift = 14, 918c2ecf20Sopenharmony_ci }, 928c2ecf20Sopenharmony_ci [MMU_PAGE_512K] = { 938c2ecf20Sopenharmony_ci .shift = 19, 948c2ecf20Sopenharmony_ci }, 958c2ecf20Sopenharmony_ci [MMU_PAGE_8M] = { 968c2ecf20Sopenharmony_ci .shift = 23, 978c2ecf20Sopenharmony_ci }, 988c2ecf20Sopenharmony_ci}; 998c2ecf20Sopenharmony_ci#else 1008c2ecf20Sopenharmony_cistruct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = { 1018c2ecf20Sopenharmony_ci [MMU_PAGE_4K] = { 1028c2ecf20Sopenharmony_ci .shift = 12, 1038c2ecf20Sopenharmony_ci .ind = 20, 1048c2ecf20Sopenharmony_ci .enc = BOOK3E_PAGESZ_4K, 1058c2ecf20Sopenharmony_ci }, 1068c2ecf20Sopenharmony_ci [MMU_PAGE_16K] = { 1078c2ecf20Sopenharmony_ci .shift = 14, 1088c2ecf20Sopenharmony_ci .enc = BOOK3E_PAGESZ_16K, 1098c2ecf20Sopenharmony_ci }, 1108c2ecf20Sopenharmony_ci [MMU_PAGE_64K] = { 1118c2ecf20Sopenharmony_ci .shift = 16, 1128c2ecf20Sopenharmony_ci .ind = 28, 1138c2ecf20Sopenharmony_ci .enc = BOOK3E_PAGESZ_64K, 1148c2ecf20Sopenharmony_ci }, 1158c2ecf20Sopenharmony_ci [MMU_PAGE_1M] = { 1168c2ecf20Sopenharmony_ci .shift = 20, 1178c2ecf20Sopenharmony_ci .enc = BOOK3E_PAGESZ_1M, 1188c2ecf20Sopenharmony_ci }, 1198c2ecf20Sopenharmony_ci [MMU_PAGE_16M] = { 1208c2ecf20Sopenharmony_ci .shift = 24, 1218c2ecf20Sopenharmony_ci .ind = 36, 1228c2ecf20Sopenharmony_ci .enc = BOOK3E_PAGESZ_16M, 1238c2ecf20Sopenharmony_ci }, 1248c2ecf20Sopenharmony_ci [MMU_PAGE_256M] = { 1258c2ecf20Sopenharmony_ci .shift = 28, 1268c2ecf20Sopenharmony_ci .enc = BOOK3E_PAGESZ_256M, 1278c2ecf20Sopenharmony_ci }, 1288c2ecf20Sopenharmony_ci [MMU_PAGE_1G] = { 1298c2ecf20Sopenharmony_ci .shift = 30, 1308c2ecf20Sopenharmony_ci .enc = BOOK3E_PAGESZ_1GB, 1318c2ecf20Sopenharmony_ci }, 1328c2ecf20Sopenharmony_ci}; 1338c2ecf20Sopenharmony_ci#endif /* CONFIG_FSL_BOOKE */ 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistatic inline int mmu_get_tsize(int psize) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci return mmu_psize_defs[psize].enc; 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci#else 1408c2ecf20Sopenharmony_cistatic inline int mmu_get_tsize(int psize) 1418c2ecf20Sopenharmony_ci{ 1428c2ecf20Sopenharmony_ci /* This isn't used on !Book3E for now */ 1438c2ecf20Sopenharmony_ci return 0; 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_BOOK3E_MMU */ 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci/* The variables below are currently only used on 64-bit Book3E 1488c2ecf20Sopenharmony_ci * though this will probably be made common with other nohash 1498c2ecf20Sopenharmony_ci * implementations at some point 1508c2ecf20Sopenharmony_ci */ 1518c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ciint mmu_linear_psize; /* Page size used for the linear mapping */ 1548c2ecf20Sopenharmony_ciint mmu_pte_psize; /* Page size used for PTE pages */ 1558c2ecf20Sopenharmony_ciint mmu_vmemmap_psize; /* Page size used for the virtual mem map */ 1568c2ecf20Sopenharmony_ciint book3e_htw_mode; /* HW tablewalk? Value is PPC_HTW_* */ 1578c2ecf20Sopenharmony_ciunsigned long linear_map_top; /* Top of linear mapping */ 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/* 1618c2ecf20Sopenharmony_ci * Number of bytes to add to SPRN_SPRG_TLB_EXFRAME on crit/mcheck/debug 1628c2ecf20Sopenharmony_ci * exceptions. This is used for bolted and e6500 TLB miss handlers which 1638c2ecf20Sopenharmony_ci * do not modify this SPRG in the TLB miss code; for other TLB miss handlers, 1648c2ecf20Sopenharmony_ci * this is set to zero. 1658c2ecf20Sopenharmony_ci */ 1668c2ecf20Sopenharmony_ciint extlb_level_exc; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */ 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_FSL_BOOK3E 1718c2ecf20Sopenharmony_ci/* next_tlbcam_idx is used to round-robin tlbcam entry assignment */ 1728c2ecf20Sopenharmony_ciDEFINE_PER_CPU(int, next_tlbcam_idx); 1738c2ecf20Sopenharmony_ciEXPORT_PER_CPU_SYMBOL(next_tlbcam_idx); 1748c2ecf20Sopenharmony_ci#endif 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci/* 1778c2ecf20Sopenharmony_ci * Base TLB flushing operations: 1788c2ecf20Sopenharmony_ci * 1798c2ecf20Sopenharmony_ci * - flush_tlb_mm(mm) flushes the specified mm context TLB's 1808c2ecf20Sopenharmony_ci * - flush_tlb_page(vma, vmaddr) flushes one page 1818c2ecf20Sopenharmony_ci * - flush_tlb_range(vma, start, end) flushes a range of pages 1828c2ecf20Sopenharmony_ci * - flush_tlb_kernel_range(start, end) flushes kernel pages 1838c2ecf20Sopenharmony_ci * 1848c2ecf20Sopenharmony_ci * - local_* variants of page and mm only apply to the current 1858c2ecf20Sopenharmony_ci * processor 1868c2ecf20Sopenharmony_ci */ 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci/* 1898c2ecf20Sopenharmony_ci * These are the base non-SMP variants of page and mm flushing 1908c2ecf20Sopenharmony_ci */ 1918c2ecf20Sopenharmony_civoid local_flush_tlb_mm(struct mm_struct *mm) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci unsigned int pid; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci preempt_disable(); 1968c2ecf20Sopenharmony_ci pid = mm->context.id; 1978c2ecf20Sopenharmony_ci if (pid != MMU_NO_CONTEXT) 1988c2ecf20Sopenharmony_ci _tlbil_pid(pid); 1998c2ecf20Sopenharmony_ci preempt_enable(); 2008c2ecf20Sopenharmony_ci} 2018c2ecf20Sopenharmony_ciEXPORT_SYMBOL(local_flush_tlb_mm); 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_civoid __local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, 2048c2ecf20Sopenharmony_ci int tsize, int ind) 2058c2ecf20Sopenharmony_ci{ 2068c2ecf20Sopenharmony_ci unsigned int pid; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci preempt_disable(); 2098c2ecf20Sopenharmony_ci pid = mm ? mm->context.id : 0; 2108c2ecf20Sopenharmony_ci if (pid != MMU_NO_CONTEXT) 2118c2ecf20Sopenharmony_ci _tlbil_va(vmaddr, pid, tsize, ind); 2128c2ecf20Sopenharmony_ci preempt_enable(); 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_civoid local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci __local_flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr, 2188c2ecf20Sopenharmony_ci mmu_get_tsize(mmu_virtual_psize), 0); 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ciEXPORT_SYMBOL(local_flush_tlb_page); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci/* 2238c2ecf20Sopenharmony_ci * And here are the SMP non-local implementations 2248c2ecf20Sopenharmony_ci */ 2258c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistatic DEFINE_RAW_SPINLOCK(tlbivax_lock); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_cistruct tlb_flush_param { 2308c2ecf20Sopenharmony_ci unsigned long addr; 2318c2ecf20Sopenharmony_ci unsigned int pid; 2328c2ecf20Sopenharmony_ci unsigned int tsize; 2338c2ecf20Sopenharmony_ci unsigned int ind; 2348c2ecf20Sopenharmony_ci}; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_cistatic void do_flush_tlb_mm_ipi(void *param) 2378c2ecf20Sopenharmony_ci{ 2388c2ecf20Sopenharmony_ci struct tlb_flush_param *p = param; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci _tlbil_pid(p ? p->pid : 0); 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_cistatic void do_flush_tlb_page_ipi(void *param) 2448c2ecf20Sopenharmony_ci{ 2458c2ecf20Sopenharmony_ci struct tlb_flush_param *p = param; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci _tlbil_va(p->addr, p->pid, p->tsize, p->ind); 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci/* Note on invalidations and PID: 2528c2ecf20Sopenharmony_ci * 2538c2ecf20Sopenharmony_ci * We snapshot the PID with preempt disabled. At this point, it can still 2548c2ecf20Sopenharmony_ci * change either because: 2558c2ecf20Sopenharmony_ci * - our context is being stolen (PID -> NO_CONTEXT) on another CPU 2568c2ecf20Sopenharmony_ci * - we are invaliating some target that isn't currently running here 2578c2ecf20Sopenharmony_ci * and is concurrently acquiring a new PID on another CPU 2588c2ecf20Sopenharmony_ci * - some other CPU is re-acquiring a lost PID for this mm 2598c2ecf20Sopenharmony_ci * etc... 2608c2ecf20Sopenharmony_ci * 2618c2ecf20Sopenharmony_ci * However, this shouldn't be a problem as we only guarantee 2628c2ecf20Sopenharmony_ci * invalidation of TLB entries present prior to this call, so we 2638c2ecf20Sopenharmony_ci * don't care about the PID changing, and invalidating a stale PID 2648c2ecf20Sopenharmony_ci * is generally harmless. 2658c2ecf20Sopenharmony_ci */ 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_civoid flush_tlb_mm(struct mm_struct *mm) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci unsigned int pid; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci preempt_disable(); 2728c2ecf20Sopenharmony_ci pid = mm->context.id; 2738c2ecf20Sopenharmony_ci if (unlikely(pid == MMU_NO_CONTEXT)) 2748c2ecf20Sopenharmony_ci goto no_context; 2758c2ecf20Sopenharmony_ci if (!mm_is_core_local(mm)) { 2768c2ecf20Sopenharmony_ci struct tlb_flush_param p = { .pid = pid }; 2778c2ecf20Sopenharmony_ci /* Ignores smp_processor_id() even if set. */ 2788c2ecf20Sopenharmony_ci smp_call_function_many(mm_cpumask(mm), 2798c2ecf20Sopenharmony_ci do_flush_tlb_mm_ipi, &p, 1); 2808c2ecf20Sopenharmony_ci } 2818c2ecf20Sopenharmony_ci _tlbil_pid(pid); 2828c2ecf20Sopenharmony_ci no_context: 2838c2ecf20Sopenharmony_ci preempt_enable(); 2848c2ecf20Sopenharmony_ci} 2858c2ecf20Sopenharmony_ciEXPORT_SYMBOL(flush_tlb_mm); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_civoid __flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, 2888c2ecf20Sopenharmony_ci int tsize, int ind) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci struct cpumask *cpu_mask; 2918c2ecf20Sopenharmony_ci unsigned int pid; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci /* 2948c2ecf20Sopenharmony_ci * This function as well as __local_flush_tlb_page() must only be called 2958c2ecf20Sopenharmony_ci * for user contexts. 2968c2ecf20Sopenharmony_ci */ 2978c2ecf20Sopenharmony_ci if (WARN_ON(!mm)) 2988c2ecf20Sopenharmony_ci return; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci preempt_disable(); 3018c2ecf20Sopenharmony_ci pid = mm->context.id; 3028c2ecf20Sopenharmony_ci if (unlikely(pid == MMU_NO_CONTEXT)) 3038c2ecf20Sopenharmony_ci goto bail; 3048c2ecf20Sopenharmony_ci cpu_mask = mm_cpumask(mm); 3058c2ecf20Sopenharmony_ci if (!mm_is_core_local(mm)) { 3068c2ecf20Sopenharmony_ci /* If broadcast tlbivax is supported, use it */ 3078c2ecf20Sopenharmony_ci if (mmu_has_feature(MMU_FTR_USE_TLBIVAX_BCAST)) { 3088c2ecf20Sopenharmony_ci int lock = mmu_has_feature(MMU_FTR_LOCK_BCAST_INVAL); 3098c2ecf20Sopenharmony_ci if (lock) 3108c2ecf20Sopenharmony_ci raw_spin_lock(&tlbivax_lock); 3118c2ecf20Sopenharmony_ci _tlbivax_bcast(vmaddr, pid, tsize, ind); 3128c2ecf20Sopenharmony_ci if (lock) 3138c2ecf20Sopenharmony_ci raw_spin_unlock(&tlbivax_lock); 3148c2ecf20Sopenharmony_ci goto bail; 3158c2ecf20Sopenharmony_ci } else { 3168c2ecf20Sopenharmony_ci struct tlb_flush_param p = { 3178c2ecf20Sopenharmony_ci .pid = pid, 3188c2ecf20Sopenharmony_ci .addr = vmaddr, 3198c2ecf20Sopenharmony_ci .tsize = tsize, 3208c2ecf20Sopenharmony_ci .ind = ind, 3218c2ecf20Sopenharmony_ci }; 3228c2ecf20Sopenharmony_ci /* Ignores smp_processor_id() even if set in cpu_mask */ 3238c2ecf20Sopenharmony_ci smp_call_function_many(cpu_mask, 3248c2ecf20Sopenharmony_ci do_flush_tlb_page_ipi, &p, 1); 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci } 3278c2ecf20Sopenharmony_ci _tlbil_va(vmaddr, pid, tsize, ind); 3288c2ecf20Sopenharmony_ci bail: 3298c2ecf20Sopenharmony_ci preempt_enable(); 3308c2ecf20Sopenharmony_ci} 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_civoid flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) 3338c2ecf20Sopenharmony_ci{ 3348c2ecf20Sopenharmony_ci#ifdef CONFIG_HUGETLB_PAGE 3358c2ecf20Sopenharmony_ci if (vma && is_vm_hugetlb_page(vma)) 3368c2ecf20Sopenharmony_ci flush_hugetlb_page(vma, vmaddr); 3378c2ecf20Sopenharmony_ci#endif 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci __flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr, 3408c2ecf20Sopenharmony_ci mmu_get_tsize(mmu_virtual_psize), 0); 3418c2ecf20Sopenharmony_ci} 3428c2ecf20Sopenharmony_ciEXPORT_SYMBOL(flush_tlb_page); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci#endif /* CONFIG_SMP */ 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_47x 3478c2ecf20Sopenharmony_civoid __init early_init_mmu_47x(void) 3488c2ecf20Sopenharmony_ci{ 3498c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 3508c2ecf20Sopenharmony_ci unsigned long root = of_get_flat_dt_root(); 3518c2ecf20Sopenharmony_ci if (of_get_flat_dt_prop(root, "cooperative-partition", NULL)) 3528c2ecf20Sopenharmony_ci mmu_clear_feature(MMU_FTR_USE_TLBIVAX_BCAST); 3538c2ecf20Sopenharmony_ci#endif /* CONFIG_SMP */ 3548c2ecf20Sopenharmony_ci} 3558c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_47x */ 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci/* 3588c2ecf20Sopenharmony_ci * Flush kernel TLB entries in the given range 3598c2ecf20Sopenharmony_ci */ 3608c2ecf20Sopenharmony_civoid flush_tlb_kernel_range(unsigned long start, unsigned long end) 3618c2ecf20Sopenharmony_ci{ 3628c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 3638c2ecf20Sopenharmony_ci preempt_disable(); 3648c2ecf20Sopenharmony_ci smp_call_function(do_flush_tlb_mm_ipi, NULL, 1); 3658c2ecf20Sopenharmony_ci _tlbil_pid(0); 3668c2ecf20Sopenharmony_ci preempt_enable(); 3678c2ecf20Sopenharmony_ci#else 3688c2ecf20Sopenharmony_ci _tlbil_pid(0); 3698c2ecf20Sopenharmony_ci#endif 3708c2ecf20Sopenharmony_ci} 3718c2ecf20Sopenharmony_ciEXPORT_SYMBOL(flush_tlb_kernel_range); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci/* 3748c2ecf20Sopenharmony_ci * Currently, for range flushing, we just do a full mm flush. This should 3758c2ecf20Sopenharmony_ci * be optimized based on a threshold on the size of the range, since 3768c2ecf20Sopenharmony_ci * some implementation can stack multiple tlbivax before a tlbsync but 3778c2ecf20Sopenharmony_ci * for now, we keep it that way 3788c2ecf20Sopenharmony_ci */ 3798c2ecf20Sopenharmony_civoid flush_tlb_range(struct vm_area_struct *vma, unsigned long start, 3808c2ecf20Sopenharmony_ci unsigned long end) 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci{ 3838c2ecf20Sopenharmony_ci if (end - start == PAGE_SIZE && !(start & ~PAGE_MASK)) 3848c2ecf20Sopenharmony_ci flush_tlb_page(vma, start); 3858c2ecf20Sopenharmony_ci else 3868c2ecf20Sopenharmony_ci flush_tlb_mm(vma->vm_mm); 3878c2ecf20Sopenharmony_ci} 3888c2ecf20Sopenharmony_ciEXPORT_SYMBOL(flush_tlb_range); 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_civoid tlb_flush(struct mmu_gather *tlb) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci flush_tlb_mm(tlb->mm); 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci/* 3968c2ecf20Sopenharmony_ci * Below are functions specific to the 64-bit variant of Book3E though that 3978c2ecf20Sopenharmony_ci * may change in the future 3988c2ecf20Sopenharmony_ci */ 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci/* 4038c2ecf20Sopenharmony_ci * Handling of virtual linear page tables or indirect TLB entries 4048c2ecf20Sopenharmony_ci * flushing when PTE pages are freed 4058c2ecf20Sopenharmony_ci */ 4068c2ecf20Sopenharmony_civoid tlb_flush_pgtable(struct mmu_gather *tlb, unsigned long address) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci int tsize = mmu_psize_defs[mmu_pte_psize].enc; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci if (book3e_htw_mode != PPC_HTW_NONE) { 4118c2ecf20Sopenharmony_ci unsigned long start = address & PMD_MASK; 4128c2ecf20Sopenharmony_ci unsigned long end = address + PMD_SIZE; 4138c2ecf20Sopenharmony_ci unsigned long size = 1UL << mmu_psize_defs[mmu_pte_psize].shift; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci /* This isn't the most optimal, ideally we would factor out the 4168c2ecf20Sopenharmony_ci * while preempt & CPU mask mucking around, or even the IPI but 4178c2ecf20Sopenharmony_ci * it will do for now 4188c2ecf20Sopenharmony_ci */ 4198c2ecf20Sopenharmony_ci while (start < end) { 4208c2ecf20Sopenharmony_ci __flush_tlb_page(tlb->mm, start, tsize, 1); 4218c2ecf20Sopenharmony_ci start += size; 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci } else { 4248c2ecf20Sopenharmony_ci unsigned long rmask = 0xf000000000000000ul; 4258c2ecf20Sopenharmony_ci unsigned long rid = (address & rmask) | 0x1000000000000000ul; 4268c2ecf20Sopenharmony_ci unsigned long vpte = address & ~rmask; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci vpte = (vpte >> (PAGE_SHIFT - 3)) & ~0xffful; 4298c2ecf20Sopenharmony_ci vpte |= rid; 4308c2ecf20Sopenharmony_ci __flush_tlb_page(tlb->mm, vpte, tsize, 0); 4318c2ecf20Sopenharmony_ci } 4328c2ecf20Sopenharmony_ci} 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_cistatic void setup_page_sizes(void) 4358c2ecf20Sopenharmony_ci{ 4368c2ecf20Sopenharmony_ci unsigned int tlb0cfg; 4378c2ecf20Sopenharmony_ci unsigned int tlb0ps; 4388c2ecf20Sopenharmony_ci unsigned int eptcfg; 4398c2ecf20Sopenharmony_ci int i, psize; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_FSL_BOOK3E 4428c2ecf20Sopenharmony_ci unsigned int mmucfg = mfspr(SPRN_MMUCFG); 4438c2ecf20Sopenharmony_ci int fsl_mmu = mmu_has_feature(MMU_FTR_TYPE_FSL_E); 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci if (fsl_mmu && (mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V1) { 4468c2ecf20Sopenharmony_ci unsigned int tlb1cfg = mfspr(SPRN_TLB1CFG); 4478c2ecf20Sopenharmony_ci unsigned int min_pg, max_pg; 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci min_pg = (tlb1cfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT; 4508c2ecf20Sopenharmony_ci max_pg = (tlb1cfg & TLBnCFG_MAXSIZE) >> TLBnCFG_MAXSIZE_SHIFT; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { 4538c2ecf20Sopenharmony_ci struct mmu_psize_def *def; 4548c2ecf20Sopenharmony_ci unsigned int shift; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci def = &mmu_psize_defs[psize]; 4578c2ecf20Sopenharmony_ci shift = def->shift; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci if (shift == 0 || shift & 1) 4608c2ecf20Sopenharmony_ci continue; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci /* adjust to be in terms of 4^shift Kb */ 4638c2ecf20Sopenharmony_ci shift = (shift - 10) >> 1; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci if ((shift >= min_pg) && (shift <= max_pg)) 4668c2ecf20Sopenharmony_ci def->flags |= MMU_PAGE_SIZE_DIRECT; 4678c2ecf20Sopenharmony_ci } 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci goto out; 4708c2ecf20Sopenharmony_ci } 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci if (fsl_mmu && (mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V2) { 4738c2ecf20Sopenharmony_ci u32 tlb1cfg, tlb1ps; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci tlb0cfg = mfspr(SPRN_TLB0CFG); 4768c2ecf20Sopenharmony_ci tlb1cfg = mfspr(SPRN_TLB1CFG); 4778c2ecf20Sopenharmony_ci tlb1ps = mfspr(SPRN_TLB1PS); 4788c2ecf20Sopenharmony_ci eptcfg = mfspr(SPRN_EPTCFG); 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci if ((tlb1cfg & TLBnCFG_IND) && (tlb0cfg & TLBnCFG_PT)) 4818c2ecf20Sopenharmony_ci book3e_htw_mode = PPC_HTW_E6500; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci /* 4848c2ecf20Sopenharmony_ci * We expect 4K subpage size and unrestricted indirect size. 4858c2ecf20Sopenharmony_ci * The lack of a restriction on indirect size is a Freescale 4868c2ecf20Sopenharmony_ci * extension, indicated by PSn = 0 but SPSn != 0. 4878c2ecf20Sopenharmony_ci */ 4888c2ecf20Sopenharmony_ci if (eptcfg != 2) 4898c2ecf20Sopenharmony_ci book3e_htw_mode = PPC_HTW_NONE; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { 4928c2ecf20Sopenharmony_ci struct mmu_psize_def *def = &mmu_psize_defs[psize]; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci if (!def->shift) 4958c2ecf20Sopenharmony_ci continue; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci if (tlb1ps & (1U << (def->shift - 10))) { 4988c2ecf20Sopenharmony_ci def->flags |= MMU_PAGE_SIZE_DIRECT; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci if (book3e_htw_mode && psize == MMU_PAGE_2M) 5018c2ecf20Sopenharmony_ci def->flags |= MMU_PAGE_SIZE_INDIRECT; 5028c2ecf20Sopenharmony_ci } 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci goto out; 5068c2ecf20Sopenharmony_ci } 5078c2ecf20Sopenharmony_ci#endif 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci tlb0cfg = mfspr(SPRN_TLB0CFG); 5108c2ecf20Sopenharmony_ci tlb0ps = mfspr(SPRN_TLB0PS); 5118c2ecf20Sopenharmony_ci eptcfg = mfspr(SPRN_EPTCFG); 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci /* Look for supported direct sizes */ 5148c2ecf20Sopenharmony_ci for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { 5158c2ecf20Sopenharmony_ci struct mmu_psize_def *def = &mmu_psize_defs[psize]; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci if (tlb0ps & (1U << (def->shift - 10))) 5188c2ecf20Sopenharmony_ci def->flags |= MMU_PAGE_SIZE_DIRECT; 5198c2ecf20Sopenharmony_ci } 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci /* Indirect page sizes supported ? */ 5228c2ecf20Sopenharmony_ci if ((tlb0cfg & TLBnCFG_IND) == 0 || 5238c2ecf20Sopenharmony_ci (tlb0cfg & TLBnCFG_PT) == 0) 5248c2ecf20Sopenharmony_ci goto out; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci book3e_htw_mode = PPC_HTW_IBM; 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci /* Now, we only deal with one IND page size for each 5298c2ecf20Sopenharmony_ci * direct size. Hopefully all implementations today are 5308c2ecf20Sopenharmony_ci * unambiguous, but we might want to be careful in the 5318c2ecf20Sopenharmony_ci * future. 5328c2ecf20Sopenharmony_ci */ 5338c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 5348c2ecf20Sopenharmony_ci unsigned int ps, sps; 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci sps = eptcfg & 0x1f; 5378c2ecf20Sopenharmony_ci eptcfg >>= 5; 5388c2ecf20Sopenharmony_ci ps = eptcfg & 0x1f; 5398c2ecf20Sopenharmony_ci eptcfg >>= 5; 5408c2ecf20Sopenharmony_ci if (!ps || !sps) 5418c2ecf20Sopenharmony_ci continue; 5428c2ecf20Sopenharmony_ci for (psize = 0; psize < MMU_PAGE_COUNT; psize++) { 5438c2ecf20Sopenharmony_ci struct mmu_psize_def *def = &mmu_psize_defs[psize]; 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci if (ps == (def->shift - 10)) 5468c2ecf20Sopenharmony_ci def->flags |= MMU_PAGE_SIZE_INDIRECT; 5478c2ecf20Sopenharmony_ci if (sps == (def->shift - 10)) 5488c2ecf20Sopenharmony_ci def->ind = ps + 10; 5498c2ecf20Sopenharmony_ci } 5508c2ecf20Sopenharmony_ci } 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ciout: 5538c2ecf20Sopenharmony_ci /* Cleanup array and print summary */ 5548c2ecf20Sopenharmony_ci pr_info("MMU: Supported page sizes\n"); 5558c2ecf20Sopenharmony_ci for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { 5568c2ecf20Sopenharmony_ci struct mmu_psize_def *def = &mmu_psize_defs[psize]; 5578c2ecf20Sopenharmony_ci const char *__page_type_names[] = { 5588c2ecf20Sopenharmony_ci "unsupported", 5598c2ecf20Sopenharmony_ci "direct", 5608c2ecf20Sopenharmony_ci "indirect", 5618c2ecf20Sopenharmony_ci "direct & indirect" 5628c2ecf20Sopenharmony_ci }; 5638c2ecf20Sopenharmony_ci if (def->flags == 0) { 5648c2ecf20Sopenharmony_ci def->shift = 0; 5658c2ecf20Sopenharmony_ci continue; 5668c2ecf20Sopenharmony_ci } 5678c2ecf20Sopenharmony_ci pr_info(" %8ld KB as %s\n", 1ul << (def->shift - 10), 5688c2ecf20Sopenharmony_ci __page_type_names[def->flags & 0x3]); 5698c2ecf20Sopenharmony_ci } 5708c2ecf20Sopenharmony_ci} 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_cistatic void setup_mmu_htw(void) 5738c2ecf20Sopenharmony_ci{ 5748c2ecf20Sopenharmony_ci /* 5758c2ecf20Sopenharmony_ci * If we want to use HW tablewalk, enable it by patching the TLB miss 5768c2ecf20Sopenharmony_ci * handlers to branch to the one dedicated to it. 5778c2ecf20Sopenharmony_ci */ 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci switch (book3e_htw_mode) { 5808c2ecf20Sopenharmony_ci case PPC_HTW_IBM: 5818c2ecf20Sopenharmony_ci patch_exception(0x1c0, exc_data_tlb_miss_htw_book3e); 5828c2ecf20Sopenharmony_ci patch_exception(0x1e0, exc_instruction_tlb_miss_htw_book3e); 5838c2ecf20Sopenharmony_ci break; 5848c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_FSL_BOOK3E 5858c2ecf20Sopenharmony_ci case PPC_HTW_E6500: 5868c2ecf20Sopenharmony_ci extlb_level_exc = EX_TLB_SIZE; 5878c2ecf20Sopenharmony_ci patch_exception(0x1c0, exc_data_tlb_miss_e6500_book3e); 5888c2ecf20Sopenharmony_ci patch_exception(0x1e0, exc_instruction_tlb_miss_e6500_book3e); 5898c2ecf20Sopenharmony_ci break; 5908c2ecf20Sopenharmony_ci#endif 5918c2ecf20Sopenharmony_ci } 5928c2ecf20Sopenharmony_ci pr_info("MMU: Book3E HW tablewalk %s\n", 5938c2ecf20Sopenharmony_ci book3e_htw_mode != PPC_HTW_NONE ? "enabled" : "not supported"); 5948c2ecf20Sopenharmony_ci} 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci/* 5978c2ecf20Sopenharmony_ci * Early initialization of the MMU TLB code 5988c2ecf20Sopenharmony_ci */ 5998c2ecf20Sopenharmony_cistatic void early_init_this_mmu(void) 6008c2ecf20Sopenharmony_ci{ 6018c2ecf20Sopenharmony_ci unsigned int mas4; 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci /* Set MAS4 based on page table setting */ 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci mas4 = 0x4 << MAS4_WIMGED_SHIFT; 6068c2ecf20Sopenharmony_ci switch (book3e_htw_mode) { 6078c2ecf20Sopenharmony_ci case PPC_HTW_E6500: 6088c2ecf20Sopenharmony_ci mas4 |= MAS4_INDD; 6098c2ecf20Sopenharmony_ci mas4 |= BOOK3E_PAGESZ_2M << MAS4_TSIZED_SHIFT; 6108c2ecf20Sopenharmony_ci mas4 |= MAS4_TLBSELD(1); 6118c2ecf20Sopenharmony_ci mmu_pte_psize = MMU_PAGE_2M; 6128c2ecf20Sopenharmony_ci break; 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci case PPC_HTW_IBM: 6158c2ecf20Sopenharmony_ci mas4 |= MAS4_INDD; 6168c2ecf20Sopenharmony_ci mas4 |= BOOK3E_PAGESZ_1M << MAS4_TSIZED_SHIFT; 6178c2ecf20Sopenharmony_ci mmu_pte_psize = MMU_PAGE_1M; 6188c2ecf20Sopenharmony_ci break; 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci case PPC_HTW_NONE: 6218c2ecf20Sopenharmony_ci mas4 |= BOOK3E_PAGESZ_4K << MAS4_TSIZED_SHIFT; 6228c2ecf20Sopenharmony_ci mmu_pte_psize = mmu_virtual_psize; 6238c2ecf20Sopenharmony_ci break; 6248c2ecf20Sopenharmony_ci } 6258c2ecf20Sopenharmony_ci mtspr(SPRN_MAS4, mas4); 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_FSL_BOOK3E 6288c2ecf20Sopenharmony_ci if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) { 6298c2ecf20Sopenharmony_ci unsigned int num_cams; 6308c2ecf20Sopenharmony_ci bool map = true; 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci /* use a quarter of the TLBCAM for bolted linear map */ 6338c2ecf20Sopenharmony_ci num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci /* 6368c2ecf20Sopenharmony_ci * Only do the mapping once per core, or else the 6378c2ecf20Sopenharmony_ci * transient mapping would cause problems. 6388c2ecf20Sopenharmony_ci */ 6398c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 6408c2ecf20Sopenharmony_ci if (hweight32(get_tensr()) > 1) 6418c2ecf20Sopenharmony_ci map = false; 6428c2ecf20Sopenharmony_ci#endif 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci if (map) 6458c2ecf20Sopenharmony_ci linear_map_top = map_mem_in_cams(linear_map_top, 6468c2ecf20Sopenharmony_ci num_cams, false); 6478c2ecf20Sopenharmony_ci } 6488c2ecf20Sopenharmony_ci#endif 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci /* A sync won't hurt us after mucking around with 6518c2ecf20Sopenharmony_ci * the MMU configuration 6528c2ecf20Sopenharmony_ci */ 6538c2ecf20Sopenharmony_ci mb(); 6548c2ecf20Sopenharmony_ci} 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_cistatic void __init early_init_mmu_global(void) 6578c2ecf20Sopenharmony_ci{ 6588c2ecf20Sopenharmony_ci /* XXX This will have to be decided at runtime, but right 6598c2ecf20Sopenharmony_ci * now our boot and TLB miss code hard wires it. Ideally 6608c2ecf20Sopenharmony_ci * we should find out a suitable page size and patch the 6618c2ecf20Sopenharmony_ci * TLB miss code (either that or use the PACA to store 6628c2ecf20Sopenharmony_ci * the value we want) 6638c2ecf20Sopenharmony_ci */ 6648c2ecf20Sopenharmony_ci mmu_linear_psize = MMU_PAGE_1G; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci /* XXX This should be decided at runtime based on supported 6678c2ecf20Sopenharmony_ci * page sizes in the TLB, but for now let's assume 16M is 6688c2ecf20Sopenharmony_ci * always there and a good fit (which it probably is) 6698c2ecf20Sopenharmony_ci * 6708c2ecf20Sopenharmony_ci * Freescale booke only supports 4K pages in TLB0, so use that. 6718c2ecf20Sopenharmony_ci */ 6728c2ecf20Sopenharmony_ci if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) 6738c2ecf20Sopenharmony_ci mmu_vmemmap_psize = MMU_PAGE_4K; 6748c2ecf20Sopenharmony_ci else 6758c2ecf20Sopenharmony_ci mmu_vmemmap_psize = MMU_PAGE_16M; 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci /* XXX This code only checks for TLB 0 capabilities and doesn't 6788c2ecf20Sopenharmony_ci * check what page size combos are supported by the HW. It 6798c2ecf20Sopenharmony_ci * also doesn't handle the case where a separate array holds 6808c2ecf20Sopenharmony_ci * the IND entries from the array loaded by the PT. 6818c2ecf20Sopenharmony_ci */ 6828c2ecf20Sopenharmony_ci /* Look for supported page sizes */ 6838c2ecf20Sopenharmony_ci setup_page_sizes(); 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci /* Look for HW tablewalk support */ 6868c2ecf20Sopenharmony_ci setup_mmu_htw(); 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_FSL_BOOK3E 6898c2ecf20Sopenharmony_ci if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) { 6908c2ecf20Sopenharmony_ci if (book3e_htw_mode == PPC_HTW_NONE) { 6918c2ecf20Sopenharmony_ci extlb_level_exc = EX_TLB_SIZE; 6928c2ecf20Sopenharmony_ci patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e); 6938c2ecf20Sopenharmony_ci patch_exception(0x1e0, 6948c2ecf20Sopenharmony_ci exc_instruction_tlb_miss_bolted_book3e); 6958c2ecf20Sopenharmony_ci } 6968c2ecf20Sopenharmony_ci } 6978c2ecf20Sopenharmony_ci#endif 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci /* Set the global containing the top of the linear mapping 7008c2ecf20Sopenharmony_ci * for use by the TLB miss code 7018c2ecf20Sopenharmony_ci */ 7028c2ecf20Sopenharmony_ci linear_map_top = memblock_end_of_DRAM(); 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci ioremap_bot = IOREMAP_BASE; 7058c2ecf20Sopenharmony_ci} 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_cistatic void __init early_mmu_set_memory_limit(void) 7088c2ecf20Sopenharmony_ci{ 7098c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_FSL_BOOK3E 7108c2ecf20Sopenharmony_ci if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) { 7118c2ecf20Sopenharmony_ci /* 7128c2ecf20Sopenharmony_ci * Limit memory so we dont have linear faults. 7138c2ecf20Sopenharmony_ci * Unlike memblock_set_current_limit, which limits 7148c2ecf20Sopenharmony_ci * memory available during early boot, this permanently 7158c2ecf20Sopenharmony_ci * reduces the memory available to Linux. We need to 7168c2ecf20Sopenharmony_ci * do this because highmem is not supported on 64-bit. 7178c2ecf20Sopenharmony_ci */ 7188c2ecf20Sopenharmony_ci memblock_enforce_memory_limit(linear_map_top); 7198c2ecf20Sopenharmony_ci } 7208c2ecf20Sopenharmony_ci#endif 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci memblock_set_current_limit(linear_map_top); 7238c2ecf20Sopenharmony_ci} 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci/* boot cpu only */ 7268c2ecf20Sopenharmony_civoid __init early_init_mmu(void) 7278c2ecf20Sopenharmony_ci{ 7288c2ecf20Sopenharmony_ci early_init_mmu_global(); 7298c2ecf20Sopenharmony_ci early_init_this_mmu(); 7308c2ecf20Sopenharmony_ci early_mmu_set_memory_limit(); 7318c2ecf20Sopenharmony_ci} 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_civoid early_init_mmu_secondary(void) 7348c2ecf20Sopenharmony_ci{ 7358c2ecf20Sopenharmony_ci early_init_this_mmu(); 7368c2ecf20Sopenharmony_ci} 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_civoid setup_initial_memory_limit(phys_addr_t first_memblock_base, 7398c2ecf20Sopenharmony_ci phys_addr_t first_memblock_size) 7408c2ecf20Sopenharmony_ci{ 7418c2ecf20Sopenharmony_ci /* On non-FSL Embedded 64-bit, we adjust the RMA size to match 7428c2ecf20Sopenharmony_ci * the bolted TLB entry. We know for now that only 1G 7438c2ecf20Sopenharmony_ci * entries are supported though that may eventually 7448c2ecf20Sopenharmony_ci * change. 7458c2ecf20Sopenharmony_ci * 7468c2ecf20Sopenharmony_ci * on FSL Embedded 64-bit, usually all RAM is bolted, but with 7478c2ecf20Sopenharmony_ci * unusual memory sizes it's possible for some RAM to not be mapped 7488c2ecf20Sopenharmony_ci * (such RAM is not used at all by Linux, since we don't support 7498c2ecf20Sopenharmony_ci * highmem on 64-bit). We limit ppc64_rma_size to what would be 7508c2ecf20Sopenharmony_ci * mappable if this memblock is the only one. Additional memblocks 7518c2ecf20Sopenharmony_ci * can only increase, not decrease, the amount that ends up getting 7528c2ecf20Sopenharmony_ci * mapped. We still limit max to 1G even if we'll eventually map 7538c2ecf20Sopenharmony_ci * more. This is due to what the early init code is set up to do. 7548c2ecf20Sopenharmony_ci * 7558c2ecf20Sopenharmony_ci * We crop it to the size of the first MEMBLOCK to 7568c2ecf20Sopenharmony_ci * avoid going over total available memory just in case... 7578c2ecf20Sopenharmony_ci */ 7588c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_FSL_BOOK3E 7598c2ecf20Sopenharmony_ci if (early_mmu_has_feature(MMU_FTR_TYPE_FSL_E)) { 7608c2ecf20Sopenharmony_ci unsigned long linear_sz; 7618c2ecf20Sopenharmony_ci unsigned int num_cams; 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci /* use a quarter of the TLBCAM for bolted linear map */ 7648c2ecf20Sopenharmony_ci num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4; 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci linear_sz = map_mem_in_cams(first_memblock_size, num_cams, 7678c2ecf20Sopenharmony_ci true); 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci ppc64_rma_size = min_t(u64, linear_sz, 0x40000000); 7708c2ecf20Sopenharmony_ci } else 7718c2ecf20Sopenharmony_ci#endif 7728c2ecf20Sopenharmony_ci ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000); 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci /* Finally limit subsequent allocations */ 7758c2ecf20Sopenharmony_ci memblock_set_current_limit(first_memblock_base + ppc64_rma_size); 7768c2ecf20Sopenharmony_ci} 7778c2ecf20Sopenharmony_ci#else /* ! CONFIG_PPC64 */ 7788c2ecf20Sopenharmony_civoid __init early_init_mmu(void) 7798c2ecf20Sopenharmony_ci{ 7808c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_47x 7818c2ecf20Sopenharmony_ci early_init_mmu_47x(); 7828c2ecf20Sopenharmony_ci#endif 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_MM_SLICES 7858c2ecf20Sopenharmony_ci mm_ctx_set_slb_addr_limit(&init_mm.context, SLB_ADDR_LIMIT_DEFAULT); 7868c2ecf20Sopenharmony_ci#endif 7878c2ecf20Sopenharmony_ci} 7888c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */ 789