int kvm_iommu_map_guest(struct kvm *kvm) { int r; if (!iommu_found()) { printk(KERN_ERR "%s: iommu not found\n", __func__); return -ENODEV; } kvm->arch.iommu_domain = iommu_domain_alloc(); if (!kvm->arch.iommu_domain) return -ENOMEM; if (!allow_unsafe_assigned_interrupts && !iommu_domain_has_cap(kvm->arch.iommu_domain, IOMMU_CAP_INTR_REMAP)) { printk(KERN_WARNING "%s: No interrupt remapping support, disallowing device assignment. Re-enble with \"allow_unsafe_assigned_interrupts=1\" module option.\n", __func__); iommu_domain_free(kvm->arch.iommu_domain); kvm->arch.iommu_domain = NULL; return -EPERM; } r = kvm_iommu_map_memslots(kvm); if (r) goto out_unmap; return 0; out_unmap: kvm_iommu_unmap_memslots(kvm); return r; }
int kvm_assign_device(struct kvm *kvm, struct kvm_assigned_dev_kernel *assigned_dev) { struct pci_dev *pdev = NULL; struct iommu_domain *domain = kvm->arch.iommu_domain; int r, last_flags; /* check if iommu exists and in use */ if (!domain) return 0; pdev = assigned_dev->dev; if (pdev == NULL) return -ENODEV; r = iommu_attach_device(domain, &pdev->dev); if (r) { printk(KERN_ERR "assign device %x:%x:%x.%x failed", pci_domain_nr(pdev->bus), pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); return r; } last_flags = kvm->arch.iommu_flags; if (iommu_domain_has_cap(kvm->arch.iommu_domain, IOMMU_CAP_CACHE_COHERENCY)) kvm->arch.iommu_flags |= KVM_IOMMU_CACHE_COHERENCY; /* Check if need to update IOMMU page table for guest memory */ if ((last_flags ^ kvm->arch.iommu_flags) == KVM_IOMMU_CACHE_COHERENCY) { kvm_iommu_unmap_memslots(kvm); r = kvm_iommu_map_memslots(kvm); if (r) goto out_unmap; } printk(KERN_DEBUG "assign device %x:%x:%x.%x\n", assigned_dev->host_segnr, assigned_dev->host_busnr, PCI_SLOT(assigned_dev->host_devfn), PCI_FUNC(assigned_dev->host_devfn)); return 0; out_unmap: kvm_iommu_unmap_memslots(kvm); return r; }
int kvm_iommu_map_guest(struct kvm *kvm) { int r; if (!iommu_found()) { printk(KERN_ERR "%s: iommu not found\n", __func__); return -ENODEV; } kvm->arch.iommu_domain = iommu_domain_alloc(); if (!kvm->arch.iommu_domain) return -ENOMEM; r = kvm_iommu_map_memslots(kvm); if (r) goto out_unmap; return 0; out_unmap: kvm_iommu_unmap_memslots(kvm); return r; }