forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-02-20 e636c8d336489bf3eed5878299e6cc045bbad077
kernel/drivers/vfio/pci/vfio_pci_rdwr.c
....@@ -1,12 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * VFIO PCI I/O Port & MMIO access
34 *
45 * Copyright (C) 2012 Red Hat, Inc. All rights reserved.
56 * Author: Alex Williamson <alex.williamson@redhat.com>
6
- *
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.
107 *
118 * Derived from original vfio:
129 * Copyright 2010 Cisco Systems, Inc. All rights reserved.
....@@ -40,17 +37,70 @@
4037 #define vfio_ioread8 ioread8
4138 #define vfio_iowrite8 iowrite8
4239
40
+#define VFIO_IOWRITE(size) \
41
+static int vfio_pci_iowrite##size(struct vfio_pci_device *vdev, \
42
+ bool test_mem, u##size val, void __iomem *io) \
43
+{ \
44
+ if (test_mem) { \
45
+ down_read(&vdev->memory_lock); \
46
+ if (!__vfio_pci_memory_enabled(vdev)) { \
47
+ up_read(&vdev->memory_lock); \
48
+ return -EIO; \
49
+ } \
50
+ } \
51
+ \
52
+ vfio_iowrite##size(val, io); \
53
+ \
54
+ if (test_mem) \
55
+ up_read(&vdev->memory_lock); \
56
+ \
57
+ return 0; \
58
+}
59
+
60
+VFIO_IOWRITE(8)
61
+VFIO_IOWRITE(16)
62
+VFIO_IOWRITE(32)
63
+#ifdef iowrite64
64
+VFIO_IOWRITE(64)
65
+#endif
66
+
67
+#define VFIO_IOREAD(size) \
68
+static int vfio_pci_ioread##size(struct vfio_pci_device *vdev, \
69
+ bool test_mem, u##size *val, void __iomem *io) \
70
+{ \
71
+ if (test_mem) { \
72
+ down_read(&vdev->memory_lock); \
73
+ if (!__vfio_pci_memory_enabled(vdev)) { \
74
+ up_read(&vdev->memory_lock); \
75
+ return -EIO; \
76
+ } \
77
+ } \
78
+ \
79
+ *val = vfio_ioread##size(io); \
80
+ \
81
+ if (test_mem) \
82
+ up_read(&vdev->memory_lock); \
83
+ \
84
+ return 0; \
85
+}
86
+
87
+VFIO_IOREAD(8)
88
+VFIO_IOREAD(16)
89
+VFIO_IOREAD(32)
90
+
4391 /*
4492 * Read or write from an __iomem region (MMIO or I/O port) with an excluded
4593 * range which is inaccessible. The excluded range drops writes and fills
4694 * reads with -1. This is intended for handling MSI-X vector tables and
4795 * leftover space for ROM BARs.
4896 */
49
-static ssize_t do_io_rw(void __iomem *io, char __user *buf,
97
+static ssize_t do_io_rw(struct vfio_pci_device *vdev, bool test_mem,
98
+ void __iomem *io, char __user *buf,
5099 loff_t off, size_t count, size_t x_start,
51100 size_t x_end, bool iswrite)
52101 {
53102 ssize_t done = 0;
103
+ int ret;
54104
55105 while (count) {
56106 size_t fillable, filled;
....@@ -69,9 +119,15 @@
69119 if (copy_from_user(&val, buf, 4))
70120 return -EFAULT;
71121
72
- vfio_iowrite32(val, io + off);
122
+ ret = vfio_pci_iowrite32(vdev, test_mem,
123
+ val, io + off);
124
+ if (ret)
125
+ return ret;
73126 } else {
74
- val = vfio_ioread32(io + off);
127
+ ret = vfio_pci_ioread32(vdev, test_mem,
128
+ &val, io + off);
129
+ if (ret)
130
+ return ret;
75131
76132 if (copy_to_user(buf, &val, 4))
77133 return -EFAULT;
....@@ -85,9 +141,15 @@
85141 if (copy_from_user(&val, buf, 2))
86142 return -EFAULT;
87143
88
- vfio_iowrite16(val, io + off);
144
+ ret = vfio_pci_iowrite16(vdev, test_mem,
145
+ val, io + off);
146
+ if (ret)
147
+ return ret;
89148 } else {
90
- val = vfio_ioread16(io + off);
149
+ ret = vfio_pci_ioread16(vdev, test_mem,
150
+ &val, io + off);
151
+ if (ret)
152
+ return ret;
91153
92154 if (copy_to_user(buf, &val, 2))
93155 return -EFAULT;
....@@ -101,9 +163,15 @@
101163 if (copy_from_user(&val, buf, 1))
102164 return -EFAULT;
103165
104
- vfio_iowrite8(val, io + off);
166
+ ret = vfio_pci_iowrite8(vdev, test_mem,
167
+ val, io + off);
168
+ if (ret)
169
+ return ret;
105170 } else {
106
- val = vfio_ioread8(io + off);
171
+ ret = vfio_pci_ioread8(vdev, test_mem,
172
+ &val, io + off);
173
+ if (ret)
174
+ return ret;
107175
108176 if (copy_to_user(buf, &val, 1))
109177 return -EFAULT;
....@@ -181,14 +249,6 @@
181249
182250 count = min(count, (size_t)(end - pos));
183251
184
- if (res->flags & IORESOURCE_MEM) {
185
- down_read(&vdev->memory_lock);
186
- if (!__vfio_pci_memory_enabled(vdev)) {
187
- up_read(&vdev->memory_lock);
188
- return -EIO;
189
- }
190
- }
191
-
192252 if (bar == PCI_ROM_RESOURCE) {
193253 /*
194254 * The ROM can fill less space than the BAR, so we start the
....@@ -216,7 +276,8 @@
216276 x_end = vdev->msix_offset + vdev->msix_size;
217277 }
218278
219
- done = do_io_rw(io, buf, pos, count, x_start, x_end, iswrite);
279
+ done = do_io_rw(vdev, res->flags & IORESOURCE_MEM, io, buf, pos,
280
+ count, x_start, x_end, iswrite);
220281
221282 if (done >= 0)
222283 *ppos += done;
....@@ -224,9 +285,6 @@
224285 if (bar == PCI_ROM_RESOURCE)
225286 pci_unmap_rom(pdev, io);
226287 out:
227
- if (res->flags & IORESOURCE_MEM)
228
- up_read(&vdev->memory_lock);
229
-
230288 return done;
231289 }
232290
....@@ -249,7 +307,7 @@
249307 switch ((u32)pos) {
250308 case 0xa0000 ... 0xbffff:
251309 count = min(count, (size_t)(0xc0000 - pos));
252
- iomem = ioremap_nocache(0xa0000, 0xbffff - 0xa0000 + 1);
310
+ iomem = ioremap(0xa0000, 0xbffff - 0xa0000 + 1);
253311 off = pos - 0xa0000;
254312 rsrc = VGA_RSRC_LEGACY_MEM;
255313 is_ioport = false;
....@@ -281,7 +339,12 @@
281339 return ret;
282340 }
283341
284
- done = do_io_rw(iomem, buf, off, count, 0, 0, iswrite);
342
+ /*
343
+ * VGA MMIO is a legacy, non-BAR resource that hopefully allows
344
+ * probing, so we don't currently worry about access in relation
345
+ * to the memory enable bit in the command register.
346
+ */
347
+ done = do_io_rw(vdev, false, iomem, buf, off, count, 0, 0, iswrite);
285348
286349 vga_put(vdev->pdev, rsrc);
287350
....@@ -293,28 +356,58 @@
293356 return done;
294357 }
295358
296
-static int vfio_pci_ioeventfd_handler(void *opaque, void *unused)
359
+static void vfio_pci_ioeventfd_do_write(struct vfio_pci_ioeventfd *ioeventfd,
360
+ bool test_mem)
297361 {
298
- struct vfio_pci_ioeventfd *ioeventfd = opaque;
299
-
300362 switch (ioeventfd->count) {
301363 case 1:
302
- vfio_iowrite8(ioeventfd->data, ioeventfd->addr);
364
+ vfio_pci_iowrite8(ioeventfd->vdev, test_mem,
365
+ ioeventfd->data, ioeventfd->addr);
303366 break;
304367 case 2:
305
- vfio_iowrite16(ioeventfd->data, ioeventfd->addr);
368
+ vfio_pci_iowrite16(ioeventfd->vdev, test_mem,
369
+ ioeventfd->data, ioeventfd->addr);
306370 break;
307371 case 4:
308
- vfio_iowrite32(ioeventfd->data, ioeventfd->addr);
372
+ vfio_pci_iowrite32(ioeventfd->vdev, test_mem,
373
+ ioeventfd->data, ioeventfd->addr);
309374 break;
310375 #ifdef iowrite64
311376 case 8:
312
- vfio_iowrite64(ioeventfd->data, ioeventfd->addr);
377
+ vfio_pci_iowrite64(ioeventfd->vdev, test_mem,
378
+ ioeventfd->data, ioeventfd->addr);
313379 break;
314380 #endif
315381 }
382
+}
383
+
384
+static int vfio_pci_ioeventfd_handler(void *opaque, void *unused)
385
+{
386
+ struct vfio_pci_ioeventfd *ioeventfd = opaque;
387
+ struct vfio_pci_device *vdev = ioeventfd->vdev;
388
+
389
+ if (ioeventfd->test_mem) {
390
+ if (!down_read_trylock(&vdev->memory_lock))
391
+ return 1; /* Lock contended, use thread */
392
+ if (!__vfio_pci_memory_enabled(vdev)) {
393
+ up_read(&vdev->memory_lock);
394
+ return 0;
395
+ }
396
+ }
397
+
398
+ vfio_pci_ioeventfd_do_write(ioeventfd, false);
399
+
400
+ if (ioeventfd->test_mem)
401
+ up_read(&vdev->memory_lock);
316402
317403 return 0;
404
+}
405
+
406
+static void vfio_pci_ioeventfd_thread(void *opaque, void *unused)
407
+{
408
+ struct vfio_pci_ioeventfd *ioeventfd = opaque;
409
+
410
+ vfio_pci_ioeventfd_do_write(ioeventfd, ioeventfd->test_mem);
318411 }
319412
320413 long vfio_pci_ioeventfd(struct vfio_pci_device *vdev, loff_t offset,
....@@ -381,14 +474,17 @@
381474 goto out_unlock;
382475 }
383476
477
+ ioeventfd->vdev = vdev;
384478 ioeventfd->addr = vdev->barmap[bar] + pos;
385479 ioeventfd->data = data;
386480 ioeventfd->pos = pos;
387481 ioeventfd->bar = bar;
388482 ioeventfd->count = count;
483
+ ioeventfd->test_mem = vdev->pdev->resource[bar].flags & IORESOURCE_MEM;
389484
390485 ret = vfio_virqfd_enable(ioeventfd, vfio_pci_ioeventfd_handler,
391
- NULL, NULL, &ioeventfd->virqfd, fd);
486
+ vfio_pci_ioeventfd_thread, NULL,
487
+ &ioeventfd->virqfd, fd);
392488 if (ret) {
393489 kfree(ioeventfd);
394490 goto out_unlock;