Skip to content

Commit a5d4b58

Browse files
kvaneeshmpe
authored andcommitted
powerpc/mm: Fixup tlbie vs store ordering issue on POWER9
On POWER9, under some circumstances, a broadcast TLB invalidation might complete before all previous stores have drained, potentially allowing stale stores from becoming visible after the invalidation. This works around it by doubling up those TLB invalidations which was verified by HW to be sufficient to close the risk window. This will be documented in a yet-to-be-published errata. Fixes: 1a472c9 ("powerpc/mm/radix: Add tlbflush routines") Signed-off-by: Aneesh Kumar K.V <[email protected]> [mpe: Enable the feature in the DT CPU features code for all Power9, rename the feature to CPU_FTR_P9_TLBIE_BUG per benh.] Signed-off-by: Michael Ellerman <[email protected]>
1 parent 243fee3 commit a5d4b58

File tree

7 files changed

+50
-2
lines changed

7 files changed

+50
-2
lines changed

arch/powerpc/include/asm/cputable.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ static inline void cpu_feature_keys_init(void) { }
203203
#define CPU_FTR_DAWR LONG_ASM_CONST(0x0400000000000000)
204204
#define CPU_FTR_DABRX LONG_ASM_CONST(0x0800000000000000)
205205
#define CPU_FTR_PMAO_BUG LONG_ASM_CONST(0x1000000000000000)
206+
#define CPU_FTR_P9_TLBIE_BUG LONG_ASM_CONST(0x2000000000000000)
206207
#define CPU_FTR_POWER9_DD1 LONG_ASM_CONST(0x4000000000000000)
207208
#define CPU_FTR_POWER9_DD2_1 LONG_ASM_CONST(0x8000000000000000)
208209

@@ -465,7 +466,7 @@ static inline void cpu_feature_keys_init(void) { }
465466
CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
466467
CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \
467468
CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | \
468-
CPU_FTR_PKEY)
469+
CPU_FTR_PKEY | CPU_FTR_P9_TLBIE_BUG)
469470
#define CPU_FTRS_POWER9_DD1 ((CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD1) & \
470471
(~CPU_FTR_SAO))
471472
#define CPU_FTRS_POWER9_DD2_0 CPU_FTRS_POWER9

arch/powerpc/kernel/dt_cpu_ftrs.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,9 @@ static __init void cpufeatures_cpu_quirks(void)
709709
cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD1;
710710
else if ((version & 0xffffefff) == 0x004e0201)
711711
cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD2_1;
712+
713+
if ((version & 0xffff0000) == 0x004e0000)
714+
cur_cpu_spec->cpu_features |= CPU_FTR_P9_TLBIE_BUG;
712715
}
713716

714717
static void __init cpufeatures_setup_finished(void)

arch/powerpc/kvm/book3s_64_mmu_radix.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ static void kvmppc_radix_tlbie_page(struct kvm *kvm, unsigned long addr,
157157
asm volatile("ptesync": : :"memory");
158158
asm volatile(PPC_TLBIE_5(%0, %1, 0, 0, 1)
159159
: : "r" (addr), "r" (kvm->arch.lpid) : "memory");
160+
if (cpu_has_feature(CPU_FTR_P9_TLBIE_BUG))
161+
asm volatile(PPC_TLBIE_5(%0, %1, 0, 0, 1)
162+
: : "r" (addr), "r" (kvm->arch.lpid) : "memory");
160163
asm volatile("ptesync": : :"memory");
161164
}
162165

arch/powerpc/kvm/book3s_hv_rm_mmu.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,17 @@ static void do_tlbies(struct kvm *kvm, unsigned long *rbvalues,
473473
trace_tlbie(kvm->arch.lpid, 0, rbvalues[i],
474474
kvm->arch.lpid, 0, 0, 0);
475475
}
476+
477+
if (cpu_has_feature(CPU_FTR_P9_TLBIE_BUG)) {
478+
/*
479+
* Need the extra ptesync to make sure we don't
480+
* re-order the tlbie
481+
*/
482+
asm volatile("ptesync": : :"memory");
483+
asm volatile(PPC_TLBIE_5(%0,%1,0,0,0) : :
484+
"r" (rbvalues[0]), "r" (kvm->arch.lpid));
485+
}
486+
476487
asm volatile("eieio; tlbsync; ptesync" : : : "memory");
477488
kvm->arch.tlbie_lock = 0;
478489
} else {

arch/powerpc/mm/hash_native_64.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,15 @@ static inline unsigned long ___tlbie(unsigned long vpn, int psize,
201201
return va;
202202
}
203203

204+
static inline void fixup_tlbie(unsigned long vpn, int psize, int apsize, int ssize)
205+
{
206+
if (cpu_has_feature(CPU_FTR_P9_TLBIE_BUG)) {
207+
/* Need the extra ptesync to ensure we don't reorder tlbie*/
208+
asm volatile("ptesync": : :"memory");
209+
___tlbie(vpn, psize, apsize, ssize);
210+
}
211+
}
212+
204213
static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize)
205214
{
206215
unsigned long rb;
@@ -278,6 +287,7 @@ static inline void tlbie(unsigned long vpn, int psize, int apsize,
278287
asm volatile("ptesync": : :"memory");
279288
} else {
280289
__tlbie(vpn, psize, apsize, ssize);
290+
fixup_tlbie(vpn, psize, apsize, ssize);
281291
asm volatile("eieio; tlbsync; ptesync": : :"memory");
282292
}
283293
if (lock_tlbie && !use_local)
@@ -771,7 +781,7 @@ static void native_hpte_clear(void)
771781
*/
772782
static void native_flush_hash_range(unsigned long number, int local)
773783
{
774-
unsigned long vpn;
784+
unsigned long vpn = 0;
775785
unsigned long hash, index, hidx, shift, slot;
776786
struct hash_pte *hptep;
777787
unsigned long hpte_v;
@@ -843,6 +853,10 @@ static void native_flush_hash_range(unsigned long number, int local)
843853
__tlbie(vpn, psize, psize, ssize);
844854
} pte_iterate_hashed_end();
845855
}
856+
/*
857+
* Just do one more with the last used values.
858+
*/
859+
fixup_tlbie(vpn, psize, psize, ssize);
846860
asm volatile("eieio; tlbsync; ptesync":::"memory");
847861

848862
if (lock_tlbie)

arch/powerpc/mm/pgtable_64.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,7 @@ void mmu_partition_table_set_entry(unsigned int lpid, unsigned long dw0,
481481
"r" (TLBIEL_INVAL_SET_LPID), "r" (lpid));
482482
trace_tlbie(lpid, 0, TLBIEL_INVAL_SET_LPID, lpid, 2, 0, 0);
483483
}
484+
/* do we need fixup here ?*/
484485
asm volatile("eieio; tlbsync; ptesync" : : : "memory");
485486
}
486487
EXPORT_SYMBOL_GPL(mmu_partition_table_set_entry);

arch/powerpc/mm/tlb-radix.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,17 @@ static inline void __tlbie_va(unsigned long va, unsigned long pid,
151151
trace_tlbie(0, 0, rb, rs, ric, prs, r);
152152
}
153153

154+
static inline void fixup_tlbie(void)
155+
{
156+
unsigned long pid = 0;
157+
unsigned long va = ((1UL << 52) - 1);
158+
159+
if (cpu_has_feature(CPU_FTR_P9_TLBIE_BUG)) {
160+
asm volatile("ptesync": : :"memory");
161+
__tlbie_va(va, pid, mmu_get_ap(MMU_PAGE_64K), RIC_FLUSH_TLB);
162+
}
163+
}
164+
154165
/*
155166
* We use 128 set in radix mode and 256 set in hpt mode.
156167
*/
@@ -200,6 +211,7 @@ static inline void _tlbie_pid(unsigned long pid, unsigned long ric)
200211
default:
201212
__tlbie_pid(pid, RIC_FLUSH_ALL);
202213
}
214+
fixup_tlbie();
203215
asm volatile("eieio; tlbsync; ptesync": : :"memory");
204216
}
205217

@@ -253,6 +265,7 @@ static inline void _tlbie_va(unsigned long va, unsigned long pid,
253265

254266
asm volatile("ptesync": : :"memory");
255267
__tlbie_va(va, pid, ap, ric);
268+
fixup_tlbie();
256269
asm volatile("eieio; tlbsync; ptesync": : :"memory");
257270
}
258271

@@ -264,6 +277,7 @@ static inline void _tlbie_va_range(unsigned long start, unsigned long end,
264277
if (also_pwc)
265278
__tlbie_pid(pid, RIC_FLUSH_PWC);
266279
__tlbie_va_range(start, end, pid, page_size, psize);
280+
fixup_tlbie();
267281
asm volatile("eieio; tlbsync; ptesync": : :"memory");
268282
}
269283

@@ -498,6 +512,7 @@ void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
498512
if (hflush)
499513
__tlbie_va_range(hstart, hend, pid,
500514
HPAGE_PMD_SIZE, MMU_PAGE_2M);
515+
fixup_tlbie();
501516
asm volatile("eieio; tlbsync; ptesync": : :"memory");
502517
}
503518
}

0 commit comments

Comments
 (0)