drivers/vfio/pci/virtio/legacy_io.c
Source file repositories/reference/linux-study-clean/drivers/vfio/pci/virtio/legacy_io.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/vfio/pci/virtio/legacy_io.c- Extension
.c- Size
- 11293 bytes
- Lines
- 397
- Domain
- Driver Families
- Bucket
- drivers/vfio
- Inferred role
- Driver Families: implementation source
- Status
- source 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.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- 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/device.hlinux/module.hlinux/mutex.hlinux/pci.hlinux/pm_runtime.hlinux/types.hlinux/uaccess.hlinux/vfio.hlinux/vfio_pci_core.hlinux/virtio_pci.hlinux/virtio_net.hlinux/virtio_pci_admin.hcommon.h
Detected Declarations
function Copyrightfunction virtiovf_pci_bar0_rwfunction virtiovf_pci_read_configfunction virtiovf_pci_core_readfunction virtiovf_pci_write_configfunction virtiovf_pci_core_writefunction virtiovf_pci_ioctl_get_region_infofunction virtiovf_set_notify_addrfunction virtiovf_open_legacy_iofunction virtiovf_get_device_config_sizefunction virtiovf_read_notify_infofunction virtiovf_bar0_existsfunction virtiovf_support_legacy_iofunction virtiovf_init_legacy_iofunction virtiovf_release_legacy_iofunction virtiovf_legacy_io_reset_done
Annotated Snippet
if (count != sizeof(queue_notify)) {
ret = -EINVAL;
goto end;
}
if (read) {
ret = vfio_pci_core_ioread16(core_device, true, &queue_notify,
virtvdev->notify_addr);
if (ret)
goto end;
if (copy_to_user(buf, &queue_notify,
sizeof(queue_notify))) {
ret = -EFAULT;
goto end;
}
} else {
if (copy_from_user(&queue_notify, buf, count)) {
ret = -EFAULT;
goto end;
}
ret = vfio_pci_core_iowrite16(core_device, true, queue_notify,
virtvdev->notify_addr);
}
break;
default:
ret = virtiovf_issue_legacy_rw_cmd(virtvdev, pos, buf, count,
read);
}
end:
pm_runtime_put(&pdev->dev);
return ret ? ret : count;
}
static ssize_t virtiovf_pci_read_config(struct vfio_device *core_vdev,
char __user *buf, size_t count,
loff_t *ppos)
{
struct virtiovf_pci_core_device *virtvdev = container_of(
core_vdev, struct virtiovf_pci_core_device, core_device.vdev);
loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
size_t register_offset;
loff_t copy_offset;
size_t copy_count;
__le32 val32;
__le16 val16;
u8 val8;
int ret;
ret = vfio_pci_core_read(core_vdev, buf, count, ppos);
if (ret < 0)
return ret;
if (vfio_pci_core_range_intersect_range(pos, count, PCI_DEVICE_ID,
sizeof(val16), ©_offset,
©_count, ®ister_offset)) {
val16 = cpu_to_le16(VIRTIO_TRANS_ID_NET);
if (copy_to_user(buf + copy_offset, (void *)&val16 + register_offset, copy_count))
return -EFAULT;
}
if ((le16_to_cpu(virtvdev->pci_cmd) & PCI_COMMAND_IO) &&
vfio_pci_core_range_intersect_range(pos, count, PCI_COMMAND,
sizeof(val16), ©_offset,
©_count, ®ister_offset)) {
if (copy_from_user((void *)&val16 + register_offset, buf + copy_offset,
copy_count))
return -EFAULT;
val16 |= cpu_to_le16(PCI_COMMAND_IO);
if (copy_to_user(buf + copy_offset, (void *)&val16 + register_offset,
copy_count))
return -EFAULT;
}
if (vfio_pci_core_range_intersect_range(pos, count, PCI_REVISION_ID,
sizeof(val8), ©_offset,
©_count, ®ister_offset)) {
/* Transional needs to have revision 0 */
val8 = 0;
if (copy_to_user(buf + copy_offset, &val8, copy_count))
return -EFAULT;
}
if (vfio_pci_core_range_intersect_range(pos, count, PCI_BASE_ADDRESS_0,
sizeof(val32), ©_offset,
©_count, ®ister_offset)) {
u32 bar_mask = ~(virtvdev->bar0_virtual_buf_size - 1);
u32 pci_base_addr_0 = le32_to_cpu(virtvdev->pci_base_addr_0);
val32 = cpu_to_le32((pci_base_addr_0 & bar_mask) | PCI_BASE_ADDRESS_SPACE_IO);
if (copy_to_user(buf + copy_offset, (void *)&val32 + register_offset, copy_count))
Annotation
- Immediate include surface: `linux/device.h`, `linux/module.h`, `linux/mutex.h`, `linux/pci.h`, `linux/pm_runtime.h`, `linux/types.h`, `linux/uaccess.h`, `linux/vfio.h`.
- Detected declarations: `function Copyright`, `function virtiovf_pci_bar0_rw`, `function virtiovf_pci_read_config`, `function virtiovf_pci_core_read`, `function virtiovf_pci_write_config`, `function virtiovf_pci_core_write`, `function virtiovf_pci_ioctl_get_region_info`, `function virtiovf_set_notify_addr`, `function virtiovf_open_legacy_io`, `function virtiovf_get_device_config_size`.
- Atlas domain: Driver Families / drivers/vfio.
- Implementation status: source implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
- 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.