mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-11 08:18:47 +00:00
1dff3064c7
On P9 DD2.2 due to a CPU defect some TM instructions need to be emulated by KVM. This is handled at first by the hardware raising a softpatch interrupt when certain TM instructions that need KVM assistance are executed in the guest. Althought some TM instructions per Power ISA are invalid forms they can raise a softpatch interrupt too. For instance, 'tresume.' instruction as defined in the ISA must have bit 31 set (1), but an instruction that matches 'tresume.' PO and XO opcode fields but has bit 31 not set (0), like 0x7cfe9ddc, also raises a softpatch interrupt. Similarly for 'treclaim.' and 'trechkpt.' instructions with bit 31 = 0, i.e. 0x7c00075c and 0x7c0007dc, respectively. Hence, if a code like the following is executed in the guest it will raise a softpatch interrupt just like a 'tresume.' when the TM facility is enabled ('tabort. 0' in the example is used only to enable the TM facility): int main() { asm("tabort. 0; .long 0x7cfe9ddc;"); } Currently in such a case KVM throws a complete trace like: [345523.705984] WARNING: CPU: 24 PID: 64413 at arch/powerpc/kvm/book3s_hv_tm.c:211 kvmhv_p9_tm_emulation+0x68/0x620 [kvm_hv] [345523.705985] Modules linked in: kvm_hv(E) xt_conntrack ipt_REJECT nf_reject_ipv4 xt_tcpudp ip6table_mangle ip6table_nat iptable_mangle iptable_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter bridge stp llc sch_fq_codel ipmi_powernv at24 vmx_crypto ipmi_devintf ipmi_msghandler ibmpowernv uio_pdrv_genirq kvm opal_prd uio leds_powernv ib_iser rdma_cm iw_cm ib_cm ib_core iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi ip_tables x_tables autofs4 btrfs blake2b_generic zstd_compress raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx libcrc32c xor raid6_pq raid1 raid0 multipath linear tg3 crct10dif_vpmsum crc32c_vpmsum ipr [last unloaded: kvm_hv] [345523.706030] CPU: 24 PID: 64413 Comm: CPU 0/KVM Tainted: G W E 5.5.0+ #1 [345523.706031] NIP: c0080000072cb9c0 LR: c0080000072b5e80 CTR: c0080000085c7850 [345523.706034] REGS: c000000399467680 TRAP: 0700 Tainted: G W E (5.5.0+) [345523.706034] MSR: 900000010282b033 <SF,HV,VEC,VSX,EE,FP,ME,IR,DR,RI,LE,TM[E]> CR: 24022428 XER: 00000000 [345523.706042] CFAR: c0080000072b5e7c IRQMASK: 0 GPR00: c0080000072b5e80 c000000399467910 c0080000072db500 c000000375ccc720 GPR04: c000000375ccc720 00000003fbec0000 0000a10395dda5a6 0000000000000000 GPR08: 000000007cfe9ddc 7cfe9ddc000005dc 7cfe9ddc7c0005dc c0080000072cd530 GPR12: c0080000085c7850 c0000003fffeb800 0000000000000001 00007dfb737f0000 GPR16: c0002001edcca558 0000000000000000 0000000000000000 0000000000000001 GPR20: c000000001b21258 c0002001edcca558 0000000000000018 0000000000000000 GPR24: 0000000001000000 ffffffffffffffff 0000000000000001 0000000000001500 GPR28: c0002001edcc4278 c00000037dd80000 800000050280f033 c000000375ccc720 [345523.706062] NIP [c0080000072cb9c0] kvmhv_p9_tm_emulation+0x68/0x620 [kvm_hv] [345523.706065] LR [c0080000072b5e80] kvmppc_handle_exit_hv.isra.53+0x3e8/0x798 [kvm_hv] [345523.706066] Call Trace: [345523.706069] [c000000399467910] [c000000399467940] 0xc000000399467940 (unreliable) [345523.706071] [c000000399467950] [c000000399467980] 0xc000000399467980 [345523.706075] [c0000003994679f0] [c0080000072bd1c4] kvmhv_run_single_vcpu+0xa1c/0xb80 [kvm_hv] [345523.706079] [c000000399467ac0] [c0080000072bd8e0] kvmppc_vcpu_run_hv+0x5b8/0xb00 [kvm_hv] [345523.706087] [c000000399467b90] [c0080000085c93cc] kvmppc_vcpu_run+0x34/0x48 [kvm] [345523.706095] [c000000399467bb0] [c0080000085c582c] kvm_arch_vcpu_ioctl_run+0x244/0x420 [kvm] [345523.706101] [c000000399467c40] [c0080000085b7498] kvm_vcpu_ioctl+0x3d0/0x7b0 [kvm] [345523.706105] [c000000399467db0] [c0000000004adf9c] ksys_ioctl+0x13c/0x170 [345523.706107] [c000000399467e00] [c0000000004adff8] sys_ioctl+0x28/0x80 [345523.706111] [c000000399467e20] [c00000000000b278] system_call+0x5c/0x68 [345523.706112] Instruction dump: [345523.706114] 419e0390 7f8a4840 409d0048 6d497c00 2f89075d 419e021c 6d497c00 2f8907dd [345523.706119] 419e01c0 6d497c00 2f8905dd 419e00a4 <0fe00000> 38210040 38600000 ebc1fff0 and then treats the executed instruction as a 'nop'. However the POWER9 User's Manual, in section "4.6.10 Book II Invalid Forms", informs that for TM instructions bit 31 is in fact ignored, thus for the TM-related invalid forms ignoring bit 31 and handling them like the valid forms is an acceptable way to handle them. POWER8 behaves the same way too. This commit changes the handling of the cases here described by treating the TM-related invalid forms that can generate a softpatch interrupt just like their valid forms (w/ bit 31 = 1) instead of as a 'nop' and by gently reporting any other unrecognized case to the host and treating it as illegal instruction instead of throwing a trace and treating it as a 'nop'. Signed-off-by: Gustavo Romero <gromero@linux.ibm.com> Reviewed-by: Segher Boessenkool <segher@kernel.crashing.org> Acked-By: Michael Neuling <mikey@neuling.org> Reviewed-by: Leonardo Bras <leonardo@linux.ibm.com> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
157 lines
4.8 KiB
C
157 lines
4.8 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
*
|
|
* Copyright IBM Corp. 2008
|
|
*
|
|
* Authors: Hollis Blanchard <hollisb@us.ibm.com>
|
|
*/
|
|
|
|
#ifndef __POWERPC_KVM_ASM_H__
|
|
#define __POWERPC_KVM_ASM_H__
|
|
|
|
#ifdef __ASSEMBLY__
|
|
#ifdef CONFIG_64BIT
|
|
#define PPC_STD(sreg, offset, areg) std sreg, (offset)(areg)
|
|
#define PPC_LD(treg, offset, areg) ld treg, (offset)(areg)
|
|
#else
|
|
#define PPC_STD(sreg, offset, areg) stw sreg, (offset+4)(areg)
|
|
#define PPC_LD(treg, offset, areg) lwz treg, (offset+4)(areg)
|
|
#endif
|
|
#endif
|
|
|
|
/* IVPR must be 64KiB-aligned. */
|
|
#define VCPU_SIZE_ORDER 4
|
|
#define VCPU_SIZE_LOG (VCPU_SIZE_ORDER + 12)
|
|
#define VCPU_SIZE_BYTES (1<<VCPU_SIZE_LOG)
|
|
|
|
#define BOOKE_INTERRUPT_CRITICAL 0
|
|
#define BOOKE_INTERRUPT_MACHINE_CHECK 1
|
|
#define BOOKE_INTERRUPT_DATA_STORAGE 2
|
|
#define BOOKE_INTERRUPT_INST_STORAGE 3
|
|
#define BOOKE_INTERRUPT_EXTERNAL 4
|
|
#define BOOKE_INTERRUPT_ALIGNMENT 5
|
|
#define BOOKE_INTERRUPT_PROGRAM 6
|
|
#define BOOKE_INTERRUPT_FP_UNAVAIL 7
|
|
#define BOOKE_INTERRUPT_SYSCALL 8
|
|
#define BOOKE_INTERRUPT_AP_UNAVAIL 9
|
|
#define BOOKE_INTERRUPT_DECREMENTER 10
|
|
#define BOOKE_INTERRUPT_FIT 11
|
|
#define BOOKE_INTERRUPT_WATCHDOG 12
|
|
#define BOOKE_INTERRUPT_DTLB_MISS 13
|
|
#define BOOKE_INTERRUPT_ITLB_MISS 14
|
|
#define BOOKE_INTERRUPT_DEBUG 15
|
|
|
|
/* E500 */
|
|
#ifdef CONFIG_SPE_POSSIBLE
|
|
#define BOOKE_INTERRUPT_SPE_UNAVAIL 32
|
|
#define BOOKE_INTERRUPT_SPE_FP_DATA 33
|
|
#define BOOKE_INTERRUPT_SPE_FP_ROUND 34
|
|
#endif
|
|
|
|
#ifdef CONFIG_PPC_E500MC
|
|
#define BOOKE_INTERRUPT_ALTIVEC_UNAVAIL 32
|
|
#define BOOKE_INTERRUPT_ALTIVEC_ASSIST 33
|
|
#endif
|
|
|
|
#define BOOKE_INTERRUPT_PERFORMANCE_MONITOR 35
|
|
#define BOOKE_INTERRUPT_DOORBELL 36
|
|
#define BOOKE_INTERRUPT_DOORBELL_CRITICAL 37
|
|
|
|
/* booke_hv */
|
|
#define BOOKE_INTERRUPT_GUEST_DBELL 38
|
|
#define BOOKE_INTERRUPT_GUEST_DBELL_CRIT 39
|
|
#define BOOKE_INTERRUPT_HV_SYSCALL 40
|
|
#define BOOKE_INTERRUPT_HV_PRIV 41
|
|
#define BOOKE_INTERRUPT_LRAT_ERROR 42
|
|
|
|
/* book3s */
|
|
|
|
#define BOOK3S_INTERRUPT_SYSTEM_RESET 0x100
|
|
#define BOOK3S_INTERRUPT_MACHINE_CHECK 0x200
|
|
#define BOOK3S_INTERRUPT_DATA_STORAGE 0x300
|
|
#define BOOK3S_INTERRUPT_DATA_SEGMENT 0x380
|
|
#define BOOK3S_INTERRUPT_INST_STORAGE 0x400
|
|
#define BOOK3S_INTERRUPT_INST_SEGMENT 0x480
|
|
#define BOOK3S_INTERRUPT_EXTERNAL 0x500
|
|
#define BOOK3S_INTERRUPT_EXTERNAL_HV 0x502
|
|
#define BOOK3S_INTERRUPT_ALIGNMENT 0x600
|
|
#define BOOK3S_INTERRUPT_PROGRAM 0x700
|
|
#define BOOK3S_INTERRUPT_FP_UNAVAIL 0x800
|
|
#define BOOK3S_INTERRUPT_DECREMENTER 0x900
|
|
#define BOOK3S_INTERRUPT_HV_DECREMENTER 0x980
|
|
#define BOOK3S_INTERRUPT_DOORBELL 0xa00
|
|
#define BOOK3S_INTERRUPT_SYSCALL 0xc00
|
|
#define BOOK3S_INTERRUPT_TRACE 0xd00
|
|
#define BOOK3S_INTERRUPT_H_DATA_STORAGE 0xe00
|
|
#define BOOK3S_INTERRUPT_H_INST_STORAGE 0xe20
|
|
#define BOOK3S_INTERRUPT_H_EMUL_ASSIST 0xe40
|
|
#define BOOK3S_INTERRUPT_HMI 0xe60
|
|
#define BOOK3S_INTERRUPT_H_DOORBELL 0xe80
|
|
#define BOOK3S_INTERRUPT_H_VIRT 0xea0
|
|
#define BOOK3S_INTERRUPT_PERFMON 0xf00
|
|
#define BOOK3S_INTERRUPT_ALTIVEC 0xf20
|
|
#define BOOK3S_INTERRUPT_VSX 0xf40
|
|
#define BOOK3S_INTERRUPT_FAC_UNAVAIL 0xf60
|
|
#define BOOK3S_INTERRUPT_H_FAC_UNAVAIL 0xf80
|
|
|
|
/* book3s_hv */
|
|
|
|
#define BOOK3S_INTERRUPT_HV_SOFTPATCH 0x1500
|
|
|
|
/*
|
|
* Special trap used to indicate to host that this is a
|
|
* passthrough interrupt that could not be handled
|
|
* completely in the guest.
|
|
*/
|
|
#define BOOK3S_INTERRUPT_HV_RM_HARD 0x5555
|
|
|
|
#define BOOK3S_IRQPRIO_SYSTEM_RESET 0
|
|
#define BOOK3S_IRQPRIO_DATA_SEGMENT 1
|
|
#define BOOK3S_IRQPRIO_INST_SEGMENT 2
|
|
#define BOOK3S_IRQPRIO_DATA_STORAGE 3
|
|
#define BOOK3S_IRQPRIO_INST_STORAGE 4
|
|
#define BOOK3S_IRQPRIO_ALIGNMENT 5
|
|
#define BOOK3S_IRQPRIO_PROGRAM 6
|
|
#define BOOK3S_IRQPRIO_FP_UNAVAIL 7
|
|
#define BOOK3S_IRQPRIO_ALTIVEC 8
|
|
#define BOOK3S_IRQPRIO_VSX 9
|
|
#define BOOK3S_IRQPRIO_FAC_UNAVAIL 10
|
|
#define BOOK3S_IRQPRIO_SYSCALL 11
|
|
#define BOOK3S_IRQPRIO_MACHINE_CHECK 12
|
|
#define BOOK3S_IRQPRIO_DEBUG 13
|
|
#define BOOK3S_IRQPRIO_EXTERNAL 14
|
|
#define BOOK3S_IRQPRIO_DECREMENTER 15
|
|
#define BOOK3S_IRQPRIO_PERFORMANCE_MONITOR 16
|
|
#define BOOK3S_IRQPRIO_MAX 17
|
|
|
|
#define BOOK3S_HFLAG_DCBZ32 0x1
|
|
#define BOOK3S_HFLAG_SLB 0x2
|
|
#define BOOK3S_HFLAG_PAIRED_SINGLE 0x4
|
|
#define BOOK3S_HFLAG_NATIVE_PS 0x8
|
|
#define BOOK3S_HFLAG_MULTI_PGSIZE 0x10
|
|
#define BOOK3S_HFLAG_NEW_TLBIE 0x20
|
|
#define BOOK3S_HFLAG_SPLIT_HACK 0x40
|
|
|
|
#define RESUME_FLAG_NV (1<<0) /* Reload guest nonvolatile state? */
|
|
#define RESUME_FLAG_HOST (1<<1) /* Resume host? */
|
|
#define RESUME_FLAG_ARCH1 (1<<2)
|
|
#define RESUME_FLAG_ARCH2 (1<<3)
|
|
|
|
#define RESUME_GUEST 0
|
|
#define RESUME_GUEST_NV RESUME_FLAG_NV
|
|
#define RESUME_HOST RESUME_FLAG_HOST
|
|
#define RESUME_HOST_NV (RESUME_FLAG_HOST|RESUME_FLAG_NV)
|
|
|
|
#define KVM_GUEST_MODE_NONE 0
|
|
#define KVM_GUEST_MODE_GUEST 1
|
|
#define KVM_GUEST_MODE_SKIP 2
|
|
#define KVM_GUEST_MODE_GUEST_HV 3
|
|
#define KVM_GUEST_MODE_HOST_HV 4
|
|
|
|
#define KVM_INST_FETCH_FAILED -1
|
|
|
|
/* Extract PO and XOP opcode fields */
|
|
#define PO_XOP_OPCODE_MASK 0xfc0007fe
|
|
|
|
#endif /* __POWERPC_KVM_ASM_H__ */
|