Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/kvm/booke_emulate.c
10820 views
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 <[email protected]>
18
*/
19
20
#include <linux/kvm_host.h>
21
#include <asm/disassemble.h>
22
23
#include "booke.h"
24
25
#define OP_19_XOP_RFI 50
26
27
#define OP_31_XOP_MFMSR 83
28
#define OP_31_XOP_WRTEE 131
29
#define OP_31_XOP_MTMSR 146
30
#define OP_31_XOP_WRTEEI 163
31
32
static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu)
33
{
34
vcpu->arch.pc = vcpu->arch.shared->srr0;
35
kvmppc_set_msr(vcpu, vcpu->arch.shared->srr1);
36
}
37
38
int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
39
unsigned int inst, int *advance)
40
{
41
int emulated = EMULATE_DONE;
42
int rs;
43
int rt;
44
45
switch (get_op(inst)) {
46
case 19:
47
switch (get_xop(inst)) {
48
case OP_19_XOP_RFI:
49
kvmppc_emul_rfi(vcpu);
50
kvmppc_set_exit_type(vcpu, EMULATED_RFI_EXITS);
51
*advance = 0;
52
break;
53
54
default:
55
emulated = EMULATE_FAIL;
56
break;
57
}
58
break;
59
60
case 31:
61
switch (get_xop(inst)) {
62
63
case OP_31_XOP_MFMSR:
64
rt = get_rt(inst);
65
kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->msr);
66
kvmppc_set_exit_type(vcpu, EMULATED_MFMSR_EXITS);
67
break;
68
69
case OP_31_XOP_MTMSR:
70
rs = get_rs(inst);
71
kvmppc_set_exit_type(vcpu, EMULATED_MTMSR_EXITS);
72
kvmppc_set_msr(vcpu, kvmppc_get_gpr(vcpu, rs));
73
break;
74
75
case OP_31_XOP_WRTEE:
76
rs = get_rs(inst);
77
vcpu->arch.shared->msr = (vcpu->arch.shared->msr & ~MSR_EE)
78
| (kvmppc_get_gpr(vcpu, rs) & MSR_EE);
79
kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS);
80
break;
81
82
case OP_31_XOP_WRTEEI:
83
vcpu->arch.shared->msr = (vcpu->arch.shared->msr & ~MSR_EE)
84
| (inst & MSR_EE);
85
kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS);
86
break;
87
88
default:
89
emulated = EMULATE_FAIL;
90
}
91
92
break;
93
94
default:
95
emulated = EMULATE_FAIL;
96
}
97
98
return emulated;
99
}
100
101
int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
102
{
103
int emulated = EMULATE_DONE;
104
ulong spr_val = kvmppc_get_gpr(vcpu, rs);
105
106
switch (sprn) {
107
case SPRN_DEAR:
108
vcpu->arch.shared->dar = spr_val; break;
109
case SPRN_ESR:
110
vcpu->arch.esr = spr_val; break;
111
case SPRN_DBCR0:
112
vcpu->arch.dbcr0 = spr_val; break;
113
case SPRN_DBCR1:
114
vcpu->arch.dbcr1 = spr_val; break;
115
case SPRN_DBSR:
116
vcpu->arch.dbsr &= ~spr_val; break;
117
case SPRN_TSR:
118
vcpu->arch.tsr &= ~spr_val; break;
119
case SPRN_TCR:
120
vcpu->arch.tcr = spr_val;
121
kvmppc_emulate_dec(vcpu);
122
break;
123
124
/* Note: SPRG4-7 are user-readable. These values are
125
* loaded into the real SPRGs when resuming the
126
* guest. */
127
case SPRN_SPRG4:
128
vcpu->arch.sprg4 = spr_val; break;
129
case SPRN_SPRG5:
130
vcpu->arch.sprg5 = spr_val; break;
131
case SPRN_SPRG6:
132
vcpu->arch.sprg6 = spr_val; break;
133
case SPRN_SPRG7:
134
vcpu->arch.sprg7 = spr_val; break;
135
136
case SPRN_IVPR:
137
vcpu->arch.ivpr = spr_val;
138
break;
139
case SPRN_IVOR0:
140
vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] = spr_val;
141
break;
142
case SPRN_IVOR1:
143
vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK] = spr_val;
144
break;
145
case SPRN_IVOR2:
146
vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE] = spr_val;
147
break;
148
case SPRN_IVOR3:
149
vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE] = spr_val;
150
break;
151
case SPRN_IVOR4:
152
vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL] = spr_val;
153
break;
154
case SPRN_IVOR5:
155
vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT] = spr_val;
156
break;
157
case SPRN_IVOR6:
158
vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM] = spr_val;
159
break;
160
case SPRN_IVOR7:
161
vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL] = spr_val;
162
break;
163
case SPRN_IVOR8:
164
vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL] = spr_val;
165
break;
166
case SPRN_IVOR9:
167
vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL] = spr_val;
168
break;
169
case SPRN_IVOR10:
170
vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER] = spr_val;
171
break;
172
case SPRN_IVOR11:
173
vcpu->arch.ivor[BOOKE_IRQPRIO_FIT] = spr_val;
174
break;
175
case SPRN_IVOR12:
176
vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG] = spr_val;
177
break;
178
case SPRN_IVOR13:
179
vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS] = spr_val;
180
break;
181
case SPRN_IVOR14:
182
vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS] = spr_val;
183
break;
184
case SPRN_IVOR15:
185
vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = spr_val;
186
break;
187
188
default:
189
emulated = EMULATE_FAIL;
190
}
191
192
return emulated;
193
}
194
195
int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
196
{
197
int emulated = EMULATE_DONE;
198
199
switch (sprn) {
200
case SPRN_IVPR:
201
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivpr); break;
202
case SPRN_DEAR:
203
kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->dar); break;
204
case SPRN_ESR:
205
kvmppc_set_gpr(vcpu, rt, vcpu->arch.esr); break;
206
case SPRN_DBCR0:
207
kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbcr0); break;
208
case SPRN_DBCR1:
209
kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbcr1); break;
210
case SPRN_DBSR:
211
kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbsr); break;
212
213
case SPRN_IVOR0:
214
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL]);
215
break;
216
case SPRN_IVOR1:
217
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK]);
218
break;
219
case SPRN_IVOR2:
220
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE]);
221
break;
222
case SPRN_IVOR3:
223
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE]);
224
break;
225
case SPRN_IVOR4:
226
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL]);
227
break;
228
case SPRN_IVOR5:
229
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT]);
230
break;
231
case SPRN_IVOR6:
232
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM]);
233
break;
234
case SPRN_IVOR7:
235
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL]);
236
break;
237
case SPRN_IVOR8:
238
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL]);
239
break;
240
case SPRN_IVOR9:
241
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL]);
242
break;
243
case SPRN_IVOR10:
244
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER]);
245
break;
246
case SPRN_IVOR11:
247
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_FIT]);
248
break;
249
case SPRN_IVOR12:
250
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG]);
251
break;
252
case SPRN_IVOR13:
253
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS]);
254
break;
255
case SPRN_IVOR14:
256
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS]);
257
break;
258
case SPRN_IVOR15:
259
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG]);
260
break;
261
262
default:
263
emulated = EMULATE_FAIL;
264
}
265
266
return emulated;
267
}
268
269