Il 05/02/2014 12:02, Peter Krempa ha scritto:
Add a new <timer> for the HyperV reference time counter
enlightenment
for Windows guests.
This feature provides a paravirtual approach to track timer events for
the quest (similar to kvmclock).
RTC can be confusing because the same acronym expands to both "real-time
clock" and "reference time counter".
By the way, the same <timer> will drive two things: the reference time
counter, and the reference TSC page. In current kernels, the reference
TSC page just tells the guest "use the reference time counter", but this
can be changed in the future without breaking the guest ABI.
So, what about naming it hv_clock or hyperv_clock or hyperv_ref?
Paolo
---
docs/formatdomain.html.in | 7 ++++-
docs/schemas/domaincommon.rng | 5 +++-
src/conf/domain_conf.c | 6 +++--
src/conf/domain_conf.h | 1 +
src/qemu/qemu_command.c | 30 ++++++++++++----------
.../qemuxml2argv-clock-timer-hyperv-rtc.args | 5 ++++
.../qemuxml2argv-clock-timer-hyperv-rtc.xml | 26 +++++++++++++++++++
tests/qemuxml2argvtest.c | 1 +
tests/qemuxml2xmltest.c | 1 +
9 files changed, 65 insertions(+), 17 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index fd02864..451ce8f 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1367,7 +1367,12 @@
being modified, and can be one of
"platform" (currently unsupported),
"hpet" (libxl, xen, qemu), "kvmclock" (qemu),
- "pit" (qemu), "rtc" (qemu), or "tsc" (libxl).
+ "pit" (qemu), "rtc" (qemu), "tsc" (libxl) or
"hyperv_rtc"
+ (qemu - <span class="since">since 1.2.2</span>).
+
+ The <code>hyperv_rtc</code> timer adds support for the
+ "reference time counter" feature for guests running the
+ Microsoft Windows operating system.
</dd>
<dt><code>track</code></dt>
<dd>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 12fc0db..96e62d3 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -915,7 +915,10 @@
</group>
<group>
<attribute name="name">
- <value>kvmclock</value>
+ <choice>
+ <value>kvmclock</value>
+ <value>hyperv_rtc</value>
+ </choice>
</attribute>
</group>
</choice>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b6c984b..33b5bee 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -726,7 +726,8 @@ VIR_ENUM_IMPL(virDomainTimerName, VIR_DOMAIN_TIMER_NAME_LAST,
"rtc",
"hpet",
"tsc",
- "kvmclock");
+ "kvmclock",
+ "hyperv_rtc");
VIR_ENUM_IMPL(virDomainTimerTrack, VIR_DOMAIN_TIMER_TRACK_LAST,
"boot",
@@ -2929,7 +2930,8 @@ virDomainDefPostParseInternal(virDomainDefPtr def,
for (i = 0; i < def->clock.ntimers; i++) {
virDomainTimerDefPtr timer = def->clock.timers[i];
- if (timer->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK) {
+ if (timer->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK ||
+ timer->name == VIR_DOMAIN_TIMER_NAME_HYPERV_RTC) {
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 d8f2e49..300ba26 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1750,6 +1750,7 @@ enum virDomainTimerNameType {
VIR_DOMAIN_TIMER_NAME_HPET,
VIR_DOMAIN_TIMER_NAME_TSC,
VIR_DOMAIN_TIMER_NAME_KVMCLOCK,
+ VIR_DOMAIN_TIMER_NAME_HYPERV_RTC,
VIR_DOMAIN_TIMER_NAME_LAST
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index eef65ae..bc5219c 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6728,20 +6728,23 @@ qemuBuildCpuArgStr(virQEMUDriverPtr driver,
}
}
- /* Now force kvmclock on/off based on the corresponding <timer> element. */
+ /* Handle paravirtual timers */
for (i = 0; i < def->clock.ntimers; i++) {
- if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK
&&
- def->clock.timers[i]->present != -1) {
- char sign;
- if (def->clock.timers[i]->present)
- sign = '+';
- else
- sign = '-';
+ virDomainTimerDefPtr timer = def->clock.timers[i];
+
+ if (timer->present == -1)
+ continue;
+
+ if (timer->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK) {
virBufferAsprintf(&buf, "%s,%ckvmclock",
have_cpu ? "" : default_model,
- sign);
+ timer->present ? '+' : '-');
+ have_cpu = true;
+ } else if (timer->name == VIR_DOMAIN_TIMER_NAME_HYPERV_RTC &&
+ timer->present) {
+ virBufferAsprintf(&buf, "%s,hv_time",
+ have_cpu ? "" : default_model);
have_cpu = true;
- break;
}
}
@@ -8003,8 +8006,7 @@ qemuBuildCommandLine(virConnectPtr conn,
}
for (i = 0; i < def->clock.ntimers; i++) {
- switch (def->clock.timers[i]->name) {
- default:
+ switch ((enum virDomainTimerNameType) def->clock.timers[i]->name) {
case VIR_DOMAIN_TIMER_NAME_PLATFORM:
case VIR_DOMAIN_TIMER_NAME_TSC:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -8013,7 +8015,9 @@ qemuBuildCommandLine(virConnectPtr conn,
goto error;
case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
- /* This is handled when building -cpu. */
+ case VIR_DOMAIN_TIMER_NAME_HYPERV_RTC:
+ /* Timers above are handled when building -cpu. */
+ case VIR_DOMAIN_TIMER_NAME_LAST:
break;
case VIR_DOMAIN_TIMER_NAME_RTC:
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.args
b/tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.args
new file mode 100644
index 0000000..1905875
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.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,hv_time -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-hyperv-rtc.xml
b/tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.xml
new file mode 100644
index 0000000..47c7c42
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.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='hyperv_rtc' 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 a25264e..1394d68 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -628,6 +628,7 @@ mymain(void)
DO_TEST("cpu-kvmclock", QEMU_CAPS_ENABLE_KVM);
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("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 41d1904..e12a0ab 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -159,6 +159,7 @@ mymain(void)
DO_TEST("cpu-kvmclock");
DO_TEST("cpu-host-kvmclock");
DO_TEST("kvmclock");
+ DO_TEST("clock-timer-hyperv-rtc");
DO_TEST("cpu-eoi-disabled");
DO_TEST("cpu-eoi-enabled");