if (vdev->reset_works)
                        info.flags |= VFIO_DEVICE_FLAGS_RESET;
  
-               info.num_regions = VFIO_PCI_NUM_REGIONS;
+               info.num_regions = VFIO_PCI_NUM_REGIONS + vdev->num_regions;
                info.num_irqs = VFIO_PCI_NUM_IRQS;
  
 -              return copy_to_user((void __user *)arg, &info, minsz);
 +              return copy_to_user((void __user *)arg, &info, minsz) ?
 +                      -EFAULT : 0;
  
        } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
                struct pci_dev *pdev = vdev->pdev;
  
                        break;
                default:
-                       return -EINVAL;
+                       if (info.index >=
+                           VFIO_PCI_NUM_REGIONS + vdev->num_regions)
+                               return -EINVAL;
+ 
+                       i = info.index - VFIO_PCI_NUM_REGIONS;
+ 
+                       info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
+                       info.size = vdev->region[i].size;
+                       info.flags = vdev->region[i].flags;
+ 
+                       ret = region_type_cap(vdev, &caps,
+                                             vdev->region[i].type,
+                                             vdev->region[i].subtype);
+                       if (ret)
+                               return ret;
+               }
+ 
+               if (caps.size) {
+                       info.flags |= VFIO_REGION_INFO_FLAG_CAPS;
+                       if (info.argsz < sizeof(info) + caps.size) {
+                               info.argsz = sizeof(info) + caps.size;
+                               info.cap_offset = 0;
+                       } else {
+                               vfio_info_cap_shift(&caps, sizeof(info));
+                               if (copy_to_user((void __user *)arg +
+                                                 sizeof(info), caps.buf,
+                                                 caps.size)) {
+                                       kfree(caps.buf);
+                                       return -EFAULT;
+                               }
+                               info.cap_offset = sizeof(info);
+                       }
+ 
+                       kfree(caps.buf);
                }
  
 -              return copy_to_user((void __user *)arg, &info, minsz);
 +              return copy_to_user((void __user *)arg, &info, minsz) ?
 +                      -EFAULT : 0;
  
        } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) {
                struct vfio_irq_info info;