Skip to content

Commit 01b0f0e

Browse files
npigginmpe
authored andcommitted
powerpc/64s: Trim offlined CPUs from mm_cpumasks
When offlining a CPU, powerpc/64s does not flush TLBs, rather it just leaves the CPU set in mm_cpumasks, so it continues to receive TLBIEs to manage its TLBs. However the exit_flush_lazy_tlbs() function expects that after returning, all CPUs (except self) have flushed TLBs for that mm, in which case TLBIEL can be used for this flush. This breaks for offline CPUs because they don't get the IPI to flush their TLB. This can lead to stale translations. Fix this by clearing the CPU from mm_cpumasks, then flushing all TLBs before going offline. These offlined CPU bits stuck in the cpumask also prevents the cpumask from being trimmed back to local mode, which means continual broadcast IPIs or TLBIEs are needed for TLB flushing. This patch prevents that situation too. A cast of many were involved in working this out, but in particular Milton, Aneesh, Paul made key discoveries. Fixes: 0cef77c ("powerpc/64s/radix: flush remote CPUs out of single-threaded mm_cpumask") Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> Debugged-by: Milton Miller <miltonm@us.ibm.com> Debugged-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> Debugged-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20201126102530.691335-5-npiggin@gmail.com
1 parent 8ff0039 commit 01b0f0e

5 files changed

Lines changed: 40 additions & 0 deletions

File tree

arch/powerpc/include/asm/book3s/64/mmu.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,18 @@ extern void radix_init_pseries(void);
242242
static inline void radix_init_pseries(void) { };
243243
#endif
244244

245+
#ifdef CONFIG_HOTPLUG_CPU
246+
#define arch_clear_mm_cpumask_cpu(cpu, mm) \
247+
do { \
248+
if (cpumask_test_cpu(cpu, mm_cpumask(mm))) { \
249+
atomic_dec(&(mm)->context.active_cpus); \
250+
cpumask_clear_cpu(cpu, mm_cpumask(mm)); \
251+
} \
252+
} while (0)
253+
254+
void cleanup_cpu_mmu_context(void);
255+
#endif
256+
245257
static inline int get_user_context(mm_context_t *ctx, unsigned long ea)
246258
{
247259
int index = ea >> MAX_EA_BITS_PER_CONTEXT;

arch/powerpc/mm/book3s64/mmu_context.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/export.h>
1818
#include <linux/gfp.h>
1919
#include <linux/slab.h>
20+
#include <linux/cpu.h>
2021

2122
#include <asm/mmu_context.h>
2223
#include <asm/pgalloc.h>
@@ -307,3 +308,22 @@ void radix__switch_mmu_context(struct mm_struct *prev, struct mm_struct *next)
307308
isync();
308309
}
309310
#endif
311+
312+
/**
313+
* cleanup_cpu_mmu_context - Clean up MMU details for this CPU (newly offlined)
314+
*
315+
* This clears the CPU from mm_cpumask for all processes, and then flushes the
316+
* local TLB to ensure TLB coherency in case the CPU is onlined again.
317+
*
318+
* KVM guest translations are not necessarily flushed here. If KVM started
319+
* using mm_cpumask or the Linux APIs which do, this would have to be resolved.
320+
*/
321+
#ifdef CONFIG_HOTPLUG_CPU
322+
void cleanup_cpu_mmu_context(void)
323+
{
324+
int cpu = smp_processor_id();
325+
326+
clear_tasks_mm_cpumask(cpu);
327+
tlbiel_all();
328+
}
329+
#endif

arch/powerpc/platforms/powermac/smp.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,8 @@ static int smp_core99_cpu_disable(void)
911911

912912
mpic_cpu_set_priority(0xf);
913913

914+
cleanup_cpu_mmu_context();
915+
914916
return 0;
915917
}
916918

arch/powerpc/platforms/powernv/smp.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ static int pnv_smp_cpu_disable(void)
143143
xive_smp_disable_cpu();
144144
else
145145
xics_migrate_irqs_away();
146+
147+
cleanup_cpu_mmu_context();
148+
146149
return 0;
147150
}
148151

arch/powerpc/platforms/pseries/hotplug-cpu.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ static int pseries_cpu_disable(void)
9090
xive_smp_disable_cpu();
9191
else
9292
xics_migrate_irqs_away();
93+
94+
cleanup_cpu_mmu_context();
95+
9396
return 0;
9497
}
9598

0 commit comments

Comments
 (0)