diff options
| -rw-r--r-- | arch/powerpc/kvm/booke.c | 56 |
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 | /** | 598 | static 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 | */ | ||
| 603 | int 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 */ | 614 | static 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(®s); |
| 622 | do_IRQ(®s); | ||
| 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(®s); |
| 626 | timer_interrupt(®s); | ||
| 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(®s); |
| 631 | doorbell_exception(®s); | ||
| 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 | */ | ||
| 645 | int 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 | ||
