]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
Add new 'kvm' domain feature and ability to hide KVM signature
authorAlex Williamson <alex.williamson@redhat.com>
Thu, 21 Aug 2014 17:04:45 +0000 (11:04 -0600)
committerJán Tomko <jtomko@redhat.com>
Tue, 26 Aug 2014 08:41:24 +0000 (10:41 +0200)
QEMU 2.1 added support for the kvm=off option to the -cpu command,
allowing the KVM hypervisor signature to be hidden from the guest.
This enables disabling of some paravirualization features in the
guest as well as allowing certain drivers which test for the
hypervisor to load.  Domain XML syntax is as follows:

<domain type='kvm>
  ...
  <features>
    ...
    <kvm>
      <hidden state='on'/>
    </kvm>
  </features>
  ...

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
12 files changed:
docs/formatdomain.html.in
docs/schemas/domaincommon.rng
src/conf/domain_conf.c
src/conf/domain_conf.h
src/qemu/qemu_command.c
tests/qemuargv2xmltest.c
tests/qemuxml2argvdata/qemuxml2argv-kvm-features-off.args [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-kvm-features-off.xml [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-kvm-features.args [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-kvm-features.xml [new file with mode: 0644]
tests/qemuxml2argvtest.c
tests/qemuxml2xmltest.c

index 59127bb0856baca9936a1831be932061e962e24d..de4e4ebfb6ba9378fe6a95cbfa5666d9c3e4a6a0 100644 (file)
       &lt;vapic state='on'/&gt;
       &lt;spinlocks state='on' retries='4096'/&gt;
     &lt;/hyperv&gt;
+    &lt;kvm&gt;
+      &lt;hidden state='on'/&gt;
+    &lt;/kvm&gt;
     &lt;pvspinlock/&gt;
 
   &lt;/features&gt;
           can be explicitly disabled by using <code>state='off'</code>
           attribute.
       </dd>
-
+      <dt><code>kvm</code></dt>
+      <dd>Various features to change the behavior of the KVM hypervisor.
+      <table class="top_table">
+        <tr>
+          <th>Feature</th>
+          <th>Description</th>
+          <th>Value</th>
+          <th>Since</th>
+        </tr>
+        <tr>
+          <td>hidden</td>
+          <td>Hide the KVM hypervisor from standard MSR based discovery</td>
+          <td>on, off</td>
+          <td><span class="since">2.1.0 (QEMU only)</span></td>
+        </tr>
+      </table>
+      </dd>
     </dl>
 
     <h3><a name="elementsTime">Time keeping</a></h3>
index 9a89dd80fb2278d266ca9bef1eb3e76531a2a71f..3170db25c38397b3aa908dc7c0717a6064e60cbd 100644 (file)
   </define>
   <!--
       A set of optional features: PAE, APIC, ACPI,
-      HyperV Enlightenment, paravirtual spinlocks  and HAP support
+      HyperV Enlightenment, KVM features, paravirtual spinlocks and HAP support
     -->
   <define name="features">
     <optional>
               <empty/>
             </element>
           </optional>
+          <optional>
+            <ref name="kvm"/>
+          </optional>
           <optional>
             <element name="privnet">
               <empty/>
     </element>
   </define>
 
+  <!-- Optional KVM features -->
+  <define name="kvm">
+    <element name="kvm">
+      <interleave>
+        <optional>
+          <element name="hidden">
+            <ref name="featurestate"/>
+          </element>
+        </optional>
+      </interleave>
+    </element>
+  </define>
+
   <!-- Optional capabilities features -->
   <define name="capabilities">
     <element name="capabilities">
index 22a7f7eac0bbc44d1fcfdd5c563714925d50c3a3..dd512cafbff5c7e073b961e83b1484def872ab32 100644 (file)
@@ -142,6 +142,7 @@ VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST,
               "viridian",
               "privnet",
               "hyperv",
+              "kvm",
               "pvspinlock",
               "capabilities")
 
@@ -155,6 +156,9 @@ VIR_ENUM_IMPL(virDomainHyperv, VIR_DOMAIN_HYPERV_LAST,
               "vapic",
               "spinlocks")
 
+VIR_ENUM_IMPL(virDomainKVM, VIR_DOMAIN_KVM_LAST,
+              "hidden")
+
 VIR_ENUM_IMPL(virDomainCapsFeature, VIR_DOMAIN_CAPS_FEATURE_LAST,
               "audit_control",
               "audit_write",
@@ -12203,6 +12207,7 @@ virDomainDefParseXML(xmlDocPtr xml,
         case VIR_DOMAIN_FEATURE_VIRIDIAN:
         case VIR_DOMAIN_FEATURE_PRIVNET:
         case VIR_DOMAIN_FEATURE_HYPERV:
+        case VIR_DOMAIN_FEATURE_KVM:
             def->features[val] = VIR_TRISTATE_SWITCH_ON;
             break;
 
@@ -12330,6 +12335,54 @@ virDomainDefParseXML(xmlDocPtr xml,
         ctxt->node = node;
     }
 
+    if (def->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON) {
+        int feature;
+        int value;
+        node = ctxt->node;
+        if ((n = virXPathNodeSet("./features/kvm/*", ctxt, &nodes)) < 0)
+            goto error;
+
+        for (i = 0; i < n; i++) {
+            feature = virDomainKVMTypeFromString((const char *)nodes[i]->name);
+            if (feature < 0) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("unsupported KVM feature: %s"),
+                               nodes[i]->name);
+                goto error;
+            }
+
+            ctxt->node = nodes[i];
+
+            switch ((virDomainKVM) feature) {
+                case VIR_DOMAIN_KVM_HIDDEN:
+                    if (!(tmp = virXPathString("string(./@state)", ctxt))) {
+                        virReportError(VIR_ERR_XML_ERROR,
+                                       _("missing 'state' attribute for "
+                                         "KVM feature '%s'"),
+                                       nodes[i]->name);
+                        goto error;
+                    }
+
+                    if ((value = virTristateSwitchTypeFromString(tmp)) < 0) {
+                        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                                       _("invalid value of state argument "
+                                         "for KVM feature '%s'"),
+                                       nodes[i]->name);
+                        goto error;
+                    }
+
+                    VIR_FREE(tmp);
+                    def->kvm_features[feature] = value;
+                    break;
+
+                case VIR_DOMAIN_KVM_LAST:
+                    break;
+            }
+        }
+        VIR_FREE(nodes);
+        ctxt->node = node;
+    }
+
     if ((n = virXPathNodeSet("./features/capabilities/*", ctxt, &nodes)) < 0)
         goto error;
 
@@ -14338,6 +14391,29 @@ virDomainDefFeaturesCheckABIStability(virDomainDefPtr src,
         }
     }
 
+    /* kvm */
+    if (src->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON) {
+        for (i = 0; i < VIR_DOMAIN_KVM_LAST; i++) {
+            switch ((virDomainKVM) i) {
+            case VIR_DOMAIN_KVM_HIDDEN:
+                if (src->kvm_features[i] != dst->kvm_features[i]) {
+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                                   _("State of KVM feature '%s' differs: "
+                                     "source: '%s', destination: '%s'"),
+                                   virDomainKVMTypeToString(i),
+                                   virTristateSwitchTypeToString(src->kvm_features[i]),
+                                   virTristateSwitchTypeToString(dst->kvm_features[i]));
+                    return false;
+                }
+
+                break;
+
+            case VIR_DOMAIN_KVM_LAST:
+                break;
+            }
+        }
+    }
+
     return true;
 }
 
@@ -18172,6 +18248,30 @@ virDomainDefFormatInternal(virDomainDefPtr def,
                 virBufferAddLit(buf, "</hyperv>\n");
                 break;
 
+            case VIR_DOMAIN_FEATURE_KVM:
+                if (def->features[i] != VIR_TRISTATE_SWITCH_ON)
+                    break;
+
+                virBufferAddLit(buf, "<kvm>\n");
+                virBufferAdjustIndent(buf, 2);
+                for (j = 0; j < VIR_DOMAIN_KVM_LAST; j++) {
+                    switch ((virDomainKVM) j) {
+                    case VIR_DOMAIN_KVM_HIDDEN:
+                        if (def->kvm_features[j])
+                            virBufferAsprintf(buf, "<%s state='%s'/>\n",
+                                              virDomainKVMTypeToString(j),
+                                              virTristateSwitchTypeToString(
+                                                  def->kvm_features[j]));
+                        break;
+
+                    case VIR_DOMAIN_KVM_LAST:
+                        break;
+                    }
+                }
+                virBufferAdjustIndent(buf, -2);
+                virBufferAddLit(buf, "</kvm>\n");
+                break;
+
             case VIR_DOMAIN_FEATURE_CAPABILITIES:
                 if (def->features[i] == VIR_DOMAIN_CAPABILITIES_POLICY_DEFAULT &&
                         !virDomainDefHasCapabilitiesFeatures(def))
index 36ccf106e07a116571f6a6c8dc4894d90bfe7ac5..aead903095b8e165fee78a6c1e4a0c4b80b6a3aa 100644 (file)
@@ -1515,6 +1515,7 @@ typedef enum {
     VIR_DOMAIN_FEATURE_VIRIDIAN,
     VIR_DOMAIN_FEATURE_PRIVNET,
     VIR_DOMAIN_FEATURE_HYPERV,
+    VIR_DOMAIN_FEATURE_KVM,
     VIR_DOMAIN_FEATURE_PVSPINLOCK,
     VIR_DOMAIN_FEATURE_CAPABILITIES,
 
@@ -1529,6 +1530,12 @@ typedef enum {
     VIR_DOMAIN_HYPERV_LAST
 } virDomainHyperv;
 
+typedef enum {
+    VIR_DOMAIN_KVM_HIDDEN = 0,
+
+    VIR_DOMAIN_KVM_LAST
+} virDomainKVM;
+
 typedef enum {
     VIR_DOMAIN_CAPABILITIES_POLICY_DEFAULT = 0,
     VIR_DOMAIN_CAPABILITIES_POLICY_ALLOW,
@@ -1945,6 +1952,7 @@ struct _virDomainDef {
     int features[VIR_DOMAIN_FEATURE_LAST];
     int apic_eoi;
     int hyperv_features[VIR_DOMAIN_HYPERV_LAST];
+    int kvm_features[VIR_DOMAIN_KVM_LAST];
     unsigned int hyperv_spinlocks;
 
     /* These options are of type virTristateSwitch: ON = keep, OFF = drop */
@@ -2628,6 +2636,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceStreamingMode)
 VIR_ENUM_DECL(virDomainGraphicsSpiceMouseMode)
 VIR_ENUM_DECL(virDomainGraphicsVNCSharePolicy)
 VIR_ENUM_DECL(virDomainHyperv)
+VIR_ENUM_DECL(virDomainKVM)
 VIR_ENUM_DECL(virDomainRNGModel)
 VIR_ENUM_DECL(virDomainRNGBackend)
 VIR_ENUM_DECL(virDomainTPMModel)
index 6dac9d3045733d81adc910189a4800b63396d388..35ff8f2f03c40ec4209fed2ec2e440a0783bc99e 100644 (file)
@@ -6230,6 +6230,25 @@ qemuBuildCpuArgStr(virQEMUDriverPtr driver,
         }
     }
 
+    if (def->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON) {
+        if (!have_cpu) {
+            virBufferAdd(&buf, default_model, -1);
+            have_cpu = true;
+        }
+
+        for (i = 0; i < VIR_DOMAIN_KVM_LAST; i++) {
+            switch ((virDomainKVM) i) {
+            case VIR_DOMAIN_KVM_HIDDEN:
+                if (def->kvm_features[i] == VIR_TRISTATE_SWITCH_ON)
+                    virBufferAddLit(&buf, ",kvm=off");
+                break;
+
+            case VIR_DOMAIN_KVM_LAST:
+                break;
+            }
+        }
+    }
+
     if (virBufferCheckError(&buf) < 0)
         goto cleanup;
 
@@ -10712,6 +10731,9 @@ qemuParseCommandLineCPU(virDomainDefPtr dom,
             }
             virStringFreeList(hv_tokens);
             hv_tokens = NULL;
+        } else if (STREQ(tokens[i], "kvm=off")) {
+             dom->features[VIR_DOMAIN_FEATURE_KVM] = VIR_TRISTATE_SWITCH_ON;
+             dom->kvm_features[VIR_DOMAIN_KVM_HIDDEN] = VIR_TRISTATE_SWITCH_ON;
         }
     }
 
index 6bad7d6d19df0d979369c7de18860c8ceda64d0e..9c00cd94db3eb78ecb69d3329d087e4a6f562cb0 100644 (file)
@@ -284,6 +284,8 @@ mymain(void)
 
     DO_TEST("hyperv");
 
+    DO_TEST("kvm-features");
+
     DO_TEST("pseries-nvram");
     DO_TEST("pseries-disk");
 
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-kvm-features-off.args b/tests/qemuxml2argvdata/qemuxml2argv-kvm-features-off.args
new file mode 100644 (file)
index 0000000..363fd2a
--- /dev/null
@@ -0,0 +1,5 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/bin/qemu \
+-S -M pc -cpu qemu32 -m 214 -smp 6 -nographic \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-boot n -usb -net none -serial none -parallel none
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-kvm-features-off.xml b/tests/qemuxml2argvdata/qemuxml2argv-kvm-features-off.xml
new file mode 100644 (file)
index 0000000..64b8cd8
--- /dev/null
@@ -0,0 +1,27 @@
+<domain type='qemu'>
+  <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>
+    <acpi/>
+    <kvm>
+      <hidden state='off'/>
+    </kvm>
+  </features>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-kvm-features.args b/tests/qemuxml2argvdata/qemuxml2argv-kvm-features.args
new file mode 100644 (file)
index 0000000..b223951
--- /dev/null
@@ -0,0 +1,5 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/bin/qemu -S -M pc \
+-cpu qemu32,kvm=off -m 214 -smp 6 -nographic -monitor \
+unix:/tmp/test-monitor,server,nowait -boot n -usb -net none -serial none \
+-parallel none
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-kvm-features.xml b/tests/qemuxml2argvdata/qemuxml2argv-kvm-features.xml
new file mode 100644 (file)
index 0000000..3f2817e
--- /dev/null
@@ -0,0 +1,27 @@
+<domain type='qemu'>
+  <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>
+    <acpi/>
+    <kvm>
+      <hidden state='on'/>
+    </kvm>
+  </features>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
index 74072723d345f945fa6a40b2772309854a671f99..1a8201aaf3c885f2c9b6796acb072e4283ca5a16 100644 (file)
@@ -672,6 +672,9 @@ mymain(void)
     DO_TEST("hyperv", NONE);
     DO_TEST("hyperv-off", NONE);
 
+    DO_TEST("kvm-features", NONE);
+    DO_TEST("kvm-features-off", NONE);
+
     DO_TEST("hugepages", QEMU_CAPS_MEM_PATH);
     DO_TEST("hugepages-pages", QEMU_CAPS_MEM_PATH, QEMU_CAPS_OBJECT_MEMORY_RAM,
             QEMU_CAPS_OBJECT_MEMORY_FILE);
index 79cf59fc2be4827eb40af0213acc362ab920329c..b2d2eed344f4f8dd2beef251836a33213af0cefd 100644 (file)
@@ -198,6 +198,9 @@ mymain(void)
     DO_TEST("hyperv");
     DO_TEST("hyperv-off");
 
+    DO_TEST("kvm-features");
+    DO_TEST("kvm-features-off");
+
     DO_TEST("hugepages");
     DO_TEST("hugepages-pages");
     DO_TEST("hugepages-pages2");