History

vfio-pci: Add support for VGA region access

PCI defines display class VGA regions at I/O port address 0x3b0, 0x3c0 and MMIO address 0xa0000. As these are non-overlapping, we can ignore the I/O port vs MMIO difference and expose them both in a single region. We make use of the VGA arbiter around each access to configure chipset access as necessary.

Alex Williamson committed 13 years ago

Commit 84237a81 parent 2dd11945 files · +102 −0Browse files

Unified · Split

5 files
  1. drivers/vfio/pci/Kconfig +10 −0
  2. drivers/vfio/pci/vfio_pci.c +18 −0
  3. drivers/vfio/pci/vfio_pci_private.h +4 −0
  4. drivers/vfio/pci/vfio_pci_rdwr.c +61 −0
  5. include/uapi/linux/vfio.h +9 −0
drivers/vfio/pci/Kconfig+10−0
@@ -6,3 +6,13 @@ config VFIO_PCI · 5 unmodified lines
66 use of PCI drivers using the VFIO framework.
77
88 If you don't know what to do here, say N.
9+
10+config VFIO_PCI_VGA
11+ bool "VFIO PCI support for VGA devices"
12+ depends on VFIO_PCI && X86 && VGA_ARB && EXPERIMENTAL
13+ help
14+ Support for VGA extension to VFIO PCI. This exposes an additional
15+ region on VGA devices for accessing legacy VGA addresses used by
16+ BIOS and generic video drivers.
17+
18+ If you don't know what to do here, say N.
drivers/vfio/pci/vfio_pci.c+18−0
@@ -84,6 +84,11 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev) · 83 unmodified lines
8484 } else
8585 vdev->msix_bar = 0xFF;
8686
87+#ifdef CONFIG_VFIO_PCI_VGA
88+ if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
89+ vdev->has_vga = true;
90+#endif
91+
8792 return 0;
8893 }
8994
@@ -285,6 +290,16 @@ static long vfio_pci_ioctl(void *device_data, · 195 unmodified lines
285290 info.flags = VFIO_REGION_INFO_FLAG_READ;
286291 break;
287292 }
293+ case VFIO_PCI_VGA_REGION_INDEX:
294+ if (!vdev->has_vga)
295+ return -EINVAL;
296+
297+ info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
298+ info.size = 0xc0000;
299+ info.flags = VFIO_REGION_INFO_FLAG_READ |
300+ VFIO_REGION_INFO_FLAG_WRITE;
301+
302+ break;
288303 default:
289304 return -EINVAL;
290305 }
@@ -386,6 +401,9 @@ static ssize_t vfio_pci_rw(void *device_data, char __user *buf, · 95 unmodified lines
386401
387402 case VFIO_PCI_BAR0_REGION_INDEX ... VFIO_PCI_BAR5_REGION_INDEX:
388403 return vfio_pci_bar_rw(vdev, buf, count, ppos, iswrite);
404+
405+ case VFIO_PCI_VGA_REGION_INDEX:
406+ return vfio_pci_vga_rw(vdev, buf, count, ppos, iswrite);
389407 }
390408
391409 return -EINVAL;
drivers/vfio/pci/vfio_pci_private.h+4−0
@@ -53,6 +53,7 @@ struct vfio_pci_device { · 52 unmodified lines
5353 bool reset_works;
5454 bool extended_caps;
5555 bool bardirty;
56+ bool has_vga;
5657 struct pci_saved_state *pci_saved_state;
5758 atomic_t refcnt;
5859 };
@@ -77,6 +78,9 @@ extern ssize_t vfio_pci_config_rw(struct vfio_pci_device *vdev, · 18 unmodified lines
7778 extern ssize_t vfio_pci_bar_rw(struct vfio_pci_device *vdev, char __user *buf,
7879 size_t count, loff_t *ppos, bool iswrite);
7980
81+extern ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, char __user *buf,
82+ size_t count, loff_t *ppos, bool iswrite);
83+
8084 extern int vfio_pci_init_perm_bits(void);
8185 extern void vfio_pci_uninit_perm_bits(void);
8286
drivers/vfio/pci/vfio_pci_rdwr.c+61−0
@@ -17,6 +17,7 @@ · 16 unmodified lines
1717 #include <linux/pci.h>
1818 #include <linux/uaccess.h>
1919 #include <linux/io.h>
20+#include <linux/vgaarb.h>
2021
2122 #include "vfio_pci_private.h"
2223
@@ -175,3 +176,63 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_device *vdev, char __user *buf, · 152 unmodified lines
175176
176177 return done;
177178 }
179+
180+ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, char __user *buf,
181+ size_t count, loff_t *ppos, bool iswrite)
182+{
183+ int ret;
184+ loff_t off, pos = *ppos & VFIO_PCI_OFFSET_MASK;
185+ void __iomem *iomem = NULL;
186+ unsigned int rsrc;
187+ bool is_ioport;
188+ ssize_t done;
189+
190+ if (!vdev->has_vga)
191+ return -EINVAL;
192+
193+ switch (pos) {
194+ case 0xa0000 ... 0xbffff:
195+ count = min(count, (size_t)(0xc0000 - pos));
196+ iomem = ioremap_nocache(0xa0000, 0xbffff - 0xa0000 + 1);
197+ off = pos - 0xa0000;
198+ rsrc = VGA_RSRC_LEGACY_MEM;
199+ is_ioport = false;
200+ break;
201+ case 0x3b0 ... 0x3bb:
202+ count = min(count, (size_t)(0x3bc - pos));
203+ iomem = ioport_map(0x3b0, 0x3bb - 0x3b0 + 1);
204+ off = pos - 0x3b0;
205+ rsrc = VGA_RSRC_LEGACY_IO;
206+ is_ioport = true;
207+ break;
208+ case 0x3c0 ... 0x3df:
209+ count = min(count, (size_t)(0x3e0 - pos));
210+ iomem = ioport_map(0x3c0, 0x3df - 0x3c0 + 1);
211+ off = pos - 0x3c0;
212+ rsrc = VGA_RSRC_LEGACY_IO;
213+ is_ioport = true;
214+ break;
215+ default:
216+ return -EINVAL;
217+ }
218+
219+ if (!iomem)
220+ return -ENOMEM;
221+
222+ ret = vga_get_interruptible(vdev->pdev, rsrc);
223+ if (ret) {
224+ is_ioport ? ioport_unmap(iomem) : iounmap(iomem);
225+ return ret;
226+ }
227+
228+ done = do_io_rw(iomem, buf, off, count, 0, 0, iswrite);
229+
230+ vga_put(vdev->pdev, rsrc);
231+
232+ is_ioport ? ioport_unmap(iomem) : iounmap(iomem);
233+
234+ if (done >= 0)
235+ *ppos += done;
236+
237+ return done;
238+}
include/uapi/linux/vfio.h+9−0
@@ -303,6 +303,15 @@ enum { · 302 unmodified lines
303303 VFIO_PCI_BAR5_REGION_INDEX,
304304 VFIO_PCI_ROM_REGION_INDEX,
305305 VFIO_PCI_CONFIG_REGION_INDEX,
306+ /*
307+ * Expose VGA regions defined for PCI base class 03, subclass 00.
308+ * This includes I/O port ranges 0x3b0 to 0x3bb and 0x3c0 to 0x3df
309+ * as well as the MMIO range 0xa0000 to 0xbffff. Each implemented
310+ * range is found at it's identity mapped offset from the region
311+ * offset, for example 0x3b0 is region_info.offset + 0x3b0. Areas
312+ * between described ranges are unimplemented.
313+ */
314+ VFIO_PCI_VGA_REGION_INDEX,
306315 VFIO_PCI_NUM_REGIONS
307316 };
308317

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t