linux/drivers/vfio/pci/vfio_pci_config.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * VFIO PCI config space virtualization
 *
 * Copyright (C) 2012 Red Hat, Inc.  All rights reserved.
 *     Author: Alex Williamson <[email protected]>
 *
 * Derived from original vfio:
 * Copyright 2010 Cisco Systems, Inc.  All rights reserved.
 * Author: Tom Lyon, [email protected]
 */

/*
 * 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_priv.h"

/* Fake capability ID for standard config space */
#define PCI_CAP_ID_BASIC

#define is_bar(offset)

/*
 * 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] =;

/*
 * 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] =;

/*
 * Read/Write Permission Bits - one bit for each bit in capability
 * Any field can be read if it exists, but what is read depends on
 * whether the field is 'virtualized', or just pass through to the
 * hardware.  Any virtualized field is also virtualized for writes.
 * Writes are only permitted if they have a 1 bit here.
 */
struct perm_bits {};

#define NO_VIRT
#define ALL_VIRT
#define NO_WRITE
#define ALL_WRITE

static int vfio_user_config_read(struct pci_dev *pdev, int offset,
				 __le32 *val, int count)
{}

static int vfio_user_config_write(struct pci_dev *pdev, int offset,
				  __le32 val, int count)
{}

static int vfio_default_config_read(struct vfio_pci_core_device *vdev, int pos,
				    int count, struct perm_bits *perm,
				    int offset, __le32 *val)
{}

static int vfio_default_config_write(struct vfio_pci_core_device *vdev, int pos,
				     int count, struct perm_bits *perm,
				     int offset, __le32 val)
{}

/* Allow direct read from hardware, except for capability next pointer */
static int vfio_direct_config_read(struct vfio_pci_core_device *vdev, int pos,
				   int count, struct perm_bits *perm,
				   int offset, __le32 *val)
{}

/* Raw access skips any kind of virtualization */
static int vfio_raw_config_write(struct vfio_pci_core_device *vdev, int pos,
				 int count, struct perm_bits *perm,
				 int offset, __le32 val)
{}

static int vfio_raw_config_read(struct vfio_pci_core_device *vdev, int pos,
				int count, struct perm_bits *perm,
				int offset, __le32 *val)
{}

/* Virt access uses only virtualization */
static int vfio_virt_config_write(struct vfio_pci_core_device *vdev, int pos,
				  int count, struct perm_bits *perm,
				  int offset, __le32 val)
{}

static int vfio_virt_config_read(struct vfio_pci_core_device *vdev, int pos,
				 int count, struct perm_bits *perm,
				 int offset, __le32 *val)
{}

/* Default capability regions to read-only, no-virtualization */
static struct perm_bits cap_perms[PCI_CAP_ID_MAX + 1] =;
static struct perm_bits ecap_perms[PCI_EXT_CAP_ID_MAX + 1] =;
/*
 * Default unassigned regions to raw read-write access.  Some devices
 * require this to function as they hide registers between the gaps in
 * config space (be2net).  Like MMIO and I/O port registers, we have
 * to trust the hardware isolation.
 */
static struct perm_bits unassigned_perms =;

static struct perm_bits virt_perms =;

static void free_perm_bits(struct perm_bits *perm)
{}

static int alloc_perm_bits(struct perm_bits *perm, int size)
{}

/*
 * Helper functions for filling in permission tables
 */
static inline void p_setb(struct perm_bits *p, int off, u8 virt, u8 write)
{}

/* Handle endian-ness - pci and tables are little-endian */
static inline void p_setw(struct perm_bits *p, int off, u16 virt, u16 write)
{}

/* Handle endian-ness - pci and tables are little-endian */
static inline void p_setd(struct perm_bits *p, int off, u32 virt, u32 write)
{}

/* Caller should hold memory_lock semaphore */
bool __vfio_pci_memory_enabled(struct vfio_pci_core_device *vdev)
{}

/*
 * Restore the *real* BARs after we detect a FLR or backdoor reset.
 * (backdoor = some device specific technique that we didn't catch)
 */
static void vfio_bar_restore(struct vfio_pci_core_device *vdev)
{}

static __le32 vfio_generate_bar_flags(struct pci_dev *pdev, int bar)
{}

/*
 * Pretend we're hardware and tweak the values of the *virtual* PCI BARs
 * to reflect the hardware capabilities.  This implements BAR sizing.
 */
static void vfio_bar_fixup(struct vfio_pci_core_device *vdev)
{}

static int vfio_basic_config_read(struct vfio_pci_core_device *vdev, int pos,
				  int count, struct perm_bits *perm,
				  int offset, __le32 *val)
{}

/* Test whether BARs match the value we think they should contain */
static bool vfio_need_bar_restore(struct vfio_pci_core_device *vdev)
{}

static int vfio_basic_config_write(struct vfio_pci_core_device *vdev, int pos,
				   int count, struct perm_bits *perm,
				   int offset, __le32 val)
{}

/* Permissions for the Basic PCI Header */
static int __init init_pci_cap_basic_perm(struct perm_bits *perm)
{}

/*
 * It takes all the required locks to protect the access of power related
 * variables and then invokes vfio_pci_set_power_state().
 */
static void vfio_lock_and_set_power_state(struct vfio_pci_core_device *vdev,
					  pci_power_t state)
{}

static int vfio_pm_config_write(struct vfio_pci_core_device *vdev, int pos,
				int count, struct perm_bits *perm,
				int offset, __le32 val)
{}

/* Permissions for the Power Management capability */
static int __init init_pci_cap_pm_perm(struct perm_bits *perm)
{}

static int vfio_vpd_config_write(struct vfio_pci_core_device *vdev, int pos,
				 int count, struct perm_bits *perm,
				 int offset, __le32 val)
{}

/* Permissions for Vital Product Data capability */
static int __init init_pci_cap_vpd_perm(struct perm_bits *perm)
{}

/* Permissions for PCI-X capability */
static int __init init_pci_cap_pcix_perm(struct perm_bits *perm)
{}

static int vfio_exp_config_write(struct vfio_pci_core_device *vdev, int pos,
				 int count, struct perm_bits *perm,
				 int offset, __le32 val)
{}

/* Permissions for PCI Express capability */
static int __init init_pci_cap_exp_perm(struct perm_bits *perm)
{}

static int vfio_af_config_write(struct vfio_pci_core_device *vdev, int pos,
				int count, struct perm_bits *perm,
				int offset, __le32 val)
{}

/* Permissions for Advanced Function capability */
static int __init init_pci_cap_af_perm(struct perm_bits *perm)
{}

/* Permissions for Advanced Error Reporting extended capability */
static int __init init_pci_ext_cap_err_perm(struct perm_bits *perm)
{}

/* Permissions for Power Budgeting extended capability */
static int __init init_pci_ext_cap_pwr_perm(struct perm_bits *perm)
{}

/*
 * Initialize the shared permission tables
 */
void vfio_pci_uninit_perm_bits(void)
{}

int __init vfio_pci_init_perm_bits(void)
{}

static int vfio_find_cap_start(struct vfio_pci_core_device *vdev, int pos)
{}

static int vfio_msi_config_read(struct vfio_pci_core_device *vdev, int pos,
				int count, struct perm_bits *perm,
				int offset, __le32 *val)
{}

static int vfio_msi_config_write(struct vfio_pci_core_device *vdev, int pos,
				 int count, struct perm_bits *perm,
				 int offset, __le32 val)
{}

/*
 * MSI determination is per-device, so this routine gets used beyond
 * initialization time. Don't add __init
 */
static int init_pci_cap_msi_perm(struct perm_bits *perm, int len, u16 flags)
{}

/* Determine MSI CAP field length; initialize msi_perms on 1st call per vdev */
static int vfio_msi_cap_len(struct vfio_pci_core_device *vdev, u8 pos)
{}

/* Determine extended capability length for VC (2 & 9) and MFVC */
static int vfio_vc_cap_len(struct vfio_pci_core_device *vdev, u16 pos)
{}

static int vfio_cap_len(struct vfio_pci_core_device *vdev, u8 cap, u8 pos)
{}

static int vfio_ext_cap_len(struct vfio_pci_core_device *vdev, u16 ecap, u16 epos)
{}

static void vfio_update_pm_vconfig_bytes(struct vfio_pci_core_device *vdev,
					 int offset)
{}

static int vfio_fill_vconfig_bytes(struct vfio_pci_core_device *vdev,
				   int offset, int size)
{}

static int vfio_cap_init(struct vfio_pci_core_device *vdev)
{}

static int vfio_ecap_init(struct vfio_pci_core_device *vdev)
{}

/*
 * Nag about hardware bugs, hopefully to have vendors fix them, but at least
 * to collect a list of dependencies for the VF INTx pin quirk below.
 */
static const struct pci_device_id known_bogus_vf_intx_pin[] =;

/*
 * For each device we allocate a pci_config_map that indicates the
 * capability occupying each dword and thus the struct perm_bits we
 * use for read and write.  We also allocate a virtualized config
 * space which tracks reads and writes to bits that we emulate for
 * the user.  Initial values filled from device.
 *
 * Using shared struct perm_bits between all vfio-pci devices saves
 * us from allocating cfg_size buffers for virt and write for every
 * device.  We could remove vconfig and allocate individual buffers
 * for each area requiring emulated bits, but the array of pointers
 * would be comparable in size (at least for standard config space).
 */
int vfio_config_init(struct vfio_pci_core_device *vdev)
{}

void vfio_config_free(struct vfio_pci_core_device *vdev)
{}

/*
 * Find the remaining number of bytes in a dword that match the given
 * position.  Stop at either the end of the capability or the dword boundary.
 */
static size_t vfio_pci_cap_remaining_dword(struct vfio_pci_core_device *vdev,
					   loff_t pos)
{}

static ssize_t vfio_config_do_rw(struct vfio_pci_core_device *vdev, char __user *buf,
				 size_t count, loff_t *ppos, bool iswrite)
{}

ssize_t vfio_pci_config_rw(struct vfio_pci_core_device *vdev, char __user *buf,
			   size_t count, loff_t *ppos, bool iswrite)
{}

/**
 * vfio_pci_core_range_intersect_range() - Determine overlap between a buffer
 *					   and register offset ranges.
 * @buf_start:		start offset of the buffer
 * @buf_cnt:		number of buffer bytes
 * @reg_start:		start register offset
 * @reg_cnt:		number of register bytes
 * @buf_offset:	start offset of overlap in the buffer
 * @intersect_count:	number of overlapping bytes
 * @register_offset:	start offset of overlap in register
 *
 * Returns: true if there is overlap, false if not.
 * The overlap start and size is returned through function args.
 */
bool vfio_pci_core_range_intersect_range(loff_t buf_start, size_t buf_cnt,
					 loff_t reg_start, size_t reg_cnt,
					 loff_t *buf_offset,
					 size_t *intersect_count,
					 size_t *register_offset)
{}
EXPORT_SYMBOL_GPL();