162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <linux/mm.h> 362306a36Sopenharmony_ci#include <linux/hugetlb.h> 462306a36Sopenharmony_ci#include <linux/security.h> 562306a36Sopenharmony_ci#include <asm/cacheflush.h> 662306a36Sopenharmony_ci#include <asm/machdep.h> 762306a36Sopenharmony_ci#include <asm/mman.h> 862306a36Sopenharmony_ci#include <asm/tlb.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_civoid radix__flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr) 1162306a36Sopenharmony_ci{ 1262306a36Sopenharmony_ci int psize; 1362306a36Sopenharmony_ci struct hstate *hstate = hstate_file(vma->vm_file); 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci psize = hstate_get_psize(hstate); 1662306a36Sopenharmony_ci radix__flush_tlb_page_psize(vma->vm_mm, vmaddr, psize); 1762306a36Sopenharmony_ci} 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_civoid radix__local_flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci int psize; 2262306a36Sopenharmony_ci struct hstate *hstate = hstate_file(vma->vm_file); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci psize = hstate_get_psize(hstate); 2562306a36Sopenharmony_ci radix__local_flush_tlb_page_psize(vma->vm_mm, vmaddr, psize); 2662306a36Sopenharmony_ci} 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_civoid radix__flush_hugetlb_tlb_range(struct vm_area_struct *vma, unsigned long start, 2962306a36Sopenharmony_ci unsigned long end) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci int psize; 3262306a36Sopenharmony_ci struct hstate *hstate = hstate_file(vma->vm_file); 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci psize = hstate_get_psize(hstate); 3562306a36Sopenharmony_ci /* 3662306a36Sopenharmony_ci * Flush PWC even if we get PUD_SIZE hugetlb invalidate to keep this simpler. 3762306a36Sopenharmony_ci */ 3862306a36Sopenharmony_ci if (end - start >= PUD_SIZE) 3962306a36Sopenharmony_ci radix__flush_tlb_pwc_range_psize(vma->vm_mm, start, end, psize); 4062306a36Sopenharmony_ci else 4162306a36Sopenharmony_ci radix__flush_tlb_range_psize(vma->vm_mm, start, end, psize); 4262306a36Sopenharmony_ci mmu_notifier_arch_invalidate_secondary_tlbs(vma->vm_mm, start, end); 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_civoid radix__huge_ptep_modify_prot_commit(struct vm_area_struct *vma, 4662306a36Sopenharmony_ci unsigned long addr, pte_t *ptep, 4762306a36Sopenharmony_ci pte_t old_pte, pte_t pte) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci struct mm_struct *mm = vma->vm_mm; 5062306a36Sopenharmony_ci unsigned long psize = huge_page_size(hstate_vma(vma)); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci /* 5362306a36Sopenharmony_ci * POWER9 NMMU must flush the TLB after clearing the PTE before 5462306a36Sopenharmony_ci * installing a PTE with more relaxed access permissions, see 5562306a36Sopenharmony_ci * radix__ptep_set_access_flags. 5662306a36Sopenharmony_ci */ 5762306a36Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_ARCH_31) && 5862306a36Sopenharmony_ci is_pte_rw_upgrade(pte_val(old_pte), pte_val(pte)) && 5962306a36Sopenharmony_ci atomic_read(&mm->context.copros) > 0) 6062306a36Sopenharmony_ci radix__flush_hugetlb_page(vma, addr); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci set_huge_pte_at(vma->vm_mm, addr, ptep, pte, psize); 6362306a36Sopenharmony_ci} 64