Source
static ssize_t vfio_config_do_rw(struct vfio_pci_device *vdev, char __user *buf,
// SPDX-License-Identifier: GPL-2.0-only
/*
* VFIO PCI config space virtualization
*
* 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
*/
/*
* This code handles reading and writing of PCI configuration registers.
* This is hairy because we want to allow a lot of flexibility to the
* user driver, but cannot trust it with all of the config fields.
* Tables determine which fields can be read and written, as well as
* which fields are 'virtualized' - special actions and translations to
* make it appear to the user that he has control, when in fact things
* must be negotiated with the underlying OS.
*/
/* Fake capability ID for standard config space */
/*
* Lengths of PCI Config Capabilities
* 0: Removed from the user visible capability list
* FF: Variable length
*/
static const u8 pci_cap_length[PCI_CAP_ID_MAX + 1] = {
[PCI_CAP_ID_BASIC] = PCI_STD_HEADER_SIZEOF, /* pci config header */
[PCI_CAP_ID_PM] = PCI_PM_SIZEOF,
[PCI_CAP_ID_AGP] = PCI_AGP_SIZEOF,
[PCI_CAP_ID_VPD] = PCI_CAP_VPD_SIZEOF,
[PCI_CAP_ID_SLOTID] = 0, /* bridge - don't care */
[PCI_CAP_ID_MSI] = 0xFF, /* 10, 14, 20, or 24 */
[PCI_CAP_ID_CHSWP] = 0, /* cpci - not yet */
[PCI_CAP_ID_PCIX] = 0xFF, /* 8 or 24 */
[PCI_CAP_ID_HT] = 0xFF, /* hypertransport */
[PCI_CAP_ID_VNDR] = 0xFF, /* variable */
[PCI_CAP_ID_DBG] = 0, /* debug - don't care */
[PCI_CAP_ID_CCRC] = 0, /* cpci - not yet */
[PCI_CAP_ID_SHPC] = 0, /* hotswap - not yet */
[PCI_CAP_ID_SSVID] = 0, /* bridge - don't care */
[PCI_CAP_ID_AGP3] = 0, /* AGP8x - not yet */
[PCI_CAP_ID_SECDEV] = 0, /* secure device not yet */
[PCI_CAP_ID_EXP] = 0xFF, /* 20 or 44 */
[PCI_CAP_ID_MSIX] = PCI_CAP_MSIX_SIZEOF,
[PCI_CAP_ID_SATA] = 0xFF,
[PCI_CAP_ID_AF] = PCI_CAP_AF_SIZEOF,
};
/*
* Lengths of PCIe/PCI-X Extended Config Capabilities
* 0: Removed or masked from the user visible capability list
* FF: Variable length
*/
static const u16 pci_ext_cap_length[PCI_EXT_CAP_ID_MAX + 1] = {
[PCI_EXT_CAP_ID_ERR] = PCI_ERR_ROOT_COMMAND,
[PCI_EXT_CAP_ID_VC] = 0xFF,
[PCI_EXT_CAP_ID_DSN] = PCI_EXT_CAP_DSN_SIZEOF,
[PCI_EXT_CAP_ID_PWR] = PCI_EXT_CAP_PWR_SIZEOF,
[PCI_EXT_CAP_ID_RCLD] = 0, /* root only - don't care */
[PCI_EXT_CAP_ID_RCILC] = 0, /* root only - don't care */
[PCI_EXT_CAP_ID_RCEC] = 0, /* root only - don't care */
[PCI_EXT_CAP_ID_MFVC] = 0xFF,
[PCI_EXT_CAP_ID_VC9] = 0xFF, /* same as CAP_ID_VC */
[PCI_EXT_CAP_ID_RCRB] = 0, /* root only - don't care */
[PCI_EXT_CAP_ID_VNDR] = 0xFF,
[PCI_EXT_CAP_ID_CAC] = 0, /* obsolete */
[PCI_EXT_CAP_ID_ACS] = 0xFF,
[PCI_EXT_CAP_ID_ARI] = PCI_EXT_CAP_ARI_SIZEOF,
[PCI_EXT_CAP_ID_ATS] = PCI_EXT_CAP_ATS_SIZEOF,
[PCI_EXT_CAP_ID_SRIOV] = PCI_EXT_CAP_SRIOV_SIZEOF,
[PCI_EXT_CAP_ID_MRIOV] = 0, /* not yet */
[PCI_EXT_CAP_ID_MCAST] = PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF,
[PCI_EXT_CAP_ID_PRI] = PCI_EXT_CAP_PRI_SIZEOF,
[PCI_EXT_CAP_ID_AMD_XXX] = 0, /* not yet */
[PCI_EXT_CAP_ID_REBAR] = 0xFF,