aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kvm/booke.c56
1 files changed, 41 insertions, 15 deletions
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index ee39c8a80c63..488936bece69 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -595,37 +595,63 @@ static int emulation_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
595 } 595 }
596} 596}
597 597
598/** 598static void kvmppc_fill_pt_regs(struct pt_regs *regs)
599 * kvmppc_handle_exit
600 *
601 * Return value is in the form (errcode<<2 | RESUME_FLAG_HOST | RESUME_FLAG_NV)
602 */
603int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
604 unsigned int exit_nr)
605{ 599{
606 int r = RESUME_HOST; 600 ulong r1, ip, msr, lr;
601
602 asm("mr %0, 1" : "=r"(r1));
603 asm("mflr %0" : "=r"(lr));
604 asm("mfmsr %0" : "=r"(msr));
605 asm("bl 1f; 1: mflr %0" : "=r"(ip));
606
607 memset(regs, 0, sizeof(*regs));
608 regs->gpr[1] = r1;
609 regs->nip = ip;
610 regs->msr = msr;
611 regs->link = lr;
612}
607 613
608 /* update before a new last_exit_type is rewritten */ 614static void kvmppc_restart_interrupt(struct kvm_vcpu *vcpu,
609 kvmppc_update_timing_stats(vcpu); 615 unsigned int exit_nr)
616{
617 struct pt_regs regs;
610 618
611 switch (exit_nr) { 619 switch (exit_nr) {
612 case BOOKE_INTERRUPT_EXTERNAL: 620 case BOOKE_INTERRUPT_EXTERNAL:
613 do_IRQ(current->thread.regs); 621 kvmppc_fill_pt_regs(&regs);
622 do_IRQ(&regs);
614 break; 623 break;
615
616 case BOOKE_INTERRUPT_DECREMENTER: 624 case BOOKE_INTERRUPT_DECREMENTER:
617 timer_interrupt(current->thread.regs); 625 kvmppc_fill_pt_regs(&regs);
626 timer_interrupt(&regs);
618 break; 627 break;
619
620#if defined(CONFIG_PPC_FSL_BOOK3E) || defined(CONFIG_PPC_BOOK3E_64) 628#if defined(CONFIG_PPC_FSL_BOOK3E) || defined(CONFIG_PPC_BOOK3E_64)
621 case BOOKE_INTERRUPT_DOORBELL: 629 case BOOKE_INTERRUPT_DOORBELL:
622 doorbell_exception(current->thread.regs); 630 kvmppc_fill_pt_regs(&regs);
631 doorbell_exception(&regs);
623 break; 632 break;
624#endif 633#endif
625 case BOOKE_INTERRUPT_MACHINE_CHECK: 634 case BOOKE_INTERRUPT_MACHINE_CHECK:
626 /* FIXME */ 635 /* FIXME */
627 break; 636 break;
628 } 637 }
638}
639
640/**
641 * kvmppc_handle_exit
642 *
643 * Return value is in the form (errcode<<2 | RESUME_FLAG_HOST | RESUME_FLAG_NV)
644 */
645int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
646 unsigned int exit_nr)
647{
648 int r = RESUME_HOST;
649
650 /* update before a new last_exit_type is rewritten */
651 kvmppc_update_timing_stats(vcpu);
652
653 /* restart interrupts if they were meant for the host */
654 kvmppc_restart_interrupt(vcpu, exit_nr);
629 655
630 local_irq_enable(); 656 local_irq_enable();
631 657