aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2020-12-14 20:48:59 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2020-12-14 20:48:59 +0000
commit2426d0d1188220a8f4a7e6846e033e2ddf4fccf4 (patch)
treeb7c05c0d00f2a8cab9b1b7d978a165d2255de7ae
parentb17a444a2988346c239df4b3c66a550b5b7e2118 (diff)
downloadsrc-2426d0d1188220a8f4a7e6846e033e2ddf4fccf4.tar.gz
src-2426d0d1188220a8f4a7e6846e033e2ddf4fccf4.zip
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.
Notes
Notes: svn path=/stable/12/; revision=368642
-rw-r--r--sys/amd64/vmm/io/ppt.c128
1 files changed, 58 insertions, 70 deletions
diff --git a/sys/amd64/vmm/io/ppt.c b/sys/amd64/vmm/io/ppt.c
index 782b1c108436..4de45ff6d6f9 100644
--- a/sys/amd64/vmm/io/ppt.c
+++ b/sys/amd64/vmm/io/ppt.c
@@ -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;
-
- 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);
-
- 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);
+ int error;
+
+ /* 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);
}
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 func,
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 slot, int func,
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 slot, int func,
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);