Commit e664067b authored by Jason Gunthorpe's avatar Jason Gunthorpe Committed by Alex Williamson
Browse files

vfio/gvt: Provide a get_region_info op

parent 61b3f7b5
Loading
Loading
Loading
Loading
+147 −148
Original line number Diff line number Diff line
@@ -1140,46 +1140,22 @@ static int intel_vgpu_set_irqs(struct intel_vgpu *vgpu, u32 flags,
	return func(vgpu, index, start, count, flags, data);
}

static long intel_vgpu_ioctl(struct vfio_device *vfio_dev, unsigned int cmd,
			     unsigned long arg)
static int intel_vgpu_ioctl_get_region_info(struct vfio_device *vfio_dev,
					    struct vfio_region_info __user *arg)
{
	struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev);
	unsigned long minsz;

	gvt_dbg_core("vgpu%d ioctl, cmd: %d\n", vgpu->id, cmd);

	if (cmd == VFIO_DEVICE_GET_INFO) {
		struct vfio_device_info info;

		minsz = offsetofend(struct vfio_device_info, num_irqs);

		if (copy_from_user(&info, (void __user *)arg, minsz))
			return -EFAULT;

		if (info.argsz < minsz)
			return -EINVAL;

		info.flags = VFIO_DEVICE_FLAGS_PCI;
		info.flags |= VFIO_DEVICE_FLAGS_RESET;
		info.num_regions = VFIO_PCI_NUM_REGIONS +
				vgpu->num_regions;
		info.num_irqs = VFIO_PCI_NUM_IRQS;

		return copy_to_user((void __user *)arg, &info, minsz) ?
			-EFAULT : 0;

	} else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
		struct vfio_region_info info;
	struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
		unsigned int i;
		int ret;
	struct vfio_region_info_cap_sparse_mmap *sparse = NULL;
	struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev);
	struct vfio_region_info info;
	unsigned long minsz;
	int nr_areas = 1;
	int cap_type_id;
	unsigned int i;
	int ret;

	minsz = offsetofend(struct vfio_region_info, offset);

		if (copy_from_user(&info, (void __user *)arg, minsz))
	if (copy_from_user(&info, arg, minsz))
		return -EFAULT;

	if (info.argsz < minsz)
@@ -1246,32 +1222,27 @@ static long intel_vgpu_ioctl(struct vfio_device *vfio_dev, unsigned int cmd,

		gvt_dbg_core("get region info index:%d\n", info.index);
		break;
		default:
			{
	default: {
		struct vfio_region_info_cap_type cap_type = {
			.header.id = VFIO_REGION_INFO_CAP_TYPE,
					.header.version = 1 };
			.header.version = 1
		};

				if (info.index >= VFIO_PCI_NUM_REGIONS +
						vgpu->num_regions)
		if (info.index >= VFIO_PCI_NUM_REGIONS + vgpu->num_regions)
			return -EINVAL;
				info.index =
					array_index_nospec(info.index,
							VFIO_PCI_NUM_REGIONS +
							vgpu->num_regions);
		info.index = array_index_nospec(
			info.index, VFIO_PCI_NUM_REGIONS + vgpu->num_regions);

		i = info.index - VFIO_PCI_NUM_REGIONS;

				info.offset =
					VFIO_PCI_INDEX_TO_OFFSET(info.index);
		info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
		info.size = vgpu->region[i].size;
		info.flags = vgpu->region[i].flags;

		cap_type.type = vgpu->region[i].type;
		cap_type.subtype = vgpu->region[i].subtype;

				ret = vfio_info_add_capability(&caps,
							&cap_type.header,
		ret = vfio_info_add_capability(&caps, &cap_type.header,
					       sizeof(cap_type));
		if (ret)
			return ret;
@@ -1281,10 +1252,9 @@ static long intel_vgpu_ioctl(struct vfio_device *vfio_dev, unsigned int cmd,
	if ((info.flags & VFIO_REGION_INFO_FLAG_CAPS) && sparse) {
		switch (cap_type_id) {
		case VFIO_REGION_INFO_CAP_SPARSE_MMAP:
				ret = vfio_info_add_capability(&caps,
					&sparse->header,
					struct_size(sparse, areas,
						    sparse->nr_areas));
			ret = vfio_info_add_capability(
				&caps, &sparse->header,
				struct_size(sparse, areas, sparse->nr_areas));
			if (ret) {
				kfree(sparse);
				return ret;
@@ -1303,9 +1273,8 @@ static long intel_vgpu_ioctl(struct vfio_device *vfio_dev, unsigned int cmd,
			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)) {
			if (copy_to_user((void __user *)arg + sizeof(info),
					 caps.buf, caps.size)) {
				kfree(caps.buf);
				kfree(sparse);
				return -EFAULT;
@@ -1317,8 +1286,37 @@ static long intel_vgpu_ioctl(struct vfio_device *vfio_dev, unsigned int cmd,
	}

	kfree(sparse);
	return copy_to_user(arg, &info, minsz) ? -EFAULT : 0;
}

static long intel_vgpu_ioctl(struct vfio_device *vfio_dev, unsigned int cmd,
			     unsigned long arg)
{
	struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev);
	unsigned long minsz;

	gvt_dbg_core("vgpu%d ioctl, cmd: %d\n", vgpu->id, cmd);

	if (cmd == VFIO_DEVICE_GET_INFO) {
		struct vfio_device_info info;

		minsz = offsetofend(struct vfio_device_info, num_irqs);

		if (copy_from_user(&info, (void __user *)arg, minsz))
			return -EFAULT;

		if (info.argsz < minsz)
			return -EINVAL;

		info.flags = VFIO_DEVICE_FLAGS_PCI;
		info.flags |= VFIO_DEVICE_FLAGS_RESET;
		info.num_regions = VFIO_PCI_NUM_REGIONS +
				vgpu->num_regions;
		info.num_irqs = VFIO_PCI_NUM_IRQS;

		return copy_to_user((void __user *)arg, &info, minsz) ?
			-EFAULT : 0;

	} else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) {
		struct vfio_irq_info info;

@@ -1475,6 +1473,7 @@ static const struct vfio_device_ops intel_vgpu_dev_ops = {
	.write		= intel_vgpu_write,
	.mmap		= intel_vgpu_mmap,
	.ioctl		= intel_vgpu_ioctl,
	.get_region_info = intel_vgpu_ioctl_get_region_info,
	.dma_unmap	= intel_vgpu_dma_unmap,
	.bind_iommufd	= vfio_iommufd_emulated_bind,
	.unbind_iommufd = vfio_iommufd_emulated_unbind,