aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-10-31 14:01:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-10-31 14:01:38 -0400
commit0c86e761b95131943c2b8af2ffb3c0554f9a71f5 (patch)
tree95f9563ca78ab077b5fbe53618d1fb30bfd28f94
parentb3491d8430dd25f0a4e00c33d60da22a9bd9d052 (diff)
parent104c7405a64d937254b6a154938e6151f91c9e0d (diff)
Merge tag 'vfio-v4.20-rc1.v2' of git://github.com/awilliam/linux-vfio
Pull VFIO updates from Alex Williamson: - EDID interfaces for vfio devices supporting display extensions (Gerd Hoffmann) - Generically select Type-1 IOMMU model support on ARM/ARM64 (Geert Uytterhoeven) - Quirk for VFs reporting INTx pin (Alex Williamson) - Fix error path memory leak in MSI support (Li Qiang) * tag 'vfio-v4.20-rc1.v2' of git://github.com/awilliam/linux-vfio: vfio: add edid support to mbochs sample driver vfio: add edid api for display (vgpu) devices. drivers/vfio: Allow type-1 IOMMU instantiation with all ARM/ARM64 IOMMUs vfio/pci: Mask buggy SR-IOV VF INTx support vfio/pci: Fix potential memory leak in vfio_msi_cap_len
-rw-r--r--drivers/vfio/Kconfig2
-rw-r--r--drivers/vfio/pci/vfio_pci.c8
-rw-r--r--drivers/vfio/pci/vfio_pci_config.c31
-rw-r--r--include/uapi/linux/vfio.h50
-rw-r--r--samples/vfio-mdev/mbochs.c136
5 files changed, 204 insertions, 23 deletions
diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
index c84333eb5eb5..9de5ed38da83 100644
--- a/drivers/vfio/Kconfig
+++ b/drivers/vfio/Kconfig
@@ -21,7 +21,7 @@ config VFIO_VIRQFD
21menuconfig VFIO 21menuconfig VFIO
22 tristate "VFIO Non-Privileged userspace driver framework" 22 tristate "VFIO Non-Privileged userspace driver framework"
23 depends on IOMMU_API 23 depends on IOMMU_API
24 select VFIO_IOMMU_TYPE1 if (X86 || S390 || ARM_SMMU || ARM_SMMU_V3) 24 select VFIO_IOMMU_TYPE1 if (X86 || S390 || ARM || ARM64)
25 select ANON_INODES 25 select ANON_INODES
26 help 26 help
27 VFIO provides a framework for secure userspace device drivers. 27 VFIO provides a framework for secure userspace device drivers.
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index cddb453a1ba5..50cdedfca9fe 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -434,10 +434,14 @@ static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type)
434{ 434{
435 if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) { 435 if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) {
436 u8 pin; 436 u8 pin;
437
438 if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) ||
439 vdev->nointx || vdev->pdev->is_virtfn)
440 return 0;
441
437 pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin); 442 pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin);
438 if (IS_ENABLED(CONFIG_VFIO_PCI_INTX) && !vdev->nointx && pin)
439 return 1;
440 443
444 return pin ? 1 : 0;
441 } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) { 445 } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) {
442 u8 pos; 446 u8 pos;
443 u16 flags; 447 u16 flags;
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
index 115a36f6f403..423ea1f98441 100644
--- a/drivers/vfio/pci/vfio_pci_config.c
+++ b/drivers/vfio/pci/vfio_pci_config.c
@@ -1180,8 +1180,10 @@ static int vfio_msi_cap_len(struct vfio_pci_device *vdev, u8 pos)
1180 return -ENOMEM; 1180 return -ENOMEM;
1181 1181
1182 ret = init_pci_cap_msi_perm(vdev->msi_perm, len, flags); 1182 ret = init_pci_cap_msi_perm(vdev->msi_perm, len, flags);
1183 if (ret) 1183 if (ret) {
1184 kfree(vdev->msi_perm);
1184 return ret; 1185 return ret;
1186 }
1185 1187
1186 return len; 1188 return len;
1187} 1189}
@@ -1610,6 +1612,15 @@ static int vfio_ecap_init(struct vfio_pci_device *vdev)
1610} 1612}
1611 1613
1612/* 1614/*
1615 * Nag about hardware bugs, hopefully to have vendors fix them, but at least
1616 * to collect a list of dependencies for the VF INTx pin quirk below.
1617 */
1618static const struct pci_device_id known_bogus_vf_intx_pin[] = {
1619 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x270c) },
1620 {}
1621};
1622
1623/*
1613 * For each device we allocate a pci_config_map that indicates the 1624 * For each device we allocate a pci_config_map that indicates the
1614 * capability occupying each dword and thus the struct perm_bits we 1625 * capability occupying each dword and thus the struct perm_bits we
1615 * use for read and write. We also allocate a virtualized config 1626 * use for read and write. We also allocate a virtualized config
@@ -1674,6 +1685,24 @@ int vfio_config_init(struct vfio_pci_device *vdev)
1674 if (pdev->is_virtfn) { 1685 if (pdev->is_virtfn) {
1675 *(__le16 *)&vconfig[PCI_VENDOR_ID] = cpu_to_le16(pdev->vendor); 1686 *(__le16 *)&vconfig[PCI_VENDOR_ID] = cpu_to_le16(pdev->vendor);
1676 *(__le16 *)&vconfig[PCI_DEVICE_ID] = cpu_to_le16(pdev->device); 1687 *(__le16 *)&vconfig[PCI_DEVICE_ID] = cpu_to_le16(pdev->device);
1688
1689 /*
1690 * Per SR-IOV spec rev 1.1, 3.4.1.18 the interrupt pin register
1691 * does not apply to VFs and VFs must implement this register
1692 * as read-only with value zero. Userspace is not readily able
1693 * to identify whether a device is a VF and thus that the pin
1694 * definition on the device is bogus should it violate this
1695 * requirement. We already virtualize the pin register for
1696 * other purposes, so we simply need to replace the bogus value
1697 * and consider VFs when we determine INTx IRQ count.
1698 */
1699 if (vconfig[PCI_INTERRUPT_PIN] &&
1700 !pci_match_id(known_bogus_vf_intx_pin, pdev))
1701 pci_warn(pdev,
1702 "Hardware bug: VF reports bogus INTx pin %d\n",
1703 vconfig[PCI_INTERRUPT_PIN]);
1704
1705 vconfig[PCI_INTERRUPT_PIN] = 0; /* Gratuitous for good VFs */
1677 } 1706 }
1678 1707
1679 if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx) 1708 if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx)
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index f378b9802d8b..813102810f53 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -303,6 +303,56 @@ struct vfio_region_info_cap_type {
303#define VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG (2) 303#define VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG (2)
304#define VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG (3) 304#define VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG (3)
305 305
306#define VFIO_REGION_TYPE_GFX (1)
307#define VFIO_REGION_SUBTYPE_GFX_EDID (1)
308
309/**
310 * struct vfio_region_gfx_edid - EDID region layout.
311 *
312 * Set display link state and EDID blob.
313 *
314 * The EDID blob has monitor information such as brand, name, serial
315 * number, physical size, supported video modes and more.
316 *
317 * This special region allows userspace (typically qemu) set a virtual
318 * EDID for the virtual monitor, which allows a flexible display
319 * configuration.
320 *
321 * For the edid blob spec look here:
322 * https://en.wikipedia.org/wiki/Extended_Display_Identification_Data
323 *
324 * On linux systems you can find the EDID blob in sysfs:
325 * /sys/class/drm/${card}/${connector}/edid
326 *
327 * You can use the edid-decode ulility (comes with xorg-x11-utils) to
328 * decode the EDID blob.
329 *
330 * @edid_offset: location of the edid blob, relative to the
331 * start of the region (readonly).
332 * @edid_max_size: max size of the edid blob (readonly).
333 * @edid_size: actual edid size (read/write).
334 * @link_state: display link state (read/write).
335 * VFIO_DEVICE_GFX_LINK_STATE_UP: Monitor is turned on.
336 * VFIO_DEVICE_GFX_LINK_STATE_DOWN: Monitor is turned off.
337 * @max_xres: max display width (0 == no limitation, readonly).
338 * @max_yres: max display height (0 == no limitation, readonly).
339 *
340 * EDID update protocol:
341 * (1) set link-state to down.
342 * (2) update edid blob and size.
343 * (3) set link-state to up.
344 */
345struct vfio_region_gfx_edid {
346 __u32 edid_offset;
347 __u32 edid_max_size;
348 __u32 edid_size;
349 __u32 max_xres;
350 __u32 max_yres;
351 __u32 link_state;
352#define VFIO_DEVICE_GFX_LINK_STATE_UP 1
353#define VFIO_DEVICE_GFX_LINK_STATE_DOWN 2
354};
355
306/* 356/*
307 * The MSIX mappable capability informs that MSIX data of a BAR can be mmapped 357 * The MSIX mappable capability informs that MSIX data of a BAR can be mmapped
308 * which allows direct access to non-MSIX registers which happened to be within 358 * which allows direct access to non-MSIX registers which happened to be within
diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index 2535c3677c7b..ca7960adf5a3 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -71,11 +71,19 @@
71#define MBOCHS_NAME "mbochs" 71#define MBOCHS_NAME "mbochs"
72#define MBOCHS_CLASS_NAME "mbochs" 72#define MBOCHS_CLASS_NAME "mbochs"
73 73
74#define MBOCHS_EDID_REGION_INDEX VFIO_PCI_NUM_REGIONS
75#define MBOCHS_NUM_REGIONS (MBOCHS_EDID_REGION_INDEX+1)
76
74#define MBOCHS_CONFIG_SPACE_SIZE 0xff 77#define MBOCHS_CONFIG_SPACE_SIZE 0xff
75#define MBOCHS_MMIO_BAR_OFFSET PAGE_SIZE 78#define MBOCHS_MMIO_BAR_OFFSET PAGE_SIZE
76#define MBOCHS_MMIO_BAR_SIZE PAGE_SIZE 79#define MBOCHS_MMIO_BAR_SIZE PAGE_SIZE
77#define MBOCHS_MEMORY_BAR_OFFSET (MBOCHS_MMIO_BAR_OFFSET + \ 80#define MBOCHS_EDID_OFFSET (MBOCHS_MMIO_BAR_OFFSET + \
78 MBOCHS_MMIO_BAR_SIZE) 81 MBOCHS_MMIO_BAR_SIZE)
82#define MBOCHS_EDID_SIZE PAGE_SIZE
83#define MBOCHS_MEMORY_BAR_OFFSET (MBOCHS_EDID_OFFSET + \
84 MBOCHS_EDID_SIZE)
85
86#define MBOCHS_EDID_BLOB_OFFSET (MBOCHS_EDID_SIZE/2)
79 87
80#define STORE_LE16(addr, val) (*(u16 *)addr = val) 88#define STORE_LE16(addr, val) (*(u16 *)addr = val)
81#define STORE_LE32(addr, val) (*(u32 *)addr = val) 89#define STORE_LE32(addr, val) (*(u32 *)addr = val)
@@ -95,16 +103,24 @@ MODULE_PARM_DESC(mem, "megabytes available to " MBOCHS_NAME " devices");
95static const struct mbochs_type { 103static const struct mbochs_type {
96 const char *name; 104 const char *name;
97 u32 mbytes; 105 u32 mbytes;
106 u32 max_x;
107 u32 max_y;
98} mbochs_types[] = { 108} mbochs_types[] = {
99 { 109 {
100 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_1, 110 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_1,
101 .mbytes = 4, 111 .mbytes = 4,
112 .max_x = 800,
113 .max_y = 600,
102 }, { 114 }, {
103 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_2, 115 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_2,
104 .mbytes = 16, 116 .mbytes = 16,
117 .max_x = 1920,
118 .max_y = 1440,
105 }, { 119 }, {
106 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_3, 120 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_3,
107 .mbytes = 64, 121 .mbytes = 64,
122 .max_x = 0,
123 .max_y = 0,
108 }, 124 },
109}; 125};
110 126
@@ -115,6 +131,11 @@ static struct cdev mbochs_cdev;
115static struct device mbochs_dev; 131static struct device mbochs_dev;
116static int mbochs_used_mbytes; 132static int mbochs_used_mbytes;
117 133
134struct vfio_region_info_ext {
135 struct vfio_region_info base;
136 struct vfio_region_info_cap_type type;
137};
138
118struct mbochs_mode { 139struct mbochs_mode {
119 u32 drm_format; 140 u32 drm_format;
120 u32 bytepp; 141 u32 bytepp;
@@ -144,13 +165,14 @@ struct mdev_state {
144 u32 memory_bar_mask; 165 u32 memory_bar_mask;
145 struct mutex ops_lock; 166 struct mutex ops_lock;
146 struct mdev_device *mdev; 167 struct mdev_device *mdev;
147 struct vfio_device_info dev_info;
148 168
149 const struct mbochs_type *type; 169 const struct mbochs_type *type;
150 u16 vbe[VBE_DISPI_INDEX_COUNT]; 170 u16 vbe[VBE_DISPI_INDEX_COUNT];
151 u64 memsize; 171 u64 memsize;
152 struct page **pages; 172 struct page **pages;
153 pgoff_t pagecount; 173 pgoff_t pagecount;
174 struct vfio_region_gfx_edid edid_regs;
175 u8 edid_blob[0x400];
154 176
155 struct list_head dmabufs; 177 struct list_head dmabufs;
156 u32 active_id; 178 u32 active_id;
@@ -342,10 +364,20 @@ static void handle_mmio_read(struct mdev_state *mdev_state, u16 offset,
342 char *buf, u32 count) 364 char *buf, u32 count)
343{ 365{
344 struct device *dev = mdev_dev(mdev_state->mdev); 366 struct device *dev = mdev_dev(mdev_state->mdev);
367 struct vfio_region_gfx_edid *edid;
345 u16 reg16 = 0; 368 u16 reg16 = 0;
346 int index; 369 int index;
347 370
348 switch (offset) { 371 switch (offset) {
372 case 0x000 ... 0x3ff: /* edid block */
373 edid = &mdev_state->edid_regs;
374 if (edid->link_state != VFIO_DEVICE_GFX_LINK_STATE_UP ||
375 offset >= edid->edid_size) {
376 memset(buf, 0, count);
377 break;
378 }
379 memcpy(buf, mdev_state->edid_blob + offset, count);
380 break;
349 case 0x500 ... 0x515: /* bochs dispi interface */ 381 case 0x500 ... 0x515: /* bochs dispi interface */
350 if (count != 2) 382 if (count != 2)
351 goto unhandled; 383 goto unhandled;
@@ -365,6 +397,44 @@ unhandled:
365 } 397 }
366} 398}
367 399
400static void handle_edid_regs(struct mdev_state *mdev_state, u16 offset,
401 char *buf, u32 count, bool is_write)
402{
403 char *regs = (void *)&mdev_state->edid_regs;
404
405 if (offset + count > sizeof(mdev_state->edid_regs))
406 return;
407 if (count != 4)
408 return;
409 if (offset % 4)
410 return;
411
412 if (is_write) {
413 switch (offset) {
414 case offsetof(struct vfio_region_gfx_edid, link_state):
415 case offsetof(struct vfio_region_gfx_edid, edid_size):
416 memcpy(regs + offset, buf, count);
417 break;
418 default:
419 /* read-only regs */
420 break;
421 }
422 } else {
423 memcpy(buf, regs + offset, count);
424 }
425}
426
427static void handle_edid_blob(struct mdev_state *mdev_state, u16 offset,
428 char *buf, u32 count, bool is_write)
429{
430 if (offset + count > mdev_state->edid_regs.edid_max_size)
431 return;
432 if (is_write)
433 memcpy(mdev_state->edid_blob + offset, buf, count);
434 else
435 memcpy(buf, mdev_state->edid_blob + offset, count);
436}
437
368static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count, 438static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
369 loff_t pos, bool is_write) 439 loff_t pos, bool is_write)
370{ 440{
@@ -384,13 +454,25 @@ static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
384 memcpy(buf, (mdev_state->vconfig + pos), count); 454 memcpy(buf, (mdev_state->vconfig + pos), count);
385 455
386 } else if (pos >= MBOCHS_MMIO_BAR_OFFSET && 456 } else if (pos >= MBOCHS_MMIO_BAR_OFFSET &&
387 pos + count <= MBOCHS_MEMORY_BAR_OFFSET) { 457 pos + count <= (MBOCHS_MMIO_BAR_OFFSET +
458 MBOCHS_MMIO_BAR_SIZE)) {
388 pos -= MBOCHS_MMIO_BAR_OFFSET; 459 pos -= MBOCHS_MMIO_BAR_OFFSET;
389 if (is_write) 460 if (is_write)
390 handle_mmio_write(mdev_state, pos, buf, count); 461 handle_mmio_write(mdev_state, pos, buf, count);
391 else 462 else
392 handle_mmio_read(mdev_state, pos, buf, count); 463 handle_mmio_read(mdev_state, pos, buf, count);
393 464
465 } else if (pos >= MBOCHS_EDID_OFFSET &&
466 pos + count <= (MBOCHS_EDID_OFFSET +
467 MBOCHS_EDID_SIZE)) {
468 pos -= MBOCHS_EDID_OFFSET;
469 if (pos < MBOCHS_EDID_BLOB_OFFSET) {
470 handle_edid_regs(mdev_state, pos, buf, count, is_write);
471 } else {
472 pos -= MBOCHS_EDID_BLOB_OFFSET;
473 handle_edid_blob(mdev_state, pos, buf, count, is_write);
474 }
475
394 } else if (pos >= MBOCHS_MEMORY_BAR_OFFSET && 476 } else if (pos >= MBOCHS_MEMORY_BAR_OFFSET &&
395 pos + count <= 477 pos + count <=
396 MBOCHS_MEMORY_BAR_OFFSET + mdev_state->memsize) { 478 MBOCHS_MEMORY_BAR_OFFSET + mdev_state->memsize) {
@@ -471,6 +553,10 @@ static int mbochs_create(struct kobject *kobj, struct mdev_device *mdev)
471 mdev_state->next_id = 1; 553 mdev_state->next_id = 1;
472 554
473 mdev_state->type = type; 555 mdev_state->type = type;
556 mdev_state->edid_regs.max_xres = type->max_x;
557 mdev_state->edid_regs.max_yres = type->max_y;
558 mdev_state->edid_regs.edid_offset = MBOCHS_EDID_BLOB_OFFSET;
559 mdev_state->edid_regs.edid_max_size = sizeof(mdev_state->edid_blob);
474 mbochs_create_config_space(mdev_state); 560 mbochs_create_config_space(mdev_state);
475 mbochs_reset(mdev); 561 mbochs_reset(mdev);
476 562
@@ -932,16 +1018,16 @@ static int mbochs_dmabuf_export(struct mbochs_dmabuf *dmabuf)
932} 1018}
933 1019
934static int mbochs_get_region_info(struct mdev_device *mdev, 1020static int mbochs_get_region_info(struct mdev_device *mdev,
935 struct vfio_region_info *region_info, 1021 struct vfio_region_info_ext *ext)
936 u16 *cap_type_id, void **cap_type)
937{ 1022{
1023 struct vfio_region_info *region_info = &ext->base;
938 struct mdev_state *mdev_state; 1024 struct mdev_state *mdev_state;
939 1025
940 mdev_state = mdev_get_drvdata(mdev); 1026 mdev_state = mdev_get_drvdata(mdev);
941 if (!mdev_state) 1027 if (!mdev_state)
942 return -EINVAL; 1028 return -EINVAL;
943 1029
944 if (region_info->index >= VFIO_PCI_NUM_REGIONS) 1030 if (region_info->index >= MBOCHS_NUM_REGIONS)
945 return -EINVAL; 1031 return -EINVAL;
946 1032
947 switch (region_info->index) { 1033 switch (region_info->index) {
@@ -964,6 +1050,20 @@ static int mbochs_get_region_info(struct mdev_device *mdev,
964 region_info->flags = (VFIO_REGION_INFO_FLAG_READ | 1050 region_info->flags = (VFIO_REGION_INFO_FLAG_READ |
965 VFIO_REGION_INFO_FLAG_WRITE); 1051 VFIO_REGION_INFO_FLAG_WRITE);
966 break; 1052 break;
1053 case MBOCHS_EDID_REGION_INDEX:
1054 ext->base.argsz = sizeof(*ext);
1055 ext->base.offset = MBOCHS_EDID_OFFSET;
1056 ext->base.size = MBOCHS_EDID_SIZE;
1057 ext->base.flags = (VFIO_REGION_INFO_FLAG_READ |
1058 VFIO_REGION_INFO_FLAG_WRITE |
1059 VFIO_REGION_INFO_FLAG_CAPS);
1060 ext->base.cap_offset = offsetof(typeof(*ext), type);
1061 ext->type.header.id = VFIO_REGION_INFO_CAP_TYPE;
1062 ext->type.header.version = 1;
1063 ext->type.header.next = 0;
1064 ext->type.type = VFIO_REGION_TYPE_GFX;
1065 ext->type.subtype = VFIO_REGION_SUBTYPE_GFX_EDID;
1066 break;
967 default: 1067 default:
968 region_info->size = 0; 1068 region_info->size = 0;
969 region_info->offset = 0; 1069 region_info->offset = 0;
@@ -984,7 +1084,7 @@ static int mbochs_get_device_info(struct mdev_device *mdev,
984 struct vfio_device_info *dev_info) 1084 struct vfio_device_info *dev_info)
985{ 1085{
986 dev_info->flags = VFIO_DEVICE_FLAGS_PCI; 1086 dev_info->flags = VFIO_DEVICE_FLAGS_PCI;
987 dev_info->num_regions = VFIO_PCI_NUM_REGIONS; 1087 dev_info->num_regions = MBOCHS_NUM_REGIONS;
988 dev_info->num_irqs = VFIO_PCI_NUM_IRQS; 1088 dev_info->num_irqs = VFIO_PCI_NUM_IRQS;
989 return 0; 1089 return 0;
990} 1090}
@@ -1084,7 +1184,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
1084 unsigned long arg) 1184 unsigned long arg)
1085{ 1185{
1086 int ret = 0; 1186 int ret = 0;
1087 unsigned long minsz; 1187 unsigned long minsz, outsz;
1088 struct mdev_state *mdev_state; 1188 struct mdev_state *mdev_state;
1089 1189
1090 mdev_state = mdev_get_drvdata(mdev); 1190 mdev_state = mdev_get_drvdata(mdev);
@@ -1106,8 +1206,6 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
1106 if (ret) 1206 if (ret)
1107 return ret; 1207 return ret;
1108 1208
1109 memcpy(&mdev_state->dev_info, &info, sizeof(info));
1110
1111 if (copy_to_user((void __user *)arg, &info, minsz)) 1209 if (copy_to_user((void __user *)arg, &info, minsz))
1112 return -EFAULT; 1210 return -EFAULT;
1113 1211
@@ -1115,24 +1213,24 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
1115 } 1213 }
1116 case VFIO_DEVICE_GET_REGION_INFO: 1214 case VFIO_DEVICE_GET_REGION_INFO:
1117 { 1215 {
1118 struct vfio_region_info info; 1216 struct vfio_region_info_ext info;
1119 u16 cap_type_id = 0;
1120 void *cap_type = NULL;
1121 1217
1122 minsz = offsetofend(struct vfio_region_info, offset); 1218 minsz = offsetofend(typeof(info), base.offset);
1123 1219
1124 if (copy_from_user(&info, (void __user *)arg, minsz)) 1220 if (copy_from_user(&info, (void __user *)arg, minsz))
1125 return -EFAULT; 1221 return -EFAULT;
1126 1222
1127 if (info.argsz < minsz) 1223 outsz = info.base.argsz;
1224 if (outsz < minsz)
1225 return -EINVAL;
1226 if (outsz > sizeof(info))
1128 return -EINVAL; 1227 return -EINVAL;
1129 1228
1130 ret = mbochs_get_region_info(mdev, &info, &cap_type_id, 1229 ret = mbochs_get_region_info(mdev, &info);
1131 &cap_type);
1132 if (ret) 1230 if (ret)
1133 return ret; 1231 return ret;
1134 1232
1135 if (copy_to_user((void __user *)arg, &info, minsz)) 1233 if (copy_to_user((void __user *)arg, &info, outsz))
1136 return -EFAULT; 1234 return -EFAULT;
1137 1235
1138 return 0; 1236 return 0;
@@ -1148,7 +1246,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
1148 return -EFAULT; 1246 return -EFAULT;
1149 1247
1150 if ((info.argsz < minsz) || 1248 if ((info.argsz < minsz) ||
1151 (info.index >= mdev_state->dev_info.num_irqs)) 1249 (info.index >= VFIO_PCI_NUM_IRQS))
1152 return -EINVAL; 1250 return -EINVAL;
1153 1251
1154 ret = mbochs_get_irq_info(mdev, &info); 1252 ret = mbochs_get_irq_info(mdev, &info);