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