aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2015-03-27 23:21:10 -0400
committerAlexander Graf <agraf@suse.de>2015-04-21 09:21:33 -0400
commit6af27c847ad1b889c29a641dfc41f2d78c46a048 (patch)
treede69e551006e793576896c81d0c741df59a18685 /arch/powerpc/kvm
parent7d6c40da198ac18bd5dd2cd18628d5b4c615d842 (diff)
KVM: PPC: Book3S HV: Streamline guest entry and exit
On entry to the guest, secondary threads now wait for the primary to switch the MMU after loading up most of their state, rather than before. This means that the secondary threads get into the guest sooner, in the common case where the secondary threads get to kvmppc_hv_entry before the primary thread. On exit, the first thread out increments the exit count and interrupts the other threads (to get them out of the guest) before saving most of its state, rather than after. That means that the other threads exit sooner and means that the first thread doesn't spend so much time waiting for the other threads at the point where the MMU gets switched back to the host. This pulls out the code that increments the exit count and interrupts other threads into a separate function, kvmhv_commence_exit(). This also makes sure that r12 and vcpu->arch.trap are set correctly in some corner cases. Statistics from /sys/kernel/debug/kvm/vm*/vcpu*/timings show the improvement. Aggregating across vcpus for a guest with 32 vcpus, 8 threads/vcore, running on a POWER8, gives this before the change: rm_entry: avg 4537.3ns (222 - 48444, 1068878 samples) rm_exit: avg 4787.6ns (152 - 165490, 1010717 samples) rm_intr: avg 1673.6ns (12 - 341304, 3818691 samples) and this after the change: rm_entry: avg 3427.7ns (232 - 68150, 1118921 samples) rm_exit: avg 4716.0ns (12 - 150720, 1119477 samples) rm_intr: avg 1614.8ns (12 - 522436, 3850432 samples) showing a substantial reduction in the time spent per guest entry in the real-mode guest entry code, and smaller reductions in the real mode guest exit and interrupt handling times. (The test was to start the guest and boot Fedora 20 big-endian to the login prompt.) Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S212
1 files changed, 126 insertions, 86 deletions
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 245f5c972030..3f6fd78cccd2 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -175,6 +175,19 @@ kvmppc_primary_no_guest:
175 /* put the HDEC into the DEC, since HDEC interrupts don't wake us */ 175 /* put the HDEC into the DEC, since HDEC interrupts don't wake us */
176 mfspr r3, SPRN_HDEC 176 mfspr r3, SPRN_HDEC
177 mtspr SPRN_DEC, r3 177 mtspr SPRN_DEC, r3
178 /*
179 * Make sure the primary has finished the MMU switch.
180 * We should never get here on a secondary thread, but
181 * check it for robustness' sake.
182 */
183 ld r5, HSTATE_KVM_VCORE(r13)
18465: lbz r0, VCORE_IN_GUEST(r5)
185 cmpwi r0, 0
186 beq 65b
187 /* Set LPCR. */
188 ld r8,VCORE_LPCR(r5)
189 mtspr SPRN_LPCR,r8
190 isync
178 /* set our bit in napping_threads */ 191 /* set our bit in napping_threads */
179 ld r5, HSTATE_KVM_VCORE(r13) 192 ld r5, HSTATE_KVM_VCORE(r13)
180 lbz r7, HSTATE_PTID(r13) 193 lbz r7, HSTATE_PTID(r13)
@@ -206,7 +219,7 @@ kvm_novcpu_wakeup:
206 219
207 /* check the wake reason */ 220 /* check the wake reason */
208 bl kvmppc_check_wake_reason 221 bl kvmppc_check_wake_reason
209 222
210 /* see if any other thread is already exiting */ 223 /* see if any other thread is already exiting */
211 lwz r0, VCORE_ENTRY_EXIT(r5) 224 lwz r0, VCORE_ENTRY_EXIT(r5)
212 cmpwi r0, 0x100 225 cmpwi r0, 0x100
@@ -244,7 +257,15 @@ kvm_novcpu_wakeup:
244 b kvmppc_got_guest 257 b kvmppc_got_guest
245 258
246kvm_novcpu_exit: 259kvm_novcpu_exit:
247 b hdec_soon 260#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
261 ld r4, HSTATE_KVM_VCPU(r13)
262 cmpdi r4, 0
263 beq 13f
264 addi r3, r4, VCPU_TB_RMEXIT
265 bl kvmhv_accumulate_time
266#endif
26713: bl kvmhv_commence_exit
268 b kvmhv_switch_to_host
248 269
249/* 270/*
250 * We come in here when wakened from nap mode. 271 * We come in here when wakened from nap mode.
@@ -422,7 +443,7 @@ kvmppc_hv_entry:
422 /* Primary thread switches to guest partition. */ 443 /* Primary thread switches to guest partition. */
423 ld r9,VCORE_KVM(r5) /* pointer to struct kvm */ 444 ld r9,VCORE_KVM(r5) /* pointer to struct kvm */
424 cmpwi r6,0 445 cmpwi r6,0
425 bne 20f 446 bne 10f
426 ld r6,KVM_SDR1(r9) 447 ld r6,KVM_SDR1(r9)
427 lwz r7,KVM_LPID(r9) 448 lwz r7,KVM_LPID(r9)
428 li r0,LPID_RSVD /* switch to reserved LPID */ 449 li r0,LPID_RSVD /* switch to reserved LPID */
@@ -493,26 +514,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
493 514
494 li r0,1 515 li r0,1
495 stb r0,VCORE_IN_GUEST(r5) /* signal secondaries to continue */ 516 stb r0,VCORE_IN_GUEST(r5) /* signal secondaries to continue */
496 b 10f
497
498 /* Secondary threads wait for primary to have done partition switch */
49920: lbz r0,VCORE_IN_GUEST(r5)
500 cmpwi r0,0
501 beq 20b
502
503 /* Set LPCR. */
50410: ld r8,VCORE_LPCR(r5)
505 mtspr SPRN_LPCR,r8
506 isync
507
508 /* Check if HDEC expires soon */
509 mfspr r3,SPRN_HDEC
510 cmpwi r3,512 /* 1 microsecond */
511 li r12,BOOK3S_INTERRUPT_HV_DECREMENTER
512 blt hdec_soon
513 517
514 /* Do we have a guest vcpu to run? */ 518 /* Do we have a guest vcpu to run? */
515 cmpdi r4, 0 51910: cmpdi r4, 0
516 beq kvmppc_primary_no_guest 520 beq kvmppc_primary_no_guest
517kvmppc_got_guest: 521kvmppc_got_guest:
518 522
@@ -837,6 +841,30 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
837 clrrdi r6,r6,1 841 clrrdi r6,r6,1
838 mtspr SPRN_CTRLT,r6 842 mtspr SPRN_CTRLT,r6
8394: 8434:
844 /* Secondary threads wait for primary to have done partition switch */
845 ld r5, HSTATE_KVM_VCORE(r13)
846 lbz r6, HSTATE_PTID(r13)
847 cmpwi r6, 0
848 beq 21f
849 lbz r0, VCORE_IN_GUEST(r5)
850 cmpwi r0, 0
851 bne 21f
852 HMT_LOW
85320: lbz r0, VCORE_IN_GUEST(r5)
854 cmpwi r0, 0
855 beq 20b
856 HMT_MEDIUM
85721:
858 /* Set LPCR. */
859 ld r8,VCORE_LPCR(r5)
860 mtspr SPRN_LPCR,r8
861 isync
862
863 /* Check if HDEC expires soon */
864 mfspr r3, SPRN_HDEC
865 cmpwi r3, 512 /* 1 microsecond */
866 blt hdec_soon
867
840 ld r6, VCPU_CTR(r4) 868 ld r6, VCPU_CTR(r4)
841 lwz r7, VCPU_XER(r4) 869 lwz r7, VCPU_XER(r4)
842 870
@@ -942,22 +970,26 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
942 hrfid 970 hrfid
943 b . 971 b .
944 972
945#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
946secondary_too_late: 973secondary_too_late:
974 li r12, 0
947 cmpdi r4, 0 975 cmpdi r4, 0
948 beq 11f 976 beq 11f
977 stw r12, VCPU_TRAP(r4)
978#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
949 addi r3, r4, VCPU_TB_RMEXIT 979 addi r3, r4, VCPU_TB_RMEXIT
950 bl kvmhv_accumulate_time 980 bl kvmhv_accumulate_time
981#endif
95111: b kvmhv_switch_to_host 98211: b kvmhv_switch_to_host
952 983
953hdec_soon: 984hdec_soon:
954 ld r4, HSTATE_KVM_VCPU(r13) 985 li r12, BOOK3S_INTERRUPT_HV_DECREMENTER
955 cmpdi r4, 0 986 stw r12, VCPU_TRAP(r4)
956 beq 12f 987 mr r9, r4
988#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
957 addi r3, r4, VCPU_TB_RMEXIT 989 addi r3, r4, VCPU_TB_RMEXIT
958 bl kvmhv_accumulate_time 990 bl kvmhv_accumulate_time
95912: b kvmhv_do_exit
960#endif 991#endif
992 b guest_exit_cont
961 993
962/****************************************************************************** 994/******************************************************************************
963 * * 995 * *
@@ -1113,7 +1145,7 @@ guest_exit_cont: /* r9 = vcpu, r12 = trap, r13 = paca */
1113 stw r7, VCPU_DSISR(r9) 1145 stw r7, VCPU_DSISR(r9)
1114 /* don't overwrite fault_dar/fault_dsisr if HDSI */ 1146 /* don't overwrite fault_dar/fault_dsisr if HDSI */
1115 cmpwi r12,BOOK3S_INTERRUPT_H_DATA_STORAGE 1147 cmpwi r12,BOOK3S_INTERRUPT_H_DATA_STORAGE
1116 beq 6f 1148 beq mc_cont
1117 std r6, VCPU_FAULT_DAR(r9) 1149 std r6, VCPU_FAULT_DAR(r9)
1118 stw r7, VCPU_FAULT_DSISR(r9) 1150 stw r7, VCPU_FAULT_DSISR(r9)
1119 1151
@@ -1127,8 +1159,11 @@ mc_cont:
1127 bl kvmhv_accumulate_time 1159 bl kvmhv_accumulate_time
1128#endif 1160#endif
1129 1161
1162 /* Increment exit count, poke other threads to exit */
1163 bl kvmhv_commence_exit
1164
1130 /* Save guest CTRL register, set runlatch to 1 */ 1165 /* Save guest CTRL register, set runlatch to 1 */
11316: mfspr r6,SPRN_CTRLF 1166 mfspr r6,SPRN_CTRLF
1132 stw r6,VCPU_CTRL(r9) 1167 stw r6,VCPU_CTRL(r9)
1133 andi. r0,r6,1 1168 andi. r0,r6,1
1134 bne 4f 1169 bne 4f
@@ -1470,68 +1505,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
1470 slbia 1505 slbia
1471 ptesync 1506 ptesync
1472 1507
1473#ifndef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
1474hdec_soon:
1475#endif
1476kvmhv_do_exit: /* r12 = trap, r13 = paca */
1477 /* 1508 /*
1478 * POWER7/POWER8 guest -> host partition switch code. 1509 * POWER7/POWER8 guest -> host partition switch code.
1479 * We don't have to lock against tlbies but we do 1510 * We don't have to lock against tlbies but we do
1480 * have to coordinate the hardware threads. 1511 * have to coordinate the hardware threads.
1481 */ 1512 */
1482 /* Set our bit in the threads-exiting-guest map in the 0xff00
1483 bits of vcore->entry_exit_map */
1484 ld r5, HSTATE_KVM_VCORE(r13)
1485 lbz r4, HSTATE_PTID(r13)
1486 li r7, 0x100
1487 sld r7, r7, r4
1488 addi r6, r5, VCORE_ENTRY_EXIT
148941: lwarx r3, 0, r6
1490 or r0, r3, r7
1491 stwcx. r0, 0, r6
1492 bne 41b
1493 isync /* order stwcx. vs. reading napping_threads */
1494
1495 /*
1496 * At this point we have an interrupt that we have to pass
1497 * up to the kernel or qemu; we can't handle it in real mode.
1498 * Thus we have to do a partition switch, so we have to
1499 * collect the other threads, if we are the first thread
1500 * to take an interrupt. To do this, we send a message or
1501 * IPI to all the threads that have their bit set in the entry
1502 * map in vcore->entry_exit_map (other than ourselves).
1503 * However, we don't need to bother if this is an HDEC
1504 * interrupt, since the other threads will already be on their
1505 * way here in that case.
1506 */
1507 cmpwi r3,0x100 /* Are we the first here? */
1508 bge 43f
1509 cmpwi r12,BOOK3S_INTERRUPT_HV_DECREMENTER
1510 beq 43f
1511
1512 srwi r0,r7,8
1513 andc. r3,r3,r0 /* no sense IPI'ing ourselves */
1514 beq 43f
1515 /* Order entry/exit update vs. IPIs */
1516 sync
1517 mulli r4,r4,PACA_SIZE /* get paca for thread 0 */
1518 subf r6,r4,r13
151942: andi. r0,r3,1
1520 beq 44f
1521 ld r8,HSTATE_XICS_PHYS(r6) /* get thread's XICS reg addr */
1522 li r0,IPI_PRIORITY
1523 li r7,XICS_MFRR
1524 stbcix r0,r7,r8 /* trigger the IPI */
152544: srdi. r3,r3,1
1526 addi r6,r6,PACA_SIZE
1527 bne 42b
1528
1529#ifndef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
1530secondary_too_late:
1531#endif
1532kvmhv_switch_to_host: 1513kvmhv_switch_to_host:
1533 /* Secondary threads wait for primary to do partition switch */ 1514 /* Secondary threads wait for primary to do partition switch */
153443: ld r5,HSTATE_KVM_VCORE(r13) 1515 ld r5,HSTATE_KVM_VCORE(r13)
1535 ld r4,VCORE_KVM(r5) /* pointer to struct kvm */ 1516 ld r4,VCORE_KVM(r5) /* pointer to struct kvm */
1536 lbz r3,HSTATE_PTID(r13) 1517 lbz r3,HSTATE_PTID(r13)
1537 cmpwi r3,0 1518 cmpwi r3,0
@@ -1633,6 +1614,63 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
1633 mtlr r0 1614 mtlr r0
1634 blr 1615 blr
1635 1616
1617kvmhv_commence_exit: /* r12 = trap, r13 = paca, doesn't trash r9 */
1618 mflr r0
1619 std r0, PPC_LR_STKOFF(r1)
1620 stdu r1, -PPC_MIN_STKFRM(r1)
1621
1622 /* Set our bit in the threads-exiting-guest map in the 0xff00
1623 bits of vcore->entry_exit_map */
1624 ld r5, HSTATE_KVM_VCORE(r13)
1625 lbz r4, HSTATE_PTID(r13)
1626 li r7, 0x100
1627 sld r7, r7, r4
1628 addi r6, r5, VCORE_ENTRY_EXIT
162941: lwarx r3, 0, r6
1630 or r0, r3, r7
1631 stwcx. r0, 0, r6
1632 bne 41b
1633 isync /* order stwcx. vs. reading napping_threads */
1634
1635 /*
1636 * At this point we have an interrupt that we have to pass
1637 * up to the kernel or qemu; we can't handle it in real mode.
1638 * Thus we have to do a partition switch, so we have to
1639 * collect the other threads, if we are the first thread
1640 * to take an interrupt. To do this, we send a message or
1641 * IPI to all the threads that have their bit set in the entry
1642 * map in vcore->entry_exit_map (other than ourselves).
1643 * However, we don't need to bother if this is an HDEC
1644 * interrupt, since the other threads will already be on their
1645 * way here in that case.
1646 */
1647 cmpwi r3,0x100 /* Are we the first here? */
1648 bge 43f
1649 cmpwi r12,BOOK3S_INTERRUPT_HV_DECREMENTER
1650 beq 43f
1651
1652 srwi r0,r7,8
1653 andc. r3,r3,r0 /* no sense IPI'ing ourselves */
1654 beq 43f
1655 /* Order entry/exit update vs. IPIs */
1656 sync
1657 mulli r4,r4,PACA_SIZE /* get paca for thread 0 */
1658 subf r6,r4,r13
165942: andi. r0,r3,1
1660 beq 44f
1661 ld r8,HSTATE_XICS_PHYS(r6) /* get thread's XICS reg addr */
1662 li r0,IPI_PRIORITY
1663 li r7,XICS_MFRR
1664 stbcix r0,r7,r8 /* trigger the IPI */
166544: srdi. r3,r3,1
1666 addi r6,r6,PACA_SIZE
1667 bne 42b
1668
166943: ld r0, PPC_MIN_STKFRM+PPC_LR_STKOFF(r1)
1670 addi r1, r1, PPC_MIN_STKFRM
1671 mtlr r0
1672 blr
1673
1636/* 1674/*
1637 * Check whether an HDSI is an HPTE not found fault or something else. 1675 * Check whether an HDSI is an HPTE not found fault or something else.
1638 * If it is an HPTE not found fault that is due to the guest accessing 1676 * If it is an HPTE not found fault that is due to the guest accessing
@@ -2068,8 +2106,8 @@ _GLOBAL(kvmppc_h_cede) /* r3 = vcpu pointer, r11 = msr, r13 = paca */
2068 lbz r5,VCPU_PRODDED(r3) 2106 lbz r5,VCPU_PRODDED(r3)
2069 cmpwi r5,0 2107 cmpwi r5,0
2070 bne kvm_cede_prodded 2108 bne kvm_cede_prodded
2071 li r0,0 /* set trap to 0 to say hcall is handled */ 2109 li r12,0 /* set trap to 0 to say hcall is handled */
2072 stw r0,VCPU_TRAP(r3) 2110 stw r12,VCPU_TRAP(r3)
2073 li r0,H_SUCCESS 2111 li r0,H_SUCCESS
2074 std r0,VCPU_GPR(R3)(r3) 2112 std r0,VCPU_GPR(R3)(r3)
2075 2113
@@ -2275,7 +2313,8 @@ kvm_cede_prodded:
2275 2313
2276 /* we've ceded but we want to give control to the host */ 2314 /* we've ceded but we want to give control to the host */
2277kvm_cede_exit: 2315kvm_cede_exit:
2278 b hcall_real_fallback 2316 ld r9, HSTATE_KVM_VCPU(r13)
2317 b guest_exit_cont
2279 2318
2280 /* Try to handle a machine check in real mode */ 2319 /* Try to handle a machine check in real mode */
2281machine_check_realmode: 2320machine_check_realmode:
@@ -2405,6 +2444,7 @@ kvmppc_read_intr:
2405 bne- 43f 2444 bne- 43f
2406 2445
2407 /* OK, it's an IPI for us */ 2446 /* OK, it's an IPI for us */
2447 li r12, 0
2408 li r3, -1 2448 li r3, -1
24091: blr 24491: blr
2410 2450