Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+159 -55
+43
arch/powerpc/kernel/interrupt.c
··· 18 18 #include <asm/switch_to.h> 19 19 #include <asm/syscall.h> 20 20 #include <asm/time.h> 21 + #include <asm/tm.h> 21 22 #include <asm/unistd.h> 22 23 23 24 #if defined(CONFIG_PPC_ADV_DEBUG_REGS) && defined(CONFIG_PPC32) ··· 136 135 * returns to user with IRQS_ENABLED, this store could be avoided! 137 136 */ 138 137 irq_soft_mask_regs_set_state(regs, IRQS_ENABLED); 138 + 139 + /* 140 + * If system call is called with TM active, set _TIF_RESTOREALL to 141 + * prevent RFSCV being used to return to userspace, because POWER9 142 + * TM implementation has problems with this instruction returning to 143 + * transactional state. Final register values are not relevant because 144 + * the transaction will be aborted upon return anyway. Or in the case 145 + * of unsupported_scv SIGILL fault, the return state does not much 146 + * matter because it's an edge case. 147 + */ 148 + if (IS_ENABLED(CONFIG_PPC_TRANSACTIONAL_MEM) && 149 + unlikely(MSR_TM_TRANSACTIONAL(regs->msr))) 150 + current_thread_info()->flags |= _TIF_RESTOREALL; 151 + 152 + /* 153 + * If the system call was made with a transaction active, doom it and 154 + * return without performing the system call. Unless it was an 155 + * unsupported scv vector, in which case it's treated like an illegal 156 + * instruction. 157 + */ 158 + #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 159 + if (unlikely(MSR_TM_TRANSACTIONAL(regs->msr)) && 160 + !trap_is_unsupported_scv(regs)) { 161 + /* Enable TM in the kernel, and disable EE (for scv) */ 162 + hard_irq_disable(); 163 + mtmsr(mfmsr() | MSR_TM); 164 + 165 + /* tabort, this dooms the transaction, nothing else */ 166 + asm volatile(".long 0x7c00071d | ((%0) << 16)" 167 + :: "r"(TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT)); 168 + 169 + /* 170 + * Userspace will never see the return value. Execution will 171 + * resume after the tbegin. of the aborted transaction with the 172 + * checkpointed register state. A context switch could occur 173 + * or signal delivered to the process before resuming the 174 + * doomed transaction context, but that should all be handled 175 + * as expected. 176 + */ 177 + return -ENOSYS; 178 + } 179 + #endif // CONFIG_PPC_TRANSACTIONAL_MEM 139 180 140 181 local_irq_enable(); 141 182
-41
arch/powerpc/kernel/interrupt_64.S
··· 12 12 #include <asm/mmu.h> 13 13 #include <asm/ppc_asm.h> 14 14 #include <asm/ptrace.h> 15 - #include <asm/tm.h> 16 15 17 16 .section ".toc","aw" 18 17 SYS_CALL_TABLE: ··· 54 55 .globl system_call_vectored_\name 55 56 system_call_vectored_\name: 56 57 _ASM_NOKPROBE_SYMBOL(system_call_vectored_\name) 57 - #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 58 - BEGIN_FTR_SECTION 59 - extrdi. r10, r12, 1, (63-MSR_TS_T_LG) /* transaction active? */ 60 - bne tabort_syscall 61 - END_FTR_SECTION_IFSET(CPU_FTR_TM) 62 - #endif 63 58 SCV_INTERRUPT_TO_KERNEL 64 59 mr r10,r1 65 60 ld r1,PACAKSAVE(r13) ··· 240 247 .globl system_call_common 241 248 system_call_common: 242 249 _ASM_NOKPROBE_SYMBOL(system_call_common) 243 - #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 244 - BEGIN_FTR_SECTION 245 - extrdi. r10, r12, 1, (63-MSR_TS_T_LG) /* transaction active? */ 246 - bne tabort_syscall 247 - END_FTR_SECTION_IFSET(CPU_FTR_TM) 248 - #endif 249 250 mr r10,r1 250 251 ld r1,PACAKSAVE(r13) 251 252 std r10,0(r1) ··· 410 423 411 424 SOFT_MASK_TABLE(.Lsyscall_rst_start, 1b) 412 425 RESTART_TABLE(.Lsyscall_rst_start, .Lsyscall_rst_end, syscall_restart) 413 - #endif 414 - 415 - #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 416 - tabort_syscall: 417 - _ASM_NOKPROBE_SYMBOL(tabort_syscall) 418 - /* Firstly we need to enable TM in the kernel */ 419 - mfmsr r10 420 - li r9, 1 421 - rldimi r10, r9, MSR_TM_LG, 63-MSR_TM_LG 422 - mtmsrd r10, 0 423 - 424 - /* tabort, this dooms the transaction, nothing else */ 425 - li r9, (TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT) 426 - TABORT(R9) 427 - 428 - /* 429 - * Return directly to userspace. We have corrupted user register state, 430 - * but userspace will never see that register state. Execution will 431 - * resume after the tbegin of the aborted transaction with the 432 - * checkpointed register state. 433 - */ 434 - li r9, MSR_RI 435 - andc r10, r10, r9 436 - mtmsrd r10, 1 437 - mtspr SPRN_SRR0, r11 438 - mtspr SPRN_SRR1, r12 439 - RFI_TO_USER 440 - b . /* prevent speculative execution */ 441 426 #endif 442 427 443 428 /*
+15 -2
arch/powerpc/kernel/mce.c
··· 249 249 { 250 250 int index; 251 251 struct machine_check_event evt; 252 + unsigned long msr; 252 253 253 254 if (!get_mce_event(&evt, MCE_EVENT_RELEASE)) 254 255 return; ··· 263 262 memcpy(&local_paca->mce_info->mce_event_queue[index], 264 263 &evt, sizeof(evt)); 265 264 266 - /* Queue irq work to process this event later. */ 267 - irq_work_queue(&mce_event_process_work); 265 + /* 266 + * Queue irq work to process this event later. Before 267 + * queuing the work enable translation for non radix LPAR, 268 + * as irq_work_queue may try to access memory outside RMO 269 + * region. 270 + */ 271 + if (!radix_enabled() && firmware_has_feature(FW_FEATURE_LPAR)) { 272 + msr = mfmsr(); 273 + mtmsr(msr | MSR_IR | MSR_DR); 274 + irq_work_queue(&mce_event_process_work); 275 + mtmsr(msr); 276 + } else { 277 + irq_work_queue(&mce_event_process_work); 278 + } 268 279 } 269 280 270 281 void mce_common_process_ue(struct pt_regs *regs,
+34 -2
arch/powerpc/kvm/book3s_hv_rmhandlers.S
··· 2536 2536 /* The following code handles the fake_suspend = 1 case */ 2537 2537 mflr r0 2538 2538 std r0, PPC_LR_STKOFF(r1) 2539 - stdu r1, -PPC_MIN_STKFRM(r1) 2539 + stdu r1, -TM_FRAME_SIZE(r1) 2540 2540 2541 2541 /* Turn on TM. */ 2542 2542 mfmsr r8 ··· 2551 2551 END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_XER_SO_BUG) 2552 2552 nop 2553 2553 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 + 2554 2572 /* We have to treclaim here because that's the only way to do S->N */ 2555 2573 li r3, TM_CAUSE_KVM_RESCHED 2556 2574 TRECLAIM(R3) 2575 + 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 2557 2589 2558 2590 /* 2559 2591 * We were in fake suspend, so we are not going to save the ··· 2614 2582 std r5, VCPU_TFHAR(r9) 2615 2583 std r6, VCPU_TFIAR(r9) 2616 2584 2617 - addi r1, r1, PPC_MIN_STKFRM 2585 + addi r1, r1, TM_FRAME_SIZE 2618 2586 ld r0, PPC_LR_STKOFF(r1) 2619 2587 mtlr r0 2620 2588 blr
+2 -2
arch/powerpc/sysdev/xics/xics-common.c
··· 348 348 if (xics_ics->check(xics_ics, hwirq)) 349 349 return -EINVAL; 350 350 351 - /* No chip data for the XICS domain */ 351 + /* Let the ICS be the chip data for the XICS domain. For ICS native */ 352 352 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); 354 354 355 355 return 0; 356 356 }
+36 -1
tools/testing/selftests/powerpc/tm/tm-syscall-asm.S
··· 1 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 - #include <ppc-asm.h> 2 + #include <basic_asm.h> 3 3 #include <asm/unistd.h> 4 4 5 5 .text ··· 25 25 blr 26 26 1: 27 27 li r3, -1 28 + 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) 28 63 blr
+29 -7
tools/testing/selftests/powerpc/tm/tm-syscall.c
··· 19 19 #include "utils.h" 20 20 #include "tm.h" 21 21 22 + #ifndef PPC_FEATURE2_SCV 23 + #define PPC_FEATURE2_SCV 0x00100000 /* scv syscall */ 24 + #endif 25 + 22 26 extern int getppid_tm_active(void); 23 27 extern int getppid_tm_suspended(void); 28 + extern int getppid_scv_tm_active(void); 29 + extern int getppid_scv_tm_suspended(void); 24 30 25 31 unsigned retries = 0; 26 32 27 33 #define TEST_DURATION 10 /* seconds */ 28 34 29 - pid_t getppid_tm(bool suspend) 35 + pid_t getppid_tm(bool scv, bool suspend) 30 36 { 31 37 int i; 32 38 pid_t pid; 33 39 34 40 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 + } 39 52 40 53 if (pid >= 0) 41 54 return pid; ··· 95 82 * Test a syscall within a suspended transaction and verify 96 83 * that it succeeds. 97 84 */ 98 - FAIL_IF(getppid_tm(true) == -1); /* Should succeed. */ 85 + FAIL_IF(getppid_tm(false, true) == -1); /* Should succeed. */ 99 86 100 87 /* 101 88 * Test a syscall within an active transaction and verify that 102 89 * it fails with the correct failure code. 103 90 */ 104 - FAIL_IF(getppid_tm(false) != -1); /* Should fail... */ 91 + FAIL_IF(getppid_tm(false, false) != -1); /* Should fail... */ 105 92 FAIL_IF(!failure_is_persistent()); /* ...persistently... */ 106 93 FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */ 94 + 95 + /* Now do it all again with scv if it is available. */ 96 + if (have_hwcap2(PPC_FEATURE2_SCV)) { 97 + FAIL_IF(getppid_tm(true, true) == -1); /* Should succeed. */ 98 + FAIL_IF(getppid_tm(true, false) != -1); /* Should fail... */ 99 + FAIL_IF(!failure_is_persistent()); /* ...persistently... */ 100 + FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */ 101 + } 102 + 107 103 gettimeofday(&now, 0); 108 104 } 109 105