aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/44x_emulate.c
diff options
context:
space:
mode:
authorHollis Blanchard <hollisb@us.ibm.com>2008-11-05 10:36:16 -0500
committerAvi Kivity <avi@redhat.com>2008-12-31 09:52:21 -0500
commit75f74f0dbe086c239b4b0cc5ed75b903ea3e663f (patch)
treec6774128934667d1c82a6e458d9a4233574a95a4 /arch/powerpc/kvm/44x_emulate.c
parentc381a04313e7c0fb04246b1ff711e0b5726de6c0 (diff)
KVM: ppc: refactor instruction emulation into generic and core-specific pieces
Cores provide 3 emulation hooks, implemented for example in the new 4xx_emulate.c: kvmppc_core_emulate_op kvmppc_core_emulate_mtspr kvmppc_core_emulate_mfspr Strictly speaking the last two aren't necessary, but provide for more informative error reporting ("unknown SPR"). Long term I'd like to have instruction decoding autogenerated from tables of opcodes, and that way we could aggregate universal, Book E, and core-specific instructions more easily and without redundant switch statements. Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc/kvm/44x_emulate.c')
-rw-r--r--arch/powerpc/kvm/44x_emulate.c335
1 files changed, 335 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/44x_emulate.c b/arch/powerpc/kvm/44x_emulate.c
new file mode 100644
index 000000000000..a634c0c4fa7e
--- /dev/null
+++ b/arch/powerpc/kvm/44x_emulate.c
@@ -0,0 +1,335 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2, as
4 * published by the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
14 *
15 * Copyright IBM Corp. 2008
16 *
17 * Authors: Hollis Blanchard <hollisb@us.ibm.com>
18 */
19
20#include <asm/kvm_ppc.h>
21#include <asm/dcr.h>
22#include <asm/dcr-regs.h>
23#include <asm/disassemble.h>
24
25#include "booke.h"
26#include "44x_tlb.h"
27
28#define OP_RFI 19
29
30#define XOP_RFI 50
31#define XOP_MFMSR 83
32#define XOP_WRTEE 131
33#define XOP_MTMSR 146
34#define XOP_WRTEEI 163
35#define XOP_MFDCR 323
36#define XOP_MTDCR 451
37#define XOP_TLBSX 914
38#define XOP_ICCCI 966
39#define XOP_TLBWE 978
40
41static inline void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 new_pid)
42{
43 if (vcpu->arch.pid != new_pid) {
44 vcpu->arch.pid = new_pid;
45 vcpu->arch.swap_pid = 1;
46 }
47}
48
49static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu)
50{
51 vcpu->arch.pc = vcpu->arch.srr0;
52 kvmppc_set_msr(vcpu, vcpu->arch.srr1);
53}
54
55int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
56 unsigned int inst, int *advance)
57{
58 int emulated = EMULATE_DONE;
59 int dcrn;
60 int ra;
61 int rb;
62 int rc;
63 int rs;
64 int rt;
65 int ws;
66
67 switch (get_op(inst)) {
68
69 case OP_RFI:
70 switch (get_xop(inst)) {
71 case XOP_RFI:
72 kvmppc_emul_rfi(vcpu);
73 *advance = 0;
74 break;
75
76 default:
77 emulated = EMULATE_FAIL;
78 break;
79 }
80 break;
81
82 case 31:
83 switch (get_xop(inst)) {
84
85 case XOP_MFMSR:
86 rt = get_rt(inst);
87 vcpu->arch.gpr[rt] = vcpu->arch.msr;
88 break;
89
90 case XOP_MTMSR:
91 rs = get_rs(inst);
92 kvmppc_set_msr(vcpu, vcpu->arch.gpr[rs]);
93 break;
94
95 case XOP_WRTEE:
96 rs = get_rs(inst);
97 vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
98 | (vcpu->arch.gpr[rs] & MSR_EE);
99 break;
100
101 case XOP_WRTEEI:
102 vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
103 | (inst & MSR_EE);
104 break;
105
106 case XOP_MFDCR:
107 dcrn = get_dcrn(inst);
108 rt = get_rt(inst);
109
110 /* The guest may access CPR0 registers to determine the timebase
111 * frequency, and it must know the real host frequency because it
112 * can directly access the timebase registers.
113 *
114 * It would be possible to emulate those accesses in userspace,
115 * but userspace can really only figure out the end frequency.
116 * We could decompose that into the factors that compute it, but
117 * that's tricky math, and it's easier to just report the real
118 * CPR0 values.
119 */
120 switch (dcrn) {
121 case DCRN_CPR0_CONFIG_ADDR:
122 vcpu->arch.gpr[rt] = vcpu->arch.cpr0_cfgaddr;
123 break;
124 case DCRN_CPR0_CONFIG_DATA:
125 local_irq_disable();
126 mtdcr(DCRN_CPR0_CONFIG_ADDR,
127 vcpu->arch.cpr0_cfgaddr);
128 vcpu->arch.gpr[rt] = mfdcr(DCRN_CPR0_CONFIG_DATA);
129 local_irq_enable();
130 break;
131 default:
132 run->dcr.dcrn = dcrn;
133 run->dcr.data = 0;
134 run->dcr.is_write = 0;
135 vcpu->arch.io_gpr = rt;
136 vcpu->arch.dcr_needed = 1;
137 emulated = EMULATE_DO_DCR;
138 }
139
140 break;
141
142 case XOP_MTDCR:
143 dcrn = get_dcrn(inst);
144 rs = get_rs(inst);
145
146 /* emulate some access in kernel */
147 switch (dcrn) {
148 case DCRN_CPR0_CONFIG_ADDR:
149 vcpu->arch.cpr0_cfgaddr = vcpu->arch.gpr[rs];
150 break;
151 default:
152 run->dcr.dcrn = dcrn;
153 run->dcr.data = vcpu->arch.gpr[rs];
154 run->dcr.is_write = 1;
155 vcpu->arch.dcr_needed = 1;
156 emulated = EMULATE_DO_DCR;
157 }
158
159 break;
160
161 case XOP_TLBWE:
162 ra = get_ra(inst);
163 rs = get_rs(inst);
164 ws = get_ws(inst);
165 emulated = kvmppc_44x_emul_tlbwe(vcpu, ra, rs, ws);
166 break;
167
168 case XOP_TLBSX:
169 rt = get_rt(inst);
170 ra = get_ra(inst);
171 rb = get_rb(inst);
172 rc = get_rc(inst);
173 emulated = kvmppc_44x_emul_tlbsx(vcpu, rt, ra, rb, rc);
174 break;
175
176 case XOP_ICCCI:
177 break;
178
179 default:
180 emulated = EMULATE_FAIL;
181 }
182
183 break;
184
185 default:
186 emulated = EMULATE_FAIL;
187 }
188
189 return emulated;
190}
191
192int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
193{
194 switch (sprn) {
195 case SPRN_MMUCR:
196 vcpu->arch.mmucr = vcpu->arch.gpr[rs]; break;
197 case SPRN_PID:
198 kvmppc_set_pid(vcpu, vcpu->arch.gpr[rs]); break;
199 case SPRN_CCR0:
200 vcpu->arch.ccr0 = vcpu->arch.gpr[rs]; break;
201 case SPRN_CCR1:
202 vcpu->arch.ccr1 = vcpu->arch.gpr[rs]; break;
203 case SPRN_DEAR:
204 vcpu->arch.dear = vcpu->arch.gpr[rs]; break;
205 case SPRN_ESR:
206 vcpu->arch.esr = vcpu->arch.gpr[rs]; break;
207 case SPRN_DBCR0:
208 vcpu->arch.dbcr0 = vcpu->arch.gpr[rs]; break;
209 case SPRN_DBCR1:
210 vcpu->arch.dbcr1 = vcpu->arch.gpr[rs]; break;
211 case SPRN_TSR:
212 vcpu->arch.tsr &= ~vcpu->arch.gpr[rs]; break;
213 case SPRN_TCR:
214 vcpu->arch.tcr = vcpu->arch.gpr[rs];
215 kvmppc_emulate_dec(vcpu);
216 break;
217
218 /* Note: SPRG4-7 are user-readable. These values are
219 * loaded into the real SPRGs when resuming the
220 * guest. */
221 case SPRN_SPRG4:
222 vcpu->arch.sprg4 = vcpu->arch.gpr[rs]; break;
223 case SPRN_SPRG5:
224 vcpu->arch.sprg5 = vcpu->arch.gpr[rs]; break;
225 case SPRN_SPRG6:
226 vcpu->arch.sprg6 = vcpu->arch.gpr[rs]; break;
227 case SPRN_SPRG7:
228 vcpu->arch.sprg7 = vcpu->arch.gpr[rs]; break;
229
230 case SPRN_IVPR:
231 vcpu->arch.ivpr = vcpu->arch.gpr[rs]; break;
232 case SPRN_IVOR0:
233 vcpu->arch.ivor[0] = vcpu->arch.gpr[rs]; break;
234 case SPRN_IVOR1:
235 vcpu->arch.ivor[1] = vcpu->arch.gpr[rs]; break;
236 case SPRN_IVOR2:
237 vcpu->arch.ivor[2] = vcpu->arch.gpr[rs]; break;
238 case SPRN_IVOR3:
239 vcpu->arch.ivor[3] = vcpu->arch.gpr[rs]; break;
240 case SPRN_IVOR4:
241 vcpu->arch.ivor[4] = vcpu->arch.gpr[rs]; break;
242 case SPRN_IVOR5:
243 vcpu->arch.ivor[5] = vcpu->arch.gpr[rs]; break;
244 case SPRN_IVOR6:
245 vcpu->arch.ivor[6] = vcpu->arch.gpr[rs]; break;
246 case SPRN_IVOR7:
247 vcpu->arch.ivor[7] = vcpu->arch.gpr[rs]; break;
248 case SPRN_IVOR8:
249 vcpu->arch.ivor[8] = vcpu->arch.gpr[rs]; break;
250 case SPRN_IVOR9:
251 vcpu->arch.ivor[9] = vcpu->arch.gpr[rs]; break;
252 case SPRN_IVOR10:
253 vcpu->arch.ivor[10] = vcpu->arch.gpr[rs]; break;
254 case SPRN_IVOR11:
255 vcpu->arch.ivor[11] = vcpu->arch.gpr[rs]; break;
256 case SPRN_IVOR12:
257 vcpu->arch.ivor[12] = vcpu->arch.gpr[rs]; break;
258 case SPRN_IVOR13:
259 vcpu->arch.ivor[13] = vcpu->arch.gpr[rs]; break;
260 case SPRN_IVOR14:
261 vcpu->arch.ivor[14] = vcpu->arch.gpr[rs]; break;
262 case SPRN_IVOR15:
263 vcpu->arch.ivor[15] = vcpu->arch.gpr[rs]; break;
264
265 default:
266 return EMULATE_FAIL;
267 }
268
269 return EMULATE_DONE;
270}
271
272int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
273{
274 switch (sprn) {
275 /* 440 */
276 case SPRN_MMUCR:
277 vcpu->arch.gpr[rt] = vcpu->arch.mmucr; break;
278 case SPRN_CCR0:
279 vcpu->arch.gpr[rt] = vcpu->arch.ccr0; break;
280 case SPRN_CCR1:
281 vcpu->arch.gpr[rt] = vcpu->arch.ccr1; break;
282
283 /* Book E */
284 case SPRN_PID:
285 vcpu->arch.gpr[rt] = vcpu->arch.pid; break;
286 case SPRN_IVPR:
287 vcpu->arch.gpr[rt] = vcpu->arch.ivpr; break;
288 case SPRN_DEAR:
289 vcpu->arch.gpr[rt] = vcpu->arch.dear; break;
290 case SPRN_ESR:
291 vcpu->arch.gpr[rt] = vcpu->arch.esr; break;
292 case SPRN_DBCR0:
293 vcpu->arch.gpr[rt] = vcpu->arch.dbcr0; break;
294 case SPRN_DBCR1:
295 vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break;
296
297 case SPRN_IVOR0:
298 vcpu->arch.gpr[rt] = vcpu->arch.ivor[0]; break;
299 case SPRN_IVOR1:
300 vcpu->arch.gpr[rt] = vcpu->arch.ivor[1]; break;
301 case SPRN_IVOR2:
302 vcpu->arch.gpr[rt] = vcpu->arch.ivor[2]; break;
303 case SPRN_IVOR3:
304 vcpu->arch.gpr[rt] = vcpu->arch.ivor[3]; break;
305 case SPRN_IVOR4:
306 vcpu->arch.gpr[rt] = vcpu->arch.ivor[4]; break;
307 case SPRN_IVOR5:
308 vcpu->arch.gpr[rt] = vcpu->arch.ivor[5]; break;
309 case SPRN_IVOR6:
310 vcpu->arch.gpr[rt] = vcpu->arch.ivor[6]; break;
311 case SPRN_IVOR7:
312 vcpu->arch.gpr[rt] = vcpu->arch.ivor[7]; break;
313 case SPRN_IVOR8:
314 vcpu->arch.gpr[rt] = vcpu->arch.ivor[8]; break;
315 case SPRN_IVOR9:
316 vcpu->arch.gpr[rt] = vcpu->arch.ivor[9]; break;
317 case SPRN_IVOR10:
318 vcpu->arch.gpr[rt] = vcpu->arch.ivor[10]; break;
319 case SPRN_IVOR11:
320 vcpu->arch.gpr[rt] = vcpu->arch.ivor[11]; break;
321 case SPRN_IVOR12:
322 vcpu->arch.gpr[rt] = vcpu->arch.ivor[12]; break;
323 case SPRN_IVOR13:
324 vcpu->arch.gpr[rt] = vcpu->arch.ivor[13]; break;
325 case SPRN_IVOR14:
326 vcpu->arch.gpr[rt] = vcpu->arch.ivor[14]; break;
327 case SPRN_IVOR15:
328 vcpu->arch.gpr[rt] = vcpu->arch.ivor[15]; break;
329 default:
330 return EMULATE_FAIL;
331 }
332
333 return EMULATE_DONE;
334}
335