Skip to content

Commit f85f6e7

Browse files
Wanpeng Libonzini
authored andcommitted
KVM: X86: Yield to IPI target if necessary
When sending a call-function IPI-many to vCPUs, yield if any of the IPI target vCPUs was preempted, we just select the first preempted target vCPU which we found since the state of target vCPUs can change underneath and to avoid race conditions. Cc: Paolo Bonzini <[email protected]> Cc: Radim Krčmář <[email protected]> Cc: Liran Alon <[email protected]> Signed-off-by: Wanpeng Li <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 11e3491 commit f85f6e7

File tree

4 files changed

+34
-0
lines changed

4 files changed

+34
-0
lines changed

Documentation/virtual/kvm/hypercalls.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,14 @@ a0 corresponds to the APIC ID in the third argument (a2), bit 1
141141
corresponds to the APIC ID a2+1, and so on.
142142

143143
Returns the number of CPUs to which the IPIs were delivered successfully.
144+
145+
7. KVM_HC_SCHED_YIELD
146+
------------------------
147+
Architecture: x86
148+
Status: active
149+
Purpose: Hypercall used to yield if the IPI target vCPU is preempted
150+
151+
a0: destination APIC ID
152+
153+
Usage example: When sending a call-function IPI-many to vCPUs, yield if
154+
any of the IPI target vCPUs was preempted.

arch/x86/include/uapi/asm/kvm_para.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#define KVM_FEATURE_ASYNC_PF_VMEXIT 10
3131
#define KVM_FEATURE_PV_SEND_IPI 11
3232
#define KVM_FEATURE_POLL_CONTROL 12
33+
#define KVM_FEATURE_PV_SCHED_YIELD 13
3334

3435
#define KVM_HINTS_REALTIME 0
3536

arch/x86/kernel/kvm.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,21 @@ static void kvm_setup_pv_ipi(void)
527527
pr_info("KVM setup pv IPIs\n");
528528
}
529529

530+
static void kvm_smp_send_call_func_ipi(const struct cpumask *mask)
531+
{
532+
int cpu;
533+
534+
native_send_call_func_ipi(mask);
535+
536+
/* Make sure other vCPUs get a chance to run if they need to. */
537+
for_each_cpu(cpu, mask) {
538+
if (vcpu_is_preempted(cpu)) {
539+
kvm_hypercall1(KVM_HC_SCHED_YIELD, per_cpu(x86_cpu_to_apicid, cpu));
540+
break;
541+
}
542+
}
543+
}
544+
530545
static void __init kvm_smp_prepare_cpus(unsigned int max_cpus)
531546
{
532547
native_smp_prepare_cpus(max_cpus);
@@ -638,6 +653,12 @@ static void __init kvm_guest_init(void)
638653
#ifdef CONFIG_SMP
639654
smp_ops.smp_prepare_cpus = kvm_smp_prepare_cpus;
640655
smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu;
656+
if (kvm_para_has_feature(KVM_FEATURE_PV_SCHED_YIELD) &&
657+
!kvm_para_has_hint(KVM_HINTS_REALTIME) &&
658+
kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
659+
smp_ops.send_call_func_ipi = kvm_smp_send_call_func_ipi;
660+
pr_info("KVM setup pv sched yield\n");
661+
}
641662
if (cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "x86/kvm:online",
642663
kvm_cpu_online, kvm_cpu_down_prepare) < 0)
643664
pr_err("kvm_guest: Failed to install cpu hotplug callbacks\n");

include/uapi/linux/kvm_para.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#define KVM_HC_MIPS_CONSOLE_OUTPUT 8
2929
#define KVM_HC_CLOCK_PAIRING 9
3030
#define KVM_HC_SEND_IPI 10
31+
#define KVM_HC_SCHED_YIELD 11
3132

3233
/*
3334
* hypercalls use architecture specific

0 commit comments

Comments
 (0)