Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f558098 authored by Marc Zyngier's avatar Marc Zyngier Committed by Christoffer Dall
Browse files

ARM: KVM: Yield CPU when vcpu executes a WFE



On an (even slightly) oversubscribed system, spinlocks are quickly
becoming a bottleneck, as some vcpus are spinning, waiting for a
lock to be released, while the vcpu holding the lock may not be
running at all.

This creates contention, and the observed slowdown is 40x for
hackbench. No, this isn't a typo.

The solution is to trap blocking WFEs and tell KVM that we're
now spinning. This ensures that other vpus will get a scheduling
boost, allowing the lock to be released more quickly. Also, using
CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT slightly improves the performance
when the VM is severely overcommited.

Quick test to estimate the performance: hackbench 1 process 1000

2xA15 host (baseline):	1.843s

2xA15 guest w/o patch:	2.083s
4xA15 guest w/o patch:	80.212s
8xA15 guest w/o patch:	Could not be bothered to find out

2xA15 guest w/ patch:	2.102s
4xA15 guest w/ patch:	3.205s
8xA15 guest w/ patch:	6.887s

So we go from a 40x degradation to 1.5x in the 2x overcommit case,
which is vaguely more acceptable.

Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Signed-off-by: default avatarChristoffer Dall <christoffer.dall@linaro.org>
parent a7265fb1
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@
 */
#define HCR_GUEST_MASK (HCR_TSC | HCR_TSW | HCR_TWI | HCR_VM | HCR_BSU_IS | \
			HCR_FB | HCR_TAC | HCR_AMO | HCR_IMO | HCR_FMO | \
			HCR_SWIO | HCR_TIDCP)
			HCR_TWE | HCR_SWIO | HCR_TIDCP)
#define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF)

/* System Control Register (SCTLR) bits */
@@ -208,6 +208,8 @@
#define HSR_EC_DABT	(0x24)
#define HSR_EC_DABT_HYP	(0x25)

#define HSR_WFI_IS_WFE		(1U << 0)

#define HSR_HVC_IMM_MASK	((1UL << 16) - 1)

#define HSR_DABT_S1PTW		(1U << 7)
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ config KVM
	bool "Kernel-based Virtual Machine (KVM) support"
	select PREEMPT_NOTIFIERS
	select ANON_INODES
	select HAVE_KVM_CPU_RELAX_INTERCEPT
	select KVM_MMIO
	select KVM_ARM_HOST
	depends on ARM_VIRT_EXT && ARM_LPAE
+5 −1
Original line number Diff line number Diff line
@@ -84,7 +84,11 @@ static int handle_dabt_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
static int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct kvm_run *run)
{
	trace_kvm_wfi(*vcpu_pc(vcpu));
	if (kvm_vcpu_get_hsr(vcpu) & HSR_WFI_IS_WFE)
		kvm_vcpu_on_spin(vcpu);
	else
		kvm_vcpu_block(vcpu);

	return 1;
}