svn commit: r368004 - head/sys/amd64/vmm/io
John Baldwin
jhb at FreeBSD.org
Tue Nov 24 23:56:34 UTC 2020
Author: jhb
Date: Tue Nov 24 23:56:33 2020
New Revision: 368004
URL: https://svnweb.freebsd.org/changeset/base/368004
Log:
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.
Reviewed by: markj, grehan
MFC after: 2 weeks
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D27301
Modified:
head/sys/amd64/vmm/io/ppt.c
Modified: head/sys/amd64/vmm/io/ppt.c
==============================================================================
--- head/sys/amd64/vmm/io/ppt.c Tue Nov 24 23:18:52 2020 (r368003)
+++ head/sys/amd64/vmm/io/ppt.c Tue Nov 24 23:56:33 2020 (r368004)
@@ -199,8 +199,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;
@@ -212,9 +212,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
@@ -378,50 +384,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
@@ -452,25 +448,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
@@ -512,11 +505,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)
@@ -605,11 +596,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)
@@ -713,12 +702,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);
More information about the svn-src-all
mailing list