diff options
| -rw-r--r-- | arch/powerpc/include/asm/machdep.h | 2 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/mmu-hash64.h | 22 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/tlbflush.h | 4 | ||||
| -rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 2 | ||||
| -rw-r--r-- | arch/powerpc/mm/hash_low_64.S | 15 | ||||
| -rw-r--r-- | arch/powerpc/mm/hash_native_64.c | 15 | ||||
| -rw-r--r-- | arch/powerpc/mm/hash_utils_64.c | 44 | ||||
| -rw-r--r-- | arch/powerpc/mm/hugepage-hash64.c | 8 | ||||
| -rw-r--r-- | arch/powerpc/mm/hugetlbpage-hash64.c | 6 | ||||
| -rw-r--r-- | arch/powerpc/mm/pgtable_64.c | 7 | ||||
| -rw-r--r-- | arch/powerpc/platforms/cell/beat_htab.c | 4 | ||||
| -rw-r--r-- | arch/powerpc/platforms/cell/spu_base.c | 5 | ||||
| -rw-r--r-- | arch/powerpc/platforms/cell/spufs/fault.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/htab.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/platforms/pseries/lpar.c | 2 | ||||
| -rw-r--r-- | drivers/misc/cxl/fault.c | 8 |
16 files changed, 91 insertions, 57 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 | |||
| 319 | extern int __hash_page_4K(unsigned long ea, unsigned long access, | 322 | extern 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); |
| 322 | extern int __hash_page_64K(unsigned long ea, unsigned long access, | 325 | extern 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); |
| 325 | struct mm_struct; | 328 | struct mm_struct; |
| 326 | unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap); | 329 | unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap); |
| 327 | extern int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, unsigned long trap); | 330 | extern int hash_page_mm(struct mm_struct *mm, unsigned long ea, |
| 328 | extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); | 331 | unsigned long access, unsigned long trap, |
| 332 | unsigned long flags); | ||
| 333 | extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap, | ||
| 334 | unsigned long dsisr); | ||
| 329 | int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, | 335 | int __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 |
| 333 | extern int __hash_page_thp(unsigned long ea, unsigned long access, | 339 | extern 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 |
| 337 | static inline int __hash_page_thp(unsigned long ea, unsigned long access, | 343 | static 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 | ||
| 127 | extern void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, | 127 | extern void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, |
| 128 | int ssize, int local); | 128 | int ssize, unsigned long flags); |
| 129 | extern void flush_hash_range(unsigned long number, int local); | 129 | extern void flush_hash_range(unsigned long number, int local); |
| 130 | extern void flush_hash_hugepage(unsigned long vsid, unsigned long addr, | 130 | extern 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 | ||
| 134 | static inline void local_flush_tlb_mm(struct mm_struct *mm) | 134 | static 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 |
| 303 | htab_call_hpte_updatepp: | 304 | htab_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 |
| 671 | htab_call_hpte_updatepp: | 672 | htab_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 |
| 967 | ht64_call_hpte_updatepp: | 968 | ht64_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 | ||
| 284 | static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | 284 | static 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 | */ |
| 992 | int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, unsigned long trap) | 992 | int 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 | } |
| 1182 | EXPORT_SYMBOL_GPL(hash_page_mm); | 1185 | EXPORT_SYMBOL_GPL(hash_page_mm); |
| 1183 | 1186 | ||
| 1184 | int hash_page(unsigned long ea, unsigned long access, unsigned long trap) | 1187 | int 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 | } |
| 1193 | EXPORT_SYMBOL_GPL(hash_page); | 1201 | EXPORT_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 | */ |
| 1280 | void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize, | 1289 | void 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 |
| 1319 | void flush_hash_hugepage(unsigned long vsid, unsigned long addr, | 1329 | void 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 | ||
| 21 | int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, | 21 | int __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 | ||
| 21 | int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, | 21 | int __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, | |||
| 739 | void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, | 739 | void 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 | ||
| 773 | static pmd_t pmd_set_protbits(pmd_t pmd, pgprot_t pgprot) | 774 | static 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 | ||
| 184 | extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); //XXX | 184 | extern int hash_page(unsigned long ea, unsigned long access, |
| 185 | unsigned long trap, unsigned long dsisr); //XXX | ||
| 185 | static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) | 186 | static 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 | ||
| 111 | static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp, | 111 | static 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; |
diff --git a/drivers/misc/cxl/fault.c b/drivers/misc/cxl/fault.c index c99e896604ee..f8684bca2d79 100644 --- a/drivers/misc/cxl/fault.c +++ b/drivers/misc/cxl/fault.c | |||
| @@ -133,7 +133,7 @@ static void cxl_handle_page_fault(struct cxl_context *ctx, | |||
| 133 | { | 133 | { |
| 134 | unsigned flt = 0; | 134 | unsigned flt = 0; |
| 135 | int result; | 135 | int result; |
| 136 | unsigned long access, flags; | 136 | unsigned long access, flags, inv_flags = 0; |
| 137 | 137 | ||
| 138 | if ((result = copro_handle_mm_fault(mm, dar, dsisr, &flt))) { | 138 | if ((result = copro_handle_mm_fault(mm, dar, dsisr, &flt))) { |
| 139 | pr_devel("copro_handle_mm_fault failed: %#x\n", result); | 139 | pr_devel("copro_handle_mm_fault failed: %#x\n", result); |
| @@ -149,8 +149,12 @@ static void cxl_handle_page_fault(struct cxl_context *ctx, | |||
| 149 | access |= _PAGE_RW; | 149 | access |= _PAGE_RW; |
| 150 | if ((!ctx->kernel) || ~(dar & (1ULL << 63))) | 150 | if ((!ctx->kernel) || ~(dar & (1ULL << 63))) |
| 151 | access |= _PAGE_USER; | 151 | access |= _PAGE_USER; |
| 152 | |||
| 153 | if (dsisr & DSISR_NOHPTE) | ||
| 154 | inv_flags |= HPTE_NOHPTE_UPDATE; | ||
| 155 | |||
| 152 | local_irq_save(flags); | 156 | local_irq_save(flags); |
| 153 | hash_page_mm(mm, dar, access, 0x300); | 157 | hash_page_mm(mm, dar, access, 0x300, inv_flags); |
| 154 | local_irq_restore(flags); | 158 | local_irq_restore(flags); |
| 155 | 159 | ||
| 156 | pr_devel("Page fault successfully handled for pe: %i!\n", ctx->pe); | 160 | pr_devel("Page fault successfully handled for pe: %i!\n", ctx->pe); |
