Skip to content

Commit

Permalink
KVM: Call kvm_arch_vcpu_blocking early into the blocking sequence
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Marc Zyngier <[email protected]>
  • Loading branch information
Marc Zyngier committed Aug 18, 2019
1 parent 0ed5f5d commit 07ab0f8
Showing 1 changed file with 3 additions and 4 deletions.
7 changes: 3 additions & 4 deletions virt/kvm/kvm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2321,6 +2321,8 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
bool waited = false;
u64 block_ns;

kvm_arch_vcpu_blocking(vcpu);

start = cur = ktime_get();
if (vcpu->halt_poll_ns && !kvm_arch_no_poll(vcpu)) {
ktime_t stop = ktime_add_ns(ktime_get(), vcpu->halt_poll_ns);
Expand All @@ -2341,8 +2343,6 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
} while (single_task_running() && ktime_before(cur, stop));
}

kvm_arch_vcpu_blocking(vcpu);

for (;;) {
prepare_to_swait_exclusive(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);

Expand All @@ -2355,9 +2355,8 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)

finish_swait(&vcpu->wq, &wait);
cur = ktime_get();

kvm_arch_vcpu_unblocking(vcpu);
out:
kvm_arch_vcpu_unblocking(vcpu);
block_ns = ktime_to_ns(cur) - ktime_to_ns(start);

if (!vcpu_valid_wakeup(vcpu))
Expand Down

0 comments on commit 07ab0f8

Please sign in to comment.