aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-06-25 09:01:48 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-06-25 09:01:48 -0400
commit2f6e97477bb44f8d1b36e6ead62b4934052d884d (patch)
treecafbabe877031519008f473f6041c04a94ac4310
parent9521d39976db20f8ef9b56af66661482a17d5364 (diff)
parent844e3be47693f92a108cb1fb3b0606bf25e9c7a6 (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/Kconfig2
-rw-r--r--arch/powerpc/include/asm/book3s/32/pgalloc.h1
-rw-r--r--arch/powerpc/include/asm/book3s/64/mmu-hash.h1
-rw-r--r--arch/powerpc/include/asm/book3s/64/pgalloc.h16
-rw-r--r--arch/powerpc/include/asm/book3s/64/radix.h15
-rw-r--r--arch/powerpc/include/asm/book3s/64/tlbflush-radix.h3
-rw-r--r--arch/powerpc/include/asm/book3s/64/tlbflush.h14
-rw-r--r--arch/powerpc/include/asm/book3s/pgalloc.h5
-rw-r--r--arch/powerpc/kernel/eeh_driver.c7
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S7
-rw-r--r--arch/powerpc/mm/hash_native_64.c8
-rw-r--r--arch/powerpc/mm/hash_utils_64.c14
-rw-r--r--arch/powerpc/mm/mmu_context_book3s64.c2
-rw-r--r--arch/powerpc/mm/pgtable-radix.c9
-rw-r--r--arch/powerpc/mm/tlb-radix.c84
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,
102static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table, 102static 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)
109static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud, 109static 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)
125static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd, 130static 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)
196static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table, 206static 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
229extern int radix__map_kernel_page(unsigned long ea, unsigned long pa, 229extern 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
232static 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);
18extern void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); 18extern void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
19extern void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, 19extern 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);
21extern void radix__local_flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr);
21extern void radix__tlb_flush(struct mmu_gather *tlb); 22extern void radix__tlb_flush(struct mmu_gather *tlb);
22#ifdef CONFIG_SMP 23#ifdef CONFIG_SMP
23extern void radix__flush_tlb_mm(struct mm_struct *mm); 24extern void radix__flush_tlb_mm(struct mm_struct *mm);
24extern void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); 25extern void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
25extern void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, 26extern void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
26 unsigned long ap, int nid); 27 unsigned long ap, int nid);
28extern 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 */
78static 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
6extern void tlb_remove_table(struct mmu_gather *tlb, void *table); 6extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
7static 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
1402BEGIN_MMU_FTR_SECTION
1403 b 2f
1404END_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 */
1403BEGIN_MMU_FTR_SECTION
1406 beq- 2f 1404 beq- 2f
1405FTR_SECTION_ELSE
1406 b 2f
1407ALT_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:
176static void __init radix_init_partition_table(void) 175static 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
19static DEFINE_RAW_SPINLOCK(native_tlbie_lock); 19static DEFINE_RAW_SPINLOCK(native_tlbie_lock);
20 20
21static 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
25static 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 */
42static inline void _tlbiel_pid(unsigned long pid) 46static 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
52static inline void _tlbie_pid(unsigned long pid) 56static 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
69static inline void _tlbiel_va(unsigned long va, unsigned long pid, 72static 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
88static inline void _tlbie_va(unsigned long va, unsigned long pid, 90static 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}
128EXPORT_SYMBOL(radix__local_flush_tlb_mm); 129EXPORT_SYMBOL(radix__local_flush_tlb_mm);
129 130
131void 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}
144EXPORT_SYMBOL(radix__local_flush_tlb_pwc);
145
130void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, 146void 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);
180no_context: 196no_context:
181 preempt_enable(); 197 preempt_enable();
182} 198}
183EXPORT_SYMBOL(radix__flush_tlb_mm); 199EXPORT_SYMBOL(radix__flush_tlb_mm);
184 200
201void 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);
222no_context:
223 preempt_enable();
224}
225EXPORT_SYMBOL(radix__flush_tlb_pwc);
226
185void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, 227void 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);
204bail: 246bail:
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}