diff options
-rw-r--r-- | arch/powerpc/kvm/book3s_hv_rmhandlers.S | 192 |
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 |
207 | 4: lwarx r3, 0, r6 | 209 | 4: 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 | ||
292 | 27: /* XXX should handle hypervisor maintenance interrupts etc. here */ | ||
293 | b kvm_no_guest | ||
294 | 28: /* SRR1 said external but ICP said nope?? */ | ||
295 | b kvm_no_guest | ||
296 | 29: /* External non-IPI interrupt to offline secondary thread? help?? */ | ||
297 | stw r8,HSTATE_SAVED_XIRR(r13) | ||
298 | b kvm_no_guest | ||
299 | |||
300 | 30: | ||
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 */ | ||
324 | 37: 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 | ||
778 | kvmppc_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) |
823 | kvmppc_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 | ||
786 | deliver_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 | ||
839 | BEGIN_FTR_SECTION | 797 | BEGIN_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 |
844 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) | 803 | END_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 |
847 | 12: 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 | |||
812 | 12: 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 | 817 | 5: |
853 | 11: 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 */ | ||
860 | 5: 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 | */ |
1050 | do_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 | ||
1080 | 2: mr r4, r9 | ||
1081 | mtspr SPRN_LPCR, r8 | ||
1082 | b fast_guest_return | ||
1083 | 1019 | ||
1084 | ext_interrupt_to_host: | 1020 | ext_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 | ||
1878 | 33: mr r4, r3 | ||
1879 | li r3, 0 | ||
1880 | li r12, 0 | ||
1881 | b 34f | ||
1882 | |||
1943 | kvm_end_cede: | 1883 | kvm_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 */ |
1974 | 33: ld r5,HSTATE_KVM_VCORE(r13) | 1917 | 34: 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 |
1979 | 32: lwarx r7,0,r6 | 1922 | 32: 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 */ |
2005 | kvm_cede_prodded: | 1943 | kvm_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 | */ | ||
1980 | kvmppc_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 */ | ||
1991 | 0: 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 | ||
2091 | 43: /* We raced with the host, we need to resend that IPI, bummer */ | 2052 | 43: /* 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 | /* |