Skip to content

Commit 62453a4

Browse files
committed
Merge tag 'powerpc-5.15-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc fixes from Michael Ellerman: - Fix crashes when scv (System Call Vectored) is used to make a syscall when a transaction is active, on Power9 or later. - Fix bad interactions between rfscv (Return-from scv) and Power9 fake-suspend mode. - Fix crashes when handling machine checks in LPARs using the Hash MMU. - Partly revert a recent change to our XICS interrupt controller code, which broke the recently added Microwatt support. Thanks to Cédric Le Goater, Eirik Fuller, Ganesh Goudar, Gustavo Romero, Joel Stanley, Nicholas Piggin. * tag 'powerpc-5.15-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc/xics: Set the IRQ chip data for the ICS native backend powerpc/mce: Fix access error in mce handler KVM: PPC: Book3S HV: Tolerate treclaim. in fake-suspend mode changing registers powerpc/64s: system call rfscv workaround for TM bugs selftests/powerpc: Add scv versions of the basic TM syscall tests powerpc/64s: system call scv tabort fix for corrupt irq soft-mask state
2 parents 2f62996 + c006a06 commit 62453a4

File tree

7 files changed

+159
-55
lines changed

7 files changed

+159
-55
lines changed

arch/powerpc/kernel/interrupt.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <asm/switch_to.h>
1919
#include <asm/syscall.h>
2020
#include <asm/time.h>
21+
#include <asm/tm.h>
2122
#include <asm/unistd.h>
2223

2324
#if defined(CONFIG_PPC_ADV_DEBUG_REGS) && defined(CONFIG_PPC32)
@@ -136,6 +137,48 @@ notrace long system_call_exception(long r3, long r4, long r5,
136137
*/
137138
irq_soft_mask_regs_set_state(regs, IRQS_ENABLED);
138139

140+
/*
141+
* If system call is called with TM active, set _TIF_RESTOREALL to
142+
* prevent RFSCV being used to return to userspace, because POWER9
143+
* TM implementation has problems with this instruction returning to
144+
* transactional state. Final register values are not relevant because
145+
* the transaction will be aborted upon return anyway. Or in the case
146+
* of unsupported_scv SIGILL fault, the return state does not much
147+
* matter because it's an edge case.
148+
*/
149+
if (IS_ENABLED(CONFIG_PPC_TRANSACTIONAL_MEM) &&
150+
unlikely(MSR_TM_TRANSACTIONAL(regs->msr)))
151+
current_thread_info()->flags |= _TIF_RESTOREALL;
152+
153+
/*
154+
* If the system call was made with a transaction active, doom it and
155+
* return without performing the system call. Unless it was an
156+
* unsupported scv vector, in which case it's treated like an illegal
157+
* instruction.
158+
*/
159+
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
160+
if (unlikely(MSR_TM_TRANSACTIONAL(regs->msr)) &&
161+
!trap_is_unsupported_scv(regs)) {
162+
/* Enable TM in the kernel, and disable EE (for scv) */
163+
hard_irq_disable();
164+
mtmsr(mfmsr() | MSR_TM);
165+
166+
/* tabort, this dooms the transaction, nothing else */
167+
asm volatile(".long 0x7c00071d | ((%0) << 16)"
168+
:: "r"(TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT));
169+
170+
/*
171+
* Userspace will never see the return value. Execution will
172+
* resume after the tbegin. of the aborted transaction with the
173+
* checkpointed register state. A context switch could occur
174+
* or signal delivered to the process before resuming the
175+
* doomed transaction context, but that should all be handled
176+
* as expected.
177+
*/
178+
return -ENOSYS;
179+
}
180+
#endif // CONFIG_PPC_TRANSACTIONAL_MEM
181+
139182
local_irq_enable();
140183

141184
if (unlikely(current_thread_info()->flags & _TIF_SYSCALL_DOTRACE)) {

arch/powerpc/kernel/interrupt_64.S

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include <asm/mmu.h>
1313
#include <asm/ppc_asm.h>
1414
#include <asm/ptrace.h>
15-
#include <asm/tm.h>
1615

1716
.section ".toc","aw"
1817
SYS_CALL_TABLE:
@@ -55,12 +54,6 @@ COMPAT_SYS_CALL_TABLE:
5554
.globl system_call_vectored_\name
5655
system_call_vectored_\name:
5756
_ASM_NOKPROBE_SYMBOL(system_call_vectored_\name)
58-
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
59-
BEGIN_FTR_SECTION
60-
extrdi. r10, r12, 1, (63-MSR_TS_T_LG) /* transaction active? */
61-
bne tabort_syscall
62-
END_FTR_SECTION_IFSET(CPU_FTR_TM)
63-
#endif
6457
SCV_INTERRUPT_TO_KERNEL
6558
mr r10,r1
6659
ld r1,PACAKSAVE(r13)
@@ -247,12 +240,6 @@ _ASM_NOKPROBE_SYMBOL(system_call_common_real)
247240
.globl system_call_common
248241
system_call_common:
249242
_ASM_NOKPROBE_SYMBOL(system_call_common)
250-
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
251-
BEGIN_FTR_SECTION
252-
extrdi. r10, r12, 1, (63-MSR_TS_T_LG) /* transaction active? */
253-
bne tabort_syscall
254-
END_FTR_SECTION_IFSET(CPU_FTR_TM)
255-
#endif
256243
mr r10,r1
257244
ld r1,PACAKSAVE(r13)
258245
std r10,0(r1)
@@ -425,34 +412,6 @@ SOFT_MASK_TABLE(.Lsyscall_rst_start, 1b)
425412
RESTART_TABLE(.Lsyscall_rst_start, .Lsyscall_rst_end, syscall_restart)
426413
#endif
427414

428-
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
429-
tabort_syscall:
430-
_ASM_NOKPROBE_SYMBOL(tabort_syscall)
431-
/* Firstly we need to enable TM in the kernel */
432-
mfmsr r10
433-
li r9, 1
434-
rldimi r10, r9, MSR_TM_LG, 63-MSR_TM_LG
435-
mtmsrd r10, 0
436-
437-
/* tabort, this dooms the transaction, nothing else */
438-
li r9, (TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT)
439-
TABORT(R9)
440-
441-
/*
442-
* Return directly to userspace. We have corrupted user register state,
443-
* but userspace will never see that register state. Execution will
444-
* resume after the tbegin of the aborted transaction with the
445-
* checkpointed register state.
446-
*/
447-
li r9, MSR_RI
448-
andc r10, r10, r9
449-
mtmsrd r10, 1
450-
mtspr SPRN_SRR0, r11
451-
mtspr SPRN_SRR1, r12
452-
RFI_TO_USER
453-
b . /* prevent speculative execution */
454-
#endif
455-
456415
/*
457416
* If MSR EE/RI was never enabled, IRQs not reconciled, NVGPRs not
458417
* touched, no exit work created, then this can be used.

arch/powerpc/kernel/mce.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ void machine_check_queue_event(void)
249249
{
250250
int index;
251251
struct machine_check_event evt;
252+
unsigned long msr;
252253

253254
if (!get_mce_event(&evt, MCE_EVENT_RELEASE))
254255
return;
@@ -262,8 +263,20 @@ void machine_check_queue_event(void)
262263
memcpy(&local_paca->mce_info->mce_event_queue[index],
263264
&evt, sizeof(evt));
264265

265-
/* Queue irq work to process this event later. */
266-
irq_work_queue(&mce_event_process_work);
266+
/*
267+
* Queue irq work to process this event later. Before
268+
* queuing the work enable translation for non radix LPAR,
269+
* as irq_work_queue may try to access memory outside RMO
270+
* region.
271+
*/
272+
if (!radix_enabled() && firmware_has_feature(FW_FEATURE_LPAR)) {
273+
msr = mfmsr();
274+
mtmsr(msr | MSR_IR | MSR_DR);
275+
irq_work_queue(&mce_event_process_work);
276+
mtmsr(msr);
277+
} else {
278+
irq_work_queue(&mce_event_process_work);
279+
}
267280
}
268281

269282
void mce_common_process_ue(struct pt_regs *regs,

arch/powerpc/kvm/book3s_hv_rmhandlers.S

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2536,7 +2536,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_P9_TM_HV_ASSIST)
25362536
/* The following code handles the fake_suspend = 1 case */
25372537
mflr r0
25382538
std r0, PPC_LR_STKOFF(r1)
2539-
stdu r1, -PPC_MIN_STKFRM(r1)
2539+
stdu r1, -TM_FRAME_SIZE(r1)
25402540

25412541
/* Turn on TM. */
25422542
mfmsr r8
@@ -2551,10 +2551,42 @@ BEGIN_FTR_SECTION
25512551
END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_XER_SO_BUG)
25522552
nop
25532553

2554+
/*
2555+
* It's possible that treclaim. may modify registers, if we have lost
2556+
* track of fake-suspend state in the guest due to it using rfscv.
2557+
* Save and restore registers in case this occurs.
2558+
*/
2559+
mfspr r3, SPRN_DSCR
2560+
mfspr r4, SPRN_XER
2561+
mfspr r5, SPRN_AMR
2562+
/* SPRN_TAR would need to be saved here if the kernel ever used it */
2563+
mfcr r12
2564+
SAVE_NVGPRS(r1)
2565+
SAVE_GPR(2, r1)
2566+
SAVE_GPR(3, r1)
2567+
SAVE_GPR(4, r1)
2568+
SAVE_GPR(5, r1)
2569+
stw r12, 8(r1)
2570+
std r1, HSTATE_HOST_R1(r13)
2571+
25542572
/* We have to treclaim here because that's the only way to do S->N */
25552573
li r3, TM_CAUSE_KVM_RESCHED
25562574
TRECLAIM(R3)
25572575

2576+
GET_PACA(r13)
2577+
ld r1, HSTATE_HOST_R1(r13)
2578+
REST_GPR(2, r1)
2579+
REST_GPR(3, r1)
2580+
REST_GPR(4, r1)
2581+
REST_GPR(5, r1)
2582+
lwz r12, 8(r1)
2583+
REST_NVGPRS(r1)
2584+
mtspr SPRN_DSCR, r3
2585+
mtspr SPRN_XER, r4
2586+
mtspr SPRN_AMR, r5
2587+
mtcr r12
2588+
HMT_MEDIUM
2589+
25582590
/*
25592591
* We were in fake suspend, so we are not going to save the
25602592
* register state as the guest checkpointed state (since
@@ -2582,7 +2614,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_XER_SO_BUG)
25822614
std r5, VCPU_TFHAR(r9)
25832615
std r6, VCPU_TFIAR(r9)
25842616

2585-
addi r1, r1, PPC_MIN_STKFRM
2617+
addi r1, r1, TM_FRAME_SIZE
25862618
ld r0, PPC_LR_STKOFF(r1)
25872619
mtlr r0
25882620
blr

arch/powerpc/sysdev/xics/xics-common.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,9 +348,9 @@ static int xics_host_map(struct irq_domain *domain, unsigned int virq,
348348
if (xics_ics->check(xics_ics, hwirq))
349349
return -EINVAL;
350350

351-
/* No chip data for the XICS domain */
351+
/* Let the ICS be the chip data for the XICS domain. For ICS native */
352352
irq_domain_set_info(domain, virq, hwirq, xics_ics->chip,
353-
NULL, handle_fasteoi_irq, NULL, NULL);
353+
xics_ics, handle_fasteoi_irq, NULL, NULL);
354354

355355
return 0;
356356
}

tools/testing/selftests/powerpc/tm/tm-syscall-asm.S

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* SPDX-License-Identifier: GPL-2.0 */
2-
#include <ppc-asm.h>
2+
#include <basic_asm.h>
33
#include <asm/unistd.h>
44

55
.text
@@ -26,3 +26,38 @@ FUNC_START(getppid_tm_suspended)
2626
1:
2727
li r3, -1
2828
blr
29+
30+
31+
.macro scv level
32+
.long (0x44000001 | (\level) << 5)
33+
.endm
34+
35+
FUNC_START(getppid_scv_tm_active)
36+
PUSH_BASIC_STACK(0)
37+
tbegin.
38+
beq 1f
39+
li r0, __NR_getppid
40+
scv 0
41+
tend.
42+
POP_BASIC_STACK(0)
43+
blr
44+
1:
45+
li r3, -1
46+
POP_BASIC_STACK(0)
47+
blr
48+
49+
FUNC_START(getppid_scv_tm_suspended)
50+
PUSH_BASIC_STACK(0)
51+
tbegin.
52+
beq 1f
53+
li r0, __NR_getppid
54+
tsuspend.
55+
scv 0
56+
tresume.
57+
tend.
58+
POP_BASIC_STACK(0)
59+
blr
60+
1:
61+
li r3, -1
62+
POP_BASIC_STACK(0)
63+
blr

tools/testing/selftests/powerpc/tm/tm-syscall.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,36 @@
1919
#include "utils.h"
2020
#include "tm.h"
2121

22+
#ifndef PPC_FEATURE2_SCV
23+
#define PPC_FEATURE2_SCV 0x00100000 /* scv syscall */
24+
#endif
25+
2226
extern int getppid_tm_active(void);
2327
extern int getppid_tm_suspended(void);
28+
extern int getppid_scv_tm_active(void);
29+
extern int getppid_scv_tm_suspended(void);
2430

2531
unsigned retries = 0;
2632

2733
#define TEST_DURATION 10 /* seconds */
2834

29-
pid_t getppid_tm(bool suspend)
35+
pid_t getppid_tm(bool scv, bool suspend)
3036
{
3137
int i;
3238
pid_t pid;
3339

3440
for (i = 0; i < TM_RETRIES; i++) {
35-
if (suspend)
36-
pid = getppid_tm_suspended();
37-
else
38-
pid = getppid_tm_active();
41+
if (suspend) {
42+
if (scv)
43+
pid = getppid_scv_tm_suspended();
44+
else
45+
pid = getppid_tm_suspended();
46+
} else {
47+
if (scv)
48+
pid = getppid_scv_tm_active();
49+
else
50+
pid = getppid_tm_active();
51+
}
3952

4053
if (pid >= 0)
4154
return pid;
@@ -82,15 +95,24 @@ int tm_syscall(void)
8295
* Test a syscall within a suspended transaction and verify
8396
* that it succeeds.
8497
*/
85-
FAIL_IF(getppid_tm(true) == -1); /* Should succeed. */
98+
FAIL_IF(getppid_tm(false, true) == -1); /* Should succeed. */
8699

87100
/*
88101
* Test a syscall within an active transaction and verify that
89102
* it fails with the correct failure code.
90103
*/
91-
FAIL_IF(getppid_tm(false) != -1); /* Should fail... */
104+
FAIL_IF(getppid_tm(false, false) != -1); /* Should fail... */
92105
FAIL_IF(!failure_is_persistent()); /* ...persistently... */
93106
FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */
107+
108+
/* Now do it all again with scv if it is available. */
109+
if (have_hwcap2(PPC_FEATURE2_SCV)) {
110+
FAIL_IF(getppid_tm(true, true) == -1); /* Should succeed. */
111+
FAIL_IF(getppid_tm(true, false) != -1); /* Should fail... */
112+
FAIL_IF(!failure_is_persistent()); /* ...persistently... */
113+
FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */
114+
}
115+
94116
gettimeofday(&now, 0);
95117
}
96118

0 commit comments

Comments
 (0)