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