aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2014-12-04 00:30:14 -0500
committerMichael Ellerman <mpe@ellerman.id.au>2014-12-05 00:26:15 -0500
commitaefa5688c070727b8729de1aef85cad7b9933fc7 (patch)
treed6036007b0eca0b325aa3f050defb00f89341209 /arch/powerpc
parentabb90ee7bca5af977b90a0c6be44f631fdacc932 (diff)
powerpc/mm: don't do tlbie for updatepp request with NO HPTE fault
upatepp can get called for a nohpte fault when we find from the linux page table that the translation was hashed before. In that case we are sure that there is no existing translation, hence we could avoid doing tlbie. We could possibly race with a parallel fault filling the TLB. But that should be ok because updatepp is only ever relaxing permissions. We also look at linux pte permission bits when filling hash pte permission bits. We also hold the linux pte busy bits while inserting/updating a hashpte entry, hence a paralle update of linux pte is not possible. On the other hand mprotect involves ptep_modify_prot_start which cause a hpte invalidate and not updatepp. Performance number: We use randbox_access_bench written by Anton. Kernel with THP disabled and smaller hash page table size. 86.60% random_access_b [kernel.kallsyms] [k] .native_hpte_updatepp 2.10% random_access_b random_access_bench [.] doit 1.99% random_access_b [kernel.kallsyms] [k] .do_raw_spin_lock 1.85% random_access_b [kernel.kallsyms] [k] .native_hpte_insert 1.26% random_access_b [kernel.kallsyms] [k] .native_flush_hash_range 1.18% random_access_b [kernel.kallsyms] [k] .__delay 0.69% random_access_b [kernel.kallsyms] [k] .native_hpte_remove 0.37% random_access_b [kernel.kallsyms] [k] .clear_user_page 0.34% random_access_b [kernel.kallsyms] [k] .__hash_page_64K 0.32% random_access_b [kernel.kallsyms] [k] fast_exception_return 0.30% random_access_b [kernel.kallsyms] [k] .hash_page_mm With Fix: 27.54% random_access_b random_access_bench [.] doit 22.90% random_access_b [kernel.kallsyms] [k] .native_hpte_insert 5.76% random_access_b [kernel.kallsyms] [k] .native_hpte_remove 5.20% random_access_b [kernel.kallsyms] [k] fast_exception_return 5.12% random_access_b [kernel.kallsyms] [k] .__hash_page_64K 4.80% random_access_b [kernel.kallsyms] [k] .hash_page_mm 3.31% random_access_b [kernel.kallsyms] [k] data_access_common 1.84% random_access_b [kernel.kallsyms] [k] .trace_hardirqs_on_caller Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/machdep.h2
-rw-r--r--arch/powerpc/include/asm/mmu-hash64.h22
-rw-r--r--arch/powerpc/include/asm/tlbflush.h4
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S2
-rw-r--r--arch/powerpc/mm/hash_low_64.S15
-rw-r--r--arch/powerpc/mm/hash_native_64.c15
-rw-r--r--arch/powerpc/mm/hash_utils_64.c44
-rw-r--r--arch/powerpc/mm/hugepage-hash64.c8
-rw-r--r--arch/powerpc/mm/hugetlbpage-hash64.c6
-rw-r--r--arch/powerpc/mm/pgtable_64.c7
-rw-r--r--arch/powerpc/platforms/cell/beat_htab.c4
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c5
-rw-r--r--arch/powerpc/platforms/cell/spufs/fault.c2
-rw-r--r--arch/powerpc/platforms/ps3/htab.c2
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c2
15 files changed, 85 insertions, 55 deletions
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index e5c0919acca4..c8175a3fe560 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -42,7 +42,7 @@ struct machdep_calls {
42 unsigned long newpp, 42 unsigned long newpp,
43 unsigned long vpn, 43 unsigned long vpn,
44 int bpsize, int apsize, 44 int bpsize, int apsize,
45 int ssize, int local); 45 int ssize, unsigned long flags);
46 void (*hpte_updateboltedpp)(unsigned long newpp, 46 void (*hpte_updateboltedpp)(unsigned long newpp,
47 unsigned long ea, 47 unsigned long ea,
48 int psize, int ssize); 48 int psize, int ssize);
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index aeebc94b2bce..4f13c3ed7acf 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -316,27 +316,33 @@ static inline unsigned long hpt_hash(unsigned long vpn,
316 return hash & 0x7fffffffffUL; 316 return hash & 0x7fffffffffUL;
317} 317}
318 318
319#define HPTE_LOCAL_UPDATE 0x1
320#define HPTE_NOHPTE_UPDATE 0x2
321
319extern int __hash_page_4K(unsigned long ea, unsigned long access, 322extern int __hash_page_4K(unsigned long ea, unsigned long access,
320 unsigned long vsid, pte_t *ptep, unsigned long trap, 323 unsigned long vsid, pte_t *ptep, unsigned long trap,
321 unsigned int local, int ssize, int subpage_prot); 324 unsigned long flags, int ssize, int subpage_prot);
322extern int __hash_page_64K(unsigned long ea, unsigned long access, 325extern int __hash_page_64K(unsigned long ea, unsigned long access,
323 unsigned long vsid, pte_t *ptep, unsigned long trap, 326 unsigned long vsid, pte_t *ptep, unsigned long trap,
324 unsigned int local, int ssize); 327 unsigned long flags, int ssize);
325struct mm_struct; 328struct mm_struct;
326unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap); 329unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap);
327extern int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, unsigned long trap); 330extern int hash_page_mm(struct mm_struct *mm, unsigned long ea,
328extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); 331 unsigned long access, unsigned long trap,
332 unsigned long flags);
333extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap,
334 unsigned long dsisr);
329int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, 335int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
330 pte_t *ptep, unsigned long trap, int local, int ssize, 336 pte_t *ptep, unsigned long trap, unsigned long flags,
331 unsigned int shift, unsigned int mmu_psize); 337 int ssize, unsigned int shift, unsigned int mmu_psize);
332#ifdef CONFIG_TRANSPARENT_HUGEPAGE 338#ifdef CONFIG_TRANSPARENT_HUGEPAGE
333extern int __hash_page_thp(unsigned long ea, unsigned long access, 339extern int __hash_page_thp(unsigned long ea, unsigned long access,
334 unsigned long vsid, pmd_t *pmdp, unsigned long trap, 340 unsigned long vsid, pmd_t *pmdp, unsigned long trap,
335 int local, int ssize, unsigned int psize); 341 unsigned long flags, int ssize, unsigned int psize);
336#else 342#else
337static inline int __hash_page_thp(unsigned long ea, unsigned long access, 343static inline int __hash_page_thp(unsigned long ea, unsigned long access,
338 unsigned long vsid, pmd_t *pmdp, 344 unsigned long vsid, pmd_t *pmdp,
339 unsigned long trap, int local, 345 unsigned long trap, unsigned long flags,
340 int ssize, unsigned int psize) 346 int ssize, unsigned int psize)
341{ 347{
342 BUG(); 348 BUG();
diff --git a/arch/powerpc/include/asm/tlbflush.h b/arch/powerpc/include/asm/tlbflush.h
index 4d3ecd8d8929..23d351ca0303 100644
--- a/arch/powerpc/include/asm/tlbflush.h
+++ b/arch/powerpc/include/asm/tlbflush.h
@@ -125,11 +125,11 @@ static inline void arch_leave_lazy_mmu_mode(void)
125 125
126 126
127extern void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, 127extern void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize,
128 int ssize, int local); 128 int ssize, unsigned long flags);
129extern void flush_hash_range(unsigned long number, int local); 129extern void flush_hash_range(unsigned long number, int local);
130extern void flush_hash_hugepage(unsigned long vsid, unsigned long addr, 130extern void flush_hash_hugepage(unsigned long vsid, unsigned long addr,
131 pmd_t *pmdp, unsigned int psize, int ssize, 131 pmd_t *pmdp, unsigned int psize, int ssize,
132 int local); 132 unsigned long flags);
133 133
134static inline void local_flush_tlb_mm(struct mm_struct *mm) 134static inline void local_flush_tlb_mm(struct mm_struct *mm)
135{ 135{
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index ad62f4d6ce31..6213f494f40b 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1565,9 +1565,11 @@ do_hash_page:
1565 * r3 contains the faulting address 1565 * r3 contains the faulting address
1566 * r4 contains the required access permissions 1566 * r4 contains the required access permissions
1567 * r5 contains the trap number 1567 * r5 contains the trap number
1568 * r6 contains dsisr
1568 * 1569 *
1569 * at return r3 = 0 for success, 1 for page fault, negative for error 1570 * at return r3 = 0 for success, 1 for page fault, negative for error
1570 */ 1571 */
1572 ld r6,_DSISR(r1)
1571 bl hash_page /* build HPTE if possible */ 1573 bl hash_page /* build HPTE if possible */
1572 cmpdi r3,0 /* see if hash_page succeeded */ 1574 cmpdi r3,0 /* see if hash_page succeeded */
1573 1575
diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S
index 5094f32b706e..463174a4a647 100644
--- a/arch/powerpc/mm/hash_low_64.S
+++ b/arch/powerpc/mm/hash_low_64.S
@@ -46,7 +46,8 @@
46 46
47/* 47/*
48 * _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid, 48 * _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
49 * pte_t *ptep, unsigned long trap, int local, int ssize) 49 * pte_t *ptep, unsigned long trap, unsigned long flags,
50 * int ssize)
50 * 51 *
51 * Adds a 4K page to the hash table in a segment of 4K pages only 52 * Adds a 4K page to the hash table in a segment of 4K pages only
52 */ 53 */
@@ -298,7 +299,7 @@ htab_modify_pte:
298 li r6,MMU_PAGE_4K /* base page size */ 299 li r6,MMU_PAGE_4K /* base page size */
299 li r7,MMU_PAGE_4K /* actual page size */ 300 li r7,MMU_PAGE_4K /* actual page size */
300 ld r8,STK_PARAM(R9)(r1) /* segment size */ 301 ld r8,STK_PARAM(R9)(r1) /* segment size */
301 ld r9,STK_PARAM(R8)(r1) /* get "local" param */ 302 ld r9,STK_PARAM(R8)(r1) /* get "flags" param */
302.globl htab_call_hpte_updatepp 303.globl htab_call_hpte_updatepp
303htab_call_hpte_updatepp: 304htab_call_hpte_updatepp:
304 bl . /* Patched by htab_finish_init() */ 305 bl . /* Patched by htab_finish_init() */
@@ -338,8 +339,8 @@ htab_pte_insert_failure:
338 *****************************************************************************/ 339 *****************************************************************************/
339 340
340/* _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid, 341/* _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
341 * pte_t *ptep, unsigned long trap, int local, int ssize, 342 * pte_t *ptep, unsigned long trap, unsigned local flags,
342 * int subpg_prot) 343 * int ssize, int subpg_prot)
343 */ 344 */
344 345
345/* 346/*
@@ -594,7 +595,7 @@ htab_inval_old_hpte:
594 li r5,0 /* PTE.hidx */ 595 li r5,0 /* PTE.hidx */
595 li r6,MMU_PAGE_64K /* psize */ 596 li r6,MMU_PAGE_64K /* psize */
596 ld r7,STK_PARAM(R9)(r1) /* ssize */ 597 ld r7,STK_PARAM(R9)(r1) /* ssize */
597 ld r8,STK_PARAM(R8)(r1) /* local */ 598 ld r8,STK_PARAM(R8)(r1) /* flags */
598 bl flush_hash_page 599 bl flush_hash_page
599 /* Clear out _PAGE_HPTE_SUB bits in the new linux PTE */ 600 /* Clear out _PAGE_HPTE_SUB bits in the new linux PTE */
600 lis r0,_PAGE_HPTE_SUB@h 601 lis r0,_PAGE_HPTE_SUB@h
@@ -666,7 +667,7 @@ htab_modify_pte:
666 li r6,MMU_PAGE_4K /* base page size */ 667 li r6,MMU_PAGE_4K /* base page size */
667 li r7,MMU_PAGE_4K /* actual page size */ 668 li r7,MMU_PAGE_4K /* actual page size */
668 ld r8,STK_PARAM(R9)(r1) /* segment size */ 669 ld r8,STK_PARAM(R9)(r1) /* segment size */
669 ld r9,STK_PARAM(R8)(r1) /* get "local" param */ 670 ld r9,STK_PARAM(R8)(r1) /* get "flags" param */
670.globl htab_call_hpte_updatepp 671.globl htab_call_hpte_updatepp
671htab_call_hpte_updatepp: 672htab_call_hpte_updatepp:
672 bl . /* patched by htab_finish_init() */ 673 bl . /* patched by htab_finish_init() */
@@ -962,7 +963,7 @@ ht64_modify_pte:
962 li r6,MMU_PAGE_64K /* base page size */ 963 li r6,MMU_PAGE_64K /* base page size */
963 li r7,MMU_PAGE_64K /* actual page size */ 964 li r7,MMU_PAGE_64K /* actual page size */
964 ld r8,STK_PARAM(R9)(r1) /* segment size */ 965 ld r8,STK_PARAM(R9)(r1) /* segment size */
965 ld r9,STK_PARAM(R8)(r1) /* get "local" param */ 966 ld r9,STK_PARAM(R8)(r1) /* get "flags" param */
966.globl ht64_call_hpte_updatepp 967.globl ht64_call_hpte_updatepp
967ht64_call_hpte_updatepp: 968ht64_call_hpte_updatepp:
968 bl . /* patched by htab_finish_init() */ 969 bl . /* patched by htab_finish_init() */
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 13700911b522..9c4880ddecd6 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -283,11 +283,11 @@ static long native_hpte_remove(unsigned long hpte_group)
283 283
284static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, 284static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
285 unsigned long vpn, int bpsize, 285 unsigned long vpn, int bpsize,
286 int apsize, int ssize, int local) 286 int apsize, int ssize, unsigned long flags)
287{ 287{
288 struct hash_pte *hptep = htab_address + slot; 288 struct hash_pte *hptep = htab_address + slot;
289 unsigned long hpte_v, want_v; 289 unsigned long hpte_v, want_v;
290 int ret = 0; 290 int ret = 0, local = 0;
291 291
292 want_v = hpte_encode_avpn(vpn, bpsize, ssize); 292 want_v = hpte_encode_avpn(vpn, bpsize, ssize);
293 293
@@ -322,8 +322,15 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
322 } 322 }
323 native_unlock_hpte(hptep); 323 native_unlock_hpte(hptep);
324 } 324 }
325 /* Ensure it is out of the tlb too. */ 325
326 tlbie(vpn, bpsize, apsize, ssize, local); 326 if (flags & HPTE_LOCAL_UPDATE)
327 local = 1;
328 /*
329 * Ensure it is out of the tlb too if it is not a nohpte fault
330 */
331 if (!(flags & HPTE_NOHPTE_UPDATE))
332 tlbie(vpn, bpsize, apsize, ssize, local);
333
327 return ret; 334 return ret;
328} 335}
329 336
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 68211d398fdb..e56a307bc676 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -989,7 +989,9 @@ static void check_paca_psize(unsigned long ea, struct mm_struct *mm,
989 * -1 - critical hash insertion error 989 * -1 - critical hash insertion error
990 * -2 - access not permitted by subpage protection mechanism 990 * -2 - access not permitted by subpage protection mechanism
991 */ 991 */
992int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, unsigned long trap) 992int hash_page_mm(struct mm_struct *mm, unsigned long ea,
993 unsigned long access, unsigned long trap,
994 unsigned long flags)
993{ 995{
994 enum ctx_state prev_state = exception_enter(); 996 enum ctx_state prev_state = exception_enter();
995 pgd_t *pgdir; 997 pgd_t *pgdir;
@@ -997,7 +999,7 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, u
997 pte_t *ptep; 999 pte_t *ptep;
998 unsigned hugeshift; 1000 unsigned hugeshift;
999 const struct cpumask *tmp; 1001 const struct cpumask *tmp;
1000 int rc, user_region = 0, local = 0; 1002 int rc, user_region = 0;
1001 int psize, ssize; 1003 int psize, ssize;
1002 1004
1003 DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n", 1005 DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n",
@@ -1049,7 +1051,7 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, u
1049 /* Check CPU locality */ 1051 /* Check CPU locality */
1050 tmp = cpumask_of(smp_processor_id()); 1052 tmp = cpumask_of(smp_processor_id());
1051 if (user_region && cpumask_equal(mm_cpumask(mm), tmp)) 1053 if (user_region && cpumask_equal(mm_cpumask(mm), tmp))
1052 local = 1; 1054 flags |= HPTE_LOCAL_UPDATE;
1053 1055
1054#ifndef CONFIG_PPC_64K_PAGES 1056#ifndef CONFIG_PPC_64K_PAGES
1055 /* If we use 4K pages and our psize is not 4K, then we might 1057 /* If we use 4K pages and our psize is not 4K, then we might
@@ -1086,11 +1088,11 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, u
1086 if (hugeshift) { 1088 if (hugeshift) {
1087 if (pmd_trans_huge(*(pmd_t *)ptep)) 1089 if (pmd_trans_huge(*(pmd_t *)ptep))
1088 rc = __hash_page_thp(ea, access, vsid, (pmd_t *)ptep, 1090 rc = __hash_page_thp(ea, access, vsid, (pmd_t *)ptep,
1089 trap, local, ssize, psize); 1091 trap, flags, ssize, psize);
1090#ifdef CONFIG_HUGETLB_PAGE 1092#ifdef CONFIG_HUGETLB_PAGE
1091 else 1093 else
1092 rc = __hash_page_huge(ea, access, vsid, ptep, trap, 1094 rc = __hash_page_huge(ea, access, vsid, ptep, trap,
1093 local, ssize, hugeshift, psize); 1095 flags, ssize, hugeshift, psize);
1094#else 1096#else
1095 else { 1097 else {
1096 /* 1098 /*
@@ -1149,7 +1151,8 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, u
1149 1151
1150#ifdef CONFIG_PPC_HAS_HASH_64K 1152#ifdef CONFIG_PPC_HAS_HASH_64K
1151 if (psize == MMU_PAGE_64K) 1153 if (psize == MMU_PAGE_64K)
1152 rc = __hash_page_64K(ea, access, vsid, ptep, trap, local, ssize); 1154 rc = __hash_page_64K(ea, access, vsid, ptep, trap,
1155 flags, ssize);
1153 else 1156 else
1154#endif /* CONFIG_PPC_HAS_HASH_64K */ 1157#endif /* CONFIG_PPC_HAS_HASH_64K */
1155 { 1158 {
@@ -1158,7 +1161,7 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, u
1158 rc = -2; 1161 rc = -2;
1159 else 1162 else
1160 rc = __hash_page_4K(ea, access, vsid, ptep, trap, 1163 rc = __hash_page_4K(ea, access, vsid, ptep, trap,
1161 local, ssize, spp); 1164 flags, ssize, spp);
1162 } 1165 }
1163 1166
1164 /* Dump some info in case of hash insertion failure, they should 1167 /* Dump some info in case of hash insertion failure, they should
@@ -1181,14 +1184,19 @@ bail:
1181} 1184}
1182EXPORT_SYMBOL_GPL(hash_page_mm); 1185EXPORT_SYMBOL_GPL(hash_page_mm);
1183 1186
1184int hash_page(unsigned long ea, unsigned long access, unsigned long trap) 1187int hash_page(unsigned long ea, unsigned long access, unsigned long trap,
1188 unsigned long dsisr)
1185{ 1189{
1190 unsigned long flags = 0;
1186 struct mm_struct *mm = current->mm; 1191 struct mm_struct *mm = current->mm;
1187 1192
1188 if (REGION_ID(ea) == VMALLOC_REGION_ID) 1193 if (REGION_ID(ea) == VMALLOC_REGION_ID)
1189 mm = &init_mm; 1194 mm = &init_mm;
1190 1195
1191 return hash_page_mm(mm, ea, access, trap); 1196 if (dsisr & DSISR_NOHPTE)
1197 flags |= HPTE_NOHPTE_UPDATE;
1198
1199 return hash_page_mm(mm, ea, access, trap, flags);
1192} 1200}
1193EXPORT_SYMBOL_GPL(hash_page); 1201EXPORT_SYMBOL_GPL(hash_page);
1194 1202
@@ -1200,7 +1208,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
1200 pgd_t *pgdir; 1208 pgd_t *pgdir;
1201 pte_t *ptep; 1209 pte_t *ptep;
1202 unsigned long flags; 1210 unsigned long flags;
1203 int rc, ssize, local = 0; 1211 int rc, ssize, update_flags = 0;
1204 1212
1205 BUG_ON(REGION_ID(ea) != USER_REGION_ID); 1213 BUG_ON(REGION_ID(ea) != USER_REGION_ID);
1206 1214
@@ -1251,16 +1259,17 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
1251 1259
1252 /* Is that local to this CPU ? */ 1260 /* Is that local to this CPU ? */
1253 if (cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) 1261 if (cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id())))
1254 local = 1; 1262 update_flags |= HPTE_LOCAL_UPDATE;
1255 1263
1256 /* Hash it in */ 1264 /* Hash it in */
1257#ifdef CONFIG_PPC_HAS_HASH_64K 1265#ifdef CONFIG_PPC_HAS_HASH_64K
1258 if (mm->context.user_psize == MMU_PAGE_64K) 1266 if (mm->context.user_psize == MMU_PAGE_64K)
1259 rc = __hash_page_64K(ea, access, vsid, ptep, trap, local, ssize); 1267 rc = __hash_page_64K(ea, access, vsid, ptep, trap,
1268 update_flags, ssize);
1260 else 1269 else
1261#endif /* CONFIG_PPC_HAS_HASH_64K */ 1270#endif /* CONFIG_PPC_HAS_HASH_64K */
1262 rc = __hash_page_4K(ea, access, vsid, ptep, trap, local, ssize, 1271 rc = __hash_page_4K(ea, access, vsid, ptep, trap, update_flags,
1263 subpage_protection(mm, ea)); 1272 ssize, subpage_protection(mm, ea));
1264 1273
1265 /* Dump some info in case of hash insertion failure, they should 1274 /* Dump some info in case of hash insertion failure, they should
1266 * never happen so it is really useful to know if/when they do 1275 * never happen so it is really useful to know if/when they do
@@ -1278,9 +1287,10 @@ out_exit:
1278 * do not forget to update the assembly call site ! 1287 * do not forget to update the assembly call site !
1279 */ 1288 */
1280void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize, 1289void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize,
1281 int local) 1290 unsigned long flags)
1282{ 1291{
1283 unsigned long hash, index, shift, hidx, slot; 1292 unsigned long hash, index, shift, hidx, slot;
1293 int local = flags & HPTE_LOCAL_UPDATE;
1284 1294
1285 DBG_LOW("flush_hash_page(vpn=%016lx)\n", vpn); 1295 DBG_LOW("flush_hash_page(vpn=%016lx)\n", vpn);
1286 pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) { 1296 pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) {
@@ -1317,12 +1327,14 @@ void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize,
1317 1327
1318#ifdef CONFIG_TRANSPARENT_HUGEPAGE 1328#ifdef CONFIG_TRANSPARENT_HUGEPAGE
1319void flush_hash_hugepage(unsigned long vsid, unsigned long addr, 1329void flush_hash_hugepage(unsigned long vsid, unsigned long addr,
1320 pmd_t *pmdp, unsigned int psize, int ssize, int local) 1330 pmd_t *pmdp, unsigned int psize, int ssize,
1331 unsigned long flags)
1321{ 1332{
1322 int i, max_hpte_count, valid; 1333 int i, max_hpte_count, valid;
1323 unsigned long s_addr; 1334 unsigned long s_addr;
1324 unsigned char *hpte_slot_array; 1335 unsigned char *hpte_slot_array;
1325 unsigned long hidx, shift, vpn, hash, slot; 1336 unsigned long hidx, shift, vpn, hash, slot;
1337 int local = flags & HPTE_LOCAL_UPDATE;
1326 1338
1327 s_addr = addr & HPAGE_PMD_MASK; 1339 s_addr = addr & HPAGE_PMD_MASK;
1328 hpte_slot_array = get_hpte_slot_array(pmdp); 1340 hpte_slot_array = get_hpte_slot_array(pmdp);
diff --git a/arch/powerpc/mm/hugepage-hash64.c b/arch/powerpc/mm/hugepage-hash64.c
index 3a648cd363ae..86686514ae13 100644
--- a/arch/powerpc/mm/hugepage-hash64.c
+++ b/arch/powerpc/mm/hugepage-hash64.c
@@ -19,8 +19,8 @@
19#include <asm/machdep.h> 19#include <asm/machdep.h>
20 20
21int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, 21int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
22 pmd_t *pmdp, unsigned long trap, int local, int ssize, 22 pmd_t *pmdp, unsigned long trap, unsigned long flags,
23 unsigned int psize) 23 int ssize, unsigned int psize)
24{ 24{
25 unsigned int index, valid; 25 unsigned int index, valid;
26 unsigned char *hpte_slot_array; 26 unsigned char *hpte_slot_array;
@@ -95,7 +95,7 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
95 */ 95 */
96 if ((old_pmd & _PAGE_HASHPTE) && !(old_pmd & _PAGE_COMBO)) 96 if ((old_pmd & _PAGE_HASHPTE) && !(old_pmd & _PAGE_COMBO))
97 flush_hash_hugepage(vsid, ea, pmdp, MMU_PAGE_64K, 97 flush_hash_hugepage(vsid, ea, pmdp, MMU_PAGE_64K,
98 ssize, local); 98 ssize, flags);
99 } 99 }
100 100
101 valid = hpte_valid(hpte_slot_array, index); 101 valid = hpte_valid(hpte_slot_array, index);
@@ -108,7 +108,7 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
108 slot += hidx & _PTEIDX_GROUP_IX; 108 slot += hidx & _PTEIDX_GROUP_IX;
109 109
110 ret = ppc_md.hpte_updatepp(slot, rflags, vpn, 110 ret = ppc_md.hpte_updatepp(slot, rflags, vpn,
111 psize, lpsize, ssize, local); 111 psize, lpsize, ssize, flags);
112 /* 112 /*
113 * We failed to update, try to insert a new entry. 113 * We failed to update, try to insert a new entry.
114 */ 114 */
diff --git a/arch/powerpc/mm/hugetlbpage-hash64.c b/arch/powerpc/mm/hugetlbpage-hash64.c
index a5bcf9301196..d94b1af53a93 100644
--- a/arch/powerpc/mm/hugetlbpage-hash64.c
+++ b/arch/powerpc/mm/hugetlbpage-hash64.c
@@ -19,8 +19,8 @@ extern long hpte_insert_repeating(unsigned long hash, unsigned long vpn,
19 unsigned long vflags, int psize, int ssize); 19 unsigned long vflags, int psize, int ssize);
20 20
21int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, 21int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
22 pte_t *ptep, unsigned long trap, int local, int ssize, 22 pte_t *ptep, unsigned long trap, unsigned long flags,
23 unsigned int shift, unsigned int mmu_psize) 23 int ssize, unsigned int shift, unsigned int mmu_psize)
24{ 24{
25 unsigned long vpn; 25 unsigned long vpn;
26 unsigned long old_pte, new_pte; 26 unsigned long old_pte, new_pte;
@@ -81,7 +81,7 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
81 slot += (old_pte & _PAGE_F_GIX) >> 12; 81 slot += (old_pte & _PAGE_F_GIX) >> 12;
82 82
83 if (ppc_md.hpte_updatepp(slot, rflags, vpn, mmu_psize, 83 if (ppc_md.hpte_updatepp(slot, rflags, vpn, mmu_psize,
84 mmu_psize, ssize, local) == -1) 84 mmu_psize, ssize, flags) == -1)
85 old_pte &= ~_PAGE_HPTEFLAGS; 85 old_pte &= ~_PAGE_HPTEFLAGS;
86 } 86 }
87 87
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index eea9fa1f8ae7..4fe5f64cc179 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -739,9 +739,10 @@ void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
739void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, 739void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr,
740 pmd_t *pmdp, unsigned long old_pmd) 740 pmd_t *pmdp, unsigned long old_pmd)
741{ 741{
742 int ssize, local = 0; 742 int ssize;
743 unsigned int psize; 743 unsigned int psize;
744 unsigned long vsid; 744 unsigned long vsid;
745 unsigned long flags = 0;
745 const struct cpumask *tmp; 746 const struct cpumask *tmp;
746 747
747 /* get the base page size,vsid and segment size */ 748 /* get the base page size,vsid and segment size */
@@ -765,9 +766,9 @@ void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr,
765 766
766 tmp = cpumask_of(smp_processor_id()); 767 tmp = cpumask_of(smp_processor_id());
767 if (cpumask_equal(mm_cpumask(mm), tmp)) 768 if (cpumask_equal(mm_cpumask(mm), tmp))
768 local = 1; 769 flags |= HPTE_LOCAL_UPDATE;
769 770
770 return flush_hash_hugepage(vsid, addr, pmdp, psize, ssize, local); 771 return flush_hash_hugepage(vsid, addr, pmdp, psize, ssize, flags);
771} 772}
772 773
773static pmd_t pmd_set_protbits(pmd_t pmd, pgprot_t pgprot) 774static pmd_t pmd_set_protbits(pmd_t pmd, pgprot_t pgprot)
diff --git a/arch/powerpc/platforms/cell/beat_htab.c b/arch/powerpc/platforms/cell/beat_htab.c
index d4d245c0d787..bee9232fe619 100644
--- a/arch/powerpc/platforms/cell/beat_htab.c
+++ b/arch/powerpc/platforms/cell/beat_htab.c
@@ -186,7 +186,7 @@ static long beat_lpar_hpte_updatepp(unsigned long slot,
186 unsigned long newpp, 186 unsigned long newpp,
187 unsigned long vpn, 187 unsigned long vpn,
188 int psize, int apsize, 188 int psize, int apsize,
189 int ssize, int local) 189 int ssize, unsigned long flags)
190{ 190{
191 unsigned long lpar_rc; 191 unsigned long lpar_rc;
192 u64 dummy0, dummy1; 192 u64 dummy0, dummy1;
@@ -369,7 +369,7 @@ static long beat_lpar_hpte_updatepp_v3(unsigned long slot,
369 unsigned long newpp, 369 unsigned long newpp,
370 unsigned long vpn, 370 unsigned long vpn,
371 int psize, int apsize, 371 int psize, int apsize,
372 int ssize, int local) 372 int ssize, unsigned long flags)
373{ 373{
374 unsigned long lpar_rc; 374 unsigned long lpar_rc;
375 unsigned long want_v; 375 unsigned long want_v;
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index ffcbd242e669..f7af74f83693 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -181,7 +181,8 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
181 return 0; 181 return 0;
182} 182}
183 183
184extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); //XXX 184extern int hash_page(unsigned long ea, unsigned long access,
185 unsigned long trap, unsigned long dsisr); //XXX
185static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) 186static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
186{ 187{
187 int ret; 188 int ret;
@@ -196,7 +197,7 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
196 (REGION_ID(ea) != USER_REGION_ID)) { 197 (REGION_ID(ea) != USER_REGION_ID)) {
197 198
198 spin_unlock(&spu->register_lock); 199 spin_unlock(&spu->register_lock);
199 ret = hash_page(ea, _PAGE_PRESENT, 0x300); 200 ret = hash_page(ea, _PAGE_PRESENT, 0x300, dsisr);
200 spin_lock(&spu->register_lock); 201 spin_lock(&spu->register_lock);
201 202
202 if (!ret) { 203 if (!ret) {
diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c
index e45894a08118..d98f845ac777 100644
--- a/arch/powerpc/platforms/cell/spufs/fault.c
+++ b/arch/powerpc/platforms/cell/spufs/fault.c
@@ -144,7 +144,7 @@ int spufs_handle_class1(struct spu_context *ctx)
144 access = (_PAGE_PRESENT | _PAGE_USER); 144 access = (_PAGE_PRESENT | _PAGE_USER);
145 access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL; 145 access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL;
146 local_irq_save(flags); 146 local_irq_save(flags);
147 ret = hash_page(ea, access, 0x300); 147 ret = hash_page(ea, access, 0x300, dsisr);
148 local_irq_restore(flags); 148 local_irq_restore(flags);
149 149
150 /* hashing failed, so try the actual fault handler */ 150 /* hashing failed, so try the actual fault handler */
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index 3e270e3412ae..2f95d33cf34a 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -110,7 +110,7 @@ static long ps3_hpte_remove(unsigned long hpte_group)
110 110
111static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp, 111static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp,
112 unsigned long vpn, int psize, int apsize, 112 unsigned long vpn, int psize, int apsize,
113 int ssize, int local) 113 int ssize, unsigned long inv_flags)
114{ 114{
115 int result; 115 int result;
116 u64 hpte_v, want_v, hpte_rs; 116 u64 hpte_v, want_v, hpte_rs;
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 832f221840f2..469751d92004 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -284,7 +284,7 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot,
284 unsigned long newpp, 284 unsigned long newpp,
285 unsigned long vpn, 285 unsigned long vpn,
286 int psize, int apsize, 286 int psize, int apsize,
287 int ssize, int local) 287 int ssize, unsigned long inv_flags)
288{ 288{
289 unsigned long lpar_rc; 289 unsigned long lpar_rc;
290 unsigned long flags = (newpp & 7) | H_AVPN; 290 unsigned long flags = (newpp & 7) | H_AVPN;