aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r--arch/powerpc/kvm/book3s_hv.c26
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S102
-rw-r--r--arch/powerpc/kvm/book3s_xics.c2
3 files changed, 112 insertions, 18 deletions
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 82ba00f68b07..16191915e8d0 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -66,6 +66,31 @@
66static void kvmppc_end_cede(struct kvm_vcpu *vcpu); 66static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
67static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu); 67static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu);
68 68
69void kvmppc_fast_vcpu_kick(struct kvm_vcpu *vcpu)
70{
71 int me;
72 int cpu = vcpu->cpu;
73 wait_queue_head_t *wqp;
74
75 wqp = kvm_arch_vcpu_wq(vcpu);
76 if (waitqueue_active(wqp)) {
77 wake_up_interruptible(wqp);
78 ++vcpu->stat.halt_wakeup;
79 }
80
81 me = get_cpu();
82
83 /* CPU points to the first thread of the core */
84 if (cpu != me && cpu >= 0 && cpu < nr_cpu_ids) {
85 int real_cpu = cpu + vcpu->arch.ptid;
86 if (paca[real_cpu].kvm_hstate.xics_phys)
87 xics_wake_cpu(real_cpu);
88 else if (cpu_online(cpu))
89 smp_send_reschedule(cpu);
90 }
91 put_cpu();
92}
93
69/* 94/*
70 * We use the vcpu_load/put functions to measure stolen time. 95 * We use the vcpu_load/put functions to measure stolen time.
71 * Stolen time is counted as time when either the vcpu is able to 96 * Stolen time is counted as time when either the vcpu is able to
@@ -985,7 +1010,6 @@ static void kvmppc_end_cede(struct kvm_vcpu *vcpu)
985} 1010}
986 1011
987extern int __kvmppc_vcore_entry(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu); 1012extern int __kvmppc_vcore_entry(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
988extern void xics_wake_cpu(int cpu);
989 1013
990static void kvmppc_remove_runnable(struct kvmppc_vcore *vc, 1014static void kvmppc_remove_runnable(struct kvmppc_vcore *vc,
991 struct kvm_vcpu *vcpu) 1015 struct kvm_vcpu *vcpu)
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 0f23bb851711..56f8927b0ddf 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -79,10 +79,6 @@ _GLOBAL(kvmppc_hv_entry_trampoline)
79 * * 79 * *
80 *****************************************************************************/ 80 *****************************************************************************/
81 81
82#define XICS_XIRR 4
83#define XICS_QIRR 0xc
84#define XICS_IPI 2 /* interrupt source # for IPIs */
85
86/* 82/*
87 * We come in here when wakened from nap mode on a secondary hw thread. 83 * We come in here when wakened from nap mode on a secondary hw thread.
88 * Relocation is off and most register values are lost. 84 * Relocation is off and most register values are lost.
@@ -122,7 +118,7 @@ kvm_start_guest:
122 beq 27f 118 beq 27f
12325: ld r5,HSTATE_XICS_PHYS(r13) 11925: ld r5,HSTATE_XICS_PHYS(r13)
124 li r0,0xff 120 li r0,0xff
125 li r6,XICS_QIRR 121 li r6,XICS_MFRR
126 li r7,XICS_XIRR 122 li r7,XICS_XIRR
127 lwzcix r8,r5,r7 /* get and ack the interrupt */ 123 lwzcix r8,r5,r7 /* get and ack the interrupt */
128 sync 124 sync
@@ -678,17 +674,91 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
678 cmpwi r12,BOOK3S_INTERRUPT_SYSCALL 674 cmpwi r12,BOOK3S_INTERRUPT_SYSCALL
679 beq hcall_try_real_mode 675 beq hcall_try_real_mode
680 676
681 /* Check for mediated interrupts (could be done earlier really ...) */ 677 /* Only handle external interrupts here on arch 206 and later */
682BEGIN_FTR_SECTION 678BEGIN_FTR_SECTION
683 cmpwi r12,BOOK3S_INTERRUPT_EXTERNAL 679 b ext_interrupt_to_host
684 bne+ 1f 680END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
685 andi. r0,r11,MSR_EE 681
686 beq 1f 682 /* External interrupt ? */
687 mfspr r5,SPRN_LPCR 683 cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL
688 andi. r0,r5,LPCR_MER 684 bne+ ext_interrupt_to_host
685
686 /* External interrupt, first check for host_ipi. If this is
687 * set, we know the host wants us out so let's do it now
688 */
689 lbz r0, HSTATE_HOST_IPI(r13)
690 cmpwi r0, 0
691 bne ext_interrupt_to_host
692
693 /* Now read the interrupt from the ICP */
694 ld r5, HSTATE_XICS_PHYS(r13)
695 li r7, XICS_XIRR
696 cmpdi r5, 0
697 beq- ext_interrupt_to_host
698 lwzcix r3, r5, r7
699 rlwinm. r0, r3, 0, 0xffffff
700 sync
701 bne 1f
702
703 /* Nothing pending in the ICP, check for mediated interrupts
704 * and bounce it to the guest
705 */
706 andi. r0, r11, MSR_EE
707 beq ext_interrupt_to_host /* shouldn't happen ?? */
708 mfspr r5, SPRN_LPCR
709 andi. r0, r5, LPCR_MER
689 bne bounce_ext_interrupt 710 bne bounce_ext_interrupt
6901: 711 b ext_interrupt_to_host /* shouldn't happen ?? */
691END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) 712
7131: /* We found something in the ICP...
714 *
715 * If it's not an IPI, stash it in the PACA and return to
716 * the host, we don't (yet) handle directing real external
717 * interrupts directly to the guest
718 */
719 cmpwi r0, XICS_IPI
720 bne ext_stash_for_host
721
722 /* It's an IPI, clear the MFRR and EOI it */
723 li r0, 0xff
724 li r6, XICS_MFRR
725 stbcix r0, r5, r6 /* clear the IPI */
726 stwcix r3, r5, r7 /* EOI it */
727 sync
728
729 /* We need to re-check host IPI now in case it got set in the
730 * meantime. If it's clear, we bounce the interrupt to the
731 * guest
732 */
733 lbz r0, HSTATE_HOST_IPI(r13)
734 cmpwi r0, 0
735 bne- 1f
736
737 /* Allright, looks like an IPI for the guest, we need to set MER */
738 mfspr r8,SPRN_LPCR
739 ori r8,r8,LPCR_MER
740 mtspr SPRN_LPCR,r8
741
742 /* And if the guest EE is set, we can deliver immediately, else
743 * we return to the guest with MER set
744 */
745 andi. r0, r11, MSR_EE
746 bne bounce_ext_interrupt
747 mr r4, r9
748 b fast_guest_return
749
750 /* We raced with the host, we need to resend that IPI, bummer */
7511: li r0, IPI_PRIORITY
752 stbcix r0, r5, r6 /* set the IPI */
753 sync
754 b ext_interrupt_to_host
755
756ext_stash_for_host:
757 /* It's not an IPI and it's for the host, stash it in the PACA
758 * before exit, it will be picked up by the host ICP driver
759 */
760 stw r3, HSTATE_SAVED_XIRR(r13)
761ext_interrupt_to_host:
692 762
693guest_exit_cont: /* r9 = vcpu, r12 = trap, r13 = paca */ 763guest_exit_cont: /* r9 = vcpu, r12 = trap, r13 = paca */
694 /* Save DEC */ 764 /* Save DEC */
@@ -831,7 +901,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
831 beq 44f 901 beq 44f
832 ld r8,HSTATE_XICS_PHYS(r6) /* get thread's XICS reg addr */ 902 ld r8,HSTATE_XICS_PHYS(r6) /* get thread's XICS reg addr */
833 li r0,IPI_PRIORITY 903 li r0,IPI_PRIORITY
834 li r7,XICS_QIRR 904 li r7,XICS_MFRR
835 stbcix r0,r7,r8 /* trigger the IPI */ 905 stbcix r0,r7,r8 /* trigger the IPI */
83644: srdi. r3,r3,1 90644: srdi. r3,r3,1
837 addi r6,r6,PACA_SIZE 907 addi r6,r6,PACA_SIZE
@@ -1630,7 +1700,7 @@ secondary_nap:
1630 beq 37f 1700 beq 37f
1631 sync 1701 sync
1632 li r0, 0xff 1702 li r0, 0xff
1633 li r6, XICS_QIRR 1703 li r6, XICS_MFRR
1634 stbcix r0, r5, r6 /* clear the IPI */ 1704 stbcix r0, r5, r6 /* clear the IPI */
1635 stwcix r3, r5, r7 /* EOI it */ 1705 stwcix r3, r5, r7 /* EOI it */
163637: sync 170637: sync
diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c
index 53af848116f2..1417e65b6bbd 100644
--- a/arch/powerpc/kvm/book3s_xics.c
+++ b/arch/powerpc/kvm/book3s_xics.c
@@ -227,7 +227,7 @@ static inline bool icp_try_update(struct kvmppc_icp *icp,
227 kvmppc_book3s_queue_irqprio(icp->vcpu, 227 kvmppc_book3s_queue_irqprio(icp->vcpu,
228 BOOK3S_INTERRUPT_EXTERNAL_LEVEL); 228 BOOK3S_INTERRUPT_EXTERNAL_LEVEL);
229 if (!change_self) 229 if (!change_self)
230 kvm_vcpu_kick(icp->vcpu); 230 kvmppc_fast_vcpu_kick(icp->vcpu);
231 } 231 }
232 bail: 232 bail:
233 return success; 233 return success;