diff options
| -rw-r--r-- | arch/powerpc/Kconfig | 2 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/book3s/32/pgalloc.h | 1 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/book3s/64/mmu-hash.h | 1 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/book3s/64/pgalloc.h | 16 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/book3s/64/radix.h | 15 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/book3s/64/tlbflush-radix.h | 3 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/book3s/64/tlbflush.h | 14 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/book3s/pgalloc.h | 5 | ||||
| -rw-r--r-- | arch/powerpc/kernel/eeh_driver.c | 7 | ||||
| -rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 7 | ||||
| -rw-r--r-- | arch/powerpc/mm/hash_native_64.c | 8 | ||||
| -rw-r--r-- | arch/powerpc/mm/hash_utils_64.c | 14 | ||||
| -rw-r--r-- | arch/powerpc/mm/mmu_context_book3s64.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/mm/pgtable-radix.c | 9 | ||||
| -rw-r--r-- | arch/powerpc/mm/tlb-radix.c | 84 |
15 files changed, 137 insertions, 51 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 01f7464d9fea..0a9d439bcda6 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
| @@ -128,7 +128,7 @@ config PPC | |||
| 128 | select IRQ_FORCED_THREADING | 128 | select IRQ_FORCED_THREADING |
| 129 | select HAVE_RCU_TABLE_FREE if SMP | 129 | select HAVE_RCU_TABLE_FREE if SMP |
| 130 | select HAVE_SYSCALL_TRACEPOINTS | 130 | select HAVE_SYSCALL_TRACEPOINTS |
| 131 | select HAVE_CBPF_JIT | 131 | select HAVE_CBPF_JIT if CPU_BIG_ENDIAN |
| 132 | select HAVE_ARCH_JUMP_LABEL | 132 | select HAVE_ARCH_JUMP_LABEL |
| 133 | select ARCH_HAVE_NMI_SAFE_CMPXCHG | 133 | select ARCH_HAVE_NMI_SAFE_CMPXCHG |
| 134 | select ARCH_HAS_GCOV_PROFILE_ALL | 134 | select ARCH_HAS_GCOV_PROFILE_ALL |
diff --git a/arch/powerpc/include/asm/book3s/32/pgalloc.h b/arch/powerpc/include/asm/book3s/32/pgalloc.h index a2350194fc76..8e21bb492dca 100644 --- a/arch/powerpc/include/asm/book3s/32/pgalloc.h +++ b/arch/powerpc/include/asm/book3s/32/pgalloc.h | |||
| @@ -102,7 +102,6 @@ static inline void pgtable_free_tlb(struct mmu_gather *tlb, | |||
| 102 | static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table, | 102 | static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table, |
| 103 | unsigned long address) | 103 | unsigned long address) |
| 104 | { | 104 | { |
| 105 | tlb_flush_pgtable(tlb, address); | ||
| 106 | pgtable_page_dtor(table); | 105 | pgtable_page_dtor(table); |
| 107 | pgtable_free_tlb(tlb, page_address(table), 0); | 106 | pgtable_free_tlb(tlb, page_address(table), 0); |
| 108 | } | 107 | } |
diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h index 290157e8d5b2..74839f24f412 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h +++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h | |||
| @@ -88,6 +88,7 @@ | |||
| 88 | #define HPTE_R_RPN_SHIFT 12 | 88 | #define HPTE_R_RPN_SHIFT 12 |
| 89 | #define HPTE_R_RPN ASM_CONST(0x0ffffffffffff000) | 89 | #define HPTE_R_RPN ASM_CONST(0x0ffffffffffff000) |
| 90 | #define HPTE_R_PP ASM_CONST(0x0000000000000003) | 90 | #define HPTE_R_PP ASM_CONST(0x0000000000000003) |
| 91 | #define HPTE_R_PPP ASM_CONST(0x8000000000000003) | ||
| 91 | #define HPTE_R_N ASM_CONST(0x0000000000000004) | 92 | #define HPTE_R_N ASM_CONST(0x0000000000000004) |
| 92 | #define HPTE_R_G ASM_CONST(0x0000000000000008) | 93 | #define HPTE_R_G ASM_CONST(0x0000000000000008) |
| 93 | #define HPTE_R_M ASM_CONST(0x0000000000000010) | 94 | #define HPTE_R_M ASM_CONST(0x0000000000000010) |
diff --git a/arch/powerpc/include/asm/book3s/64/pgalloc.h b/arch/powerpc/include/asm/book3s/64/pgalloc.h index d14fcf82c00c..cd5e7aa8cc34 100644 --- a/arch/powerpc/include/asm/book3s/64/pgalloc.h +++ b/arch/powerpc/include/asm/book3s/64/pgalloc.h | |||
| @@ -109,6 +109,11 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) | |||
| 109 | static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud, | 109 | static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud, |
| 110 | unsigned long address) | 110 | unsigned long address) |
| 111 | { | 111 | { |
| 112 | /* | ||
| 113 | * By now all the pud entries should be none entries. So go | ||
| 114 | * ahead and flush the page walk cache | ||
| 115 | */ | ||
| 116 | flush_tlb_pgtable(tlb, address); | ||
| 112 | pgtable_free_tlb(tlb, pud, PUD_INDEX_SIZE); | 117 | pgtable_free_tlb(tlb, pud, PUD_INDEX_SIZE); |
| 113 | } | 118 | } |
| 114 | 119 | ||
| @@ -125,6 +130,11 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) | |||
| 125 | static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd, | 130 | static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd, |
| 126 | unsigned long address) | 131 | unsigned long address) |
| 127 | { | 132 | { |
| 133 | /* | ||
| 134 | * By now all the pud entries should be none entries. So go | ||
| 135 | * ahead and flush the page walk cache | ||
| 136 | */ | ||
| 137 | flush_tlb_pgtable(tlb, address); | ||
| 128 | return pgtable_free_tlb(tlb, pmd, PMD_CACHE_INDEX); | 138 | return pgtable_free_tlb(tlb, pmd, PMD_CACHE_INDEX); |
| 129 | } | 139 | } |
| 130 | 140 | ||
| @@ -196,7 +206,11 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage) | |||
| 196 | static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table, | 206 | static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table, |
| 197 | unsigned long address) | 207 | unsigned long address) |
| 198 | { | 208 | { |
| 199 | tlb_flush_pgtable(tlb, address); | 209 | /* |
| 210 | * By now all the pud entries should be none entries. So go | ||
| 211 | * ahead and flush the page walk cache | ||
| 212 | */ | ||
| 213 | flush_tlb_pgtable(tlb, address); | ||
| 200 | pgtable_free_tlb(tlb, table, 0); | 214 | pgtable_free_tlb(tlb, table, 0); |
| 201 | } | 215 | } |
| 202 | 216 | ||
diff --git a/arch/powerpc/include/asm/book3s/64/radix.h b/arch/powerpc/include/asm/book3s/64/radix.h index 937d4e247ac3..df294224e280 100644 --- a/arch/powerpc/include/asm/book3s/64/radix.h +++ b/arch/powerpc/include/asm/book3s/64/radix.h | |||
| @@ -228,5 +228,20 @@ extern void radix__vmemmap_remove_mapping(unsigned long start, | |||
| 228 | 228 | ||
| 229 | extern int radix__map_kernel_page(unsigned long ea, unsigned long pa, | 229 | extern int radix__map_kernel_page(unsigned long ea, unsigned long pa, |
| 230 | pgprot_t flags, unsigned int psz); | 230 | pgprot_t flags, unsigned int psz); |
| 231 | |||
| 232 | static inline unsigned long radix__get_tree_size(void) | ||
| 233 | { | ||
| 234 | unsigned long rts_field; | ||
| 235 | /* | ||
| 236 | * we support 52 bits, hence 52-31 = 21, 0b10101 | ||
| 237 | * RTS encoding details | ||
| 238 | * bits 0 - 3 of rts -> bits 6 - 8 unsigned long | ||
| 239 | * bits 4 - 5 of rts -> bits 62 - 63 of unsigned long | ||
| 240 | */ | ||
| 241 | rts_field = (0x5UL << 5); /* 6 - 8 bits */ | ||
| 242 | rts_field |= (0x2UL << 61); | ||
| 243 | |||
| 244 | return rts_field; | ||
| 245 | } | ||
| 231 | #endif /* __ASSEMBLY__ */ | 246 | #endif /* __ASSEMBLY__ */ |
| 232 | #endif | 247 | #endif |
diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h index 13ef38828dfe..3fa94fcac628 100644 --- a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h +++ b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h | |||
| @@ -18,16 +18,19 @@ extern void radix__local_flush_tlb_mm(struct mm_struct *mm); | |||
| 18 | extern void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); | 18 | extern void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); |
| 19 | extern void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, | 19 | extern void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, |
| 20 | unsigned long ap, int nid); | 20 | unsigned long ap, int nid); |
| 21 | extern void radix__local_flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr); | ||
| 21 | extern void radix__tlb_flush(struct mmu_gather *tlb); | 22 | extern void radix__tlb_flush(struct mmu_gather *tlb); |
| 22 | #ifdef CONFIG_SMP | 23 | #ifdef CONFIG_SMP |
| 23 | extern void radix__flush_tlb_mm(struct mm_struct *mm); | 24 | extern void radix__flush_tlb_mm(struct mm_struct *mm); |
| 24 | extern void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); | 25 | extern void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); |
| 25 | extern void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, | 26 | extern void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, |
| 26 | unsigned long ap, int nid); | 27 | unsigned long ap, int nid); |
| 28 | extern void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr); | ||
| 27 | #else | 29 | #else |
| 28 | #define radix__flush_tlb_mm(mm) radix__local_flush_tlb_mm(mm) | 30 | #define radix__flush_tlb_mm(mm) radix__local_flush_tlb_mm(mm) |
| 29 | #define radix__flush_tlb_page(vma,addr) radix__local_flush_tlb_page(vma,addr) | 31 | #define radix__flush_tlb_page(vma,addr) radix__local_flush_tlb_page(vma,addr) |
| 30 | #define radix___flush_tlb_page(mm,addr,p,i) radix___local_flush_tlb_page(mm,addr,p,i) | 32 | #define radix___flush_tlb_page(mm,addr,p,i) radix___local_flush_tlb_page(mm,addr,p,i) |
| 33 | #define radix__flush_tlb_pwc(tlb, addr) radix__local_flush_tlb_pwc(tlb, addr) | ||
| 31 | #endif | 34 | #endif |
| 32 | 35 | ||
| 33 | #endif | 36 | #endif |
diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush.h b/arch/powerpc/include/asm/book3s/64/tlbflush.h index d98424ae356c..96e5769b18b0 100644 --- a/arch/powerpc/include/asm/book3s/64/tlbflush.h +++ b/arch/powerpc/include/asm/book3s/64/tlbflush.h | |||
| @@ -72,5 +72,19 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, | |||
| 72 | #define flush_tlb_mm(mm) local_flush_tlb_mm(mm) | 72 | #define flush_tlb_mm(mm) local_flush_tlb_mm(mm) |
| 73 | #define flush_tlb_page(vma, addr) local_flush_tlb_page(vma, addr) | 73 | #define flush_tlb_page(vma, addr) local_flush_tlb_page(vma, addr) |
| 74 | #endif /* CONFIG_SMP */ | 74 | #endif /* CONFIG_SMP */ |
| 75 | /* | ||
| 76 | * flush the page walk cache for the address | ||
| 77 | */ | ||
| 78 | static inline void flush_tlb_pgtable(struct mmu_gather *tlb, unsigned long address) | ||
| 79 | { | ||
| 80 | /* | ||
| 81 | * Flush the page table walk cache on freeing a page table. We already | ||
| 82 | * have marked the upper/higher level page table entry none by now. | ||
| 83 | * So it is safe to flush PWC here. | ||
| 84 | */ | ||
| 85 | if (!radix_enabled()) | ||
| 86 | return; | ||
| 75 | 87 | ||
| 88 | radix__flush_tlb_pwc(tlb, address); | ||
| 89 | } | ||
| 76 | #endif /* _ASM_POWERPC_BOOK3S_64_TLBFLUSH_H */ | 90 | #endif /* _ASM_POWERPC_BOOK3S_64_TLBFLUSH_H */ |
diff --git a/arch/powerpc/include/asm/book3s/pgalloc.h b/arch/powerpc/include/asm/book3s/pgalloc.h index 54f591e9572e..c0a69ae92256 100644 --- a/arch/powerpc/include/asm/book3s/pgalloc.h +++ b/arch/powerpc/include/asm/book3s/pgalloc.h | |||
| @@ -4,11 +4,6 @@ | |||
| 4 | #include <linux/mm.h> | 4 | #include <linux/mm.h> |
| 5 | 5 | ||
| 6 | extern void tlb_remove_table(struct mmu_gather *tlb, void *table); | 6 | extern void tlb_remove_table(struct mmu_gather *tlb, void *table); |
| 7 | static inline void tlb_flush_pgtable(struct mmu_gather *tlb, | ||
| 8 | unsigned long address) | ||
| 9 | { | ||
| 10 | |||
| 11 | } | ||
| 12 | 7 | ||
| 13 | #ifdef CONFIG_PPC64 | 8 | #ifdef CONFIG_PPC64 |
| 14 | #include <asm/book3s/64/pgalloc.h> | 9 | #include <asm/book3s/64/pgalloc.h> |
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 2714a3b81d24..b5f73cb5eeb6 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c | |||
| @@ -642,7 +642,6 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus, | |||
| 642 | if (pe->type & EEH_PE_VF) { | 642 | if (pe->type & EEH_PE_VF) { |
| 643 | eeh_pe_dev_traverse(pe, eeh_rmv_device, NULL); | 643 | eeh_pe_dev_traverse(pe, eeh_rmv_device, NULL); |
| 644 | } else { | 644 | } else { |
| 645 | eeh_pe_state_clear(pe, EEH_PE_PRI_BUS); | ||
| 646 | pci_lock_rescan_remove(); | 645 | pci_lock_rescan_remove(); |
| 647 | pci_hp_remove_devices(bus); | 646 | pci_hp_remove_devices(bus); |
| 648 | pci_unlock_rescan_remove(); | 647 | pci_unlock_rescan_remove(); |
| @@ -692,10 +691,12 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus, | |||
| 692 | */ | 691 | */ |
| 693 | edev = list_first_entry(&pe->edevs, struct eeh_dev, list); | 692 | edev = list_first_entry(&pe->edevs, struct eeh_dev, list); |
| 694 | eeh_pe_traverse(pe, eeh_pe_detach_dev, NULL); | 693 | eeh_pe_traverse(pe, eeh_pe_detach_dev, NULL); |
| 695 | if (pe->type & EEH_PE_VF) | 694 | if (pe->type & EEH_PE_VF) { |
| 696 | eeh_add_virt_device(edev, NULL); | 695 | eeh_add_virt_device(edev, NULL); |
| 697 | else | 696 | } else { |
| 697 | eeh_pe_state_clear(pe, EEH_PE_PRI_BUS); | ||
| 698 | pci_hp_add_devices(bus); | 698 | pci_hp_add_devices(bus); |
| 699 | } | ||
| 699 | } else if (frozen_bus && rmv_data->removed) { | 700 | } else if (frozen_bus && rmv_data->removed) { |
| 700 | pr_info("EEH: Sleep 5s ahead of partial hotplug\n"); | 701 | pr_info("EEH: Sleep 5s ahead of partial hotplug\n"); |
| 701 | ssleep(5); | 702 | ssleep(5); |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 4c9440629128..8bcc1b457115 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
| @@ -1399,11 +1399,12 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_RADIX) | |||
| 1399 | lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ | 1399 | lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ |
| 1400 | 1400 | ||
| 1401 | mtlr r10 | 1401 | mtlr r10 |
| 1402 | BEGIN_MMU_FTR_SECTION | ||
| 1403 | b 2f | ||
| 1404 | END_MMU_FTR_SECTION_IFSET(MMU_FTR_RADIX) | ||
| 1405 | andi. r10,r12,MSR_RI /* check for unrecoverable exception */ | 1402 | andi. r10,r12,MSR_RI /* check for unrecoverable exception */ |
| 1403 | BEGIN_MMU_FTR_SECTION | ||
| 1406 | beq- 2f | 1404 | beq- 2f |
| 1405 | FTR_SECTION_ELSE | ||
| 1406 | b 2f | ||
| 1407 | ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_RADIX) | ||
| 1407 | 1408 | ||
| 1408 | .machine push | 1409 | .machine push |
| 1409 | .machine "power4" | 1410 | .machine "power4" |
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index 40e05e7f43de..f8a871a72985 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c | |||
| @@ -316,8 +316,8 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | |||
| 316 | DBG_LOW(" -> hit\n"); | 316 | DBG_LOW(" -> hit\n"); |
| 317 | /* Update the HPTE */ | 317 | /* Update the HPTE */ |
| 318 | hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) & | 318 | hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) & |
| 319 | ~(HPTE_R_PP | HPTE_R_N)) | | 319 | ~(HPTE_R_PPP | HPTE_R_N)) | |
| 320 | (newpp & (HPTE_R_PP | HPTE_R_N | | 320 | (newpp & (HPTE_R_PPP | HPTE_R_N | |
| 321 | HPTE_R_C))); | 321 | HPTE_R_C))); |
| 322 | } | 322 | } |
| 323 | native_unlock_hpte(hptep); | 323 | native_unlock_hpte(hptep); |
| @@ -385,8 +385,8 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, | |||
| 385 | 385 | ||
| 386 | /* Update the HPTE */ | 386 | /* Update the HPTE */ |
| 387 | hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) & | 387 | hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) & |
| 388 | ~(HPTE_R_PP | HPTE_R_N)) | | 388 | ~(HPTE_R_PPP | HPTE_R_N)) | |
| 389 | (newpp & (HPTE_R_PP | HPTE_R_N))); | 389 | (newpp & (HPTE_R_PPP | HPTE_R_N))); |
| 390 | /* | 390 | /* |
| 391 | * Ensure it is out of the tlb too. Bolted entries base and | 391 | * Ensure it is out of the tlb too. Bolted entries base and |
| 392 | * actual page size will be same. | 392 | * actual page size will be same. |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index b2740c67e172..5b22ba0b58bc 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
| @@ -201,9 +201,8 @@ unsigned long htab_convert_pte_flags(unsigned long pteflags) | |||
| 201 | /* | 201 | /* |
| 202 | * We can't allow hardware to update hpte bits. Hence always | 202 | * We can't allow hardware to update hpte bits. Hence always |
| 203 | * set 'R' bit and set 'C' if it is a write fault | 203 | * set 'R' bit and set 'C' if it is a write fault |
| 204 | * Memory coherence is always enabled | ||
| 205 | */ | 204 | */ |
| 206 | rflags |= HPTE_R_R | HPTE_R_M; | 205 | rflags |= HPTE_R_R; |
| 207 | 206 | ||
| 208 | if (pteflags & _PAGE_DIRTY) | 207 | if (pteflags & _PAGE_DIRTY) |
| 209 | rflags |= HPTE_R_C; | 208 | rflags |= HPTE_R_C; |
| @@ -213,10 +212,15 @@ unsigned long htab_convert_pte_flags(unsigned long pteflags) | |||
| 213 | 212 | ||
| 214 | if ((pteflags & _PAGE_CACHE_CTL) == _PAGE_TOLERANT) | 213 | if ((pteflags & _PAGE_CACHE_CTL) == _PAGE_TOLERANT) |
| 215 | rflags |= HPTE_R_I; | 214 | rflags |= HPTE_R_I; |
| 216 | if ((pteflags & _PAGE_CACHE_CTL ) == _PAGE_NON_IDEMPOTENT) | 215 | else if ((pteflags & _PAGE_CACHE_CTL) == _PAGE_NON_IDEMPOTENT) |
| 217 | rflags |= (HPTE_R_I | HPTE_R_G); | 216 | rflags |= (HPTE_R_I | HPTE_R_G); |
| 218 | if ((pteflags & _PAGE_CACHE_CTL) == _PAGE_SAO) | 217 | else if ((pteflags & _PAGE_CACHE_CTL) == _PAGE_SAO) |
| 219 | rflags |= (HPTE_R_I | HPTE_R_W); | 218 | rflags |= (HPTE_R_W | HPTE_R_I | HPTE_R_M); |
| 219 | else | ||
| 220 | /* | ||
| 221 | * Add memory coherence if cache inhibited is not set | ||
| 222 | */ | ||
| 223 | rflags |= HPTE_R_M; | ||
| 220 | 224 | ||
| 221 | return rflags; | 225 | return rflags; |
| 222 | } | 226 | } |
diff --git a/arch/powerpc/mm/mmu_context_book3s64.c b/arch/powerpc/mm/mmu_context_book3s64.c index 227b2a6c4544..196222227e82 100644 --- a/arch/powerpc/mm/mmu_context_book3s64.c +++ b/arch/powerpc/mm/mmu_context_book3s64.c | |||
| @@ -65,7 +65,7 @@ static int radix__init_new_context(struct mm_struct *mm, int index) | |||
| 65 | /* | 65 | /* |
| 66 | * set the process table entry, | 66 | * set the process table entry, |
| 67 | */ | 67 | */ |
| 68 | rts_field = 3ull << PPC_BITLSHIFT(2); | 68 | rts_field = radix__get_tree_size(); |
| 69 | process_tb[index].prtb0 = cpu_to_be64(rts_field | __pa(mm->pgd) | RADIX_PGD_INDEX_SIZE); | 69 | process_tb[index].prtb0 = cpu_to_be64(rts_field | __pa(mm->pgd) | RADIX_PGD_INDEX_SIZE); |
| 70 | return 0; | 70 | return 0; |
| 71 | } | 71 | } |
diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c index c939e6e57a9e..e58707deef5c 100644 --- a/arch/powerpc/mm/pgtable-radix.c +++ b/arch/powerpc/mm/pgtable-radix.c | |||
| @@ -160,9 +160,8 @@ redo: | |||
| 160 | process_tb = early_alloc_pgtable(1UL << PRTB_SIZE_SHIFT); | 160 | process_tb = early_alloc_pgtable(1UL << PRTB_SIZE_SHIFT); |
| 161 | /* | 161 | /* |
| 162 | * Fill in the process table. | 162 | * Fill in the process table. |
| 163 | * we support 52 bits, hence 52-28 = 24, 11000 | ||
| 164 | */ | 163 | */ |
| 165 | rts_field = 3ull << PPC_BITLSHIFT(2); | 164 | rts_field = radix__get_tree_size(); |
| 166 | process_tb->prtb0 = cpu_to_be64(rts_field | __pa(init_mm.pgd) | RADIX_PGD_INDEX_SIZE); | 165 | process_tb->prtb0 = cpu_to_be64(rts_field | __pa(init_mm.pgd) | RADIX_PGD_INDEX_SIZE); |
| 167 | /* | 166 | /* |
| 168 | * Fill in the partition table. We are suppose to use effective address | 167 | * Fill in the partition table. We are suppose to use effective address |
| @@ -176,10 +175,8 @@ redo: | |||
| 176 | static void __init radix_init_partition_table(void) | 175 | static void __init radix_init_partition_table(void) |
| 177 | { | 176 | { |
| 178 | unsigned long rts_field; | 177 | unsigned long rts_field; |
| 179 | /* | 178 | |
| 180 | * we support 52 bits, hence 52-28 = 24, 11000 | 179 | rts_field = radix__get_tree_size(); |
| 181 | */ | ||
| 182 | rts_field = 3ull << PPC_BITLSHIFT(2); | ||
| 183 | 180 | ||
| 184 | BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 24), "Partition table size too large."); | 181 | BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 24), "Partition table size too large."); |
| 185 | partition_tb = early_alloc_pgtable(1UL << PATB_SIZE_SHIFT); | 182 | partition_tb = early_alloc_pgtable(1UL << PATB_SIZE_SHIFT); |
diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c index 54efba2fd66e..ab2f60e812e2 100644 --- a/arch/powerpc/mm/tlb-radix.c +++ b/arch/powerpc/mm/tlb-radix.c | |||
| @@ -18,16 +18,20 @@ | |||
| 18 | 18 | ||
| 19 | static DEFINE_RAW_SPINLOCK(native_tlbie_lock); | 19 | static DEFINE_RAW_SPINLOCK(native_tlbie_lock); |
| 20 | 20 | ||
| 21 | static inline void __tlbiel_pid(unsigned long pid, int set) | 21 | #define RIC_FLUSH_TLB 0 |
| 22 | #define RIC_FLUSH_PWC 1 | ||
| 23 | #define RIC_FLUSH_ALL 2 | ||
| 24 | |||
| 25 | static inline void __tlbiel_pid(unsigned long pid, int set, | ||
| 26 | unsigned long ric) | ||
| 22 | { | 27 | { |
| 23 | unsigned long rb,rs,ric,prs,r; | 28 | unsigned long rb,rs,prs,r; |
| 24 | 29 | ||
| 25 | rb = PPC_BIT(53); /* IS = 1 */ | 30 | rb = PPC_BIT(53); /* IS = 1 */ |
| 26 | rb |= set << PPC_BITLSHIFT(51); | 31 | rb |= set << PPC_BITLSHIFT(51); |
| 27 | rs = ((unsigned long)pid) << PPC_BITLSHIFT(31); | 32 | rs = ((unsigned long)pid) << PPC_BITLSHIFT(31); |
| 28 | prs = 1; /* process scoped */ | 33 | prs = 1; /* process scoped */ |
| 29 | r = 1; /* raidx format */ | 34 | r = 1; /* raidx format */ |
| 30 | ric = 2; /* invalidate all the caches */ | ||
| 31 | 35 | ||
| 32 | asm volatile("ptesync": : :"memory"); | 36 | asm volatile("ptesync": : :"memory"); |
| 33 | asm volatile(".long 0x7c000224 | (%0 << 11) | (%1 << 16) |" | 37 | asm volatile(".long 0x7c000224 | (%0 << 11) | (%1 << 16) |" |
| @@ -39,25 +43,24 @@ static inline void __tlbiel_pid(unsigned long pid, int set) | |||
| 39 | /* | 43 | /* |
| 40 | * We use 128 set in radix mode and 256 set in hpt mode. | 44 | * We use 128 set in radix mode and 256 set in hpt mode. |
| 41 | */ | 45 | */ |
| 42 | static inline void _tlbiel_pid(unsigned long pid) | 46 | static inline void _tlbiel_pid(unsigned long pid, unsigned long ric) |
| 43 | { | 47 | { |
| 44 | int set; | 48 | int set; |
| 45 | 49 | ||
| 46 | for (set = 0; set < POWER9_TLB_SETS_RADIX ; set++) { | 50 | for (set = 0; set < POWER9_TLB_SETS_RADIX ; set++) { |
| 47 | __tlbiel_pid(pid, set); | 51 | __tlbiel_pid(pid, set, ric); |
| 48 | } | 52 | } |
| 49 | return; | 53 | return; |
| 50 | } | 54 | } |
| 51 | 55 | ||
| 52 | static inline void _tlbie_pid(unsigned long pid) | 56 | static inline void _tlbie_pid(unsigned long pid, unsigned long ric) |
| 53 | { | 57 | { |
| 54 | unsigned long rb,rs,ric,prs,r; | 58 | unsigned long rb,rs,prs,r; |
| 55 | 59 | ||
| 56 | rb = PPC_BIT(53); /* IS = 1 */ | 60 | rb = PPC_BIT(53); /* IS = 1 */ |
| 57 | rs = pid << PPC_BITLSHIFT(31); | 61 | rs = pid << PPC_BITLSHIFT(31); |
| 58 | prs = 1; /* process scoped */ | 62 | prs = 1; /* process scoped */ |
| 59 | r = 1; /* raidx format */ | 63 | r = 1; /* raidx format */ |
| 60 | ric = 2; /* invalidate all the caches */ | ||
| 61 | 64 | ||
| 62 | asm volatile("ptesync": : :"memory"); | 65 | asm volatile("ptesync": : :"memory"); |
| 63 | asm volatile(".long 0x7c000264 | (%0 << 11) | (%1 << 16) |" | 66 | asm volatile(".long 0x7c000264 | (%0 << 11) | (%1 << 16) |" |
| @@ -67,16 +70,15 @@ static inline void _tlbie_pid(unsigned long pid) | |||
| 67 | } | 70 | } |
| 68 | 71 | ||
| 69 | static inline void _tlbiel_va(unsigned long va, unsigned long pid, | 72 | static inline void _tlbiel_va(unsigned long va, unsigned long pid, |
| 70 | unsigned long ap) | 73 | unsigned long ap, unsigned long ric) |
| 71 | { | 74 | { |
| 72 | unsigned long rb,rs,ric,prs,r; | 75 | unsigned long rb,rs,prs,r; |
| 73 | 76 | ||
| 74 | rb = va & ~(PPC_BITMASK(52, 63)); | 77 | rb = va & ~(PPC_BITMASK(52, 63)); |
| 75 | rb |= ap << PPC_BITLSHIFT(58); | 78 | rb |= ap << PPC_BITLSHIFT(58); |
| 76 | rs = pid << PPC_BITLSHIFT(31); | 79 | rs = pid << PPC_BITLSHIFT(31); |
| 77 | prs = 1; /* process scoped */ | 80 | prs = 1; /* process scoped */ |
| 78 | r = 1; /* raidx format */ | 81 | r = 1; /* raidx format */ |
| 79 | ric = 0; /* no cluster flush yet */ | ||
| 80 | 82 | ||
| 81 | asm volatile("ptesync": : :"memory"); | 83 | asm volatile("ptesync": : :"memory"); |
| 82 | asm volatile(".long 0x7c000224 | (%0 << 11) | (%1 << 16) |" | 84 | asm volatile(".long 0x7c000224 | (%0 << 11) | (%1 << 16) |" |
| @@ -86,16 +88,15 @@ static inline void _tlbiel_va(unsigned long va, unsigned long pid, | |||
| 86 | } | 88 | } |
| 87 | 89 | ||
| 88 | static inline void _tlbie_va(unsigned long va, unsigned long pid, | 90 | static inline void _tlbie_va(unsigned long va, unsigned long pid, |
| 89 | unsigned long ap) | 91 | unsigned long ap, unsigned long ric) |
| 90 | { | 92 | { |
| 91 | unsigned long rb,rs,ric,prs,r; | 93 | unsigned long rb,rs,prs,r; |
| 92 | 94 | ||
| 93 | rb = va & ~(PPC_BITMASK(52, 63)); | 95 | rb = va & ~(PPC_BITMASK(52, 63)); |
| 94 | rb |= ap << PPC_BITLSHIFT(58); | 96 | rb |= ap << PPC_BITLSHIFT(58); |
| 95 | rs = pid << PPC_BITLSHIFT(31); | 97 | rs = pid << PPC_BITLSHIFT(31); |
| 96 | prs = 1; /* process scoped */ | 98 | prs = 1; /* process scoped */ |
| 97 | r = 1; /* raidx format */ | 99 | r = 1; /* raidx format */ |
| 98 | ric = 0; /* no cluster flush yet */ | ||
| 99 | 100 | ||
| 100 | asm volatile("ptesync": : :"memory"); | 101 | asm volatile("ptesync": : :"memory"); |
| 101 | asm volatile(".long 0x7c000264 | (%0 << 11) | (%1 << 16) |" | 102 | asm volatile(".long 0x7c000264 | (%0 << 11) | (%1 << 16) |" |
| @@ -122,11 +123,26 @@ void radix__local_flush_tlb_mm(struct mm_struct *mm) | |||
| 122 | preempt_disable(); | 123 | preempt_disable(); |
| 123 | pid = mm->context.id; | 124 | pid = mm->context.id; |
| 124 | if (pid != MMU_NO_CONTEXT) | 125 | if (pid != MMU_NO_CONTEXT) |
| 125 | _tlbiel_pid(pid); | 126 | _tlbiel_pid(pid, RIC_FLUSH_ALL); |
| 126 | preempt_enable(); | 127 | preempt_enable(); |
| 127 | } | 128 | } |
| 128 | EXPORT_SYMBOL(radix__local_flush_tlb_mm); | 129 | EXPORT_SYMBOL(radix__local_flush_tlb_mm); |
| 129 | 130 | ||
| 131 | void radix__local_flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr) | ||
| 132 | { | ||
| 133 | unsigned long pid; | ||
| 134 | struct mm_struct *mm = tlb->mm; | ||
| 135 | |||
| 136 | preempt_disable(); | ||
| 137 | |||
| 138 | pid = mm->context.id; | ||
| 139 | if (pid != MMU_NO_CONTEXT) | ||
| 140 | _tlbiel_pid(pid, RIC_FLUSH_PWC); | ||
| 141 | |||
| 142 | preempt_enable(); | ||
| 143 | } | ||
| 144 | EXPORT_SYMBOL(radix__local_flush_tlb_pwc); | ||
| 145 | |||
| 130 | void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, | 146 | void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, |
| 131 | unsigned long ap, int nid) | 147 | unsigned long ap, int nid) |
| 132 | { | 148 | { |
| @@ -135,7 +151,7 @@ void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, | |||
| 135 | preempt_disable(); | 151 | preempt_disable(); |
| 136 | pid = mm ? mm->context.id : 0; | 152 | pid = mm ? mm->context.id : 0; |
| 137 | if (pid != MMU_NO_CONTEXT) | 153 | if (pid != MMU_NO_CONTEXT) |
| 138 | _tlbiel_va(vmaddr, pid, ap); | 154 | _tlbiel_va(vmaddr, pid, ap, RIC_FLUSH_TLB); |
| 139 | preempt_enable(); | 155 | preempt_enable(); |
| 140 | } | 156 | } |
| 141 | 157 | ||
| @@ -172,16 +188,42 @@ void radix__flush_tlb_mm(struct mm_struct *mm) | |||
| 172 | 188 | ||
| 173 | if (lock_tlbie) | 189 | if (lock_tlbie) |
| 174 | raw_spin_lock(&native_tlbie_lock); | 190 | raw_spin_lock(&native_tlbie_lock); |
| 175 | _tlbie_pid(pid); | 191 | _tlbie_pid(pid, RIC_FLUSH_ALL); |
| 176 | if (lock_tlbie) | 192 | if (lock_tlbie) |
| 177 | raw_spin_unlock(&native_tlbie_lock); | 193 | raw_spin_unlock(&native_tlbie_lock); |
| 178 | } else | 194 | } else |
| 179 | _tlbiel_pid(pid); | 195 | _tlbiel_pid(pid, RIC_FLUSH_ALL); |
| 180 | no_context: | 196 | no_context: |
| 181 | preempt_enable(); | 197 | preempt_enable(); |
| 182 | } | 198 | } |
| 183 | EXPORT_SYMBOL(radix__flush_tlb_mm); | 199 | EXPORT_SYMBOL(radix__flush_tlb_mm); |
| 184 | 200 | ||
| 201 | void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr) | ||
| 202 | { | ||
| 203 | unsigned long pid; | ||
| 204 | struct mm_struct *mm = tlb->mm; | ||
| 205 | |||
| 206 | preempt_disable(); | ||
| 207 | |||
| 208 | pid = mm->context.id; | ||
| 209 | if (unlikely(pid == MMU_NO_CONTEXT)) | ||
| 210 | goto no_context; | ||
| 211 | |||
| 212 | if (!mm_is_core_local(mm)) { | ||
| 213 | int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); | ||
| 214 | |||
| 215 | if (lock_tlbie) | ||
| 216 | raw_spin_lock(&native_tlbie_lock); | ||
| 217 | _tlbie_pid(pid, RIC_FLUSH_PWC); | ||
| 218 | if (lock_tlbie) | ||
| 219 | raw_spin_unlock(&native_tlbie_lock); | ||
| 220 | } else | ||
| 221 | _tlbiel_pid(pid, RIC_FLUSH_PWC); | ||
| 222 | no_context: | ||
| 223 | preempt_enable(); | ||
| 224 | } | ||
| 225 | EXPORT_SYMBOL(radix__flush_tlb_pwc); | ||
| 226 | |||
| 185 | void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, | 227 | void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, |
| 186 | unsigned long ap, int nid) | 228 | unsigned long ap, int nid) |
| 187 | { | 229 | { |
| @@ -196,11 +238,11 @@ void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, | |||
| 196 | 238 | ||
| 197 | if (lock_tlbie) | 239 | if (lock_tlbie) |
| 198 | raw_spin_lock(&native_tlbie_lock); | 240 | raw_spin_lock(&native_tlbie_lock); |
| 199 | _tlbie_va(vmaddr, pid, ap); | 241 | _tlbie_va(vmaddr, pid, ap, RIC_FLUSH_TLB); |
| 200 | if (lock_tlbie) | 242 | if (lock_tlbie) |
| 201 | raw_spin_unlock(&native_tlbie_lock); | 243 | raw_spin_unlock(&native_tlbie_lock); |
| 202 | } else | 244 | } else |
| 203 | _tlbiel_va(vmaddr, pid, ap); | 245 | _tlbiel_va(vmaddr, pid, ap, RIC_FLUSH_TLB); |
| 204 | bail: | 246 | bail: |
| 205 | preempt_enable(); | 247 | preempt_enable(); |
| 206 | } | 248 | } |
| @@ -224,7 +266,7 @@ void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end) | |||
| 224 | 266 | ||
| 225 | if (lock_tlbie) | 267 | if (lock_tlbie) |
| 226 | raw_spin_lock(&native_tlbie_lock); | 268 | raw_spin_lock(&native_tlbie_lock); |
| 227 | _tlbie_pid(0); | 269 | _tlbie_pid(0, RIC_FLUSH_ALL); |
| 228 | if (lock_tlbie) | 270 | if (lock_tlbie) |
| 229 | raw_spin_unlock(&native_tlbie_lock); | 271 | raw_spin_unlock(&native_tlbie_lock); |
| 230 | } | 272 | } |
