summaryrefslogtreecommitdiffstats
path: root/virt/kvm
diff options
context:
space:
mode:
authorMarc Zyngier <maz@kernel.org>2019-08-02 06:37:09 -0400
committerMarc Zyngier <maz@kernel.org>2019-08-18 13:50:44 -0400
commit07ab0f8d9a129add914aff3e988da4033471dfc0 (patch)
tree4cd843fb35c7ceae08922bad7a4e9a2ea640cca7 /virt/kvm
parent0ed5f5d63963673ccdd00d101637bf56e6d3d6dc (diff)
KVM: Call kvm_arch_vcpu_blocking early into the blocking sequence
When a vpcu is about to block by calling kvm_vcpu_block, we call back into the arch code to allow any form of synchronization that may be required at this point (SVN stops the AVIC, ARM synchronises the VMCR and enables GICv4 doorbells). But this synchronization comes in quite late, as we've potentially waited for halt_poll_ns to expire. Instead, let's move kvm_arch_vcpu_blocking() to the beginning of kvm_vcpu_block(), which on ARM has several benefits: - VMCR gets synchronised early, meaning that any interrupt delivered during the polling window will be evaluated with the correct guest PMR - GICv4 doorbells are enabled, which means that any guest interrupt directly injected during that window will be immediately recognised Tang Nianyao ran some tests on a GICv4 machine to evaluate such change, and reported up to a 10% improvement for netperf: <quote> netperf result: D06 as server, intel 8180 server as client with change: package 512 bytes - 5500 Mbits/s package 64 bytes - 760 Mbits/s without change: package 512 bytes - 5000 Mbits/s package 64 bytes - 710 Mbits/s </quote> Acked-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Marc Zyngier <maz@kernel.org>
Diffstat (limited to 'virt/kvm')
-rw-r--r--virt/kvm/kvm_main.c7
1 files changed, 3 insertions, 4 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index c6a91b044d8d..e6de3159e682 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2321,6 +2321,8 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
2321 bool waited = false; 2321 bool waited = false;
2322 u64 block_ns; 2322 u64 block_ns;
2323 2323
2324 kvm_arch_vcpu_blocking(vcpu);
2325
2324 start = cur = ktime_get(); 2326 start = cur = ktime_get();
2325 if (vcpu->halt_poll_ns && !kvm_arch_no_poll(vcpu)) { 2327 if (vcpu->halt_poll_ns && !kvm_arch_no_poll(vcpu)) {
2326 ktime_t stop = ktime_add_ns(ktime_get(), vcpu->halt_poll_ns); 2328 ktime_t stop = ktime_add_ns(ktime_get(), vcpu->halt_poll_ns);
@@ -2341,8 +2343,6 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
2341 } while (single_task_running() && ktime_before(cur, stop)); 2343 } while (single_task_running() && ktime_before(cur, stop));
2342 } 2344 }
2343 2345
2344 kvm_arch_vcpu_blocking(vcpu);
2345
2346 for (;;) { 2346 for (;;) {
2347 prepare_to_swait_exclusive(&vcpu->wq, &wait, TASK_INTERRUPTIBLE); 2347 prepare_to_swait_exclusive(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
2348 2348
@@ -2355,9 +2355,8 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
2355 2355
2356 finish_swait(&vcpu->wq, &wait); 2356 finish_swait(&vcpu->wq, &wait);
2357 cur = ktime_get(); 2357 cur = ktime_get();
2358
2359 kvm_arch_vcpu_unblocking(vcpu);
2360out: 2358out:
2359 kvm_arch_vcpu_unblocking(vcpu);
2361 block_ns = ktime_to_ns(cur) - ktime_to_ns(start); 2360 block_ns = ktime_to_ns(cur) - ktime_to_ns(start);
2362 2361
2363 if (!vcpu_valid_wakeup(vcpu)) 2362 if (!vcpu_valid_wakeup(vcpu))