1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright 2017 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com> 4 */ 5 6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7 8 #include <linux/kvm_host.h> 9 10 #include <asm/kvm_ppc.h> 11 #include <asm/kvm_book3s.h> 12 #include <asm/kvm_book3s_64.h> 13 #include <asm/reg.h> 14 #include <asm/ppc-opcode.h> 15 16 static void emulate_tx_failure(struct kvm_vcpu *vcpu, u64 failure_cause) 17 { 18 u64 texasr, tfiar; 19 u64 msr = vcpu->arch.shregs.msr; 20 21 tfiar = vcpu->arch.regs.nip & ~0x3ull; 22 texasr = (failure_cause << 56) | TEXASR_ABORT | TEXASR_FS | TEXASR_EXACT; 23 if (MSR_TM_SUSPENDED(vcpu->arch.shregs.msr)) 24 texasr |= TEXASR_SUSP; 25 if (msr & MSR_PR) { 26 texasr |= TEXASR_PR; 27 tfiar |= 1; 28 } 29 vcpu->arch.tfiar = tfiar; 30 /* Preserve ROT and TL fields of existing TEXASR */ 31 vcpu->arch.texasr = (vcpu->arch.texasr & 0x3ffffff) | texasr; 32 } 33 34 /* 35 * This gets called on a softpatch interrupt on POWER9 DD2.2 processors. 36 * We expect to find a TM-related instruction to be emulated. The 37 * instruction image is in vcpu->arch.emul_inst. If the guest was in 38 * TM suspended or transactional state, the checkpointed state has been 39 * reclaimed and is in the vcpu struct. The CPU is in virtual mode in 40 * host context. 41 */ 42 int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu) 43 { 44 u32 instr = vcpu->arch.emul_inst; 45 u64 msr = vcpu->arch.shregs.msr; 46 u64 newmsr, bescr; 47 int ra, rs; 48 49 /* 50 * rfid, rfebb, and mtmsrd encode bit 31 = 0 since it's a reserved bit 51 * in these instructions, so masking bit 31 out doesn't change these 52 * instructions. For treclaim., tsr., and trechkpt. instructions if bit 53 * 31 = 0 then they are per ISA invalid forms, however P9 UM, in section 54 * 4.6.10 Book II Invalid Forms, informs specifically that ignoring bit 55 * 31 is an acceptable way to handle these invalid forms that have 56 * bit 31 = 0. Moreover, for emulation purposes both forms (w/ and wo/ 57 * bit 31 set) can generate a softpatch interrupt. Hence both forms 58 * are handled below for these instructions so they behave the same way. 59 */ 60 switch (instr & PO_XOP_OPCODE_MASK) { 61 case PPC_INST_RFID: 62 /* XXX do we need to check for PR=0 here? */ 63 newmsr = vcpu->arch.shregs.srr1; 64 /* should only get here for Sx -> T1 transition */ 65 WARN_ON_ONCE(!(MSR_TM_SUSPENDED(msr) && 66 MSR_TM_TRANSACTIONAL(newmsr) && 67 (newmsr & MSR_TM))); 68 newmsr = sanitize_msr(newmsr); 69 vcpu->arch.shregs.msr = newmsr; 70 vcpu->arch.cfar = vcpu->arch.regs.nip - 4; 71 vcpu->arch.regs.nip = vcpu->arch.shregs.srr0; 72 return RESUME_GUEST; 73 74 case PPC_INST_RFEBB: 75 if ((msr & MSR_PR) && (vcpu->arch.vcore->pcr & PCR_ARCH_206)) { 76 /* generate an illegal instruction interrupt */ 77 kvmppc_core_queue_program(vcpu, SRR1_PROGILL); 78 return RESUME_GUEST; 79 } 80 /* check EBB facility is available */ 81 if (!(vcpu->arch.hfscr & HFSCR_EBB)) { 82 /* generate an illegal instruction interrupt */ 83 kvmppc_core_queue_program(vcpu, SRR1_PROGILL); 84 return RESUME_GUEST; 85 } 86 if ((msr & MSR_PR) && !(vcpu->arch.fscr & FSCR_EBB)) { 87 /* generate a facility unavailable interrupt */ 88 vcpu->arch.fscr = (vcpu->arch.fscr & ~(0xffull << 56)) | 89 ((u64)FSCR_EBB_LG << 56); 90 kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_FAC_UNAVAIL); 91 return RESUME_GUEST; 92 } 93 bescr = vcpu->arch.bescr; 94 /* expect to see a S->T transition requested */ 95 WARN_ON_ONCE(!(MSR_TM_SUSPENDED(msr) && 96 ((bescr >> 30) & 3) == 2)); 97 bescr &= ~BESCR_GE; 98 if (instr & (1 << 11)) 99 bescr |= BESCR_GE; 100 vcpu->arch.bescr = bescr; 101 msr = (msr & ~MSR_TS_MASK) | MSR_TS_T; 102 vcpu->arch.shregs.msr = msr; 103 vcpu->arch.cfar = vcpu->arch.regs.nip - 4; 104 vcpu->arch.regs.nip = vcpu->arch.ebbrr; 105 return RESUME_GUEST; 106 107 case PPC_INST_MTMSRD: 108 /* XXX do we need to check for PR=0 here? */ 109 rs = (instr >> 21) & 0x1f; 110 newmsr = kvmppc_get_gpr(vcpu, rs); 111 /* check this is a Sx -> T1 transition */ 112 WARN_ON_ONCE(!(MSR_TM_SUSPENDED(msr) && 113 MSR_TM_TRANSACTIONAL(newmsr) && 114 (newmsr & MSR_TM))); 115 /* mtmsrd doesn't change LE */ 116 newmsr = (newmsr & ~MSR_LE) | (msr & MSR_LE); 117 newmsr = sanitize_msr(newmsr); 118 vcpu->arch.shregs.msr = newmsr; 119 return RESUME_GUEST; 120 121 /* ignore bit 31, see comment above */ 122 case (PPC_INST_TSR & PO_XOP_OPCODE_MASK): 123 /* check for PR=1 and arch 2.06 bit set in PCR */ 124 if ((msr & MSR_PR) && (vcpu->arch.vcore->pcr & PCR_ARCH_206)) { 125 /* generate an illegal instruction interrupt */ 126 kvmppc_core_queue_program(vcpu, SRR1_PROGILL); 127 return RESUME_GUEST; 128 } 129 /* check for TM disabled in the HFSCR or MSR */ 130 if (!(vcpu->arch.hfscr & HFSCR_TM)) { 131 /* generate an illegal instruction interrupt */ 132 kvmppc_core_queue_program(vcpu, SRR1_PROGILL); 133 return RESUME_GUEST; 134 } 135 if (!(msr & MSR_TM)) { 136 /* generate a facility unavailable interrupt */ 137 vcpu->arch.fscr = (vcpu->arch.fscr & ~(0xffull << 56)) | 138 ((u64)FSCR_TM_LG << 56); 139 kvmppc_book3s_queue_irqprio(vcpu, 140 BOOK3S_INTERRUPT_FAC_UNAVAIL); 141 return RESUME_GUEST; 142 } 143 /* Set CR0 to indicate previous transactional state */ 144 vcpu->arch.regs.ccr = (vcpu->arch.regs.ccr & 0x0fffffff) | 145 (((msr & MSR_TS_MASK) >> MSR_TS_S_LG) << 29); 146 /* L=1 => tresume, L=0 => tsuspend */ 147 if (instr & (1 << 21)) { 148 if (MSR_TM_SUSPENDED(msr)) 149 msr = (msr & ~MSR_TS_MASK) | MSR_TS_T; 150 } else { 151 if (MSR_TM_TRANSACTIONAL(msr)) 152 msr = (msr & ~MSR_TS_MASK) | MSR_TS_S; 153 } 154 vcpu->arch.shregs.msr = msr; 155 return RESUME_GUEST; 156 157 /* ignore bit 31, see comment above */ 158 case (PPC_INST_TRECLAIM & PO_XOP_OPCODE_MASK): 159 /* check for TM disabled in the HFSCR or MSR */ 160 if (!(vcpu->arch.hfscr & HFSCR_TM)) { 161 /* generate an illegal instruction interrupt */ 162 kvmppc_core_queue_program(vcpu, SRR1_PROGILL); 163 return RESUME_GUEST; 164 } 165 if (!(msr & MSR_TM)) { 166 /* generate a facility unavailable interrupt */ 167 vcpu->arch.fscr = (vcpu->arch.fscr & ~(0xffull << 56)) | 168 ((u64)FSCR_TM_LG << 56); 169 kvmppc_book3s_queue_irqprio(vcpu, 170 BOOK3S_INTERRUPT_FAC_UNAVAIL); 171 return RESUME_GUEST; 172 } 173 /* If no transaction active, generate TM bad thing */ 174 if (!MSR_TM_ACTIVE(msr)) { 175 kvmppc_core_queue_program(vcpu, SRR1_PROGTM); 176 return RESUME_GUEST; 177 } 178 /* If failure was not previously recorded, recompute TEXASR */ 179 if (!(vcpu->arch.orig_texasr & TEXASR_FS)) { 180 ra = (instr >> 16) & 0x1f; 181 if (ra) 182 ra = kvmppc_get_gpr(vcpu, ra) & 0xff; 183 emulate_tx_failure(vcpu, ra); 184 } 185 186 copy_from_checkpoint(vcpu); 187 188 /* Set CR0 to indicate previous transactional state */ 189 vcpu->arch.regs.ccr = (vcpu->arch.regs.ccr & 0x0fffffff) | 190 (((msr & MSR_TS_MASK) >> MSR_TS_S_LG) << 29); 191 vcpu->arch.shregs.msr &= ~MSR_TS_MASK; 192 return RESUME_GUEST; 193 194 /* ignore bit 31, see comment above */ 195 case (PPC_INST_TRECHKPT & PO_XOP_OPCODE_MASK): 196 /* XXX do we need to check for PR=0 here? */ 197 /* check for TM disabled in the HFSCR or MSR */ 198 if (!(vcpu->arch.hfscr & HFSCR_TM)) { 199 /* generate an illegal instruction interrupt */ 200 kvmppc_core_queue_program(vcpu, SRR1_PROGILL); 201 return RESUME_GUEST; 202 } 203 if (!(msr & MSR_TM)) { 204 /* generate a facility unavailable interrupt */ 205 vcpu->arch.fscr = (vcpu->arch.fscr & ~(0xffull << 56)) | 206 ((u64)FSCR_TM_LG << 56); 207 kvmppc_book3s_queue_irqprio(vcpu, 208 BOOK3S_INTERRUPT_FAC_UNAVAIL); 209 return RESUME_GUEST; 210 } 211 /* If transaction active or TEXASR[FS] = 0, bad thing */ 212 if (MSR_TM_ACTIVE(msr) || !(vcpu->arch.texasr & TEXASR_FS)) { 213 kvmppc_core_queue_program(vcpu, SRR1_PROGTM); 214 return RESUME_GUEST; 215 } 216 217 copy_to_checkpoint(vcpu); 218 219 /* Set CR0 to indicate previous transactional state */ 220 vcpu->arch.regs.ccr = (vcpu->arch.regs.ccr & 0x0fffffff) | 221 (((msr & MSR_TS_MASK) >> MSR_TS_S_LG) << 29); 222 vcpu->arch.shregs.msr = msr | MSR_TS_S; 223 return RESUME_GUEST; 224 } 225 226 /* What should we do here? We didn't recognize the instruction */ 227 kvmppc_core_queue_program(vcpu, SRR1_PROGILL); 228 pr_warn_ratelimited("Unrecognized TM-related instruction %#x for emulation", instr); 229 230 return RESUME_GUEST; 231 } 232