From 361550c621762e1c89defe45d575b49bb520e7ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Tue, 29 Oct 2019 03:13:49 +0100 Subject: [PATCH] vm: improve error message about missing IOMMU Handle this case specifically, as way too many users ignore the message during installation and complain it doesn't work later. Name the problem explicitly, instead of pointing at libvirt error log. Fixes QubesOS/qubes-issues#4689 --- qubes/app.py | 10 ++++++++++ qubes/vm/qubesvm.py | 13 +++++++++++++ 2 files changed, 23 insertions(+) diff --git a/qubes/app.py b/qubes/app.py index 016a3cd9..8b7c9398 100644 --- a/qubes/app.py +++ b/qubes/app.py @@ -314,6 +314,16 @@ class QubesHost: raise NotImplementedError('This function requires Xen hypervisor') return int(self._physinfo['free_memory']) + def is_iommu_supported(self): + """Check if IOMMU is supported on this platform""" + if self._physinfo is None: + try: + self._physinfo = self.app.vmm.xc.physinfo() + except AttributeError: + raise NotImplementedError( + 'This function requires Xen hypervisor') + return 'hvm_directio' in self._physinfo['virt_caps'] + def get_vm_stats(self, previous_time=None, previous=None, only_vm=None): """Measure cpu usage for all domains at once. diff --git a/qubes/vm/qubesvm.py b/qubes/vm/qubesvm.py index 2aea4330..9df7190f 100644 --- a/qubes/vm/qubesvm.py +++ b/qubes/vm/qubesvm.py @@ -1115,6 +1115,19 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM): self.libvirt_domain.createWithFlags( libvirt.VIR_DOMAIN_START_PAUSED) + except libvirt.libvirtError as exc: + # missing IOMMU? + if self.virt_mode == 'hvm' and \ + list(self.devices['pci'].persistent()) and \ + not self.app.host.is_iommu_supported(): + exc = qubes.exc.QubesException( + 'Failed to start an HVM qube with PCI devices assigned ' + '- hardware does not support IOMMU/VT-d/AMD-Vi') + self.log.error('Start failed: %s', str(exc)) + yield from self.fire_event_async('domain-start-failed', + reason=str(exc)) + yield from self.storage.stop() + raise exc except Exception as exc: self.log.error('Start failed: %s', str(exc)) # let anyone receiving domain-pre-start know that startup failed