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