1 /* 2 * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved. 3 * 4 * Author: Yu Liu, <yu.liu@freescale.com> 5 * 6 * Description: 7 * This file is derived from arch/powerpc/kvm/44x_emulate.c, 8 * by Hollis Blanchard <hollisb@us.ibm.com>. 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License, version 2, as 12 * published by the Free Software Foundation. 13 */ 14 15 #include <asm/kvm_ppc.h> 16 #include <asm/disassemble.h> 17 #include <asm/dbell.h> 18 19 #include "booke.h" 20 #include "e500.h" 21 22 #define XOP_MSGSND 206 23 #define XOP_MSGCLR 238 24 #define XOP_TLBIVAX 786 25 #define XOP_TLBSX 914 26 #define XOP_TLBRE 946 27 #define XOP_TLBWE 978 28 #define XOP_TLBILX 18 29 30 #ifdef CONFIG_KVM_E500MC 31 static int dbell2prio(ulong param) 32 { 33 int msg = param & PPC_DBELL_TYPE_MASK; 34 int prio = -1; 35 36 switch (msg) { 37 case PPC_DBELL_TYPE(PPC_DBELL): 38 prio = BOOKE_IRQPRIO_DBELL; 39 break; 40 case PPC_DBELL_TYPE(PPC_DBELL_CRIT): 41 prio = BOOKE_IRQPRIO_DBELL_CRIT; 42 break; 43 default: 44 break; 45 } 46 47 return prio; 48 } 49 50 static int kvmppc_e500_emul_msgclr(struct kvm_vcpu *vcpu, int rb) 51 { 52 ulong param = vcpu->arch.gpr[rb]; 53 int prio = dbell2prio(param); 54 55 if (prio < 0) 56 return EMULATE_FAIL; 57 58 clear_bit(prio, &vcpu->arch.pending_exceptions); 59 return EMULATE_DONE; 60 } 61 62 static int kvmppc_e500_emul_msgsnd(struct kvm_vcpu *vcpu, int rb) 63 { 64 ulong param = vcpu->arch.gpr[rb]; 65 int prio = dbell2prio(rb); 66 int pir = param & PPC_DBELL_PIR_MASK; 67 int i; 68 struct kvm_vcpu *cvcpu; 69 70 if (prio < 0) 71 return EMULATE_FAIL; 72 73 kvm_for_each_vcpu(i, cvcpu, vcpu->kvm) { 74 int cpir = cvcpu->arch.shared->pir; 75 if ((param & PPC_DBELL_MSG_BRDCAST) || (cpir == pir)) { 76 set_bit(prio, &cvcpu->arch.pending_exceptions); 77 kvm_vcpu_kick(cvcpu); 78 } 79 } 80 81 return EMULATE_DONE; 82 } 83 #endif 84 85 int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, 86 unsigned int inst, int *advance) 87 { 88 int emulated = EMULATE_DONE; 89 int ra = get_ra(inst); 90 int rb = get_rb(inst); 91 int rt = get_rt(inst); 92 gva_t ea; 93 94 switch (get_op(inst)) { 95 case 31: 96 switch (get_xop(inst)) { 97 98 #ifdef CONFIG_KVM_E500MC 99 case XOP_MSGSND: 100 emulated = kvmppc_e500_emul_msgsnd(vcpu, rb); 101 break; 102 103 case XOP_MSGCLR: 104 emulated = kvmppc_e500_emul_msgclr(vcpu, rb); 105 break; 106 #endif 107 108 case XOP_TLBRE: 109 emulated = kvmppc_e500_emul_tlbre(vcpu); 110 break; 111 112 case XOP_TLBWE: 113 emulated = kvmppc_e500_emul_tlbwe(vcpu); 114 break; 115 116 case XOP_TLBSX: 117 ea = kvmppc_get_ea_indexed(vcpu, ra, rb); 118 emulated = kvmppc_e500_emul_tlbsx(vcpu, ea); 119 break; 120 121 case XOP_TLBILX: { 122 int type = rt & 0x3; 123 ea = kvmppc_get_ea_indexed(vcpu, ra, rb); 124 emulated = kvmppc_e500_emul_tlbilx(vcpu, type, ea); 125 break; 126 } 127 128 case XOP_TLBIVAX: 129 ea = kvmppc_get_ea_indexed(vcpu, ra, rb); 130 emulated = kvmppc_e500_emul_tlbivax(vcpu, ea); 131 break; 132 133 default: 134 emulated = EMULATE_FAIL; 135 } 136 137 break; 138 139 default: 140 emulated = EMULATE_FAIL; 141 } 142 143 if (emulated == EMULATE_FAIL) 144 emulated = kvmppc_booke_emulate_op(run, vcpu, inst, advance); 145 146 return emulated; 147 } 148 149 int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) 150 { 151 struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); 152 int emulated = EMULATE_DONE; 153 154 switch (sprn) { 155 #ifndef CONFIG_KVM_BOOKE_HV 156 case SPRN_PID: 157 kvmppc_set_pid(vcpu, spr_val); 158 break; 159 case SPRN_PID1: 160 if (spr_val != 0) 161 return EMULATE_FAIL; 162 vcpu_e500->pid[1] = spr_val; 163 break; 164 case SPRN_PID2: 165 if (spr_val != 0) 166 return EMULATE_FAIL; 167 vcpu_e500->pid[2] = spr_val; 168 break; 169 case SPRN_MAS0: 170 vcpu->arch.shared->mas0 = spr_val; 171 break; 172 case SPRN_MAS1: 173 vcpu->arch.shared->mas1 = spr_val; 174 break; 175 case SPRN_MAS2: 176 vcpu->arch.shared->mas2 = spr_val; 177 break; 178 case SPRN_MAS3: 179 vcpu->arch.shared->mas7_3 &= ~(u64)0xffffffff; 180 vcpu->arch.shared->mas7_3 |= spr_val; 181 break; 182 case SPRN_MAS4: 183 vcpu->arch.shared->mas4 = spr_val; 184 break; 185 case SPRN_MAS6: 186 vcpu->arch.shared->mas6 = spr_val; 187 break; 188 case SPRN_MAS7: 189 vcpu->arch.shared->mas7_3 &= (u64)0xffffffff; 190 vcpu->arch.shared->mas7_3 |= (u64)spr_val << 32; 191 break; 192 #endif 193 case SPRN_L1CSR0: 194 vcpu_e500->l1csr0 = spr_val; 195 vcpu_e500->l1csr0 &= ~(L1CSR0_DCFI | L1CSR0_CLFC); 196 break; 197 case SPRN_L1CSR1: 198 vcpu_e500->l1csr1 = spr_val; 199 break; 200 case SPRN_HID0: 201 vcpu_e500->hid0 = spr_val; 202 break; 203 case SPRN_HID1: 204 vcpu_e500->hid1 = spr_val; 205 break; 206 207 case SPRN_MMUCSR0: 208 emulated = kvmppc_e500_emul_mt_mmucsr0(vcpu_e500, 209 spr_val); 210 break; 211 212 /* extra exceptions */ 213 case SPRN_IVOR32: 214 vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val; 215 break; 216 case SPRN_IVOR33: 217 vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] = spr_val; 218 break; 219 case SPRN_IVOR34: 220 vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = spr_val; 221 break; 222 case SPRN_IVOR35: 223 vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = spr_val; 224 break; 225 #ifdef CONFIG_KVM_BOOKE_HV 226 case SPRN_IVOR36: 227 vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL] = spr_val; 228 break; 229 case SPRN_IVOR37: 230 vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL_CRIT] = spr_val; 231 break; 232 #endif 233 default: 234 emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, spr_val); 235 } 236 237 return emulated; 238 } 239 240 int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val) 241 { 242 struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); 243 int emulated = EMULATE_DONE; 244 245 switch (sprn) { 246 #ifndef CONFIG_KVM_BOOKE_HV 247 case SPRN_PID: 248 *spr_val = vcpu_e500->pid[0]; 249 break; 250 case SPRN_PID1: 251 *spr_val = vcpu_e500->pid[1]; 252 break; 253 case SPRN_PID2: 254 *spr_val = vcpu_e500->pid[2]; 255 break; 256 case SPRN_MAS0: 257 *spr_val = vcpu->arch.shared->mas0; 258 break; 259 case SPRN_MAS1: 260 *spr_val = vcpu->arch.shared->mas1; 261 break; 262 case SPRN_MAS2: 263 *spr_val = vcpu->arch.shared->mas2; 264 break; 265 case SPRN_MAS3: 266 *spr_val = (u32)vcpu->arch.shared->mas7_3; 267 break; 268 case SPRN_MAS4: 269 *spr_val = vcpu->arch.shared->mas4; 270 break; 271 case SPRN_MAS6: 272 *spr_val = vcpu->arch.shared->mas6; 273 break; 274 case SPRN_MAS7: 275 *spr_val = vcpu->arch.shared->mas7_3 >> 32; 276 break; 277 #endif 278 case SPRN_DECAR: 279 *spr_val = vcpu->arch.decar; 280 break; 281 case SPRN_TLB0CFG: 282 *spr_val = vcpu->arch.tlbcfg[0]; 283 break; 284 case SPRN_TLB1CFG: 285 *spr_val = vcpu->arch.tlbcfg[1]; 286 break; 287 case SPRN_TLB0PS: 288 if (!has_feature(vcpu, VCPU_FTR_MMU_V2)) 289 return EMULATE_FAIL; 290 *spr_val = vcpu->arch.tlbps[0]; 291 break; 292 case SPRN_TLB1PS: 293 if (!has_feature(vcpu, VCPU_FTR_MMU_V2)) 294 return EMULATE_FAIL; 295 *spr_val = vcpu->arch.tlbps[1]; 296 break; 297 case SPRN_L1CSR0: 298 *spr_val = vcpu_e500->l1csr0; 299 break; 300 case SPRN_L1CSR1: 301 *spr_val = vcpu_e500->l1csr1; 302 break; 303 case SPRN_HID0: 304 *spr_val = vcpu_e500->hid0; 305 break; 306 case SPRN_HID1: 307 *spr_val = vcpu_e500->hid1; 308 break; 309 case SPRN_SVR: 310 *spr_val = vcpu_e500->svr; 311 break; 312 313 case SPRN_MMUCSR0: 314 *spr_val = 0; 315 break; 316 317 case SPRN_MMUCFG: 318 *spr_val = vcpu->arch.mmucfg; 319 break; 320 case SPRN_EPTCFG: 321 if (!has_feature(vcpu, VCPU_FTR_MMU_V2)) 322 return EMULATE_FAIL; 323 /* 324 * Legacy Linux guests access EPTCFG register even if the E.PT 325 * category is disabled in the VM. Give them a chance to live. 326 */ 327 *spr_val = vcpu->arch.eptcfg; 328 break; 329 330 /* extra exceptions */ 331 case SPRN_IVOR32: 332 *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL]; 333 break; 334 case SPRN_IVOR33: 335 *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA]; 336 break; 337 case SPRN_IVOR34: 338 *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND]; 339 break; 340 case SPRN_IVOR35: 341 *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR]; 342 break; 343 #ifdef CONFIG_KVM_BOOKE_HV 344 case SPRN_IVOR36: 345 *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL]; 346 break; 347 case SPRN_IVOR37: 348 *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL_CRIT]; 349 break; 350 #endif 351 default: 352 emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, spr_val); 353 } 354 355 return emulated; 356 } 357 358