Sync TSC for guest when vcpu has been migrated to another cpu
cover Sync TSC for guest when vcpu has been migrated to another cpu
When a vcpu is migrated to another cpu, an unexpected difference in current and previous cpu TSC values can cause a guest to wait indefinitely. A known workaround has been to run kvm with taskset, locking it to a single cpu. This patch series modifies the guest TSC offset as needed to guarantee that the guest sees a monotonically increasing TSC, adds a statistic for vcpu_migrated and updates kvm_stat so the first column isn't truncated.
[1/3] Sync guest viewable TSC when vcpu migrated
[2/3] Add a vcpu_migrated statistic
[3/3] Widen key column in kvm_stat
-- Leonard
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
A message that is not in the archive (sent off-list or not yet received): 45E853A0.3080207-g2GXA8XeJSExHbG02/[email protected]
PATCH 1/3 Sync guest viewable TSC when vcpu migrated
When a vcpu is migrated to another cpu, an unexpected difference in current and previous cpu TSC values can cause a guest to wait indefinitely. A known workaround has been to run kvm with taskset, locking it to a single cpu. This patch modifies the guest viewable TSC so that the TSC is guaranteed to be monotonically increasing.
Thanks to Avi Kivity for help in pinpointing this issue and advice for fixing it.
drivers/kvm/svm.c +37 -1
@@ -598,9 +598,45 @@kfree (vcpu->svm); } +#ifdef CONFIG_SMP +static void ipi_rdtscll (void *arg) +{ +u64 *tsc = arg; +rdtscll (*tsc); +} +#endif + +/* +* Switches to specified vcpu, until a matching vcpu_put(), but assumes +* vcpu mutex is already taken. +*/ static struct kvm_vcpu *svm_vcpu_load (struct kvm_vcpu *vcpu) { -get_cpu (); +int cpu; + + cpu =get_cpu (); + +#ifdef CONFIG_SMP +if (vcpu->cpu != cpu) { +if (vcpu->cpu !=-1 ) { +u64 tsc_this, tsc_previous; + +/* Get TSC value for this and the previous cpu. */ +rdtscll (tsc_this); +smp_call_function_single (vcpu->cpu, ipi_rdtscll, + &tsc_previous,0 ,1 ); + +/* +* Make sure that the guest sees a monotonically +* increasing TSC. +*/ + vcpu->svm->vmcb->control.tsc_offset += + tsc_previous - tsc_this; + } + } +#endif + + vcpu->cpu = cpu;return vcpu; }
drivers/kvm/vmx.c +27 -0
@@ -200,6 +200,14 @@#endif } +#ifdef CONFIG_SMP +static void ipi_rdtscll (void *arg) +{ +u64 *tsc = arg; +rdtscll (*tsc); +} +#endif +/* * Switches to specified vcpu, until a matching vcpu_put(), but assumes * vcpu mutex is already taken.
@@ -230,6 +238,25 @@struct descriptor_table dt;unsigned long sysenter_esp; +#ifdef CONFIG_SMP +if (vcpu->cpu !=-1 ) { +u64 tsc_this, tsc_previous, guest_tsc_offset; + +/* Get TSC value for this and the previous cpu. */ +rdtscll (tsc_this); +smp_call_function_single (vcpu->cpu, ipi_rdtscll, + &tsc_previous,0 ,1 ); + +/* +* Make sure that the guest sees a monotonically +* increasing TSC. +*/ + guest_tsc_offset =vmcs_read64 (TSC_OFFSET ); +vmcs_write64 (TSC_OFFSET , guest_tsc_offset + + tsc_previous - tsc_this); + } +#endif + vcpu->cpu = cpu;/* * Linux uses per-cpu TSS and GDT, so set these when switching
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel
A message that is not in the archive (sent off-list or not yet received): 45E85566.3010706-g2GXA8XeJSExHbG02/[email protected]
Re: [PATCH 1/3] Sync guest viewable TSC when vcpu migrated
Quoted 11 lines · Leonard Norrgard
When a vcpu is migrated to another cpu, an unexpected difference in current and previous cpu TSC values can cause a guest to wait indefinitely. A known workaround has been to run kvm with taskset, locking it to a single cpu. This patch modifies the guest viewable TSC so that the TSC is guaranteed to be monotonically increasing.
Thanks to Avi Kivity for help in pinpointing this issue and advice for fixing it.
Signed-off-by Leonard Norrgård <[email protected]>
Hi Leonard,
Why not factor the common code into kvm_main.c and add a set_tsc_offset member to the kvm ops function table?
Regards,
Anthony Liguori
Quoted 108 lines
------------------------------------------------------------------------
Index:
linux-2.6/drivers/kvm/svm.c
===================================================================drivers/kvm/svm.c +37
-1@@ -598,9 +598,45 @@kfree (vcpu->svm); } +#ifdef CONFIG_SMP +static void ipi_rdtscll (void *arg) +{ +u64 *tsc = arg; +rdtscll (*tsc); +} +#endif + +/* +* Switches to specified vcpu, until a matching vcpu_put(), but assumes +* vcpu mutex is already taken. +*/ static struct kvm_vcpu *svm_vcpu_load (struct kvm_vcpu *vcpu) { -get_cpu (); +int cpu; + + cpu =get_cpu (); + +#ifdef CONFIG_SMP +if (vcpu->cpu != cpu) { +if (vcpu->cpu !=-1 ) { +u64 tsc_this, tsc_previous; + +/* Get TSC value for this and the previous cpu. */ +rdtscll (tsc_this); +smp_call_function_single (vcpu->cpu, ipi_rdtscll, + &tsc_previous,0 ,1 ); + +/* +* Make sure that the guest sees a monotonically +* increasing TSC. +*/ + vcpu->svm->vmcb->control.tsc_offset += + tsc_previous - tsc_this; + } + } +#endif + + vcpu->cpu = cpu;return vcpu; }Index:
linux-2.6/drivers/kvm/vmx.c
===================================================================drivers/kvm/vmx.c +27
-2@@ -200,6 +200,14 @@#endif } +#ifdef CONFIG_SMP +static void ipi_rdtscll (void *arg) +{ +u64 *tsc = arg; +rdtscll (*tsc); +} +#endif +/* * Switches to specified vcpu, until a matching vcpu_put(), but assumes * vcpu mutex is already taken. @@ -230,6 +238,25 @@struct descriptor_table dt;unsigned long sysenter_esp; +#ifdef CONFIG_SMP +if (vcpu->cpu !=-1 ) { +u64 tsc_this, tsc_previous, guest_tsc_offset; + +/* Get TSC value for this and the previous cpu. */ +rdtscll (tsc_this); +smp_call_function_single (vcpu->cpu, ipi_rdtscll, + &tsc_previous,0 ,1 ); + +/* +* Make sure that the guest sees a monotonically +* increasing TSC. +*/ + guest_tsc_offset =vmcs_read64 (TSC_OFFSET ); +vmcs_write64 (TSC_OFFSET , guest_tsc_offset + + tsc_previous - tsc_this); + } +#endif + vcpu->cpu = cpu;/* * Linux uses per-cpu TSS and GDT, so set these when switching ------------------------------------------------------------------------ ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
------------------------------------------------------------------------
Quoted 5 lines
_______________________________________________
kvm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
kvm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel
A message that is not in the archive (sent off-list or not yet received): 45E85717.6030906-r/[email protected]
Re: [PATCH 1/3] Sync guest viewable TSC when vcpu migrated
Quoted 4 lines
Hi Leonard,
Why not factor the common code into
kvm_main.cand add aset_tsc_offsetmember to the kvm ops function table?
Good idea, I put it on the todo list.
Quoted 3 lines
Regards,
Anthony Liguori
Thanks,
-- Leonard
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
Re: [PATCH 1/3] Sync guest viewable TSC when vcpu migrated
In reply to a message not in the archiveThanks for picking this up! Some comments below.
Quoted 19 lines · Leonard Norrgard
Index:
linux-2.6/drivers/kvm/svm.c
===================================================================drivers/kvm/svm.c +11
-0@@ -598,9 +598,45 @@kfree (vcpu->svm); } +#ifdef CONFIG_SMP +static void ipi_rdtscll (void *arg) +{ +u64 *tsc = arg; +rdtscll (*tsc); +} +#endif + +/* +* Switches to specified vcpu, until a matching vcpu_put(), but assumes +* vcpu mutex is already taken.
drivers/kvm/svm.c line 620
Quoted 10 lines
drivers/kvm/svm.c +6
-1+*/ static struct kvm_vcpu *svm_vcpu_load (struct kvm_vcpu *vcpu) { -get_cpu (); +int cpu; + + cpu =get_cpu (); + +#ifdef CONFIG_SMP
Please avoid such #ifdefs. Non-SMP virtualization capable processors are rare, and smp_call_function_single() is defined for the !CONFIG_SMP case.
Quoted 51 lines
drivers/kvm/svm.c +15
-0+if (vcpu->cpu != cpu) { +if (vcpu->cpu !=-1 ) { +u64 tsc_this, tsc_previous; + +/* Get TSC value for this and the previous cpu. */ +rdtscll (tsc_this); +smp_call_function_single (vcpu->cpu, ipi_rdtscll, + &tsc_previous,0 ,1 ); + +/* +* Make sure that the guest sees a monotonically +* increasing TSC. +*/ + vcpu->svm->vmcb->control.tsc_offset += + tsc_previous - tsc_this;Index:
linux-2.6/drivers/kvm/vmx.c
===================================================================drivers/kvm/vmx.c +18
-0@@ -200,6 +200,14 @@#endif } +#ifdef CONFIG_SMP +static void ipi_rdtscll (void *arg) +{ +u64 *tsc = arg; +rdtscll (*tsc); +} +#endif +/* * Switches to specified vcpu, until a matching vcpu_put(), but assumes * vcpu mutex is already taken. @@ -230,6 +238,25 @@struct descriptor_table dt;unsigned long sysenter_esp; +#ifdef CONFIG_SMP +if (vcpu->cpu !=-1 ) { +u64 tsc_this, tsc_previous, guest_tsc_offset; + +/* Get TSC value for this and the previous cpu. */ +rdtscll (tsc_this); +smp_call_function_single (vcpu->cpu, ipi_rdtscll, + &tsc_previous,0 ,1 ); + +/*
drivers/kvm/vmx.c line 260
Quoted 10 lines
drivers/kvm/vmx.c +9
-0+* Make sure that the guest sees a monotonically +* increasing TSC. +*/ + guest_tsc_offset =vmcs_read64 (TSC_OFFSET ); +vmcs_write64 (TSC_OFFSET , guest_tsc_offset + + tsc_previous - tsc_this); + } +#endif +
The vmx code already has an IPI (in vcpu_clear), so the two should be merged. IPIs are very expensive.
Perhaps call a vmx_vcpu_migrate IPI, which calls __vcpu_clear() and loads the tsc. You can add a tsc_previous to struct kvm_vcpu so you have somewhere to store it.
Signature · 8 lines
Do not meddle in the internals of kernels, for they are subtle and quick to panic. ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 2/3 Add a vcpu_migrated statistic
In reply to a message not in the archiveThe previous patch introduces an IPI on every vcpu migration on SMP machines to find out the TSC value on the previous cpu. We might be able to avoid this IPI on systems that have a synchronized TSC by checking for it in svm/vmx_vcpu_load:
+ /* If this isn't the first vcpu_load and if the TSC
+ doesn't run at a constant rate, we must handle TSC
+ offsets. */
+ if (vcpu->cpu != -1
+ && !boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) {
Wether this is actually reliable and working in the intended way is not know yet. In the meantime, introduce a statistic for vcpu migration, so we get some decision support for the needs for such an optimization.
drivers/kvm/kvm_main.c +1 -0
@@ -67,6 +67,7 @@ { "halt_exits", &kvm_stat.halt_exits }, { "request_irq", &kvm_stat.request_irq_exits }, { "irq_exits", &kvm_stat.irq_exits }, + { "vcpu_migrated", &kvm_stat.vcpu_migrated }, { NULL, NULL } };
drivers/kvm/svm.c +2 -0
@@ -621,6 +621,8 @@if (vcpu->cpu !=-1 ) {u64 tsc_this, tsc_previous; + ++kvm_stat.vcpu_migrated; +/* Get TSC value for this and the previous cpu. */ rdtscll (tsc_this); smp_call_function_single(vcpu->cpu, ipi_rdtscll,
drivers/kvm/vmx.c +2 -0
@@ -242,6 +242,8 @@if (vcpu->cpu !=-1 ) {u64 tsc_this, tsc_previous, guest_tsc_offset; + ++kvm_stat.vcpu_migrated; +/* Get TSC value for this and the previous cpu. */ rdtscll (tsc_this); smp_call_function_single(vcpu->cpu, ipi_rdtscll,
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel
A message that is not in the archive (sent off-list or not yet received): 45E8567C.6080704-g2GXA8XeJSExHbG02/[email protected]
Re: [PATCH 2/3] Add a vcpu_migrated statistic
Quoted 11 lines · Leonard Norrgard
The previous patch introduces an IPI on every vcpu migration on SMP machines to find out the TSC value on the previous cpu. We might be able to avoid this IPI on systems that have a synchronized TSC by checking for it in svm/vmx_vcpu_load:
(quoted diff) +5
-0+ /* If this isn't the first vcpu_load and if the TSC + doesn't run at a constant rate, we must handle TSC + offsets. */ + if (vcpu->cpu != -1 + && !boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) {
Quoted 2 lines
Wether this is actually reliable and working in the intended way is not know yet.
Reading the documentation for X86_FEATURE_CONSTANT_TSC, I'm not sure either.
Quoted 5 lines
In the meantime, introduce a statistic for vcpu migration, so we get some decision support for the needs for such an optimization.
The statistic is great (vcpu migrations are very expensive, we should know when they happen), but why two unrelated changes in a patch? I think you can drop the constant tsc optimization for now, given we aren't certain it works as we expect.
Signature · 8 lines
Do not meddle in the internals of kernels, for they are subtle and quick to panic. ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 3/3 Widen key column in kvm_stat
In reply to a message not in the archiveMake the key column wider, so the keys are fully shown.
=== kvm_stat
==================================================================
kvm_stat +2 -2
@@ -39,9 +39,9 @@ for key in sorted(s.keys()): values = s[key] screen.addstr(row, 1, key) - screen.addstr(row, 12, '%10d' % (values[0],)) + screen.addstr(row, 14, '%10d' % (values[0],)) if values[1] is not None: - screen.addstr(row, 22, '%8d' % (values[1],)) + screen.addstr(row, 24, '%8d' % (values[1],)) row += 1 screen.refresh()
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel