diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-13 20:05:32 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-13 20:05:32 -0500 |
| commit | 934f98d7e8123892bd9ca8ea08728ee0784e6597 (patch) | |
| tree | 1a73064970020d945ca5f2c31ce420021b99e94c | |
| parent | f3996e6ac6e2bd739d8a82cc9acae0653c2d5dca (diff) | |
| parent | 222e684ca762e9288108fcf852eb5d08cbe10ae3 (diff) | |
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
| -rw-r--r-- | drivers/vfio/Kconfig | 15 | ||||
| -rw-r--r-- | drivers/vfio/pci/vfio_pci.c | 8 | ||||
| -rw-r--r-- | drivers/vfio/pci/vfio_pci_config.c | 74 | ||||
| -rw-r--r-- | drivers/vfio/platform/Makefile | 6 | ||||
| -rw-r--r-- | drivers/vfio/platform/reset/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/vfio/platform/reset/Makefile | 2 | ||||
| -rw-r--r-- | drivers/vfio/platform/reset/vfio_platform_amdxgbe.c | 127 | ||||
| -rw-r--r-- | drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c | 19 | ||||
| -rw-r--r-- | drivers/vfio/platform/vfio_amba.c | 1 | ||||
| -rw-r--r-- | drivers/vfio/platform/vfio_platform.c | 1 | ||||
| -rw-r--r-- | drivers/vfio/platform/vfio_platform_common.c | 155 | ||||
| -rw-r--r-- | drivers/vfio/platform/vfio_platform_irq.c | 1 | ||||
| -rw-r--r-- | drivers/vfio/platform/vfio_platform_private.h | 40 | ||||
| -rw-r--r-- | drivers/vfio/vfio.c | 224 | ||||
| -rw-r--r-- | drivers/vfio/vfio_iommu_type1.c | 15 | ||||
| -rw-r--r-- | include/linux/vfio.h | 3 | ||||
| -rw-r--r-- | include/uapi/linux/vfio.h | 7 |
17 files changed, 616 insertions, 90 deletions
diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig index 850d86ca685b..da6e2ce77495 100644 --- a/drivers/vfio/Kconfig +++ b/drivers/vfio/Kconfig | |||
| @@ -31,6 +31,21 @@ menuconfig VFIO | |||
| 31 | 31 | ||
| 32 | If you don't know what to do here, say N. | 32 | If you don't know what to do here, say N. |
| 33 | 33 | ||
| 34 | menuconfig VFIO_NOIOMMU | ||
| 35 | bool "VFIO No-IOMMU support" | ||
| 36 | depends on VFIO | ||
| 37 | help | ||
| 38 | VFIO is built on the ability to isolate devices using the IOMMU. | ||
| 39 | Only with an IOMMU can userspace access to DMA capable devices be | ||
| 40 | considered secure. VFIO No-IOMMU mode enables IOMMU groups for | ||
| 41 | devices without IOMMU backing for the purpose of re-using the VFIO | ||
| 42 | infrastructure in a non-secure mode. Use of this mode will result | ||
| 43 | in an unsupportable kernel and will therefore taint the kernel. | ||
| 44 | Device assignment to virtual machines is also not possible with | ||
| 45 | this mode since there is no IOMMU to provide DMA translation. | ||
| 46 | |||
| 47 | If you don't know what to do here, say N. | ||
| 48 | |||
| 34 | source "drivers/vfio/pci/Kconfig" | 49 | source "drivers/vfio/pci/Kconfig" |
| 35 | source "drivers/vfio/platform/Kconfig" | 50 | source "drivers/vfio/platform/Kconfig" |
| 36 | source "virt/lib/Kconfig" | 51 | source "virt/lib/Kconfig" |
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 964ad572aaee..32b88bd2c82c 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c | |||
| @@ -940,13 +940,13 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 940 | if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL) | 940 | if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL) |
| 941 | return -EINVAL; | 941 | return -EINVAL; |
| 942 | 942 | ||
| 943 | group = iommu_group_get(&pdev->dev); | 943 | group = vfio_iommu_group_get(&pdev->dev); |
| 944 | if (!group) | 944 | if (!group) |
| 945 | return -EINVAL; | 945 | return -EINVAL; |
| 946 | 946 | ||
| 947 | vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); | 947 | vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); |
| 948 | if (!vdev) { | 948 | if (!vdev) { |
| 949 | iommu_group_put(group); | 949 | vfio_iommu_group_put(group, &pdev->dev); |
| 950 | return -ENOMEM; | 950 | return -ENOMEM; |
| 951 | } | 951 | } |
| 952 | 952 | ||
| @@ -957,7 +957,7 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 957 | 957 | ||
| 958 | ret = vfio_add_group_dev(&pdev->dev, &vfio_pci_ops, vdev); | 958 | ret = vfio_add_group_dev(&pdev->dev, &vfio_pci_ops, vdev); |
| 959 | if (ret) { | 959 | if (ret) { |
| 960 | iommu_group_put(group); | 960 | vfio_iommu_group_put(group, &pdev->dev); |
| 961 | kfree(vdev); | 961 | kfree(vdev); |
| 962 | return ret; | 962 | return ret; |
| 963 | } | 963 | } |
| @@ -993,7 +993,7 @@ static void vfio_pci_remove(struct pci_dev *pdev) | |||
| 993 | if (!vdev) | 993 | if (!vdev) |
| 994 | return; | 994 | return; |
| 995 | 995 | ||
| 996 | iommu_group_put(pdev->dev.iommu_group); | 996 | vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev); |
| 997 | kfree(vdev); | 997 | kfree(vdev); |
| 998 | 998 | ||
| 999 | if (vfio_pci_is_vga(pdev)) { | 999 | if (vfio_pci_is_vga(pdev)) { |
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c index ff75ca31a199..fe2b470d7ec6 100644 --- a/drivers/vfio/pci/vfio_pci_config.c +++ b/drivers/vfio/pci/vfio_pci_config.c | |||
| @@ -46,7 +46,7 @@ | |||
| 46 | * 0: Removed from the user visible capability list | 46 | * 0: Removed from the user visible capability list |
| 47 | * FF: Variable length | 47 | * FF: Variable length |
| 48 | */ | 48 | */ |
| 49 | static u8 pci_cap_length[] = { | 49 | static const u8 pci_cap_length[PCI_CAP_ID_MAX + 1] = { |
| 50 | [PCI_CAP_ID_BASIC] = PCI_STD_HEADER_SIZEOF, /* pci config header */ | 50 | [PCI_CAP_ID_BASIC] = PCI_STD_HEADER_SIZEOF, /* pci config header */ |
| 51 | [PCI_CAP_ID_PM] = PCI_PM_SIZEOF, | 51 | [PCI_CAP_ID_PM] = PCI_PM_SIZEOF, |
| 52 | [PCI_CAP_ID_AGP] = PCI_AGP_SIZEOF, | 52 | [PCI_CAP_ID_AGP] = PCI_AGP_SIZEOF, |
| @@ -74,7 +74,7 @@ static u8 pci_cap_length[] = { | |||
| 74 | * 0: Removed or masked from the user visible capabilty list | 74 | * 0: Removed or masked from the user visible capabilty list |
| 75 | * FF: Variable length | 75 | * FF: Variable length |
| 76 | */ | 76 | */ |
| 77 | static u16 pci_ext_cap_length[] = { | 77 | static const u16 pci_ext_cap_length[PCI_EXT_CAP_ID_MAX + 1] = { |
| 78 | [PCI_EXT_CAP_ID_ERR] = PCI_ERR_ROOT_COMMAND, | 78 | [PCI_EXT_CAP_ID_ERR] = PCI_ERR_ROOT_COMMAND, |
| 79 | [PCI_EXT_CAP_ID_VC] = 0xFF, | 79 | [PCI_EXT_CAP_ID_VC] = 0xFF, |
| 80 | [PCI_EXT_CAP_ID_DSN] = PCI_EXT_CAP_DSN_SIZEOF, | 80 | [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) | |||
| 671 | return 0; | 671 | return 0; |
| 672 | } | 672 | } |
| 673 | 673 | ||
| 674 | static int vfio_vpd_config_write(struct vfio_pci_device *vdev, int pos, | ||
| 675 | int count, struct perm_bits *perm, | ||
| 676 | int offset, __le32 val) | ||
| 677 | { | ||
| 678 | struct pci_dev *pdev = vdev->pdev; | ||
| 679 | __le16 *paddr = (__le16 *)(vdev->vconfig + pos - offset + PCI_VPD_ADDR); | ||
| 680 | __le32 *pdata = (__le32 *)(vdev->vconfig + pos - offset + PCI_VPD_DATA); | ||
| 681 | u16 addr; | ||
| 682 | u32 data; | ||
| 683 | |||
| 684 | /* | ||
| 685 | * Write through to emulation. If the write includes the upper byte | ||
| 686 | * of PCI_VPD_ADDR, then the PCI_VPD_ADDR_F bit is written and we | ||
| 687 | * have work to do. | ||
| 688 | */ | ||
| 689 | count = vfio_default_config_write(vdev, pos, count, perm, offset, val); | ||
| 690 | if (count < 0 || offset > PCI_VPD_ADDR + 1 || | ||
| 691 | offset + count <= PCI_VPD_ADDR + 1) | ||
| 692 | return count; | ||
| 693 | |||
| 694 | addr = le16_to_cpu(*paddr); | ||
| 695 | |||
| 696 | if (addr & PCI_VPD_ADDR_F) { | ||
| 697 | data = le32_to_cpu(*pdata); | ||
| 698 | if (pci_write_vpd(pdev, addr & ~PCI_VPD_ADDR_F, 4, &data) != 4) | ||
| 699 | return count; | ||
| 700 | } else { | ||
| 701 | if (pci_read_vpd(pdev, addr, 4, &data) != 4) | ||
| 702 | return count; | ||
| 703 | *pdata = cpu_to_le32(data); | ||
| 704 | } | ||
| 705 | |||
| 706 | /* | ||
| 707 | * Toggle PCI_VPD_ADDR_F in the emulated PCI_VPD_ADDR register to | ||
| 708 | * signal completion. If an error occurs above, we assume that not | ||
| 709 | * toggling this bit will induce a driver timeout. | ||
| 710 | */ | ||
| 711 | addr ^= PCI_VPD_ADDR_F; | ||
| 712 | *paddr = cpu_to_le16(addr); | ||
| 713 | |||
| 714 | return count; | ||
| 715 | } | ||
| 716 | |||
| 717 | /* Permissions for Vital Product Data capability */ | ||
| 718 | static int __init init_pci_cap_vpd_perm(struct perm_bits *perm) | ||
| 719 | { | ||
| 720 | if (alloc_perm_bits(perm, pci_cap_length[PCI_CAP_ID_VPD])) | ||
| 721 | return -ENOMEM; | ||
| 722 | |||
| 723 | perm->writefn = vfio_vpd_config_write; | ||
| 724 | |||
| 725 | /* | ||
| 726 | * We always virtualize the next field so we can remove | ||
| 727 | * capabilities from the chain if we want to. | ||
| 728 | */ | ||
| 729 | p_setb(perm, PCI_CAP_LIST_NEXT, (u8)ALL_VIRT, NO_WRITE); | ||
| 730 | |||
| 731 | /* | ||
| 732 | * Both the address and data registers are virtualized to | ||
| 733 | * enable access through the pci_vpd_read/write functions | ||
| 734 | */ | ||
| 735 | p_setw(perm, PCI_VPD_ADDR, (u16)ALL_VIRT, (u16)ALL_WRITE); | ||
| 736 | p_setd(perm, PCI_VPD_DATA, ALL_VIRT, ALL_WRITE); | ||
| 737 | |||
| 738 | return 0; | ||
| 739 | } | ||
| 740 | |||
| 674 | /* Permissions for PCI-X capability */ | 741 | /* Permissions for PCI-X capability */ |
| 675 | static int __init init_pci_cap_pcix_perm(struct perm_bits *perm) | 742 | static int __init init_pci_cap_pcix_perm(struct perm_bits *perm) |
| 676 | { | 743 | { |
| @@ -790,6 +857,7 @@ void vfio_pci_uninit_perm_bits(void) | |||
| 790 | free_perm_bits(&cap_perms[PCI_CAP_ID_BASIC]); | 857 | free_perm_bits(&cap_perms[PCI_CAP_ID_BASIC]); |
