Skip to content

Commit 91562cf

Browse files
committed
Merge tag 'powerpc-6.1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc fixes from Michael Ellerman: - Fix a case of rescheduling with user access unlocked, when preempt is enabled. - A follow-up fix for a recent fix, which could lead to IRQ state assertions firing incorrectly. - Two fixes for lockdep warnings seen when using kfence with the Hash MMU. - Two fixes for preempt warnings seen when using the Hash MMU. - Two fixes for the VAS coprocessor mechanism used on pseries. - Prevent building some of our older KVM backends when CONTEXT_TRACKING_USER is enabled, as it's known to cause crashes. - A couple of fixes for issues seen with PMU NMIs. Thanks to Nicholas Piggin, Guenter Roeck, Frederic Barrat Haren Myneni, Sachin Sant, and Samuel Holland. * tag 'powerpc-6.1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc/64s/interrupt: Fix clear of PACA_IRQS_HARD_DIS when returning to soft-masked context powerpc/64s/interrupt: Perf NMI should not take normal exit path powerpc/64/interrupt: Prevent NMI PMI causing a dangerous warning KVM: PPC: BookS PR-KVM and BookE do not support context tracking powerpc: Fix reschedule bug in KUAP-unlocked user copy powerpc/64s: Fix hash__change_memory_range preemption warning powerpc/64s: Disable preemption in hash lazy mmu mode powerpc/64s: make linear_map_hash_lock a raw spinlock powerpc/64s: make HPTE lock and native_tlbie_lock irq-safe powerpc/64s: Add lockdep for HPTE lock powerpc/pseries: Use lparcfg to reconfig VAS windows for DLPAR CPU powerpc/pseries/vas: Add VAS IRQ primary handler
2 parents 576e61c + 6572273 commit 91562cf

File tree

13 files changed

+212
-45
lines changed

13 files changed

+212
-45
lines changed

arch/powerpc/include/asm/book3s/64/tlbflush-hash.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ static inline void arch_enter_lazy_mmu_mode(void)
3232

3333
if (radix_enabled())
3434
return;
35+
/*
36+
* apply_to_page_range can call us this preempt enabled when
37+
* operating on kernel page tables.
38+
*/
39+
preempt_disable();
3540
batch = this_cpu_ptr(&ppc64_tlb_batch);
3641
batch->active = 1;
3742
}
@@ -47,6 +52,7 @@ static inline void arch_leave_lazy_mmu_mode(void)
4752
if (batch->index)
4853
__flush_tlb_pending(batch);
4954
batch->active = 0;
55+
preempt_enable();
5056
}
5157

5258
#define arch_flush_lazy_mmu_mode() do {} while (0)

arch/powerpc/kernel/exceptions-64e.S

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,13 @@ kernel_dbg_exc:
813813
EXCEPTION_COMMON(0x260)
814814
CHECK_NAPPING()
815815
addi r3,r1,STACK_FRAME_OVERHEAD
816+
/*
817+
* XXX: Returning from performance_monitor_exception taken as a
818+
* soft-NMI (Linux irqs disabled) may be risky to use interrupt_return
819+
* and could cause bugs in return or elsewhere. That case should just
820+
* restore registers and return. There is a workaround for one known
821+
* problem in interrupt_exit_kernel_prepare().
822+
*/
816823
bl performance_monitor_exception
817824
b interrupt_return
818825

arch/powerpc/kernel/exceptions-64s.S

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2357,9 +2357,21 @@ EXC_VIRT_END(performance_monitor, 0x4f00, 0x20)
23572357
EXC_COMMON_BEGIN(performance_monitor_common)
23582358
GEN_COMMON performance_monitor
23592359
addi r3,r1,STACK_FRAME_OVERHEAD
2360-
bl performance_monitor_exception
2360+
lbz r4,PACAIRQSOFTMASK(r13)
2361+
cmpdi r4,IRQS_ENABLED
2362+
bne 1f
2363+
bl performance_monitor_exception_async
23612364
b interrupt_return_srr
2365+
1:
2366+
bl performance_monitor_exception_nmi
2367+
/* Clear MSR_RI before setting SRR0 and SRR1. */
2368+
li r9,0
2369+
mtmsrd r9,1
23622370

2371+
kuap_kernel_restore r9, r10
2372+
2373+
EXCEPTION_RESTORE_REGS hsrr=0
2374+
RFI_TO_KERNEL
23632375

23642376
/**
23652377
* Interrupt 0xf20 - Vector Unavailable Interrupt.

arch/powerpc/kernel/interrupt.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -374,10 +374,18 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs)
374374
if (regs_is_unrecoverable(regs))
375375
unrecoverable_exception(regs);
376376
/*
377-
* CT_WARN_ON comes here via program_check_exception,
378-
* so avoid recursion.
377+
* CT_WARN_ON comes here via program_check_exception, so avoid
378+
* recursion.
379+
*
380+
* Skip the assertion on PMIs on 64e to work around a problem caused
381+
* by NMI PMIs incorrectly taking this interrupt return path, it's
382+
* possible for this to hit after interrupt exit to user switches
383+
* context to user. See also the comment in the performance monitor
384+
* handler in exceptions-64e.S
379385
*/
380-
if (TRAP(regs) != INTERRUPT_PROGRAM)
386+
if (!IS_ENABLED(CONFIG_PPC_BOOK3E_64) &&
387+
TRAP(regs) != INTERRUPT_PROGRAM &&
388+
TRAP(regs) != INTERRUPT_PERFMON)
381389
CT_WARN_ON(ct_state() == CONTEXT_USER);
382390

383391
kuap = kuap_get_and_assert_locked();

arch/powerpc/kernel/interrupt_64.S

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -532,15 +532,24 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_kernel)
532532
* Returning to soft-disabled context.
533533
* Check if a MUST_HARD_MASK interrupt has become pending, in which
534534
* case we need to disable MSR[EE] in the return context.
535+
*
536+
* The MSR[EE] check catches among other things the short incoherency
537+
* in hard_irq_disable() between clearing MSR[EE] and setting
538+
* PACA_IRQ_HARD_DIS.
535539
*/
536540
ld r12,_MSR(r1)
537541
andi. r10,r12,MSR_EE
538542
beq .Lfast_kernel_interrupt_return_\srr\() // EE already disabled
539543
lbz r11,PACAIRQHAPPENED(r13)
540544
andi. r10,r11,PACA_IRQ_MUST_HARD_MASK
541-
beq .Lfast_kernel_interrupt_return_\srr\() // No HARD_MASK pending
545+
bne 1f // HARD_MASK is pending
546+
// No HARD_MASK pending, clear possible HARD_DIS set by interrupt
547+
andi. r11,r11,(~PACA_IRQ_HARD_DIS)@l
548+
stb r11,PACAIRQHAPPENED(r13)
549+
b .Lfast_kernel_interrupt_return_\srr\()
550+
542551

543-
/* Must clear MSR_EE from _MSR */
552+
1: /* Must clear MSR_EE from _MSR */
544553
#ifdef CONFIG_PPC_BOOK3S
545554
li r10,0
546555
/* Clear valid before changing _MSR */

arch/powerpc/kvm/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ config KVM_BOOK3S_HV_POSSIBLE
5151
config KVM_BOOK3S_32
5252
tristate "KVM support for PowerPC book3s_32 processors"
5353
depends on PPC_BOOK3S_32 && !SMP && !PTE_64BIT
54+
depends on !CONTEXT_TRACKING_USER
5455
select KVM
5556
select KVM_BOOK3S_32_HANDLER
5657
select KVM_BOOK3S_PR_POSSIBLE
@@ -105,6 +106,7 @@ config KVM_BOOK3S_64_HV
105106
config KVM_BOOK3S_64_PR
106107
tristate "KVM support without using hypervisor mode in host"
107108
depends on KVM_BOOK3S_64
109+
depends on !CONTEXT_TRACKING_USER
108110
select KVM_BOOK3S_PR_POSSIBLE
109111
help
110112
Support running guest kernels in virtual machines on processors
@@ -190,6 +192,7 @@ config KVM_EXIT_TIMING
190192
config KVM_E500V2
191193
bool "KVM support for PowerPC E500v2 processors"
192194
depends on PPC_E500 && !PPC_E500MC
195+
depends on !CONTEXT_TRACKING_USER
193196
select KVM
194197
select KVM_MMIO
195198
select MMU_NOTIFIER
@@ -205,6 +208,7 @@ config KVM_E500V2
205208
config KVM_E500MC
206209
bool "KVM support for PowerPC E500MC/E5500/E6500 processors"
207210
depends on PPC_E500MC
211+
depends on !CONTEXT_TRACKING_USER
208212
select KVM
209213
select KVM_MMIO
210214
select KVM_BOOKE_HV

arch/powerpc/lib/vmx-helper.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,17 @@ int exit_vmx_usercopy(void)
3636
{
3737
disable_kernel_altivec();
3838
pagefault_enable();
39-
preempt_enable();
39+
preempt_enable_no_resched();
40+
/*
41+
* Must never explicitly call schedule (including preempt_enable())
42+
* while in a kuap-unlocked user copy, because the AMR register will
43+
* not be saved and restored across context switch. However preempt
44+
* kernels need to be preempted as soon as possible if need_resched is
45+
* set and we are preemptible. The hack here is to schedule a
46+
* decrementer to fire here and reschedule for us if necessary.
47+
*/
48+
if (IS_ENABLED(CONFIG_PREEMPT) && need_resched())
49+
set_dec(1);
4050
return 0;
4151
}
4252

arch/powerpc/mm/book3s64/hash_native.c

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,29 @@
4343

4444
static DEFINE_RAW_SPINLOCK(native_tlbie_lock);
4545

46+
#ifdef CONFIG_LOCKDEP
47+
static struct lockdep_map hpte_lock_map =
48+
STATIC_LOCKDEP_MAP_INIT("hpte_lock", &hpte_lock_map);
49+
50+
static void acquire_hpte_lock(void)
51+
{
52+
lock_map_acquire(&hpte_lock_map);
53+
}
54+
55+
static void release_hpte_lock(void)
56+
{
57+
lock_map_release(&hpte_lock_map);
58+
}
59+
#else
60+
static void acquire_hpte_lock(void)
61+
{
62+
}
63+
64+
static void release_hpte_lock(void)
65+
{
66+
}
67+
#endif
68+
4669
static inline unsigned long ___tlbie(unsigned long vpn, int psize,
4770
int apsize, int ssize)
4871
{
@@ -220,6 +243,7 @@ static inline void native_lock_hpte(struct hash_pte *hptep)
220243
{
221244
unsigned long *word = (unsigned long *)&hptep->v;
222245

246+
acquire_hpte_lock();
223247
while (1) {
224248
if (!test_and_set_bit_lock(HPTE_LOCK_BIT, word))
225249
break;
@@ -234,6 +258,7 @@ static inline void native_unlock_hpte(struct hash_pte *hptep)
234258
{
235259
unsigned long *word = (unsigned long *)&hptep->v;
236260

261+
release_hpte_lock();
237262
clear_bit_unlock(HPTE_LOCK_BIT, word);
238263
}
239264

@@ -243,8 +268,11 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long vpn,
243268
{
244269
struct hash_pte *hptep = htab_address + hpte_group;
245270
unsigned long hpte_v, hpte_r;
271+
unsigned long flags;
246272
int i;
247273

274+
local_irq_save(flags);
275+
248276
if (!(vflags & HPTE_V_BOLTED)) {
249277
DBG_LOW(" insert(group=%lx, vpn=%016lx, pa=%016lx,"
250278
" rflags=%lx, vflags=%lx, psize=%d)\n",
@@ -263,8 +291,10 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long vpn,
263291
hptep++;
264292
}
265293

266-
if (i == HPTES_PER_GROUP)
294+
if (i == HPTES_PER_GROUP) {
295+
local_irq_restore(flags);
267296
return -1;
297+
}
268298

269299
hpte_v = hpte_encode_v(vpn, psize, apsize, ssize) | vflags | HPTE_V_VALID;
270300
hpte_r = hpte_encode_r(pa, psize, apsize) | rflags;
@@ -286,10 +316,13 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long vpn,
286316
* Now set the first dword including the valid bit
287317
* NOTE: this also unlocks the hpte
288318
*/
319+
release_hpte_lock();
289320
hptep->v = cpu_to_be64(hpte_v);
290321

291322
__asm__ __volatile__ ("ptesync" : : : "memory");
292323

324+
local_irq_restore(flags);
325+
293326
return i | (!!(vflags & HPTE_V_SECONDARY) << 3);
294327
}
295328

@@ -327,6 +360,7 @@ static long native_hpte_remove(unsigned long hpte_group)
327360
return -1;
328361

329362
/* Invalidate the hpte. NOTE: this also unlocks it */
363+
release_hpte_lock();
330364
hptep->v = 0;
331365

332366
return i;
@@ -339,6 +373,9 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
339373
struct hash_pte *hptep = htab_address + slot;
340374
unsigned long hpte_v, want_v;
341375
int ret = 0, local = 0;
376+
unsigned long irqflags;
377+
378+
local_irq_save(irqflags);
342379

343380
want_v = hpte_encode_avpn(vpn, bpsize, ssize);
344381

@@ -382,6 +419,8 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
382419
if (!(flags & HPTE_NOHPTE_UPDATE))
383420
tlbie(vpn, bpsize, apsize, ssize, local);
384421

422+
local_irq_restore(irqflags);
423+
385424
return ret;
386425
}
387426

@@ -445,6 +484,9 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
445484
unsigned long vsid;
446485
long slot;
447486
struct hash_pte *hptep;
487+
unsigned long flags;
488+
489+
local_irq_save(flags);
448490

449491
vsid = get_kernel_vsid(ea, ssize);
450492
vpn = hpt_vpn(ea, vsid, ssize);
@@ -463,6 +505,8 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
463505
* actual page size will be same.
464506
*/
465507
tlbie(vpn, psize, psize, ssize, 0);
508+
509+
local_irq_restore(flags);
466510
}
467511

468512
/*
@@ -476,6 +520,9 @@ static int native_hpte_removebolted(unsigned long ea, int psize, int ssize)
476520
unsigned long vsid;
477521
long slot;
478522
struct hash_pte *hptep;
523+
unsigned long flags;
524+
525+
local_irq_save(flags);
479526

480527
vsid = get_kernel_vsid(ea, ssize);
481528
vpn = hpt_vpn(ea, vsid, ssize);
@@ -493,6 +540,9 @@ static int native_hpte_removebolted(unsigned long ea, int psize, int ssize)
493540

494541
/* Invalidate the TLB */
495542
tlbie(vpn, psize, psize, ssize, 0);
543+
544+
local_irq_restore(flags);
545+
496546
return 0;
497547
}
498548

@@ -517,10 +567,11 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long vpn,
517567
/* recheck with locks held */
518568
hpte_v = hpte_get_old_v(hptep);
519569

520-
if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID))
570+
if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID)) {
521571
/* Invalidate the hpte. NOTE: this also unlocks it */
572+
release_hpte_lock();
522573
hptep->v = 0;
523-
else
574+
} else
524575
native_unlock_hpte(hptep);
525576
}
526577
/*
@@ -580,10 +631,8 @@ static void native_hugepage_invalidate(unsigned long vsid,
580631
hpte_v = hpte_get_old_v(hptep);
581632

582633
if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID)) {
583-
/*
584-
* Invalidate the hpte. NOTE: this also unlocks it
585-
*/
586-
634+
/* Invalidate the hpte. NOTE: this also unlocks it */
635+
release_hpte_lock();
587636
hptep->v = 0;
588637
} else
589638
native_unlock_hpte(hptep);
@@ -765,8 +814,10 @@ static void native_flush_hash_range(unsigned long number, int local)
765814

766815
if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID))
767816
native_unlock_hpte(hptep);
768-
else
817+
else {
818+
release_hpte_lock();
769819
hptep->v = 0;
820+
}
770821

771822
} pte_iterate_hashed_end();
772823
}

arch/powerpc/mm/book3s64/hash_pgtable.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,8 @@ EXPORT_SYMBOL_GPL(hash__has_transparent_hugepage);
404404

405405
struct change_memory_parms {
406406
unsigned long start, end, newpp;
407-
unsigned int step, nr_cpus, master_cpu;
407+
unsigned int step, nr_cpus;
408+
atomic_t master_cpu;
408409
atomic_t cpu_counter;
409410
};
410411

@@ -478,7 +479,8 @@ static int change_memory_range_fn(void *data)
478479
{
479480
struct change_memory_parms *parms = data;
480481

481-
if (parms->master_cpu != smp_processor_id())
482+
// First CPU goes through, all others wait.
483+
if (atomic_xchg(&parms->master_cpu, 1) == 1)
482484
return chmem_secondary_loop(parms);
483485

484486
// Wait for all but one CPU (this one) to call-in
@@ -516,7 +518,7 @@ static bool hash__change_memory_range(unsigned long start, unsigned long end,
516518
chmem_parms.end = end;
517519
chmem_parms.step = step;
518520
chmem_parms.newpp = newpp;
519-
chmem_parms.master_cpu = smp_processor_id();
521+
atomic_set(&chmem_parms.master_cpu, 0);
520522

521523
cpus_read_lock();
522524

0 commit comments

Comments
 (0)