Loading include/linux/kvm_host.h +8 −0 Original line number Diff line number Diff line Loading @@ -334,6 +334,8 @@ int kvm_iommu_map_guest(struct kvm *kvm); int kvm_iommu_unmap_guest(struct kvm *kvm); int kvm_assign_device(struct kvm *kvm, struct kvm_assigned_dev_kernel *assigned_dev); int kvm_deassign_device(struct kvm *kvm, struct kvm_assigned_dev_kernel *assigned_dev); #else /* CONFIG_DMAR */ static inline int kvm_iommu_map_pages(struct kvm *kvm, gfn_t base_gfn, Loading @@ -357,6 +359,12 @@ static inline int kvm_assign_device(struct kvm *kvm, { return 0; } static inline int kvm_deassign_device(struct kvm *kvm, struct kvm_assigned_dev_kernel *assigned_dev) { return 0; } #endif /* CONFIG_DMAR */ static inline void kvm_guest_enter(void) Loading virt/kvm/kvm_main.c +42 −0 Original line number Diff line number Diff line Loading @@ -530,6 +530,35 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, } #endif #ifdef KVM_CAP_DEVICE_DEASSIGNMENT static int kvm_vm_ioctl_deassign_device(struct kvm *kvm, struct kvm_assigned_pci_dev *assigned_dev) { int r = 0; struct kvm_assigned_dev_kernel *match; mutex_lock(&kvm->lock); match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head, assigned_dev->assigned_dev_id); if (!match) { printk(KERN_INFO "%s: device hasn't been assigned before, " "so cannot be deassigned\n", __func__); r = -EINVAL; goto out; } if (assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) kvm_deassign_device(kvm, match); kvm_free_assigned_device(kvm, match); out: mutex_unlock(&kvm->lock); return r; } #endif static inline int valid_vcpu(int n) { return likely(n >= 0 && n < KVM_MAX_VCPUS); Loading Loading @@ -1862,6 +1891,19 @@ static long kvm_vm_ioctl(struct file *filp, goto out; break; } #endif #ifdef KVM_CAP_DEVICE_DEASSIGNMENT case KVM_DEASSIGN_PCI_DEVICE: { struct kvm_assigned_pci_dev assigned_dev; r = -EFAULT; if (copy_from_user(&assigned_dev, argp, sizeof assigned_dev)) goto out; r = kvm_vm_ioctl_deassign_device(kvm, &assigned_dev); if (r) goto out; break; } #endif default: r = kvm_arch_vm_ioctl(filp, ioctl, arg); Loading virt/kvm/vtd.c +24 −0 Original line number Diff line number Diff line Loading @@ -116,6 +116,30 @@ int kvm_assign_device(struct kvm *kvm, return 0; } int kvm_deassign_device(struct kvm *kvm, struct kvm_assigned_dev_kernel *assigned_dev) { struct dmar_domain *domain = kvm->arch.intel_iommu_domain; struct pci_dev *pdev = NULL; /* check if iommu exists and in use */ if (!domain) return 0; pdev = assigned_dev->dev; if (pdev == NULL) return -ENODEV; intel_iommu_detach_device(domain, pdev); printk(KERN_DEBUG "deassign device: host bdf = %x:%x:%x\n", assigned_dev->host_busnr, PCI_SLOT(assigned_dev->host_devfn), PCI_FUNC(assigned_dev->host_devfn)); return 0; } int kvm_iommu_map_guest(struct kvm *kvm) { int r; Loading Loading
include/linux/kvm_host.h +8 −0 Original line number Diff line number Diff line Loading @@ -334,6 +334,8 @@ int kvm_iommu_map_guest(struct kvm *kvm); int kvm_iommu_unmap_guest(struct kvm *kvm); int kvm_assign_device(struct kvm *kvm, struct kvm_assigned_dev_kernel *assigned_dev); int kvm_deassign_device(struct kvm *kvm, struct kvm_assigned_dev_kernel *assigned_dev); #else /* CONFIG_DMAR */ static inline int kvm_iommu_map_pages(struct kvm *kvm, gfn_t base_gfn, Loading @@ -357,6 +359,12 @@ static inline int kvm_assign_device(struct kvm *kvm, { return 0; } static inline int kvm_deassign_device(struct kvm *kvm, struct kvm_assigned_dev_kernel *assigned_dev) { return 0; } #endif /* CONFIG_DMAR */ static inline void kvm_guest_enter(void) Loading
virt/kvm/kvm_main.c +42 −0 Original line number Diff line number Diff line Loading @@ -530,6 +530,35 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, } #endif #ifdef KVM_CAP_DEVICE_DEASSIGNMENT static int kvm_vm_ioctl_deassign_device(struct kvm *kvm, struct kvm_assigned_pci_dev *assigned_dev) { int r = 0; struct kvm_assigned_dev_kernel *match; mutex_lock(&kvm->lock); match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head, assigned_dev->assigned_dev_id); if (!match) { printk(KERN_INFO "%s: device hasn't been assigned before, " "so cannot be deassigned\n", __func__); r = -EINVAL; goto out; } if (assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) kvm_deassign_device(kvm, match); kvm_free_assigned_device(kvm, match); out: mutex_unlock(&kvm->lock); return r; } #endif static inline int valid_vcpu(int n) { return likely(n >= 0 && n < KVM_MAX_VCPUS); Loading Loading @@ -1862,6 +1891,19 @@ static long kvm_vm_ioctl(struct file *filp, goto out; break; } #endif #ifdef KVM_CAP_DEVICE_DEASSIGNMENT case KVM_DEASSIGN_PCI_DEVICE: { struct kvm_assigned_pci_dev assigned_dev; r = -EFAULT; if (copy_from_user(&assigned_dev, argp, sizeof assigned_dev)) goto out; r = kvm_vm_ioctl_deassign_device(kvm, &assigned_dev); if (r) goto out; break; } #endif default: r = kvm_arch_vm_ioctl(filp, ioctl, arg); Loading
virt/kvm/vtd.c +24 −0 Original line number Diff line number Diff line Loading @@ -116,6 +116,30 @@ int kvm_assign_device(struct kvm *kvm, return 0; } int kvm_deassign_device(struct kvm *kvm, struct kvm_assigned_dev_kernel *assigned_dev) { struct dmar_domain *domain = kvm->arch.intel_iommu_domain; struct pci_dev *pdev = NULL; /* check if iommu exists and in use */ if (!domain) return 0; pdev = assigned_dev->dev; if (pdev == NULL) return -ENODEV; intel_iommu_detach_device(domain, pdev); printk(KERN_DEBUG "deassign device: host bdf = %x:%x:%x\n", assigned_dev->host_busnr, PCI_SLOT(assigned_dev->host_devfn), PCI_FUNC(assigned_dev->host_devfn)); return 0; } int kvm_iommu_map_guest(struct kvm *kvm) { int r; Loading