/*
* VFIO PCI config space virtualization
*
* Copyright (C) 2012 Red Hat, Inc. All rights reserved.
* Author: Alex Williamson <alex.williamson@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#include <linux/fs.h>
#include <linux/pci.h>
#include <linux/uaccess.h>
#include <linux/vfio.h>
#include <linux/slab.h>
#include "vfio_pci_private.h"
#define PCI_CFG_SPACE_SIZE 256
/* Useful "pseudo" capabilities */
#define PCI_CAP_ID_BASIC 0
#define PCI_CAP_ID_INVALID 0xFF
#define is_bar(offset) \
((offset >= PCI_BASE_ADDRESS_0 && offset < PCI_BASE_ADDRESS_5 + 4) || \
(offset >= PCI_ROM_ADDRESS && offset < PCI_ROM_ADDRESS + 4))
/*
* 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,
|