Skip to content

Commit bd5050e

Browse files
kvaneeshmpe
authored andcommitted
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 <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent e4c1112 commit bd5050e

File tree

7 files changed

+17
-7
lines changed

7 files changed

+17
-7
lines changed

arch/powerpc/include/asm/book3s/32/pgtable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma,
245245
unsigned long clr = ~pte_val(entry) & _PAGE_RO;
246246

247247
pte_update(ptep, clr, set);
248+
249+
flush_tlb_page(vma, address);
248250
}
249251

250252
#define __HAVE_ARCH_PTE_SAME

arch/powerpc/include/asm/nohash/32/pgtable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,8 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma,
266266
unsigned long clr = ~pte_val(entry) & (_PAGE_RO | _PAGE_NA);
267267

268268
pte_update(ptep, clr, set);
269+
270+
flush_tlb_page(vma, address);
269271
}
270272

271273
static inline int pte_young(pte_t pte)

arch/powerpc/include/asm/nohash/64/pgtable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,8 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma,
304304
unsigned long old = pte_val(*ptep);
305305
*ptep = __pte(old | bits);
306306
#endif
307+
308+
flush_tlb_page(vma, address);
307309
}
308310

309311
#define __HAVE_ARCH_PTE_SAME

arch/powerpc/include/asm/pgtable.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <asm/processor.h> /* For TASK_SIZE */
99
#include <asm/mmu.h>
1010
#include <asm/page.h>
11+
#include <asm/tlbflush.h>
1112

1213
struct mm_struct;
1314

arch/powerpc/mm/pgtable-book3s64.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address,
5252
*/
5353
__ptep_set_access_flags(vma, pmdp_ptep(pmdp),
5454
pmd_pte(entry), address, MMU_PAGE_2M);
55-
flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
5655
}
5756
return changed;
5857
}

arch/powerpc/mm/pgtable-radix.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,18 +1091,24 @@ void radix__ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep,
10911091
struct mm_struct *mm = vma->vm_mm;
10921092
unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_ACCESSED |
10931093
_PAGE_RW | _PAGE_EXEC);
1094-
1095-
if (cpu_has_feature(CPU_FTR_POWER9_DD1)) {
1094+
/*
1095+
* To avoid NMMU hang while relaxing access, we need mark
1096+
* the pte invalid in between.
1097+
*/
1098+
if (cpu_has_feature(CPU_FTR_POWER9_DD1) ||
1099+
atomic_read(&mm->context.copros) > 0) {
10961100
unsigned long old_pte, new_pte;
10971101

10981102
old_pte = __radix_pte_update(ptep, ~0, 0);
10991103
/*
11001104
* new value of pte
11011105
*/
11021106
new_pte = old_pte | set;
1103-
radix__flush_tlb_pte_p9_dd1(old_pte, mm, address);
1107+
radix__flush_tlb_page_psize(mm, address, psize);
11041108
__radix_pte_update(ptep, 0, new_pte);
1105-
} else
1109+
} else {
11061110
__radix_pte_update(ptep, 0, set);
1111+
radix__flush_tlb_page_psize(mm, address, psize);
1112+
}
11071113
asm volatile("ptesync" : : : "memory");
11081114
}

arch/powerpc/mm/pgtable.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,6 @@ int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
224224
assert_pte_locked(vma->vm_mm, address);
225225
__ptep_set_access_flags(vma, ptep, entry,
226226
address, mmu_virtual_psize);
227-
flush_tlb_page(vma, address);
228227
}
229228
return changed;
230229
}
@@ -263,7 +262,6 @@ extern int huge_ptep_set_access_flags(struct vm_area_struct *vma,
263262
assert_spin_locked(&vma->vm_mm->page_table_lock);
264263
#endif
265264
__ptep_set_access_flags(vma, ptep, pte, addr, psize);
266-
flush_hugetlb_page(vma, addr);
267265
}
268266
return changed;
269267
#endif

0 commit comments

Comments
 (0)