aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMahesh Salgaonkar <mahesh@linux.vnet.ibm.com>2014-12-18 22:11:05 -0500
committerMichael Ellerman <mpe@ellerman.id.au>2015-03-16 16:52:48 -0400
commit45706bb53d118b5340a12926e26444d73b6491f9 (patch)
treeb88f88494c7fd725987973c83b3cbf4cb1760911
parent7f664cf9e422105644818b180349e3b10a370de7 (diff)
powerpc/book3s: Fix flush_tlb cpu_spec hook to take a generic argument.
The flush_tlb hook in cpu_spec was introduced as a generic function hook to invalidate TLBs. But the current implementation of flush_tlb hook takes IS (invalidation selector) as an argument which is architecture dependent. Hence, It is not right to have a generic routine where caller has to pass non-generic argument. This patch fixes this and makes flush_tlb hook as high level API. Reported-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/include/asm/cputable.h8
-rw-r--r--arch/powerpc/include/asm/mmu-hash64.h1
-rw-r--r--arch/powerpc/kernel/cpu_setup_power.S10
-rw-r--r--arch/powerpc/kernel/cputable.c4
-rw-r--r--arch/powerpc/kernel/mce_power.c53
-rw-r--r--arch/powerpc/kvm/book3s_hv_ras.c4
6 files changed, 65 insertions, 15 deletions
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 5cf5a6d10685..6367b8347dad 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -100,7 +100,7 @@ struct cpu_spec {
100 /* 100 /*
101 * Processor specific routine to flush tlbs. 101 * Processor specific routine to flush tlbs.
102 */ 102 */
103 void (*flush_tlb)(unsigned long inval_selector); 103 void (*flush_tlb)(unsigned int action);
104 104
105}; 105};
106 106
@@ -114,6 +114,12 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
114 114
115extern const char *powerpc_base_platform; 115extern const char *powerpc_base_platform;
116 116
117/* TLB flush actions. Used as argument to cpu_spec.flush_tlb() hook */
118enum {
119 TLB_INVAL_SCOPE_GLOBAL = 0, /* invalidate all TLBs */
120 TLB_INVAL_SCOPE_LPID = 1, /* invalidate TLBs for current LPID */
121};
122
117#endif /* __ASSEMBLY__ */ 123#endif /* __ASSEMBLY__ */
118 124
119/* CPU kernel features */ 125/* CPU kernel features */
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index 4f13c3ed7acf..1da6a81ce541 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -112,6 +112,7 @@
112#define TLBIEL_INVAL_SET_SHIFT 12 112#define TLBIEL_INVAL_SET_SHIFT 12
113 113
114#define POWER7_TLB_SETS 128 /* # sets in POWER7 TLB */ 114#define POWER7_TLB_SETS 128 /* # sets in POWER7 TLB */
115#define POWER8_TLB_SETS 512 /* # sets in POWER8 TLB */
115 116
116#ifndef __ASSEMBLY__ 117#ifndef __ASSEMBLY__
117 118
diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S
index 46733535cc0b..9c9b7411b28b 100644
--- a/arch/powerpc/kernel/cpu_setup_power.S
+++ b/arch/powerpc/kernel/cpu_setup_power.S
@@ -137,15 +137,11 @@ __init_HFSCR:
137/* 137/*
138 * Clear the TLB using the specified IS form of tlbiel instruction 138 * Clear the TLB using the specified IS form of tlbiel instruction
139 * (invalidate by congruence class). P7 has 128 CCs., P8 has 512. 139 * (invalidate by congruence class). P7 has 128 CCs., P8 has 512.
140 *
141 * r3 = IS field
142 */ 140 */
143__init_tlb_power7: 141__init_tlb_power7:
144 li r3,0xc00 /* IS field = 0b11 */
145_GLOBAL(__flush_tlb_power7)
146 li r6,128 142 li r6,128
147 mtctr r6 143 mtctr r6
148 mr r7,r3 /* IS field */ 144 li r7,0xc00 /* IS field = 0b11 */
149 ptesync 145 ptesync
1502: tlbiel r7 1462: tlbiel r7
151 addi r7,r7,0x1000 147 addi r7,r7,0x1000
@@ -154,11 +150,9 @@ _GLOBAL(__flush_tlb_power7)
1541: blr 1501: blr
155 151
156__init_tlb_power8: 152__init_tlb_power8:
157 li r3,0xc00 /* IS field = 0b11 */
158_GLOBAL(__flush_tlb_power8)
159 li r6,512 153 li r6,512
160 mtctr r6 154 mtctr r6
161 mr r7,r3 /* IS field */ 155 li r7,0xc00 /* IS field = 0b11 */
162 ptesync 156 ptesync
1632: tlbiel r7 1572: tlbiel r7
164 addi r7,r7,0x1000 158 addi r7,r7,0x1000
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index f337666768a7..7ed126bc9b18 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -71,8 +71,8 @@ extern void __restore_cpu_power7(void);
71extern void __setup_cpu_power8(unsigned long offset, struct cpu_spec* spec); 71extern void __setup_cpu_power8(unsigned long offset, struct cpu_spec* spec);
72extern void __restore_cpu_power8(void); 72extern void __restore_cpu_power8(void);
73extern void __restore_cpu_a2(void); 73extern void __restore_cpu_a2(void);
74extern void __flush_tlb_power7(unsigned long inval_selector); 74extern void __flush_tlb_power7(unsigned int action);
75extern void __flush_tlb_power8(unsigned long inval_selector); 75extern void __flush_tlb_power8(unsigned int action);
76extern long __machine_check_early_realmode_p7(struct pt_regs *regs); 76extern long __machine_check_early_realmode_p7(struct pt_regs *regs);
77extern long __machine_check_early_realmode_p8(struct pt_regs *regs); 77extern long __machine_check_early_realmode_p8(struct pt_regs *regs);
78#endif /* CONFIG_PPC64 */ 78#endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c
index b6f123ab90ed..2c647b1e62e4 100644
--- a/arch/powerpc/kernel/mce_power.c
+++ b/arch/powerpc/kernel/mce_power.c
@@ -28,6 +28,55 @@
28#include <asm/mce.h> 28#include <asm/mce.h>
29#include <asm/machdep.h> 29#include <asm/machdep.h>
30 30
31static void flush_tlb_206(unsigned int num_sets, unsigned int action)
32{
33 unsigned long rb;
34 unsigned int i;
35
36 switch (action) {
37 case TLB_INVAL_SCOPE_GLOBAL:
38 rb = TLBIEL_INVAL_SET;
39 break;
40 case TLB_INVAL_SCOPE_LPID:
41 rb = TLBIEL_INVAL_SET_LPID;
42 break;
43 default:
44 BUG();
45 break;
46 }
47
48 asm volatile("ptesync" : : : "memory");
49 for (i = 0; i < num_sets; i++) {
50 asm volatile("tlbiel %0" : : "r" (rb));
51 rb += 1 << TLBIEL_INVAL_SET_SHIFT;
52 }
53 asm volatile("ptesync" : : : "memory");
54}
55
56/*
57 * Generic routine to flush TLB on power7. This routine is used as
58 * flush_tlb hook in cpu_spec for Power7 processor.
59 *
60 * action => TLB_INVAL_SCOPE_GLOBAL: Invalidate all TLBs.
61 * TLB_INVAL_SCOPE_LPID: Invalidate TLB for current LPID.
62 */
63void __flush_tlb_power7(unsigned int action)
64{
65 flush_tlb_206(POWER7_TLB_SETS, action);
66}
67
68/*
69 * Generic routine to flush TLB on power8. This routine is used as
70 * flush_tlb hook in cpu_spec for power8 processor.
71 *
72 * action => TLB_INVAL_SCOPE_GLOBAL: Invalidate all TLBs.
73 * TLB_INVAL_SCOPE_LPID: Invalidate TLB for current LPID.
74 */
75void __flush_tlb_power8(unsigned int action)
76{
77 flush_tlb_206(POWER8_TLB_SETS, action);
78}
79
31/* flush SLBs and reload */ 80/* flush SLBs and reload */
32static void flush_and_reload_slb(void) 81static void flush_and_reload_slb(void)
33{ 82{
@@ -79,7 +128,7 @@ static long mce_handle_derror(uint64_t dsisr, uint64_t slb_error_bits)
79 } 128 }
80 if (dsisr & P7_DSISR_MC_TLB_MULTIHIT_MFTLB) { 129 if (dsisr & P7_DSISR_MC_TLB_MULTIHIT_MFTLB) {
81 if (cur_cpu_spec && cur_cpu_spec->flush_tlb) 130 if (cur_cpu_spec && cur_cpu_spec->flush_tlb)
82 cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET); 131 cur_cpu_spec->flush_tlb(TLB_INVAL_SCOPE_GLOBAL);
83 /* reset error bits */ 132 /* reset error bits */
84 dsisr &= ~P7_DSISR_MC_TLB_MULTIHIT_MFTLB; 133 dsisr &= ~P7_DSISR_MC_TLB_MULTIHIT_MFTLB;
85 } 134 }
@@ -110,7 +159,7 @@ static long mce_handle_common_ierror(uint64_t srr1)
110 break; 159 break;
111 case P7_SRR1_MC_IFETCH_TLB_MULTIHIT: 160 case P7_SRR1_MC_IFETCH_TLB_MULTIHIT:
112 if (cur_cpu_spec && cur_cpu_spec->flush_tlb) { 161 if (cur_cpu_spec && cur_cpu_spec->flush_tlb) {
113 cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET); 162 cur_cpu_spec->flush_tlb(TLB_INVAL_SCOPE_GLOBAL);
114 handled = 1; 163 handled = 1;
115 } 164 }
116 break; 165 break;
diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c
index 60081bd75847..93b5f5c9b445 100644
--- a/arch/powerpc/kvm/book3s_hv_ras.c
+++ b/arch/powerpc/kvm/book3s_hv_ras.c
@@ -84,7 +84,7 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
84 } 84 }
85 if (dsisr & DSISR_MC_TLB_MULTI) { 85 if (dsisr & DSISR_MC_TLB_MULTI) {
86 if (cur_cpu_spec && cur_cpu_spec->flush_tlb) 86 if (cur_cpu_spec && cur_cpu_spec->flush_tlb)
87 cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET_LPID); 87 cur_cpu_spec->flush_tlb(TLB_INVAL_SCOPE_LPID);
88 dsisr &= ~DSISR_MC_TLB_MULTI; 88 dsisr &= ~DSISR_MC_TLB_MULTI;
89 } 89 }
90 /* Any other errors we don't understand? */ 90 /* Any other errors we don't understand? */
@@ -102,7 +102,7 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
102 break; 102 break;
103 case SRR1_MC_IFETCH_TLBMULTI: 103 case SRR1_MC_IFETCH_TLBMULTI:
104 if (cur_cpu_spec && cur_cpu_spec->flush_tlb) 104 if (cur_cpu_spec && cur_cpu_spec->flush_tlb)
105 cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET_LPID); 105 cur_cpu_spec->flush_tlb(TLB_INVAL_SCOPE_LPID);
106 break; 106 break;
107 default: 107 default:
108 handled = 0; 108 handled = 0;