diff options
Diffstat (limited to 'arch/powerpc/kvm/booke.c')
-rw-r--r-- | arch/powerpc/kvm/booke.c | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index b1e90a15155a..138014acf3cf 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
@@ -134,6 +134,40 @@ void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu) | |||
134 | } | 134 | } |
135 | } | 135 | } |
136 | 136 | ||
137 | static void kvmppc_booke_queue_exception(struct kvm_vcpu *vcpu, int exception) | ||
138 | { | ||
139 | unsigned int priority = exception_priority[exception]; | ||
140 | set_bit(priority, &vcpu->arch.pending_exceptions); | ||
141 | } | ||
142 | |||
143 | static void kvmppc_booke_clear_exception(struct kvm_vcpu *vcpu, int exception) | ||
144 | { | ||
145 | unsigned int priority = exception_priority[exception]; | ||
146 | clear_bit(priority, &vcpu->arch.pending_exceptions); | ||
147 | } | ||
148 | |||
149 | void kvmppc_core_queue_program(struct kvm_vcpu *vcpu) | ||
150 | { | ||
151 | kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM); | ||
152 | } | ||
153 | |||
154 | void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu) | ||
155 | { | ||
156 | kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_DECREMENTER); | ||
157 | } | ||
158 | |||
159 | int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu) | ||
160 | { | ||
161 | unsigned int priority = exception_priority[BOOKE_INTERRUPT_DECREMENTER]; | ||
162 | return test_bit(priority, &vcpu->arch.pending_exceptions); | ||
163 | } | ||
164 | |||
165 | void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, | ||
166 | struct kvm_interrupt *irq) | ||
167 | { | ||
168 | kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_EXTERNAL); | ||
169 | } | ||
170 | |||
137 | /* Check if we are ready to deliver the interrupt */ | 171 | /* Check if we are ready to deliver the interrupt */ |
138 | static int kvmppc_can_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt) | 172 | static int kvmppc_can_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt) |
139 | { | 173 | { |
@@ -168,7 +202,7 @@ static int kvmppc_can_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt) | |||
168 | return r; | 202 | return r; |
169 | } | 203 | } |
170 | 204 | ||
171 | static void kvmppc_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt) | 205 | static void kvmppc_booke_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt) |
172 | { | 206 | { |
173 | switch (interrupt) { | 207 | switch (interrupt) { |
174 | case BOOKE_INTERRUPT_DECREMENTER: | 208 | case BOOKE_INTERRUPT_DECREMENTER: |
@@ -183,7 +217,7 @@ static void kvmppc_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt) | |||
183 | } | 217 | } |
184 | 218 | ||
185 | /* Check pending exceptions and deliver one, if possible. */ | 219 | /* Check pending exceptions and deliver one, if possible. */ |
186 | void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu) | 220 | void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) |
187 | { | 221 | { |
188 | unsigned long *pending = &vcpu->arch.pending_exceptions; | 222 | unsigned long *pending = &vcpu->arch.pending_exceptions; |
189 | unsigned int exception; | 223 | unsigned int exception; |
@@ -193,8 +227,8 @@ void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu) | |||
193 | while (priority <= BOOKE_MAX_INTERRUPT) { | 227 | while (priority <= BOOKE_MAX_INTERRUPT) { |
194 | exception = priority_exception[priority]; | 228 | exception = priority_exception[priority]; |
195 | if (kvmppc_can_deliver_interrupt(vcpu, exception)) { | 229 | if (kvmppc_can_deliver_interrupt(vcpu, exception)) { |
196 | kvmppc_clear_exception(vcpu, exception); | 230 | kvmppc_booke_clear_exception(vcpu, exception); |
197 | kvmppc_deliver_interrupt(vcpu, exception); | 231 | kvmppc_booke_deliver_interrupt(vcpu, exception); |
198 | break; | 232 | break; |
199 | } | 233 | } |
200 | 234 | ||
@@ -251,7 +285,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
251 | /* Program traps generated by user-level software must be handled | 285 | /* Program traps generated by user-level software must be handled |
252 | * by the guest kernel. */ | 286 | * by the guest kernel. */ |
253 | vcpu->arch.esr = vcpu->arch.fault_esr; | 287 | vcpu->arch.esr = vcpu->arch.fault_esr; |
254 | kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM); | 288 | kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM); |
255 | r = RESUME_GUEST; | 289 | r = RESUME_GUEST; |
256 | break; | 290 | break; |
257 | } | 291 | } |
@@ -284,27 +318,27 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
284 | break; | 318 | break; |
285 | 319 | ||
286 | case BOOKE_INTERRUPT_FP_UNAVAIL: | 320 | case BOOKE_INTERRUPT_FP_UNAVAIL: |
287 | kvmppc_queue_exception(vcpu, exit_nr); | 321 | kvmppc_booke_queue_exception(vcpu, exit_nr); |
288 | r = RESUME_GUEST; | 322 | r = RESUME_GUEST; |
289 | break; | 323 | break; |
290 | 324 | ||
291 | case BOOKE_INTERRUPT_DATA_STORAGE: | 325 | case BOOKE_INTERRUPT_DATA_STORAGE: |
292 | vcpu->arch.dear = vcpu->arch.fault_dear; | 326 | vcpu->arch.dear = vcpu->arch.fault_dear; |
293 | vcpu->arch.esr = vcpu->arch.fault_esr; | 327 | vcpu->arch.esr = vcpu->arch.fault_esr; |
294 | kvmppc_queue_exception(vcpu, exit_nr); | 328 | kvmppc_booke_queue_exception(vcpu, exit_nr); |
295 | vcpu->stat.dsi_exits++; | 329 | vcpu->stat.dsi_exits++; |
296 | r = RESUME_GUEST; | 330 | r = RESUME_GUEST; |
297 | break; | 331 | break; |
298 | 332 | ||
299 | case BOOKE_INTERRUPT_INST_STORAGE: | 333 | case BOOKE_INTERRUPT_INST_STORAGE: |
300 | vcpu->arch.esr = vcpu->arch.fault_esr; | 334 | vcpu->arch.esr = vcpu->arch.fault_esr; |
301 | kvmppc_queue_exception(vcpu, exit_nr); | 335 | kvmppc_booke_queue_exception(vcpu, exit_nr); |
302 | vcpu->stat.isi_exits++; | 336 | vcpu->stat.isi_exits++; |
303 | r = RESUME_GUEST; | 337 | r = RESUME_GUEST; |
304 | break; | 338 | break; |
305 | 339 | ||
306 | case BOOKE_INTERRUPT_SYSCALL: | 340 | case BOOKE_INTERRUPT_SYSCALL: |
307 | kvmppc_queue_exception(vcpu, exit_nr); | 341 | kvmppc_booke_queue_exception(vcpu, exit_nr); |
308 | vcpu->stat.syscall_exits++; | 342 | vcpu->stat.syscall_exits++; |
309 | r = RESUME_GUEST; | 343 | r = RESUME_GUEST; |
310 | break; | 344 | break; |
@@ -318,7 +352,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
318 | gtlbe = kvmppc_44x_dtlb_search(vcpu, eaddr); | 352 | gtlbe = kvmppc_44x_dtlb_search(vcpu, eaddr); |
319 | if (!gtlbe) { | 353 | if (!gtlbe) { |
320 | /* The guest didn't have a mapping for it. */ | 354 | /* The guest didn't have a mapping for it. */ |
321 | kvmppc_queue_exception(vcpu, exit_nr); | 355 | kvmppc_booke_queue_exception(vcpu, exit_nr); |
322 | vcpu->arch.dear = vcpu->arch.fault_dear; | 356 | vcpu->arch.dear = vcpu->arch.fault_dear; |
323 | vcpu->arch.esr = vcpu->arch.fault_esr; | 357 | vcpu->arch.esr = vcpu->arch.fault_esr; |
324 | vcpu->stat.dtlb_real_miss_exits++; | 358 | vcpu->stat.dtlb_real_miss_exits++; |
@@ -360,7 +394,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
360 | gtlbe = kvmppc_44x_itlb_search(vcpu, eaddr); | 394 | gtlbe = kvmppc_44x_itlb_search(vcpu, eaddr); |
361 | if (!gtlbe) { | 395 | if (!gtlbe) { |
362 | /* The guest didn't have a mapping for it. */ | 396 | /* The guest didn't have a mapping for it. */ |
363 | kvmppc_queue_exception(vcpu, exit_nr); | 397 | kvmppc_booke_queue_exception(vcpu, exit_nr); |
364 | vcpu->stat.itlb_real_miss_exits++; | 398 | vcpu->stat.itlb_real_miss_exits++; |
365 | break; | 399 | break; |
366 | } | 400 | } |
@@ -380,8 +414,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
380 | gtlbe->word2); | 414 | gtlbe->word2); |
381 | } else { | 415 | } else { |
382 | /* Guest mapped and leaped at non-RAM! */ | 416 | /* Guest mapped and leaped at non-RAM! */ |
383 | kvmppc_queue_exception(vcpu, | 417 | kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_MACHINE_CHECK); |
384 | BOOKE_INTERRUPT_MACHINE_CHECK); | ||
385 | } | 418 | } |
386 | 419 | ||
387 | break; | 420 | break; |
@@ -409,7 +442,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
409 | 442 | ||
410 | local_irq_disable(); | 443 | local_irq_disable(); |
411 | 444 | ||
412 | kvmppc_check_and_deliver_interrupts(vcpu); | 445 | kvmppc_core_deliver_interrupts(vcpu); |
413 | 446 | ||
414 | /* Do some exit accounting. */ | 447 | /* Do some exit accounting. */ |
415 | vcpu->stat.sum_exits++; | 448 | vcpu->stat.sum_exits++; |