KVM: support device deassignment
Support device deassignment, it can be used in device hotplug. Signed-off-by: Weidong Han <weidong.han@intel.com> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
This commit is contained in:
Родитель
260782bcfd
Коммит
0a92035674
|
@ -334,6 +334,8 @@ int kvm_iommu_map_guest(struct kvm *kvm);
|
||||||
int kvm_iommu_unmap_guest(struct kvm *kvm);
|
int kvm_iommu_unmap_guest(struct kvm *kvm);
|
||||||
int kvm_assign_device(struct kvm *kvm,
|
int kvm_assign_device(struct kvm *kvm,
|
||||||
struct kvm_assigned_dev_kernel *assigned_dev);
|
struct kvm_assigned_dev_kernel *assigned_dev);
|
||||||
|
int kvm_deassign_device(struct kvm *kvm,
|
||||||
|
struct kvm_assigned_dev_kernel *assigned_dev);
|
||||||
#else /* CONFIG_DMAR */
|
#else /* CONFIG_DMAR */
|
||||||
static inline int kvm_iommu_map_pages(struct kvm *kvm,
|
static inline int kvm_iommu_map_pages(struct kvm *kvm,
|
||||||
gfn_t base_gfn,
|
gfn_t base_gfn,
|
||||||
|
@ -357,6 +359,12 @@ static inline int kvm_assign_device(struct kvm *kvm,
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int kvm_deassign_device(struct kvm *kvm,
|
||||||
|
struct kvm_assigned_dev_kernel *assigned_dev)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif /* CONFIG_DMAR */
|
#endif /* CONFIG_DMAR */
|
||||||
|
|
||||||
static inline void kvm_guest_enter(void)
|
static inline void kvm_guest_enter(void)
|
||||||
|
|
|
@ -530,6 +530,35 @@ out_free:
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
static inline int valid_vcpu(int n)
|
||||||
{
|
{
|
||||||
return likely(n >= 0 && n < KVM_MAX_VCPUS);
|
return likely(n >= 0 && n < KVM_MAX_VCPUS);
|
||||||
|
@ -1862,6 +1891,19 @@ static long kvm_vm_ioctl(struct file *filp,
|
||||||
goto out;
|
goto out;
|
||||||
break;
|
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
|
#endif
|
||||||
default:
|
default:
|
||||||
r = kvm_arch_vm_ioctl(filp, ioctl, arg);
|
r = kvm_arch_vm_ioctl(filp, ioctl, arg);
|
||||||
|
|
|
@ -116,6 +116,30 @@ int kvm_assign_device(struct kvm *kvm,
|
||||||
return 0;
|
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 kvm_iommu_map_guest(struct kvm *kvm)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче