From 7df7f5f131608fa93ccc9775cecb6d5b2d2758e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20=C5=A0est=C3=A1k?= Date: Tue, 18 May 2021 10:38:55 +0200 Subject: [PATCH 1/3] Partial fix for PCI devices reordering. See https://github.com/QubesOS/qubes-issues/issues/6587 . --- qubes/devices.py | 39 ++++++++++++++++++++++++++++++++++++++- qubes/vm/__init__.py | 2 +- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/qubes/devices.py b/qubes/devices.py index f41c8597a..1650f504c 100644 --- a/qubes/devices.py +++ b/qubes/devices.py @@ -56,6 +56,8 @@ `device-list-change:class` event. ''' import asyncio +from collections import OrderedDict +from typing import Optional import qubes.utils @@ -375,6 +377,41 @@ def assignments(self, persistent=None): result.update(self._set) return result + def assignments_list(self, persistent: Optional[bool]=None): + '''List assignments for devices which are (or may be) attached to the + vm. + + Devices may be attached persistently (so they are included in + :file:`qubes.xml`) or not. Device can also be in :file:`qubes.xml`, + but be temporarily detached. + + :param Optional[bool] persistent: only include devices which are or are not + attached persistently. + ''' + + try: + devices = self._vm.fire_event('device-list-attached:' + self._bus, + persistent=persistent) + except Exception: # pylint: disable=broad-except + self._vm.log.exception('Failed to list {} devices'.format( + self._bus)) + if persistent is True: + # don't break app.save() + return list(self._set) + raise + result = [] + if persistent is not False: # None or True + result.extend(self._set) + if not persistent: # None or False + for dev, options in devices: + if dev not in self._set: + result.append( + DeviceAssignment( + backend_domain=dev.backend_domain, + ident=dev.ident, options=options, + bus=self._bus)) + return result + def available(self): '''List devices exposed by this vm''' devices = self._vm.fire_event('device-list:' + self._bus) @@ -437,7 +474,7 @@ class PersistentCollection: ''' def __init__(self): - self._dict = {} + self._dict = OrderedDict() def add(self, assignment: DeviceAssignment): ''' Add assignment to collection ''' diff --git a/qubes/vm/__init__.py b/qubes/vm/__init__.py index 31e35b7a7..ee1ce036f 100644 --- a/qubes/vm/__init__.py +++ b/qubes/vm/__init__.py @@ -323,7 +323,7 @@ def __xml__(self): for devclass in self.devices: devices = lxml.etree.Element('devices') devices.set('class', devclass) - for device in self.devices[devclass].assignments(persistent=True): + for device in self.devices[devclass].assignments_list(persistent=True): node = lxml.etree.Element('device') node.set('backend-domain', device.backend_domain.name) node.set('id', device.ident) From 4fc7fa649f3985e9f5e47560fc625a2c0c8fbf82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20=C5=A0est=C3=A1k?= Date: Tue, 18 May 2021 16:25:48 +0200 Subject: [PATCH 2/3] Attempt to fix the rest of PCI device reordering --- qubes/devices.py | 40 ---------------------------------------- qubes/vm/__init__.py | 2 +- 2 files changed, 1 insertion(+), 41 deletions(-) diff --git a/qubes/devices.py b/qubes/devices.py index 1650f504c..4093bb621 100644 --- a/qubes/devices.py +++ b/qubes/devices.py @@ -345,46 +345,6 @@ def assignments(self, persistent=None): :file:`qubes.xml`) or not. Device can also be in :file:`qubes.xml`, but be temporarily detached. - :param bool persistent: only include devices which are or are not - attached persistently. - ''' - - try: - devices = self._vm.fire_event('device-list-attached:' + self._bus, - persistent=persistent) - except Exception: # pylint: disable=broad-except - self._vm.log.exception('Failed to list {} devices'.format( - self._bus)) - if persistent is True: - # don't break app.save() - return self._set - raise - result = set() - for dev, options in devices: - if dev in self._set and not persistent: - continue - if dev in self._set: - result.add(self._set.get(dev)) - elif dev not in self._set and persistent: - continue - else: - result.add( - DeviceAssignment( - backend_domain=dev.backend_domain, - ident=dev.ident, options=options, - bus=self._bus)) - if persistent is not False: - result.update(self._set) - return result - - def assignments_list(self, persistent: Optional[bool]=None): - '''List assignments for devices which are (or may be) attached to the - vm. - - Devices may be attached persistently (so they are included in - :file:`qubes.xml`) or not. Device can also be in :file:`qubes.xml`, - but be temporarily detached. - :param Optional[bool] persistent: only include devices which are or are not attached persistently. ''' diff --git a/qubes/vm/__init__.py b/qubes/vm/__init__.py index ee1ce036f..31e35b7a7 100644 --- a/qubes/vm/__init__.py +++ b/qubes/vm/__init__.py @@ -323,7 +323,7 @@ def __xml__(self): for devclass in self.devices: devices = lxml.etree.Element('devices') devices.set('class', devclass) - for device in self.devices[devclass].assignments_list(persistent=True): + for device in self.devices[devclass].assignments(persistent=True): node = lxml.etree.Element('device') node.set('backend-domain', device.backend_domain.name) node.set('id', device.ident) From c7512e9db0362faa5a8a03e5ea35ff853418d765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20=C5=A0est=C3=A1k?= Date: Tue, 18 May 2021 16:28:00 +0200 Subject: [PATCH 3/3] Fix formatting --- qubes/devices.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qubes/devices.py b/qubes/devices.py index 4093bb621..24bb1f702 100644 --- a/qubes/devices.py +++ b/qubes/devices.py @@ -345,8 +345,8 @@ def assignments(self, persistent=None): :file:`qubes.xml`) or not. Device can also be in :file:`qubes.xml`, but be temporarily detached. - :param Optional[bool] persistent: only include devices which are or are not - attached persistently. + :param Optional[bool] persistent: only include devices which are or are + not attached persistently. ''' try: