2 * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved.
4 * Author: Yu Liu, <yu.liu@freescale.com>
7 * This file is derived from arch/powerpc/kvm/44x_emulate.c,
8 * by Hollis Blanchard <hollisb@us.ibm.com>.
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.
15 #include <asm/kvm_ppc.h>
16 #include <asm/disassemble.h>
21 #define XOP_TLBIVAX 786
27 int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
28 unsigned int inst, int *advance)
30 int emulated = EMULATE_DONE;
35 switch (get_op(inst)) {
37 switch (get_xop(inst)) {
40 emulated = kvmppc_e500_emul_tlbre(vcpu);
44 emulated = kvmppc_e500_emul_tlbwe(vcpu);
49 emulated = kvmppc_e500_emul_tlbsx(vcpu,rb);
56 emulated = kvmppc_e500_emul_tlbilx(vcpu, rt, ra, rb);
62 emulated = kvmppc_e500_emul_tlbivax(vcpu, ra, rb);
66 emulated = EMULATE_FAIL;
72 emulated = EMULATE_FAIL;
75 if (emulated == EMULATE_FAIL)
76 emulated = kvmppc_booke_emulate_op(run, vcpu, inst, advance);
81 int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
83 struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
84 int emulated = EMULATE_DONE;
85 ulong spr_val = kvmppc_get_gpr(vcpu, rs);
88 #ifndef CONFIG_KVM_BOOKE_HV
90 kvmppc_set_pid(vcpu, spr_val);
95 vcpu_e500->pid[1] = spr_val; break;
99 vcpu_e500->pid[2] = spr_val; break;
101 vcpu->arch.shared->mas0 = spr_val; break;
103 vcpu->arch.shared->mas1 = spr_val; break;
105 vcpu->arch.shared->mas2 = spr_val; break;
107 vcpu->arch.shared->mas7_3 &= ~(u64)0xffffffff;
108 vcpu->arch.shared->mas7_3 |= spr_val;
111 vcpu->arch.shared->mas4 = spr_val; break;
113 vcpu->arch.shared->mas6 = spr_val; break;
115 vcpu->arch.shared->mas7_3 &= (u64)0xffffffff;
116 vcpu->arch.shared->mas7_3 |= (u64)spr_val << 32;
120 vcpu_e500->l1csr0 = spr_val;
121 vcpu_e500->l1csr0 &= ~(L1CSR0_DCFI | L1CSR0_CLFC);
124 vcpu_e500->l1csr1 = spr_val; break;
126 vcpu_e500->hid0 = spr_val; break;
128 vcpu_e500->hid1 = spr_val; break;
131 emulated = kvmppc_e500_emul_mt_mmucsr0(vcpu_e500,
135 /* extra exceptions */
137 vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val;
140 vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] = spr_val;
143 vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = spr_val;
146 vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = spr_val;
148 #ifdef CONFIG_KVM_BOOKE_HV
150 vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL] = spr_val;
153 vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL_CRIT] = spr_val;
157 emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, rs);
163 int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
165 struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
166 int emulated = EMULATE_DONE;
169 #ifndef CONFIG_KVM_BOOKE_HV
173 kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[0]); break;
175 kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[1]); break;
177 kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[2]); break;
179 kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas0); break;
181 kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas1); break;
183 kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas2); break;
185 val = (u32)vcpu->arch.shared->mas7_3;
186 kvmppc_set_gpr(vcpu, rt, val);
189 kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas4); break;
191 kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas6); break;
193 val = vcpu->arch.shared->mas7_3 >> 32;
194 kvmppc_set_gpr(vcpu, rt, val);
198 kvmppc_set_gpr(vcpu, rt, vcpu->arch.tlbcfg[0]); break;
200 kvmppc_set_gpr(vcpu, rt, vcpu->arch.tlbcfg[1]); break;
202 kvmppc_set_gpr(vcpu, rt, vcpu_e500->l1csr0); break;
204 kvmppc_set_gpr(vcpu, rt, vcpu_e500->l1csr1); break;
206 kvmppc_set_gpr(vcpu, rt, vcpu_e500->hid0); break;
208 kvmppc_set_gpr(vcpu, rt, vcpu_e500->hid1); break;
210 kvmppc_set_gpr(vcpu, rt, vcpu_e500->svr); break;
213 kvmppc_set_gpr(vcpu, rt, 0); break;
216 kvmppc_set_gpr(vcpu, rt, vcpu->arch.mmucfg); break;
218 /* extra exceptions */
220 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL]);
223 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA]);
226 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND]);
229 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR]);
231 #ifdef CONFIG_KVM_BOOKE_HV
233 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL]);
236 kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL_CRIT]);
240 emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, rt);