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 * 17 * Authors: Hollis Blanchard <hollisb@us.ibm.com> 18 */ 19 20 #include <linux/kvm_host.h> 21 #include <asm/disassemble.h> 22 23 #include "booke.h" 24 25 #define OP_19_XOP_RFI 50 26 27 #define OP_31_XOP_MFMSR 83 28 #define OP_31_XOP_WRTEE 131 29 #define OP_31_XOP_MTMSR 146 30 #define OP_31_XOP_WRTEEI 163 31 32 static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu) 33 { 34 vcpu->arch.pc = vcpu->arch.srr0; 35 kvmppc_set_msr(vcpu, vcpu->arch.srr1); 36 } 37 38 int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, 39 unsigned int inst, int *advance) 40 { 41 int emulated = EMULATE_DONE; 42 int rs; 43 int rt; 44 45 switch (get_op(inst)) { 46 case 19: 47 switch (get_xop(inst)) { 48 case OP_19_XOP_RFI: 49 kvmppc_emul_rfi(vcpu); 50 kvmppc_set_exit_type(vcpu, EMULATED_RFI_EXITS); 51 *advance = 0; 52 break; 53 54 default: 55 emulated = EMULATE_FAIL; 56 break; 57 } 58 break; 59 60 case 31: 61 switch (get_xop(inst)) { 62 63 case OP_31_XOP_MFMSR: 64 rt = get_rt(inst); 65 vcpu->arch.gpr[rt] = vcpu->arch.msr; 66 kvmppc_set_exit_type(vcpu, EMULATED_MFMSR_EXITS); 67 break; 68 69 case OP_31_XOP_MTMSR: 70 rs = get_rs(inst); 71 kvmppc_set_exit_type(vcpu, EMULATED_MTMSR_EXITS); 72 kvmppc_set_msr(vcpu, vcpu->arch.gpr[rs]); 73 break; 74 75 case OP_31_XOP_WRTEE: 76 rs = get_rs(inst); 77 vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE) 78 | (vcpu->arch.gpr[rs] & MSR_EE); 79 kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS); 80 break; 81 82 case OP_31_XOP_WRTEEI: 83 vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE) 84 | (inst & MSR_EE); 85 kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS); 86 break; 87 88 default: 89 emulated = EMULATE_FAIL; 90 } 91 92 break; 93 94 default: 95 emulated = EMULATE_FAIL; 96 } 97 98 return emulated; 99 } 100 101 int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) 102 { 103 int emulated = EMULATE_DONE; 104 105 switch (sprn) { 106 case SPRN_DEAR: 107 vcpu->arch.dear = vcpu->arch.gpr[rs]; break; 108 case SPRN_ESR: 109 vcpu->arch.esr = vcpu->arch.gpr[rs]; break; 110 case SPRN_DBCR0: 111 vcpu->arch.dbcr0 = vcpu->arch.gpr[rs]; break; 112 case SPRN_DBCR1: 113 vcpu->arch.dbcr1 = vcpu->arch.gpr[rs]; break; 114 case SPRN_DBSR: 115 vcpu->arch.dbsr &= ~vcpu->arch.gpr[rs]; break; 116 case SPRN_TSR: 117 vcpu->arch.tsr &= ~vcpu->arch.gpr[rs]; break; 118 case SPRN_TCR: 119 vcpu->arch.tcr = vcpu->arch.gpr[rs]; 120 kvmppc_emulate_dec(vcpu); 121 break; 122 123 /* Note: SPRG4-7 are user-readable. These values are 124 * loaded into the real SPRGs when resuming the 125 * guest. */ 126 case SPRN_SPRG4: 127 vcpu->arch.sprg4 = vcpu->arch.gpr[rs]; break; 128 case SPRN_SPRG5: 129 vcpu->arch.sprg5 = vcpu->arch.gpr[rs]; break; 130 case SPRN_SPRG6: 131 vcpu->arch.sprg6 = vcpu->arch.gpr[rs]; break; 132 case SPRN_SPRG7: 133 vcpu->arch.sprg7 = vcpu->arch.gpr[rs]; break; 134 135 case SPRN_IVPR: 136 vcpu->arch.ivpr = vcpu->arch.gpr[rs]; 137 break; 138 case SPRN_IVOR0: 139 vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] = vcpu->arch.gpr[rs]; 140 break; 141 case SPRN_IVOR1: 142 vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK] = vcpu->arch.gpr[rs]; 143 break; 144 case SPRN_IVOR2: 145 vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE] = vcpu->arch.gpr[rs]; 146 break; 147 case SPRN_IVOR3: 148 vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE] = vcpu->arch.gpr[rs]; 149 break; 150 case SPRN_IVOR4: 151 vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL] = vcpu->arch.gpr[rs]; 152 break; 153 case SPRN_IVOR5: 154 vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT] = vcpu->arch.gpr[rs]; 155 break; 156 case SPRN_IVOR6: 157 vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM] = vcpu->arch.gpr[rs]; 158 break; 159 case SPRN_IVOR7: 160 vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL] = vcpu->arch.gpr[rs]; 161 break; 162 case SPRN_IVOR8: 163 vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL] = vcpu->arch.gpr[rs]; 164 break; 165 case SPRN_IVOR9: 166 vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL] = vcpu->arch.gpr[rs]; 167 break; 168 case SPRN_IVOR10: 169 vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER] = vcpu->arch.gpr[rs]; 170 break; 171 case SPRN_IVOR11: 172 vcpu->arch.ivor[BOOKE_IRQPRIO_FIT] = vcpu->arch.gpr[rs]; 173 break; 174 case SPRN_IVOR12: 175 vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG] = vcpu->arch.gpr[rs]; 176 break; 177 case SPRN_IVOR13: 178 vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS] = vcpu->arch.gpr[rs]; 179 break; 180 case SPRN_IVOR14: 181 vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS] = vcpu->arch.gpr[rs]; 182 break; 183 case SPRN_IVOR15: 184 vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = vcpu->arch.gpr[rs]; 185 break; 186 187 default: 188 emulated = EMULATE_FAIL; 189 } 190 191 return emulated; 192 } 193 194 int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) 195 { 196 int emulated = EMULATE_DONE; 197 198 switch (sprn) { 199 case SPRN_IVPR: 200 vcpu->arch.gpr[rt] = vcpu->arch.ivpr; break; 201 case SPRN_DEAR: 202 vcpu->arch.gpr[rt] = vcpu->arch.dear; break; 203 case SPRN_ESR: 204 vcpu->arch.gpr[rt] = vcpu->arch.esr; break; 205 case SPRN_DBCR0: 206 vcpu->arch.gpr[rt] = vcpu->arch.dbcr0; break; 207 case SPRN_DBCR1: 208 vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break; 209 case SPRN_DBSR: 210 vcpu->arch.gpr[rt] = vcpu->arch.dbsr; break; 211 212 case SPRN_IVOR0: 213 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL]; 214 break; 215 case SPRN_IVOR1: 216 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK]; 217 break; 218 case SPRN_IVOR2: 219 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE]; 220 break; 221 case SPRN_IVOR3: 222 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE]; 223 break; 224 case SPRN_IVOR4: 225 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL]; 226 break; 227 case SPRN_IVOR5: 228 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT]; 229 break; 230 case SPRN_IVOR6: 231 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM]; 232 break; 233 case SPRN_IVOR7: 234 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL]; 235 break; 236 case SPRN_IVOR8: 237 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL]; 238 break; 239 case SPRN_IVOR9: 240 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL]; 241 break; 242 case SPRN_IVOR10: 243 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER]; 244 break; 245 case SPRN_IVOR11: 246 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FIT]; 247 break; 248 case SPRN_IVOR12: 249 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG]; 250 break; 251 case SPRN_IVOR13: 252 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS]; 253 break; 254 case SPRN_IVOR14: 255 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS]; 256 break; 257 case SPRN_IVOR15: 258 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG]; 259 break; 260 261 default: 262 emulated = EMULATE_FAIL; 263 } 264 265 return emulated; 266 } 267