12191d657SAlexander Graf /* 22191d657SAlexander Graf * This program is free software; you can redistribute it and/or modify 32191d657SAlexander Graf * it under the terms of the GNU General Public License, version 2, as 42191d657SAlexander Graf * published by the Free Software Foundation. 52191d657SAlexander Graf * 62191d657SAlexander Graf * This program is distributed in the hope that it will be useful, 72191d657SAlexander Graf * but WITHOUT ANY WARRANTY; without even the implied warranty of 82191d657SAlexander Graf * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 92191d657SAlexander Graf * GNU General Public License for more details. 102191d657SAlexander Graf * 112191d657SAlexander Graf * You should have received a copy of the GNU General Public License 122191d657SAlexander Graf * along with this program; if not, write to the Free Software 132191d657SAlexander Graf * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 142191d657SAlexander Graf * 152191d657SAlexander Graf * Copyright SUSE Linux Products GmbH 2009 162191d657SAlexander Graf * 172191d657SAlexander Graf * Authors: Alexander Graf <agraf@suse.de> 182191d657SAlexander Graf */ 192191d657SAlexander Graf 202191d657SAlexander Graf #include <asm/kvm_ppc.h> 212191d657SAlexander Graf #include <asm/disassemble.h> 222191d657SAlexander Graf #include <asm/kvm_book3s.h> 232191d657SAlexander Graf #include <asm/reg.h> 2495327d08SBenjamin Herrenschmidt #include <asm/switch_to.h> 25b0a94d4eSPaul Mackerras #include <asm/time.h> 265706340aSSimon Guo #include <asm/tm.h> 275358a963SThomas Huth #include "book3s.h" 28533082aeSSimon Guo #include <asm/asm-prototypes.h> 292191d657SAlexander Graf 302191d657SAlexander Graf #define OP_19_XOP_RFID 18 312191d657SAlexander Graf #define OP_19_XOP_RFI 50 322191d657SAlexander Graf 332191d657SAlexander Graf #define OP_31_XOP_MFMSR 83 342191d657SAlexander Graf #define OP_31_XOP_MTMSR 146 352191d657SAlexander Graf #define OP_31_XOP_MTMSRD 178 362191d657SAlexander Graf #define OP_31_XOP_MTSR 210 372191d657SAlexander Graf #define OP_31_XOP_MTSRIN 242 382191d657SAlexander Graf #define OP_31_XOP_TLBIEL 274 392191d657SAlexander Graf #define OP_31_XOP_TLBIE 306 4050c7bb80SAlexander Graf /* Opcode is officially reserved, reuse it as sc 1 when sc 1 doesn't trap */ 4150c7bb80SAlexander Graf #define OP_31_XOP_FAKE_SC1 308 422191d657SAlexander Graf #define OP_31_XOP_SLBMTE 402 432191d657SAlexander Graf #define OP_31_XOP_SLBIE 434 442191d657SAlexander Graf #define OP_31_XOP_SLBIA 498 452191d657SAlexander Graf #define OP_31_XOP_MFSR 595 462191d657SAlexander Graf #define OP_31_XOP_MFSRIN 659 472191d657SAlexander Graf #define OP_31_XOP_DCBA 758 482191d657SAlexander Graf #define OP_31_XOP_SLBMFEV 851 492191d657SAlexander Graf #define OP_31_XOP_EIOIO 854 502191d657SAlexander Graf #define OP_31_XOP_SLBMFEE 915 512191d657SAlexander Graf 525706340aSSimon Guo #define OP_31_XOP_TBEGIN 654 5326798f88SSimon Guo #define OP_31_XOP_TABORT 910 545706340aSSimon Guo 5503c81682SSimon Guo #define OP_31_XOP_TRECLAIM 942 56e32c53d1SSimon Guo #define OP_31_XOP_TRCHKPT 1006 5703c81682SSimon Guo 582191d657SAlexander Graf /* DCBZ is actually 1014, but we patch it to 1010 so we get a trap */ 592191d657SAlexander Graf #define OP_31_XOP_DCBZ 1010 602191d657SAlexander Graf 612191d657SAlexander Graf #define OP_LFS 48 622191d657SAlexander Graf #define OP_LFD 50 632191d657SAlexander Graf #define OP_STFS 52 642191d657SAlexander Graf #define OP_STFD 54 652191d657SAlexander Graf 662191d657SAlexander Graf #define SPRN_GQR0 912 672191d657SAlexander Graf #define SPRN_GQR1 913 682191d657SAlexander Graf #define SPRN_GQR2 914 692191d657SAlexander Graf #define SPRN_GQR3 915 702191d657SAlexander Graf #define SPRN_GQR4 916 712191d657SAlexander Graf #define SPRN_GQR5 917 722191d657SAlexander Graf #define SPRN_GQR6 918 732191d657SAlexander Graf #define SPRN_GQR7 919 742191d657SAlexander Graf 7507b0907dSAlexander Graf /* Book3S_32 defines mfsrin(v) - but that messes up our abstract 7607b0907dSAlexander Graf * function pointers, so let's just disable the define. */ 7707b0907dSAlexander Graf #undef mfsrin 7807b0907dSAlexander Graf 79317a8fa3SAlexander Graf enum priv_level { 80317a8fa3SAlexander Graf PRIV_PROBLEM = 0, 81317a8fa3SAlexander Graf PRIV_SUPER = 1, 82317a8fa3SAlexander Graf PRIV_HYPER = 2, 83317a8fa3SAlexander Graf }; 84317a8fa3SAlexander Graf 85317a8fa3SAlexander Graf static bool spr_allowed(struct kvm_vcpu *vcpu, enum priv_level level) 86317a8fa3SAlexander Graf { 87317a8fa3SAlexander Graf /* PAPR VMs only access supervisor SPRs */ 88317a8fa3SAlexander Graf if (vcpu->arch.papr_enabled && (level > PRIV_SUPER)) 89317a8fa3SAlexander Graf return false; 90317a8fa3SAlexander Graf 91317a8fa3SAlexander Graf /* Limit user space to its own small SPR set */ 925deb8e7aSAlexander Graf if ((kvmppc_get_msr(vcpu) & MSR_PR) && level > PRIV_PROBLEM) 93317a8fa3SAlexander Graf return false; 94317a8fa3SAlexander Graf 95317a8fa3SAlexander Graf return true; 96317a8fa3SAlexander Graf } 97317a8fa3SAlexander Graf 98de7ad932SSimon Guo #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 99de7ad932SSimon Guo static inline void kvmppc_copyto_vcpu_tm(struct kvm_vcpu *vcpu) 100de7ad932SSimon Guo { 101de7ad932SSimon Guo memcpy(&vcpu->arch.gpr_tm[0], &vcpu->arch.regs.gpr[0], 102de7ad932SSimon Guo sizeof(vcpu->arch.gpr_tm)); 103de7ad932SSimon Guo memcpy(&vcpu->arch.fp_tm, &vcpu->arch.fp, 104de7ad932SSimon Guo sizeof(struct thread_fp_state)); 105de7ad932SSimon Guo memcpy(&vcpu->arch.vr_tm, &vcpu->arch.vr, 106de7ad932SSimon Guo sizeof(struct thread_vr_state)); 107de7ad932SSimon Guo vcpu->arch.ppr_tm = vcpu->arch.ppr; 108de7ad932SSimon Guo vcpu->arch.dscr_tm = vcpu->arch.dscr; 109de7ad932SSimon Guo vcpu->arch.amr_tm = vcpu->arch.amr; 110de7ad932SSimon Guo vcpu->arch.ctr_tm = vcpu->arch.regs.ctr; 111de7ad932SSimon Guo vcpu->arch.tar_tm = vcpu->arch.tar; 112de7ad932SSimon Guo vcpu->arch.lr_tm = vcpu->arch.regs.link; 113de7ad932SSimon Guo vcpu->arch.cr_tm = vcpu->arch.cr; 114de7ad932SSimon Guo vcpu->arch.xer_tm = vcpu->arch.regs.xer; 115de7ad932SSimon Guo vcpu->arch.vrsave_tm = vcpu->arch.vrsave; 116de7ad932SSimon Guo } 117de7ad932SSimon Guo 118de7ad932SSimon Guo static inline void kvmppc_copyfrom_vcpu_tm(struct kvm_vcpu *vcpu) 119de7ad932SSimon Guo { 120de7ad932SSimon Guo memcpy(&vcpu->arch.regs.gpr[0], &vcpu->arch.gpr_tm[0], 121de7ad932SSimon Guo sizeof(vcpu->arch.regs.gpr)); 122de7ad932SSimon Guo memcpy(&vcpu->arch.fp, &vcpu->arch.fp_tm, 123de7ad932SSimon Guo sizeof(struct thread_fp_state)); 124de7ad932SSimon Guo memcpy(&vcpu->arch.vr, &vcpu->arch.vr_tm, 125de7ad932SSimon Guo sizeof(struct thread_vr_state)); 126de7ad932SSimon Guo vcpu->arch.ppr = vcpu->arch.ppr_tm; 127de7ad932SSimon Guo vcpu->arch.dscr = vcpu->arch.dscr_tm; 128de7ad932SSimon Guo vcpu->arch.amr = vcpu->arch.amr_tm; 129de7ad932SSimon Guo vcpu->arch.regs.ctr = vcpu->arch.ctr_tm; 130de7ad932SSimon Guo vcpu->arch.tar = vcpu->arch.tar_tm; 131de7ad932SSimon Guo vcpu->arch.regs.link = vcpu->arch.lr_tm; 132de7ad932SSimon Guo vcpu->arch.cr = vcpu->arch.cr_tm; 133de7ad932SSimon Guo vcpu->arch.regs.xer = vcpu->arch.xer_tm; 134de7ad932SSimon Guo vcpu->arch.vrsave = vcpu->arch.vrsave_tm; 135de7ad932SSimon Guo } 136de7ad932SSimon Guo 13703c81682SSimon Guo static void kvmppc_emulate_treclaim(struct kvm_vcpu *vcpu, int ra_val) 13803c81682SSimon Guo { 13903c81682SSimon Guo unsigned long guest_msr = kvmppc_get_msr(vcpu); 14003c81682SSimon Guo int fc_val = ra_val ? ra_val : 1; 141a50623fbSPaul Mackerras uint64_t texasr; 14203c81682SSimon Guo 14303c81682SSimon Guo /* CR0 = 0 | MSR[TS] | 0 */ 14403c81682SSimon Guo vcpu->arch.cr = (vcpu->arch.cr & ~(CR0_MASK << CR0_SHIFT)) | 14503c81682SSimon Guo (((guest_msr & MSR_TS_MASK) >> (MSR_TS_S_LG - 1)) 14603c81682SSimon Guo << CR0_SHIFT); 14703c81682SSimon Guo 14803c81682SSimon Guo preempt_disable(); 149a50623fbSPaul Mackerras tm_enable(); 150a50623fbSPaul Mackerras texasr = mfspr(SPRN_TEXASR); 15103c81682SSimon Guo kvmppc_save_tm_pr(vcpu); 15203c81682SSimon Guo kvmppc_copyfrom_vcpu_tm(vcpu); 15303c81682SSimon Guo 15403c81682SSimon Guo /* failure recording depends on Failure Summary bit */ 155a50623fbSPaul Mackerras if (!(texasr & TEXASR_FS)) { 156a50623fbSPaul Mackerras texasr &= ~TEXASR_FC; 157a50623fbSPaul Mackerras texasr |= ((u64)fc_val << TEXASR_FC_LG) | TEXASR_FS; 15803c81682SSimon Guo 159a50623fbSPaul Mackerras texasr &= ~(TEXASR_PR | TEXASR_HV); 16003c81682SSimon Guo if (kvmppc_get_msr(vcpu) & MSR_PR) 161a50623fbSPaul Mackerras texasr |= TEXASR_PR; 16203c81682SSimon Guo 16303c81682SSimon Guo if (kvmppc_get_msr(vcpu) & MSR_HV) 164a50623fbSPaul Mackerras texasr |= TEXASR_HV; 16503c81682SSimon Guo 166a50623fbSPaul Mackerras vcpu->arch.texasr = texasr; 16703c81682SSimon Guo vcpu->arch.tfiar = kvmppc_get_pc(vcpu); 168a50623fbSPaul Mackerras mtspr(SPRN_TEXASR, texasr); 16903c81682SSimon Guo mtspr(SPRN_TFIAR, vcpu->arch.tfiar); 17003c81682SSimon Guo } 17103c81682SSimon Guo tm_disable(); 17203c81682SSimon Guo /* 17303c81682SSimon Guo * treclaim need quit to non-transactional state. 17403c81682SSimon Guo */ 17503c81682SSimon Guo guest_msr &= ~(MSR_TS_MASK); 17603c81682SSimon Guo kvmppc_set_msr(vcpu, guest_msr); 17703c81682SSimon Guo preempt_enable(); 1787284ca8aSSimon Guo 1797284ca8aSSimon Guo if (vcpu->arch.shadow_fscr & FSCR_TAR) 1807284ca8aSSimon Guo mtspr(SPRN_TAR, vcpu->arch.tar); 18103c81682SSimon Guo } 182e32c53d1SSimon Guo 183e32c53d1SSimon Guo static void kvmppc_emulate_trchkpt(struct kvm_vcpu *vcpu) 184e32c53d1SSimon Guo { 185e32c53d1SSimon Guo unsigned long guest_msr = kvmppc_get_msr(vcpu); 186e32c53d1SSimon Guo 187e32c53d1SSimon Guo preempt_disable(); 188e32c53d1SSimon Guo /* 189e32c53d1SSimon Guo * need flush FP/VEC/VSX to vcpu save area before 190e32c53d1SSimon Guo * copy. 191e32c53d1SSimon Guo */ 192e32c53d1SSimon Guo kvmppc_giveup_ext(vcpu, MSR_VSX); 1937284ca8aSSimon Guo kvmppc_giveup_fac(vcpu, FSCR_TAR_LG); 194e32c53d1SSimon Guo kvmppc_copyto_vcpu_tm(vcpu); 195e32c53d1SSimon Guo kvmppc_save_tm_sprs(vcpu); 196e32c53d1SSimon Guo 197e32c53d1SSimon Guo /* 198e32c53d1SSimon Guo * as a result of trecheckpoint. set TS to suspended. 199e32c53d1SSimon Guo */ 200e32c53d1SSimon Guo guest_msr &= ~(MSR_TS_MASK); 201e32c53d1SSimon Guo guest_msr |= MSR_TS_S; 202e32c53d1SSimon Guo kvmppc_set_msr(vcpu, guest_msr); 203e32c53d1SSimon Guo kvmppc_restore_tm_pr(vcpu); 204e32c53d1SSimon Guo preempt_enable(); 205e32c53d1SSimon Guo } 20626798f88SSimon Guo 20726798f88SSimon Guo /* emulate tabort. at guest privilege state */ 20868ab07b9SSimon Guo void kvmppc_emulate_tabort(struct kvm_vcpu *vcpu, int ra_val) 20926798f88SSimon Guo { 21026798f88SSimon Guo /* currently we only emulate tabort. but no emulation of other 21126798f88SSimon Guo * tabort variants since there is no kernel usage of them at 21226798f88SSimon Guo * present. 21326798f88SSimon Guo */ 21426798f88SSimon Guo unsigned long guest_msr = kvmppc_get_msr(vcpu); 21526798f88SSimon Guo 21626798f88SSimon Guo preempt_disable(); 21726798f88SSimon Guo tm_enable(); 21826798f88SSimon Guo tm_abort(ra_val); 21926798f88SSimon Guo 22026798f88SSimon Guo /* CR0 = 0 | MSR[TS] | 0 */ 22126798f88SSimon Guo vcpu->arch.cr = (vcpu->arch.cr & ~(CR0_MASK << CR0_SHIFT)) | 22226798f88SSimon Guo (((guest_msr & MSR_TS_MASK) >> (MSR_TS_S_LG - 1)) 22326798f88SSimon Guo << CR0_SHIFT); 22426798f88SSimon Guo 22526798f88SSimon Guo vcpu->arch.texasr = mfspr(SPRN_TEXASR); 22626798f88SSimon Guo /* failure recording depends on Failure Summary bit, 22726798f88SSimon Guo * and tabort will be treated as nops in non-transactional 22826798f88SSimon Guo * state. 22926798f88SSimon Guo */ 23026798f88SSimon Guo if (!(vcpu->arch.texasr & TEXASR_FS) && 23126798f88SSimon Guo MSR_TM_ACTIVE(guest_msr)) { 23226798f88SSimon Guo vcpu->arch.texasr &= ~(TEXASR_PR | TEXASR_HV); 23326798f88SSimon Guo if (guest_msr & MSR_PR) 23426798f88SSimon Guo vcpu->arch.texasr |= TEXASR_PR; 23526798f88SSimon Guo 23626798f88SSimon Guo if (guest_msr & MSR_HV) 23726798f88SSimon Guo vcpu->arch.texasr |= TEXASR_HV; 23826798f88SSimon Guo 23926798f88SSimon Guo vcpu->arch.tfiar = kvmppc_get_pc(vcpu); 24026798f88SSimon Guo mtspr(SPRN_TEXASR, vcpu->arch.texasr); 24126798f88SSimon Guo mtspr(SPRN_TFIAR, vcpu->arch.tfiar); 24226798f88SSimon Guo } 24326798f88SSimon Guo tm_disable(); 24426798f88SSimon Guo preempt_enable(); 24526798f88SSimon Guo } 24626798f88SSimon Guo 247de7ad932SSimon Guo #endif 248de7ad932SSimon Guo 2493a167beaSAneesh Kumar K.V int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, 2502191d657SAlexander Graf unsigned int inst, int *advance) 2512191d657SAlexander Graf { 2522191d657SAlexander Graf int emulated = EMULATE_DONE; 253c46dc9a8SAlexander Graf int rt = get_rt(inst); 254c46dc9a8SAlexander Graf int rs = get_rs(inst); 255c46dc9a8SAlexander Graf int ra = get_ra(inst); 256c46dc9a8SAlexander Graf int rb = get_rb(inst); 25742188365SAlexander Graf u32 inst_sc = 0x44000002; 2582191d657SAlexander Graf 2592191d657SAlexander Graf switch (get_op(inst)) { 26042188365SAlexander Graf case 0: 26142188365SAlexander Graf emulated = EMULATE_FAIL; 26242188365SAlexander Graf if ((kvmppc_get_msr(vcpu) & MSR_LE) && 26342188365SAlexander Graf (inst == swab32(inst_sc))) { 26442188365SAlexander Graf /* 26542188365SAlexander Graf * This is the byte reversed syscall instruction of our 26642188365SAlexander Graf * hypercall handler. Early versions of LE Linux didn't 26742188365SAlexander Graf * swap the instructions correctly and ended up in 26842188365SAlexander Graf * illegal instructions. 26942188365SAlexander Graf * Just always fail hypercalls on these broken systems. 27042188365SAlexander Graf */ 27142188365SAlexander Graf kvmppc_set_gpr(vcpu, 3, EV_UNIMPLEMENTED); 27242188365SAlexander Graf kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) + 4); 27342188365SAlexander Graf emulated = EMULATE_DONE; 27442188365SAlexander Graf } 27542188365SAlexander Graf break; 2762191d657SAlexander Graf case 19: 2772191d657SAlexander Graf switch (get_xop(inst)) { 2782191d657SAlexander Graf case OP_19_XOP_RFID: 279401a89e9SSimon Guo case OP_19_XOP_RFI: { 280401a89e9SSimon Guo unsigned long srr1 = kvmppc_get_srr1(vcpu); 281401a89e9SSimon Guo #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 282401a89e9SSimon Guo unsigned long cur_msr = kvmppc_get_msr(vcpu); 283401a89e9SSimon Guo 284401a89e9SSimon Guo /* 285401a89e9SSimon Guo * add rules to fit in ISA specification regarding TM 286401a89e9SSimon Guo * state transistion in TM disable/Suspended state, 287401a89e9SSimon Guo * and target TM state is TM inactive(00) state. (the 288401a89e9SSimon Guo * change should be suppressed). 289401a89e9SSimon Guo */ 290401a89e9SSimon Guo if (((cur_msr & MSR_TM) == 0) && 291401a89e9SSimon Guo ((srr1 & MSR_TM) == 0) && 292401a89e9SSimon Guo MSR_TM_SUSPENDED(cur_msr) && 293401a89e9SSimon Guo !MSR_TM_ACTIVE(srr1)) 294401a89e9SSimon Guo srr1 |= MSR_TS_S; 295401a89e9SSimon Guo #endif 2965deb8e7aSAlexander Graf kvmppc_set_pc(vcpu, kvmppc_get_srr0(vcpu)); 297401a89e9SSimon Guo kvmppc_set_msr(vcpu, srr1); 2982191d657SAlexander Graf *advance = 0; 2992191d657SAlexander Graf break; 300401a89e9SSimon Guo } 3012191d657SAlexander Graf 3022191d657SAlexander Graf default: 3032191d657SAlexander Graf emulated = EMULATE_FAIL; 3042191d657SAlexander Graf break; 3052191d657SAlexander Graf } 3062191d657SAlexander Graf break; 3072191d657SAlexander Graf case 31: 3082191d657SAlexander Graf switch (get_xop(inst)) { 3092191d657SAlexander Graf case OP_31_XOP_MFMSR: 3105deb8e7aSAlexander Graf kvmppc_set_gpr(vcpu, rt, kvmppc_get_msr(vcpu)); 3112191d657SAlexander Graf break; 3122191d657SAlexander Graf case OP_31_XOP_MTMSRD: 3132191d657SAlexander Graf { 314c46dc9a8SAlexander Graf ulong rs_val = kvmppc_get_gpr(vcpu, rs); 3152191d657SAlexander Graf if (inst & 0x10000) { 3165deb8e7aSAlexander Graf ulong new_msr = kvmppc_get_msr(vcpu); 317c46dc9a8SAlexander Graf new_msr &= ~(MSR_RI | MSR_EE); 318c46dc9a8SAlexander Graf new_msr |= rs_val & (MSR_RI | MSR_EE); 3195deb8e7aSAlexander Graf kvmppc_set_msr_fast(vcpu, new_msr); 3202191d657SAlexander Graf } else 321c46dc9a8SAlexander Graf kvmppc_set_msr(vcpu, rs_val); 3222191d657SAlexander Graf break; 3232191d657SAlexander Graf } 3242191d657SAlexander Graf case OP_31_XOP_MTMSR: 325c46dc9a8SAlexander Graf kvmppc_set_msr(vcpu, kvmppc_get_gpr(vcpu, rs)); 3262191d657SAlexander Graf break; 3272191d657SAlexander Graf case OP_31_XOP_MFSR: 3282191d657SAlexander Graf { 3292191d657SAlexander Graf int srnum; 3302191d657SAlexander Graf 3312191d657SAlexander Graf srnum = kvmppc_get_field(inst, 12 + 32, 15 + 32); 3322191d657SAlexander Graf if (vcpu->arch.mmu.mfsrin) { 3332191d657SAlexander Graf u32 sr; 3342191d657SAlexander Graf sr = vcpu->arch.mmu.mfsrin(vcpu, srnum); 335c46dc9a8SAlexander Graf kvmppc_set_gpr(vcpu, rt, sr); 3362191d657SAlexander Graf } 3372191d657SAlexander Graf break; 3382191d657SAlexander Graf } 3392191d657SAlexander Graf case OP_31_XOP_MFSRIN: 3402191d657SAlexander Graf { 3412191d657SAlexander Graf int srnum; 3422191d657SAlexander Graf 343c46dc9a8SAlexander Graf srnum = (kvmppc_get_gpr(vcpu, rb) >> 28) & 0xf; 3442191d657SAlexander Graf if (vcpu->arch.mmu.mfsrin) { 3452191d657SAlexander Graf u32 sr; 3462191d657SAlexander Graf sr = vcpu->arch.mmu.mfsrin(vcpu, srnum); 347c46dc9a8SAlexander Graf kvmppc_set_gpr(vcpu, rt, sr); 3482191d657SAlexander Graf } 3492191d657SAlexander Graf break; 3502191d657SAlexander Graf } 3512191d657SAlexander Graf case OP_31_XOP_MTSR: 3522191d657SAlexander Graf vcpu->arch.mmu.mtsrin(vcpu, 3532191d657SAlexander Graf (inst >> 16) & 0xf, 354c46dc9a8SAlexander Graf kvmppc_get_gpr(vcpu, rs)); 3552191d657SAlexander Graf break; 3562191d657SAlexander Graf case OP_31_XOP_MTSRIN: 3572191d657SAlexander Graf vcpu->arch.mmu.mtsrin(vcpu, 358c46dc9a8SAlexander Graf (kvmppc_get_gpr(vcpu, rb) >> 28) & 0xf, 359c46dc9a8SAlexander Graf kvmppc_get_gpr(vcpu, rs)); 3602191d657SAlexander Graf break; 3612191d657SAlexander Graf case OP_31_XOP_TLBIE: 3622191d657SAlexander Graf case OP_31_XOP_TLBIEL: 3632191d657SAlexander Graf { 3642191d657SAlexander Graf bool large = (inst & 0x00200000) ? true : false; 365c46dc9a8SAlexander Graf ulong addr = kvmppc_get_gpr(vcpu, rb); 3662191d657SAlexander Graf vcpu->arch.mmu.tlbie(vcpu, addr, large); 3672191d657SAlexander Graf break; 3682191d657SAlexander Graf } 3692ba9f0d8SAneesh Kumar K.V #ifdef CONFIG_PPC_BOOK3S_64 37050c7bb80SAlexander Graf case OP_31_XOP_FAKE_SC1: 37150c7bb80SAlexander Graf { 37250c7bb80SAlexander Graf /* SC 1 papr hypercalls */ 37350c7bb80SAlexander Graf ulong cmd = kvmppc_get_gpr(vcpu, 3); 37450c7bb80SAlexander Graf int i; 37550c7bb80SAlexander Graf 3765deb8e7aSAlexander Graf if ((kvmppc_get_msr(vcpu) & MSR_PR) || 37750c7bb80SAlexander Graf !vcpu->arch.papr_enabled) { 37850c7bb80SAlexander Graf emulated = EMULATE_FAIL; 37950c7bb80SAlexander Graf break; 38050c7bb80SAlexander Graf } 38150c7bb80SAlexander Graf 38250c7bb80SAlexander Graf if (kvmppc_h_pr(vcpu, cmd) == EMULATE_DONE) 38350c7bb80SAlexander Graf break; 38450c7bb80SAlexander Graf 38550c7bb80SAlexander Graf run->papr_hcall.nr = cmd; 38650c7bb80SAlexander Graf for (i = 0; i < 9; ++i) { 38750c7bb80SAlexander Graf ulong gpr = kvmppc_get_gpr(vcpu, 4 + i); 38850c7bb80SAlexander Graf run->papr_hcall.args[i] = gpr; 38950c7bb80SAlexander Graf } 39050c7bb80SAlexander Graf 3910f47f9b5SBharat Bhushan run->exit_reason = KVM_EXIT_PAPR_HCALL; 3920f47f9b5SBharat Bhushan vcpu->arch.hcall_needed = 1; 393c402a3f4SBharat Bhushan emulated = EMULATE_EXIT_USER; 39450c7bb80SAlexander Graf break; 39550c7bb80SAlexander Graf } 39650c7bb80SAlexander Graf #endif 3972191d657SAlexander Graf case OP_31_XOP_EIOIO: 3982191d657SAlexander Graf break; 3992191d657SAlexander Graf case OP_31_XOP_SLBMTE: 4002191d657SAlexander Graf if (!vcpu->arch.mmu.slbmte) 4012191d657SAlexander Graf return EMULATE_FAIL; 4022191d657SAlexander Graf 4032191d657SAlexander Graf vcpu->arch.mmu.slbmte(vcpu, 404c46dc9a8SAlexander Graf kvmppc_get_gpr(vcpu, rs), 405c46dc9a8SAlexander Graf kvmppc_get_gpr(vcpu, rb)); 4062191d657SAlexander Graf break; 4072191d657SAlexander Graf case OP_31_XOP_SLBIE: 4082191d657SAlexander Graf if (!vcpu->arch.mmu.slbie) 4092191d657SAlexander Graf return EMULATE_FAIL; 4102191d657SAlexander Graf 4112191d657SAlexander Graf vcpu->arch.mmu.slbie(vcpu, 412c46dc9a8SAlexander Graf kvmppc_get_gpr(vcpu, rb)); 4132191d657SAlexander Graf break; 4142191d657SAlexander Graf case OP_31_XOP_SLBIA: 4152191d657SAlexander Graf if (!vcpu->arch.mmu.slbia) 4162191d657SAlexander Graf return EMULATE_FAIL; 4172191d657SAlexander Graf 4182191d657SAlexander Graf vcpu->arch.mmu.slbia(vcpu); 4192191d657SAlexander Graf break; 4202191d657SAlexander Graf case OP_31_XOP_SLBMFEE: 4212191d657SAlexander Graf if (!vcpu->arch.mmu.slbmfee) { 4222191d657SAlexander Graf emulated = EMULATE_FAIL; 4232191d657SAlexander Graf } else { 424c46dc9a8SAlexander Graf ulong t, rb_val; 4252191d657SAlexander Graf 426c46dc9a8SAlexander Graf rb_val = kvmppc_get_gpr(vcpu, rb); 427c46dc9a8SAlexander Graf t = vcpu->arch.mmu.slbmfee(vcpu, rb_val); 428c46dc9a8SAlexander Graf kvmppc_set_gpr(vcpu, rt, t); 4292191d657SAlexander Graf } 4302191d657SAlexander Graf break; 4312191d657SAlexander Graf case OP_31_XOP_SLBMFEV: 4322191d657SAlexander Graf if (!vcpu->arch.mmu.slbmfev) { 4332191d657SAlexander Graf emulated = EMULATE_FAIL; 4342191d657SAlexander Graf } else { 435c46dc9a8SAlexander Graf ulong t, rb_val; 4362191d657SAlexander Graf 437c46dc9a8SAlexander Graf rb_val = kvmppc_get_gpr(vcpu, rb); 438c46dc9a8SAlexander Graf t = vcpu->arch.mmu.slbmfev(vcpu, rb_val); 439c46dc9a8SAlexander Graf kvmppc_set_gpr(vcpu, rt, t); 4402191d657SAlexander Graf } 4412191d657SAlexander Graf break; 4422191d657SAlexander Graf case OP_31_XOP_DCBA: 4432191d657SAlexander Graf /* Gets treated as NOP */ 4442191d657SAlexander Graf break; 4452191d657SAlexander Graf case OP_31_XOP_DCBZ: 4462191d657SAlexander Graf { 447c46dc9a8SAlexander Graf ulong rb_val = kvmppc_get_gpr(vcpu, rb); 448c46dc9a8SAlexander Graf ulong ra_val = 0; 4492191d657SAlexander Graf ulong addr, vaddr; 4502191d657SAlexander Graf u32 zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 4512191d657SAlexander Graf u32 dsisr; 4522191d657SAlexander Graf int r; 4532191d657SAlexander Graf 454c46dc9a8SAlexander Graf if (ra) 455c46dc9a8SAlexander Graf ra_val = kvmppc_get_gpr(vcpu, ra); 4562191d657SAlexander Graf 457c46dc9a8SAlexander Graf addr = (ra_val + rb_val) & ~31ULL; 4585deb8e7aSAlexander Graf if (!(kvmppc_get_msr(vcpu) & MSR_SF)) 4592191d657SAlexander Graf addr &= 0xffffffff; 4602191d657SAlexander Graf vaddr = addr; 4612191d657SAlexander Graf 4622191d657SAlexander Graf r = kvmppc_st(vcpu, &addr, 32, zeros, true); 4632191d657SAlexander Graf if ((r == -ENOENT) || (r == -EPERM)) { 4642191d657SAlexander Graf *advance = 0; 4655deb8e7aSAlexander Graf kvmppc_set_dar(vcpu, vaddr); 466a2d56020SPaul Mackerras vcpu->arch.fault_dar = vaddr; 4672191d657SAlexander Graf 4682191d657SAlexander Graf dsisr = DSISR_ISSTORE; 4692191d657SAlexander Graf if (r == -ENOENT) 4702191d657SAlexander Graf dsisr |= DSISR_NOHPTE; 4712191d657SAlexander Graf else if (r == -EPERM) 4722191d657SAlexander Graf dsisr |= DSISR_PROTFAULT; 4732191d657SAlexander Graf 4745deb8e7aSAlexander Graf kvmppc_set_dsisr(vcpu, dsisr); 475a2d56020SPaul Mackerras vcpu->arch.fault_dsisr = dsisr; 4762191d657SAlexander Graf 4772191d657SAlexander Graf kvmppc_book3s_queue_irqprio(vcpu, 4782191d657SAlexander Graf BOOK3S_INTERRUPT_DATA_STORAGE); 4792191d657SAlexander Graf } 4802191d657SAlexander Graf 4812191d657SAlexander Graf break; 4822191d657SAlexander Graf } 4835706340aSSimon Guo #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 4845706340aSSimon Guo case OP_31_XOP_TBEGIN: 4855706340aSSimon Guo { 4865706340aSSimon Guo if (!cpu_has_feature(CPU_FTR_TM)) 4875706340aSSimon Guo break; 4885706340aSSimon Guo 4895706340aSSimon Guo if (!(kvmppc_get_msr(vcpu) & MSR_TM)) { 4905706340aSSimon Guo kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG); 4915706340aSSimon Guo emulated = EMULATE_AGAIN; 4925706340aSSimon Guo break; 4935706340aSSimon Guo } 4945706340aSSimon Guo 4955706340aSSimon Guo if (!(kvmppc_get_msr(vcpu) & MSR_PR)) { 4965706340aSSimon Guo preempt_disable(); 4975706340aSSimon Guo vcpu->arch.cr = (CR0_TBEGIN_FAILURE | 4985706340aSSimon Guo (vcpu->arch.cr & ~(CR0_MASK << CR0_SHIFT))); 4995706340aSSimon Guo 5005706340aSSimon Guo vcpu->arch.texasr = (TEXASR_FS | TEXASR_EXACT | 5015706340aSSimon Guo (((u64)(TM_CAUSE_EMULATE | TM_CAUSE_PERSISTENT)) 5025706340aSSimon Guo << TEXASR_FC_LG)); 5035706340aSSimon Guo 5045706340aSSimon Guo if ((inst >> 21) & 0x1) 5055706340aSSimon Guo vcpu->arch.texasr |= TEXASR_ROT; 5065706340aSSimon Guo 5075706340aSSimon Guo if (kvmppc_get_msr(vcpu) & MSR_HV) 5085706340aSSimon Guo vcpu->arch.texasr |= TEXASR_HV; 5095706340aSSimon Guo 5105706340aSSimon Guo vcpu->arch.tfhar = kvmppc_get_pc(vcpu) + 4; 5115706340aSSimon Guo vcpu->arch.tfiar = kvmppc_get_pc(vcpu); 5125706340aSSimon Guo 5135706340aSSimon Guo kvmppc_restore_tm_sprs(vcpu); 5145706340aSSimon Guo preempt_enable(); 5155706340aSSimon Guo } else 5165706340aSSimon Guo emulated = EMULATE_FAIL; 5175706340aSSimon Guo break; 5185706340aSSimon Guo } 51926798f88SSimon Guo case OP_31_XOP_TABORT: 52026798f88SSimon Guo { 52126798f88SSimon Guo ulong guest_msr = kvmppc_get_msr(vcpu); 52226798f88SSimon Guo unsigned long ra_val = 0; 52326798f88SSimon Guo 52426798f88SSimon Guo if (!cpu_has_feature(CPU_FTR_TM)) 52526798f88SSimon Guo break; 52626798f88SSimon Guo 52726798f88SSimon Guo if (!(kvmppc_get_msr(vcpu) & MSR_TM)) { 52826798f88SSimon Guo kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG); 52926798f88SSimon Guo emulated = EMULATE_AGAIN; 53026798f88SSimon Guo break; 53126798f88SSimon Guo } 53226798f88SSimon Guo 53326798f88SSimon Guo /* only emulate for privilege guest, since problem state 53426798f88SSimon Guo * guest can run with TM enabled and we don't expect to 53526798f88SSimon Guo * trap at here for that case. 53626798f88SSimon Guo */ 53726798f88SSimon Guo WARN_ON(guest_msr & MSR_PR); 53826798f88SSimon Guo 53926798f88SSimon Guo if (ra) 54026798f88SSimon Guo ra_val = kvmppc_get_gpr(vcpu, ra); 54126798f88SSimon Guo 54226798f88SSimon Guo kvmppc_emulate_tabort(vcpu, ra_val); 54326798f88SSimon Guo break; 54426798f88SSimon Guo } 54503c81682SSimon Guo case OP_31_XOP_TRECLAIM: 54603c81682SSimon Guo { 54703c81682SSimon Guo ulong guest_msr = kvmppc_get_msr(vcpu); 54803c81682SSimon Guo unsigned long ra_val = 0; 54903c81682SSimon Guo 55003c81682SSimon Guo if (!cpu_has_feature(CPU_FTR_TM)) 55103c81682SSimon Guo break; 55203c81682SSimon Guo 55303c81682SSimon Guo if (!(kvmppc_get_msr(vcpu) & MSR_TM)) { 55403c81682SSimon Guo kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG); 55503c81682SSimon Guo emulated = EMULATE_AGAIN; 55603c81682SSimon Guo break; 55703c81682SSimon Guo } 55803c81682SSimon Guo 55903c81682SSimon Guo /* generate interrupts based on priorities */ 56003c81682SSimon Guo if (guest_msr & MSR_PR) { 56103c81682SSimon Guo /* Privileged Instruction type Program Interrupt */ 56203c81682SSimon Guo kvmppc_core_queue_program(vcpu, SRR1_PROGPRIV); 56303c81682SSimon Guo emulated = EMULATE_AGAIN; 56403c81682SSimon Guo break; 56503c81682SSimon Guo } 56603c81682SSimon Guo 56703c81682SSimon Guo if (!MSR_TM_ACTIVE(guest_msr)) { 56803c81682SSimon Guo /* TM bad thing interrupt */ 56903c81682SSimon Guo kvmppc_core_queue_program(vcpu, SRR1_PROGTM); 57003c81682SSimon Guo emulated = EMULATE_AGAIN; 57103c81682SSimon Guo break; 57203c81682SSimon Guo } 57303c81682SSimon Guo 57403c81682SSimon Guo if (ra) 57503c81682SSimon Guo ra_val = kvmppc_get_gpr(vcpu, ra); 57603c81682SSimon Guo kvmppc_emulate_treclaim(vcpu, ra_val); 57703c81682SSimon Guo break; 57803c81682SSimon Guo } 579e32c53d1SSimon Guo case OP_31_XOP_TRCHKPT: 580e32c53d1SSimon Guo { 581e32c53d1SSimon Guo ulong guest_msr = kvmppc_get_msr(vcpu); 582e32c53d1SSimon Guo unsigned long texasr; 583e32c53d1SSimon Guo 584e32c53d1SSimon Guo if (!cpu_has_feature(CPU_FTR_TM)) 585e32c53d1SSimon Guo break; 586e32c53d1SSimon Guo 587e32c53d1SSimon Guo if (!(kvmppc_get_msr(vcpu) & MSR_TM)) { 588e32c53d1SSimon Guo kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG); 589e32c53d1SSimon Guo emulated = EMULATE_AGAIN; 590e32c53d1SSimon Guo break; 591e32c53d1SSimon Guo } 592e32c53d1SSimon Guo 593e32c53d1SSimon Guo /* generate interrupt based on priorities */ 594e32c53d1SSimon Guo if (guest_msr & MSR_PR) { 595e32c53d1SSimon Guo /* Privileged Instruction type Program Intr */ 596e32c53d1SSimon Guo kvmppc_core_queue_program(vcpu, SRR1_PROGPRIV); 597e32c53d1SSimon Guo emulated = EMULATE_AGAIN; 598e32c53d1SSimon Guo break; 599e32c53d1SSimon Guo } 600e32c53d1SSimon Guo 601e32c53d1SSimon Guo tm_enable(); 602e32c53d1SSimon Guo texasr = mfspr(SPRN_TEXASR); 603e32c53d1SSimon Guo tm_disable(); 604e32c53d1SSimon Guo 605e32c53d1SSimon Guo if (MSR_TM_ACTIVE(guest_msr) || 606e32c53d1SSimon Guo !(texasr & (TEXASR_FS))) { 607e32c53d1SSimon Guo /* TM bad thing interrupt */ 608e32c53d1SSimon Guo kvmppc_core_queue_program(vcpu, SRR1_PROGTM); 609e32c53d1SSimon Guo emulated = EMULATE_AGAIN; 610e32c53d1SSimon Guo break; 611e32c53d1SSimon Guo } 612e32c53d1SSimon Guo 613e32c53d1SSimon Guo kvmppc_emulate_trchkpt(vcpu); 614e32c53d1SSimon Guo break; 615e32c53d1SSimon Guo } 6165706340aSSimon Guo #endif 6172191d657SAlexander Graf default: 6182191d657SAlexander Graf emulated = EMULATE_FAIL; 6192191d657SAlexander Graf } 6202191d657SAlexander Graf break; 6212191d657SAlexander Graf default: 6222191d657SAlexander Graf emulated = EMULATE_FAIL; 6232191d657SAlexander Graf } 6242191d657SAlexander Graf 6252191d657SAlexander Graf if (emulated == EMULATE_FAIL) 6262191d657SAlexander Graf emulated = kvmppc_emulate_paired_single(run, vcpu); 6272191d657SAlexander Graf 6282191d657SAlexander Graf return emulated; 6292191d657SAlexander Graf } 6302191d657SAlexander Graf 6312191d657SAlexander Graf void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, bool upper, 6322191d657SAlexander Graf u32 val) 6332191d657SAlexander Graf { 6342191d657SAlexander Graf if (upper) { 6352191d657SAlexander Graf /* Upper BAT */ 6362191d657SAlexander Graf u32 bl = (val >> 2) & 0x7ff; 6372191d657SAlexander Graf bat->bepi_mask = (~bl << 17); 6382191d657SAlexander Graf bat->bepi = val & 0xfffe0000; 6392191d657SAlexander Graf bat->vs = (val & 2) ? 1 : 0; 6402191d657SAlexander Graf bat->vp = (val & 1) ? 1 : 0; 6412191d657SAlexander Graf bat->raw = (bat->raw & 0xffffffff00000000ULL) | val; 6422191d657SAlexander Graf } else { 6432191d657SAlexander Graf /* Lower BAT */ 6442191d657SAlexander Graf bat->brpn = val & 0xfffe0000; 6452191d657SAlexander Graf bat->wimg = (val >> 3) & 0xf; 6462191d657SAlexander Graf bat->pp = val & 3; 6472191d657SAlexander Graf bat->raw = (bat->raw & 0x00000000ffffffffULL) | ((u64)val << 32); 6482191d657SAlexander Graf } 6492191d657SAlexander Graf } 6502191d657SAlexander Graf 651c1c88e2fSAlexander Graf static struct kvmppc_bat *kvmppc_find_bat(struct kvm_vcpu *vcpu, int sprn) 6522191d657SAlexander Graf { 6532191d657SAlexander Graf struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); 6542191d657SAlexander Graf struct kvmppc_bat *bat; 6552191d657SAlexander Graf 6562191d657SAlexander Graf switch (sprn) { 6572191d657SAlexander Graf case SPRN_IBAT0U ... SPRN_IBAT3L: 6582191d657SAlexander Graf bat = &vcpu_book3s->ibat[(sprn - SPRN_IBAT0U) / 2]; 6592191d657SAlexander Graf break; 6602191d657SAlexander Graf case SPRN_IBAT4U ... SPRN_IBAT7L: 6612191d657SAlexander Graf bat = &vcpu_book3s->ibat[4 + ((sprn - SPRN_IBAT4U) / 2)]; 6622191d657SAlexander Graf break; 6632191d657SAlexander Graf case SPRN_DBAT0U ... SPRN_DBAT3L: 6642191d657SAlexander Graf bat = &vcpu_book3s->dbat[(sprn - SPRN_DBAT0U) / 2]; 6652191d657SAlexander Graf break; 6662191d657SAlexander Graf case SPRN_DBAT4U ... SPRN_DBAT7L: 6672191d657SAlexander Graf bat = &vcpu_book3s->dbat[4 + ((sprn - SPRN_DBAT4U) / 2)]; 6682191d657SAlexander Graf break; 6692191d657SAlexander Graf default: 6702191d657SAlexander Graf BUG(); 6712191d657SAlexander Graf } 6722191d657SAlexander Graf 673c1c88e2fSAlexander Graf return bat; 6742191d657SAlexander Graf } 6752191d657SAlexander Graf 6763a167beaSAneesh Kumar K.V int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) 6772191d657SAlexander Graf { 6782191d657SAlexander Graf int emulated = EMULATE_DONE; 6792191d657SAlexander Graf 6802191d657SAlexander Graf switch (sprn) { 6812191d657SAlexander Graf case SPRN_SDR1: 682317a8fa3SAlexander Graf if (!spr_allowed(vcpu, PRIV_HYPER)) 683317a8fa3SAlexander Graf goto unprivileged; 6842191d657SAlexander Graf to_book3s(vcpu)->sdr1 = spr_val; 6852191d657SAlexander Graf break; 6862191d657SAlexander Graf case SPRN_DSISR: 6875deb8e7aSAlexander Graf kvmppc_set_dsisr(vcpu, spr_val); 6882191d657SAlexander Graf break; 6892191d657SAlexander Graf case SPRN_DAR: 6905deb8e7aSAlexander Graf kvmppc_set_dar(vcpu, spr_val); 6912191d657SAlexander Graf break; 6922191d657SAlexander Graf case SPRN_HIOR: 6932191d657SAlexander Graf to_book3s(vcpu)->hior = spr_val; 6942191d657SAlexander Graf break; 6952191d657SAlexander Graf case SPRN_IBAT0U ... SPRN_IBAT3L: 6962191d657SAlexander Graf case SPRN_IBAT4U ... SPRN_IBAT7L: 6972191d657SAlexander Graf case SPRN_DBAT0U ... SPRN_DBAT3L: 6982191d657SAlexander Graf case SPRN_DBAT4U ... SPRN_DBAT7L: 699c1c88e2fSAlexander Graf { 700c1c88e2fSAlexander Graf struct kvmppc_bat *bat = kvmppc_find_bat(vcpu, sprn); 701c1c88e2fSAlexander Graf 702c1c88e2fSAlexander Graf kvmppc_set_bat(vcpu, bat, !(sprn % 2), (u32)spr_val); 7032191d657SAlexander Graf /* BAT writes happen so rarely that we're ok to flush 7042191d657SAlexander Graf * everything here */ 7052191d657SAlexander Graf kvmppc_mmu_pte_flush(vcpu, 0, 0); 7062191d657SAlexander Graf kvmppc_mmu_flush_segments(vcpu); 7072191d657SAlexander Graf break; 708c1c88e2fSAlexander Graf } 7092191d657SAlexander Graf case SPRN_HID0: 7102191d657SAlexander Graf to_book3s(vcpu)->hid[0] = spr_val; 7112191d657SAlexander Graf break; 7122191d657SAlexander Graf case SPRN_HID1: 7132191d657SAlexander Graf to_book3s(vcpu)->hid[1] = spr_val; 7142191d657SAlexander Graf break; 7152191d657SAlexander Graf case SPRN_HID2: 7162191d657SAlexander Graf to_book3s(vcpu)->hid[2] = spr_val; 7172191d657SAlexander Graf break; 7182191d657SAlexander Graf case SPRN_HID2_GEKKO: 7192191d657SAlexander Graf to_book3s(vcpu)->hid[2] = spr_val; 7202191d657SAlexander Graf /* HID2.PSE controls paired single on gekko */ 7212191d657SAlexander Graf switch (vcpu->arch.pvr) { 7222191d657SAlexander Graf case 0x00080200: /* lonestar 2.0 */ 7232191d657SAlexander Graf case 0x00088202: /* lonestar 2.2 */ 7242191d657SAlexander Graf case 0x70000100: /* gekko 1.0 */ 7252191d657SAlexander Graf case 0x00080100: /* gekko 2.0 */ 7262191d657SAlexander Graf case 0x00083203: /* gekko 2.3a */ 7272191d657SAlexander Graf case 0x00083213: /* gekko 2.3b */ 7282191d657SAlexander Graf case 0x00083204: /* gekko 2.4 */ 7292191d657SAlexander Graf case 0x00083214: /* gekko 2.4e (8SE) - retail HW2 */ 730b83d4a9cSAlexander Graf case 0x00087200: /* broadway */ 731b83d4a9cSAlexander Graf if (vcpu->arch.hflags & BOOK3S_HFLAG_NATIVE_PS) { 732b83d4a9cSAlexander Graf /* Native paired singles */ 733b83d4a9cSAlexander Graf } else if (spr_val & (1 << 29)) { /* HID2.PSE */ 7342191d657SAlexander Graf vcpu->arch.hflags |= BOOK3S_HFLAG_PAIRED_SINGLE; 7352191d657SAlexander Graf kvmppc_giveup_ext(vcpu, MSR_FP); 7362191d657SAlexander Graf } else { 7372191d657SAlexander Graf vcpu->arch.hflags &= ~BOOK3S_HFLAG_PAIRED_SINGLE; 7382191d657SAlexander Graf } 7392191d657SAlexander Graf break; 7402191d657SAlexander Graf } 7412191d657SAlexander Graf break; 7422191d657SAlexander Graf case SPRN_HID4: 7432191d657SAlexander Graf case SPRN_HID4_GEKKO: 7442191d657SAlexander Graf to_book3s(vcpu)->hid[4] = spr_val; 7452191d657SAlexander Graf break; 7462191d657SAlexander Graf case SPRN_HID5: 7472191d657SAlexander Graf to_book3s(vcpu)->hid[5] = spr_val; 7482191d657SAlexander Graf /* guest HID5 set can change is_dcbz32 */ 7492191d657SAlexander Graf if (vcpu->arch.mmu.is_dcbz32(vcpu) && 7502191d657SAlexander Graf (mfmsr() & MSR_HV)) 7512191d657SAlexander Graf vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32; 7522191d657SAlexander Graf break; 7532191d657SAlexander Graf case SPRN_GQR0: 7542191d657SAlexander Graf case SPRN_GQR1: 7552191d657SAlexander Graf case SPRN_GQR2: 7562191d657SAlexander Graf case SPRN_GQR3: 7572191d657SAlexander Graf case SPRN_GQR4: 7582191d657SAlexander Graf case SPRN_GQR5: 7592191d657SAlexander Graf case SPRN_GQR6: 7602191d657SAlexander Graf case SPRN_GQR7: 7612191d657SAlexander Graf to_book3s(vcpu)->gqr[sprn - SPRN_GQR0] = spr_val; 7622191d657SAlexander Graf break; 7632e23f544SAlexander Graf #ifdef CONFIG_PPC_BOOK3S_64 7648e6afa36SAlexander Graf case SPRN_FSCR: 7658e6afa36SAlexander Graf kvmppc_set_fscr(vcpu, spr_val); 7668e6afa36SAlexander Graf break; 7672e23f544SAlexander Graf case SPRN_BESCR: 7682e23f544SAlexander Graf vcpu->arch.bescr = spr_val; 7692e23f544SAlexander Graf break; 7702e23f544SAlexander Graf case SPRN_EBBHR: 7712e23f544SAlexander Graf vcpu->arch.ebbhr = spr_val; 7722e23f544SAlexander Graf break; 7732e23f544SAlexander Graf case SPRN_EBBRR: 7742e23f544SAlexander Graf vcpu->arch.ebbrr = spr_val; 7752e23f544SAlexander Graf break; 7769916d57eSAlexander Graf #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 7779916d57eSAlexander Graf case SPRN_TFHAR: 7789916d57eSAlexander Graf case SPRN_TEXASR: 7799916d57eSAlexander Graf case SPRN_TFIAR: 780533082aeSSimon Guo if (!cpu_has_feature(CPU_FTR_TM)) 781533082aeSSimon Guo break; 782533082aeSSimon Guo 783533082aeSSimon Guo if (!(kvmppc_get_msr(vcpu) & MSR_TM)) { 784533082aeSSimon Guo kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG); 785533082aeSSimon Guo emulated = EMULATE_AGAIN; 786533082aeSSimon Guo break; 787533082aeSSimon Guo } 788533082aeSSimon Guo 789533082aeSSimon Guo if (MSR_TM_ACTIVE(kvmppc_get_msr(vcpu)) && 790533082aeSSimon Guo !((MSR_TM_SUSPENDED(kvmppc_get_msr(vcpu))) && 791533082aeSSimon Guo (sprn == SPRN_TFHAR))) { 792533082aeSSimon Guo /* it is illegal to mtspr() TM regs in 793533082aeSSimon Guo * other than non-transactional state, with 794533082aeSSimon Guo * the exception of TFHAR in suspend state. 795533082aeSSimon Guo */ 796533082aeSSimon Guo kvmppc_core_queue_program(vcpu, SRR1_PROGTM); 797533082aeSSimon Guo emulated = EMULATE_AGAIN; 798533082aeSSimon Guo break; 799533082aeSSimon Guo } 800533082aeSSimon Guo 801533082aeSSimon Guo tm_enable(); 802533082aeSSimon Guo if (sprn == SPRN_TFHAR) 803533082aeSSimon Guo mtspr(SPRN_TFHAR, spr_val); 804533082aeSSimon Guo else if (sprn == SPRN_TEXASR) 805533082aeSSimon Guo mtspr(SPRN_TEXASR, spr_val); 806533082aeSSimon Guo else 807533082aeSSimon Guo mtspr(SPRN_TFIAR, spr_val); 808533082aeSSimon Guo tm_disable(); 809533082aeSSimon Guo 8109916d57eSAlexander Graf break; 8119916d57eSAlexander Graf #endif 8122e23f544SAlexander Graf #endif 8132191d657SAlexander Graf case SPRN_ICTC: 8142191d657SAlexander Graf case SPRN_THRM1: 8152191d657SAlexander Graf case SPRN_THRM2: 8162191d657SAlexander Graf case SPRN_THRM3: 8172191d657SAlexander Graf case SPRN_CTRLF: 8182191d657SAlexander Graf case SPRN_CTRLT: 8192191d657SAlexander Graf case SPRN_L2CR: 820b0a94d4eSPaul Mackerras case SPRN_DSCR: 8212191d657SAlexander Graf case SPRN_MMCR0_GEKKO: 8222191d657SAlexander Graf case SPRN_MMCR1_GEKKO: 8232191d657SAlexander Graf case SPRN_PMC1_GEKKO: 8242191d657SAlexander Graf case SPRN_PMC2_GEKKO: 8252191d657SAlexander Graf case SPRN_PMC3_GEKKO: 8262191d657SAlexander Graf case SPRN_PMC4_GEKKO: 8272191d657SAlexander Graf case SPRN_WPAR_GEKKO: 828f2be6550SMihai Caraman case SPRN_MSSSR0: 829f3532028SAlexander Graf case SPRN_DABR: 830f8f6eb0dSAlexander Graf #ifdef CONFIG_PPC_BOOK3S_64 831f8f6eb0dSAlexander Graf case SPRN_MMCRS: 832f8f6eb0dSAlexander Graf case SPRN_MMCRA: 833f8f6eb0dSAlexander Graf case SPRN_MMCR0: 834f8f6eb0dSAlexander Graf case SPRN_MMCR1: 835f8f6eb0dSAlexander Graf case SPRN_MMCR2: 836fa73c3b2SThomas Huth case SPRN_UMMCR2: 837f8f6eb0dSAlexander Graf #endif 8382191d657SAlexander Graf break; 839317a8fa3SAlexander Graf unprivileged: 8402191d657SAlexander Graf default: 841feafd13cSThomas Huth pr_info_ratelimited("KVM: invalid SPR write: %d\n", sprn); 842feafd13cSThomas Huth if (sprn & 0x10) { 843feafd13cSThomas Huth if (kvmppc_get_msr(vcpu) & MSR_PR) { 844feafd13cSThomas Huth kvmppc_core_queue_program(vcpu, SRR1_PROGPRIV); 845feafd13cSThomas Huth emulated = EMULATE_AGAIN; 846feafd13cSThomas Huth } 847feafd13cSThomas Huth } else { 848feafd13cSThomas Huth if ((kvmppc_get_msr(vcpu) & MSR_PR) || sprn == 0) { 849feafd13cSThomas Huth kvmppc_core_queue_program(vcpu, SRR1_PROGILL); 850feafd13cSThomas Huth emulated = EMULATE_AGAIN; 851feafd13cSThomas Huth } 852feafd13cSThomas Huth } 8532191d657SAlexander Graf break; 8542191d657SAlexander Graf } 8552191d657SAlexander Graf 8562191d657SAlexander Graf return emulated; 8572191d657SAlexander Graf } 8582191d657SAlexander Graf 8593a167beaSAneesh Kumar K.V int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val) 8602191d657SAlexander Graf { 8612191d657SAlexander Graf int emulated = EMULATE_DONE; 8622191d657SAlexander Graf 8632191d657SAlexander Graf switch (sprn) { 8642191d657SAlexander Graf case SPRN_IBAT0U ... SPRN_IBAT3L: 8652191d657SAlexander Graf case SPRN_IBAT4U ... SPRN_IBAT7L: 8662191d657SAlexander Graf case SPRN_DBAT0U ... SPRN_DBAT3L: 8672191d657SAlexander Graf case SPRN_DBAT4U ... SPRN_DBAT7L: 868c1c88e2fSAlexander Graf { 869c1c88e2fSAlexander Graf struct kvmppc_bat *bat = kvmppc_find_bat(vcpu, sprn); 870c1c88e2fSAlexander Graf 871c1c88e2fSAlexander Graf if (sprn % 2) 87254771e62SAlexander Graf *spr_val = bat->raw >> 32; 873c1c88e2fSAlexander Graf else 87454771e62SAlexander Graf *spr_val = bat->raw; 875c1c88e2fSAlexander Graf 8762191d657SAlexander Graf break; 877c1c88e2fSAlexander Graf } 8782191d657SAlexander Graf case SPRN_SDR1: 879317a8fa3SAlexander Graf if (!spr_allowed(vcpu, PRIV_HYPER)) 880317a8fa3SAlexander Graf goto unprivileged; 88154771e62SAlexander Graf *spr_val = to_book3s(vcpu)->sdr1; 8822191d657SAlexander Graf break; 8832191d657SAlexander Graf case SPRN_DSISR: 8845deb8e7aSAlexander Graf *spr_val = kvmppc_get_dsisr(vcpu); 8852191d657SAlexander Graf break; 8862191d657SAlexander Graf case SPRN_DAR: 8875deb8e7aSAlexander Graf *spr_val = kvmppc_get_dar(vcpu); 8882191d657SAlexander Graf break; 8892191d657SAlexander Graf case SPRN_HIOR: 89054771e62SAlexander Graf *spr_val = to_book3s(vcpu)->hior; 8912191d657SAlexander Graf break; 8922191d657SAlexander Graf case SPRN_HID0: 89354771e62SAlexander Graf *spr_val = to_book3s(vcpu)->hid[0]; 8942191d657SAlexander Graf break; 8952191d657SAlexander Graf case SPRN_HID1: 89654771e62SAlexander Graf *spr_val = to_book3s(vcpu)->hid[1]; 8972191d657SAlexander Graf break; 8982191d657SAlexander Graf case SPRN_HID2: 8992191d657SAlexander Graf case SPRN_HID2_GEKKO: 90054771e62SAlexander Graf *spr_val = to_book3s(vcpu)->hid[2]; 9012191d657SAlexander Graf break; 9022191d657SAlexander Graf case SPRN_HID4: 9032191d657SAlexander Graf case SPRN_HID4_GEKKO: 90454771e62SAlexander Graf *spr_val = to_book3s(vcpu)->hid[4]; 9052191d657SAlexander Graf break; 9062191d657SAlexander Graf case SPRN_HID5: 90754771e62SAlexander Graf *spr_val = to_book3s(vcpu)->hid[5]; 9082191d657SAlexander Graf break; 909aacf9aa3SAlexander Graf case SPRN_CFAR: 910b0a94d4eSPaul Mackerras case SPRN_DSCR: 91154771e62SAlexander Graf *spr_val = 0; 912aacf9aa3SAlexander Graf break; 913b0a94d4eSPaul Mackerras case SPRN_PURR: 9143cd60e31SAneesh Kumar K.V /* 9153cd60e31SAneesh Kumar K.V * On exit we would have updated purr 9163cd60e31SAneesh Kumar K.V */ 9173cd60e31SAneesh Kumar K.V *spr_val = vcpu->arch.purr; 918b0a94d4eSPaul Mackerras break; 919b0a94d4eSPaul Mackerras case SPRN_SPURR: 9203cd60e31SAneesh Kumar K.V /* 9213cd60e31SAneesh Kumar K.V * On exit we would have updated spurr 9223cd60e31SAneesh Kumar K.V */ 9233cd60e31SAneesh Kumar K.V *spr_val = vcpu->arch.spurr; 924b0a94d4eSPaul Mackerras break; 9258f42ab27SAneesh Kumar K.V case SPRN_VTB: 92688b02cf9SPaul Mackerras *spr_val = to_book3s(vcpu)->vtb; 9278f42ab27SAneesh Kumar K.V break; 92806da28e7SAneesh Kumar K.V case SPRN_IC: 92906da28e7SAneesh Kumar K.V *spr_val = vcpu->arch.ic; 93006da28e7SAneesh Kumar K.V break; 9312191d657SAlexander Graf case SPRN_GQR0: 9322191d657SAlexander Graf case SPRN_GQR1: 9332191d657SAlexander Graf case SPRN_GQR2: 9342191d657SAlexander Graf case SPRN_GQR3: 9352191d657SAlexander Graf case SPRN_GQR4: 9362191d657SAlexander Graf case SPRN_GQR5: 9372191d657SAlexander Graf case SPRN_GQR6: 9382191d657SAlexander Graf case SPRN_GQR7: 93954771e62SAlexander Graf *spr_val = to_book3s(vcpu)->gqr[sprn - SPRN_GQR0]; 9402191d657SAlexander Graf break; 9418e6afa36SAlexander Graf #ifdef CONFIG_PPC_BOOK3S_64 942616dff86SAlexander Graf case SPRN_FSCR: 943616dff86SAlexander Graf *spr_val = vcpu->arch.fscr; 944616dff86SAlexander Graf break; 9452e23f544SAlexander Graf case SPRN_BESCR: 9462e23f544SAlexander Graf *spr_val = vcpu->arch.bescr; 9472e23f544SAlexander Graf break; 9482e23f544SAlexander Graf case SPRN_EBBHR: 9492e23f544SAlexander Graf *spr_val = vcpu->arch.ebbhr; 9502e23f544SAlexander Graf break; 9512e23f544SAlexander Graf case SPRN_EBBRR: 9522e23f544SAlexander Graf *spr_val = vcpu->arch.ebbrr; 9532e23f544SAlexander Graf break; 9549916d57eSAlexander Graf #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 9559916d57eSAlexander Graf case SPRN_TFHAR: 9569916d57eSAlexander Graf case SPRN_TEXASR: 9579916d57eSAlexander Graf case SPRN_TFIAR: 958533082aeSSimon Guo if (!cpu_has_feature(CPU_FTR_TM)) 959533082aeSSimon Guo break; 960533082aeSSimon Guo 961533082aeSSimon Guo if (!(kvmppc_get_msr(vcpu) & MSR_TM)) { 962533082aeSSimon Guo kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG); 963533082aeSSimon Guo emulated = EMULATE_AGAIN; 964533082aeSSimon Guo break; 965533082aeSSimon Guo } 966533082aeSSimon Guo 967533082aeSSimon Guo tm_enable(); 968533082aeSSimon Guo if (sprn == SPRN_TFHAR) 969533082aeSSimon Guo *spr_val = mfspr(SPRN_TFHAR); 970533082aeSSimon Guo else if (sprn == SPRN_TEXASR) 971533082aeSSimon Guo *spr_val = mfspr(SPRN_TEXASR); 972533082aeSSimon Guo else if (sprn == SPRN_TFIAR) 973533082aeSSimon Guo *spr_val = mfspr(SPRN_TFIAR); 974533082aeSSimon Guo tm_disable(); 9759916d57eSAlexander Graf break; 9769916d57eSAlexander Graf #endif 9772e23f544SAlexander Graf #endif 9782191d657SAlexander Graf case SPRN_THRM1: 9792191d657SAlexander Graf case SPRN_THRM2: 9802191d657SAlexander Graf case SPRN_THRM3: 9812191d657SAlexander Graf case SPRN_CTRLF: 9822191d657SAlexander Graf case SPRN_CTRLT: 9832191d657SAlexander Graf case SPRN_L2CR: 9842191d657SAlexander Graf case SPRN_MMCR0_GEKKO: 9852191d657SAlexander Graf case SPRN_MMCR1_GEKKO: 9862191d657SAlexander Graf case SPRN_PMC1_GEKKO: 9872191d657SAlexander Graf case SPRN_PMC2_GEKKO: 9882191d657SAlexander Graf case SPRN_PMC3_GEKKO: 9892191d657SAlexander Graf case SPRN_PMC4_GEKKO: 9902191d657SAlexander Graf case SPRN_WPAR_GEKKO: 991f2be6550SMihai Caraman case SPRN_MSSSR0: 992f3532028SAlexander Graf case SPRN_DABR: 993f8f6eb0dSAlexander Graf #ifdef CONFIG_PPC_BOOK3S_64 994f8f6eb0dSAlexander Graf case SPRN_MMCRS: 995f8f6eb0dSAlexander Graf case SPRN_MMCRA: 996f8f6eb0dSAlexander Graf case SPRN_MMCR0: 997f8f6eb0dSAlexander Graf case SPRN_MMCR1: 998f8f6eb0dSAlexander Graf case SPRN_MMCR2: 999fa73c3b2SThomas Huth case SPRN_UMMCR2: 1000a5948fa0SAlexander Graf case SPRN_TIR: 1001f8f6eb0dSAlexander Graf #endif 100254771e62SAlexander Graf *spr_val = 0; 10032191d657SAlexander Graf break; 10042191d657SAlexander Graf default: 1005317a8fa3SAlexander Graf unprivileged: 1006feafd13cSThomas Huth pr_info_ratelimited("KVM: invalid SPR read: %d\n", sprn); 1007feafd13cSThomas Huth if (sprn & 0x10) { 1008feafd13cSThomas Huth if (kvmppc_get_msr(vcpu) & MSR_PR) { 1009feafd13cSThomas Huth kvmppc_core_queue_program(vcpu, SRR1_PROGPRIV); 1010feafd13cSThomas Huth emulated = EMULATE_AGAIN; 1011feafd13cSThomas Huth } 1012feafd13cSThomas Huth } else { 1013feafd13cSThomas Huth if ((kvmppc_get_msr(vcpu) & MSR_PR) || sprn == 0 || 1014feafd13cSThomas Huth sprn == 4 || sprn == 5 || sprn == 6) { 1015feafd13cSThomas Huth kvmppc_core_queue_program(vcpu, SRR1_PROGILL); 1016feafd13cSThomas Huth emulated = EMULATE_AGAIN; 1017feafd13cSThomas Huth } 1018feafd13cSThomas Huth } 1019feafd13cSThomas Huth 10202191d657SAlexander Graf break; 10212191d657SAlexander Graf } 10222191d657SAlexander Graf 10232191d657SAlexander Graf return emulated; 10242191d657SAlexander Graf } 10252191d657SAlexander Graf 10262191d657SAlexander Graf u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst) 10272191d657SAlexander Graf { 1028ddca156aSAneesh Kumar K.V return make_dsisr(inst); 10292191d657SAlexander Graf } 10302191d657SAlexander Graf 10312191d657SAlexander Graf ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst) 10322191d657SAlexander Graf { 10337310f3a5SAneesh Kumar K.V #ifdef CONFIG_PPC_BOOK3S_64 10347310f3a5SAneesh Kumar K.V /* 10357310f3a5SAneesh Kumar K.V * Linux's fix_alignment() assumes that DAR is valid, so can we 10367310f3a5SAneesh Kumar K.V */ 10377310f3a5SAneesh Kumar K.V return vcpu->arch.fault_dar; 10387310f3a5SAneesh Kumar K.V #else 10392191d657SAlexander Graf ulong dar = 0; 1040c46dc9a8SAlexander Graf ulong ra = get_ra(inst); 1041c46dc9a8SAlexander Graf ulong rb = get_rb(inst); 10422191d657SAlexander Graf 10432191d657SAlexander Graf switch (get_op(inst)) { 10442191d657SAlexander Graf case OP_LFS: 10452191d657SAlexander Graf case OP_LFD: 10462191d657SAlexander Graf case OP_STFD: 10472191d657SAlexander Graf case OP_STFS: 10482191d657SAlexander Graf if (ra) 10492191d657SAlexander Graf dar = kvmppc_get_gpr(vcpu, ra); 10502191d657SAlexander Graf dar += (s32)((s16)inst); 10512191d657SAlexander Graf break; 10522191d657SAlexander Graf case 31: 10532191d657SAlexander Graf if (ra) 10542191d657SAlexander Graf dar = kvmppc_get_gpr(vcpu, ra); 1055c46dc9a8SAlexander Graf dar += kvmppc_get_gpr(vcpu, rb); 10562191d657SAlexander Graf break; 10572191d657SAlexander Graf default: 10582191d657SAlexander Graf printk(KERN_INFO "KVM: Unaligned instruction 0x%x\n", inst); 10592191d657SAlexander Graf break; 10602191d657SAlexander Graf } 10612191d657SAlexander Graf 10622191d657SAlexander Graf return dar; 10637310f3a5SAneesh Kumar K.V #endif 10642191d657SAlexander Graf } 1065