Skip to content

Commit

Permalink
KVM: support device deassignment
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Weidong Han authored and Joerg Roedel committed Jan 3, 2009
1 parent 260782b commit 0a92035
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
8 changes: 8 additions & 0 deletions include/linux/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)
Expand Down
42 changes: 42 additions & 0 deletions virt/kvm/kvm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
24 changes: 24 additions & 0 deletions virt/kvm/vtd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 0a92035

Please sign in to comment.