diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-06-25 09:01:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-06-25 09:01:48 -0400 |
commit | 2f6e97477bb44f8d1b36e6ead62b4934052d884d (patch) | |
tree | cafbabe877031519008f473f6041c04a94ac4310 | |
parent | 9521d39976db20f8ef9b56af66661482a17d5364 (diff) | |
parent | 844e3be47693f92a108cb1fb3b0606bf25e9c7a6 (diff) |
Merge tag 'powerpc-4.7-4' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc fixes from Michael Ellerman:
"mm/radix (Aneesh Kumar K.V):
- Update to tlb functions ric argument
- Flush page walk cache when freeing page table
- Update Radix tree size as per ISA 3.0
mm/hash (Aneesh Kumar K.V):
- Use the correct PPP mask when updating HPTE
- Don't add memory coherence if cache inhibited is set
eeh (Gavin Shan):
- Fix invalid cached PE primary bus
bpf/jit (Naveen N. Rao):
- Disable classic BPF JIT on ppc64le
.. and fix faults caused by radix patching of SLB miss handler
(Michael Ellerman)"
* tag 'powerpc-4.7-4' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
powerpc/bpf/jit: Disable classic BPF JIT on ppc64le
powerpc: Fix faults caused by radix patching of SLB miss handler
powerpc/eeh: Fix invalid cached PE primary bus
powerpc/mm/radix: Update Radix tree size as per ISA 3.0
powerpc/mm/hash: Don't add memory coherence if cache inhibited is set
powerpc/mm/hash: Use the correct PPP mask when updating HPTE
powerpc/mm/radix: Flush page walk cache when freeing page table
powerpc/mm/radix: Update to tlb functions ric argument
-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 | } |