// SPDX-License-Identifier: GPL-2.0-only /* * VFIO PCI I/O Port & MMIO access * * 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
*/
/* * Read or write from an __iomem region (MMIO or I/O port) with an excluded * range which is inaccessible. The excluded range drops writes and fills * reads with -1. This is intended for handling MSI-X vector tables and * leftover space for ROM BARs.
*/
ssize_t vfio_pci_core_do_io_rw(struct vfio_pci_core_device *vdev, bool test_mem, void __iomem *io, char __user *buf,
loff_t off, size_t count, size_t x_start,
size_t x_end, bool iswrite)
{
ssize_t done = 0; int ret;
if (pci_resource_start(pdev, bar))
end = pci_resource_len(pdev, bar); elseif (bar == PCI_ROM_RESOURCE && pdev->rom && pdev->romlen)
end = roundup_pow_of_two(pdev->romlen); else return -EINVAL;
if (pos >= end) return -EINVAL;
count = min(count, (size_t)(end - pos));
if (bar == PCI_ROM_RESOURCE) { /* * The ROM can fill less space than the BAR, so we start the * excluded range at the end of the actual ROM. This makes * filling large ROM BARs much faster.
*/ if (pci_resource_start(pdev, bar)) {
io = pci_map_rom(pdev, &x_start);
} else {
io = ioremap(pdev->rom, pdev->romlen);
x_start = pdev->romlen;
} if (!io) return -ENOMEM;
x_end = end;
} else { int ret = vfio_pci_core_setup_barmap(vdev, bar); if (ret) {
done = ret; goto out;
}
ret = vga_get_interruptible(vdev->pdev, rsrc); if (ret) {
is_ioport ? ioport_unmap(iomem) : iounmap(iomem); return ret;
}
/* * VGA MMIO is a legacy, non-BAR resource that hopefully allows * probing, so we don't currently worry about access in relation * to the memory enable bit in the command register.
*/
done = vfio_pci_core_do_io_rw(vdev, false, iomem, buf, off, count,
0, 0, iswrite);
vga_put(vdev->pdev, rsrc);
is_ioport ? ioport_unmap(iomem) : iounmap(iomem);
if (done >= 0)
*ppos += done;
return done;
} #endif
staticvoid vfio_pci_ioeventfd_do_write(struct vfio_pci_ioeventfd *ioeventfd, bool test_mem)
{ switch (ioeventfd->count) { case 1:
vfio_pci_core_iowrite8(ioeventfd->vdev, test_mem,
ioeventfd->data, ioeventfd->addr); break; case 2:
vfio_pci_core_iowrite16(ioeventfd->vdev, test_mem,
ioeventfd->data, ioeventfd->addr); break; case 4:
vfio_pci_core_iowrite32(ioeventfd->vdev, test_mem,
ioeventfd->data, ioeventfd->addr); break; case 8:
vfio_pci_core_iowrite64(ioeventfd->vdev, test_mem,
ioeventfd->data, ioeventfd->addr); break;
}
}
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.