Skip to content

Commit 63d1cb5

Browse files
committed
Merge tag 'powerpc-5.13-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc fixes from Michael Ellerman: - Fix a regression in the conversion of the 64-bit BookE interrupt entry to C. - Fix KVM hosts running with the hash MMU since the recent KVM gfn changes. - Fix a deadlock in our paravirt spinlocks when hcall tracing is enabled. - Several fixes for oopses in our runtime code patching for security mitigations. - A couple of minor fixes for the recent conversion of 32-bit interrupt entry/exit to C. - Fix __get_user() causing spurious crashes in sigreturn due to a bad inline asm constraint, spotted with GCC 11. - A fix for the way we track IRQ masking state vs NMI interrupts when using the new scv system call entry path. - A couple more minor fixes. Thanks to Cédric Le Goater, Christian Zigotzky, Christophe Leroy, Naveen N. Rao, Nicholas Piggin Paul Menzel, and Sean Christopherson. * tag 'powerpc-5.13-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc/64e/interrupt: Fix nvgprs being clobbered powerpc/64s: Make NMI record implicitly soft-masked code as irqs disabled powerpc/64s: Fix stf mitigation patching w/strict RWX & hash powerpc/64s: Fix entry flush patching w/strict RWX & hash powerpc/64s: Fix crashes when toggling entry flush barrier powerpc/64s: Fix crashes when toggling stf barrier KVM: PPC: Book3S HV: Fix kvm_unmap_gfn_range_hv() for Hash MMU powerpc/legacy_serial: Fix UBSAN: array-index-out-of-bounds powerpc/signal: Fix possible build failure with unsafe_copy_fpr_{to/from}_user powerpc/uaccess: Fix __get_user() with CONFIG_CC_HAS_ASM_GOTO_OUTPUT powerpc/pseries: warn if recursing into the hcall tracing code powerpc/pseries: use notrace hcall variant for H_CEDE idle powerpc/pseries: Don't trace hcall tracing wrapper powerpc/pseries: Fix hcall tracing recursion in pv queued spinlocks powerpc/syscall: Calling kuap_save_and_lock() is wrong powerpc/interrupts: Fix kuep_unlock() call
2 parents c12a29e + c6ac667 commit 63d1cb5

File tree

13 files changed

+175
-75
lines changed

13 files changed

+175
-75
lines changed

arch/powerpc/include/asm/hvcall.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,9 @@
448448
*/
449449
long plpar_hcall_norets(unsigned long opcode, ...);
450450

451+
/* Variant which does not do hcall tracing */
452+
long plpar_hcall_norets_notrace(unsigned long opcode, ...);
453+
451454
/**
452455
* plpar_hcall: - Make a pseries hypervisor call
453456
* @opcode: The hypervisor call to make.

arch/powerpc/include/asm/interrupt.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,6 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrup
153153
*/
154154
static inline void interrupt_exit_prepare(struct pt_regs *regs, struct interrupt_state *state)
155155
{
156-
if (user_mode(regs))
157-
kuep_unlock();
158156
}
159157

160158
static inline void interrupt_async_enter_prepare(struct pt_regs *regs, struct interrupt_state *state)
@@ -222,6 +220,13 @@ static inline void interrupt_nmi_enter_prepare(struct pt_regs *regs, struct inte
222220
local_paca->irq_soft_mask = IRQS_ALL_DISABLED;
223221
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
224222

223+
if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && !(regs->msr & MSR_PR) &&
224+
regs->nip < (unsigned long)__end_interrupts) {
225+
// Kernel code running below __end_interrupts is
226+
// implicitly soft-masked.
227+
regs->softe = IRQS_ALL_DISABLED;
228+
}
229+
225230
/* Don't do any per-CPU operations until interrupt state is fixed */
226231

227232
if (nmi_disables_ftrace(regs)) {

arch/powerpc/include/asm/paravirt.h

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,35 @@ static inline u32 yield_count_of(int cpu)
2828
return be32_to_cpu(yield_count);
2929
}
3030

31+
/*
32+
* Spinlock code confers and prods, so don't trace the hcalls because the
33+
* tracing code takes spinlocks which can cause recursion deadlocks.
34+
*
35+
* These calls are made while the lock is not held: the lock slowpath yields if
36+
* it can not acquire the lock, and unlock slow path might prod if a waiter has
37+
* yielded). So this may not be a problem for simple spin locks because the
38+
* tracing does not technically recurse on the lock, but we avoid it anyway.
39+
*
40+
* However the queued spin lock contended path is more strictly ordered: the
41+
* H_CONFER hcall is made after the task has queued itself on the lock, so then
42+
* recursing on that lock will cause the task to then queue up again behind the
43+
* first instance (or worse: queued spinlocks use tricks that assume a context
44+
* never waits on more than one spinlock, so such recursion may cause random
45+
* corruption in the lock code).
46+
*/
3147
static inline void yield_to_preempted(int cpu, u32 yield_count)
3248
{
33-
plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(cpu), yield_count);
49+
plpar_hcall_norets_notrace(H_CONFER, get_hard_smp_processor_id(cpu), yield_count);
3450
}
3551

3652
static inline void prod_cpu(int cpu)
3753
{
38-
plpar_hcall_norets(H_PROD, get_hard_smp_processor_id(cpu));
54+
plpar_hcall_norets_notrace(H_PROD, get_hard_smp_processor_id(cpu));
3955
}
4056

4157
static inline void yield_to_any(void)
4258
{
43-
plpar_hcall_norets(H_CONFER, -1, 0);
59+
plpar_hcall_norets_notrace(H_CONFER, -1, 0);
4460
}
4561
#else
4662
static inline bool is_shared_processor(void)

arch/powerpc/include/asm/plpar_wrappers.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ static inline void set_cede_latency_hint(u8 latency_hint)
2828

2929
static inline long cede_processor(void)
3030
{
31-
return plpar_hcall_norets(H_CEDE);
31+
/*
32+
* We cannot call tracepoints inside RCU idle regions which
33+
* means we must not trace H_CEDE.
34+
*/
35+
return plpar_hcall_norets_notrace(H_CEDE);
3236
}
3337

3438
static inline long extended_cede_processor(unsigned long latency_hint)

arch/powerpc/include/asm/uaccess.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ do { \
157157
"2: lwz%X1 %L0, %L1\n" \
158158
EX_TABLE(1b, %l2) \
159159
EX_TABLE(2b, %l2) \
160-
: "=r" (x) \
160+
: "=&r" (x) \
161161
: "m" (*addr) \
162162
: \
163163
: label)

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

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,12 @@ ret_from_mc_except:
340340
andi. r10,r10,IRQS_DISABLED; /* yes -> go out of line */ \
341341
bne masked_interrupt_book3e_##n
342342

343+
/*
344+
* Additional regs must be re-loaded from paca before EXCEPTION_COMMON* is
345+
* called, because that does SAVE_NVGPRS which must see the original register
346+
* values, otherwise the scratch values might be restored when exiting the
347+
* interrupt.
348+
*/
343349
#define PROLOG_ADDITION_2REGS_GEN(n) \
344350
std r14,PACA_EXGEN+EX_R14(r13); \
345351
std r15,PACA_EXGEN+EX_R15(r13)
@@ -535,6 +541,10 @@ __end_interrupts:
535541
PROLOG_ADDITION_2REGS)
536542
mfspr r14,SPRN_DEAR
537543
mfspr r15,SPRN_ESR
544+
std r14,_DAR(r1)
545+
std r15,_DSISR(r1)
546+
ld r14,PACA_EXGEN+EX_R14(r13)
547+
ld r15,PACA_EXGEN+EX_R15(r13)
538548
EXCEPTION_COMMON(0x300)
539549
b storage_fault_common
540550

@@ -544,6 +554,10 @@ __end_interrupts:
544554
PROLOG_ADDITION_2REGS)
545555
li r15,0
546556
mr r14,r10
557+
std r14,_DAR(r1)
558+
std r15,_DSISR(r1)
559+
ld r14,PACA_EXGEN+EX_R14(r13)
560+
ld r15,PACA_EXGEN+EX_R15(r13)
547561
EXCEPTION_COMMON(0x400)
548562
b storage_fault_common
549563

@@ -557,6 +571,10 @@ __end_interrupts:
557571
PROLOG_ADDITION_2REGS)
558572
mfspr r14,SPRN_DEAR
559573
mfspr r15,SPRN_ESR
574+
std r14,_DAR(r1)
575+
std r15,_DSISR(r1)
576+
ld r14,PACA_EXGEN+EX_R14(r13)
577+
ld r15,PACA_EXGEN+EX_R15(r13)
560578
EXCEPTION_COMMON(0x600)
561579
b alignment_more /* no room, go out of line */
562580

@@ -565,10 +583,10 @@ __end_interrupts:
565583
NORMAL_EXCEPTION_PROLOG(0x700, BOOKE_INTERRUPT_PROGRAM,
566584
PROLOG_ADDITION_1REG)
567585
mfspr r14,SPRN_ESR
568-
EXCEPTION_COMMON(0x700)
569586
std r14,_DSISR(r1)
570-
addi r3,r1,STACK_FRAME_OVERHEAD
571587
ld r14,PACA_EXGEN+EX_R14(r13)
588+
EXCEPTION_COMMON(0x700)
589+
addi r3,r1,STACK_FRAME_OVERHEAD
572590
bl program_check_exception
573591
REST_NVGPRS(r1)
574592
b interrupt_return
@@ -725,11 +743,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
725743
* normal exception
726744
*/
727745
mfspr r14,SPRN_DBSR
728-
EXCEPTION_COMMON_CRIT(0xd00)
729746
std r14,_DSISR(r1)
730-
addi r3,r1,STACK_FRAME_OVERHEAD
731747
ld r14,PACA_EXCRIT+EX_R14(r13)
732748
ld r15,PACA_EXCRIT+EX_R15(r13)
749+
EXCEPTION_COMMON_CRIT(0xd00)
750+
addi r3,r1,STACK_FRAME_OVERHEAD
733751
bl DebugException
734752
REST_NVGPRS(r1)
735753
b interrupt_return
@@ -796,11 +814,11 @@ kernel_dbg_exc:
796814
* normal exception
797815
*/
798816
mfspr r14,SPRN_DBSR
799-
EXCEPTION_COMMON_DBG(0xd08)
800817
std r14,_DSISR(r1)
801-
addi r3,r1,STACK_FRAME_OVERHEAD
802818
ld r14,PACA_EXDBG+EX_R14(r13)
803819
ld r15,PACA_EXDBG+EX_R15(r13)
820+
EXCEPTION_COMMON_DBG(0xd08)
821+
addi r3,r1,STACK_FRAME_OVERHEAD
804822
bl DebugException
805823
REST_NVGPRS(r1)
806824
b interrupt_return
@@ -931,11 +949,7 @@ masked_interrupt_book3e_0x2c0:
931949
* original values stashed away in the PACA
932950
*/
933951
storage_fault_common:
934-
std r14,_DAR(r1)
935-
std r15,_DSISR(r1)
936952
addi r3,r1,STACK_FRAME_OVERHEAD
937-
ld r14,PACA_EXGEN+EX_R14(r13)
938-
ld r15,PACA_EXGEN+EX_R15(r13)
939953
bl do_page_fault
940954
b interrupt_return
941955

@@ -944,11 +958,7 @@ storage_fault_common:
944958
* continues here.
945959
*/
946960
alignment_more:
947-
std r14,_DAR(r1)
948-
std r15,_DSISR(r1)
949961
addi r3,r1,STACK_FRAME_OVERHEAD
950-
ld r14,PACA_EXGEN+EX_R14(r13)
951-
ld r15,PACA_EXGEN+EX_R15(r13)
952962
bl alignment_exception
953963
REST_NVGPRS(r1)
954964
b interrupt_return

arch/powerpc/kernel/interrupt.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@ notrace long system_call_exception(long r3, long r4, long r5,
3434
syscall_fn f;
3535

3636
kuep_lock();
37-
#ifdef CONFIG_PPC32
38-
kuap_save_and_lock(regs);
39-
#endif
4037

4138
regs->orig_gpr3 = r3;
4239

@@ -427,6 +424,7 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs, unsigned
427424

428425
/* Restore user access locks last */
429426
kuap_user_restore(regs);
427+
kuep_unlock();
430428

431429
return ret;
432430
}

arch/powerpc/kernel/legacy_serial.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,13 +356,16 @@ static void __init setup_legacy_serial_console(int console)
356356

357357
static int __init ioremap_legacy_serial_console(void)
358358
{
359-
struct legacy_serial_info *info = &legacy_serial_infos[legacy_serial_console];
360-
struct plat_serial8250_port *port = &legacy_serial_ports[legacy_serial_console];
359+
struct plat_serial8250_port *port;
360+
struct legacy_serial_info *info;
361361
void __iomem *vaddr;
362362

363363
if (legacy_serial_console < 0)
364364
return 0;
365365

366+
info = &legacy_serial_infos[legacy_serial_console];
367+
port = &legacy_serial_ports[legacy_serial_console];
368+
366369
if (!info->early_addr)
367370
return 0;
368371

arch/powerpc/kernel/signal.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,9 @@ copy_ckfpr_from_user(struct task_struct *task, void __user *from)
166166
}
167167
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
168168
#else
169-
#define unsafe_copy_fpr_to_user(to, task, label) do { } while (0)
169+
#define unsafe_copy_fpr_to_user(to, task, label) do { if (0) goto label;} while (0)
170170

171-
#define unsafe_copy_fpr_from_user(task, from, label) do { } while (0)
171+
#define unsafe_copy_fpr_from_user(task, from, label) do { if (0) goto label;} while (0)
172172

173173
static inline unsigned long
174174
copy_fpr_to_user(void __user *to, struct task_struct *task)

arch/powerpc/kvm/book3s_64_mmu_hv.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ bool kvm_unmap_gfn_range_hv(struct kvm *kvm, struct kvm_gfn_range *range)
840840
kvm_unmap_radix(kvm, range->slot, gfn);
841841
} else {
842842
for (gfn = range->start; gfn < range->end; gfn++)
843-
kvm_unmap_rmapp(kvm, range->slot, range->start);
843+
kvm_unmap_rmapp(kvm, range->slot, gfn);
844844
}
845845

846846
return false;

0 commit comments

Comments
 (0)