// SPDX-License-Identifier: GPL-2.0-or-later1/*2* This file contains the routines for flushing entries from the3* TLB and MMU hash table.4*5* Derived from arch/ppc64/mm/init.c:6* Copyright (C) 1995-1996 Gary Thomas ([email protected])7*8* Modifications by Paul Mackerras (PowerMac) ([email protected])9* and Cort Dougan (PReP) ([email protected])10* Copyright (C) 1996 Paul Mackerras11*12* Derived from "arch/i386/mm/init.c"13* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds14*15* Dave Engebretsen <[email protected]>16* Rework for PPC64 port.17*/1819#include <linux/kernel.h>20#include <linux/mm.h>21#include <linux/percpu.h>22#include <linux/hardirq.h>23#include <asm/tlbflush.h>24#include <asm/tlb.h>25#include <asm/bug.h>26#include <asm/pte-walk.h>27#include <kunit/visibility.h>2829#include <trace/events/thp.h>3031DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);32EXPORT_SYMBOL_IF_KUNIT(ppc64_tlb_batch);3334/*35* A linux PTE was changed and the corresponding hash table entry36* neesd to be flushed. This function will either perform the flush37* immediately or will batch it up if the current CPU has an active38* batch on it.39*/40void hpte_need_flush(struct mm_struct *mm, unsigned long addr,41pte_t *ptep, unsigned long pte, int huge)42{43unsigned long vpn;44struct ppc64_tlb_batch *batch = &get_cpu_var(ppc64_tlb_batch);45unsigned long vsid;46unsigned int psize;47int ssize;48real_pte_t rpte;49int i, offset;5051i = batch->index;5253/*54* Get page size (maybe move back to caller).55*56* NOTE: when using special 64K mappings in 4K environment like57* for SPEs, we obtain the page size from the slice, which thus58* must still exist (and thus the VMA not reused) at the time59* of this call60*/61if (huge) {62#ifdef CONFIG_HUGETLB_PAGE63psize = get_slice_psize(mm, addr);64/* Mask the address for the correct page size */65addr &= ~((1UL << mmu_psize_defs[psize].shift) - 1);66if (unlikely(psize == MMU_PAGE_16G))67offset = PTRS_PER_PUD;68else69offset = PTRS_PER_PMD;70#else71BUG();72psize = pte_pagesize_index(mm, addr, pte); /* shutup gcc */73#endif74} else {75psize = pte_pagesize_index(mm, addr, pte);76/*77* Mask the address for the standard page size. If we78* have a 64k page kernel, but the hardware does not79* support 64k pages, this might be different from the80* hardware page size encoded in the slice table.81*/82addr &= PAGE_MASK;83offset = PTRS_PER_PTE;84}858687/* Build full vaddr */88if (!is_kernel_addr(addr)) {89ssize = user_segment_size(addr);90vsid = get_user_vsid(&mm->context, addr, ssize);91} else {92vsid = get_kernel_vsid(addr, mmu_kernel_ssize);93ssize = mmu_kernel_ssize;94}95WARN_ON(vsid == 0);96vpn = hpt_vpn(addr, vsid, ssize);97rpte = __real_pte(__pte(pte), ptep, offset);9899/*100* Check if we have an active batch on this CPU. If not, just101* flush now and return.102*/103if (!is_lazy_mmu_mode_active()) {104flush_hash_page(vpn, rpte, psize, ssize, mm_is_thread_local(mm));105put_cpu_var(ppc64_tlb_batch);106return;107}108109/*110* This can happen when we are in the middle of a TLB batch and111* we encounter memory pressure (eg copy_page_range when it tries112* to allocate a new pte). If we have to reclaim memory and end113* up scanning and resetting referenced bits then our batch context114* will change mid stream.115*116* We also need to ensure only one page size is present in a given117* batch118*/119if (i != 0 && (mm != batch->mm || batch->psize != psize ||120batch->ssize != ssize)) {121__flush_tlb_pending(batch);122i = 0;123}124if (i == 0) {125batch->mm = mm;126batch->psize = psize;127batch->ssize = ssize;128}129batch->pte[i] = rpte;130batch->vpn[i] = vpn;131batch->index = ++i;132if (i >= PPC64_TLB_BATCH_NR)133__flush_tlb_pending(batch);134put_cpu_var(ppc64_tlb_batch);135}136137/*138* This function is called when terminating an mmu batch or when a batch139* is full. It will perform the flush of all the entries currently stored140* in a batch.141*142* Must be called from within some kind of spinlock/non-preempt region...143*/144void __flush_tlb_pending(struct ppc64_tlb_batch *batch)145{146int i, local;147148i = batch->index;149local = mm_is_thread_local(batch->mm);150if (i == 1)151flush_hash_page(batch->vpn[0], batch->pte[0],152batch->psize, batch->ssize, local);153else154flush_hash_range(i, local);155batch->index = 0;156}157EXPORT_SYMBOL_IF_KUNIT(__flush_tlb_pending);158159void hash__tlb_flush(struct mmu_gather *tlb)160{161struct ppc64_tlb_batch *tlbbatch = &get_cpu_var(ppc64_tlb_batch);162163/*164* If there's a TLB batch pending, then we must flush it because the165* pages are going to be freed and we really don't want to have a CPU166* access a freed page because it has a stale TLB167*/168if (tlbbatch->index)169__flush_tlb_pending(tlbbatch);170171put_cpu_var(ppc64_tlb_batch);172}173174/**175* __flush_hash_table_range - Flush all HPTEs for a given address range176* from the hash table (and the TLB). But keeps177* the linux PTEs intact.178*179* @start : starting address180* @end : ending address (not included in the flush)181*182* This function is mostly to be used by some IO hotplug code in order183* to remove all hash entries from a given address range used to map IO184* space on a removed PCI-PCI bidge without tearing down the full mapping185* since 64K pages may overlap with other bridges when using 64K pages186* with 4K HW pages on IO space.187*188* Because of that usage pattern, it is implemented for small size rather189* than speed.190*/191void __flush_hash_table_range(unsigned long start, unsigned long end)192{193int hugepage_shift;194unsigned long flags;195196start = ALIGN_DOWN(start, PAGE_SIZE);197end = ALIGN(end, PAGE_SIZE);198199200/*201* Note: Normally, we should only ever use a batch within a202* PTE locked section. This violates the rule, but will work203* since we don't actually modify the PTEs, we just flush the204* hash while leaving the PTEs intact (including their reference205* to being hashed). This is not the most performance oriented206* way to do things but is fine for our needs here.207*/208local_irq_save(flags);209lazy_mmu_mode_enable();210for (; start < end; start += PAGE_SIZE) {211pte_t *ptep = find_init_mm_pte(start, &hugepage_shift);212unsigned long pte;213214if (ptep == NULL)215continue;216pte = pte_val(*ptep);217if (!(pte & H_PAGE_HASHPTE))218continue;219hpte_need_flush(&init_mm, start, ptep, pte, hugepage_shift);220}221lazy_mmu_mode_disable();222local_irq_restore(flags);223}224225void flush_hash_table_pmd_range(struct mm_struct *mm, pmd_t *pmd, unsigned long addr)226{227pte_t *pte;228pte_t *start_pte;229unsigned long flags;230231addr = ALIGN_DOWN(addr, PMD_SIZE);232/*233* Note: Normally, we should only ever use a batch within a234* PTE locked section. This violates the rule, but will work235* since we don't actually modify the PTEs, we just flush the236* hash while leaving the PTEs intact (including their reference237* to being hashed). This is not the most performance oriented238* way to do things but is fine for our needs here.239*/240local_irq_save(flags);241lazy_mmu_mode_enable();242start_pte = pte_offset_map(pmd, addr);243if (!start_pte)244goto out;245for (pte = start_pte; pte < start_pte + PTRS_PER_PTE; pte++) {246unsigned long pteval = pte_val(*pte);247if (pteval & H_PAGE_HASHPTE)248hpte_need_flush(mm, addr, pte, pteval, 0);249addr += PAGE_SIZE;250}251pte_unmap(start_pte);252out:253lazy_mmu_mode_disable();254local_irq_restore(flags);255}256257258