Merge tag 'tag-chrome-platform-for-v5.13' of git://git.kernel.org/pub/scm/linux/kerne...
[linux-2.6-microblaze.git] / drivers / vfio / pci / vfio_pci_igd.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * VFIO PCI Intel Graphics support
4  *
5  * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
6  *      Author: Alex Williamson <alex.williamson@redhat.com>
7  *
8  * Register a device specific region through which to provide read-only
9  * access to the Intel IGD opregion.  The register defining the opregion
10  * address is also virtualized to prevent user modification.
11  */
12
13 #include <linux/io.h>
14 #include <linux/pci.h>
15 #include <linux/uaccess.h>
16 #include <linux/vfio.h>
17
18 #include "vfio_pci_private.h"
19
20 #define OPREGION_SIGNATURE      "IntelGraphicsMem"
21 #define OPREGION_SIZE           (8 * 1024)
22 #define OPREGION_PCI_ADDR       0xfc
23
24 #define OPREGION_RVDA           0x3ba
25 #define OPREGION_RVDS           0x3c2
26 #define OPREGION_VERSION        0x16
27
28 static size_t vfio_pci_igd_rw(struct vfio_pci_device *vdev, char __user *buf,
29                               size_t count, loff_t *ppos, bool iswrite)
30 {
31         unsigned int i = VFIO_PCI_OFFSET_TO_INDEX(*ppos) - VFIO_PCI_NUM_REGIONS;
32         void *base = vdev->region[i].data;
33         loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
34
35         if (pos >= vdev->region[i].size || iswrite)
36                 return -EINVAL;
37
38         count = min(count, (size_t)(vdev->region[i].size - pos));
39
40         if (copy_to_user(buf, base + pos, count))
41                 return -EFAULT;
42
43         *ppos += count;
44
45         return count;
46 }
47
48 static void vfio_pci_igd_release(struct vfio_pci_device *vdev,
49                                  struct vfio_pci_region *region)
50 {
51         memunmap(region->data);
52 }
53
54 static const struct vfio_pci_regops vfio_pci_igd_regops = {
55         .rw             = vfio_pci_igd_rw,
56         .release        = vfio_pci_igd_release,
57 };
58
59 static int vfio_pci_igd_opregion_init(struct vfio_pci_device *vdev)
60 {
61         __le32 *dwordp = (__le32 *)(vdev->vconfig + OPREGION_PCI_ADDR);
62         u32 addr, size;
63         void *base;
64         int ret;
65         u16 version;
66
67         ret = pci_read_config_dword(vdev->pdev, OPREGION_PCI_ADDR, &addr);
68         if (ret)
69                 return ret;
70
71         if (!addr || !(~addr))
72                 return -ENODEV;
73
74         base = memremap(addr, OPREGION_SIZE, MEMREMAP_WB);
75         if (!base)
76                 return -ENOMEM;
77
78         if (memcmp(base, OPREGION_SIGNATURE, 16)) {
79                 memunmap(base);
80                 return -EINVAL;
81         }
82
83         size = le32_to_cpu(*(__le32 *)(base + 16));
84         if (!size) {
85                 memunmap(base);
86                 return -EINVAL;
87         }
88
89         size *= 1024; /* In KB */
90
91         /*
92          * Support opregion v2.1+
93          * When VBT data exceeds 6KB size and cannot be within mailbox #4, then
94          * the Extended VBT region next to opregion is used to hold the VBT data.
95          * RVDA (Relative Address of VBT Data from Opregion Base) and RVDS
96          * (Raw VBT Data Size) from opregion structure member are used to hold the
97          * address from region base and size of VBT data. RVDA/RVDS are not
98          * defined before opregion 2.0.
99          *
100          * opregion 2.1+: RVDA is unsigned, relative offset from
101          * opregion base, and should point to the end of opregion.
102          * otherwise, exposing to userspace to allow read access to everything between
103          * the OpRegion and VBT is not safe.
104          * RVDS is defined as size in bytes.
105          *
106          * opregion 2.0: rvda is the physical VBT address.
107          * Since rvda is HPA it cannot be directly used in guest.
108          * And it should not be practically available for end user,so it is not supported.
109          */
110         version = le16_to_cpu(*(__le16 *)(base + OPREGION_VERSION));
111         if (version >= 0x0200) {
112                 u64 rvda;
113                 u32 rvds;
114
115                 rvda = le64_to_cpu(*(__le64 *)(base + OPREGION_RVDA));
116                 rvds = le32_to_cpu(*(__le32 *)(base + OPREGION_RVDS));
117                 if (rvda && rvds) {
118                         /* no support for opregion v2.0 with physical VBT address */
119                         if (version == 0x0200) {
120                                 memunmap(base);
121                                 pci_err(vdev->pdev,
122                                         "IGD assignment does not support opregion v2.0 with an extended VBT region\n");
123                                 return -EINVAL;
124                         }
125
126                         if (rvda != size) {
127                                 memunmap(base);
128                                 pci_err(vdev->pdev,
129                                         "Extended VBT does not follow opregion on version 0x%04x\n",
130                                         version);
131                                 return -EINVAL;
132                         }
133
134                         /* region size for opregion v2.0+: opregion and VBT size. */
135                         size += rvds;
136                 }
137         }
138
139         if (size != OPREGION_SIZE) {
140                 memunmap(base);
141                 base = memremap(addr, size, MEMREMAP_WB);
142                 if (!base)
143                         return -ENOMEM;
144         }
145
146         ret = vfio_pci_register_dev_region(vdev,
147                 PCI_VENDOR_ID_INTEL | VFIO_REGION_TYPE_PCI_VENDOR_TYPE,
148                 VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION,
149                 &vfio_pci_igd_regops, size, VFIO_REGION_INFO_FLAG_READ, base);
150         if (ret) {
151                 memunmap(base);
152                 return ret;
153         }
154
155         /* Fill vconfig with the hw value and virtualize register */
156         *dwordp = cpu_to_le32(addr);
157         memset(vdev->pci_config_map + OPREGION_PCI_ADDR,
158                PCI_CAP_ID_INVALID_VIRT, 4);
159
160         return ret;
161 }
162
163 static size_t vfio_pci_igd_cfg_rw(struct vfio_pci_device *vdev,
164                                   char __user *buf, size_t count, loff_t *ppos,
165                                   bool iswrite)
166 {
167         unsigned int i = VFIO_PCI_OFFSET_TO_INDEX(*ppos) - VFIO_PCI_NUM_REGIONS;
168         struct pci_dev *pdev = vdev->region[i].data;
169         loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
170         size_t size;
171         int ret;
172
173         if (pos >= vdev->region[i].size || iswrite)
174                 return -EINVAL;
175
176         size = count = min(count, (size_t)(vdev->region[i].size - pos));
177
178         if ((pos & 1) && size) {
179                 u8 val;
180
181                 ret = pci_user_read_config_byte(pdev, pos, &val);
182                 if (ret)
183                         return ret;
184
185                 if (copy_to_user(buf + count - size, &val, 1))
186                         return -EFAULT;
187
188                 pos++;
189                 size--;
190         }
191
192         if ((pos & 3) && size > 2) {
193                 u16 val;
194
195                 ret = pci_user_read_config_word(pdev, pos, &val);
196                 if (ret)
197                         return ret;
198
199                 val = cpu_to_le16(val);
200                 if (copy_to_user(buf + count - size, &val, 2))
201                         return -EFAULT;
202
203                 pos += 2;
204                 size -= 2;
205         }
206
207         while (size > 3) {
208                 u32 val;
209
210                 ret = pci_user_read_config_dword(pdev, pos, &val);
211                 if (ret)
212                         return ret;
213
214                 val = cpu_to_le32(val);
215                 if (copy_to_user(buf + count - size, &val, 4))
216                         return -EFAULT;
217
218                 pos += 4;
219                 size -= 4;
220         }
221
222         while (size >= 2) {
223                 u16 val;
224
225                 ret = pci_user_read_config_word(pdev, pos, &val);
226                 if (ret)
227                         return ret;
228
229                 val = cpu_to_le16(val);
230                 if (copy_to_user(buf + count - size, &val, 2))
231                         return -EFAULT;
232
233                 pos += 2;
234                 size -= 2;
235         }
236
237         while (size) {
238                 u8 val;
239
240                 ret = pci_user_read_config_byte(pdev, pos, &val);
241                 if (ret)
242                         return ret;
243
244                 if (copy_to_user(buf + count - size, &val, 1))
245                         return -EFAULT;
246
247                 pos++;
248                 size--;
249         }
250
251         *ppos += count;
252
253         return count;
254 }
255
256 static void vfio_pci_igd_cfg_release(struct vfio_pci_device *vdev,
257                                      struct vfio_pci_region *region)
258 {
259         struct pci_dev *pdev = region->data;
260
261         pci_dev_put(pdev);
262 }
263
264 static const struct vfio_pci_regops vfio_pci_igd_cfg_regops = {
265         .rw             = vfio_pci_igd_cfg_rw,
266         .release        = vfio_pci_igd_cfg_release,
267 };
268
269 static int vfio_pci_igd_cfg_init(struct vfio_pci_device *vdev)
270 {
271         struct pci_dev *host_bridge, *lpc_bridge;
272         int ret;
273
274         host_bridge = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
275         if (!host_bridge)
276                 return -ENODEV;
277
278         if (host_bridge->vendor != PCI_VENDOR_ID_INTEL ||
279             host_bridge->class != (PCI_CLASS_BRIDGE_HOST << 8)) {
280                 pci_dev_put(host_bridge);
281                 return -EINVAL;
282         }
283
284         ret = vfio_pci_register_dev_region(vdev,
285                 PCI_VENDOR_ID_INTEL | VFIO_REGION_TYPE_PCI_VENDOR_TYPE,
286                 VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG,
287                 &vfio_pci_igd_cfg_regops, host_bridge->cfg_size,
288                 VFIO_REGION_INFO_FLAG_READ, host_bridge);
289         if (ret) {
290                 pci_dev_put(host_bridge);
291                 return ret;
292         }
293
294         lpc_bridge = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0x1f, 0));
295         if (!lpc_bridge)
296                 return -ENODEV;
297
298         if (lpc_bridge->vendor != PCI_VENDOR_ID_INTEL ||
299             lpc_bridge->class != (PCI_CLASS_BRIDGE_ISA << 8)) {
300                 pci_dev_put(lpc_bridge);
301                 return -EINVAL;
302         }
303
304         ret = vfio_pci_register_dev_region(vdev,
305                 PCI_VENDOR_ID_INTEL | VFIO_REGION_TYPE_PCI_VENDOR_TYPE,
306                 VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG,
307                 &vfio_pci_igd_cfg_regops, lpc_bridge->cfg_size,
308                 VFIO_REGION_INFO_FLAG_READ, lpc_bridge);
309         if (ret) {
310                 pci_dev_put(lpc_bridge);
311                 return ret;
312         }
313
314         return 0;
315 }
316
317 int vfio_pci_igd_init(struct vfio_pci_device *vdev)
318 {
319         int ret;
320
321         ret = vfio_pci_igd_opregion_init(vdev);
322         if (ret)
323                 return ret;
324
325         ret = vfio_pci_igd_cfg_init(vdev);
326         if (ret)
327                 return ret;
328
329         return 0;
330 }