aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/cpu_setup_power.S13
-rw-r--r--arch/powerpc/kernel/dt_cpu_ftrs.c16
-rw-r--r--arch/powerpc/kernel/mce_power.c56
3 files changed, 67 insertions, 18 deletions
diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S
index 10cb2896b2ae..610955fe8b81 100644
--- a/arch/powerpc/kernel/cpu_setup_power.S
+++ b/arch/powerpc/kernel/cpu_setup_power.S
@@ -218,13 +218,20 @@ __init_tlb_power8:
218 ptesync 218 ptesync
2191: blr 2191: blr
220 220
221/*
222 * Flush the TLB in hash mode. Hash must flush with RIC=2 once for process
223 * and one for partition scope to clear process and partition table entries.
224 */
221__init_tlb_power9: 225__init_tlb_power9:
222 li r6,POWER9_TLB_SETS_HASH 226 li r6,POWER9_TLB_SETS_HASH - 1
223 mtctr r6 227 mtctr r6
224 li r7,0xc00 /* IS field = 0b11 */ 228 li r7,0xc00 /* IS field = 0b11 */
229 li r8,0
225 ptesync 230 ptesync
2262: tlbiel r7 231 PPC_TLBIEL(7, 8, 2, 1, 0)
227 addi r7,r7,0x1000 232 PPC_TLBIEL(7, 8, 2, 0, 0)
2332: addi r7,r7,0x1000
234 PPC_TLBIEL(7, 8, 0, 0, 0)
228 bdnz 2b 235 bdnz 2b
229 ptesync 236 ptesync
2301: blr 2371: blr
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
index 4c7656dc4e04..1df770e8cbe0 100644
--- a/arch/powerpc/kernel/dt_cpu_ftrs.c
+++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
@@ -94,9 +94,6 @@ static void (*init_pmu_registers)(void);
94 94
95static void cpufeatures_flush_tlb(void) 95static void cpufeatures_flush_tlb(void)
96{ 96{
97 unsigned long rb;
98 unsigned int i, num_sets;
99
100 /* 97 /*
101 * This is a temporary measure to keep equivalent TLB flush as the 98 * This is a temporary measure to keep equivalent TLB flush as the
102 * cputable based setup code. 99 * cputable based setup code.
@@ -105,24 +102,15 @@ static void cpufeatures_flush_tlb(void)
105 case PVR_POWER8: 102 case PVR_POWER8:
106 case PVR_POWER8E: 103 case PVR_POWER8E:
107 case PVR_POWER8NVL: 104 case PVR_POWER8NVL:
108 num_sets = POWER8_TLB_SETS; 105 __flush_tlb_power8(POWER8_TLB_SETS);
109 break; 106 break;
110 case PVR_POWER9: 107 case PVR_POWER9:
111 num_sets = POWER9_TLB_SETS_HASH; 108 __flush_tlb_power9(POWER9_TLB_SETS_HASH);
112 break; 109 break;
113 default: 110 default:
114 num_sets = 1;
115 pr_err("unknown CPU version for boot TLB flush\n"); 111 pr_err("unknown CPU version for boot TLB flush\n");
116 break; 112 break;
117 } 113 }
118
119 asm volatile("ptesync" : : : "memory");
120 rb = TLBIEL_INVAL_SET;
121 for (i = 0; i < num_sets; i++) {
122 asm volatile("tlbiel %0" : : "r" (rb));
123 rb += 1 << TLBIEL_INVAL_SET_SHIFT;
124 }
125 asm volatile("ptesync" : : : "memory");
126} 114}
127 115
128static void __restore_cpu_cpufeatures(void) 116static void __restore_cpu_cpufeatures(void)
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c
index d24e689e893f..b76ca198e09c 100644
--- a/arch/powerpc/kernel/mce_power.c
+++ b/arch/powerpc/kernel/mce_power.c
@@ -53,6 +53,60 @@ static void flush_tlb_206(unsigned int num_sets, unsigned int action)
53 asm volatile("ptesync" : : : "memory"); 53 asm volatile("ptesync" : : : "memory");
54} 54}
55 55
56static void flush_tlb_300(unsigned int num_sets, unsigned int action)
57{
58 unsigned long rb;
59 unsigned int i;
60 unsigned int r;
61
62 switch (action) {
63 case TLB_INVAL_SCOPE_GLOBAL:
64 rb = TLBIEL_INVAL_SET;
65 break;
66 case TLB_INVAL_SCOPE_LPID:
67 rb = TLBIEL_INVAL_SET_LPID;
68 break;
69 default:
70 BUG();
71 break;
72 }
73
74 asm volatile("ptesync" : : : "memory");
75
76 if (early_radix_enabled())
77 r = 1;
78 else
79 r = 0;
80
81 /*
82 * First flush table/PWC caches with set 0, then flush the
83 * rest of the sets, partition scope. Radix must then do it
84 * all again with process scope. Hash just has to flush
85 * process table.
86 */
87 asm volatile(PPC_TLBIEL(%0, %1, %2, %3, %4) : :
88 "r"(rb), "r"(0), "i"(2), "i"(0), "r"(r));
89 for (i = 1; i < num_sets; i++) {
90 unsigned long set = i * (1<<TLBIEL_INVAL_SET_SHIFT);
91
92 asm volatile(PPC_TLBIEL(%0, %1, %2, %3, %4) : :
93 "r"(rb+set), "r"(0), "i"(2), "i"(0), "r"(r));
94 }
95
96 asm volatile(PPC_TLBIEL(%0, %1, %2, %3, %4) : :
97 "r"(rb), "r"(0), "i"(2), "i"(1), "r"(r));
98 if (early_radix_enabled()) {
99 for (i = 1; i < num_sets; i++) {
100 unsigned long set = i * (1<<TLBIEL_INVAL_SET_SHIFT);
101
102 asm volatile(PPC_TLBIEL(%0, %1, %2, %3, %4) : :
103 "r"(rb+set), "r"(0), "i"(2), "i"(1), "r"(r));
104 }
105 }
106
107 asm volatile("ptesync" : : : "memory");
108}
109
56/* 110/*
57 * Generic routines to flush TLB on POWER processors. These routines 111 * Generic routines to flush TLB on POWER processors. These routines
58 * are used as flush_tlb hook in the cpu_spec. 112 * are used as flush_tlb hook in the cpu_spec.
@@ -79,7 +133,7 @@ void __flush_tlb_power9(unsigned int action)
79 else 133 else
80 num_sets = POWER9_TLB_SETS_HASH; 134 num_sets = POWER9_TLB_SETS_HASH;
81 135
82 flush_tlb_206(num_sets, action); 136 flush_tlb_300(num_sets, action);
83} 137}
84 138
85 139