diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> | 2018-05-29 16:28:41 +0200 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2018-06-03 12:40:34 +0200 |
commit | bd5050e38aec3055ff4257ade987d808ac93b582 (patch) | |
tree | be6977a946ecb940ccd15a099689e86169be1bc0 /arch/powerpc/mm | |
parent | powerpc/mm: Change function prototype (diff) | |
download | linux-bd5050e38aec3055ff4257ade987d808ac93b582.tar.xz linux-bd5050e38aec3055ff4257ade987d808ac93b582.zip |
powerpc/mm/radix: Change pte relax sequence to handle nest MMU hang
When relaxing access (read -> read_write update), pte needs to be marked invalid
to handle a nest MMU bug. We also need to do a tlb flush after the pte is
marked invalid before updating the pte with new access bits.
We also move tlb flush to platform specific __ptep_set_access_flags. This will
help us to gerid of unnecessary tlb flush on BOOK3S 64 later. We don't do that
in this patch. This also helps in avoiding multiple tlbies with coprocessor
attached.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/mm')
-rw-r--r-- | arch/powerpc/mm/pgtable-book3s64.c | 1 | ||||
-rw-r--r-- | arch/powerpc/mm/pgtable-radix.c | 14 | ||||
-rw-r--r-- | arch/powerpc/mm/pgtable.c | 2 |
3 files changed, 10 insertions, 7 deletions
diff --git a/arch/powerpc/mm/pgtable-book3s64.c b/arch/powerpc/mm/pgtable-book3s64.c index 4a8150481a88..82fed87289de 100644 --- a/arch/powerpc/mm/pgtable-book3s64.c +++ b/arch/powerpc/mm/pgtable-book3s64.c @@ -52,7 +52,6 @@ int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address, */ __ptep_set_access_flags(vma, pmdp_ptep(pmdp), pmd_pte(entry), address, MMU_PAGE_2M); - flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE); } return changed; } diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c index 2034cbc9aa56..0ddfe591cd24 100644 --- a/arch/powerpc/mm/pgtable-radix.c +++ b/arch/powerpc/mm/pgtable-radix.c @@ -1091,8 +1091,12 @@ void radix__ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep, struct mm_struct *mm = vma->vm_mm; unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); - - if (cpu_has_feature(CPU_FTR_POWER9_DD1)) { + /* + * To avoid NMMU hang while relaxing access, we need mark + * the pte invalid in between. + */ + if (cpu_has_feature(CPU_FTR_POWER9_DD1) || + atomic_read(&mm->context.copros) > 0) { unsigned long old_pte, new_pte; old_pte = __radix_pte_update(ptep, ~0, 0); @@ -1100,9 +1104,11 @@ void radix__ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep, * new value of pte */ new_pte = old_pte | set; - radix__flush_tlb_pte_p9_dd1(old_pte, mm, address); + radix__flush_tlb_page_psize(mm, address, psize); __radix_pte_update(ptep, 0, new_pte); - } else + } else { __radix_pte_update(ptep, 0, set); + radix__flush_tlb_page_psize(mm, address, psize); + } asm volatile("ptesync" : : : "memory"); } diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index 20cacd33e5be..5281c2c064af 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c @@ -224,7 +224,6 @@ int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address, assert_pte_locked(vma->vm_mm, address); __ptep_set_access_flags(vma, ptep, entry, address, mmu_virtual_psize); - flush_tlb_page(vma, address); } return changed; } @@ -263,7 +262,6 @@ extern int huge_ptep_set_access_flags(struct vm_area_struct *vma, assert_spin_locked(&vma->vm_mm->page_table_lock); #endif __ptep_set_access_flags(vma, ptep, pte, addr, psize); - flush_hugetlb_page(vma, addr); } return changed; #endif |