Not yet merged in upstream QEMU: https://lists.gnu.org/archive/html/qemu-devel/2014-04/msg05024.html Add support for invariant TSC timer running at constant rate in all ACPI P-, C- and T-states. It can be enabled by specifying: <clock> <timer name='invtsc' present='yes'/> </clock> in the domain XML. Migration and saving the domain does not work with this timer. The support for this timer is indicated by bit 8 of EDX after calling CPUID with 0x80000007. It does not show up in /proc/cpuinfo [1] and since we're calling qemu without 'enforce', it doesn't error out if the host doesn't support this. Alternatively, we could expose it in libvirt as a cpu flag: <cpu mode='custom' match='exact'> <model fallback='forbid'>qemu64</model> <feature policy='require' name='invtsc'/> </cpu> or maybe add +invtsc to qemu args when the 'nonstop_tsc' flag is requested? [1]: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/powerflags.c?id=30321c7b#n18 --- docs/formatdomain.html.in | 9 ++++++-- docs/schemas/domaincommon.rng | 1 + src/conf/domain_conf.c | 6 +++-- src/conf/domain_conf.h | 1 + src/qemu/qemu_command.c | 6 +++++ src/qemu/qemu_migration.c | 14 ++++++++++++ .../qemuxml2argv-clock-timer-inv-tsc.args | 5 +++++ .../qemuxml2argv-clock-timer-inv-tsc.xml | 26 ++++++++++++++++++++++ tests/qemuxml2argvtest.c | 1 + tests/qemuxml2xmltest.c | 1 + 10 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-timer-inv-tsc.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-timer-inv-tsc.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 4f19473..1d3fd93 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1368,13 +1368,18 @@ being modified, and can be one of "platform" (currently unsupported), "hpet" (libxl, xen, qemu), "kvmclock" (qemu), - "pit" (qemu), "rtc" (qemu), "tsc" (libxl) or "hypervclock" - (qemu - <span class="since">since 1.2.2</span>). + "pit" (qemu), "rtc" (qemu), "tsc" (libxl), "hypervclock" + (qemu - <span class="since">since 1.2.2</span>) or + "invtsc" (qemu - <span class="since">since 1.2.5</span>). The <code>hypervclock</code> timer adds support for the reference time counter and the reference page for iTSC feature for guests running the Microsoft Windows operating system. + + The <code>invtsc</code> timer adds support for the invariant + TSC. It runs at a constant rate in all ACPI P- C- and T-states. + A guest with this timer enabled cannot be migrated or saved. </dd> <dt><code>track</code></dt> <dd> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 4249ed5..5154826 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -918,6 +918,7 @@ <choice> <value>kvmclock</value> <value>hypervclock</value> + <value>invtsc</value> </choice> </attribute> </group> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 6c3bdad..893d904 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -706,7 +706,8 @@ VIR_ENUM_IMPL(virDomainTimerName, VIR_DOMAIN_TIMER_NAME_LAST, "hpet", "tsc", "kvmclock", - "hypervclock"); + "hypervclock", + "invtsc"); VIR_ENUM_IMPL(virDomainTimerTrack, VIR_DOMAIN_TIMER_TRACK_LAST, "boot", @@ -2931,7 +2932,8 @@ virDomainDefPostParseInternal(virDomainDefPtr def, virDomainTimerDefPtr timer = def->clock.timers[i]; if (timer->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK || - timer->name == VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK) { + timer->name == VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK || + timer->name == VIR_DOMAIN_TIMER_NAME_INVTSC) { if (timer->tickpolicy != -1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("timer %s doesn't support setting of " diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index a92f0f3..53c02e6 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1635,6 +1635,7 @@ enum virDomainTimerNameType { VIR_DOMAIN_TIMER_NAME_TSC, VIR_DOMAIN_TIMER_NAME_KVMCLOCK, VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK, + VIR_DOMAIN_TIMER_NAME_INVTSC, VIR_DOMAIN_TIMER_NAME_LAST }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 6c1e17d..2994427 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6736,6 +6736,11 @@ qemuBuildCpuArgStr(virQEMUDriverPtr driver, have_cpu ? "" : default_model, timer->present ? '+' : '-'); have_cpu = true; + } else if (timer->name == VIR_DOMAIN_TIMER_NAME_INVTSC) { + virBufferAsprintf(&buf, "%s,%cinvtsc", + have_cpu ? "" : default_model, + timer->present ? '+' : '-'); + have_cpu = true; } else if (timer->name == VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK && timer->present) { virBufferAsprintf(&buf, "%s,hv_time", @@ -8063,6 +8068,7 @@ qemuBuildCommandLine(virConnectPtr conn, case VIR_DOMAIN_TIMER_NAME_KVMCLOCK: case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK: + case VIR_DOMAIN_TIMER_NAME_INVTSC: /* Timers above are handled when building -cpu. */ case VIR_DOMAIN_TIMER_NAME_LAST: break; diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index a9f7fea..c1ffc0f 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1513,6 +1513,20 @@ qemuMigrationIsAllowed(virQEMUDriverPtr driver, virDomainObjPtr vm, return false; } + for (i = 0; i < def->clock.ntimers; i++) { + virDomainTimerDefPtr timer = def->clock.timers[i]; + + if (timer->present != 1) + continue; + + if (timer->name == VIR_DOMAIN_TIMER_NAME_INVTSC) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("domain has '%s' timer"), + virDomainTimerNameTypeToString(timer->name)); + return false; + } + } + return true; } diff --git a/tests/qemuxml2argvdata/qemuxml2argv-clock-timer-inv-tsc.args b/tests/qemuxml2argvdata/qemuxml2argv-clock-timer-inv-tsc.args new file mode 100644 index 0000000..ae74ae8 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-clock-timer-inv-tsc.args @@ -0,0 +1,5 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \ +/usr/bin/kvm -S -M pc \ +-cpu qemu32,+invtsc -m 214 -smp 6 \ +-nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot n -usb -net \ +none -serial none -parallel none diff --git a/tests/qemuxml2argvdata/qemuxml2argv-clock-timer-inv-tsc.xml b/tests/qemuxml2argvdata/qemuxml2argv-clock-timer-inv-tsc.xml new file mode 100644 index 0000000..b4a82e8 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-clock-timer-inv-tsc.xml @@ -0,0 +1,26 @@ +<domain type='kvm'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>6</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='network'/> + </os> + <features> + <pae/> + </features> + <clock offset='utc'> + <timer name='invtsc' present='yes'/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/kvm</emulator> + <controller type='usb' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 14482fd..3c5024e 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -641,6 +641,7 @@ mymain(void) DO_TEST("cpu-host-kvmclock", QEMU_CAPS_ENABLE_KVM, QEMU_CAPS_CPU_HOST); DO_TEST("kvmclock", QEMU_CAPS_KVM); DO_TEST("clock-timer-hyperv-rtc", QEMU_CAPS_KVM); + DO_TEST("clock-timer-inv-tsc", QEMU_CAPS_KVM); DO_TEST("cpu-eoi-disabled", QEMU_CAPS_ENABLE_KVM); DO_TEST("cpu-eoi-enabled", QEMU_CAPS_ENABLE_KVM); diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 3ea03e6..a659cd0 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -185,6 +185,7 @@ mymain(void) DO_TEST("clock-catchup"); DO_TEST("kvmclock"); DO_TEST("clock-timer-hyperv-rtc"); + DO_TEST("clock-timer-inv-tsc"); DO_TEST("cpu-eoi-disabled"); DO_TEST("cpu-eoi-enabled"); -- 1.8.3.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list