1 /* 2 * Copyright (C) 2008 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 78 switch (sprn) { 79 case SPRN_PID: 80 vcpu_e500->pid[0] = vcpu->arch.shadow_pid = 81 vcpu->arch.pid = vcpu->arch.gpr[rs]; 82 break; 83 case SPRN_PID1: 84 vcpu_e500->pid[1] = vcpu->arch.gpr[rs]; break; 85 case SPRN_PID2: 86 vcpu_e500->pid[2] = vcpu->arch.gpr[rs]; break; 87 case SPRN_MAS0: 88 vcpu_e500->mas0 = vcpu->arch.gpr[rs]; break; 89 case SPRN_MAS1: 90 vcpu_e500->mas1 = vcpu->arch.gpr[rs]; break; 91 case SPRN_MAS2: 92 vcpu_e500->mas2 = vcpu->arch.gpr[rs]; break; 93 case SPRN_MAS3: 94 vcpu_e500->mas3 = vcpu->arch.gpr[rs]; break; 95 case SPRN_MAS4: 96 vcpu_e500->mas4 = vcpu->arch.gpr[rs]; break; 97 case SPRN_MAS6: 98 vcpu_e500->mas6 = vcpu->arch.gpr[rs]; break; 99 case SPRN_MAS7: 100 vcpu_e500->mas7 = vcpu->arch.gpr[rs]; break; 101 case SPRN_L1CSR1: 102 vcpu_e500->l1csr1 = vcpu->arch.gpr[rs]; break; 103 case SPRN_HID0: 104 vcpu_e500->hid0 = vcpu->arch.gpr[rs]; break; 105 case SPRN_HID1: 106 vcpu_e500->hid1 = vcpu->arch.gpr[rs]; break; 107 108 case SPRN_MMUCSR0: 109 emulated = kvmppc_e500_emul_mt_mmucsr0(vcpu_e500, 110 vcpu->arch.gpr[rs]); 111 break; 112 113 /* extra exceptions */ 114 case SPRN_IVOR32: 115 vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = vcpu->arch.gpr[rs]; 116 break; 117 case SPRN_IVOR33: 118 vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] = vcpu->arch.gpr[rs]; 119 break; 120 case SPRN_IVOR34: 121 vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = vcpu->arch.gpr[rs]; 122 break; 123 case SPRN_IVOR35: 124 vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = vcpu->arch.gpr[rs]; 125 break; 126 127 default: 128 emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, rs); 129 } 130 131 return emulated; 132 } 133 134 int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) 135 { 136 struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); 137 int emulated = EMULATE_DONE; 138 139 switch (sprn) { 140 case SPRN_PID: 141 vcpu->arch.gpr[rt] = vcpu_e500->pid[0]; break; 142 case SPRN_PID1: 143 vcpu->arch.gpr[rt] = vcpu_e500->pid[1]; break; 144 case SPRN_PID2: 145 vcpu->arch.gpr[rt] = vcpu_e500->pid[2]; break; 146 case SPRN_MAS0: 147 vcpu->arch.gpr[rt] = vcpu_e500->mas0; break; 148 case SPRN_MAS1: 149 vcpu->arch.gpr[rt] = vcpu_e500->mas1; break; 150 case SPRN_MAS2: 151 vcpu->arch.gpr[rt] = vcpu_e500->mas2; break; 152 case SPRN_MAS3: 153 vcpu->arch.gpr[rt] = vcpu_e500->mas3; break; 154 case SPRN_MAS4: 155 vcpu->arch.gpr[rt] = vcpu_e500->mas4; break; 156 case SPRN_MAS6: 157 vcpu->arch.gpr[rt] = vcpu_e500->mas6; break; 158 case SPRN_MAS7: 159 vcpu->arch.gpr[rt] = vcpu_e500->mas7; break; 160 161 case SPRN_TLB0CFG: 162 vcpu->arch.gpr[rt] = mfspr(SPRN_TLB0CFG); 163 vcpu->arch.gpr[rt] &= ~0xfffUL; 164 vcpu->arch.gpr[rt] |= vcpu_e500->guest_tlb_size[0]; 165 break; 166 167 case SPRN_TLB1CFG: 168 vcpu->arch.gpr[rt] = mfspr(SPRN_TLB1CFG); 169 vcpu->arch.gpr[rt] &= ~0xfffUL; 170 vcpu->arch.gpr[rt] |= vcpu_e500->guest_tlb_size[1]; 171 break; 172 173 case SPRN_L1CSR1: 174 vcpu->arch.gpr[rt] = vcpu_e500->l1csr1; break; 175 case SPRN_HID0: 176 vcpu->arch.gpr[rt] = vcpu_e500->hid0; break; 177 case SPRN_HID1: 178 vcpu->arch.gpr[rt] = vcpu_e500->hid1; break; 179 180 case SPRN_MMUCSR0: 181 vcpu->arch.gpr[rt] = 0; break; 182 183 case SPRN_MMUCFG: 184 vcpu->arch.gpr[rt] = mfspr(SPRN_MMUCFG); break; 185 186 /* extra exceptions */ 187 case SPRN_IVOR32: 188 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL]; 189 break; 190 case SPRN_IVOR33: 191 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA]; 192 break; 193 case SPRN_IVOR34: 194 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND]; 195 break; 196 case SPRN_IVOR35: 197 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR]; 198 break; 199 default: 200 emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, rt); 201 } 202 203 return emulated; 204 } 205 206