每一个virt设备都要定义vfio-pci region,标准的vfio-pci region数量为9。通过传入的offset知道要访问的是哪一个bar。
/** The VFIO-PCI bus driver makes use of the following fixed region and* IRQ index mapping. Unimplemented regions return a size of zero.* Unimplemented IRQ types return a count of zero.*/enum {VFIO_PCI_BAR0_REGION_INDEX,VFIO_PCI_BAR1_REGION_INDEX,VFIO_PCI_BAR2_REGION_INDEX,VFIO_PCI_BAR3_REGION_INDEX,VFIO_PCI_BAR4_REGION_INDEX,VFIO_PCI_BAR5_REGION_INDEX,VFIO_PCI_ROM_REGION_INDEX,VFIO_PCI_CONFIG_REGION_INDEX,/** Expose VGA regions defined for PCI base class 03, subclass 00.* This includes I/O port ranges 0x3b0 to 0x3bb and 0x3c0 to 0x3df* as well as the MMIO range 0xa0000 to 0xbffff. Each implemented* range is found at it's identity mapped offset from the region* offset, for example 0x3b0 is region_info.offset + 0x3b0. Areas* between described ranges are unimplemented.*/VFIO_PCI_VGA_REGION_INDEX,VFIO_PCI_NUM_REGIONS = 9 /* Fixed user ABI, region indexes >=9 use *//* device specific cap to define content. */
};
i915中关于这一层的代码调用,这一层就是对bar的模拟
@linux5.15/drivers/gpu/drm/i915/gvt/kvmgt.c
static struct mdev_parent_ops intel_vgpu_ops = {.mdev_attr_groups = intel_vgpu_groups,.create = intel_vgpu_create,.remove = intel_vgpu_remove,.open_device = intel_vgpu_open_device,.close_device = intel_vgpu_close_device,.read = intel_vgpu_read,.write = intel_vgpu_write,.mmap = intel_vgpu_mmap,.ioctl = intel_vgpu_ioctl,
};static int kvmgt_host_init(struct device *dev, void *gvt, const void *ops)
{int ret;ret = intel_gvt_init_vgpu_type_groups((struct intel_gvt *)gvt);if (ret)return ret;intel_gvt_ops = ops;intel_vgpu_ops.supported_type_groups = gvt_vgpu_type_groups;ret = mdev_register_device(dev, &intel_vgpu_ops);if (ret)intel_gvt_cleanup_vgpu_type_groups((struct intel_gvt *)gvt);return ret;
}static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf,size_t count, loff_t *ppos, bool is_write)
{struct intel_vgpu *vgpu = mdev_get_drvdata(mdev);struct kvmgt_vdev *vdev = kvmgt_vdev(vgpu);unsigned int index = VFIO_PCI_OFFSET_TO_INDEX(*ppos);u64 pos = *ppos & VFIO_PCI_OFFSET_MASK;int ret = -EINVAL;if (index >= VFIO_PCI_NUM_REGIONS + vdev->num_regions) {gvt_vgpu_err("invalid index: %u\n", index);return -EINVAL;}switch (index) {case VFIO_PCI_CONFIG_REGION_INDEX:if (is_write)ret = intel_gvt_ops->emulate_cfg_write(vgpu, pos,buf, count);elseret = intel_gvt_ops->emulate_cfg_read(vgpu, pos,buf, count);break;case VFIO_PCI_BAR0_REGION_INDEX:ret = intel_vgpu_bar_rw(vgpu, PCI_BASE_ADDRESS_0, pos,buf, count, is_write);break;case VFIO_PCI_BAR2_REGION_INDEX:ret = intel_vgpu_aperture_rw(vgpu, pos, buf, count, is_write);break;case VFIO_PCI_BAR1_REGION_INDEX:case VFIO_PCI_BAR3_REGION_INDEX:case VFIO_PCI_BAR4_REGION_INDEX:case VFIO_PCI_BAR5_REGION_INDEX:case VFIO_PCI_VGA_REGION_INDEX:case VFIO_PCI_ROM_REGION_INDEX:break;default:if (index >= VFIO_PCI_NUM_REGIONS + vdev->num_regions)return -EINVAL;index -= VFIO_PCI_NUM_REGIONS;return vdev->region[index].ops->rw(vgpu, buf, count,ppos, is_write);}return ret == 0 ? count : ret;
}static ssize_t intel_vgpu_read(struct mdev_device *mdev, char __user *buf,size_t count, loff_t *ppos)
{unsigned int done = 0;int ret;while (count) {size_t filled;/* Only support GGTT entry 8 bytes read */if (count >= 8 && !(*ppos % 8) &>t_entry(mdev, ppos)) {u64 val;ret = intel_vgpu_rw(mdev, (char *)&val, sizeof(val),ppos, false);if (ret <= 0)goto read_err;if (copy_to_user(buf, &val, sizeof(val)))goto read_err;filled = 8;} else if (count >= 4 && !(*ppos % 4)) {u32 val;ret = intel_vgpu_rw(mdev, (char *)&val, sizeof(val),ppos, false);if (ret <= 0)goto read_err;if (copy_to_user(buf, &val, sizeof(val)))goto read_err;filled = 4;} else if (count >= 2 && !(*ppos % 2)) {u16 val;ret = intel_vgpu_rw(mdev, (char *)&val, sizeof(val),ppos, false);if (ret <= 0)goto read_err;if (copy_to_user(buf, &val, sizeof(val)))goto read_err;filled = 2;} else {u8 val;ret = intel_vgpu_rw(mdev, &val, sizeof(val), ppos,false);if (ret <= 0)goto read_err;if (copy_to_user(buf, &val, sizeof(val)))goto read_err;filled = 1;}count -= filled;done += filled;*ppos += filled;buf += filled;}return done;read_err:return -EFAULT;
}
