// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2012 Red Hat, Inc. All rights reserved. * Author: Alex Williamson <alex.williamson@redhat.com> * * Derived from original vfio: * Copyright 2010 Cisco Systems, Inc. All rights reserved. * Author: Tom Lyon, pugs@cisco.com
*/
/* List of PF's that vfio_pci_core_sriov_configure() has been called on */ static DEFINE_MUTEX(vfio_pci_sriov_pfs_mutex); static LIST_HEAD(vfio_pci_sriov_pfs);
/* * Our VGA arbiter participation is limited since we don't know anything * about the device itself. However, if the device is the only VGA device * downstream of a bridge and VFIO VGA support is disabled, then we can * safely return legacy VGA IO and memory as not decoded since the user * has no way to get to it and routing can be disabled externally at the * bridge.
*/ staticunsignedint vfio_pci_set_decode(struct pci_dev *pdev, bool single_vga)
{ struct pci_dev *tmp = NULL; unsignedchar max_busnr; unsignedint decodes;
for (i = 0; i < PCI_STD_NUM_BARS; i++) { int bar = i + PCI_STD_RESOURCES;
res = &vdev->pdev->resource[bar];
if (vdev->pdev->non_mappable_bars) goto no_mmap;
if (!(res->flags & IORESOURCE_MEM)) goto no_mmap;
/* * The PCI core shouldn't set up a resource with a * type but zero size. But there may be bugs that * cause us to do that.
*/ if (!resource_size(res)) goto no_mmap;
if (resource_size(res) >= PAGE_SIZE) {
vdev->bar_mmap_supported[bar] = true; continue;
}
if (!(res->start & ~PAGE_MASK)) { /* * Add a dummy resource to reserve the remainder * of the exclusive page in case that hot-add * device's bar is assigned into it.
*/
dummy_res =
kzalloc(sizeof(*dummy_res), GFP_KERNEL_ACCOUNT); if (dummy_res == NULL) goto no_mmap;
dummy_res->resource.name = "vfio sub-page reserved";
dummy_res->resource.start = res->end + 1;
dummy_res->resource.end = res->start + PAGE_SIZE - 1;
dummy_res->resource.flags = res->flags; if (request_resource(res->parent,
&dummy_res->resource)) {
kfree(dummy_res); goto no_mmap;
}
dummy_res->index = bar;
list_add(&dummy_res->res_next,
&vdev->dummy_resources_list);
vdev->bar_mmap_supported[bar] = true; continue;
} /* * Here we don't handle the case when the BAR is not page * aligned because we can't expect the BAR will be * assigned into the same location in a page in guest * when we passthrough the BAR. And it's hard to access * this BAR in userspace because we have no way to get * the BAR's location in a page.
*/
no_mmap:
vdev->bar_mmap_supported[bar] = false;
}
}
/* * INTx masking requires the ability to disable INTx signaling via PCI_COMMAND * _and_ the ability detect when the device is asserting INTx via PCI_STATUS. * If a device implements the former but not the latter we would typically * expect broken_intx_masking be set and require an exclusive interrupt. * However since we do have control of the device's ability to assert INTx, * we can instead pretend that the device does not implement INTx, virtualizing * the pin register to report zero and maintaining DisINTx set on the host.
*/ staticbool vfio_pci_nointx(struct pci_dev *pdev)
{ switch (pdev->vendor) { case PCI_VENDOR_ID_INTEL: switch (pdev->device) { /* All i40e (XL710/X710/XXV710) 10/20/25/40GbE NICs */ case 0x1572: case 0x1574: case 0x1580 ... 0x1581: case 0x1583 ... 0x158b: case 0x37d0 ... 0x37d2: /* X550 */ case 0x1563: returntrue; default: returnfalse;
}
}
/* * pci_set_power_state() wrapper handling devices which perform a soft reset on * D3->D0 transition. Save state prior to D0/1/2->D3, stash it on the vdev, * restore when returned to D0. Saved separately from pci_saved_state for use * by PM capability emulation and separately from pci_dev internal saved state * to avoid it being overwritten and consumed around other resets.
*/ int vfio_pci_set_power_state(struct vfio_pci_core_device *vdev, pci_power_t state)
{ struct pci_dev *pdev = vdev->pdev; bool needs_restore = false, needs_save = false; int ret;
/* Prevent changing power state for PFs with VFs enabled */ if (pci_num_vf(pdev) && state > PCI_D0) return -EBUSY;
if (vdev->needs_pm_restore) { if (pdev->current_state < PCI_D3hot && state >= PCI_D3hot) {
pci_save_state(pdev);
needs_save = true;
}
if (pdev->current_state >= PCI_D3hot && state <= PCI_D0)
needs_restore = true;
}
ret = pci_set_power_state(pdev, state);
if (!ret) { /* D3 might be unsupported via quirk, skip unless in D3 */ if (needs_save && pdev->current_state >= PCI_D3hot) { /* * The current PCI state will be saved locally in * 'pm_save' during the D3hot transition. When the * device state is changed to D0 again with the current * function, then pci_store_saved_state() will restore * the state and will free the memory pointed by * 'pm_save'. There are few cases where the PCI power * state can be changed to D0 without the involvement * of the driver. For these cases, free the earlier * allocated memory first before overwriting 'pm_save' * to prevent the memory leak.
*/
kfree(vdev->pm_save);
vdev->pm_save = pci_store_saved_state(pdev);
} elseif (needs_restore) {
pci_load_and_free_saved_state(pdev, &vdev->pm_save);
pci_restore_state(pdev);
}
}
return ret;
}
staticint vfio_pci_runtime_pm_entry(struct vfio_pci_core_device *vdev, struct eventfd_ctx *efdctx)
{ /* * The vdev power related flags are protected with 'memory_lock' * semaphore.
*/
vfio_pci_zap_and_down_write_memory_lock(vdev); if (vdev->pm_runtime_engaged) {
up_write(&vdev->memory_lock); return -EINVAL;
}
ret = vfio_check_feature(flags, argsz, VFIO_DEVICE_FEATURE_SET, 0); if (ret != 1) return ret;
/* * Inside vfio_pci_runtime_pm_entry(), only the runtime PM usage count * will be decremented. The pm_runtime_put() will be invoked again * while returning from the ioctl and then the device can go into * runtime suspended state.
*/ return vfio_pci_runtime_pm_entry(vdev, NULL);
}
if (vdev->pm_wake_eventfd_ctx) {
eventfd_ctx_put(vdev->pm_wake_eventfd_ctx);
vdev->pm_wake_eventfd_ctx = NULL;
}
}
}
staticvoid vfio_pci_runtime_pm_exit(struct vfio_pci_core_device *vdev)
{ /* * The vdev power related flags are protected with 'memory_lock' * semaphore.
*/
down_write(&vdev->memory_lock);
__vfio_pci_runtime_pm_exit(vdev);
up_write(&vdev->memory_lock);
}
ret = vfio_check_feature(flags, argsz, VFIO_DEVICE_FEATURE_SET, 0); if (ret != 1) return ret;
/* * The device is always in the active state here due to pm wrappers * around ioctls. If the device had entered a low power state and * pm_wake_eventfd_ctx is valid, vfio_pci_core_runtime_resume() has * already signaled the eventfd and exited low power mode itself. * pm_runtime_engaged protects the redundant call here.
*/
vfio_pci_runtime_pm_exit(vdev); return 0;
}
down_write(&vdev->memory_lock); /* * The user can move the device into D3hot state before invoking * power management IOCTL. Move the device into D0 state here and then * the pci-driver core runtime PM suspend function will move the device * into the low power state. Also, for the devices which have * NoSoftRst-, it will help in restoring the original state * (saved locally in 'vdev->pm_save').
*/
vfio_pci_set_power_state(vdev, PCI_D0);
up_write(&vdev->memory_lock);
/* * If INTx is enabled, then mask INTx before going into the runtime * suspended state and unmask the same in the runtime resume. * If INTx has already been masked by the user, then * vfio_pci_intx_mask() will return false and in that case, INTx * should not be unmasked in the runtime resume.
*/
vdev->pm_intx_masked = ((vdev->irq_type == VFIO_PCI_INTX_IRQ_INDEX) &&
vfio_pci_intx_mask(vdev));
/* * Resume with a pm_wake_eventfd_ctx signals the eventfd and exit * low power mode.
*/
down_write(&vdev->memory_lock); if (vdev->pm_wake_eventfd_ctx) {
eventfd_signal(vdev->pm_wake_eventfd_ctx);
__vfio_pci_runtime_pm_exit(vdev);
}
up_write(&vdev->memory_lock);
if (vdev->pm_intx_masked)
vfio_pci_intx_unmask(vdev);
return 0;
} #endif/* CONFIG_PM */
/* * The pci-driver core runtime PM routines always save the device state * before going into suspended state. If the device is going into low power * state with only with runtime PM ops, then no explicit handling is needed * for the devices which have NoSoftRst-.
*/ staticconststruct dev_pm_ops vfio_pci_core_pm_ops = {
SET_RUNTIME_PM_OPS(vfio_pci_core_runtime_suspend,
vfio_pci_core_runtime_resume,
NULL)
};
int vfio_pci_core_enable(struct vfio_pci_core_device *vdev)
{ struct pci_dev *pdev = vdev->pdev; int ret;
u16 cmd;
u8 msix_pos;
if (!disable_idle_d3) {
ret = pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) return ret;
}
/* Don't allow our initial saved state to include busmaster */
pci_clear_master(pdev);
ret = pci_enable_device(pdev); if (ret) goto out_power;
/* If reset fails because of the device lock, fail this path entirely */
ret = pci_try_reset_function(pdev); if (ret == -EAGAIN) goto out_disable_device;
vdev->reset_works = !ret;
pci_save_state(pdev);
vdev->pci_saved_state = pci_store_saved_state(pdev); if (!vdev->pci_saved_state)
pci_dbg(pdev, "%s: Couldn't store saved state\n", __func__);
/* For needs_reset */
lockdep_assert_held(&vdev->vdev.dev_set->lock);
/* * This function can be invoked while the power state is non-D0. * This non-D0 power state can be with or without runtime PM. * vfio_pci_runtime_pm_exit() will internally increment the usage * count corresponding to pm_runtime_put() called during low power * feature entry and then pm_runtime_resume() will wake up the device, * if the device has already gone into the suspended state. Otherwise, * the vfio_pci_set_power_state() will change the device power state * to D0.
*/
vfio_pci_runtime_pm_exit(vdev);
pm_runtime_resume(&pdev->dev);
/* * This function calls __pci_reset_function_locked() which internally * can use pci_pm_reset() for the function reset. pci_pm_reset() will * fail if the power state is non-D0. Also, for the devices which * have NoSoftRst-, the reset function can cause the PCI config space * reset without restoring the original state (saved locally in * 'vdev->pm_save').
*/
vfio_pci_set_power_state(vdev, PCI_D0);
/* Stop the device from further DMA */
pci_clear_master(pdev);
for (i = 0; i < PCI_STD_NUM_BARS; i++) {
bar = i + PCI_STD_RESOURCES; if (!vdev->barmap[bar]) continue;
pci_iounmap(pdev, vdev->barmap[bar]);
pci_release_selected_regions(pdev, 1 << bar);
vdev->barmap[bar] = NULL;
}
/* * If we have saved state, restore it. If we can reset the device, * even better. Resetting with current state seems better than * nothing, but saving and restoring current state without reset * is just busy work.
*/ if (pci_load_and_free_saved_state(pdev, &vdev->pci_saved_state)) {
pci_info(pdev, "%s: Couldn't reload saved state\n", __func__);
if (!vdev->reset_works) goto out;
pci_save_state(pdev);
}
/* * Disable INTx and MSI, presumably to avoid spurious interrupts * during reset. Stolen from pci_reset_function()
*/
pci_write_config_word(pdev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE);
/* * Try to get the locks ourselves to prevent a deadlock. The * success of this is dependent on being able to lock the device, * which is not always possible. * We can not use the "try" reset interface here, which will * overwrite the previously restored configuration information.
*/ if (vdev->reset_works && pci_dev_trylock(pdev)) { if (!__pci_reset_function_locked(pdev))
vdev->needs_reset = false;
pci_dev_unlock(pdev);
}
/* Put the pm-runtime usage counter acquired during enable */ if (!disable_idle_d3)
pm_runtime_put(&pdev->dev);
}
EXPORT_SYMBOL_GPL(vfio_pci_core_disable);
/* * hot-reset requires all affected devices be represented in * the dev_set.
*/
vdev = vfio_find_device_in_devset(dev_set, &pdev->dev); if (!vdev) {
info->devid = VFIO_PCI_DEVID_NOT_OWNED;
} else { int id = vfio_iommufd_get_dev_id(vdev, iommufd);
if (id > 0)
info->devid = id; elseif (id == -ENOENT)
info->devid = VFIO_PCI_DEVID_OWNED; else
info->devid = VFIO_PCI_DEVID_NOT_OWNED;
} /* If devid is VFIO_PCI_DEVID_NOT_OWNED, clear owned flag. */ if (info->devid == VFIO_PCI_DEVID_NOT_OWNED)
fill->flags &= ~VFIO_PCI_HOT_RESET_FLAG_DEV_ID_OWNED;
} else { struct iommu_group *iommu_group;
ret = vfio_pci_info_zdev_add_caps(vdev, &caps); if (ret && ret != -ENODEV) {
pci_warn(vdev->pdev, "Failed to setup zPCI info capabilities\n"); return ret;
}
ret = vfio_pci_info_atomic_cap(vdev, &caps); if (ret && ret != -ENODEV) {
pci_warn(vdev->pdev, "Failed to setup AtomicOps info capability\n"); return ret;
}
if (pci_resource_start(pdev, PCI_ROM_RESOURCE)) { /* * Check ROM content is valid. Need to enable memory * decode for ROM access in pci_map_rom().
*/
cmd = vfio_pci_memory_lock_and_enable(vdev);
io = pci_map_rom(pdev, &size); if (io) {
info.flags = VFIO_REGION_INFO_FLAG_READ; /* Report the BAR size, not the ROM size. */
info.size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
pci_unmap_rom(pdev, io);
}
vfio_pci_memory_unlock_and_restore(vdev, cmd);
} elseif (pdev->rom && pdev->romlen) {
info.flags = VFIO_REGION_INFO_FLAG_READ; /* Report BAR size as power of two. */
info.size = roundup_pow_of_two(pdev->romlen);
}
break;
} case VFIO_PCI_VGA_REGION_INDEX: if (!vdev->has_vga) return -EINVAL;
if (copy_from_user(&info, arg, minsz)) return -EFAULT;
if (info.argsz < minsz || info.index >= VFIO_PCI_NUM_IRQS) return -EINVAL;
switch (info.index) { case VFIO_PCI_INTX_IRQ_INDEX ... VFIO_PCI_MSIX_IRQ_INDEX: case VFIO_PCI_REQ_IRQ_INDEX: break; case VFIO_PCI_ERR_IRQ_INDEX: if (pci_is_pcie(vdev->pdev)) break;
fallthrough; default: return -EINVAL;
}
if (copy_from_user(&hdr, arg, minsz)) return -EFAULT;
max = vfio_pci_get_irq_count(vdev, hdr.index);
ret = vfio_set_irqs_validate_and_prepare(&hdr, max, VFIO_PCI_NUM_IRQS,
&data_size); if (ret) return ret;
if (data_size) {
data = memdup_user(&arg->data, data_size); if (IS_ERR(data)) return PTR_ERR(data);
}
mutex_lock(&vdev->igate);
ret = vfio_pci_set_irqs_ioctl(vdev, hdr.flags, hdr.index, hdr.start,
hdr.count, data);
mutex_unlock(&vdev->igate);
kfree(data);
return ret;
}
staticint vfio_pci_ioctl_reset(struct vfio_pci_core_device *vdev, void __user *arg)
{ int ret;
if (!vdev->reset_works) return -EINVAL;
vfio_pci_zap_and_down_write_memory_lock(vdev);
/* * This function can be invoked while the power state is non-D0. If * pci_try_reset_function() has been called while the power state is * non-D0, then pci_try_reset_function() will internally set the power * state to D0 without vfio driver involvement. For the devices which * have NoSoftRst-, the reset function can cause the PCI config space * reset without restoring the original state (saved locally in * 'vdev->pm_save').
*/
vfio_pci_set_power_state(vdev, PCI_D0);
ret = pci_try_reset_function(vdev->pdev);
up_write(&vdev->memory_lock);
if (copy_from_user(&hdr, arg, minsz)) return -EFAULT;
if (hdr.argsz < minsz) return -EINVAL;
hdr.flags = 0;
/* Can we do a slot or bus reset or neither? */ if (!pci_probe_reset_slot(vdev->pdev->slot))
slot = true; elseif (pci_probe_reset_bus(vdev->pdev->bus)) return -ENODEV;
ret = vfio_pci_for_each_slot_or_bus(vdev->pdev, vfio_pci_count_devs,
&count, slot); if (ret) return ret;
if (WARN_ON(!count)) /* Should always be at least one */ return -ERANGE;
if (count > (hdr.argsz - sizeof(hdr)) / sizeof(*devices)) {
hdr.count = count;
ret = -ENOSPC; goto header;
}
devices = kcalloc(count, sizeof(*devices), GFP_KERNEL); if (!devices) return -ENOMEM;
/* * We can't let userspace give us an arbitrarily large buffer to copy, * so verify how many we think there could be. Note groups can have * multiple devices so one group per device is the max.
*/
ret = vfio_pci_for_each_slot_or_bus(vdev->pdev, vfio_pci_count_devs,
&count, slot); if (ret) return ret;
/* * Get the group file for each fd to ensure the group is held across * the reset
*/ for (file_idx = 0; file_idx < array_count; file_idx++) { struct file *file = fget(group_fds[file_idx]);
if (!file) {
ret = -EBADF; break;
}
/* Ensure the FD is a vfio group FD.*/ if (!vfio_file_is_group(file)) {
fput(file);
ret = -EINVAL; break;
}
files[file_idx] = file;
}
kfree(group_fds);
/* release reference to groups on error */ if (ret) goto hot_reset_release;
info.count = array_count;
info.files = files;
ret = vfio_pci_dev_set_hot_reset(vdev->vdev.dev_set, &info, NULL);
hot_reset_release: for (file_idx--; file_idx >= 0; file_idx--)
fput(files[file_idx]);
if (copy_from_user(&hdr, arg, minsz)) return -EFAULT;
if (hdr.argsz < minsz || hdr.flags) return -EINVAL;
/* zero-length array is only for cdev opened devices */ if (!!hdr.count == vfio_device_cdev_opened(&vdev->vdev)) return -EINVAL;
/* Can we do a slot or bus reset or neither? */ if (!pci_probe_reset_slot(vdev->pdev->slot))
slot = true; elseif (pci_probe_reset_bus(vdev->pdev->bus)) return -ENODEV;
if (hdr.count) return vfio_pci_ioctl_pci_hot_reset_groups(vdev, hdr.count, slot, arg);
if (!vdev->vf_token) return -ENOTTY; /* * We do not support GET of the VF Token UUID as this could * expose the token of the previous device user.
*/
ret = vfio_check_feature(flags, argsz, VFIO_DEVICE_FEATURE_SET, sizeof(uuid)); if (ret != 1) return ret;
if (copy_from_user(&uuid, arg, sizeof(uuid))) return -EFAULT;
if (req_start + req_len > phys_len) return -EINVAL;
/* * Even though we don't make use of the barmap for the mmap, * we need to request the region and the barmap tracks that.
*/ if (!vdev->barmap[index]) {
ret = pci_request_selected_regions(pdev,
1 << index, "vfio-pci"); if (ret) return ret;
/* * Set vm_flags now, they should not be changed in the fault handler. * We want the same flags and page protection (decrypted above) as * io_remap_pfn_range() would set. * * VM_ALLOW_ANY_UNCACHED: The VMA flag is implemented for ARM64, * allowing KVM stage 2 device mapping attributes to use Normal-NC * rather than DEVICE_nGnRE, which allows guest mappings * supporting write-combining attributes (WC). ARM does not * architecturally guarantee this is safe, and indeed some MMIO * regions like the GICv2 VCPU interface can trigger uncontained * faults if Normal-NC is used. * * To safely use VFIO in KVM the platform must guarantee full * safety in the guest where no action taken against a MMIO * mapping can trigger an uncontained failure. The assumption is * that most VFIO PCI platforms support this for both mapping types, * at least in common flows, based on some expectations of how * PCI IP is integrated. Hence VM_ALLOW_ANY_UNCACHED is set in * the VMA flags.
*/
vm_flags_set(vma, VM_ALLOW_ANY_UNCACHED | VM_IO | VM_PFNMAP |
VM_DONTEXPAND | VM_DONTDUMP);
vma->vm_ops = &vfio_pci_mmap_ops;
if (vdev->req_trigger) { if (!(count % 10))
pci_notice_ratelimited(pdev, "Relaying device request to user (#%u)\n",
count);
eventfd_signal(vdev->req_trigger);
} elseif (count == 0) {
pci_warn(pdev, "No device request channel registered, blocked until released by user\n");
}
/* * There's always some degree of trust or collaboration between SR-IOV * PF and VFs, even if just that the PF hosts the SR-IOV capability and * can disrupt VFs with a reset, but often the PF has more explicit * access to deny service to the VF or access data passed through the * VF. We therefore require an opt-in via a shared VF token (UUID) to * represent this trust. This both prevents that a VF driver might * assume the PF driver is a trusted, in-kernel driver, and also that * a PF driver might be replaced with a rogue driver, unknown to in-use * VF drivers. * * Therefore when presented with a VF, if the PF is a vfio device and * it is bound to the vfio-pci driver, the user needs to provide a VF * token to access the device, in the form of appending a vf_token to * the device name, for example: * * "0000:04:10.0 vf_token=bd8d9d2b-5a5f-4f5a-a211-f591514ba1f3" * * When presented with a PF which has VFs in use, the user must also * provide the current VF token to prove collaboration with existing * VF users. If VFs are not in use, the VF token provided for the PF * device will act to set the VF token. * * If the VF token is provided but unused, an error is generated.
*/ if (vdev->pdev->is_virtfn) { struct vfio_pci_core_device *pf_vdev = vdev->sriov_pf_core_dev; bool match;
if (!pf_vdev) { if (!uuid) return 0; /* PF is not vfio-pci, no VF token */
pci_info_ratelimited(vdev->pdev, "VF token incorrectly provided, PF not bound to vfio-pci\n"); return -EINVAL;
}
if (!uuid) {
pci_info_ratelimited(vdev->pdev, "VF token required to access device\n"); return -EACCES;
}
mutex_lock(&pf_vdev->vf_token->lock);
match = uuid_equal(uuid, &pf_vdev->vf_token->uuid);
mutex_unlock(&pf_vdev->vf_token->lock);
if (!match) {
pci_info_ratelimited(vdev->pdev, "Incorrect VF token provided for device\n"); return -EACCES;
}
} elseif (vdev->vf_token) {
mutex_lock(&vdev->vf_token->lock); if (vdev->vf_token->users) { if (!uuid) {
mutex_unlock(&vdev->vf_token->lock);
pci_info_ratelimited(vdev->pdev, "VF token required to access device\n"); return -EACCES;
}
if (pdev->is_virtfn) { /* * If this VF was created by our vfio_pci_core_sriov_configure() * then we can find the PF vfio_pci_core_device now, and due to * the locking in pci_disable_sriov() it cannot change until * this VF device driver is removed.
*/
physfn = pci_physfn(vdev->pdev);
mutex_lock(&vfio_pci_sriov_pfs_mutex);
list_for_each_entry(cur, &vfio_pci_sriov_pfs, sriov_pfs_item) { if (cur->pdev == physfn) {
vdev->sriov_pf_core_dev = cur; break;
}
}
mutex_unlock(&vfio_pci_sriov_pfs_mutex); return 0;
}
/* Not a SRIOV PF */ if (!pdev->is_physfn) return 0;
vdev->vf_token = kzalloc(sizeof(*vdev->vf_token), GFP_KERNEL); if (!vdev->vf_token) return -ENOMEM;
int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev)
{ struct pci_dev *pdev = vdev->pdev; struct device *dev = &pdev->dev; int ret;
/* Drivers must set the vfio_pci_core_device to their drvdata */ if (WARN_ON(vdev != dev_get_drvdata(dev))) return -EINVAL;
if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL) return -EINVAL;
if (vdev->vdev.mig_ops) { if (!(vdev->vdev.mig_ops->migration_get_state &&
vdev->vdev.mig_ops->migration_set_state &&
vdev->vdev.mig_ops->migration_get_data_size) ||
!(vdev->vdev.migration_flags & VFIO_MIGRATION_STOP_COPY)) return -EINVAL;
}
if (vdev->vdev.log_ops && !(vdev->vdev.log_ops->log_start &&
vdev->vdev.log_ops->log_stop &&
vdev->vdev.log_ops->log_read_and_clear)) return -EINVAL;
/* * Prevent binding to PFs with VFs enabled, the VFs might be in use * by the host or other users. We cannot capture the VFs if they * already exist, nor can we track VF users. Disabling SR-IOV here * would initiate removing the VFs, which would unbind the driver, * which is prone to blocking if that VF is also in use by vfio-pci. * Just reject these PFs and let the user sort it out.
*/ if (pci_num_vf(pdev)) {
pci_warn(pdev, "Cannot bind to PF with SR-IOV enabled\n"); return -EBUSY;
}
if (pci_is_root_bus(pdev->bus) || pdev->is_virtfn) {
ret = vfio_assign_device_set(&vdev->vdev, vdev);
} elseif (!pci_probe_reset_slot(pdev->slot)) {
ret = vfio_assign_device_set(&vdev->vdev, pdev->slot);
} else { /* * If there is no slot reset support for this device, the whole * bus needs to be grouped together to support bus-wide resets.
*/
ret = vfio_assign_device_set(&vdev->vdev, pdev->bus);
}
if (ret) return ret;
ret = vfio_pci_vf_init(vdev); if (ret) return ret;
ret = vfio_pci_vga_init(vdev); if (ret) goto out_vf;
vfio_pci_probe_power_state(vdev);
/* * pci-core sets the device power state to an unknown value at * bootup and after being removed from a driver. The only * transition it allows from this unknown state is to D0, which * typically happens when a driver calls pci_enable_device(). * We're not ready to enable the device yet, but we do want to * be able to get to D3. Therefore first do a D0 transition * before enabling runtime PM.
*/
vfio_pci_set_power_state(vdev, PCI_D0);
dev->driver->pm = &vfio_pci_core_pm_ops;
pm_runtime_allow(dev); if (!disable_idle_d3)
pm_runtime_put(dev);
ret = vfio_register_group_dev(&vdev->vdev); if (ret) goto out_power; return 0;
out_power: if (!disable_idle_d3)
pm_runtime_get_noresume(dev);
int vfio_pci_core_sriov_configure(struct vfio_pci_core_device *vdev, int nr_virtfn)
{ struct pci_dev *pdev = vdev->pdev; int ret = 0;
device_lock_assert(&pdev->dev);
if (nr_virtfn) {
mutex_lock(&vfio_pci_sriov_pfs_mutex); /* * The thread that adds the vdev to the list is the only thread * that gets to call pci_enable_sriov() and we will only allow * it to be called once without going through * pci_disable_sriov()
*/ if (!list_empty(&vdev->sriov_pfs_item)) {
ret = -EINVAL; goto out_unlock;
}
list_add_tail(&vdev->sriov_pfs_item, &vfio_pci_sriov_pfs);
mutex_unlock(&vfio_pci_sriov_pfs_mutex);
/* * The PF power state should always be higher than the VF power * state. The PF can be in low power state either with runtime * power management (when there is no user) or PCI_PM_CTRL * register write by the user. If PF is in the low power state, * then change the power state to D0 first before enabling * SR-IOV. Also, this function can be called at any time, and * userspace PCI_PM_CTRL write can race against this code path, * so protect the same with 'memory_lock'.
*/
ret = pm_runtime_resume_and_get(&pdev->dev); if (ret) goto out_del;
down_write(&vdev->memory_lock);
vfio_pci_set_power_state(vdev, PCI_D0);
ret = pci_enable_sriov(pdev, nr_virtfn);
up_write(&vdev->memory_lock); if (ret) {
pm_runtime_put(&pdev->dev); goto out_del;
} return nr_virtfn;
}
if (pci_num_vf(pdev)) {
pci_disable_sriov(pdev);
pm_runtime_put(&pdev->dev);
}
/* * vfio-core considers a group to be viable and will create a vfio_device even * if some devices are bound to drivers like pci-stub or pcieport. Here we * require all PCI devices to be inside our dev_set since that ensures they stay * put and that every driver controlling the device can co-ordinate with the * device reset. * * Returns the pci_dev to pass to pci_reset_bus() if every PCI device to be * reset is inside the dev_set, and pci_reset_bus() can succeed. NULL otherwise.
*/ staticstruct pci_dev *
vfio_pci_dev_set_resettable(struct vfio_device_set *dev_set)
{ struct pci_dev *pdev;
lockdep_assert_held(&dev_set->lock);
/* * By definition all PCI devices in the dev_set share the same PCI * reset, so any pci_dev will have the same outcomes for * pci_probe_reset_*() and pci_reset_bus().
*/
pdev = list_first_entry(&dev_set->device_list, struct vfio_pci_core_device,
vdev.dev_set_list)->pdev;
/* pci_reset_bus() is supported */ if (pci_probe_reset_slot(pdev->slot) && pci_probe_reset_bus(pdev->bus)) return NULL;
if (vfio_pci_for_each_slot_or_bus(pdev, vfio_pci_is_device_in_set,
dev_set,
!pci_probe_reset_slot(pdev->slot))) return NULL; return pdev;
}
staticint vfio_pci_dev_set_pm_runtime_get(struct vfio_device_set *dev_set)
{ struct vfio_pci_core_device *cur; int ret;
list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list) {
ret = pm_runtime_resume_and_get(&cur->pdev->dev); if (ret) goto unwind;
}
pdev = vfio_pci_dev_set_resettable(dev_set); if (!pdev) {
ret = -EINVAL; goto err_unlock;
}
/* * Some of the devices in the dev_set can be in the runtime suspended * state. Increment the usage count for all the devices in the dev_set * before reset and decrement the same after reset.
*/
ret = vfio_pci_dev_set_pm_runtime_get(dev_set); if (ret) goto err_unlock;
/* * Test whether all the affected devices can be reset by the * user. * * If called from a group opened device and the user provides * a set of groups, all the devices in the dev_set should be * contained by the set of groups provided by the user. * * If called from a cdev opened device and the user provides * a zero-length array, all the devices in the dev_set must * be bound to the same iommufd_ctx as the input iommufd_ctx. * If there is any device that has not been bound to any * iommufd_ctx yet, check if its iommu_group has any device * bound to the input iommufd_ctx. Such devices can be * considered owned by the input iommufd_ctx as the device * cannot be owned by another iommufd_ctx when its iommu_group * is owned. * * Otherwise, reset is not allowed.
*/ if (iommufd_ctx) { int devid = vfio_iommufd_get_dev_id(&vdev->vdev,
iommufd_ctx);
/* * Take the memory write lock for each device and zap BAR * mappings to prevent the user accessing the device while in * reset. Locking multiple devices is prone to deadlock, * runaway and unwind if we hit contention.
*/ if (!down_write_trylock(&vdev->memory_lock)) {
ret = -EBUSY; break;
}
/* * The pci_reset_bus() will reset all the devices in the bus. * The power state can be non-D0 for some of the devices in the bus. * For these devices, the pci_reset_bus() will internally set * the power state to D0 without vfio driver involvement. * For the devices which have NoSoftRst-, the reset function can * cause the PCI config space reset without restoring the original * state (saved locally in 'vdev->pm_save').
*/
list_for_each_entry(vdev, &dev_set->device_list, vdev.dev_set_list)
vfio_pci_set_power_state(vdev, PCI_D0);
/* * If a bus or slot reset is available for the provided dev_set and: * - All of the devices affected by that bus or slot reset are unused * - At least one of the affected devices is marked dirty via * needs_reset (such as by lack of FLR support) * Then attempt to perform that bus or slot reset.
*/ staticvoid vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set)
{ struct vfio_pci_core_device *cur; struct pci_dev *pdev; bool reset_done = false;
if (!vfio_pci_dev_set_needs_reset(dev_set)) return;
pdev = vfio_pci_dev_set_resettable(dev_set); if (!pdev) return;
/* * Some of the devices in the bus can be in the runtime suspended * state. Increment the usage count for all the devices in the dev_set * before reset and decrement the same after reset.
*/ if (!disable_idle_d3 && vfio_pci_dev_set_pm_runtime_get(dev_set)) return;
if (!pci_reset_bus(pdev))
reset_done = true;
list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list) { if (reset_done)
cur->needs_reset = false;
if (!disable_idle_d3)
pm_runtime_put(&cur->pdev->dev);
}
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.72Bemerkung:
(vorverarbeitet am 2026-04-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.