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 535706340aSSimon Guo 5403c81682SSimon Guo #define OP_31_XOP_TRECLAIM 942 55e32c53d1SSimon Guo #define OP_31_XOP_TRCHKPT 1006 5603c81682SSimon Guo 572191d657SAlexander Graf /* DCBZ is actually 1014, but we patch it to 1010 so we get a trap */ 582191d657SAlexander Graf #define OP_31_XOP_DCBZ 1010 592191d657SAlexander Graf 602191d657SAlexander Graf #define OP_LFS 48 612191d657SAlexander Graf #define OP_LFD 50 622191d657SAlexander Graf #define OP_STFS 52 632191d657SAlexander Graf #define OP_STFD 54 642191d657SAlexander Graf 652191d657SAlexander Graf #define SPRN_GQR0 912 662191d657SAlexander Graf #define SPRN_GQR1 913 672191d657SAlexander Graf #define SPRN_GQR2 914 682191d657SAlexander Graf #define SPRN_GQR3 915 692191d657SAlexander Graf #define SPRN_GQR4 916 702191d657SAlexander Graf #define SPRN_GQR5 917 712191d657SAlexander Graf #define SPRN_GQR6 918 722191d657SAlexander Graf #define SPRN_GQR7 919 732191d657SAlexander Graf 7407b0907dSAlexander Graf /* Book3S_32 defines mfsrin(v) - but that messes up our abstract 7507b0907dSAlexander Graf * function pointers, so let's just disable the define. */ 7607b0907dSAlexander Graf #undef mfsrin 7707b0907dSAlexander Graf 78317a8fa3SAlexander Graf enum priv_level { 79317a8fa3SAlexander Graf PRIV_PROBLEM = 0, 80317a8fa3SAlexander Graf PRIV_SUPER = 1, 81317a8fa3SAlexander Graf PRIV_HYPER = 2, 82317a8fa3SAlexander Graf }; 83317a8fa3SAlexander Graf 84317a8fa3SAlexander Graf static bool spr_allowed(struct kvm_vcpu *vcpu, enum priv_level level) 85317a8fa3SAlexander Graf { 86317a8fa3SAlexander Graf /* PAPR VMs only access supervisor SPRs */ 87317a8fa3SAlexander Graf if (vcpu->arch.papr_enabled && (level > PRIV_SUPER)) 88317a8fa3SAlexander Graf return false; 89317a8fa3SAlexander Graf 90317a8fa3SAlexander Graf /* Limit user space to its own small SPR set */ 915deb8e7aSAlexander Graf if ((kvmppc_get_msr(vcpu) & MSR_PR) && level > PRIV_PROBLEM) 92317a8fa3SAlexander Graf return false; 93317a8fa3SAlexander Graf 94317a8fa3SAlexander Graf return true; 95317a8fa3SAlexander Graf } 96317a8fa3SAlexander Graf 97de7ad932SSimon Guo #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 98de7ad932SSimon Guo static inline void kvmppc_copyto_vcpu_tm(struct kvm_vcpu *vcpu) 99de7ad932SSimon Guo { 100de7ad932SSimon Guo memcpy(&vcpu->arch.gpr_tm[0], &vcpu->arch.regs.gpr[0], 101de7ad932SSimon Guo sizeof(vcpu->arch.gpr_tm)); 102de7ad932SSimon Guo memcpy(&vcpu->arch.fp_tm, &vcpu->arch.fp, 103de7ad932SSimon Guo sizeof(struct thread_fp_state)); 104de7ad932SSimon Guo memcpy(&vcpu->arch.vr_tm, &vcpu->arch.vr, 105de7ad932SSimon Guo sizeof(struct thread_vr_state)); 106de7ad932SSimon Guo vcpu->arch.ppr_tm = vcpu->arch.ppr; 107de7ad932SSimon Guo vcpu->arch.dscr_tm = vcpu->arch.dscr; 108de7ad932SSimon Guo vcpu->arch.amr_tm = vcpu->arch.amr; 109de7ad932SSimon Guo vcpu->arch.ctr_tm = vcpu->arch.regs.ctr; 110de7ad932SSimon Guo vcpu->arch.tar_tm = vcpu->arch.tar; 111de7ad932SSimon Guo vcpu->arch.lr_tm = vcpu->arch.regs.link; 112de7ad932SSimon Guo vcpu->arch.cr_tm = vcpu->arch.cr; 113de7ad932SSimon Guo vcpu->arch.xer_tm = vcpu->arch.regs.xer; 114de7ad932SSimon Guo vcpu->arch.vrsave_tm = vcpu->arch.vrsave; 115de7ad932SSimon Guo } 116de7ad932SSimon Guo 117de7ad932SSimon Guo static inline void kvmppc_copyfrom_vcpu_tm(struct kvm_vcpu *vcpu) 118de7ad932SSimon Guo { 119de7ad932SSimon Guo memcpy(&vcpu->arch.regs.gpr[0], &vcpu->arch.gpr_tm[0], 120de7ad932SSimon Guo sizeof(vcpu->arch.regs.gpr)); 121de7ad932SSimon Guo memcpy(&vcpu->arch.fp, &vcpu->arch.fp_tm, 122de7ad932SSimon Guo sizeof(struct thread_fp_state)); 123de7ad932SSimon Guo memcpy(&vcpu->arch.vr, &vcpu->arch.vr_tm, 124de7ad932SSimon Guo sizeof(struct thread_vr_state)); 125de7ad932SSimon Guo vcpu->arch.ppr = vcpu->arch.ppr_tm; 126de7ad932SSimon Guo vcpu->arch.dscr = vcpu->arch.dscr_tm; 127de7ad932SSimon Guo vcpu->arch.amr = vcpu->arch.amr_tm; 128de7ad932SSimon Guo vcpu->arch.regs.ctr = vcpu->arch.ctr_tm; 129de7ad932SSimon Guo vcpu->arch.tar = vcpu->arch.tar_tm; 130de7ad932SSimon Guo vcpu->arch.regs.link = vcpu->arch.lr_tm; 131de7ad932SSimon Guo vcpu->arch.cr = vcpu->arch.cr_tm; 132de7ad932SSimon Guo vcpu->arch.regs.xer = vcpu->arch.xer_tm; 133de7ad932SSimon Guo vcpu->arch.vrsave = vcpu->arch.vrsave_tm; 134de7ad932SSimon Guo } 135de7ad932SSimon Guo 13603c81682SSimon Guo static void kvmppc_emulate_treclaim(struct kvm_vcpu *vcpu, int ra_val) 13703c81682SSimon Guo { 13803c81682SSimon Guo unsigned long guest_msr = kvmppc_get_msr(vcpu); 13903c81682SSimon Guo int fc_val = ra_val ? ra_val : 1; 14003c81682SSimon Guo 14103c81682SSimon Guo /* CR0 = 0 | MSR[TS] | 0 */ 14203c81682SSimon Guo vcpu->arch.cr = (vcpu->arch.cr & ~(CR0_MASK << CR0_SHIFT)) | 14303c81682SSimon Guo (((guest_msr & MSR_TS_MASK) >> (MSR_TS_S_LG - 1)) 14403c81682SSimon Guo << CR0_SHIFT); 14503c81682SSimon Guo 14603c81682SSimon Guo preempt_disable(); 14703c81682SSimon Guo kvmppc_save_tm_pr(vcpu); 14803c81682SSimon Guo kvmppc_copyfrom_vcpu_tm(vcpu); 14903c81682SSimon Guo 15003c81682SSimon Guo tm_enable(); 15103c81682SSimon Guo vcpu->arch.texasr = mfspr(SPRN_TEXASR); 15203c81682SSimon Guo /* failure recording depends on Failure Summary bit */ 15303c81682SSimon Guo if (!(vcpu->arch.texasr & TEXASR_FS)) { 15403c81682SSimon Guo vcpu->arch.texasr &= ~TEXASR_FC; 15503c81682SSimon Guo vcpu->arch.texasr |= ((u64)fc_val << TEXASR_FC_LG); 15603c81682SSimon Guo 15703c81682SSimon Guo vcpu->arch.texasr &= ~(TEXASR_PR | TEXASR_HV); 15803c81682SSimon Guo if (kvmppc_get_msr(vcpu) & MSR_PR) 15903c81682SSimon Guo vcpu->arch.texasr |= TEXASR_PR; 16003c81682SSimon Guo 16103c81682SSimon Guo if (kvmppc_get_msr(vcpu) & MSR_HV) 16203c81682SSimon Guo vcpu->arch.texasr |= TEXASR_HV; 16303c81682SSimon Guo 16403c81682SSimon Guo vcpu->arch.tfiar = kvmppc_get_pc(vcpu); 16503c81682SSimon Guo mtspr(SPRN_TEXASR, vcpu->arch.texasr); 16603c81682SSimon Guo mtspr(SPRN_TFIAR, vcpu->arch.tfiar); 16703c81682SSimon Guo } 16803c81682SSimon Guo tm_disable(); 16903c81682SSimon Guo /* 17003c81682SSimon Guo * treclaim need quit to non-transactional state. 17103c81682SSimon Guo */ 17203c81682SSimon Guo guest_msr &= ~(MSR_TS_MASK); 17303c81682SSimon Guo kvmppc_set_msr(vcpu, guest_msr); 17403c81682SSimon Guo preempt_enable(); 17503c81682SSimon Guo } 176e32c53d1SSimon Guo 177e32c53d1SSimon Guo static void kvmppc_emulate_trchkpt(struct kvm_vcpu *vcpu) 178e32c53d1SSimon Guo { 179e32c53d1SSimon Guo unsigned long guest_msr = kvmppc_get_msr(vcpu); 180e32c53d1SSimon Guo 181e32c53d1SSimon Guo preempt_disable(); 182e32c53d1SSimon Guo /* 183e32c53d1SSimon Guo * need flush FP/VEC/VSX to vcpu save area before 184e32c53d1SSimon Guo * copy. 185e32c53d1SSimon Guo */ 186e32c53d1SSimon Guo kvmppc_giveup_ext(vcpu, MSR_VSX); 187e32c53d1SSimon Guo kvmppc_copyto_vcpu_tm(vcpu); 188e32c53d1SSimon Guo kvmppc_save_tm_sprs(vcpu); 189e32c53d1SSimon Guo 190e32c53d1SSimon Guo /* 191e32c53d1SSimon Guo * as a result of trecheckpoint. set TS to suspended. 192e32c53d1SSimon Guo */ 193e32c53d1SSimon Guo guest_msr &= ~(MSR_TS_MASK); 194e32c53d1SSimon Guo guest_msr |= MSR_TS_S; 195e32c53d1SSimon Guo kvmppc_set_msr(vcpu, guest_msr); 196e32c53d1SSimon Guo kvmppc_restore_tm_pr(vcpu); 197e32c53d1SSimon Guo preempt_enable(); 198e32c53d1SSimon Guo } 199de7ad932SSimon Guo #endif 200de7ad932SSimon Guo 2013a167beaSAneesh Kumar K.V int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, 2022191d657SAlexander Graf unsigned int inst, int *advance) 2032191d657SAlexander Graf { 2042191d657SAlexander Graf int emulated = EMULATE_DONE; 205c46dc9a8SAlexander Graf int rt = get_rt(inst); 206c46dc9a8SAlexander Graf int rs = get_rs(inst); 207c46dc9a8SAlexander Graf int ra = get_ra(inst); 208c46dc9a8SAlexander Graf int rb = get_rb(inst); 20942188365SAlexander Graf u32 inst_sc = 0x44000002; 2102191d657SAlexander Graf 2112191d657SAlexander Graf switch (get_op(inst)) { 21242188365SAlexander Graf case 0: 21342188365SAlexander Graf emulated = EMULATE_FAIL; 21442188365SAlexander Graf if ((kvmppc_get_msr(vcpu) & MSR_LE) && 21542188365SAlexander Graf (inst == swab32(inst_sc))) { 21642188365SAlexander Graf /* 21742188365SAlexander Graf * This is the byte reversed syscall instruction of our 21842188365SAlexander Graf * hypercall handler. Early versions of LE Linux didn't 21942188365SAlexander Graf * swap the instructions correctly and ended up in 22042188365SAlexander Graf * illegal instructions. 22142188365SAlexander Graf * Just always fail hypercalls on these broken systems. 22242188365SAlexander Graf */ 22342188365SAlexander Graf kvmppc_set_gpr(vcpu, 3, EV_UNIMPLEMENTED); 22442188365SAlexander Graf kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) + 4); 22542188365SAlexander Graf emulated = EMULATE_DONE; 22642188365SAlexander Graf } 22742188365SAlexander Graf break; 2282191d657SAlexander Graf case 19: 2292191d657SAlexander Graf switch (get_xop(inst)) { 2302191d657SAlexander Graf case OP_19_XOP_RFID: 231401a89e9SSimon Guo case OP_19_XOP_RFI: { 232401a89e9SSimon Guo unsigned long srr1 = kvmppc_get_srr1(vcpu); 233401a89e9SSimon Guo #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 234401a89e9SSimon Guo unsigned long cur_msr = kvmppc_get_msr(vcpu); 235401a89e9SSimon Guo 236401a89e9SSimon Guo /* 237401a89e9SSimon Guo * add rules to fit in ISA specification regarding TM 238401a89e9SSimon Guo * state transistion in TM disable/Suspended state, 239401a89e9SSimon Guo * and target TM state is TM inactive(00) state. (the 240401a89e9SSimon Guo * change should be suppressed). 241401a89e9SSimon Guo */ 242401a89e9SSimon Guo if (((cur_msr & MSR_TM) == 0) && 243401a89e9SSimon Guo ((srr1 & MSR_TM) == 0) && 244401a89e9SSimon Guo MSR_TM_SUSPENDED(cur_msr) && 245401a89e9SSimon Guo !MSR_TM_ACTIVE(srr1)) 246401a89e9SSimon Guo srr1 |= MSR_TS_S; 247401a89e9SSimon Guo #endif 2485deb8e7aSAlexander Graf kvmppc_set_pc(vcpu, kvmppc_get_srr0(vcpu)); 249401a89e9SSimon Guo kvmppc_set_msr(vcpu, srr1); 2502191d657SAlexander Graf *advance = 0; 2512191d657SAlexander Graf break; 252401a89e9SSimon Guo } 2532191d657SAlexander Graf 2542191d657SAlexander Graf default: 2552191d657SAlexander Graf emulated = EMULATE_FAIL; 2562191d657SAlexander Graf break; 2572191d657SAlexander Graf } 2582191d657SAlexander Graf break; 2592191d657SAlexander Graf case 31: 2602191d657SAlexander Graf switch (get_xop(inst)) { 2612191d657SAlexander Graf case OP_31_XOP_MFMSR: 2625deb8e7aSAlexander Graf kvmppc_set_gpr(vcpu, rt, kvmppc_get_msr(vcpu)); 2632191d657SAlexander Graf break; 2642191d657SAlexander Graf case OP_31_XOP_MTMSRD: 2652191d657SAlexander Graf { 266c46dc9a8SAlexander Graf ulong rs_val = kvmppc_get_gpr(vcpu, rs); 2672191d657SAlexander Graf if (inst & 0x10000) { 2685deb8e7aSAlexander Graf ulong new_msr = kvmppc_get_msr(vcpu); 269c46dc9a8SAlexander Graf new_msr &= ~(MSR_RI | MSR_EE); 270c46dc9a8SAlexander Graf new_msr |= rs_val & (MSR_RI | MSR_EE); 2715deb8e7aSAlexander Graf kvmppc_set_msr_fast(vcpu, new_msr); 2722191d657SAlexander Graf } else 273c46dc9a8SAlexander Graf kvmppc_set_msr(vcpu, rs_val); 2742191d657SAlexander Graf break; 2752191d657SAlexander Graf } 2762191d657SAlexander Graf case OP_31_XOP_MTMSR: 277c46dc9a8SAlexander Graf kvmppc_set_msr(vcpu, kvmppc_get_gpr(vcpu, rs)); 2782191d657SAlexander Graf break; 2792191d657SAlexander Graf case OP_31_XOP_MFSR: 2802191d657SAlexander Graf { 2812191d657SAlexander Graf int srnum; 2822191d657SAlexander Graf 2832191d657SAlexander Graf srnum = kvmppc_get_field(inst, 12 + 32, 15 + 32); 2842191d657SAlexander Graf if (vcpu->arch.mmu.mfsrin) { 2852191d657SAlexander Graf u32 sr; 2862191d657SAlexander Graf sr = vcpu->arch.mmu.mfsrin(vcpu, srnum); 287c46dc9a8SAlexander Graf kvmppc_set_gpr(vcpu, rt, sr); 2882191d657SAlexander Graf } 2892191d657SAlexander Graf break; 2902191d657SAlexander Graf } 2912191d657SAlexander Graf case OP_31_XOP_MFSRIN: 2922191d657SAlexander Graf { 2932191d657SAlexander Graf int srnum; 2942191d657SAlexander Graf 295c46dc9a8SAlexander Graf srnum = (kvmppc_get_gpr(vcpu, rb) >> 28) & 0xf; 2962191d657SAlexander Graf if (vcpu->arch.mmu.mfsrin) { 2972191d657SAlexander Graf u32 sr; 2982191d657SAlexander Graf sr = vcpu->arch.mmu.mfsrin(vcpu, srnum); 299c46dc9a8SAlexander Graf kvmppc_set_gpr(vcpu, rt, sr); 3002191d657SAlexander Graf } 3012191d657SAlexander Graf break; 3022191d657SAlexander Graf } 3032191d657SAlexander Graf case OP_31_XOP_MTSR: 3042191d657SAlexander Graf vcpu->arch.mmu.mtsrin(vcpu, 3052191d657SAlexander Graf (inst >> 16) & 0xf, 306c46dc9a8SAlexander Graf kvmppc_get_gpr(vcpu, rs)); 3072191d657SAlexander Graf break; 3082191d657SAlexander Graf case OP_31_XOP_MTSRIN: 3092191d657SAlexander Graf vcpu->arch.mmu.mtsrin(vcpu, 310c46dc9a8SAlexander Graf (kvmppc_get_gpr(vcpu, rb) >> 28) & 0xf, 311c46dc9a8SAlexander Graf kvmppc_get_gpr(vcpu, rs)); 3122191d657SAlexander Graf break; 3132191d657SAlexander Graf case OP_31_XOP_TLBIE: 3142191d657SAlexander Graf case OP_31_XOP_TLBIEL: 3152191d657SAlexander Graf { 3162191d657SAlexander Graf bool large = (inst & 0x00200000) ? true : false; 317c46dc9a8SAlexander Graf ulong addr = kvmppc_get_gpr(vcpu, rb); 3182191d657SAlexander Graf vcpu->arch.mmu.tlbie(vcpu, addr, large); 3192191d657SAlexander Graf break; 3202191d657SAlexander Graf } 3212ba9f0d8SAneesh Kumar K.V #ifdef CONFIG_PPC_BOOK3S_64 32250c7bb80SAlexander Graf case OP_31_XOP_FAKE_SC1: 32350c7bb80SAlexander Graf { 32450c7bb80SAlexander Graf /* SC 1 papr hypercalls */ 32550c7bb80SAlexander Graf ulong cmd = kvmppc_get_gpr(vcpu, 3); 32650c7bb80SAlexander Graf int i; 32750c7bb80SAlexander Graf 3285deb8e7aSAlexander Graf if ((kvmppc_get_msr(vcpu) & MSR_PR) || 32950c7bb80SAlexander Graf !vcpu->arch.papr_enabled) { 33050c7bb80SAlexander Graf emulated = EMULATE_FAIL; 33150c7bb80SAlexander Graf break; 33250c7bb80SAlexander Graf } 33350c7bb80SAlexander Graf 33450c7bb80SAlexander Graf if (kvmppc_h_pr(vcpu, cmd) == EMULATE_DONE) 33550c7bb80SAlexander Graf break; 33650c7bb80SAlexander Graf 33750c7bb80SAlexander Graf run->papr_hcall.nr = cmd; 33850c7bb80SAlexander Graf for (i = 0; i < 9; ++i) { 33950c7bb80SAlexander Graf ulong gpr = kvmppc_get_gpr(vcpu, 4 + i); 34050c7bb80SAlexander Graf run->papr_hcall.args[i] = gpr; 34150c7bb80SAlexander Graf } 34250c7bb80SAlexander Graf 3430f47f9b5SBharat Bhushan run->exit_reason = KVM_EXIT_PAPR_HCALL; 3440f47f9b5SBharat Bhushan vcpu->arch.hcall_needed = 1; 345c402a3f4SBharat Bhushan emulated = EMULATE_EXIT_USER; 34650c7bb80SAlexander Graf break; 34750c7bb80SAlexander Graf } 34850c7bb80SAlexander Graf #endif 3492191d657SAlexander Graf case OP_31_XOP_EIOIO: 3502191d657SAlexander Graf break; 3512191d657SAlexander Graf case OP_31_XOP_SLBMTE: 3522191d657SAlexander Graf if (!vcpu->arch.mmu.slbmte) 3532191d657SAlexander Graf return EMULATE_FAIL; 3542191d657SAlexander Graf 3552191d657SAlexander Graf vcpu->arch.mmu.slbmte(vcpu, 356c46dc9a8SAlexander Graf kvmppc_get_gpr(vcpu, rs), 357c46dc9a8SAlexander Graf kvmppc_get_gpr(vcpu, rb)); 3582191d657SAlexander Graf break; 3592191d657SAlexander Graf case OP_31_XOP_SLBIE: 3602191d657SAlexander Graf if (!vcpu->arch.mmu.slbie) 3612191d657SAlexander Graf return EMULATE_FAIL; 3622191d657SAlexander Graf 3632191d657SAlexander Graf vcpu->arch.mmu.slbie(vcpu, 364c46dc9a8SAlexander Graf kvmppc_get_gpr(vcpu, rb)); 3652191d657SAlexander Graf break; 3662191d657SAlexander Graf case OP_31_XOP_SLBIA: 3672191d657SAlexander Graf if (!vcpu->arch.mmu.slbia) 3682191d657SAlexander Graf return EMULATE_FAIL; 3692191d657SAlexander Graf 3702191d657SAlexander Graf vcpu->arch.mmu.slbia(vcpu); 3712191d657SAlexander Graf break; 3722191d657SAlexander Graf case OP_31_XOP_SLBMFEE: 3732191d657SAlexander Graf if (!vcpu->arch.mmu.slbmfee) { 3742191d657SAlexander Graf emulated = EMULATE_FAIL; 3752191d657SAlexander Graf } else { 376c46dc9a8SAlexander Graf ulong t, rb_val; 3772191d657SAlexander Graf 378c46dc9a8SAlexander Graf rb_val = kvmppc_get_gpr(vcpu, rb); 379c46dc9a8SAlexander Graf t = vcpu->arch.mmu.slbmfee(vcpu, rb_val); 380c46dc9a8SAlexander Graf kvmppc_set_gpr(vcpu, rt, t); 3812191d657SAlexander Graf } 3822191d657SAlexander Graf break; 3832191d657SAlexander Graf case OP_31_XOP_SLBMFEV: 3842191d657SAlexander Graf if (!vcpu->arch.mmu.slbmfev) { 3852191d657SAlexander Graf emulated = EMULATE_FAIL; 3862191d657SAlexander Graf } else { 387c46dc9a8SAlexander Graf ulong t, rb_val; 3882191d657SAlexander Graf 389c46dc9a8SAlexander Graf rb_val = kvmppc_get_gpr(vcpu, rb); 390c46dc9a8SAlexander Graf t = vcpu->arch.mmu.slbmfev(vcpu, rb_val); 391c46dc9a8SAlexander Graf kvmppc_set_gpr(vcpu, rt, t); 3922191d657SAlexander Graf } 3932191d657SAlexander Graf break; 3942191d657SAlexander Graf case OP_31_XOP_DCBA: 3952191d657SAlexander Graf /* Gets treated as NOP */ 3962191d657SAlexander Graf break; 3972191d657SAlexander Graf case OP_31_XOP_DCBZ: 3982191d657SAlexander Graf { 399c46dc9a8SAlexander Graf ulong rb_val = kvmppc_get_gpr(vcpu, rb); 400c46dc9a8SAlexander Graf ulong ra_val = 0; 4012191d657SAlexander Graf ulong addr, vaddr; 4022191d657SAlexander Graf u32 zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 4032191d657SAlexander Graf u32 dsisr; 4042191d657SAlexander Graf int r; 4052191d657SAlexander Graf 406c46dc9a8SAlexander Graf if (ra) 407c46dc9a8SAlexander Graf ra_val = kvmppc_get_gpr(vcpu, ra); 4082191d657SAlexander Graf 409c46dc9a8SAlexander Graf addr = (ra_val + rb_val) & ~31ULL; 4105deb8e7aSAlexander Graf if (!(kvmppc_get_msr(vcpu) & MSR_SF)) 4112191d657SAlexander Graf addr &= 0xffffffff; 4122191d657SAlexander Graf vaddr = addr; 4132191d657SAlexander Graf 4142191d657SAlexander Graf r = kvmppc_st(vcpu, &addr, 32, zeros, true); 4152191d657SAlexander Graf if ((r == -ENOENT) || (r == -EPERM)) { 4162191d657SAlexander Graf *advance = 0; 4175deb8e7aSAlexander Graf kvmppc_set_dar(vcpu, vaddr); 418a2d56020SPaul Mackerras vcpu->arch.fault_dar = vaddr; 4192191d657SAlexander Graf 4202191d657SAlexander Graf dsisr = DSISR_ISSTORE; 4212191d657SAlexander Graf if (r == -ENOENT) 4222191d657SAlexander Graf dsisr |= DSISR_NOHPTE; 4232191d657SAlexander Graf else if (r == -EPERM) 4242191d657SAlexander Graf dsisr |= DSISR_PROTFAULT; 4252191d657SAlexander Graf 4265deb8e7aSAlexander Graf kvmppc_set_dsisr(vcpu, dsisr); 427a2d56020SPaul Mackerras vcpu->arch.fault_dsisr = dsisr; 4282191d657SAlexander Graf 4292191d657SAlexander Graf kvmppc_book3s_queue_irqprio(vcpu, 4302191d657SAlexander Graf BOOK3S_INTERRUPT_DATA_STORAGE); 4312191d657SAlexander Graf } 4322191d657SAlexander Graf 4332191d657SAlexander Graf break; 4342191d657SAlexander Graf } 4355706340aSSimon Guo #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 4365706340aSSimon Guo case OP_31_XOP_TBEGIN: 4375706340aSSimon Guo { 4385706340aSSimon Guo if (!cpu_has_feature(CPU_FTR_TM)) 4395706340aSSimon Guo break; 4405706340aSSimon Guo 4415706340aSSimon Guo if (!(kvmppc_get_msr(vcpu) & MSR_TM)) { 4425706340aSSimon Guo kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG); 4435706340aSSimon Guo emulated = EMULATE_AGAIN; 4445706340aSSimon Guo break; 4455706340aSSimon Guo } 4465706340aSSimon Guo 4475706340aSSimon Guo if (!(kvmppc_get_msr(vcpu) & MSR_PR)) { 4485706340aSSimon Guo preempt_disable(); 4495706340aSSimon Guo vcpu->arch.cr = (CR0_TBEGIN_FAILURE | 4505706340aSSimon Guo (vcpu->arch.cr & ~(CR0_MASK << CR0_SHIFT))); 4515706340aSSimon Guo 4525706340aSSimon Guo vcpu->arch.texasr = (TEXASR_FS | TEXASR_EXACT | 4535706340aSSimon Guo (((u64)(TM_CAUSE_EMULATE | TM_CAUSE_PERSISTENT)) 4545706340aSSimon Guo << TEXASR_FC_LG)); 4555706340aSSimon Guo 4565706340aSSimon Guo if ((inst >> 21) & 0x1) 4575706340aSSimon Guo vcpu->arch.texasr |= TEXASR_ROT; 4585706340aSSimon Guo 4595706340aSSimon Guo if (kvmppc_get_msr(vcpu) & MSR_HV) 4605706340aSSimon Guo vcpu->arch.texasr |= TEXASR_HV; 4615706340aSSimon Guo 4625706340aSSimon Guo vcpu->arch.tfhar = kvmppc_get_pc(vcpu) + 4; 4635706340aSSimon Guo vcpu->arch.tfiar = kvmppc_get_pc(vcpu); 4645706340aSSimon Guo 4655706340aSSimon Guo kvmppc_restore_tm_sprs(vcpu); 4665706340aSSimon Guo preempt_enable(); 4675706340aSSimon Guo } else 4685706340aSSimon Guo emulated = EMULATE_FAIL; 4695706340aSSimon Guo break; 4705706340aSSimon Guo } 47103c81682SSimon Guo case OP_31_XOP_TRECLAIM: 47203c81682SSimon Guo { 47303c81682SSimon Guo ulong guest_msr = kvmppc_get_msr(vcpu); 47403c81682SSimon Guo unsigned long ra_val = 0; 47503c81682SSimon Guo 47603c81682SSimon Guo if (!cpu_has_feature(CPU_FTR_TM)) 47703c81682SSimon Guo break; 47803c81682SSimon Guo 47903c81682SSimon Guo if (!(kvmppc_get_msr(vcpu) & MSR_TM)) { 48003c81682SSimon Guo kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG); 48103c81682SSimon Guo emulated = EMULATE_AGAIN; 48203c81682SSimon Guo break; 48303c81682SSimon Guo } 48403c81682SSimon Guo 48503c81682SSimon Guo /* generate interrupts based on priorities */ 48603c81682SSimon Guo if (guest_msr & MSR_PR) { 48703c81682SSimon Guo /* Privileged Instruction type Program Interrupt */ 48803c81682SSimon Guo kvmppc_core_queue_program(vcpu, SRR1_PROGPRIV); 48903c81682SSimon Guo emulated = EMULATE_AGAIN; 49003c81682SSimon Guo break; 49103c81682SSimon Guo } 49203c81682SSimon Guo 49303c81682SSimon Guo if (!MSR_TM_ACTIVE(guest_msr)) { 49403c81682SSimon Guo /* TM bad thing interrupt */ 49503c81682SSimon Guo kvmppc_core_queue_program(vcpu, SRR1_PROGTM); 49603c81682SSimon Guo emulated = EMULATE_AGAIN; 49703c81682SSimon Guo break; 49803c81682SSimon Guo } 49903c81682SSimon Guo 50003c81682SSimon Guo if (ra) 50103c81682SSimon Guo ra_val = kvmppc_get_gpr(vcpu, ra); 50203c81682SSimon Guo kvmppc_emulate_treclaim(vcpu, ra_val); 50303c81682SSimon Guo break; 50403c81682SSimon Guo } 505e32c53d1SSimon Guo case OP_31_XOP_TRCHKPT: 506e32c53d1SSimon Guo { 507e32c53d1SSimon Guo ulong guest_msr = kvmppc_get_msr(vcpu); 508e32c53d1SSimon Guo unsigned long texasr; 509e32c53d1SSimon Guo 510e32c53d1SSimon Guo if (!cpu_has_feature(CPU_FTR_TM)) 511e32c53d1SSimon Guo break; 512e32c53d1SSimon Guo 513e32c53d1SSimon Guo if (!(kvmppc_get_msr(vcpu) & MSR_TM)) { 514e32c53d1SSimon Guo kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG); 515e32c53d1SSimon Guo emulated = EMULATE_AGAIN; 516e32c53d1SSimon Guo break; 517e32c53d1SSimon Guo } 518e32c53d1SSimon Guo 519e32c53d1SSimon Guo /* generate interrupt based on priorities */ 520e32c53d1SSimon Guo if (guest_msr & MSR_PR) { 521e32c53d1SSimon Guo /* Privileged Instruction type Program Intr */ 522e32c53d1SSimon Guo kvmppc_core_queue_program(vcpu, SRR1_PROGPRIV); 523e32c53d1SSimon Guo emulated = EMULATE_AGAIN; 524e32c53d1SSimon Guo break; 525e32c53d1SSimon Guo } 526e32c53d1SSimon Guo 527e32c53d1SSimon Guo tm_enable(); 528e32c53d1SSimon Guo texasr = mfspr(SPRN_TEXASR); 529e32c53d1SSimon Guo tm_disable(); 530e32c53d1SSimon Guo 531e32c53d1SSimon Guo if (MSR_TM_ACTIVE(guest_msr) || 532e32c53d1SSimon Guo !(texasr & (TEXASR_FS))) { 533e32c53d1SSimon Guo /* TM bad thing interrupt */ 534e32c53d1SSimon Guo kvmppc_core_queue_program(vcpu, SRR1_PROGTM); 535e32c53d1SSimon Guo emulated = EMULATE_AGAIN; 536e32c53d1SSimon Guo break; 537e32c53d1SSimon Guo } 538e32c53d1SSimon Guo 539e32c53d1SSimon Guo kvmppc_emulate_trchkpt(vcpu); 540e32c53d1SSimon Guo break; 541e32c53d1SSimon Guo } 5425706340aSSimon Guo #endif 5432191d657SAlexander Graf default: 5442191d657SAlexander Graf emulated = EMULATE_FAIL; 5452191d657SAlexander Graf } 5462191d657SAlexander Graf break; 5472191d657SAlexander Graf default: 5482191d657SAlexander Graf emulated = EMULATE_FAIL; 5492191d657SAlexander Graf } 5502191d657SAlexander Graf 5512191d657SAlexander Graf if (emulated == EMULATE_FAIL) 5522191d657SAlexander Graf emulated = kvmppc_emulate_paired_single(run, vcpu); 5532191d657SAlexander Graf 5542191d657SAlexander Graf return emulated; 5552191d657SAlexander Graf } 5562191d657SAlexander Graf 5572191d657SAlexander Graf void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, bool upper, 5582191d657SAlexander Graf u32 val) 5592191d657SAlexander Graf { 5602191d657SAlexander Graf if (upper) { 5612191d657SAlexander Graf /* Upper BAT */ 5622191d657SAlexander Graf u32 bl = (val >> 2) & 0x7ff; 5632191d657SAlexander Graf bat->bepi_mask = (~bl << 17); 5642191d657SAlexander Graf bat->bepi = val & 0xfffe0000; 5652191d657SAlexander Graf bat->vs = (val & 2) ? 1 : 0; 5662191d657SAlexander Graf bat->vp = (val & 1) ? 1 : 0; 5672191d657SAlexander Graf bat->raw = (bat->raw & 0xffffffff00000000ULL) | val; 5682191d657SAlexander Graf } else { 5692191d657SAlexander Graf /* Lower BAT */ 5702191d657SAlexander Graf bat->brpn = val & 0xfffe0000; 5712191d657SAlexander Graf bat->wimg = (val >> 3) & 0xf; 5722191d657SAlexander Graf bat->pp = val & 3; 5732191d657SAlexander Graf bat->raw = (bat->raw & 0x00000000ffffffffULL) | ((u64)val << 32); 5742191d657SAlexander Graf } 5752191d657SAlexander Graf } 5762191d657SAlexander Graf 577c1c88e2fSAlexander Graf static struct kvmppc_bat *kvmppc_find_bat(struct kvm_vcpu *vcpu, int sprn) 5782191d657SAlexander Graf { 5792191d657SAlexander Graf struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); 5802191d657SAlexander Graf struct kvmppc_bat *bat; 5812191d657SAlexander Graf 5822191d657SAlexander Graf switch (sprn) { 5832191d657SAlexander Graf case SPRN_IBAT0U ... SPRN_IBAT3L: 5842191d657SAlexander Graf bat = &vcpu_book3s->ibat[(sprn - SPRN_IBAT0U) / 2]; 5852191d657SAlexander Graf break; 5862191d657SAlexander Graf case SPRN_IBAT4U ... SPRN_IBAT7L: 5872191d657SAlexander Graf bat = &vcpu_book3s->ibat[4 + ((sprn - SPRN_IBAT4U) / 2)]; 5882191d657SAlexander Graf break; 5892191d657SAlexander Graf case SPRN_DBAT0U ... SPRN_DBAT3L: 5902191d657SAlexander Graf bat = &vcpu_book3s->dbat[(sprn - SPRN_DBAT0U) / 2]; 5912191d657SAlexander Graf break; 5922191d657SAlexander Graf case SPRN_DBAT4U ... SPRN_DBAT7L: 5932191d657SAlexander Graf bat = &vcpu_book3s->dbat[4 + ((sprn - SPRN_DBAT4U) / 2)]; 5942191d657SAlexander Graf break; 5952191d657SAlexander Graf default: 5962191d657SAlexander Graf BUG(); 5972191d657SAlexander Graf } 5982191d657SAlexander Graf 599c1c88e2fSAlexander Graf return bat; 6002191d657SAlexander Graf } 6012191d657SAlexander Graf 6023a167beaSAneesh Kumar K.V int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) 6032191d657SAlexander Graf { 6042191d657SAlexander Graf int emulated = EMULATE_DONE; 6052191d657SAlexander Graf 6062191d657SAlexander Graf switch (sprn) { 6072191d657SAlexander Graf case SPRN_SDR1: 608317a8fa3SAlexander Graf if (!spr_allowed(vcpu, PRIV_HYPER)) 609317a8fa3SAlexander Graf goto unprivileged; 6102191d657SAlexander Graf to_book3s(vcpu)->sdr1 = spr_val; 6112191d657SAlexander Graf break; 6122191d657SAlexander Graf case SPRN_DSISR: 6135deb8e7aSAlexander Graf kvmppc_set_dsisr(vcpu, spr_val); 6142191d657SAlexander Graf break; 6152191d657SAlexander Graf case SPRN_DAR: 6165deb8e7aSAlexander Graf kvmppc_set_dar(vcpu, spr_val); 6172191d657SAlexander Graf break; 6182191d657SAlexander Graf case SPRN_HIOR: 6192191d657SAlexander Graf to_book3s(vcpu)->hior = spr_val; 6202191d657SAlexander Graf break; 6212191d657SAlexander Graf case SPRN_IBAT0U ... SPRN_IBAT3L: 6222191d657SAlexander Graf case SPRN_IBAT4U ... SPRN_IBAT7L: 6232191d657SAlexander Graf case SPRN_DBAT0U ... SPRN_DBAT3L: 6242191d657SAlexander Graf case SPRN_DBAT4U ... SPRN_DBAT7L: 625c1c88e2fSAlexander Graf { 626c1c88e2fSAlexander Graf struct kvmppc_bat *bat = kvmppc_find_bat(vcpu, sprn); 627c1c88e2fSAlexander Graf 628c1c88e2fSAlexander Graf kvmppc_set_bat(vcpu, bat, !(sprn % 2), (u32)spr_val); 6292191d657SAlexander Graf /* BAT writes happen so rarely that we're ok to flush 6302191d657SAlexander Graf * everything here */ 6312191d657SAlexander Graf kvmppc_mmu_pte_flush(vcpu, 0, 0); 6322191d657SAlexander Graf kvmppc_mmu_flush_segments(vcpu); 6332191d657SAlexander Graf break; 634c1c88e2fSAlexander Graf } 6352191d657SAlexander Graf case SPRN_HID0: 6362191d657SAlexander Graf to_book3s(vcpu)->hid[0] = spr_val; 6372191d657SAlexander Graf break; 6382191d657SAlexander Graf case SPRN_HID1: 6392191d657SAlexander Graf to_book3s(vcpu)->hid[1] = spr_val; 6402191d657SAlexander Graf break; 6412191d657SAlexander Graf case SPRN_HID2: 6422191d657SAlexander Graf to_book3s(vcpu)->hid[2] = spr_val; 6432191d657SAlexander Graf break; 6442191d657SAlexander Graf case SPRN_HID2_GEKKO: 6452191d657SAlexander Graf to_book3s(vcpu)->hid[2] = spr_val; 6462191d657SAlexander Graf /* HID2.PSE controls paired single on gekko */ 6472191d657SAlexander Graf switch (vcpu->arch.pvr) { 6482191d657SAlexander Graf case 0x00080200: /* lonestar 2.0 */ 6492191d657SAlexander Graf case 0x00088202: /* lonestar 2.2 */ 6502191d657SAlexander Graf case 0x70000100: /* gekko 1.0 */ 6512191d657SAlexander Graf case 0x00080100: /* gekko 2.0 */ 6522191d657SAlexander Graf case 0x00083203: /* gekko 2.3a */ 6532191d657SAlexander Graf case 0x00083213: /* gekko 2.3b */ 6542191d657SAlexander Graf case 0x00083204: /* gekko 2.4 */ 6552191d657SAlexander Graf case 0x00083214: /* gekko 2.4e (8SE) - retail HW2 */ 656b83d4a9cSAlexander Graf case 0x00087200: /* broadway */ 657b83d4a9cSAlexander Graf if (vcpu->arch.hflags & BOOK3S_HFLAG_NATIVE_PS) { 658b83d4a9cSAlexander Graf /* Native paired singles */ 659b83d4a9cSAlexander Graf } else if (spr_val & (1 << 29)) { /* HID2.PSE */ 6602191d657SAlexander Graf vcpu->arch.hflags |= BOOK3S_HFLAG_PAIRED_SINGLE; 6612191d657SAlexander Graf kvmppc_giveup_ext(vcpu, MSR_FP); 6622191d657SAlexander Graf } else { 6632191d657SAlexander Graf vcpu->arch.hflags &= ~BOOK3S_HFLAG_PAIRED_SINGLE; 6642191d657SAlexander Graf } 6652191d657SAlexander Graf break; 6662191d657SAlexander Graf } 6672191d657SAlexander Graf break; 6682191d657SAlexander Graf case SPRN_HID4: 6692191d657SAlexander Graf case SPRN_HID4_GEKKO: 6702191d657SAlexander Graf to_book3s(vcpu)->hid[4] = spr_val; 6712191d657SAlexander Graf break; 6722191d657SAlexander Graf case SPRN_HID5: 6732191d657SAlexander Graf to_book3s(vcpu)->hid[5] = spr_val; 6742191d657SAlexander Graf /* guest HID5 set can change is_dcbz32 */ 6752191d657SAlexander Graf if (vcpu->arch.mmu.is_dcbz32(vcpu) && 6762191d657SAlexander Graf (mfmsr() & MSR_HV)) 6772191d657SAlexander Graf vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32; 6782191d657SAlexander Graf break; 6792191d657SAlexander Graf case SPRN_GQR0: 6802191d657SAlexander Graf case SPRN_GQR1: 6812191d657SAlexander Graf case SPRN_GQR2: 6822191d657SAlexander Graf case SPRN_GQR3: 6832191d657SAlexander Graf case SPRN_GQR4: 6842191d657SAlexander Graf case SPRN_GQR5: 6852191d657SAlexander Graf case SPRN_GQR6: 6862191d657SAlexander Graf case SPRN_GQR7: 6872191d657SAlexander Graf to_book3s(vcpu)->gqr[sprn - SPRN_GQR0] = spr_val; 6882191d657SAlexander Graf break; 6892e23f544SAlexander Graf #ifdef CONFIG_PPC_BOOK3S_64 6908e6afa36SAlexander Graf case SPRN_FSCR: 6918e6afa36SAlexander Graf kvmppc_set_fscr(vcpu, spr_val); 6928e6afa36SAlexander Graf break; 6932e23f544SAlexander Graf case SPRN_BESCR: 6942e23f544SAlexander Graf vcpu->arch.bescr = spr_val; 6952e23f544SAlexander Graf break; 6962e23f544SAlexander Graf case SPRN_EBBHR: 6972e23f544SAlexander Graf vcpu->arch.ebbhr = spr_val; 6982e23f544SAlexander Graf break; 6992e23f544SAlexander Graf case SPRN_EBBRR: 7002e23f544SAlexander Graf vcpu->arch.ebbrr = spr_val; 7012e23f544SAlexander Graf break; 7029916d57eSAlexander Graf #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 7039916d57eSAlexander Graf case SPRN_TFHAR: 7049916d57eSAlexander Graf case SPRN_TEXASR: 7059916d57eSAlexander Graf case SPRN_TFIAR: 706533082aeSSimon Guo if (!cpu_has_feature(CPU_FTR_TM)) 707533082aeSSimon Guo break; 708533082aeSSimon Guo 709533082aeSSimon Guo if (!(kvmppc_get_msr(vcpu) & MSR_TM)) { 710533082aeSSimon Guo kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG); 711533082aeSSimon Guo emulated = EMULATE_AGAIN; 712533082aeSSimon Guo break; 713533082aeSSimon Guo } 714533082aeSSimon Guo 715533082aeSSimon Guo if (MSR_TM_ACTIVE(kvmppc_get_msr(vcpu)) && 716533082aeSSimon Guo !((MSR_TM_SUSPENDED(kvmppc_get_msr(vcpu))) && 717533082aeSSimon Guo (sprn == SPRN_TFHAR))) { 718533082aeSSimon Guo /* it is illegal to mtspr() TM regs in 719533082aeSSimon Guo * other than non-transactional state, with 720533082aeSSimon Guo * the exception of TFHAR in suspend state. 721533082aeSSimon Guo */ 722533082aeSSimon Guo kvmppc_core_queue_program(vcpu, SRR1_PROGTM); 723533082aeSSimon Guo emulated = EMULATE_AGAIN; 724533082aeSSimon Guo break; 725533082aeSSimon Guo } 726533082aeSSimon Guo 727533082aeSSimon Guo tm_enable(); 728533082aeSSimon Guo if (sprn == SPRN_TFHAR) 729533082aeSSimon Guo mtspr(SPRN_TFHAR, spr_val); 730533082aeSSimon Guo else if (sprn == SPRN_TEXASR) 731533082aeSSimon Guo mtspr(SPRN_TEXASR, spr_val); 732533082aeSSimon Guo else 733533082aeSSimon Guo mtspr(SPRN_TFIAR, spr_val); 734533082aeSSimon Guo tm_disable(); 735533082aeSSimon Guo 7369916d57eSAlexander Graf break; 7379916d57eSAlexander Graf #endif 7382e23f544SAlexander Graf #endif 7392191d657SAlexander Graf case SPRN_ICTC: 7402191d657SAlexander Graf case SPRN_THRM1: 7412191d657SAlexander Graf case SPRN_THRM2: 7422191d657SAlexander Graf case SPRN_THRM3: 7432191d657SAlexander Graf case SPRN_CTRLF: 7442191d657SAlexander Graf case SPRN_CTRLT: 7452191d657SAlexander Graf case SPRN_L2CR: 746b0a94d4eSPaul Mackerras case SPRN_DSCR: 7472191d657SAlexander Graf case SPRN_MMCR0_GEKKO: 7482191d657SAlexander Graf case SPRN_MMCR1_GEKKO: 7492191d657SAlexander Graf case SPRN_PMC1_GEKKO: 7502191d657SAlexander Graf case SPRN_PMC2_GEKKO: 7512191d657SAlexander Graf case SPRN_PMC3_GEKKO: 7522191d657SAlexander Graf case SPRN_PMC4_GEKKO: 7532191d657SAlexander Graf case SPRN_WPAR_GEKKO: 754f2be6550SMihai Caraman case SPRN_MSSSR0: 755f3532028SAlexander Graf case SPRN_DABR: 756f8f6eb0dSAlexander Graf #ifdef CONFIG_PPC_BOOK3S_64 757f8f6eb0dSAlexander Graf case SPRN_MMCRS: 758f8f6eb0dSAlexander Graf case SPRN_MMCRA: 759f8f6eb0dSAlexander Graf case SPRN_MMCR0: 760f8f6eb0dSAlexander Graf case SPRN_MMCR1: 761f8f6eb0dSAlexander Graf case SPRN_MMCR2: 762fa73c3b2SThomas Huth case SPRN_UMMCR2: 763f8f6eb0dSAlexander Graf #endif 7642191d657SAlexander Graf break; 765317a8fa3SAlexander Graf unprivileged: 7662191d657SAlexander Graf default: 767feafd13cSThomas Huth pr_info_ratelimited("KVM: invalid SPR write: %d\n", sprn); 768feafd13cSThomas Huth if (sprn & 0x10) { 769feafd13cSThomas Huth if (kvmppc_get_msr(vcpu) & MSR_PR) { 770feafd13cSThomas Huth kvmppc_core_queue_program(vcpu, SRR1_PROGPRIV); 771feafd13cSThomas Huth emulated = EMULATE_AGAIN; 772feafd13cSThomas Huth } 773feafd13cSThomas Huth } else { 774feafd13cSThomas Huth if ((kvmppc_get_msr(vcpu) & MSR_PR) || sprn == 0) { 775feafd13cSThomas Huth kvmppc_core_queue_program(vcpu, SRR1_PROGILL); 776feafd13cSThomas Huth emulated = EMULATE_AGAIN; 777feafd13cSThomas Huth } 778feafd13cSThomas Huth } 7792191d657SAlexander Graf break; 7802191d657SAlexander Graf } 7812191d657SAlexander Graf 7822191d657SAlexander Graf return emulated; 7832191d657SAlexander Graf } 7842191d657SAlexander Graf 7853a167beaSAneesh Kumar K.V int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val) 7862191d657SAlexander Graf { 7872191d657SAlexander Graf int emulated = EMULATE_DONE; 7882191d657SAlexander Graf 7892191d657SAlexander Graf switch (sprn) { 7902191d657SAlexander Graf case SPRN_IBAT0U ... SPRN_IBAT3L: 7912191d657SAlexander Graf case SPRN_IBAT4U ... SPRN_IBAT7L: 7922191d657SAlexander Graf case SPRN_DBAT0U ... SPRN_DBAT3L: 7932191d657SAlexander Graf case SPRN_DBAT4U ... SPRN_DBAT7L: 794c1c88e2fSAlexander Graf { 795c1c88e2fSAlexander Graf struct kvmppc_bat *bat = kvmppc_find_bat(vcpu, sprn); 796c1c88e2fSAlexander Graf 797c1c88e2fSAlexander Graf if (sprn % 2) 79854771e62SAlexander Graf *spr_val = bat->raw >> 32; 799c1c88e2fSAlexander Graf else 80054771e62SAlexander Graf *spr_val = bat->raw; 801c1c88e2fSAlexander Graf 8022191d657SAlexander Graf break; 803c1c88e2fSAlexander Graf } 8042191d657SAlexander Graf case SPRN_SDR1: 805317a8fa3SAlexander Graf if (!spr_allowed(vcpu, PRIV_HYPER)) 806317a8fa3SAlexander Graf goto unprivileged; 80754771e62SAlexander Graf *spr_val = to_book3s(vcpu)->sdr1; 8082191d657SAlexander Graf break; 8092191d657SAlexander Graf case SPRN_DSISR: 8105deb8e7aSAlexander Graf *spr_val = kvmppc_get_dsisr(vcpu); 8112191d657SAlexander Graf break; 8122191d657SAlexander Graf case SPRN_DAR: 8135deb8e7aSAlexander Graf *spr_val = kvmppc_get_dar(vcpu); 8142191d657SAlexander Graf break; 8152191d657SAlexander Graf case SPRN_HIOR: 81654771e62SAlexander Graf *spr_val = to_book3s(vcpu)->hior; 8172191d657SAlexander Graf break; 8182191d657SAlexander Graf case SPRN_HID0: 81954771e62SAlexander Graf *spr_val = to_book3s(vcpu)->hid[0]; 8202191d657SAlexander Graf break; 8212191d657SAlexander Graf case SPRN_HID1: 82254771e62SAlexander Graf *spr_val = to_book3s(vcpu)->hid[1]; 8232191d657SAlexander Graf break; 8242191d657SAlexander Graf case SPRN_HID2: 8252191d657SAlexander Graf case SPRN_HID2_GEKKO: 82654771e62SAlexander Graf *spr_val = to_book3s(vcpu)->hid[2]; 8272191d657SAlexander Graf break; 8282191d657SAlexander Graf case SPRN_HID4: 8292191d657SAlexander Graf case SPRN_HID4_GEKKO: 83054771e62SAlexander Graf *spr_val = to_book3s(vcpu)->hid[4]; 8312191d657SAlexander Graf break; 8322191d657SAlexander Graf case SPRN_HID5: 83354771e62SAlexander Graf *spr_val = to_book3s(vcpu)->hid[5]; 8342191d657SAlexander Graf break; 835aacf9aa3SAlexander Graf case SPRN_CFAR: 836b0a94d4eSPaul Mackerras case SPRN_DSCR: 83754771e62SAlexander Graf *spr_val = 0; 838aacf9aa3SAlexander Graf break; 839b0a94d4eSPaul Mackerras case SPRN_PURR: 8403cd60e31SAneesh Kumar K.V /* 8413cd60e31SAneesh Kumar K.V * On exit we would have updated purr 8423cd60e31SAneesh Kumar K.V */ 8433cd60e31SAneesh Kumar K.V *spr_val = vcpu->arch.purr; 844b0a94d4eSPaul Mackerras break; 845b0a94d4eSPaul Mackerras case SPRN_SPURR: 8463cd60e31SAneesh Kumar K.V /* 8473cd60e31SAneesh Kumar K.V * On exit we would have updated spurr 8483cd60e31SAneesh Kumar K.V */ 8493cd60e31SAneesh Kumar K.V *spr_val = vcpu->arch.spurr; 850b0a94d4eSPaul Mackerras break; 8518f42ab27SAneesh Kumar K.V case SPRN_VTB: 85288b02cf9SPaul Mackerras *spr_val = to_book3s(vcpu)->vtb; 8538f42ab27SAneesh Kumar K.V break; 85406da28e7SAneesh Kumar K.V case SPRN_IC: 85506da28e7SAneesh Kumar K.V *spr_val = vcpu->arch.ic; 85606da28e7SAneesh Kumar K.V break; 8572191d657SAlexander Graf case SPRN_GQR0: 8582191d657SAlexander Graf case SPRN_GQR1: 8592191d657SAlexander Graf case SPRN_GQR2: 8602191d657SAlexander Graf case SPRN_GQR3: 8612191d657SAlexander Graf case SPRN_GQR4: 8622191d657SAlexander Graf case SPRN_GQR5: 8632191d657SAlexander Graf case SPRN_GQR6: 8642191d657SAlexander Graf case SPRN_GQR7: 86554771e62SAlexander Graf *spr_val = to_book3s(vcpu)->gqr[sprn - SPRN_GQR0]; 8662191d657SAlexander Graf break; 8678e6afa36SAlexander Graf #ifdef CONFIG_PPC_BOOK3S_64 868616dff86SAlexander Graf case SPRN_FSCR: 869616dff86SAlexander Graf *spr_val = vcpu->arch.fscr; 870616dff86SAlexander Graf break; 8712e23f544SAlexander Graf case SPRN_BESCR: 8722e23f544SAlexander Graf *spr_val = vcpu->arch.bescr; 8732e23f544SAlexander Graf break; 8742e23f544SAlexander Graf case SPRN_EBBHR: 8752e23f544SAlexander Graf *spr_val = vcpu->arch.ebbhr; 8762e23f544SAlexander Graf break; 8772e23f544SAlexander Graf case SPRN_EBBRR: 8782e23f544SAlexander Graf *spr_val = vcpu->arch.ebbrr; 8792e23f544SAlexander Graf break; 8809916d57eSAlexander Graf #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 8819916d57eSAlexander Graf case SPRN_TFHAR: 8829916d57eSAlexander Graf case SPRN_TEXASR: 8839916d57eSAlexander Graf case SPRN_TFIAR: 884533082aeSSimon Guo if (!cpu_has_feature(CPU_FTR_TM)) 885533082aeSSimon Guo break; 886533082aeSSimon Guo 887533082aeSSimon Guo if (!(kvmppc_get_msr(vcpu) & MSR_TM)) { 888533082aeSSimon Guo kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG); 889533082aeSSimon Guo emulated = EMULATE_AGAIN; 890533082aeSSimon Guo break; 891533082aeSSimon Guo } 892533082aeSSimon Guo 893533082aeSSimon Guo tm_enable(); 894533082aeSSimon Guo if (sprn == SPRN_TFHAR) 895533082aeSSimon Guo *spr_val = mfspr(SPRN_TFHAR); 896533082aeSSimon Guo else if (sprn == SPRN_TEXASR) 897533082aeSSimon Guo *spr_val = mfspr(SPRN_TEXASR); 898533082aeSSimon Guo else if (sprn == SPRN_TFIAR) 899533082aeSSimon Guo *spr_val = mfspr(SPRN_TFIAR); 900533082aeSSimon Guo tm_disable(); 9019916d57eSAlexander Graf break; 9029916d57eSAlexander Graf #endif 9032e23f544SAlexander Graf #endif 9042191d657SAlexander Graf case SPRN_THRM1: 9052191d657SAlexander Graf case SPRN_THRM2: 9062191d657SAlexander Graf case SPRN_THRM3: 9072191d657SAlexander Graf case SPRN_CTRLF: 9082191d657SAlexander Graf case SPRN_CTRLT: 9092191d657SAlexander Graf case SPRN_L2CR: 9102191d657SAlexander Graf case SPRN_MMCR0_GEKKO: 9112191d657SAlexander Graf case SPRN_MMCR1_GEKKO: 9122191d657SAlexander Graf case SPRN_PMC1_GEKKO: 9132191d657SAlexander Graf case SPRN_PMC2_GEKKO: 9142191d657SAlexander Graf case SPRN_PMC3_GEKKO: 9152191d657SAlexander Graf case SPRN_PMC4_GEKKO: 9162191d657SAlexander Graf case SPRN_WPAR_GEKKO: 917f2be6550SMihai Caraman case SPRN_MSSSR0: 918f3532028SAlexander Graf case SPRN_DABR: 919f8f6eb0dSAlexander Graf #ifdef CONFIG_PPC_BOOK3S_64 920f8f6eb0dSAlexander Graf case SPRN_MMCRS: 921f8f6eb0dSAlexander Graf case SPRN_MMCRA: 922f8f6eb0dSAlexander Graf case SPRN_MMCR0: 923f8f6eb0dSAlexander Graf case SPRN_MMCR1: 924f8f6eb0dSAlexander Graf case SPRN_MMCR2: 925fa73c3b2SThomas Huth case SPRN_UMMCR2: 926a5948fa0SAlexander Graf case SPRN_TIR: 927f8f6eb0dSAlexander Graf #endif 92854771e62SAlexander Graf *spr_val = 0; 9292191d657SAlexander Graf break; 9302191d657SAlexander Graf default: 931317a8fa3SAlexander Graf unprivileged: 932feafd13cSThomas Huth pr_info_ratelimited("KVM: invalid SPR read: %d\n", sprn); 933feafd13cSThomas Huth if (sprn & 0x10) { 934feafd13cSThomas Huth if (kvmppc_get_msr(vcpu) & MSR_PR) { 935feafd13cSThomas Huth kvmppc_core_queue_program(vcpu, SRR1_PROGPRIV); 936feafd13cSThomas Huth emulated = EMULATE_AGAIN; 937feafd13cSThomas Huth } 938feafd13cSThomas Huth } else { 939feafd13cSThomas Huth if ((kvmppc_get_msr(vcpu) & MSR_PR) || sprn == 0 || 940feafd13cSThomas Huth sprn == 4 || sprn == 5 || sprn == 6) { 941feafd13cSThomas Huth kvmppc_core_queue_program(vcpu, SRR1_PROGILL); 942feafd13cSThomas Huth emulated = EMULATE_AGAIN; 943feafd13cSThomas Huth } 944feafd13cSThomas Huth } 945feafd13cSThomas Huth 9462191d657SAlexander Graf break; 9472191d657SAlexander Graf } 9482191d657SAlexander Graf 9492191d657SAlexander Graf return emulated; 9502191d657SAlexander Graf } 9512191d657SAlexander Graf 9522191d657SAlexander Graf u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst) 9532191d657SAlexander Graf { 954ddca156aSAneesh Kumar K.V return make_dsisr(inst); 9552191d657SAlexander Graf } 9562191d657SAlexander Graf 9572191d657SAlexander Graf ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst) 9582191d657SAlexander Graf { 9597310f3a5SAneesh Kumar K.V #ifdef CONFIG_PPC_BOOK3S_64 9607310f3a5SAneesh Kumar K.V /* 9617310f3a5SAneesh Kumar K.V * Linux's fix_alignment() assumes that DAR is valid, so can we 9627310f3a5SAneesh Kumar K.V */ 9637310f3a5SAneesh Kumar K.V return vcpu->arch.fault_dar; 9647310f3a5SAneesh Kumar K.V #else 9652191d657SAlexander Graf ulong dar = 0; 966c46dc9a8SAlexander Graf ulong ra = get_ra(inst); 967c46dc9a8SAlexander Graf ulong rb = get_rb(inst); 9682191d657SAlexander Graf 9692191d657SAlexander Graf switch (get_op(inst)) { 9702191d657SAlexander Graf case OP_LFS: 9712191d657SAlexander Graf case OP_LFD: 9722191d657SAlexander Graf case OP_STFD: 9732191d657SAlexander Graf case OP_STFS: 9742191d657SAlexander Graf if (ra) 9752191d657SAlexander Graf dar = kvmppc_get_gpr(vcpu, ra); 9762191d657SAlexander Graf dar += (s32)((s16)inst); 9772191d657SAlexander Graf break; 9782191d657SAlexander Graf case 31: 9792191d657SAlexander Graf if (ra) 9802191d657SAlexander Graf dar = kvmppc_get_gpr(vcpu, ra); 981c46dc9a8SAlexander Graf dar += kvmppc_get_gpr(vcpu, rb); 9822191d657SAlexander Graf break; 9832191d657SAlexander Graf default: 9842191d657SAlexander Graf printk(KERN_INFO "KVM: Unaligned instruction 0x%x\n", inst); 9852191d657SAlexander Graf break; 9862191d657SAlexander Graf } 9872191d657SAlexander Graf 9882191d657SAlexander Graf return dar; 9897310f3a5SAneesh Kumar K.V #endif 9902191d657SAlexander Graf } 991