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_rmhandlers.S117
1 files changed, 68 insertions, 49 deletions
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 2bf295102f6a..c91ae2b67845 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -862,46 +862,11 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
862 * set, we know the host wants us out so let's do it now 862 * set, we know the host wants us out so let's do it now
863 */ 863 */
864do_ext_interrupt: 864do_ext_interrupt:
865 lbz r0, HSTATE_HOST_IPI(r13) 865 bl kvmppc_read_intr
866 cmpwi r0, 0 866 cmpdi r3, 0
867 bne ext_interrupt_to_host 867 bgt ext_interrupt_to_host
868
869 /* Now read the interrupt from the ICP */
870 ld r5, HSTATE_XICS_PHYS(r13)
871 li r7, XICS_XIRR
872 cmpdi r5, 0
873 beq- ext_interrupt_to_host
874 lwzcix r3, r5, r7
875 rlwinm. r0, r3, 0, 0xffffff
876 sync
877 beq 3f /* if nothing pending in the ICP */
878
879 /* We found something in the ICP...
880 *
881 * If it's not an IPI, stash it in the PACA and return to
882 * the host, we don't (yet) handle directing real external
883 * interrupts directly to the guest
884 */
885 cmpwi r0, XICS_IPI
886 bne ext_stash_for_host
887
888 /* It's an IPI, clear the MFRR and EOI it */
889 li r0, 0xff
890 li r6, XICS_MFRR
891 stbcix r0, r5, r6 /* clear the IPI */
892 stwcix r3, r5, r7 /* EOI it */
893 sync
894
895 /* We need to re-check host IPI now in case it got set in the
896 * meantime. If it's clear, we bounce the interrupt to the
897 * guest
898 */
899 lbz r0, HSTATE_HOST_IPI(r13)
900 cmpwi r0, 0
901 bne- 1f
902 868
903 /* Allright, looks like an IPI for the guest, we need to set MER */ 869 /* Allright, looks like an IPI for the guest, we need to set MER */
9043:
905 /* Check if any CPU is heading out to the host, if so head out too */ 870 /* Check if any CPU is heading out to the host, if so head out too */
906 ld r5, HSTATE_KVM_VCORE(r13) 871 ld r5, HSTATE_KVM_VCORE(r13)
907 lwz r0, VCORE_ENTRY_EXIT(r5) 872 lwz r0, VCORE_ENTRY_EXIT(r5)
@@ -930,17 +895,6 @@ do_ext_interrupt:
930 mtspr SPRN_LPCR, r8 895 mtspr SPRN_LPCR, r8
931 b fast_guest_return 896 b fast_guest_return
932 897
933 /* We raced with the host, we need to resend that IPI, bummer */
9341: li r0, IPI_PRIORITY
935 stbcix r0, r5, r6 /* set the IPI */
936 sync
937 b ext_interrupt_to_host
938
939ext_stash_for_host:
940 /* It's not an IPI and it's for the host, stash it in the PACA
941 * before exit, it will be picked up by the host ICP driver
942 */
943 stw r3, HSTATE_SAVED_XIRR(r13)
944ext_interrupt_to_host: 898ext_interrupt_to_host:
945 899
946guest_exit_cont: /* r9 = vcpu, r12 = trap, r13 = paca */ 900guest_exit_cont: /* r9 = vcpu, r12 = trap, r13 = paca */
@@ -1816,6 +1770,71 @@ machine_check_realmode:
1816 b fast_interrupt_c_return 1770 b fast_interrupt_c_return
1817 1771
1818/* 1772/*
1773 * Determine what sort of external interrupt is pending (if any).
1774 * Returns:
1775 * 0 if no interrupt is pending
1776 * 1 if an interrupt is pending that needs to be handled by the host
1777 * -1 if there was a guest wakeup IPI (which has now been cleared)
1778 */
1779kvmppc_read_intr:
1780 /* see if a host IPI is pending */
1781 li r3, 1
1782 lbz r0, HSTATE_HOST_IPI(r13)
1783 cmpwi r0, 0
1784 bne 1f
1785
1786 /* Now read the interrupt from the ICP */
1787 ld r6, HSTATE_XICS_PHYS(r13)
1788 li r7, XICS_XIRR
1789 cmpdi r6, 0
1790 beq- 1f
1791 lwzcix r0, r6, r7
1792 rlwinm. r3, r0, 0, 0xffffff
1793 sync
1794 beq 1f /* if nothing pending in the ICP */
1795
1796 /* We found something in the ICP...
1797 *
1798 * If it's not an IPI, stash it in the PACA and return to
1799 * the host, we don't (yet) handle directing real external
1800 * interrupts directly to the guest
1801 */
1802 cmpwi r3, XICS_IPI /* if there is, is it an IPI? */
1803 li r3, 1
1804 bne 42f
1805
1806 /* It's an IPI, clear the MFRR and EOI it */
1807 li r3, 0xff
1808 li r8, XICS_MFRR
1809 stbcix r3, r6, r8 /* clear the IPI */
1810 stwcix r0, r6, r7 /* EOI it */
1811 sync
1812
1813 /* We need to re-check host IPI now in case it got set in the
1814 * meantime. If it's clear, we bounce the interrupt to the
1815 * guest
1816 */
1817 lbz r0, HSTATE_HOST_IPI(r13)
1818 cmpwi r0, 0
1819 bne- 43f
1820
1821 /* OK, it's an IPI for us */
1822 li r3, -1
18231: blr
1824
182542: /* It's not an IPI and it's for the host, stash it in the PACA
1826 * before exit, it will be picked up by the host ICP driver
1827 */
1828 stw r0, HSTATE_SAVED_XIRR(r13)
1829 b 1b
1830
183143: /* We raced with the host, we need to resend that IPI, bummer */
1832 li r0, IPI_PRIORITY
1833 stbcix r0, r6, r8 /* set the IPI */
1834 sync
1835 b 1b
1836
1837/*
1819 * Save away FP, VMX and VSX registers. 1838 * Save away FP, VMX and VSX registers.
1820 * r3 = vcpu pointer 1839 * r3 = vcpu pointer
1821 */ 1840 */