[Kimchi-devel] [PATCH] Fix passthrough bugs
Jose Ricardo Ziviani
joserz at linux.vnet.ibm.com
Wed Oct 21 12:21:00 UTC 2015
- when the guest is turned off, a multi function pci device must be
attached using mutifunction attribute in the pci address. Otherwise
the pci won't be attached correctly. Libvirt doesn't support
multifunction hotplug, so we don't change anything if the guest is
running.
- after any recent libvirt update, the device dettachment must be
done just before attaching it into the guest because they query
/sys to retrieve some device state.
Signed-off-by: Jose Ricardo Ziviani <joserz at linux.vnet.ibm.com>
---
src/kimchi/model/vmhostdevs.py | 63 +++++++++++++++++++++++++++++++++++++++---
1 file changed, 59 insertions(+), 4 deletions(-)
diff --git a/src/kimchi/model/vmhostdevs.py b/src/kimchi/model/vmhostdevs.py
index 0a263e8..c5ae560 100644
--- a/src/kimchi/model/vmhostdevs.py
+++ b/src/kimchi/model/vmhostdevs.py
@@ -23,6 +23,7 @@ import os
import libvirt
from lxml import etree, objectify
from lxml.builder import E
+from operator import itemgetter
from kimchi.exception import InvalidOperation, InvalidParameter, NotFoundError
from kimchi.exception import OperationFailed
@@ -62,6 +63,9 @@ class VMHostDevsModel(object):
self._passthrough_device_validate(dev_name)
dev_info = DeviceModel(conn=self.conn).lookup(dev_name)
+ if dev_info['device_type'] == 'pci':
+ return self._attach_pci_device(vmid, dev_info)
+
with RollbackContext() as rollback:
try:
dev = self.conn.get().nodeDeviceLookupByName(dev_name)
@@ -79,7 +83,7 @@ class VMHostDevsModel(object):
return info
- def _get_pci_device_xml(self, dev_info):
+ def _get_pci_device_xml(self, dev_info, slot, is_multifunction):
if 'detach_driver' not in dev_info:
dev_info['detach_driver'] = 'kvm'
@@ -88,8 +92,29 @@ class VMHostDevsModel(object):
slot=str(dev_info['slot']),
function=str(dev_info['function'])))
driver = E.driver(name=dev_info['detach_driver'])
- host_dev = E.hostdev(source, driver,
- mode='subsystem', type='pci', managed='yes')
+
+ if is_multifunction:
+ multi = E.address(type='pci',
+ domain='0',
+ bus='0',
+ slot=str(slot),
+ function=str(dev_info['function']))
+
+ if dev_info['function'] == 0:
+ multi = E.address(type='pci',
+ domain='0',
+ bus='0',
+ slot=str(slot),
+ function=str(dev_info['function']),
+ multifunction='on')
+
+
+ host_dev = E.hostdev(source, driver, multi,
+ mode='subsystem', type='pci', managed='yes')
+
+ else:
+ host_dev = E.hostdev(source, driver,
+ mode='subsystem', type='pci', managed='yes')
return etree.tostring(host_dev)
@@ -132,6 +157,27 @@ class VMHostDevsModel(object):
return False
+ def _available_slot(self, dom):
+ xmlstr = dom.XMLDesc(0)
+ root = objectify.fromstring(xmlstr)
+ slots = []
+ try:
+ devices = root.devices
+ slots = [DeviceModel._toint(dev.attrib['slot'])
+ for dev in devices.findall('.//address')
+ if 'slot' in dev.attrib]
+
+ except AttributeError:
+ return 1
+
+ slots = sorted(slots)
+
+ for free, slot in enumerate(slots, start=1):
+ if free < slot:
+ return free
+
+ return free+1
+
def _attach_pci_device(self, vmid, dev_info):
self._validate_pci_passthrough_env()
@@ -163,6 +209,10 @@ class VMHostDevsModel(object):
pci_infos = [dev_model.lookup(dev_name) for dev_name in group_names]
pci_infos.append(dev_info)
+ is_multifunction = len(pci_infos) > 1 and \
+ DOM_STATE_MAP[dom.info()[0]] == "shutoff"
+ pci_infos = sorted(pci_infos, key=itemgetter('name'))
+
# all devices in the group that is going to be attached to the vm
# must be detached from the host first
with RollbackContext() as rollback:
@@ -181,10 +231,15 @@ class VMHostDevsModel(object):
device_flags = get_vm_config_flag(dom, mode='all')
+ slot = 0
+ if is_multifunction:
+ slot = self._available_slot(dom)
with RollbackContext() as rollback:
for pci_info in pci_infos:
pci_info['detach_driver'] = driver
- xmlstr = self._get_pci_device_xml(pci_info)
+ xmlstr = self._get_pci_device_xml(pci_info,
+ slot,
+ is_multifunction)
try:
dom.attachDeviceFlags(xmlstr, device_flags)
except libvirt.libvirtError:
--
1.9.1
More information about the Kimchi-devel
mailing list