1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 XOP_MFDCR 323
31#define XOP_MTDCR 451
32#define XOP_TLBSX 914
33#define XOP_ICCCI 966
34#define XOP_TLBWE 978
35
36int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
37 unsigned int inst, int *advance)
38{
39 int emulated = EMULATE_DONE;
40 int dcrn = get_dcrn(inst);
41 int ra = get_ra(inst);
42 int rb = get_rb(inst);
43 int rc = get_rc(inst);
44 int rs = get_rs(inst);
45 int rt = get_rt(inst);
46 int ws = get_ws(inst);
47
48 switch (get_op(inst)) {
49 case 31:
50 switch (get_xop(inst)) {
51
52 case XOP_MFDCR:
53
54
55
56
57
58
59
60
61
62
63 switch (dcrn) {
64 case DCRN_CPR0_CONFIG_ADDR:
65 kvmppc_set_gpr(vcpu, rt, vcpu->arch.cpr0_cfgaddr);
66 break;
67 case DCRN_CPR0_CONFIG_DATA:
68 local_irq_disable();
69 mtdcr(DCRN_CPR0_CONFIG_ADDR,
70 vcpu->arch.cpr0_cfgaddr);
71 kvmppc_set_gpr(vcpu, rt,
72 mfdcr(DCRN_CPR0_CONFIG_DATA));
73 local_irq_enable();
74 break;
75 default:
76 run->dcr.dcrn = dcrn;
77 run->dcr.data = 0;
78 run->dcr.is_write = 0;
79 vcpu->arch.dcr_is_write = 0;
80 vcpu->arch.io_gpr = rt;
81 vcpu->arch.dcr_needed = 1;
82 kvmppc_account_exit(vcpu, DCR_EXITS);
83 emulated = EMULATE_DO_DCR;
84 }
85
86 break;
87
88 case XOP_MTDCR:
89
90 switch (dcrn) {
91 case DCRN_CPR0_CONFIG_ADDR:
92 vcpu->arch.cpr0_cfgaddr = kvmppc_get_gpr(vcpu, rs);
93 break;
94 default:
95 run->dcr.dcrn = dcrn;
96 run->dcr.data = kvmppc_get_gpr(vcpu, rs);
97 run->dcr.is_write = 1;
98 vcpu->arch.dcr_is_write = 1;
99 vcpu->arch.dcr_needed = 1;
100 kvmppc_account_exit(vcpu, DCR_EXITS);
101 emulated = EMULATE_DO_DCR;
102 }
103
104 break;
105
106 case XOP_TLBWE:
107 emulated = kvmppc_44x_emul_tlbwe(vcpu, ra, rs, ws);
108 break;
109
110 case XOP_TLBSX:
111 emulated = kvmppc_44x_emul_tlbsx(vcpu, rt, ra, rb, rc);
112 break;
113
114 case XOP_ICCCI:
115 break;
116
117 default:
118 emulated = EMULATE_FAIL;
119 }
120
121 break;
122
123 default:
124 emulated = EMULATE_FAIL;
125 }
126
127 if (emulated == EMULATE_FAIL)
128 emulated = kvmppc_booke_emulate_op(run, vcpu, inst, advance);
129
130 return emulated;
131}
132
133int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
134{
135 int emulated = EMULATE_DONE;
136
137 switch (sprn) {
138 case SPRN_PID:
139 kvmppc_set_pid(vcpu, spr_val); break;
140 case SPRN_MMUCR:
141 vcpu->arch.mmucr = spr_val; break;
142 case SPRN_CCR0:
143 vcpu->arch.ccr0 = spr_val; break;
144 case SPRN_CCR1:
145 vcpu->arch.ccr1 = spr_val; break;
146 default:
147 emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, spr_val);
148 }
149
150 return emulated;
151}
152
153int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
154{
155 int emulated = EMULATE_DONE;
156
157 switch (sprn) {
158 case SPRN_PID:
159 *spr_val = vcpu->arch.pid; break;
160 case SPRN_MMUCR:
161 *spr_val = vcpu->arch.mmucr; break;
162 case SPRN_CCR0:
163 *spr_val = vcpu->arch.ccr0; break;
164 case SPRN_CCR1:
165 *spr_val = vcpu->arch.ccr1; break;
166 default:
167 emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, spr_val);
168 }
169
170 return emulated;
171}
172
173