aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vfio
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2015-04-07 13:14:41 -0400
committerAlex Williamson <alex.williamson@redhat.com>2015-04-07 13:14:41 -0400
commitecaa1f6a01544604de5f9531379a303eee886162 (patch)
tree8d83dec6854b9b3246fab77601c448a5176d572d /drivers/vfio
parent88c0dead9fb2cc66962b64064770558eecf3eafd (diff)
vfio-pci: Add VGA arbiter client
If VFIO VGA access is disabled for the user, either by CONFIG option or module parameter, we can often opt-out of VGA arbitration. We can do this when PCI bridge control of VGA routing is possible. This means that we must have a parent bridge and there must only be a single VGA device below that bridge. Fortunately this is the typical case for discrete GPUs. Doing this allows us to minimize the impact of additional GPUs, in terms of VGA arbitration, when they are only used via vfio-pci for non-VGA applications. Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Diffstat (limited to 'drivers/vfio')
-rw-r--r--drivers/vfio/pci/vfio_pci.c67
1 files changed, 63 insertions, 4 deletions
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 7053110e4734..25aef05b8692 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -25,6 +25,7 @@
25#include <linux/types.h> 25#include <linux/types.h>
26#include <linux/uaccess.h> 26#include <linux/uaccess.h>
27#include <linux/vfio.h> 27#include <linux/vfio.h>
28#include <linux/vgaarb.h>
28 29
29#include "vfio_pci_private.h" 30#include "vfio_pci_private.h"
30 31
@@ -54,6 +55,50 @@ static inline bool vfio_vga_disabled(void)
54#endif 55#endif
55} 56}
56 57
58/*
59 * Our VGA arbiter participation is limited since we don't know anything
60 * about the device itself. However, if the device is the only VGA device
61 * downstream of a bridge and VFIO VGA support is disabled, then we can
62 * safely return legacy VGA IO and memory as not decoded since the user
63 * has no way to get to it and routing can be disabled externally at the
64 * bridge.
65 */
66static unsigned int vfio_pci_set_vga_decode(void *opaque, bool single_vga)
67{
68 struct vfio_pci_device *vdev = opaque;
69 struct pci_dev *tmp = NULL, *pdev = vdev->pdev;
70 unsigned char max_busnr;
71 unsigned int decodes;
72
73 if (single_vga || !vfio_vga_disabled() || pci_is_root_bus(pdev->bus))
74 return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM |
75 VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM;
76
77 max_busnr = pci_bus_max_busnr(pdev->bus);
78 decodes = VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
79
80 while ((tmp = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, tmp)) != NULL) {
81 if (tmp == pdev ||
82 pci_domain_nr(tmp->bus) != pci_domain_nr(pdev->bus) ||
83 pci_is_root_bus(tmp->bus))
84 continue;
85
86 if (tmp->bus->number >= pdev->bus->number &&
87 tmp->bus->number <= max_busnr) {
88 pci_dev_put(tmp);
89 decodes |= VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM;
90 break;
91 }
92 }
93
94 return decodes;
95}
96
97static inline bool vfio_pci_is_vga(struct pci_dev *pdev)
98{
99 return (pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA;
100}
101
57static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev); 102static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev);
58 103
59static int vfio_pci_enable(struct vfio_pci_device *vdev) 104static int vfio_pci_enable(struct vfio_pci_device *vdev)
@@ -108,7 +153,7 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
108 } else 153 } else
109 vdev->msix_bar = 0xFF; 154 vdev->msix_bar = 0xFF;
110 155
111 if (!vfio_vga_disabled() && (pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) 156 if (!vfio_vga_disabled() && vfio_pci_is_vga(pdev))
112 vdev->has_vga = true; 157 vdev->has_vga = true;
113 158
114 return 0; 159 return 0;
@@ -900,6 +945,12 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
900 kfree(vdev); 945 kfree(vdev);
901 } 946 }
902 947
948 if (vfio_pci_is_vga(pdev)) {
949 vga_client_register(pdev, vdev, NULL, vfio_pci_set_vga_decode);
950 vga_set_legacy_decoding(pdev,
951 vfio_pci_set_vga_decode(vdev, false));
952 }
953
903 return ret; 954 return ret;
904} 955}
905 956
@@ -908,9 +959,17 @@ static void vfio_pci_remove(struct pci_dev *pdev)
908 struct vfio_pci_device *vdev; 959 struct vfio_pci_device *vdev;
909 960
910 vdev = vfio_del_group_dev(&pdev->dev); 961 vdev = vfio_del_group_dev(&pdev->dev);
911 if (vdev) { 962 if (!vdev)
912 iommu_group_put(pdev->dev.iommu_group); 963 return;
913 kfree(vdev); 964
965 iommu_group_put(pdev->dev.iommu_group);
966 kfree(vdev);
967
968 if (vfio_pci_is_vga(pdev)) {
969 vga_client_register(pdev, NULL, NULL, NULL);
970 vga_set_legacy_decoding(pdev,
971 VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM |
972 VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM);
914 } 973 }
915} 974}
916 975