c401cc
From 6b9aed5d14f800a2f47e6b34460bd618237c0f57 Mon Sep 17 00:00:00 2001
c401cc
Message-Id: <6b9aed5d14f800a2f47e6b34460bd618237c0f57@dist-git>
c401cc
From: Peter Krempa <pkrempa@redhat.com>
c401cc
Date: Mon, 10 Feb 2014 14:02:49 +0100
c401cc
Subject: [PATCH] qemu: hyperv: Add support for timer enlightenments
c401cc
c401cc
https://bugzilla.redhat.com/show_bug.cgi?id=1056205
c401cc
c401cc
Add a new <timer> for the HyperV reference time counter enlightenment
c401cc
and the iTSC reference page for Windows guests.
c401cc
c401cc
This feature provides a paravirtual approach to track timer events for
c401cc
the guest (similar to kvmclock) with the option to use real hardware
c401cc
clock on systems with a iTSC with compensation across various hosts.
c401cc
c401cc
Tweaks:
c401cc
    tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.args:
c401cc
    - removed QEMU_AUDIO_DRV env var
c401cc
c401cc
(cherry picked from commit 600bca592b2352b683856f4b7f2694f366feac36)
c401cc
c401cc
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c401cc
---
c401cc
 docs/formatdomain.html.in                          |  8 +++++-
c401cc
 docs/schemas/domaincommon.rng                      |  5 +++-
c401cc
 src/conf/domain_conf.c                             |  6 +++--
c401cc
 src/conf/domain_conf.h                             |  1 +
c401cc
 src/qemu/qemu_command.c                            | 30 ++++++++++++----------
c401cc
 .../qemuxml2argv-clock-timer-hyperv-rtc.args       |  5 ++++
c401cc
 .../qemuxml2argv-clock-timer-hyperv-rtc.xml        | 26 +++++++++++++++++++
c401cc
 tests/qemuxml2argvtest.c                           |  1 +
c401cc
 tests/qemuxml2xmltest.c                            |  1 +
c401cc
 9 files changed, 66 insertions(+), 17 deletions(-)
c401cc
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.args
c401cc
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.xml
c401cc
c401cc
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
c401cc
index fc8a397..994ebed 100644
c401cc
--- a/docs/formatdomain.html.in
c401cc
+++ b/docs/formatdomain.html.in
c401cc
@@ -1365,7 +1365,13 @@
c401cc
             being modified, and can be one of
c401cc
             "platform" (currently unsupported),
c401cc
             "hpet" (libxl, xen, qemu), "kvmclock" (qemu),
c401cc
-            "pit" (qemu), "rtc" (qemu), or "tsc" (libxl).
c401cc
+            "pit" (qemu), "rtc" (qemu), "tsc" (libxl) or "hypervclock"
c401cc
+            (qemu - since 1.2.2).
c401cc
+
c401cc
+            The hypervclock timer adds support for the
c401cc
+            reference time counter and the reference page for iTSC
c401cc
+            feature for guests running the Microsoft Windows
c401cc
+            operating system.
c401cc
           
c401cc
           
track
c401cc
           
c401cc
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
c401cc
index f75bf78..551e82b 100644
c401cc
--- a/docs/schemas/domaincommon.rng
c401cc
+++ b/docs/schemas/domaincommon.rng
c401cc
@@ -849,7 +849,10 @@
c401cc
         </group>
c401cc
         <group>
c401cc
           <attribute name="name">
c401cc
-            <value>kvmclock</value>
c401cc
+            <choice>
c401cc
+              <value>kvmclock</value>
c401cc
+              <value>hypervclock</value>
c401cc
+            </choice>
c401cc
           </attribute>
c401cc
         </group>
c401cc
       </choice>
c401cc
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
c401cc
index d6c5b3b..6359805 100644
c401cc
--- a/src/conf/domain_conf.c
c401cc
+++ b/src/conf/domain_conf.c
c401cc
@@ -713,7 +713,8 @@ VIR_ENUM_IMPL(virDomainTimerName, VIR_DOMAIN_TIMER_NAME_LAST,
c401cc
               "rtc",
c401cc
               "hpet",
c401cc
               "tsc",
c401cc
-              "kvmclock");
c401cc
+              "kvmclock",
c401cc
+              "hypervclock");
c401cc
 
c401cc
 VIR_ENUM_IMPL(virDomainTimerTrack, VIR_DOMAIN_TIMER_TRACK_LAST,
c401cc
               "boot",
c401cc
@@ -2806,7 +2807,8 @@ virDomainDefPostParseInternal(virDomainDefPtr def,
c401cc
     for (i = 0; i < def->clock.ntimers; i++) {
c401cc
         virDomainTimerDefPtr timer = def->clock.timers[i];
c401cc
 
c401cc
-        if (timer->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK) {
c401cc
+        if (timer->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK ||
c401cc
+            timer->name == VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK) {
c401cc
             if (timer->tickpolicy != -1) {
c401cc
                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
c401cc
                                _("timer %s doesn't support setting of "
c401cc
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
c401cc
index ed40def..824fb8e 100644
c401cc
--- a/src/conf/domain_conf.h
c401cc
+++ b/src/conf/domain_conf.h
c401cc
@@ -1724,6 +1724,7 @@ enum virDomainTimerNameType {
c401cc
     VIR_DOMAIN_TIMER_NAME_HPET,
c401cc
     VIR_DOMAIN_TIMER_NAME_TSC,
c401cc
     VIR_DOMAIN_TIMER_NAME_KVMCLOCK,
c401cc
+    VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK,
c401cc
 
c401cc
     VIR_DOMAIN_TIMER_NAME_LAST
c401cc
 };
c401cc
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
c401cc
index a0ae10c..debafa2 100644
c401cc
--- a/src/qemu/qemu_command.c
c401cc
+++ b/src/qemu/qemu_command.c
c401cc
@@ -6544,20 +6544,23 @@ qemuBuildCpuArgStr(const virQEMUDriverPtr driver,
c401cc
         }
c401cc
     }
c401cc
 
c401cc
-    /* Now force kvmclock on/off based on the corresponding <timer> element.  */
c401cc
+    /* Handle paravirtual timers  */
c401cc
     for (i = 0; i < def->clock.ntimers; i++) {
c401cc
-        if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK &&
c401cc
-            def->clock.timers[i]->present != -1) {
c401cc
-            char sign;
c401cc
-            if (def->clock.timers[i]->present)
c401cc
-                sign = '+';
c401cc
-            else
c401cc
-                sign = '-';
c401cc
+        virDomainTimerDefPtr timer = def->clock.timers[i];
c401cc
+
c401cc
+        if (timer->present == -1)
c401cc
+            continue;
c401cc
+
c401cc
+        if (timer->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK) {
c401cc
             virBufferAsprintf(&buf, "%s,%ckvmclock",
c401cc
                               have_cpu ? "" : default_model,
c401cc
-                              sign);
c401cc
+                              timer->present ? '+' : '-');
c401cc
+            have_cpu = true;
c401cc
+        } else if (timer->name == VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK &&
c401cc
+                   timer->present) {
c401cc
+            virBufferAsprintf(&buf, "%s,hv_time",
c401cc
+                              have_cpu ? "" : default_model);
c401cc
             have_cpu = true;
c401cc
-            break;
c401cc
         }
c401cc
     }
c401cc
 
c401cc
@@ -7798,8 +7801,7 @@ qemuBuildCommandLine(virConnectPtr conn,
c401cc
     }
c401cc
 
c401cc
     for (i = 0; i < def->clock.ntimers; i++) {
c401cc
-        switch (def->clock.timers[i]->name) {
c401cc
-        default:
c401cc
+        switch ((enum virDomainTimerNameType) def->clock.timers[i]->name) {
c401cc
         case VIR_DOMAIN_TIMER_NAME_PLATFORM:
c401cc
         case VIR_DOMAIN_TIMER_NAME_TSC:
c401cc
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
c401cc
@@ -7808,7 +7810,9 @@ qemuBuildCommandLine(virConnectPtr conn,
c401cc
             goto error;
c401cc
 
c401cc
         case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
c401cc
-            /* This is handled when building -cpu.  */
c401cc
+        case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK:
c401cc
+            /* Timers above are handled when building -cpu.  */
c401cc
+        case VIR_DOMAIN_TIMER_NAME_LAST:
c401cc
             break;
c401cc
 
c401cc
         case VIR_DOMAIN_TIMER_NAME_RTC:
c401cc
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.args b/tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.args
c401cc
new file mode 100644
c401cc
index 0000000..368b4c5
c401cc
--- /dev/null
c401cc
+++ b/tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.args
c401cc
@@ -0,0 +1,5 @@
c401cc
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
c401cc
+/usr/bin/kvm -S -M pc \
c401cc
+-cpu qemu32,hv_time -m 214 -smp 6 \
c401cc
+-nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot n -usb -net \
c401cc
+none -serial none -parallel none
c401cc
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.xml b/tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.xml
c401cc
new file mode 100644
c401cc
index 0000000..596e619
c401cc
--- /dev/null
c401cc
+++ b/tests/qemuxml2argvdata/qemuxml2argv-clock-timer-hyperv-rtc.xml
c401cc
@@ -0,0 +1,26 @@
c401cc
+<domain type='kvm'>
c401cc
+  <name>QEMUGuest1</name>
c401cc
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
c401cc
+  <memory unit='KiB'>219100</memory>
c401cc
+  <currentMemory unit='KiB'>219100</currentMemory>
c401cc
+  <vcpu placement='static'>6</vcpu>
c401cc
+  <os>
c401cc
+    <type arch='i686' machine='pc'>hvm</type>
c401cc
+    <boot dev='network'/>
c401cc
+  </os>
c401cc
+  <features>
c401cc
+    <pae/>
c401cc
+  </features>
c401cc
+  <clock offset='utc'>
c401cc
+    <timer name='hypervclock' present='yes'/>
c401cc
+  </clock>
c401cc
+  <on_poweroff>destroy</on_poweroff>
c401cc
+  <on_reboot>restart</on_reboot>
c401cc
+  <on_crash>destroy</on_crash>
c401cc
+  <devices>
c401cc
+    <emulator>/usr/bin/kvm</emulator>
c401cc
+    <controller type='usb' index='0'/>
c401cc
+    <controller type='pci' index='0' model='pci-root'/>
c401cc
+    <memballoon model='virtio'/>
c401cc
+  </devices>
c401cc
+</domain>
c401cc
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
c401cc
index 88ebc18..0e2435b 100644
c401cc
--- a/tests/qemuxml2argvtest.c
c401cc
+++ b/tests/qemuxml2argvtest.c
c401cc
@@ -440,6 +440,7 @@ mymain(void)
c401cc
     DO_TEST("cpu-kvmclock", QEMU_CAPS_ENABLE_KVM);
c401cc
     DO_TEST("cpu-host-kvmclock", QEMU_CAPS_ENABLE_KVM, QEMU_CAPS_CPU_HOST);
c401cc
     DO_TEST("kvmclock", QEMU_CAPS_KVM);
c401cc
+    DO_TEST("clock-timer-hyperv-rtc", QEMU_CAPS_KVM);
c401cc
 
c401cc
     DO_TEST("cpu-eoi-disabled", QEMU_CAPS_ENABLE_KVM);
c401cc
     DO_TEST("cpu-eoi-enabled", QEMU_CAPS_ENABLE_KVM);
c401cc
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
c401cc
index 92504ad..d16fdc3 100644
c401cc
--- a/tests/qemuxml2xmltest.c
c401cc
+++ b/tests/qemuxml2xmltest.c
c401cc
@@ -152,6 +152,7 @@ mymain(void)
c401cc
     DO_TEST("cpu-host-kvmclock");
c401cc
     DO_TEST("clock-catchup");
c401cc
     DO_TEST("kvmclock");
c401cc
+    DO_TEST("clock-timer-hyperv-rtc");
c401cc
 
c401cc
     DO_TEST("cpu-eoi-disabled");
c401cc
     DO_TEST("cpu-eoi-enabled");
c401cc
-- 
c401cc
1.8.5.4
c401cc