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/kvm_e500.h> 18 19 #include "booke.h" 20 #include "e500_tlb.h" 21 22 #define XOP_TLBIVAX 786 23 #define XOP_TLBSX 914 24 #define XOP_TLBRE 946 25 #define XOP_TLBWE 978 26 27 int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, 28 unsigned int inst, int *advance) 29 { 30 int emulated = EMULATE_DONE; 31 int ra; 32 int rb; 33 34 switch (get_op(inst)) { 35 case 31: 36 switch (get_xop(inst)) { 37 38 case XOP_TLBRE: 39 emulated = kvmppc_e500_emul_tlbre(vcpu); 40 break; 41 42 case XOP_TLBWE: 43 emulated = kvmppc_e500_emul_tlbwe(vcpu); 44 break; 45 46 case XOP_TLBSX: 47 rb = get_rb(inst); 48 emulated = kvmppc_e500_emul_tlbsx(vcpu,rb); 49 break; 50 51 case XOP_TLBIVAX: 52 ra = get_ra(inst); 53 rb = get_rb(inst); 54 emulated = kvmppc_e500_emul_tlbivax(vcpu, ra, rb); 55 break; 56 57 default: 58 emulated = EMULATE_FAIL; 59 } 60 61 break; 62 63 default: 64 emulated = EMULATE_FAIL; 65 } 66 67 if (emulated == EMULATE_FAIL) 68 emulated = kvmppc_booke_emulate_op(run, vcpu, inst, advance); 69 70 return emulated; 71 } 72 73 int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) 74 { 75 struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); 76 int emulated = EMULATE_DONE; 77 ulong spr_val = kvmppc_get_gpr(vcpu, rs); 78 79 switch (sprn) { 80 case SPRN_PID: 81 kvmppc_set_pid(vcpu, spr_val); 82 break; 83 case SPRN_PID1: 84 if (spr_val != 0) 85 return EMULATE_FAIL; 86 vcpu_e500->pid[1] = spr_val; break; 87 case SPRN_PID2: 88 if (spr_val != 0) 89 return EMULATE_FAIL; 90 vcpu_e500->pid[2] = spr_val; break; 91 case SPRN_MAS0: 92 vcpu->arch.shared->mas0 = spr_val; break; 93 case SPRN_MAS1: 94 vcpu->arch.shared->mas1 = spr_val; break; 95 case SPRN_MAS2: 96 vcpu->arch.shared->mas2 = spr_val; break; 97 case SPRN_MAS3: 98 vcpu->arch.shared->mas7_3 &= ~(u64)0xffffffff; 99 vcpu->arch.shared->mas7_3 |= spr_val; 100 break; 101 case SPRN_MAS4: 102 vcpu->arch.shared->mas4 = spr_val; break; 103 case SPRN_MAS6: 104 vcpu->arch.shared->mas6 = spr_val; break; 105 case SPRN_MAS7: 106 vcpu->arch.shared->mas7_3 &= (u64)0xffffffff; 107 vcpu->arch.shared->mas7_3 |= (u64)spr_val << 32; 108 break; 109 case SPRN_L1CSR0: 110 vcpu_e500->l1csr0 = spr_val; 111 vcpu_e500->l1csr0 &= ~(L1CSR0_DCFI | L1CSR0_CLFC); 112 break; 113 case SPRN_L1CSR1: 114 vcpu_e500->l1csr1 = spr_val; break; 115 case SPRN_HID0: 116 vcpu_e500->hid0 = spr_val; break; 117 case SPRN_HID1: 118 vcpu_e500->hid1 = spr_val; break; 119 120 case SPRN_MMUCSR0: 121 emulated = kvmppc_e500_emul_mt_mmucsr0(vcpu_e500, 122 spr_val); 123 break; 124 125 /* extra exceptions */ 126 case SPRN_IVOR32: 127 vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val; 128 break; 129 case SPRN_IVOR33: 130 vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] = spr_val; 131 break; 132 case SPRN_IVOR34: 133 vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = spr_val; 134 break; 135 case SPRN_IVOR35: 136 vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = spr_val; 137 break; 138 139 default: 140 emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, rs); 141 } 142 143 return emulated; 144 } 145 146 int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) 147 { 148 struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); 149 int emulated = EMULATE_DONE; 150 unsigned long val; 151 152 switch (sprn) { 153 case SPRN_PID: 154 kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[0]); break; 155 case SPRN_PID1: 156 kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[1]); break; 157 case SPRN_PID2: 158 kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[2]); break; 159 case SPRN_MAS0: 160 kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas0); break; 161 case SPRN_MAS1: 162 kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas1); break; 163 case SPRN_MAS2: 164 kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas2); break; 165 case SPRN_MAS3: 166 val = (u32)vcpu->arch.shared->mas7_3; 167 kvmppc_set_gpr(vcpu, rt, val); 168 break; 169 case SPRN_MAS4: 170 kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas4); break; 171 case SPRN_MAS6: 172 kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas6); break; 173 case SPRN_MAS7: 174 val = vcpu->arch.shared->mas7_3 >> 32; 175 kvmppc_set_gpr(vcpu, rt, val); 176 break; 177 case SPRN_TLB0CFG: 178 kvmppc_set_gpr(vcpu, rt, vcpu_e500->tlb0cfg); break; 179 case SPRN_TLB1CFG: 180 kvmppc_set_gpr(vcpu, rt, vcpu_e500->tlb1cfg); break; 181 case SPRN_L1CSR0: 182 kvmppc_set_gpr(vcpu, rt, vcpu_e500->l1csr0); break; 183 case SPRN_L1CSR1: 184 kvmppc_set_gpr(vcpu, rt, vcpu_e500->l1csr1); break; 185 case SPRN_HID0: 186 kvmppc_set_gpr(vcpu, rt, vcpu_e500->hid0); break; 187 case SPRN_HID1: 188 kvmppc_set_gpr(vcpu, rt, vcpu_e500->hid1); break; 189 case SPRN_SVR: 190 kvmppc_set_gpr(vcpu, rt, vcpu_e500->svr); break; 191 192 case SPRN_MMUCSR0: 193 kvmppc_set_gpr(vcpu, rt, 0); break; 194 195 case SPRN_MMUCFG: 196 kvmppc_set_gpr(vcpu, rt, mfspr(SPRN_MMUCFG)); break; 197 198 /* extra exceptions */ 199 case SPRN_IVOR32: 200 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL]); 201 break; 202 case SPRN_IVOR33: 203 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA]); 204 break; 205 case SPRN_IVOR34: 206 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND]); 207 break; 208 case SPRN_IVOR35: 209 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR]); 210 break; 211 default: 212 emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, rt); 213 } 214 215 return emulated; 216 } 217 218