diff options
-rw-r--r-- | arch/powerpc/include/asm/kvm_ppc.h | 3 | ||||
-rw-r--r-- | arch/powerpc/kvm/44x_emulate.c | 100 | ||||
-rw-r--r-- | arch/powerpc/kvm/booke.c | 175 | ||||
-rw-r--r-- | arch/powerpc/kvm/booke.h | 18 |
4 files changed, 140 insertions, 156 deletions
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 976ecc4b322e..844f683302f6 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h | |||
@@ -36,9 +36,6 @@ enum emulation_result { | |||
36 | EMULATE_FAIL, /* can't emulate this instruction */ | 36 | EMULATE_FAIL, /* can't emulate this instruction */ |
37 | }; | 37 | }; |
38 | 38 | ||
39 | extern const unsigned char exception_priority[]; | ||
40 | extern const unsigned char priority_exception[]; | ||
41 | |||
42 | extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu); | 39 | extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu); |
43 | extern char kvmppc_handlers_start[]; | 40 | extern char kvmppc_handlers_start[]; |
44 | extern unsigned long kvmppc_handler_len; | 41 | extern unsigned long kvmppc_handler_len; |
diff --git a/arch/powerpc/kvm/44x_emulate.c b/arch/powerpc/kvm/44x_emulate.c index a634c0c4fa7e..9bc50cebf9ec 100644 --- a/arch/powerpc/kvm/44x_emulate.c +++ b/arch/powerpc/kvm/44x_emulate.c | |||
@@ -228,39 +228,56 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) | |||
228 | vcpu->arch.sprg7 = vcpu->arch.gpr[rs]; break; | 228 | vcpu->arch.sprg7 = vcpu->arch.gpr[rs]; break; |
229 | 229 | ||
230 | case SPRN_IVPR: | 230 | case SPRN_IVPR: |
231 | vcpu->arch.ivpr = vcpu->arch.gpr[rs]; break; | 231 | vcpu->arch.ivpr = vcpu->arch.gpr[rs]; |
232 | break; | ||
232 | case SPRN_IVOR0: | 233 | case SPRN_IVOR0: |
233 | vcpu->arch.ivor[0] = vcpu->arch.gpr[rs]; break; | 234 | vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] = vcpu->arch.gpr[rs]; |
235 | break; | ||
234 | case SPRN_IVOR1: | 236 | case SPRN_IVOR1: |
235 | vcpu->arch.ivor[1] = vcpu->arch.gpr[rs]; break; | 237 | vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK] = vcpu->arch.gpr[rs]; |
238 | break; | ||
236 | case SPRN_IVOR2: | 239 | case SPRN_IVOR2: |
237 | vcpu->arch.ivor[2] = vcpu->arch.gpr[rs]; break; | 240 | vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE] = vcpu->arch.gpr[rs]; |
241 | break; | ||
238 | case SPRN_IVOR3: | 242 | case SPRN_IVOR3: |
239 | vcpu->arch.ivor[3] = vcpu->arch.gpr[rs]; break; | 243 | vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE] = vcpu->arch.gpr[rs]; |
244 | break; | ||
240 | case SPRN_IVOR4: | 245 | case SPRN_IVOR4: |
241 | vcpu->arch.ivor[4] = vcpu->arch.gpr[rs]; break; | 246 | vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL] = vcpu->arch.gpr[rs]; |
247 | break; | ||
242 | case SPRN_IVOR5: | 248 | case SPRN_IVOR5: |
243 | vcpu->arch.ivor[5] = vcpu->arch.gpr[rs]; break; | 249 | vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT] = vcpu->arch.gpr[rs]; |
250 | break; | ||
244 | case SPRN_IVOR6: | 251 | case SPRN_IVOR6: |
245 | vcpu->arch.ivor[6] = vcpu->arch.gpr[rs]; break; | 252 | vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM] = vcpu->arch.gpr[rs]; |
253 | break; | ||
246 | case SPRN_IVOR7: | 254 | case SPRN_IVOR7: |
247 | vcpu->arch.ivor[7] = vcpu->arch.gpr[rs]; break; | 255 | vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL] = vcpu->arch.gpr[rs]; |
256 | break; | ||
248 | case SPRN_IVOR8: | 257 | case SPRN_IVOR8: |
249 | vcpu->arch.ivor[8] = vcpu->arch.gpr[rs]; break; | 258 | vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL] = vcpu->arch.gpr[rs]; |
259 | break; | ||
250 | case SPRN_IVOR9: | 260 | case SPRN_IVOR9: |
251 | vcpu->arch.ivor[9] = vcpu->arch.gpr[rs]; break; | 261 | vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL] = vcpu->arch.gpr[rs]; |
262 | break; | ||
252 | case SPRN_IVOR10: | 263 | case SPRN_IVOR10: |
253 | vcpu->arch.ivor[10] = vcpu->arch.gpr[rs]; break; | 264 | vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER] = vcpu->arch.gpr[rs]; |
265 | break; | ||
254 | case SPRN_IVOR11: | 266 | case SPRN_IVOR11: |
255 | vcpu->arch.ivor[11] = vcpu->arch.gpr[rs]; break; | 267 | vcpu->arch.ivor[BOOKE_IRQPRIO_FIT] = vcpu->arch.gpr[rs]; |
268 | break; | ||
256 | case SPRN_IVOR12: | 269 | case SPRN_IVOR12: |
257 | vcpu->arch.ivor[12] = vcpu->arch.gpr[rs]; break; | 270 | vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG] = vcpu->arch.gpr[rs]; |
271 | break; | ||
258 | case SPRN_IVOR13: | 272 | case SPRN_IVOR13: |
259 | vcpu->arch.ivor[13] = vcpu->arch.gpr[rs]; break; | 273 | vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS] = vcpu->arch.gpr[rs]; |
274 | break; | ||
260 | case SPRN_IVOR14: | 275 | case SPRN_IVOR14: |
261 | vcpu->arch.ivor[14] = vcpu->arch.gpr[rs]; break; | 276 | vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS] = vcpu->arch.gpr[rs]; |
277 | break; | ||
262 | case SPRN_IVOR15: | 278 | case SPRN_IVOR15: |
263 | vcpu->arch.ivor[15] = vcpu->arch.gpr[rs]; break; | 279 | vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = vcpu->arch.gpr[rs]; |
280 | break; | ||
264 | 281 | ||
265 | default: | 282 | default: |
266 | return EMULATE_FAIL; | 283 | return EMULATE_FAIL; |
@@ -295,37 +312,54 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) | |||
295 | vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break; | 312 | vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break; |
296 | 313 | ||
297 | case SPRN_IVOR0: | 314 | case SPRN_IVOR0: |
298 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[0]; break; | 315 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL]; |
316 | break; | ||
299 | case SPRN_IVOR1: | 317 | case SPRN_IVOR1: |
300 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[1]; break; | 318 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK]; |
319 | break; | ||
301 | case SPRN_IVOR2: | 320 | case SPRN_IVOR2: |
302 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[2]; break; | 321 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE]; |
322 | break; | ||
303 | case SPRN_IVOR3: | 323 | case SPRN_IVOR3: |
304 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[3]; break; | 324 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE]; |
325 | break; | ||
305 | case SPRN_IVOR4: | 326 | case SPRN_IVOR4: |
306 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[4]; break; | 327 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL]; |
328 | break; | ||
307 | case SPRN_IVOR5: | 329 | case SPRN_IVOR5: |
308 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[5]; break; | 330 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT]; |
331 | break; | ||
309 | case SPRN_IVOR6: | 332 | case SPRN_IVOR6: |
310 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[6]; break; | 333 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM]; |
334 | break; | ||
311 | case SPRN_IVOR7: | 335 | case SPRN_IVOR7: |
312 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[7]; break; | 336 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL]; |
337 | break; | ||
313 | case SPRN_IVOR8: | 338 | case SPRN_IVOR8: |
314 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[8]; break; | 339 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL]; |
340 | break; | ||
315 | case SPRN_IVOR9: | 341 | case SPRN_IVOR9: |
316 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[9]; break; | 342 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL]; |
343 | break; | ||
317 | case SPRN_IVOR10: | 344 | case SPRN_IVOR10: |
318 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[10]; break; | 345 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER]; |
346 | break; | ||
319 | case SPRN_IVOR11: | 347 | case SPRN_IVOR11: |
320 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[11]; break; | 348 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FIT]; |
349 | break; | ||
321 | case SPRN_IVOR12: | 350 | case SPRN_IVOR12: |
322 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[12]; break; | 351 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG]; |
352 | break; | ||
323 | case SPRN_IVOR13: | 353 | case SPRN_IVOR13: |
324 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[13]; break; | 354 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS]; |
355 | break; | ||
325 | case SPRN_IVOR14: | 356 | case SPRN_IVOR14: |
326 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[14]; break; | 357 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS]; |
358 | break; | ||
327 | case SPRN_IVOR15: | 359 | case SPRN_IVOR15: |
328 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[15]; break; | 360 | vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG]; |
361 | break; | ||
362 | |||
329 | default: | 363 | default: |
330 | return EMULATE_FAIL; | 364 | return EMULATE_FAIL; |
331 | } | 365 | } |
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 0f064719162c..ec59a6768ec3 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
@@ -55,64 +55,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
55 | { NULL } | 55 | { NULL } |
56 | }; | 56 | }; |
57 | 57 | ||
58 | static const u32 interrupt_msr_mask[16] = { | ||
59 | [BOOKE_INTERRUPT_CRITICAL] = MSR_ME, | ||
60 | [BOOKE_INTERRUPT_MACHINE_CHECK] = 0, | ||
61 | [BOOKE_INTERRUPT_DATA_STORAGE] = MSR_CE|MSR_ME|MSR_DE, | ||
62 | [BOOKE_INTERRUPT_INST_STORAGE] = MSR_CE|MSR_ME|MSR_DE, | ||
63 | [BOOKE_INTERRUPT_EXTERNAL] = MSR_CE|MSR_ME|MSR_DE, | ||
64 | [BOOKE_INTERRUPT_ALIGNMENT] = MSR_CE|MSR_ME|MSR_DE, | ||
65 | [BOOKE_INTERRUPT_PROGRAM] = MSR_CE|MSR_ME|MSR_DE, | ||
66 | [BOOKE_INTERRUPT_FP_UNAVAIL] = MSR_CE|MSR_ME|MSR_DE, | ||
67 | [BOOKE_INTERRUPT_SYSCALL] = MSR_CE|MSR_ME|MSR_DE, | ||
68 | [BOOKE_INTERRUPT_AP_UNAVAIL] = MSR_CE|MSR_ME|MSR_DE, | ||
69 | [BOOKE_INTERRUPT_DECREMENTER] = MSR_CE|MSR_ME|MSR_DE, | ||
70 | [BOOKE_INTERRUPT_FIT] = MSR_CE|MSR_ME|MSR_DE, | ||
71 | [BOOKE_INTERRUPT_WATCHDOG] = MSR_ME, | ||
72 | [BOOKE_INTERRUPT_DTLB_MISS] = MSR_CE|MSR_ME|MSR_DE, | ||
73 | [BOOKE_INTERRUPT_ITLB_MISS] = MSR_CE|MSR_ME|MSR_DE, | ||
74 | [BOOKE_INTERRUPT_DEBUG] = MSR_ME, | ||
75 | }; | ||
76 | |||
77 | const unsigned char exception_priority[] = { | ||
78 | [BOOKE_INTERRUPT_DATA_STORAGE] = 0, | ||
79 | [BOOKE_INTERRUPT_INST_STORAGE] = 1, | ||
80 | [BOOKE_INTERRUPT_ALIGNMENT] = 2, | ||
81 | [BOOKE_INTERRUPT_PROGRAM] = 3, | ||
82 | [BOOKE_INTERRUPT_FP_UNAVAIL] = 4, | ||
83 | [BOOKE_INTERRUPT_SYSCALL] = 5, | ||
84 | [BOOKE_INTERRUPT_AP_UNAVAIL] = 6, | ||
85 | [BOOKE_INTERRUPT_DTLB_MISS] = 7, | ||
86 | [BOOKE_INTERRUPT_ITLB_MISS] = 8, | ||
87 | [BOOKE_INTERRUPT_MACHINE_CHECK] = 9, | ||
88 | [BOOKE_INTERRUPT_DEBUG] = 10, | ||
89 | [BOOKE_INTERRUPT_CRITICAL] = 11, | ||
90 | [BOOKE_INTERRUPT_WATCHDOG] = 12, | ||
91 | [BOOKE_INTERRUPT_EXTERNAL] = 13, | ||
92 | [BOOKE_INTERRUPT_FIT] = 14, | ||
93 | [BOOKE_INTERRUPT_DECREMENTER] = 15, | ||
94 | }; | ||
95 | |||
96 | const unsigned char priority_exception[] = { | ||
97 | BOOKE_INTERRUPT_DATA_STORAGE, | ||
98 | BOOKE_INTERRUPT_INST_STORAGE, | ||
99 | BOOKE_INTERRUPT_ALIGNMENT, | ||
100 | BOOKE_INTERRUPT_PROGRAM, | ||
101 | BOOKE_INTERRUPT_FP_UNAVAIL, | ||
102 | BOOKE_INTERRUPT_SYSCALL, | ||
103 | BOOKE_INTERRUPT_AP_UNAVAIL, | ||
104 | BOOKE_INTERRUPT_DTLB_MISS, | ||
105 | BOOKE_INTERRUPT_ITLB_MISS, | ||
106 | BOOKE_INTERRUPT_MACHINE_CHECK, | ||
107 | BOOKE_INTERRUPT_DEBUG, | ||
108 | BOOKE_INTERRUPT_CRITICAL, | ||
109 | BOOKE_INTERRUPT_WATCHDOG, | ||
110 | BOOKE_INTERRUPT_EXTERNAL, | ||
111 | BOOKE_INTERRUPT_FIT, | ||
112 | BOOKE_INTERRUPT_DECREMENTER, | ||
113 | }; | ||
114 | |||
115 | |||
116 | /* TODO: use vcpu_printf() */ | 58 | /* TODO: use vcpu_printf() */ |
117 | void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu) | 59 | void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu) |
118 | { | 60 | { |
@@ -133,103 +75,96 @@ void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu) | |||
133 | } | 75 | } |
134 | } | 76 | } |
135 | 77 | ||
136 | static void kvmppc_booke_queue_exception(struct kvm_vcpu *vcpu, int exception) | 78 | static void kvmppc_booke_queue_irqprio(struct kvm_vcpu *vcpu, |
79 | unsigned int priority) | ||
137 | { | 80 | { |
138 | unsigned int priority = exception_priority[exception]; | ||
139 | set_bit(priority, &vcpu->arch.pending_exceptions); | 81 | set_bit(priority, &vcpu->arch.pending_exceptions); |
140 | } | 82 | } |
141 | 83 | ||
142 | static void kvmppc_booke_clear_exception(struct kvm_vcpu *vcpu, int exception) | ||
143 | { | ||
144 | unsigned int priority = exception_priority[exception]; | ||
145 | clear_bit(priority, &vcpu->arch.pending_exceptions); | ||
146 | } | ||
147 | |||
148 | void kvmppc_core_queue_program(struct kvm_vcpu *vcpu) | 84 | void kvmppc_core_queue_program(struct kvm_vcpu *vcpu) |
149 | { | 85 | { |
150 | kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM); | 86 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_PROGRAM); |
151 | } | 87 | } |
152 | 88 | ||
153 | void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu) | 89 | void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu) |
154 | { | 90 | { |
155 | kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_DECREMENTER); | 91 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DECREMENTER); |
156 | } | 92 | } |
157 | 93 | ||
158 | int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu) | 94 | int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu) |
159 | { | 95 | { |
160 | unsigned int priority = exception_priority[BOOKE_INTERRUPT_DECREMENTER]; | 96 | return test_bit(BOOKE_IRQPRIO_DECREMENTER, &vcpu->arch.pending_exceptions); |
161 | return test_bit(priority, &vcpu->arch.pending_exceptions); | ||
162 | } | 97 | } |
163 | 98 | ||
164 | void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, | 99 | void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, |
165 | struct kvm_interrupt *irq) | 100 | struct kvm_interrupt *irq) |
166 | { | 101 | { |
167 | kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_EXTERNAL); | 102 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_EXTERNAL); |
168 | } | 103 | } |
169 | 104 | ||
170 | /* Check if we are ready to deliver the interrupt */ | 105 | /* Deliver the interrupt of the corresponding priority, if possible. */ |
171 | static int kvmppc_can_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt) | 106 | static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, |
107 | unsigned int priority) | ||
172 | { | 108 | { |
173 | int r; | 109 | int allowed = 0; |
174 | 110 | ulong msr_mask; | |
175 | switch (interrupt) { | 111 | |
176 | case BOOKE_INTERRUPT_CRITICAL: | 112 | switch (priority) { |
177 | r = vcpu->arch.msr & MSR_CE; | 113 | case BOOKE_IRQPRIO_PROGRAM: |
114 | case BOOKE_IRQPRIO_DTLB_MISS: | ||
115 | case BOOKE_IRQPRIO_ITLB_MISS: | ||
116 | case BOOKE_IRQPRIO_SYSCALL: | ||
117 | case BOOKE_IRQPRIO_DATA_STORAGE: | ||
118 | case BOOKE_IRQPRIO_INST_STORAGE: | ||
119 | case BOOKE_IRQPRIO_FP_UNAVAIL: | ||
120 | case BOOKE_IRQPRIO_AP_UNAVAIL: | ||
121 | case BOOKE_IRQPRIO_ALIGNMENT: | ||
122 | allowed = 1; | ||
123 | msr_mask = MSR_CE|MSR_ME|MSR_DE; | ||
178 | break; | 124 | break; |
179 | case BOOKE_INTERRUPT_MACHINE_CHECK: | 125 | case BOOKE_IRQPRIO_CRITICAL: |
180 | r = vcpu->arch.msr & MSR_ME; | 126 | case BOOKE_IRQPRIO_WATCHDOG: |
127 | allowed = vcpu->arch.msr & MSR_CE; | ||
128 | msr_mask = MSR_ME; | ||
181 | break; | 129 | break; |
182 | case BOOKE_INTERRUPT_EXTERNAL: | 130 | case BOOKE_IRQPRIO_MACHINE_CHECK: |
183 | r = vcpu->arch.msr & MSR_EE; | 131 | allowed = vcpu->arch.msr & MSR_ME; |
184 | break; | 132 | msr_mask = 0; |
185 | case BOOKE_INTERRUPT_DECREMENTER: | ||
186 | r = vcpu->arch.msr & MSR_EE; | ||
187 | break; | 133 | break; |
188 | case BOOKE_INTERRUPT_FIT: | 134 | case BOOKE_IRQPRIO_EXTERNAL: |
189 | r = vcpu->arch.msr & MSR_EE; | 135 | case BOOKE_IRQPRIO_DECREMENTER: |
136 | case BOOKE_IRQPRIO_FIT: | ||
137 | allowed = vcpu->arch.msr & MSR_EE; | ||
138 | msr_mask = MSR_CE|MSR_ME|MSR_DE; | ||
190 | break; | 139 | break; |
191 | case BOOKE_INTERRUPT_WATCHDOG: | 140 | case BOOKE_IRQPRIO_DEBUG: |
192 | r = vcpu->arch.msr & MSR_CE; | 141 | allowed = vcpu->arch.msr & MSR_DE; |
142 | msr_mask = MSR_ME; | ||
193 | break; | 143 | break; |
194 | case BOOKE_INTERRUPT_DEBUG: | ||
195 | r = vcpu->arch.msr & MSR_DE; | ||
196 | break; | ||
197 | default: | ||
198 | r = 1; | ||
199 | } | 144 | } |
200 | 145 | ||
201 | return r; | 146 | if (allowed) { |
202 | } | 147 | vcpu->arch.srr0 = vcpu->arch.pc; |
148 | vcpu->arch.srr1 = vcpu->arch.msr; | ||
149 | vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority]; | ||
150 | kvmppc_set_msr(vcpu, vcpu->arch.msr & msr_mask); | ||
203 | 151 | ||
204 | static void kvmppc_booke_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt) | 152 | clear_bit(priority, &vcpu->arch.pending_exceptions); |
205 | { | ||
206 | switch (interrupt) { | ||
207 | case BOOKE_INTERRUPT_DECREMENTER: | ||
208 | vcpu->arch.tsr |= TSR_DIS; | ||
209 | break; | ||
210 | } | 153 | } |
211 | 154 | ||
212 | vcpu->arch.srr0 = vcpu->arch.pc; | 155 | return allowed; |
213 | vcpu->arch.srr1 = vcpu->arch.msr; | ||
214 | vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[interrupt]; | ||
215 | kvmppc_set_msr(vcpu, vcpu->arch.msr & interrupt_msr_mask[interrupt]); | ||
216 | } | 156 | } |
217 | 157 | ||
218 | /* Check pending exceptions and deliver one, if possible. */ | 158 | /* Check pending exceptions and deliver one, if possible. */ |
219 | void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) | 159 | void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) |
220 | { | 160 | { |
221 | unsigned long *pending = &vcpu->arch.pending_exceptions; | 161 | unsigned long *pending = &vcpu->arch.pending_exceptions; |
222 | unsigned int exception; | ||
223 | unsigned int priority; | 162 | unsigned int priority; |
224 | 163 | ||
225 | priority = __ffs(*pending); | 164 | priority = __ffs(*pending); |
226 | while (priority <= BOOKE_MAX_INTERRUPT) { | 165 | while (priority <= BOOKE_MAX_INTERRUPT) { |
227 | exception = priority_exception[priority]; | 166 | if (kvmppc_booke_irqprio_deliver(vcpu, priority)) |
228 | if (kvmppc_can_deliver_interrupt(vcpu, exception)) { | ||
229 | kvmppc_booke_clear_exception(vcpu, exception); | ||
230 | kvmppc_booke_deliver_interrupt(vcpu, exception); | ||
231 | break; | 167 | break; |
232 | } | ||
233 | 168 | ||
234 | priority = find_next_bit(pending, | 169 | priority = find_next_bit(pending, |
235 | BITS_PER_BYTE * sizeof(*pending), | 170 | BITS_PER_BYTE * sizeof(*pending), |
@@ -287,7 +222,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
287 | /* Program traps generated by user-level software must be handled | 222 | /* Program traps generated by user-level software must be handled |
288 | * by the guest kernel. */ | 223 | * by the guest kernel. */ |
289 | vcpu->arch.esr = vcpu->arch.fault_esr; | 224 | vcpu->arch.esr = vcpu->arch.fault_esr; |
290 | kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM); | 225 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_PROGRAM); |
291 | r = RESUME_GUEST; | 226 | r = RESUME_GUEST; |
292 | break; | 227 | break; |
293 | } | 228 | } |
@@ -321,27 +256,27 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
321 | break; | 256 | break; |
322 | 257 | ||
323 | case BOOKE_INTERRUPT_FP_UNAVAIL: | 258 | case BOOKE_INTERRUPT_FP_UNAVAIL: |
324 | kvmppc_booke_queue_exception(vcpu, exit_nr); | 259 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_FP_UNAVAIL); |
325 | r = RESUME_GUEST; | 260 | r = RESUME_GUEST; |
326 | break; | 261 | break; |
327 | 262 | ||
328 | case BOOKE_INTERRUPT_DATA_STORAGE: | 263 | case BOOKE_INTERRUPT_DATA_STORAGE: |
329 | vcpu->arch.dear = vcpu->arch.fault_dear; | 264 | vcpu->arch.dear = vcpu->arch.fault_dear; |
330 | vcpu->arch.esr = vcpu->arch.fault_esr; | 265 | vcpu->arch.esr = vcpu->arch.fault_esr; |
331 | kvmppc_booke_queue_exception(vcpu, exit_nr); | 266 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DATA_STORAGE); |
332 | vcpu->stat.dsi_exits++; | 267 | vcpu->stat.dsi_exits++; |
333 | r = RESUME_GUEST; | 268 | r = RESUME_GUEST; |
334 | break; | 269 | break; |
335 | 270 | ||
336 | case BOOKE_INTERRUPT_INST_STORAGE: | 271 | case BOOKE_INTERRUPT_INST_STORAGE: |
337 | vcpu->arch.esr = vcpu->arch.fault_esr; | 272 | vcpu->arch.esr = vcpu->arch.fault_esr; |
338 | kvmppc_booke_queue_exception(vcpu, exit_nr); | 273 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_INST_STORAGE); |
339 | vcpu->stat.isi_exits++; | 274 | vcpu->stat.isi_exits++; |
340 | r = RESUME_GUEST; | 275 | r = RESUME_GUEST; |
341 | break; | 276 | break; |
342 | 277 | ||
343 | case BOOKE_INTERRUPT_SYSCALL: | 278 | case BOOKE_INTERRUPT_SYSCALL: |
344 | kvmppc_booke_queue_exception(vcpu, exit_nr); | 279 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SYSCALL); |
345 | vcpu->stat.syscall_exits++; | 280 | vcpu->stat.syscall_exits++; |
346 | r = RESUME_GUEST; | 281 | r = RESUME_GUEST; |
347 | break; | 282 | break; |
@@ -355,7 +290,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
355 | gtlbe = kvmppc_44x_dtlb_search(vcpu, eaddr); | 290 | gtlbe = kvmppc_44x_dtlb_search(vcpu, eaddr); |
356 | if (!gtlbe) { | 291 | if (!gtlbe) { |
357 | /* The guest didn't have a mapping for it. */ | 292 | /* The guest didn't have a mapping for it. */ |
358 | kvmppc_booke_queue_exception(vcpu, exit_nr); | 293 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS); |
359 | vcpu->arch.dear = vcpu->arch.fault_dear; | 294 | vcpu->arch.dear = vcpu->arch.fault_dear; |
360 | vcpu->arch.esr = vcpu->arch.fault_esr; | 295 | vcpu->arch.esr = vcpu->arch.fault_esr; |
361 | vcpu->stat.dtlb_real_miss_exits++; | 296 | vcpu->stat.dtlb_real_miss_exits++; |
@@ -398,7 +333,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
398 | gtlbe = kvmppc_44x_itlb_search(vcpu, eaddr); | 333 | gtlbe = kvmppc_44x_itlb_search(vcpu, eaddr); |
399 | if (!gtlbe) { | 334 | if (!gtlbe) { |
400 | /* The guest didn't have a mapping for it. */ | 335 | /* The guest didn't have a mapping for it. */ |
401 | kvmppc_booke_queue_exception(vcpu, exit_nr); | 336 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ITLB_MISS); |
402 | vcpu->stat.itlb_real_miss_exits++; | 337 | vcpu->stat.itlb_real_miss_exits++; |
403 | break; | 338 | break; |
404 | } | 339 | } |
@@ -418,7 +353,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
418 | gtlbe->word2); | 353 | gtlbe->word2); |
419 | } else { | 354 | } else { |
420 | /* Guest mapped and leaped at non-RAM! */ | 355 | /* Guest mapped and leaped at non-RAM! */ |
421 | kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_MACHINE_CHECK); | 356 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_MACHINE_CHECK); |
422 | } | 357 | } |
423 | 358 | ||
424 | break; | 359 | break; |
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h index f694a4b2dafa..48d905fd60ab 100644 --- a/arch/powerpc/kvm/booke.h +++ b/arch/powerpc/kvm/booke.h | |||
@@ -23,6 +23,24 @@ | |||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/kvm_host.h> | 24 | #include <linux/kvm_host.h> |
25 | 25 | ||
26 | /* interrupt priortity ordering */ | ||
27 | #define BOOKE_IRQPRIO_DATA_STORAGE 0 | ||
28 | #define BOOKE_IRQPRIO_INST_STORAGE 1 | ||
29 | #define BOOKE_IRQPRIO_ALIGNMENT 2 | ||
30 | #define BOOKE_IRQPRIO_PROGRAM 3 | ||
31 | #define BOOKE_IRQPRIO_FP_UNAVAIL 4 | ||
32 | #define BOOKE_IRQPRIO_SYSCALL 5 | ||
33 | #define BOOKE_IRQPRIO_AP_UNAVAIL 6 | ||
34 | #define BOOKE_IRQPRIO_DTLB_MISS 7 | ||
35 | #define BOOKE_IRQPRIO_ITLB_MISS 8 | ||
36 | #define BOOKE_IRQPRIO_MACHINE_CHECK 9 | ||
37 | #define BOOKE_IRQPRIO_DEBUG 10 | ||
38 | #define BOOKE_IRQPRIO_CRITICAL 11 | ||
39 | #define BOOKE_IRQPRIO_WATCHDOG 12 | ||
40 | #define BOOKE_IRQPRIO_EXTERNAL 13 | ||
41 | #define BOOKE_IRQPRIO_FIT 14 | ||
42 | #define BOOKE_IRQPRIO_DECREMENTER 15 | ||
43 | |||
26 | /* Helper function for "full" MSR writes. No need to call this if only EE is | 44 | /* Helper function for "full" MSR writes. No need to call this if only EE is |
27 | * changing. */ | 45 | * changing. */ |
28 | static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr) | 46 | static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr) |