Author: jhb
Date: Mon Dec 14 20:48:59 2020
New Revision: 368642
URL: https://svnweb.freebsd.org/changeset/base/368642

Log:
  MFC 368004: Pull the check for VM ownership into ppt_find().
  
  This reduces some code duplication.  One behavior change is that
  ppt_assign_device() will now only succeed if the device is unowned.
  Previously, a device could be assigned to the same VM multiple times,
  but each time it was assigned, the device's state was reset.

Modified:
  stable/12/sys/amd64/vmm/io/ppt.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/amd64/vmm/io/ppt.c
==============================================================================
--- stable/12/sys/amd64/vmm/io/ppt.c    Mon Dec 14 20:40:21 2020        
(r368641)
+++ stable/12/sys/amd64/vmm/io/ppt.c    Mon Dec 14 20:48:59 2020        
(r368642)
@@ -198,8 +198,8 @@ static devclass_t ppt_devclass;
 DEFINE_CLASS_0(ppt, ppt_driver, ppt_methods, sizeof(struct pptdev));
 DRIVER_MODULE(ppt, pci, ppt_driver, ppt_devclass, NULL, NULL);
 
-static struct pptdev *
-ppt_find(int bus, int slot, int func)
+static int
+ppt_find(struct vm *vm, int bus, int slot, int func, struct pptdev **pptp)
 {
        device_t dev;
        struct pptdev *ppt;
@@ -211,9 +211,15 @@ ppt_find(int bus, int slot, int func)
                s = pci_get_slot(dev);
                f = pci_get_function(dev);
                if (bus == b && slot == s && func == f)
-                       return (ppt);
+                       break;
        }
-       return (NULL);
+
+       if (ppt == NULL)
+               return (ENOENT);
+       if (ppt->vm != vm)              /* Make sure we own this device */
+               return (EBUSY);
+       *pptp = ppt;
+       return (0);
 }
 
 static void
@@ -377,50 +383,40 @@ int
 ppt_assign_device(struct vm *vm, int bus, int slot, int func)
 {
        struct pptdev *ppt;
+       int error;
 
-       ppt = ppt_find(bus, slot, func);
-       if (ppt != NULL) {
-               /*
-                * If this device is owned by a different VM then we
-                * cannot change its owner.
-                */
-               if (ppt->vm != NULL && ppt->vm != vm)
-                       return (EBUSY);
+       /* Passing NULL requires the device to be unowned. */
+       error = ppt_find(NULL, bus, slot, func, &ppt);
+       if (error)
+               return (error);
 
-               pci_save_state(ppt->dev);
-               ppt_pci_reset(ppt->dev);
-               pci_restore_state(ppt->dev);
-               ppt->vm = vm;
-               iommu_add_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev));
-               return (0);
-       }
-       return (ENOENT);
+       pci_save_state(ppt->dev);
+       ppt_pci_reset(ppt->dev);
+       pci_restore_state(ppt->dev);
+       ppt->vm = vm;
+       iommu_add_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev));
+       return (0);
 }
 
 int
 ppt_unassign_device(struct vm *vm, int bus, int slot, int func)
 {
        struct pptdev *ppt;
+       int error;
 
-       ppt = ppt_find(bus, slot, func);
-       if (ppt != NULL) {
-               /*
-                * If this device is not owned by this 'vm' then bail out.
-                */
-               if (ppt->vm != vm)
-                       return (EBUSY);
+       error = ppt_find(vm, bus, slot, func, &ppt);
+       if (error)
+               return (error);
 
-               pci_save_state(ppt->dev);
-               ppt_pci_reset(ppt->dev);
-               pci_restore_state(ppt->dev);
-               ppt_unmap_mmio(vm, ppt);
-               ppt_teardown_msi(ppt);
-               ppt_teardown_msix(ppt);
-               iommu_remove_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev));
-               ppt->vm = NULL;
-               return (0);
-       }
-       return (ENOENT);
+       pci_save_state(ppt->dev);
+       ppt_pci_reset(ppt->dev);
+       pci_restore_state(ppt->dev);
+       ppt_unmap_mmio(vm, ppt);
+       ppt_teardown_msi(ppt);
+       ppt_teardown_msix(ppt);
+       iommu_remove_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev));
+       ppt->vm = NULL;
+       return (0);
 }
 
 int
@@ -451,25 +447,22 @@ ppt_map_mmio(struct vm *vm, int bus, int slot, int fun
        struct pptseg *seg;
        struct pptdev *ppt;
 
-       ppt = ppt_find(bus, slot, func);
-       if (ppt != NULL) {
-               if (ppt->vm != vm)
-                       return (EBUSY);
+       error = ppt_find(vm, bus, slot, func, &ppt);
+       if (error)
+               return (error);
 
-               for (i = 0; i < MAX_MMIOSEGS; i++) {
-                       seg = &ppt->mmio[i];
-                       if (seg->len == 0) {
-                               error = vm_map_mmio(vm, gpa, len, hpa);
-                               if (error == 0) {
-                                       seg->gpa = gpa;
-                                       seg->len = len;
-                               }
-                               return (error);
+       for (i = 0; i < MAX_MMIOSEGS; i++) {
+               seg = &ppt->mmio[i];
+               if (seg->len == 0) {
+                       error = vm_map_mmio(vm, gpa, len, hpa);
+                       if (error == 0) {
+                               seg->gpa = gpa;
+                               seg->len = len;
                        }
+                       return (error);
                }
-               return (ENOSPC);
        }
-       return (ENOENT);
+       return (ENOSPC);
 }
 
 static int
@@ -511,11 +504,9 @@ ppt_setup_msi(struct vm *vm, int vcpu, int bus, int sl
        if (numvec < 0 || numvec > MAX_MSIMSGS)
                return (EINVAL);
 
-       ppt = ppt_find(bus, slot, func);
-       if (ppt == NULL)
-               return (ENOENT);
-       if (ppt->vm != vm)              /* Make sure we own this device */
-               return (EBUSY);
+       error = ppt_find(vm, bus, slot, func, &ppt);
+       if (error)
+               return (error);
 
        /* Reject attempts to enable MSI while MSI-X is active. */
        if (ppt->msix.num_msgs != 0 && numvec != 0)
@@ -604,11 +595,9 @@ ppt_setup_msix(struct vm *vm, int vcpu, int bus, int s
        int numvec, alloced, rid, error;
        size_t res_size, cookie_size, arg_size;
 
-       ppt = ppt_find(bus, slot, func);
-       if (ppt == NULL)
-               return (ENOENT);
-       if (ppt->vm != vm)              /* Make sure we own this device */
-               return (EBUSY);
+       error = ppt_find(vm, bus, slot, func, &ppt);
+       if (error)
+               return (error);
 
        /* Reject attempts to enable MSI-X while MSI is active. */
        if (ppt->msi.num_msgs != 0)
@@ -712,12 +701,11 @@ int
 ppt_disable_msix(struct vm *vm, int bus, int slot, int func)
 {
        struct pptdev *ppt;
+       int error;
 
-       ppt = ppt_find(bus, slot, func);
-       if (ppt == NULL)
-               return (ENOENT);
-       if (ppt->vm != vm)              /* Make sure we own this device */
-               return (EBUSY);
+       error = ppt_find(vm, bus, slot, func, &ppt);
+       if (error)
+               return (error);
 
        ppt_teardown_msix(ppt);
        return (0);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to