[libvirt] [RFC PATCH] Add support for invtsc timer
Marcelo Tosatti
mtosatti at redhat.com
Wed May 7 22:35:13 UTC 2014
On Tue, May 06, 2014 at 03:27:20PM +0200, Ján Tomko wrote:
> 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.
It is not a timer, really, but a CPU flag.
> 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>
Would prefer that option. Can't one modify QEMU's "-cpu" parameters, via
libvirt XML?
> or maybe add +invtsc to qemu args when the 'nonstop_tsc' flag is
> requested?
No, since it blocks migration better not condition "+invtsc" on
presence of 'nonstop_tsc' flag.
>
> [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
More information about the libvir-list
mailing list