]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/powerpc/kvm/44x_emulate.c
KVM: ppc: mostly cosmetic updates to the exit timing accounting code
[karo-tx-linux.git] / arch / powerpc / kvm / 44x_emulate.c
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 #include <asm/kvm_44x.h>
25 #include "timing.h"
26
27 #include "booke.h"
28 #include "44x_tlb.h"
29
30 #define OP_RFI      19
31
32 #define XOP_RFI     50
33 #define XOP_MFMSR   83
34 #define XOP_WRTEE   131
35 #define XOP_MTMSR   146
36 #define XOP_WRTEEI  163
37 #define XOP_MFDCR   323
38 #define XOP_MTDCR   451
39 #define XOP_TLBSX   914
40 #define XOP_ICCCI   966
41 #define XOP_TLBWE   978
42
43 static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu)
44 {
45         vcpu->arch.pc = vcpu->arch.srr0;
46         kvmppc_set_msr(vcpu, vcpu->arch.srr1);
47 }
48
49 int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
50                            unsigned int inst, int *advance)
51 {
52         int emulated = EMULATE_DONE;
53         int dcrn;
54         int ra;
55         int rb;
56         int rc;
57         int rs;
58         int rt;
59         int ws;
60
61         switch (get_op(inst)) {
62         case OP_RFI:
63                 switch (get_xop(inst)) {
64                 case XOP_RFI:
65                         kvmppc_emul_rfi(vcpu);
66                         kvmppc_set_exit_type(vcpu, EMULATED_RFI_EXITS);
67                         *advance = 0;
68                         break;
69
70                 default:
71                         emulated = EMULATE_FAIL;
72                         break;
73                 }
74                 break;
75
76         case 31:
77                 switch (get_xop(inst)) {
78
79                 case XOP_MFMSR:
80                         rt = get_rt(inst);
81                         vcpu->arch.gpr[rt] = vcpu->arch.msr;
82                         kvmppc_set_exit_type(vcpu, EMULATED_MFMSR_EXITS);
83                         break;
84
85                 case XOP_MTMSR:
86                         rs = get_rs(inst);
87                         kvmppc_set_exit_type(vcpu, EMULATED_MTMSR_EXITS);
88                         kvmppc_set_msr(vcpu, vcpu->arch.gpr[rs]);
89                         break;
90
91                 case XOP_WRTEE:
92                         rs = get_rs(inst);
93                         vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
94                                                          | (vcpu->arch.gpr[rs] & MSR_EE);
95                         kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS);
96                         break;
97
98                 case XOP_WRTEEI:
99                         vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
100                                                          | (inst & MSR_EE);
101                         kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS);
102                         break;
103
104                 case XOP_MFDCR:
105                         dcrn = get_dcrn(inst);
106                         rt = get_rt(inst);
107
108                         /* The guest may access CPR0 registers to determine the timebase
109                          * frequency, and it must know the real host frequency because it
110                          * can directly access the timebase registers.
111                          *
112                          * It would be possible to emulate those accesses in userspace,
113                          * but userspace can really only figure out the end frequency.
114                          * We could decompose that into the factors that compute it, but
115                          * that's tricky math, and it's easier to just report the real
116                          * CPR0 values.
117                          */
118                         switch (dcrn) {
119                         case DCRN_CPR0_CONFIG_ADDR:
120                                 vcpu->arch.gpr[rt] = vcpu->arch.cpr0_cfgaddr;
121                                 break;
122                         case DCRN_CPR0_CONFIG_DATA:
123                                 local_irq_disable();
124                                 mtdcr(DCRN_CPR0_CONFIG_ADDR,
125                                           vcpu->arch.cpr0_cfgaddr);
126                                 vcpu->arch.gpr[rt] = mfdcr(DCRN_CPR0_CONFIG_DATA);
127                                 local_irq_enable();
128                                 break;
129                         default:
130                                 run->dcr.dcrn = dcrn;
131                                 run->dcr.data =  0;
132                                 run->dcr.is_write = 0;
133                                 vcpu->arch.io_gpr = rt;
134                                 vcpu->arch.dcr_needed = 1;
135                                 kvmppc_account_exit(vcpu, DCR_EXITS);
136                                 emulated = EMULATE_DO_DCR;
137                         }
138
139                         break;
140
141                 case XOP_MTDCR:
142                         dcrn = get_dcrn(inst);
143                         rs = get_rs(inst);
144
145                         /* emulate some access in kernel */
146                         switch (dcrn) {
147                         case DCRN_CPR0_CONFIG_ADDR:
148                                 vcpu->arch.cpr0_cfgaddr = vcpu->arch.gpr[rs];
149                                 break;
150                         default:
151                                 run->dcr.dcrn = dcrn;
152                                 run->dcr.data = vcpu->arch.gpr[rs];
153                                 run->dcr.is_write = 1;
154                                 vcpu->arch.dcr_needed = 1;
155                                 kvmppc_account_exit(vcpu, DCR_EXITS);
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
192 int 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];
232                 break;
233         case SPRN_IVOR0:
234                 vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] = vcpu->arch.gpr[rs];
235                 break;
236         case SPRN_IVOR1:
237                 vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK] = vcpu->arch.gpr[rs];
238                 break;
239         case SPRN_IVOR2:
240                 vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE] = vcpu->arch.gpr[rs];
241                 break;
242         case SPRN_IVOR3:
243                 vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE] = vcpu->arch.gpr[rs];
244                 break;
245         case SPRN_IVOR4:
246                 vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL] = vcpu->arch.gpr[rs];
247                 break;
248         case SPRN_IVOR5:
249                 vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT] = vcpu->arch.gpr[rs];
250                 break;
251         case SPRN_IVOR6:
252                 vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM] = vcpu->arch.gpr[rs];
253                 break;
254         case SPRN_IVOR7:
255                 vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL] = vcpu->arch.gpr[rs];
256                 break;
257         case SPRN_IVOR8:
258                 vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL] = vcpu->arch.gpr[rs];
259                 break;
260         case SPRN_IVOR9:
261                 vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL] = vcpu->arch.gpr[rs];
262                 break;
263         case SPRN_IVOR10:
264                 vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER] = vcpu->arch.gpr[rs];
265                 break;
266         case SPRN_IVOR11:
267                 vcpu->arch.ivor[BOOKE_IRQPRIO_FIT] = vcpu->arch.gpr[rs];
268                 break;
269         case SPRN_IVOR12:
270                 vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG] = vcpu->arch.gpr[rs];
271                 break;
272         case SPRN_IVOR13:
273                 vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS] = vcpu->arch.gpr[rs];
274                 break;
275         case SPRN_IVOR14:
276                 vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS] = vcpu->arch.gpr[rs];
277                 break;
278         case SPRN_IVOR15:
279                 vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = vcpu->arch.gpr[rs];
280                 break;
281
282         default:
283                 return EMULATE_FAIL;
284         }
285
286         kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS);
287         return EMULATE_DONE;
288 }
289
290 int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
291 {
292         switch (sprn) {
293         /* 440 */
294         case SPRN_MMUCR:
295                 vcpu->arch.gpr[rt] = vcpu->arch.mmucr; break;
296         case SPRN_CCR0:
297                 vcpu->arch.gpr[rt] = vcpu->arch.ccr0; break;
298         case SPRN_CCR1:
299                 vcpu->arch.gpr[rt] = vcpu->arch.ccr1; break;
300
301         /* Book E */
302         case SPRN_PID:
303                 vcpu->arch.gpr[rt] = vcpu->arch.pid; break;
304         case SPRN_IVPR:
305                 vcpu->arch.gpr[rt] = vcpu->arch.ivpr; break;
306         case SPRN_DEAR:
307                 vcpu->arch.gpr[rt] = vcpu->arch.dear; break;
308         case SPRN_ESR:
309                 vcpu->arch.gpr[rt] = vcpu->arch.esr; break;
310         case SPRN_DBCR0:
311                 vcpu->arch.gpr[rt] = vcpu->arch.dbcr0; break;
312         case SPRN_DBCR1:
313                 vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break;
314
315         case SPRN_IVOR0:
316                 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL];
317                 break;
318         case SPRN_IVOR1:
319                 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK];
320                 break;
321         case SPRN_IVOR2:
322                 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE];
323                 break;
324         case SPRN_IVOR3:
325                 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE];
326                 break;
327         case SPRN_IVOR4:
328                 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL];
329                 break;
330         case SPRN_IVOR5:
331                 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT];
332                 break;
333         case SPRN_IVOR6:
334                 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM];
335                 break;
336         case SPRN_IVOR7:
337                 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL];
338                 break;
339         case SPRN_IVOR8:
340                 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL];
341                 break;
342         case SPRN_IVOR9:
343                 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL];
344                 break;
345         case SPRN_IVOR10:
346                 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER];
347                 break;
348         case SPRN_IVOR11:
349                 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FIT];
350                 break;
351         case SPRN_IVOR12:
352                 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG];
353                 break;
354         case SPRN_IVOR13:
355                 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS];
356                 break;
357         case SPRN_IVOR14:
358                 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS];
359                 break;
360         case SPRN_IVOR15:
361                 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG];
362                 break;
363
364         default:
365                 return EMULATE_FAIL;
366         }
367
368         kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS);
369         return EMULATE_DONE;
370 }
371