From 14d6a1ad2cc3671ad87e0d9e9bd8432c4aa62bd1 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] Partial fix for PCI devices reordering. See https://github.com/QubesOS/qubes-issues/issues/6587 . --- qubes/devices.py | 40 +++++++++++++++++++++++++++++++++++++++- qubes/vm/__init__.py | 2 +- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/qubes/devices.py b/qubes/devices.py index a02eab8b0..df6fd409e 100644 --- a/qubes/devices.py +++ b/qubes/devices.py @@ -55,6 +55,9 @@ `domain-qdb-change:path`) to detect changes and fire `device-list-change:class` event. ''' +from collections import OrderedDict +from typing import Optional + import qubes.utils class DeviceNotAttached(qubes.exc.QubesException, KeyError): @@ -371,6 +374,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) @@ -433,7 +471,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 1a5b9d08a..0383e92d2 100644 --- a/qubes/vm/__init__.py +++ b/qubes/vm/__init__.py @@ -329,7 +329,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)