2 * VFIO PCI I/O Port & MMIO access
4 * Copyright (C) 2012 Red Hat, Inc. All rights reserved.
5 * Author: Alex Williamson <alex.williamson@redhat.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * Derived from original vfio:
12 * Copyright 2010 Cisco Systems, Inc. All rights reserved.
13 * Author: Tom Lyon, pugs@cisco.com
17 #include <linux/pci.h>
18 #include <linux/uaccess.h>
20 #include <linux/vfio.h>
21 #include <linux/vgaarb.h>
23 #include "vfio_pci_private.h"
25 #ifdef __LITTLE_ENDIAN
26 #define vfio_ioread64 ioread64
27 #define vfio_iowrite64 iowrite64
28 #define vfio_ioread32 ioread32
29 #define vfio_iowrite32 iowrite32
30 #define vfio_ioread16 ioread16
31 #define vfio_iowrite16 iowrite16
33 #define vfio_ioread64 ioread64be
34 #define vfio_iowrite64 iowrite64be
35 #define vfio_ioread32 ioread32be
36 #define vfio_iowrite32 iowrite32be
37 #define vfio_ioread16 ioread16be
38 #define vfio_iowrite16 iowrite16be
40 #define vfio_ioread8 ioread8
41 #define vfio_iowrite8 iowrite8
44 * Read or write from an __iomem region (MMIO or I/O port) with an excluded
45 * range which is inaccessible. The excluded range drops writes and fills
46 * reads with -1. This is intended for handling MSI-X vector tables and
47 * leftover space for ROM BARs.
49 static ssize_t
do_io_rw(void __iomem
*io
, char __user
*buf
,
50 loff_t off
, size_t count
, size_t x_start
,
51 size_t x_end
, bool iswrite
)
56 size_t fillable
, filled
;
59 fillable
= min(count
, (size_t)(x_start
- off
));
60 else if (off
>= x_end
)
65 if (fillable
>= 4 && !(off
% 4)) {
69 if (copy_from_user(&val
, buf
, 4))
72 vfio_iowrite32(val
, io
+ off
);
74 val
= vfio_ioread32(io
+ off
);
76 if (copy_to_user(buf
, &val
, 4))
81 } else if (fillable
>= 2 && !(off
% 2)) {
85 if (copy_from_user(&val
, buf
, 2))
88 vfio_iowrite16(val
, io
+ off
);
90 val
= vfio_ioread16(io
+ off
);
92 if (copy_to_user(buf
, &val
, 2))
97 } else if (fillable
) {
101 if (copy_from_user(&val
, buf
, 1))
104 vfio_iowrite8(val
, io
+ off
);
106 val
= vfio_ioread8(io
+ off
);
108 if (copy_to_user(buf
, &val
, 1))
114 /* Fill reads with -1, drop writes */
115 filled
= min(count
, (size_t)(x_end
- off
));
120 for (i
= 0; i
< filled
; i
++)
121 if (copy_to_user(buf
+ i
, &val
, 1))
135 static int vfio_pci_setup_barmap(struct vfio_pci_device
*vdev
, int bar
)
137 struct pci_dev
*pdev
= vdev
->pdev
;
141 if (vdev
->barmap
[bar
])
144 ret
= pci_request_selected_regions(pdev
, 1 << bar
, "vfio");
148 io
= pci_iomap(pdev
, bar
, 0);
150 pci_release_selected_regions(pdev
, 1 << bar
);
154 vdev
->barmap
[bar
] = io
;
159 ssize_t
vfio_pci_bar_rw(struct vfio_pci_device
*vdev
, char __user
*buf
,
160 size_t count
, loff_t
*ppos
, bool iswrite
)
162 struct pci_dev
*pdev
= vdev
->pdev
;
163 loff_t pos
= *ppos
& VFIO_PCI_OFFSET_MASK
;
164 int bar
= VFIO_PCI_OFFSET_TO_INDEX(*ppos
);
165 size_t x_start
= 0, x_end
= 0;
170 if (pci_resource_start(pdev
, bar
))
171 end
= pci_resource_len(pdev
, bar
);
172 else if (bar
== PCI_ROM_RESOURCE
&&
173 pdev
->resource
[bar
].flags
& IORESOURCE_ROM_SHADOW
)
181 count
= min(count
, (size_t)(end
- pos
));
183 if (bar
== PCI_ROM_RESOURCE
) {
185 * The ROM can fill less space than the BAR, so we start the
186 * excluded range at the end of the actual ROM. This makes
187 * filling large ROM BARs much faster.
189 io
= pci_map_rom(pdev
, &x_start
);
194 int ret
= vfio_pci_setup_barmap(vdev
, bar
);
198 io
= vdev
->barmap
[bar
];
201 if (bar
== vdev
->msix_bar
) {
202 x_start
= vdev
->msix_offset
;
203 x_end
= vdev
->msix_offset
+ vdev
->msix_size
;
206 done
= do_io_rw(io
, buf
, pos
, count
, x_start
, x_end
, iswrite
);
211 if (bar
== PCI_ROM_RESOURCE
)
212 pci_unmap_rom(pdev
, io
);
217 ssize_t
vfio_pci_vga_rw(struct vfio_pci_device
*vdev
, char __user
*buf
,
218 size_t count
, loff_t
*ppos
, bool iswrite
)
221 loff_t off
, pos
= *ppos
& VFIO_PCI_OFFSET_MASK
;
222 void __iomem
*iomem
= NULL
;
234 case 0xa0000 ... 0xbffff:
235 count
= min(count
, (size_t)(0xc0000 - pos
));
236 iomem
= ioremap_nocache(0xa0000, 0xbffff - 0xa0000 + 1);
238 rsrc
= VGA_RSRC_LEGACY_MEM
;
241 case 0x3b0 ... 0x3bb:
242 count
= min(count
, (size_t)(0x3bc - pos
));
243 iomem
= ioport_map(0x3b0, 0x3bb - 0x3b0 + 1);
245 rsrc
= VGA_RSRC_LEGACY_IO
;
248 case 0x3c0 ... 0x3df:
249 count
= min(count
, (size_t)(0x3e0 - pos
));
250 iomem
= ioport_map(0x3c0, 0x3df - 0x3c0 + 1);
252 rsrc
= VGA_RSRC_LEGACY_IO
;
262 ret
= vga_get_interruptible(vdev
->pdev
, rsrc
);
264 is_ioport
? ioport_unmap(iomem
) : iounmap(iomem
);
268 done
= do_io_rw(iomem
, buf
, off
, count
, 0, 0, iswrite
);
270 vga_put(vdev
->pdev
, rsrc
);
272 is_ioport
? ioport_unmap(iomem
) : iounmap(iomem
);
280 static int vfio_pci_ioeventfd_handler(void *opaque
, void *unused
)
282 struct vfio_pci_ioeventfd
*ioeventfd
= opaque
;
284 switch (ioeventfd
->count
) {
286 vfio_iowrite8(ioeventfd
->data
, ioeventfd
->addr
);
289 vfio_iowrite16(ioeventfd
->data
, ioeventfd
->addr
);
292 vfio_iowrite32(ioeventfd
->data
, ioeventfd
->addr
);
296 vfio_iowrite64(ioeventfd
->data
, ioeventfd
->addr
);
304 long vfio_pci_ioeventfd(struct vfio_pci_device
*vdev
, loff_t offset
,
305 uint64_t data
, int count
, int fd
)
307 struct pci_dev
*pdev
= vdev
->pdev
;
308 loff_t pos
= offset
& VFIO_PCI_OFFSET_MASK
;
309 int ret
, bar
= VFIO_PCI_OFFSET_TO_INDEX(offset
);
310 struct vfio_pci_ioeventfd
*ioeventfd
;
312 /* Only support ioeventfds into BARs */
313 if (bar
> VFIO_PCI_BAR5_REGION_INDEX
)
316 if (pos
+ count
> pci_resource_len(pdev
, bar
))
319 /* Disallow ioeventfds working around MSI-X table writes */
320 if (bar
== vdev
->msix_bar
&&
321 !(pos
+ count
<= vdev
->msix_offset
||
322 pos
>= vdev
->msix_offset
+ vdev
->msix_size
))
330 ret
= vfio_pci_setup_barmap(vdev
, bar
);
334 mutex_lock(&vdev
->ioeventfds_lock
);
336 list_for_each_entry(ioeventfd
, &vdev
->ioeventfds_list
, next
) {
337 if (ioeventfd
->pos
== pos
&& ioeventfd
->bar
== bar
&&
338 ioeventfd
->data
== data
&& ioeventfd
->count
== count
) {
340 vfio_virqfd_disable(&ioeventfd
->virqfd
);
341 list_del(&ioeventfd
->next
);
342 vdev
->ioeventfds_nr
--;
357 if (vdev
->ioeventfds_nr
>= VFIO_PCI_IOEVENTFD_MAX
) {
362 ioeventfd
= kzalloc(sizeof(*ioeventfd
), GFP_KERNEL
);
368 ioeventfd
->addr
= vdev
->barmap
[bar
] + pos
;
369 ioeventfd
->data
= data
;
370 ioeventfd
->pos
= pos
;
371 ioeventfd
->bar
= bar
;
372 ioeventfd
->count
= count
;
374 ret
= vfio_virqfd_enable(ioeventfd
, vfio_pci_ioeventfd_handler
,
375 NULL
, NULL
, &ioeventfd
->virqfd
, fd
);
381 list_add(&ioeventfd
->next
, &vdev
->ioeventfds_list
);
382 vdev
->ioeventfds_nr
++;
385 mutex_unlock(&vdev
->ioeventfds_lock
);