147d99948SChristophe Leroy // SPDX-License-Identifier: GPL-2.0 247d99948SChristophe Leroy #include <linux/mm.h> 347d99948SChristophe Leroy #include <linux/hugetlb.h> 447d99948SChristophe Leroy #include <linux/security.h> 547d99948SChristophe Leroy #include <asm/cacheflush.h> 647d99948SChristophe Leroy #include <asm/machdep.h> 747d99948SChristophe Leroy #include <asm/mman.h> 847d99948SChristophe Leroy #include <asm/tlb.h> 947d99948SChristophe Leroy 1047d99948SChristophe Leroy void radix__flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr) 1147d99948SChristophe Leroy { 1247d99948SChristophe Leroy int psize; 1347d99948SChristophe Leroy struct hstate *hstate = hstate_file(vma->vm_file); 1447d99948SChristophe Leroy 1547d99948SChristophe Leroy psize = hstate_get_psize(hstate); 1647d99948SChristophe Leroy radix__flush_tlb_page_psize(vma->vm_mm, vmaddr, psize); 1747d99948SChristophe Leroy } 1847d99948SChristophe Leroy 1947d99948SChristophe Leroy void radix__local_flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr) 2047d99948SChristophe Leroy { 2147d99948SChristophe Leroy int psize; 2247d99948SChristophe Leroy struct hstate *hstate = hstate_file(vma->vm_file); 2347d99948SChristophe Leroy 2447d99948SChristophe Leroy psize = hstate_get_psize(hstate); 2547d99948SChristophe Leroy radix__local_flush_tlb_page_psize(vma->vm_mm, vmaddr, psize); 2647d99948SChristophe Leroy } 2747d99948SChristophe Leroy 2847d99948SChristophe Leroy void radix__flush_hugetlb_tlb_range(struct vm_area_struct *vma, unsigned long start, 2947d99948SChristophe Leroy unsigned long end) 3047d99948SChristophe Leroy { 3147d99948SChristophe Leroy int psize; 3247d99948SChristophe Leroy struct hstate *hstate = hstate_file(vma->vm_file); 3347d99948SChristophe Leroy 3447d99948SChristophe Leroy psize = hstate_get_psize(hstate); 35cec6515aSAneesh Kumar K.V /* 36cec6515aSAneesh Kumar K.V * Flush PWC even if we get PUD_SIZE hugetlb invalidate to keep this simpler. 37cec6515aSAneesh Kumar K.V */ 38cec6515aSAneesh Kumar K.V if (end - start >= PUD_SIZE) 39cec6515aSAneesh Kumar K.V radix__flush_tlb_pwc_range_psize(vma->vm_mm, start, end, psize); 40cec6515aSAneesh Kumar K.V else 4147d99948SChristophe Leroy radix__flush_tlb_range_psize(vma->vm_mm, start, end, psize); 42*1af5a810SAlistair Popple mmu_notifier_arch_invalidate_secondary_tlbs(vma->vm_mm, start, end); 4347d99948SChristophe Leroy } 4447d99948SChristophe Leroy 4547d99948SChristophe Leroy void radix__huge_ptep_modify_prot_commit(struct vm_area_struct *vma, 4647d99948SChristophe Leroy unsigned long addr, pte_t *ptep, 4747d99948SChristophe Leroy pte_t old_pte, pte_t pte) 4847d99948SChristophe Leroy { 4947d99948SChristophe Leroy struct mm_struct *mm = vma->vm_mm; 5047d99948SChristophe Leroy 5147d99948SChristophe Leroy /* 522a8a0f42SNicholas Piggin * POWER9 NMMU must flush the TLB after clearing the PTE before 532a8a0f42SNicholas Piggin * installing a PTE with more relaxed access permissions, see 542a8a0f42SNicholas Piggin * radix__ptep_set_access_flags. 5547d99948SChristophe Leroy */ 562a8a0f42SNicholas Piggin if (!cpu_has_feature(CPU_FTR_ARCH_31) && 572a8a0f42SNicholas Piggin is_pte_rw_upgrade(pte_val(old_pte), pte_val(pte)) && 582a8a0f42SNicholas Piggin atomic_read(&mm->context.copros) > 0) 5947d99948SChristophe Leroy radix__flush_hugetlb_page(vma, addr); 6047d99948SChristophe Leroy 6147d99948SChristophe Leroy set_huge_pte_at(vma->vm_mm, addr, ptep, pte); 6247d99948SChristophe Leroy } 63