1 /* 2 * This program is free software; you can redistribute it and/or modify 3 * it under the terms of the GNU General Public License, version 2, as 4 * published by the Free Software Foundation. 5 * 6 * This program is distributed in the hope that it will be useful, 7 * but WITHOUT ANY WARRANTY; without even the implied warranty of 8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 * GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License 12 * along with this program; if not, write to the Free Software 13 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 14 * 15 * Copyright IBM Corp. 2008 16 * Copyright 2011 Freescale Semiconductor, Inc. 17 * 18 * Authors: Hollis Blanchard <hollisb@us.ibm.com> 19 */ 20 21 #include <linux/kvm_host.h> 22 #include <asm/disassemble.h> 23 24 #include "booke.h" 25 26 #define OP_19_XOP_RFI 50 27 28 #define OP_31_XOP_MFMSR 83 29 #define OP_31_XOP_WRTEE 131 30 #define OP_31_XOP_MTMSR 146 31 #define OP_31_XOP_WRTEEI 163 32 33 static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu) 34 { 35 vcpu->arch.pc = vcpu->arch.shared->srr0; 36 kvmppc_set_msr(vcpu, vcpu->arch.shared->srr1); 37 } 38 39 int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, 40 unsigned int inst, int *advance) 41 { 42 int emulated = EMULATE_DONE; 43 int rs; 44 int rt; 45 46 switch (get_op(inst)) { 47 case 19: 48 switch (get_xop(inst)) { 49 case OP_19_XOP_RFI: 50 kvmppc_emul_rfi(vcpu); 51 kvmppc_set_exit_type(vcpu, EMULATED_RFI_EXITS); 52 *advance = 0; 53 break; 54 55 default: 56 emulated = EMULATE_FAIL; 57 break; 58 } 59 break; 60 61 case 31: 62 switch (get_xop(inst)) { 63 64 case OP_31_XOP_MFMSR: 65 rt = get_rt(inst); 66 kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->msr); 67 kvmppc_set_exit_type(vcpu, EMULATED_MFMSR_EXITS); 68 break; 69 70 case OP_31_XOP_MTMSR: 71 rs = get_rs(inst); 72 kvmppc_set_exit_type(vcpu, EMULATED_MTMSR_EXITS); 73 kvmppc_set_msr(vcpu, kvmppc_get_gpr(vcpu, rs)); 74 break; 75 76 case OP_31_XOP_WRTEE: 77 rs = get_rs(inst); 78 vcpu->arch.shared->msr = (vcpu->arch.shared->msr & ~MSR_EE) 79 | (kvmppc_get_gpr(vcpu, rs) & MSR_EE); 80 kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS); 81 break; 82 83 case OP_31_XOP_WRTEEI: 84 vcpu->arch.shared->msr = (vcpu->arch.shared->msr & ~MSR_EE) 85 | (inst & MSR_EE); 86 kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS); 87 break; 88 89 default: 90 emulated = EMULATE_FAIL; 91 } 92 93 break; 94 95 default: 96 emulated = EMULATE_FAIL; 97 } 98 99 return emulated; 100 } 101 102 int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) 103 { 104 int emulated = EMULATE_DONE; 105 ulong spr_val = kvmppc_get_gpr(vcpu, rs); 106 107 switch (sprn) { 108 case SPRN_DEAR: 109 vcpu->arch.shared->dar = spr_val; break; 110 case SPRN_ESR: 111 vcpu->arch.shared->esr = spr_val; break; 112 case SPRN_DBCR0: 113 vcpu->arch.dbcr0 = spr_val; break; 114 case SPRN_DBCR1: 115 vcpu->arch.dbcr1 = spr_val; break; 116 case SPRN_DBSR: 117 vcpu->arch.dbsr &= ~spr_val; break; 118 case SPRN_TSR: 119 kvmppc_clr_tsr_bits(vcpu, spr_val); 120 break; 121 case SPRN_TCR: 122 kvmppc_set_tcr(vcpu, spr_val); 123 break; 124 125 /* Note: SPRG4-7 are user-readable. These values are 126 * loaded into the real SPRGs when resuming the 127 * guest. */ 128 case SPRN_SPRG4: 129 vcpu->arch.shared->sprg4 = spr_val; break; 130 case SPRN_SPRG5: 131 vcpu->arch.shared->sprg5 = spr_val; break; 132 case SPRN_SPRG6: 133 vcpu->arch.shared->sprg6 = spr_val; break; 134 case SPRN_SPRG7: 135 vcpu->arch.shared->sprg7 = spr_val; break; 136 137 case SPRN_IVPR: 138 vcpu->arch.ivpr = spr_val; 139 break; 140 case SPRN_IVOR0: 141 vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] = spr_val; 142 break; 143 case SPRN_IVOR1: 144 vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK] = spr_val; 145 break; 146 case SPRN_IVOR2: 147 vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE] = spr_val; 148 break; 149 case SPRN_IVOR3: 150 vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE] = spr_val; 151 break; 152 case SPRN_IVOR4: 153 vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL] = spr_val; 154 break; 155 case SPRN_IVOR5: 156 vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT] = spr_val; 157 break; 158 case SPRN_IVOR6: 159 vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM] = spr_val; 160 break; 161 case SPRN_IVOR7: 162 vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL] = spr_val; 163 break; 164 case SPRN_IVOR8: 165 vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL] = spr_val; 166 break; 167 case SPRN_IVOR9: 168 vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL] = spr_val; 169 break; 170 case SPRN_IVOR10: 171 vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER] = spr_val; 172 break; 173 case SPRN_IVOR11: 174 vcpu->arch.ivor[BOOKE_IRQPRIO_FIT] = spr_val; 175 break; 176 case SPRN_IVOR12: 177 vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG] = spr_val; 178 break; 179 case SPRN_IVOR13: 180 vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS] = spr_val; 181 break; 182 case SPRN_IVOR14: 183 vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS] = spr_val; 184 break; 185 case SPRN_IVOR15: 186 vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = spr_val; 187 break; 188 189 default: 190 emulated = EMULATE_FAIL; 191 } 192 193 return emulated; 194 } 195 196 int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) 197 { 198 int emulated = EMULATE_DONE; 199 200 switch (sprn) { 201 case SPRN_IVPR: 202 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivpr); break; 203 case SPRN_DEAR: 204 kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->dar); break; 205 case SPRN_ESR: 206 kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->esr); break; 207 case SPRN_DBCR0: 208 kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbcr0); break; 209 case SPRN_DBCR1: 210 kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbcr1); break; 211 case SPRN_DBSR: 212 kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbsr); break; 213 case SPRN_TSR: 214 kvmppc_set_gpr(vcpu, rt, vcpu->arch.tsr); break; 215 case SPRN_TCR: 216 kvmppc_set_gpr(vcpu, rt, vcpu->arch.tcr); break; 217 218 case SPRN_IVOR0: 219 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL]); 220 break; 221 case SPRN_IVOR1: 222 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK]); 223 break; 224 case SPRN_IVOR2: 225 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE]); 226 break; 227 case SPRN_IVOR3: 228 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE]); 229 break; 230 case SPRN_IVOR4: 231 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL]); 232 break; 233 case SPRN_IVOR5: 234 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT]); 235 break; 236 case SPRN_IVOR6: 237 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM]); 238 break; 239 case SPRN_IVOR7: 240 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL]); 241 break; 242 case SPRN_IVOR8: 243 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL]); 244 break; 245 case SPRN_IVOR9: 246 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL]); 247 break; 248 case SPRN_IVOR10: 249 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER]); 250 break; 251 case SPRN_IVOR11: 252 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_FIT]); 253 break; 254 case SPRN_IVOR12: 255 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG]); 256 break; 257 case SPRN_IVOR13: 258 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS]); 259 break; 260 case SPRN_IVOR14: 261 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS]); 262 break; 263 case SPRN_IVOR15: 264 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG]); 265 break; 266 267 default: 268 emulated = EMULATE_FAIL; 269 } 270 271 return emulated; 272 } 273