drivers/vfio/pci/vfio_pci_core.c
Source file repositories/reference/linux-study-clean/drivers/vfio/pci/vfio_pci_core.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/vfio/pci/vfio_pci_core.c- Extension
.c- Size
- 72341 bytes
- Lines
- 2643
- Domain
- Driver Families
- Bucket
- drivers/vfio
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/aperture.hlinux/device.hlinux/eventfd.hlinux/file.hlinux/interrupt.hlinux/iommu.hlinux/module.hlinux/mutex.hlinux/notifier.hlinux/pci.hlinux/pm_runtime.hlinux/slab.hlinux/types.hlinux/uaccess.hlinux/vgaarb.hlinux/nospec.hlinux/sched/mm.hlinux/iommufd.hlinux/pci-p2pdma.hasm/eeh.hvfio_pci_priv.h
Detected Declarations
struct vfio_pci_dummy_resourcestruct vfio_pci_vf_tokenstruct vfio_pci_group_infostruct vfio_pci_fill_infostruct vfio_pci_group_infostruct vfio_pci_walk_infofunction vfio_pci_eventfd_rcu_freefunction vfio_pci_eventfd_replace_lockedfunction vfio_vga_disabledfunction vfio_pci_set_decodefunction vfio_pci_probe_mmapsfunction vfio_pci_nointxfunction vfio_pci_probe_power_statefunction pci_set_power_statefunction vfio_pci_runtime_pm_entryfunction vfio_pci_core_pm_entryfunction vfio_pci_core_pm_entry_with_wakeupfunction __vfio_pci_runtime_pm_exitfunction vfio_pci_runtime_pm_exitfunction vfio_pci_core_pm_exitfunction vfio_pci_core_runtime_suspendfunction vfio_pci_core_runtime_resumefunction vfio_pci_core_map_barsfunction vfio_pci_core_enablefunction vfio_pci_core_disablefunction list_for_each_entry_safefunction vfio_pci_core_close_devicefunction vfio_pci_core_finish_enablefunction vfio_pci_get_irq_countfunction vfio_pci_count_devsfunction vfio_pci_fill_devsfunction vfio_pci_dev_below_slotfunction vfio_pci_walk_wrapperfunction vfio_pci_for_each_slot_or_busfunction msix_mmappable_capfunction vfio_pci_core_register_dev_regionfunction vfio_pci_info_atomic_capfunction vfio_pci_ioctl_get_infofunction vfio_pci_ioctl_get_region_infofunction vfio_pci_ioctl_get_irq_infofunction vfio_pci_ioctl_set_irqsfunction vfio_pci_ioctl_resetfunction vfio_pci_ioctl_get_pci_hot_reset_infofunction vfio_pci_ioctl_pci_hot_reset_groupsfunction vfio_pci_ioctl_pci_hot_resetfunction vfio_pci_ioctl_ioeventfdfunction vfio_pci_core_ioctlfunction vfio_pci_core_feature_token
Annotated Snippet
struct pci_driver *drv = pci_dev_driver(pdev);
if (drv && drv != pci_dev_driver(vdev->pdev))
pci_warn(vdev->pdev,
"VF %s bound to driver %s while PF bound to driver %s\n",
pci_name(pdev), drv->name,
pci_dev_driver(vdev->pdev)->name);
}
return 0;
}
static int vfio_pci_vf_init(struct vfio_pci_core_device *vdev)
{
struct pci_dev *pdev = vdev->pdev;
struct vfio_pci_core_device *cur;
struct pci_dev *physfn;
int ret;
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_obj(*vdev->vf_token);
if (!vdev->vf_token)
return -ENOMEM;
mutex_init(&vdev->vf_token->lock);
uuid_gen(&vdev->vf_token->uuid);
vdev->nb.notifier_call = vfio_pci_bus_notifier;
ret = bus_register_notifier(&pci_bus_type, &vdev->nb);
if (ret) {
kfree(vdev->vf_token);
return ret;
}
return 0;
}
static void vfio_pci_vf_uninit(struct vfio_pci_core_device *vdev)
{
if (!vdev->vf_token)
return;
bus_unregister_notifier(&pci_bus_type, &vdev->nb);
WARN_ON(vdev->vf_token->users);
mutex_destroy(&vdev->vf_token->lock);
kfree(vdev->vf_token);
}
static int vfio_pci_vga_init(struct vfio_pci_core_device *vdev)
{
struct pci_dev *pdev = vdev->pdev;
int ret;
if (!vfio_pci_is_vga(pdev))
return 0;
ret = aperture_remove_conflicting_pci_devices(pdev, vdev->vdev.ops->name);
if (ret)
return ret;
ret = vga_client_register(pdev, vfio_pci_set_decode);
if (ret)
return ret;
vga_set_legacy_decoding(pdev, vfio_pci_set_decode(pdev, false));
return 0;
}
static void vfio_pci_vga_uninit(struct vfio_pci_core_device *vdev)
{
Annotation
- Immediate include surface: `linux/aperture.h`, `linux/device.h`, `linux/eventfd.h`, `linux/file.h`, `linux/interrupt.h`, `linux/iommu.h`, `linux/module.h`, `linux/mutex.h`.
- Detected declarations: `struct vfio_pci_dummy_resource`, `struct vfio_pci_vf_token`, `struct vfio_pci_group_info`, `struct vfio_pci_fill_info`, `struct vfio_pci_group_info`, `struct vfio_pci_walk_info`, `function vfio_pci_eventfd_rcu_free`, `function vfio_pci_eventfd_replace_locked`, `function vfio_vga_disabled`, `function vfio_pci_set_decode`.
- Atlas domain: Driver Families / drivers/vfio.
- Implementation status: pattern implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.