lkml.org 
[lkml]   [2022]   [Mar]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 3/5] KVM: X86: Boost vCPU which is in the critical section
Date
From: Wanpeng Li <wanpengli@tencent.com>

The missing semantic gap that occurs when a guest OS is preempted
when executing its own critical section, this leads to degradation
of application scalability. We try to bridge this semantic gap in
some ways, by passing guest preempt_count to the host and checking
guest irq disable state, the hypervisor now knows whether guest
OSes are running in the critical section, the hypervisor yield-on-spin
heuristics can be more smart this time to boost the vCPU candidate
who is in the critical section to mitigate this preemption problem,
in addition, it is more likely to be a potential lock holder.

Testing on 96 HT 2 socket Xeon CLX server, with 96 vCPUs VM 100GB RAM,
one VM running benchmark, the other(none-2) VMs running cpu-bound
workloads, There is no performance regression for other benchmarks
like Unixbench etc.

1VM:
vanilla optimized improved

hackbench -l 50000
28 21.45 30.5%
ebizzy -M
12189 12354 1.4%
dbench
712 MB/sec 722 MB/sec 1.4%

2VM:
vanilla optimized improved

hackbench -l 10000
29.4 26 13%
ebizzy -M
3834 4033 5%
dbench
42.3 MB/sec 44.1 MB/sec 4.3%

3VM:
vanilla optimized improved

hackbench -l 10000
47 35.46 33%
ebizzy -M
3828 4031 5%
dbench
30.5 MB/sec 31.16 MB/sec 2.3%

Signed-off-by: Wanpeng Li <wanpengli@tencent.com>
---
arch/x86/kvm/x86.c | 22 ++++++++++++++++++++++
include/linux/kvm_host.h | 1 +
virt/kvm/kvm_main.c | 7 +++++++
3 files changed, 30 insertions(+)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 425fd7f38fa9..6b300496bbd0 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10375,6 +10375,28 @@ static int vcpu_run(struct kvm_vcpu *vcpu)
return r;
}

+static int kvm_vcpu_non_preemptable(struct kvm_vcpu *vcpu)
+{
+ int count;
+
+ if (!vcpu->arch.pv_pc.preempt_count_enabled)
+ return 0;
+
+ if (!kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.pv_pc.preempt_count_cache,
+ &count, sizeof(int)))
+ return (count & ~PREEMPT_NEED_RESCHED);
+
+ return 0;
+}
+
+bool kvm_arch_boost_candidate(struct kvm_vcpu *vcpu)
+{
+ if (vcpu->arch.irq_disabled || kvm_vcpu_non_preemptable(vcpu))
+ return true;
+
+ return false;
+}
+
static inline int complete_emulated_io(struct kvm_vcpu *vcpu)
{
int r;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 252ee4a61b58..9f1a7d9540de 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1428,6 +1428,7 @@ bool kvm_arch_dy_has_pending_interrupt(struct kvm_vcpu *vcpu);
int kvm_arch_post_init_vm(struct kvm *kvm);
void kvm_arch_pre_destroy_vm(struct kvm *kvm);
int kvm_arch_create_vm_debugfs(struct kvm *kvm);
+bool kvm_arch_boost_candidate(struct kvm_vcpu *vcpu);

#ifndef __KVM_HAVE_ARCH_VM_ALLOC
/*
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 9581a24c3d17..ee5a788892e0 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -3545,6 +3545,11 @@ bool __weak kvm_arch_dy_has_pending_interrupt(struct kvm_vcpu *vcpu)
return false;
}

+bool __weak kvm_arch_boost_candidate(struct kvm_vcpu *vcpu)
+{
+ return true;
+}
+
void kvm_vcpu_on_spin(struct kvm_vcpu *me, bool yield_to_kernel_mode)
{
struct kvm *kvm = me->kvm;
@@ -3580,6 +3585,8 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me, bool yield_to_kernel_mode)
!kvm_arch_dy_has_pending_interrupt(vcpu) &&
!kvm_arch_vcpu_in_kernel(vcpu))
continue;
+ if (!kvm_arch_boost_candidate(vcpu))
+ continue;
if (!kvm_vcpu_eligible_for_directed_yield(vcpu))
continue;

--
2.25.1
\
 
 \ /
  Last update: 2022-03-11 09:32    [W:0.075 / U:0.440 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site