[virt-tools-list] [PATCH] [RFC] CPU model capabilities vs domcapabilities

Charles Arnold carnold at suse.com
Fri Mar 23 20:35:21 UTC 2018


The issue is when the host has been updated with microcode for Spectre
but qemu has _not_ been updated. In this scenario (as an example),
'virsh capabilities' shows the host cpu model as IvyBridge-IBRS, which is
correct. However, 'virsh domcapabilities' shows IvyBridge as the host-model
and does not show any of the '-IBRS' flavors available under the custom model,
which is also correct since the qemu does not have Spectre patches.

Be default, virt-manager uses 'custom' for the cpu mode XML. For example,

  <cpu mode="custom" match="exact">
    <model>IvyBridge-IBRS</model>
  </cpu>

Starting an installation in the above scenario will fail because qemu
doesn't understand '-IBRS' but will be okay using the domcapabilities
model which does not contain '-IBRS'.

The patch below pulls the cpu model from domcapabilites instead of
capabilities. Not sure this is the right way to go so please chime in on
how you think this problem could be solved.

Thanks


Signed-off-by: Charles Arnold <carnold at suse.com>

diff --git a/virtinst/domain/cpu.py b/virtinst/domain/cpu.py
index 3c1089c..b3607ea 100644
--- a/virtinst/domain/cpu.py
+++ b/virtinst/domain/cpu.py
@@ -6,6 +6,7 @@
 # See the COPYING file in the top-level directory.
 
 from ..xmlbuilder import XMLBuilder, XMLProperty, XMLChildProperty
+from .domcapabilities import DomainCapabilities
 
 
 class _CPUCellSibling(XMLBuilder):
@@ -79,7 +80,7 @@ class DomainCpu(XMLBuilder):
     SPECIAL_MODES = [SPECIAL_MODE_HOST_MODEL_ONLY, SPECIAL_MODE_HV_DEFAULT,
                      SPECIAL_MODE_HOST_COPY, SPECIAL_MODE_HOST_MODEL,
                      SPECIAL_MODE_HOST_PASSTHROUGH, SPECIAL_MODE_CLEAR]
-    def set_special_mode(self, val):
+    def set_special_mode(self, val, guest=None):
         if (val == self.SPECIAL_MODE_HOST_MODEL or
             val == self.SPECIAL_MODE_HOST_PASSTHROUGH):
             self.model = None
@@ -94,7 +95,16 @@ class DomainCpu(XMLBuilder):
               val == self.SPECIAL_MODE_CLEAR):
             self.clear()
         elif val == self.SPECIAL_MODE_HOST_MODEL_ONLY:
-            if self.conn.caps.host.cpu.model:
+            domcaps_model = None
+            if guest:
+                domcaps = DomainCapabilities.build_from_guest(guest)
+                model = domcaps.cpu.get_mode("host-model").get_models()
+                if len(model):
+                    domcaps_model = model[0]
+            if domcaps_model:
+                self.clear()
+                self.model = domcaps_model
+            elif self.conn.caps.host.cpu.model:
                 self.clear()
                 self.model = self.conn.caps.host.cpu.model
         else:
diff --git a/virtinst/domcapabilities.py b/virtinst/domcapabilities.py
index f98c807..cae1fb2 100644
--- a/virtinst/domcapabilities.py
+++ b/virtinst/domcapabilities.py
@@ -29,9 +29,27 @@ class _Enum(_HasValues):
     name = XMLProperty("./@name")
 
 
+class _Model(XMLBuilder):
+    _XML_ROOT_NAME = "model"
+    model = XMLProperty(".")
+
+
+class _HasModels(XMLBuilder):
+    models = XMLChildProperty(_Model)
+
+    def get_models(self):
+        return [v.model for v in self.models]
+
+
+class _CPUMode(_HasModels):
+    _XML_ROOT_NAME = "mode"
+    name = XMLProperty("./@name")
+
+
 class _CapsBlock(_HasValues):
     supported = XMLProperty("./@supported", is_yesno=True)
     enums = XMLChildProperty(_Enum)
+    modes = XMLChildProperty(_CPUMode)
 
     def enum_names(self):
         return [e.name for e in self.enums]
@@ -40,6 +58,12 @@ class _CapsBlock(_HasValues):
         d = dict((e.name, e) for e in self.enums)
         return d[name]
 
+    def mode_names(self):
+        return [m.name for m in self.modes]
+
+    def get_mode(self, name):
+        d = dict((m.name, m) for m in self.modes)
+        return d[name]
 
 def _make_capsblock(xml_root_name):
     class TmpClass(_CapsBlock):
@@ -53,6 +77,11 @@ class _OS(_CapsBlock):
     loader = XMLChildProperty(_make_capsblock("loader"), is_single=True)
 
 
+class _CPU(_CapsBlock):
+    _XML_ROOT_NAME = "cpu"
+    mode = XMLChildProperty(_make_capsblock("mode"), is_single=True)
+
+
 class _Devices(_CapsBlock):
     XML_NAME = "devices"
     hostdev = XMLChildProperty(_make_capsblock("hostdev"), is_single=True)
@@ -151,6 +180,7 @@ class DomainCapabilities(XMLBuilder):
 
     XML_NAME = "domainCapabilities"
     os = XMLChildProperty(_OS, is_single=True)
+    cpu = XMLChildProperty(_CPU, is_single=True)
     devices = XMLChildProperty(_Devices, is_single=True)
 
     arch = XMLProperty("./arch")
diff --git a/virtinst/guest.py b/virtinst/guest.py
index 5e7d807..35d162c 100644
--- a/virtinst/guest.py
+++ b/virtinst/guest.py
@@ -868,7 +868,7 @@ class Guest(XMLBuilder):
             if self.os.arch != self.conn.caps.host.cpu.arch:
                 return
 
-            self.cpu.set_special_mode(self.x86_cpu_default)
+            self.cpu.set_special_mode(self.x86_cpu_default, self)
             if self._os_object.broken_x2apic():
                 self.cpu.add_feature("x2apic", policy="disable")
 




More information about the virt-tools-list mailing list