Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 934f98d7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'vfio-v4.4-rc1' of git://github.com/awilliam/linux-vfio

Pull VFIO updates from Alex Williamson:
 - Use kernel interfaces for VPD emulation (Alex Williamson)
 - Platform fix for releasing IRQs (Eric Auger)
 - Type1 IOMMU always advertises PAGE_SIZE support when smaller mapping
   sizes are available (Eric Auger)
 - Platform fixes for incorrectly using copies of structures rather than
   pointers to structures (James Morse)
 - Rework platform reset modules, fix leak, and add AMD xgbe reset
   module (Eric Auger)
 - Fix vfio_device_get_from_name() return value (Joerg Roedel)
 - No-IOMMU interface (Alex Williamson)
 - Fix potential out of bounds array access in PCI config handling (Dan
   Carpenter)

* tag 'vfio-v4.4-rc1' of git://github.com/awilliam/linux-vfio:
  vfio/pci: make an array larger
  vfio: Include No-IOMMU mode
  vfio: Fix bug in vfio_device_get_from_name()
  VFIO: platform: reset: AMD xgbe reset module
  vfio: platform: reset: calxedaxgmac: fix ioaddr leak
  vfio: platform: add dev_info on device reset
  vfio: platform: use list of registered reset function
  vfio: platform: add compat in vfio_platform_device
  vfio: platform: reset: calxedaxgmac: add reset function registration
  vfio: platform: introduce module_vfio_reset_handler macro
  vfio: platform: add capability to register a reset function
  vfio: platform: introduce vfio-platform-base module
  vfio/platform: store mapped memory in region, instead of an on-stack copy
  vfio/type1: handle case where IOMMU does not support PAGE_SIZE size
  VFIO: platform: clear IRQ_NOAUTOEN when de-assigning the IRQ
  vfio/pci: Use kernel VPD access functions
  vfio: Whitelist PCI bridges
parents f3996e6a 222e684c
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -31,6 +31,21 @@ menuconfig VFIO

	  If you don't know what to do here, say N.

menuconfig VFIO_NOIOMMU
	bool "VFIO No-IOMMU support"
	depends on VFIO
	help
	  VFIO is built on the ability to isolate devices using the IOMMU.
	  Only with an IOMMU can userspace access to DMA capable devices be
	  considered secure.  VFIO No-IOMMU mode enables IOMMU groups for
	  devices without IOMMU backing for the purpose of re-using the VFIO
	  infrastructure in a non-secure mode.  Use of this mode will result
	  in an unsupportable kernel and will therefore taint the kernel.
	  Device assignment to virtual machines is also not possible with
	  this mode since there is no IOMMU to provide DMA translation.

	  If you don't know what to do here, say N.

source "drivers/vfio/pci/Kconfig"
source "drivers/vfio/platform/Kconfig"
source "virt/lib/Kconfig"
+4 −4
Original line number Diff line number Diff line
@@ -940,13 +940,13 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
		return -EINVAL;

	group = iommu_group_get(&pdev->dev);
	group = vfio_iommu_group_get(&pdev->dev);
	if (!group)
		return -EINVAL;

	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
	if (!vdev) {
		iommu_group_put(group);
		vfio_iommu_group_put(group, &pdev->dev);
		return -ENOMEM;
	}

@@ -957,7 +957,7 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)

	ret = vfio_add_group_dev(&pdev->dev, &vfio_pci_ops, vdev);
	if (ret) {
		iommu_group_put(group);
		vfio_iommu_group_put(group, &pdev->dev);
		kfree(vdev);
		return ret;
	}
@@ -993,7 +993,7 @@ static void vfio_pci_remove(struct pci_dev *pdev)
	if (!vdev)
		return;

	iommu_group_put(pdev->dev.iommu_group);
	vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev);
	kfree(vdev);

	if (vfio_pci_is_vga(pdev)) {
+71 −3
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@
 *   0: Removed from the user visible capability list
 *   FF: Variable length
 */
static u8 pci_cap_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,
@@ -74,7 +74,7 @@ static u8 pci_cap_length[] = {
 *   0: Removed or masked from the user visible capabilty list
 *   FF: Variable length
 */
static u16 pci_ext_cap_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,
@@ -671,6 +671,73 @@ static int __init init_pci_cap_pm_perm(struct perm_bits *perm)
	return 0;
}

static int vfio_vpd_config_write(struct vfio_pci_device *vdev, int pos,
				 int count, struct perm_bits *perm,
				 int offset, __le32 val)
{
	struct pci_dev *pdev = vdev->pdev;
	__le16 *paddr = (__le16 *)(vdev->vconfig + pos - offset + PCI_VPD_ADDR);
	__le32 *pdata = (__le32 *)(vdev->vconfig + pos - offset + PCI_VPD_DATA);
	u16 addr;
	u32 data;

	/*
	 * Write through to emulation.  If the write includes the upper byte
	 * of PCI_VPD_ADDR, then the PCI_VPD_ADDR_F bit is written and we
	 * have work to do.
	 */
	count = vfio_default_config_write(vdev, pos, count, perm, offset, val);
	if (count < 0 || offset > PCI_VPD_ADDR + 1 ||
	    offset + count <= PCI_VPD_ADDR + 1)
		return count;

	addr = le16_to_cpu(*paddr);

	if (addr & PCI_VPD_ADDR_F) {
		data = le32_to_cpu(*pdata);
		if (pci_write_vpd(pdev, addr & ~PCI_VPD_ADDR_F, 4, &data) != 4)
			return count;
	} else {
		if (pci_read_vpd(pdev, addr, 4, &data) != 4)
			return count;
		*pdata = cpu_to_le32(data);
	}

	/*
	 * Toggle PCI_VPD_ADDR_F in the emulated PCI_VPD_ADDR register to
	 * signal completion.  If an error occurs above, we assume that not
	 * toggling this bit will induce a driver timeout.
	 */
	addr ^= PCI_VPD_ADDR_F;
	*paddr = cpu_to_le16(addr);

	return count;
}

/* Permissions for Vital Product Data capability */
static int __init init_pci_cap_vpd_perm(struct perm_bits *perm)
{
	if (alloc_perm_bits(perm, pci_cap_length[PCI_CAP_ID_VPD]))
		return -ENOMEM;

	perm->writefn = vfio_vpd_config_write;

	/*
	 * We always virtualize the next field so we can remove
	 * capabilities from the chain if we want to.
	 */
	p_setb(perm, PCI_CAP_LIST_NEXT, (u8)ALL_VIRT, NO_WRITE);

	/*
	 * Both the address and data registers are virtualized to
	 * enable access through the pci_vpd_read/write functions
	 */
	p_setw(perm, PCI_VPD_ADDR, (u16)ALL_VIRT, (u16)ALL_WRITE);
	p_setd(perm, PCI_VPD_DATA, ALL_VIRT, ALL_WRITE);

	return 0;
}

/* Permissions for PCI-X capability */
static int __init init_pci_cap_pcix_perm(struct perm_bits *perm)
{
@@ -790,6 +857,7 @@ void vfio_pci_uninit_perm_bits(void)
	free_perm_bits(&cap_perms[PCI_CAP_ID_BASIC]);

	free_perm_bits(&cap_perms[PCI_CAP_ID_PM]);
	free_perm_bits(&cap_perms[PCI_CAP_ID_VPD]);
	free_perm_bits(&cap_perms[PCI_CAP_ID_PCIX]);
	free_perm_bits(&cap_perms[PCI_CAP_ID_EXP]);
	free_perm_bits(&cap_perms[PCI_CAP_ID_AF]);
@@ -807,7 +875,7 @@ int __init vfio_pci_init_perm_bits(void)

	/* Capabilities */
	ret |= init_pci_cap_pm_perm(&cap_perms[PCI_CAP_ID_PM]);
	cap_perms[PCI_CAP_ID_VPD].writefn = vfio_raw_config_write;
	ret |= init_pci_cap_vpd_perm(&cap_perms[PCI_CAP_ID_VPD]);
	ret |= init_pci_cap_pcix_perm(&cap_perms[PCI_CAP_ID_PCIX]);
	cap_perms[PCI_CAP_ID_VNDR].writefn = vfio_raw_config_write;
	ret |= init_pci_cap_exp_perm(&cap_perms[PCI_CAP_ID_EXP]);
+4 −2
Original line number Diff line number Diff line

vfio-platform-y := vfio_platform.o vfio_platform_common.o vfio_platform_irq.o
vfio-platform-base-y := vfio_platform_common.o vfio_platform_irq.o
vfio-platform-y := vfio_platform.o

obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform-base.o
obj-$(CONFIG_VFIO_PLATFORM) += reset/

vfio-amba-y := vfio_amba.o

obj-$(CONFIG_VFIO_AMBA) += vfio-amba.o
obj-$(CONFIG_VFIO_AMBA) += vfio-platform-base.o
obj-$(CONFIG_VFIO_AMBA) += reset/
+8 −0
Original line number Diff line number Diff line
@@ -5,3 +5,11 @@ config VFIO_PLATFORM_CALXEDAXGMAC_RESET
	  Enables the VFIO platform driver to handle reset for Calxeda xgmac

	  If you don't know what to do here, say N.

config VFIO_PLATFORM_AMDXGBE_RESET
	tristate "VFIO support for AMD XGBE reset"
	depends on VFIO_PLATFORM
	help
	  Enables the VFIO platform driver to handle reset for AMD XGBE

	  If you don't know what to do here, say N.
Loading