Skip to content

Commit 8577370

Browse files
matosattiKAGA-KOKO
authored andcommitted
KVM: Use simple waitqueue for vcpu->wq
The problem: On -rt, an emulated LAPIC timer instances has the following path: 1) hard interrupt 2) ksoftirqd is scheduled 3) ksoftirqd wakes up vcpu thread 4) vcpu thread is scheduled This extra context switch introduces unnecessary latency in the LAPIC path for a KVM guest. The solution: Allow waking up vcpu thread from hardirq context, thus avoiding the need for ksoftirqd to be scheduled. Normal waitqueues make use of spinlocks, which on -RT are sleepable locks. Therefore, waking up a waitqueue waiter involves locking a sleeping lock, which is not allowed from hard interrupt context. cyclictest command line: This patch reduces the average latency in my tests from 14us to 11us. Daniel writes: Paolo asked for numbers from kvm-unit-tests/tscdeadline_latency benchmark on mainline. The test was run 1000 times on tip/sched/core 4.4.0-rc8-01134-g0905f04: ./x86-run x86/tscdeadline_latency.flat -cpu host with idle=poll. The test seems not to deliver really stable numbers though most of them are smaller. Paolo write: "Anything above ~10000 cycles means that the host went to C1 or lower---the number means more or less nothing in that case. The mean shows an improvement indeed." Before: min max mean std count 1000.000000 1000.000000 1000.000000 1000.000000 mean 5162.596000 2019270.084000 5824.491541 20681.645558 std 75.431231 622607.723969 89.575700 6492.272062 min 4466.000000 23928.000000 5537.926500 585.864966 25% 5163.000000 1613252.750000 5790.132275 16683.745433 50% 5175.000000 2281919.000000 5834.654000 23151.990026 75% 5190.000000 2382865.750000 5861.412950 24148.206168 max 5228.000000 4175158.000000 6254.827300 46481.048691 After min max mean std count 1000.000000 1000.00000 1000.000000 1000.000000 mean 5143.511000 2076886.10300 5813.312474 21207.357565 std 77.668322 610413.09583 86.541500 6331.915127 min 4427.000000 25103.00000 5529.756600 559.187707 25% 5148.000000 1691272.75000 5784.889825 17473.518244 50% 5160.000000 2308328.50000 5832.025000 23464.837068 75% 5172.000000 2393037.75000 5853.177675 24223.969976 max 5222.000000 3922458.00000 6186.720500 42520.379830 [Patch was originaly based on the swait implementation found in the -rt tree. Daniel ported it to mainline's version and gathered the benchmark numbers for tscdeadline_latency test.] Signed-off-by: Daniel Wagner <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Cc: [email protected] Cc: Boqun Feng <[email protected]> Cc: Marcelo Tosatti <[email protected]> Cc: Steven Rostedt <[email protected]> Cc: Paul Gortmaker <[email protected]> Cc: Paolo Bonzini <[email protected]> Cc: "Paul E. McKenney" <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Thomas Gleixner <[email protected]>
1 parent ef50c04 commit 8577370

File tree

11 files changed

+42
-43
lines changed

11 files changed

+42
-43
lines changed

arch/arm/kvm/arm.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -506,18 +506,18 @@ static void kvm_arm_resume_guest(struct kvm *kvm)
506506
struct kvm_vcpu *vcpu;
507507

508508
kvm_for_each_vcpu(i, vcpu, kvm) {
509-
wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu);
509+
struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
510510

511511
vcpu->arch.pause = false;
512-
wake_up_interruptible(wq);
512+
swake_up(wq);
513513
}
514514
}
515515

516516
static void vcpu_sleep(struct kvm_vcpu *vcpu)
517517
{
518-
wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu);
518+
struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
519519

520-
wait_event_interruptible(*wq, ((!vcpu->arch.power_off) &&
520+
swait_event_interruptible(*wq, ((!vcpu->arch.power_off) &&
521521
(!vcpu->arch.pause)));
522522
}
523523

arch/arm/kvm/psci.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
7070
{
7171
struct kvm *kvm = source_vcpu->kvm;
7272
struct kvm_vcpu *vcpu = NULL;
73-
wait_queue_head_t *wq;
73+
struct swait_queue_head *wq;
7474
unsigned long cpu_id;
7575
unsigned long context_id;
7676
phys_addr_t target_pc;
@@ -119,7 +119,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
119119
smp_mb(); /* Make sure the above is visible */
120120

121121
wq = kvm_arch_vcpu_wq(vcpu);
122-
wake_up_interruptible(wq);
122+
swake_up(wq);
123123

124124
return PSCI_RET_SUCCESS;
125125
}

arch/mips/kvm/mips.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -445,8 +445,8 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
445445

446446
dvcpu->arch.wait = 0;
447447

448-
if (waitqueue_active(&dvcpu->wq))
449-
wake_up_interruptible(&dvcpu->wq);
448+
if (swait_active(&dvcpu->wq))
449+
swake_up(&dvcpu->wq);
450450

451451
return 0;
452452
}
@@ -1174,8 +1174,8 @@ static void kvm_mips_comparecount_func(unsigned long data)
11741174
kvm_mips_callbacks->queue_timer_int(vcpu);
11751175

11761176
vcpu->arch.wait = 0;
1177-
if (waitqueue_active(&vcpu->wq))
1178-
wake_up_interruptible(&vcpu->wq);
1177+
if (swait_active(&vcpu->wq))
1178+
swake_up(&vcpu->wq);
11791179
}
11801180

11811181
/* low level hrtimer wake routine */

arch/powerpc/include/asm/kvm_host.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ struct kvmppc_vcore {
289289
struct list_head runnable_threads;
290290
struct list_head preempt_list;
291291
spinlock_t lock;
292-
wait_queue_head_t wq;
292+
struct swait_queue_head wq;
293293
spinlock_t stoltb_lock; /* protects stolen_tb and preempt_tb */
294294
u64 stolen_tb;
295295
u64 preempt_tb;
@@ -629,7 +629,7 @@ struct kvm_vcpu_arch {
629629
u8 prodded;
630630
u32 last_inst;
631631

632-
wait_queue_head_t *wqp;
632+
struct swait_queue_head *wqp;
633633
struct kvmppc_vcore *vcore;
634634
int ret;
635635
int trap;

arch/powerpc/kvm/book3s_hv.c

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,11 @@ static bool kvmppc_ipi_thread(int cpu)
114114
static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu)
115115
{
116116
int cpu;
117-
wait_queue_head_t *wqp;
117+
struct swait_queue_head *wqp;
118118

119119
wqp = kvm_arch_vcpu_wq(vcpu);
120-
if (waitqueue_active(wqp)) {
121-
wake_up_interruptible(wqp);
120+
if (swait_active(wqp)) {
121+
swake_up(wqp);
122122
++vcpu->stat.halt_wakeup;
123123
}
124124

@@ -701,8 +701,8 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
701701
tvcpu->arch.prodded = 1;
702702
smp_mb();
703703
if (vcpu->arch.ceded) {
704-
if (waitqueue_active(&vcpu->wq)) {
705-
wake_up_interruptible(&vcpu->wq);
704+
if (swait_active(&vcpu->wq)) {
705+
swake_up(&vcpu->wq);
706706
vcpu->stat.halt_wakeup++;
707707
}
708708
}
@@ -1459,7 +1459,7 @@ static struct kvmppc_vcore *kvmppc_vcore_create(struct kvm *kvm, int core)
14591459
INIT_LIST_HEAD(&vcore->runnable_threads);
14601460
spin_lock_init(&vcore->lock);
14611461
spin_lock_init(&vcore->stoltb_lock);
1462-
init_waitqueue_head(&vcore->wq);
1462+
init_swait_queue_head(&vcore->wq);
14631463
vcore->preempt_tb = TB_NIL;
14641464
vcore->lpcr = kvm->arch.lpcr;
14651465
vcore->first_vcpuid = core * threads_per_subcore;
@@ -2531,10 +2531,9 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
25312531
{
25322532
struct kvm_vcpu *vcpu;
25332533
int do_sleep = 1;
2534+
DECLARE_SWAITQUEUE(wait);
25342535

2535-
DEFINE_WAIT(wait);
2536-
2537-
prepare_to_wait(&vc->wq, &wait, TASK_INTERRUPTIBLE);
2536+
prepare_to_swait(&vc->wq, &wait, TASK_INTERRUPTIBLE);
25382537

25392538
/*
25402539
* Check one last time for pending exceptions and ceded state after
@@ -2548,15 +2547,15 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
25482547
}
25492548

25502549
if (!do_sleep) {
2551-
finish_wait(&vc->wq, &wait);
2550+
finish_swait(&vc->wq, &wait);
25522551
return;
25532552
}
25542553

25552554
vc->vcore_state = VCORE_SLEEPING;
25562555
trace_kvmppc_vcore_blocked(vc, 0);
25572556
spin_unlock(&vc->lock);
25582557
schedule();
2559-
finish_wait(&vc->wq, &wait);
2558+
finish_swait(&vc->wq, &wait);
25602559
spin_lock(&vc->lock);
25612560
vc->vcore_state = VCORE_INACTIVE;
25622561
trace_kvmppc_vcore_blocked(vc, 1);
@@ -2612,7 +2611,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
26122611
kvmppc_start_thread(vcpu, vc);
26132612
trace_kvm_guest_enter(vcpu);
26142613
} else if (vc->vcore_state == VCORE_SLEEPING) {
2615-
wake_up(&vc->wq);
2614+
swake_up(&vc->wq);
26162615
}
26172616

26182617
}

arch/s390/include/asm/kvm_host.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ struct kvm_s390_irq_payload {
467467
struct kvm_s390_local_interrupt {
468468
spinlock_t lock;
469469
struct kvm_s390_float_interrupt *float_int;
470-
wait_queue_head_t *wq;
470+
struct swait_queue_head *wq;
471471
atomic_t *cpuflags;
472472
DECLARE_BITMAP(sigp_emerg_pending, KVM_MAX_VCPUS);
473473
struct kvm_s390_irq_payload irq;

arch/s390/kvm/interrupt.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -966,13 +966,13 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
966966

967967
void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu)
968968
{
969-
if (waitqueue_active(&vcpu->wq)) {
969+
if (swait_active(&vcpu->wq)) {
970970
/*
971971
* The vcpu gave up the cpu voluntarily, mark it as a good
972972
* yield-candidate.
973973
*/
974974
vcpu->preempted = true;
975-
wake_up_interruptible(&vcpu->wq);
975+
swake_up(&vcpu->wq);
976976
vcpu->stat.halt_wakeup++;
977977
}
978978
}

arch/x86/kvm/lapic.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,7 +1195,7 @@ static void apic_update_lvtt(struct kvm_lapic *apic)
11951195
static void apic_timer_expired(struct kvm_lapic *apic)
11961196
{
11971197
struct kvm_vcpu *vcpu = apic->vcpu;
1198-
wait_queue_head_t *q = &vcpu->wq;
1198+
struct swait_queue_head *q = &vcpu->wq;
11991199
struct kvm_timer *ktimer = &apic->lapic_timer;
12001200

12011201
if (atomic_read(&apic->lapic_timer.pending))
@@ -1204,8 +1204,8 @@ static void apic_timer_expired(struct kvm_lapic *apic)
12041204
atomic_inc(&apic->lapic_timer.pending);
12051205
kvm_set_pending_timer(vcpu);
12061206

1207-
if (waitqueue_active(q))
1208-
wake_up_interruptible(q);
1207+
if (swait_active(q))
1208+
swake_up(q);
12091209

12101210
if (apic_lvtt_tscdeadline(apic))
12111211
ktimer->expired_tscdeadline = ktimer->tscdeadline;

include/linux/kvm_host.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/irqflags.h>
2626
#include <linux/context_tracking.h>
2727
#include <linux/irqbypass.h>
28+
#include <linux/swait.h>
2829
#include <asm/signal.h>
2930

3031
#include <linux/kvm.h>
@@ -218,7 +219,7 @@ struct kvm_vcpu {
218219
int fpu_active;
219220
int guest_fpu_loaded, guest_xcr0_loaded;
220221
unsigned char fpu_counter;
221-
wait_queue_head_t wq;
222+
struct swait_queue_head wq;
222223
struct pid *pid;
223224
int sigset_active;
224225
sigset_t sigset;
@@ -782,7 +783,7 @@ static inline bool kvm_arch_has_assigned_device(struct kvm *kvm)
782783
}
783784
#endif
784785

785-
static inline wait_queue_head_t *kvm_arch_vcpu_wq(struct kvm_vcpu *vcpu)
786+
static inline struct swait_queue_head *kvm_arch_vcpu_wq(struct kvm_vcpu *vcpu)
786787
{
787788
#ifdef __KVM_HAVE_ARCH_WQP
788789
return vcpu->arch.wqp;

virt/kvm/async_pf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ static void async_pf_execute(struct work_struct *work)
9797
* This memory barrier pairs with prepare_to_wait's set_current_state()
9898
*/
9999
smp_mb();
100-
if (waitqueue_active(&vcpu->wq))
101-
wake_up_interruptible(&vcpu->wq);
100+
if (swait_active(&vcpu->wq))
101+
swake_up(&vcpu->wq);
102102

103103
mmput(mm);
104104
kvm_put_kvm(vcpu->kvm);

virt/kvm/kvm_main.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,7 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
216216
vcpu->kvm = kvm;
217217
vcpu->vcpu_id = id;
218218
vcpu->pid = NULL;
219-
vcpu->halt_poll_ns = 0;
220-
init_waitqueue_head(&vcpu->wq);
219+
init_swait_queue_head(&vcpu->wq);
221220
kvm_async_pf_vcpu_init(vcpu);
222221

223222
vcpu->pre_pcpu = -1;
@@ -1990,7 +1989,7 @@ static int kvm_vcpu_check_block(struct kvm_vcpu *vcpu)
19901989
void kvm_vcpu_block(struct kvm_vcpu *vcpu)
19911990
{
19921991
ktime_t start, cur;
1993-
DEFINE_WAIT(wait);
1992+
DECLARE_SWAITQUEUE(wait);
19941993
bool waited = false;
19951994
u64 block_ns;
19961995

@@ -2015,7 +2014,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
20152014
kvm_arch_vcpu_blocking(vcpu);
20162015

20172016
for (;;) {
2018-
prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
2017+
prepare_to_swait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
20192018

20202019
if (kvm_vcpu_check_block(vcpu) < 0)
20212020
break;
@@ -2024,7 +2023,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
20242023
schedule();
20252024
}
20262025

2027-
finish_wait(&vcpu->wq, &wait);
2026+
finish_swait(&vcpu->wq, &wait);
20282027
cur = ktime_get();
20292028

20302029
kvm_arch_vcpu_unblocking(vcpu);
@@ -2056,11 +2055,11 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
20562055
{
20572056
int me;
20582057
int cpu = vcpu->cpu;
2059-
wait_queue_head_t *wqp;
2058+
struct swait_queue_head *wqp;
20602059

20612060
wqp = kvm_arch_vcpu_wq(vcpu);
2062-
if (waitqueue_active(wqp)) {
2063-
wake_up_interruptible(wqp);
2061+
if (swait_active(wqp)) {
2062+
swake_up(wqp);
20642063
++vcpu->stat.halt_wakeup;
20652064
}
20662065

@@ -2161,7 +2160,7 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me)
21612160
continue;
21622161
if (vcpu == me)
21632162
continue;
2164-
if (waitqueue_active(&vcpu->wq) && !kvm_arch_vcpu_runnable(vcpu))
2163+
if (swait_active(&vcpu->wq) && !kvm_arch_vcpu_runnable(vcpu))
21652164
continue;
21662165
if (!kvm_vcpu_eligible_for_directed_yield(vcpu))
21672166
continue;

0 commit comments

Comments
 (0)