aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2014-01-08 05:25:25 -0500
committerAlexander Graf <agraf@suse.de>2014-01-27 10:01:08 -0500
commite3bbbbfa13ea2901050a58b2cb382df7974e7373 (patch)
tree15e9aa6331873878ff0a91d77131c240dafb4162
parent5557ae0ec77c2b4b5bbce2883c0603054ab66e68 (diff)
KVM: PPC: Book3S HV: Consolidate code that checks reason for wake from nap
Currently in book3s_hv_rmhandlers.S we have three places where we have woken up from nap mode and we check the reason field in SRR1 to see what event woke us up. This consolidates them into a new function, kvmppc_check_wake_reason. It looks at the wake reason field in SRR1, and if it indicates that an external interrupt caused the wakeup, calls kvmppc_read_intr to check what sort of interrupt it was. This also consolidates the two places where we synthesize an external interrupt (0x500 vector) for the guest. Now, if the guest exit code finds that there was an external interrupt which has been handled (i.e. it was an IPI indicating that there is now an interrupt pending for the guest), it jumps to deliver_guest_interrupt, which is in the last part of the guest entry code, where we synthesize guest external and decrementer interrupts. That code has been streamlined a little and now clears LPCR[MER] when appropriate as well as setting it. The extra clearing of any pending IPI on a secondary, offline CPU thread before going back to nap mode has been removed. It is no longer necessary now that we have code to read and acknowledge IPIs in the guest exit path. This fixes a minor bug in the H_CEDE real-mode handling - previously, if we found that other threads were already exiting the guest when we were about to go to nap mode, we would branch to the cede wakeup path and end up looking in SRR1 for a wakeup reason. Now we branch to a point after we have checked the wakeup reason. This also fixes a minor bug in kvmppc_read_intr - previously it could return 0xff rather than 1, in the case where we find that a host IPI is pending after we have cleared the IPI. Now it returns 1. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de>
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S192
1 files changed, 77 insertions, 115 deletions
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 19f8819f90fa..386e141dbf16 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -193,8 +193,10 @@ kvm_novcpu_wakeup:
193 stb r0, HSTATE_NAPPING(r13) 193 stb r0, HSTATE_NAPPING(r13)
194 stb r0, HSTATE_HWTHREAD_REQ(r13) 194 stb r0, HSTATE_HWTHREAD_REQ(r13)
195 195
196 /* check the wake reason */
197 bl kvmppc_check_wake_reason
198
196 /* see if any other thread is already exiting */ 199 /* see if any other thread is already exiting */
197 li r12, 0
198 lwz r0, VCORE_ENTRY_EXIT(r5) 200 lwz r0, VCORE_ENTRY_EXIT(r5)
199 cmpwi r0, 0x100 201 cmpwi r0, 0x100
200 bge kvm_novcpu_exit 202 bge kvm_novcpu_exit
@@ -204,23 +206,14 @@ kvm_novcpu_wakeup:
204 li r0, 1 206 li r0, 1
205 sld r0, r0, r7 207 sld r0, r0, r7
206 addi r6, r5, VCORE_NAPPING_THREADS 208 addi r6, r5, VCORE_NAPPING_THREADS
2074: lwarx r3, 0, r6 2094: lwarx r7, 0, r6
208 andc r3, r3, r0 210 andc r7, r7, r0
209 stwcx. r3, 0, r6 211 stwcx. r7, 0, r6
210 bne 4b 212 bne 4b
211 213
212 /* Check the wake reason in SRR1 to see why we got here */ 214 /* See if the wake reason means we need to exit */
213 mfspr r3, SPRN_SRR1
214 rlwinm r3, r3, 44-31, 0x7 /* extract wake reason field */
215 cmpwi r3, 4 /* was it an external interrupt? */
216 bne kvm_novcpu_exit /* if not, exit the guest */
217
218 /* extern interrupt - read and handle it */
219 li r12, BOOK3S_INTERRUPT_EXTERNAL
220 bl kvmppc_read_intr
221 cmpdi r3, 0 215 cmpdi r3, 0
222 bge kvm_novcpu_exit 216 bge kvm_novcpu_exit
223 li r12, 0
224 217
225 /* Got an IPI but other vcpus aren't yet exiting, must be a latecomer */ 218 /* Got an IPI but other vcpus aren't yet exiting, must be a latecomer */
226 ld r4, HSTATE_KVM_VCPU(r13) 219 ld r4, HSTATE_KVM_VCPU(r13)
@@ -264,40 +257,16 @@ kvm_start_guest:
264 */ 257 */
265 258
266 /* Check the wake reason in SRR1 to see why we got here */ 259 /* Check the wake reason in SRR1 to see why we got here */
267 mfspr r3,SPRN_SRR1 260 bl kvmppc_check_wake_reason
268 rlwinm r3,r3,44-31,0x7 /* extract wake reason field */ 261 cmpdi r3, 0
269 cmpwi r3,4 /* was it an external interrupt? */ 262 bge kvm_no_guest
270 bne 27f /* if not */
271 ld r5,HSTATE_XICS_PHYS(r13)
272 li r7,XICS_XIRR /* if it was an external interrupt, */
273 lwzcix r8,r5,r7 /* get and ack the interrupt */
274 sync
275 clrldi. r9,r8,40 /* get interrupt source ID. */
276 beq 28f /* none there? */
277 cmpwi r9,XICS_IPI /* was it an IPI? */
278 bne 29f
279 li r0,0xff
280 li r6,XICS_MFRR
281 stbcix r0,r5,r6 /* clear IPI */
282 stwcix r8,r5,r7 /* EOI the interrupt */
283 sync /* order loading of vcpu after that */
284 263
285 /* get vcpu pointer, NULL if we have no vcpu to run */ 264 /* get vcpu pointer, NULL if we have no vcpu to run */
286 ld r4,HSTATE_KVM_VCPU(r13) 265 ld r4,HSTATE_KVM_VCPU(r13)
287 cmpdi r4,0 266 cmpdi r4,0
288 /* if we have no vcpu to run, go back to sleep */ 267 /* if we have no vcpu to run, go back to sleep */
289 beq kvm_no_guest 268 beq kvm_no_guest
290 b 30f
291 269
29227: /* XXX should handle hypervisor maintenance interrupts etc. here */
293 b kvm_no_guest
29428: /* SRR1 said external but ICP said nope?? */
295 b kvm_no_guest
29629: /* External non-IPI interrupt to offline secondary thread? help?? */
297 stw r8,HSTATE_SAVED_XIRR(r13)
298 b kvm_no_guest
299
30030:
301 /* Set HSTATE_DSCR(r13) to something sensible */ 270 /* Set HSTATE_DSCR(r13) to something sensible */
302 LOAD_REG_ADDR(r6, dscr_default) 271 LOAD_REG_ADDR(r6, dscr_default)
303 ld r6, 0(r6) 272 ld r6, 0(r6)
@@ -310,18 +279,6 @@ kvm_start_guest:
310 li r0, 0 279 li r0, 0
311 std r0, HSTATE_KVM_VCPU(r13) 280 std r0, HSTATE_KVM_VCPU(r13)
312 lwsync 281 lwsync
313 /* Clear any pending IPI - we're an offline thread */
314 ld r5, HSTATE_XICS_PHYS(r13)
315 li r7, XICS_XIRR
316 lwzcix r3, r5, r7 /* ack any pending interrupt */
317 rlwinm. r0, r3, 0, 0xffffff /* any pending? */
318 beq 37f
319 sync
320 li r0, 0xff
321 li r6, XICS_MFRR
322 stbcix r0, r5, r6 /* clear the IPI */
323 stwcix r3, r5, r7 /* EOI it */
32437: sync
325 282
326 /* increment the nap count and then go to nap mode */ 283 /* increment the nap count and then go to nap mode */
327 ld r4, HSTATE_KVM_VCORE(r13) 284 ld r4, HSTATE_KVM_VCORE(r13)
@@ -818,47 +775,46 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
818 mtctr r6 775 mtctr r6
819 mtxer r7 776 mtxer r7
820 777
778kvmppc_cede_reentry: /* r4 = vcpu, r13 = paca */
821 ld r10, VCPU_PC(r4) 779 ld r10, VCPU_PC(r4)
822 ld r11, VCPU_MSR(r4) 780 ld r11, VCPU_MSR(r4)
823kvmppc_cede_reentry: /* r4 = vcpu, r13 = paca */
824 ld r6, VCPU_SRR0(r4) 781 ld r6, VCPU_SRR0(r4)
825 ld r7, VCPU_SRR1(r4) 782 ld r7, VCPU_SRR1(r4)
783 mtspr SPRN_SRR0, r6
784 mtspr SPRN_SRR1, r7
826 785
786deliver_guest_interrupt:
827 /* r11 = vcpu->arch.msr & ~MSR_HV */ 787 /* r11 = vcpu->arch.msr & ~MSR_HV */
828 rldicl r11, r11, 63 - MSR_HV_LG, 1 788 rldicl r11, r11, 63 - MSR_HV_LG, 1
829 rotldi r11, r11, 1 + MSR_HV_LG 789 rotldi r11, r11, 1 + MSR_HV_LG
830 ori r11, r11, MSR_ME 790 ori r11, r11, MSR_ME
831 791
832 /* Check if we can deliver an external or decrementer interrupt now */ 792 /* Check if we can deliver an external or decrementer interrupt now */
833 ld r0,VCPU_PENDING_EXC(r4) 793 ld r0, VCPU_PENDING_EXC(r4)
834 lis r8,(1 << BOOK3S_IRQPRIO_EXTERNAL_LEVEL)@h 794 rldicl r0, r0, 64 - BOOK3S_IRQPRIO_EXTERNAL_LEVEL, 63
835 and r0,r0,r8 795 cmpdi cr1, r0, 0
836 cmpdi cr1,r0,0 796 andi. r8, r11, MSR_EE
837 andi. r0,r11,MSR_EE
838 beq cr1,11f
839BEGIN_FTR_SECTION 797BEGIN_FTR_SECTION
840 mfspr r8,SPRN_LPCR 798 mfspr r8, SPRN_LPCR
841 ori r8,r8,LPCR_MER 799 /* Insert EXTERNAL_LEVEL bit into LPCR at the MER bit position */
842 mtspr SPRN_LPCR,r8 800 rldimi r8, r0, LPCR_MER_SH, 63 - LPCR_MER_SH
801 mtspr SPRN_LPCR, r8
843 isync 802 isync
844END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) 803END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
845 beq 5f 804 beq 5f
846 li r0,BOOK3S_INTERRUPT_EXTERNAL 805 li r0, BOOK3S_INTERRUPT_EXTERNAL
84712: mr r6,r10 806 bne cr1, 12f
807 mfspr r0, SPRN_DEC
808 cmpwi r0, 0
809 li r0, BOOK3S_INTERRUPT_DECREMENTER
810 bge 5f
811
81212: mtspr SPRN_SRR0, r10
848 mr r10,r0 813 mr r10,r0
849 mr r7,r11 814 mtspr SPRN_SRR1, r11
850 li r11,(MSR_ME << 1) | 1 /* synthesize MSR_SF | MSR_ME */ 815 li r11,(MSR_ME << 1) | 1 /* synthesize MSR_SF | MSR_ME */
851 rotldi r11,r11,63 816 rotldi r11,r11,63
852 b 5f 8175:
85311: beq 5f
854 mfspr r0,SPRN_DEC
855 cmpwi r0,0
856 li r0,BOOK3S_INTERRUPT_DECREMENTER
857 blt 12b
858
859 /* Move SRR0 and SRR1 into the respective regs */
8605: mtspr SPRN_SRR0, r6
861 mtspr SPRN_SRR1, r7
862 818
863/* 819/*
864 * Required state: 820 * Required state:
@@ -1047,39 +1003,19 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
1047 /* External interrupt, first check for host_ipi. If this is 1003 /* External interrupt, first check for host_ipi. If this is
1048 * set, we know the host wants us out so let's do it now 1004 * set, we know the host wants us out so let's do it now
1049 */ 1005 */
1050do_ext_interrupt:
1051 bl kvmppc_read_intr 1006 bl kvmppc_read_intr
1052 cmpdi r3, 0 1007 cmpdi r3, 0
1053 bgt ext_interrupt_to_host 1008 bgt ext_interrupt_to_host
1054 1009
1055 /* Allright, looks like an IPI for the guest, we need to set MER */
1056 /* Check if any CPU is heading out to the host, if so head out too */ 1010 /* Check if any CPU is heading out to the host, if so head out too */
1057 ld r5, HSTATE_KVM_VCORE(r13) 1011 ld r5, HSTATE_KVM_VCORE(r13)
1058 lwz r0, VCORE_ENTRY_EXIT(r5) 1012 lwz r0, VCORE_ENTRY_EXIT(r5)
1059 cmpwi r0, 0x100 1013 cmpwi r0, 0x100
1060 bge ext_interrupt_to_host 1014 bge ext_interrupt_to_host
1061 1015
1062 /* See if there is a pending interrupt for the guest */ 1016 /* Return to guest after delivering any pending interrupt */
1063 mfspr r8, SPRN_LPCR 1017 mr r4, r9
1064 ld r0, VCPU_PENDING_EXC(r9) 1018 b deliver_guest_interrupt
1065 /* Insert EXTERNAL_LEVEL bit into LPCR at the MER bit position */
1066 rldicl. r0, r0, 64 - BOOK3S_IRQPRIO_EXTERNAL_LEVEL, 63
1067 rldimi r8, r0, LPCR_MER_SH, 63 - LPCR_MER_SH
1068 beq 2f
1069
1070 /* And if the guest EE is set, we can deliver immediately, else
1071 * we return to the guest with MER set
1072 */
1073 andi. r0, r11, MSR_EE
1074 beq 2f
1075 mtspr SPRN_SRR0, r10
1076 mtspr SPRN_SRR1, r11
1077 li r10, BOOK3S_INTERRUPT_EXTERNAL
1078 li r11, (MSR_ME << 1) | 1 /* synthesize MSR_SF | MSR_ME */
1079 rotldi r11, r11, 63
10802: mr r4, r9
1081 mtspr SPRN_LPCR, r8
1082 b fast_guest_return
1083 1019
1084ext_interrupt_to_host: 1020ext_interrupt_to_host:
1085 1021
@@ -1887,7 +1823,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
1887 stb r0,HSTATE_NAPPING(r13) 1823 stb r0,HSTATE_NAPPING(r13)
1888 /* order napping_threads update vs testing entry_exit_count */ 1824 /* order napping_threads update vs testing entry_exit_count */
1889 lwsync 1825 lwsync
1890 mr r4,r3
1891 lwz r7,VCORE_ENTRY_EXIT(r5) 1826 lwz r7,VCORE_ENTRY_EXIT(r5)
1892 cmpwi r7,0x100 1827 cmpwi r7,0x100
1893 bge 33f /* another thread already exiting */ 1828 bge 33f /* another thread already exiting */
@@ -1940,6 +1875,11 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
1940 nap 1875 nap
1941 b . 1876 b .
1942 1877
187833: mr r4, r3
1879 li r3, 0
1880 li r12, 0
1881 b 34f
1882
1943kvm_end_cede: 1883kvm_end_cede:
1944 /* get vcpu pointer */ 1884 /* get vcpu pointer */
1945 ld r4, HSTATE_KVM_VCPU(r13) 1885 ld r4, HSTATE_KVM_VCPU(r13)
@@ -1969,12 +1909,15 @@ kvm_end_cede:
1969 ld r29, VCPU_GPR(R29)(r4) 1909 ld r29, VCPU_GPR(R29)(r4)
1970 ld r30, VCPU_GPR(R30)(r4) 1910 ld r30, VCPU_GPR(R30)(r4)
1971 ld r31, VCPU_GPR(R31)(r4) 1911 ld r31, VCPU_GPR(R31)(r4)
1912
1913 /* Check the wake reason in SRR1 to see why we got here */
1914 bl kvmppc_check_wake_reason
1972 1915
1973 /* clear our bit in vcore->napping_threads */ 1916 /* clear our bit in vcore->napping_threads */
197433: ld r5,HSTATE_KVM_VCORE(r13) 191734: ld r5,HSTATE_KVM_VCORE(r13)
1975 lbz r3,HSTATE_PTID(r13) 1918 lbz r7,HSTATE_PTID(r13)
1976 li r0,1 1919 li r0,1
1977 sld r0,r0,r3 1920 sld r0,r0,r7
1978 addi r6,r5,VCORE_NAPPING_THREADS 1921 addi r6,r5,VCORE_NAPPING_THREADS
197932: lwarx r7,0,r6 192232: lwarx r7,0,r6
1980 andc r7,r7,r0 1923 andc r7,r7,r0
@@ -1983,23 +1926,18 @@ kvm_end_cede:
1983 li r0,0 1926 li r0,0
1984 stb r0,HSTATE_NAPPING(r13) 1927 stb r0,HSTATE_NAPPING(r13)
1985 1928
1986 /* Check the wake reason in SRR1 to see why we got here */ 1929 /* See if the wake reason means we need to exit */
1987 mfspr r3, SPRN_SRR1 1930 stw r12, VCPU_TRAP(r4)
1988 rlwinm r3, r3, 44-31, 0x7 /* extract wake reason field */
1989 cmpwi r3, 4 /* was it an external interrupt? */
1990 li r12, BOOK3S_INTERRUPT_EXTERNAL
1991 mr r9, r4 1931 mr r9, r4
1992 ld r10, VCPU_PC(r9) 1932 cmpdi r3, 0
1993 ld r11, VCPU_MSR(r9) 1933 bgt guest_exit_cont
1994 beq do_ext_interrupt /* if so */
1995 1934
1996 /* see if any other thread is already exiting */ 1935 /* see if any other thread is already exiting */
1997 lwz r0,VCORE_ENTRY_EXIT(r5) 1936 lwz r0,VCORE_ENTRY_EXIT(r5)
1998 cmpwi r0,0x100 1937 cmpwi r0,0x100
1999 blt kvmppc_cede_reentry /* if not go back to guest */ 1938 bge guest_exit_cont
2000 1939
2001 /* some threads are exiting, so go to the guest exit path */ 1940 b kvmppc_cede_reentry /* if not go back to guest */
2002 b hcall_real_fallback
2003 1941
2004 /* cede when already previously prodded case */ 1942 /* cede when already previously prodded case */
2005kvm_cede_prodded: 1943kvm_cede_prodded:
@@ -2030,6 +1968,29 @@ machine_check_realmode:
2030 b fast_interrupt_c_return 1968 b fast_interrupt_c_return
2031 1969
2032/* 1970/*
1971 * Check the reason we woke from nap, and take appropriate action.
1972 * Returns:
1973 * 0 if nothing needs to be done
1974 * 1 if something happened that needs to be handled by the host
1975 * -1 if there was a guest wakeup (IPI)
1976 *
1977 * Also sets r12 to the interrupt vector for any interrupt that needs
1978 * to be handled now by the host (0x500 for external interrupt), or zero.
1979 */
1980kvmppc_check_wake_reason:
1981 mfspr r6, SPRN_SRR1
1982 rlwinm r6, r6, 44-31, 0x7 /* extract wake reason field */
1983 cmpwi r6, 4 /* was it an external interrupt? */
1984 li r12, BOOK3S_INTERRUPT_EXTERNAL
1985 beq kvmppc_read_intr /* if so, see what it was */
1986 li r3, 0
1987 li r12, 0
1988 cmpwi r6, 6 /* was it the decrementer? */
1989 beq 0f
1990 li r3, 1 /* anything else, return 1 */
19910: blr
1992
1993/*
2033 * Determine what sort of external interrupt is pending (if any). 1994 * Determine what sort of external interrupt is pending (if any).
2034 * Returns: 1995 * Returns:
2035 * 0 if no interrupt is pending 1996 * 0 if no interrupt is pending
@@ -2060,7 +2021,6 @@ kvmppc_read_intr:
2060 * interrupts directly to the guest 2021 * interrupts directly to the guest
2061 */ 2022 */
2062 cmpwi r3, XICS_IPI /* if there is, is it an IPI? */ 2023 cmpwi r3, XICS_IPI /* if there is, is it an IPI? */
2063 li r3, 1
2064 bne 42f 2024 bne 42f
2065 2025
2066 /* It's an IPI, clear the MFRR and EOI it */ 2026 /* It's an IPI, clear the MFRR and EOI it */
@@ -2086,12 +2046,14 @@ kvmppc_read_intr:
2086 * before exit, it will be picked up by the host ICP driver 2046 * before exit, it will be picked up by the host ICP driver
2087 */ 2047 */
2088 stw r0, HSTATE_SAVED_XIRR(r13) 2048 stw r0, HSTATE_SAVED_XIRR(r13)
2049 li r3, 1
2089 b 1b 2050 b 1b
2090 2051
209143: /* We raced with the host, we need to resend that IPI, bummer */ 205243: /* We raced with the host, we need to resend that IPI, bummer */
2092 li r0, IPI_PRIORITY 2053 li r0, IPI_PRIORITY
2093 stbcix r0, r6, r8 /* set the IPI */ 2054 stbcix r0, r6, r8 /* set the IPI */
2094 sync 2055 sync
2056 li r3, 1
2095 b 1b 2057 b 1b
2096 2058
2097/* 2059/*