From b0fccd926d2ee040ec590ca6439db237edf5c247 Mon Sep 17 00:00:00 2001 From: Mostafa Saleh Date: Tue, 25 Apr 2023 15:10:40 +0000 Subject: [PATCH] ANDROID: kvm/vfio: pviommu: Add set config IOCTL Add KVM_PVIOMMU_SET_CONFIG that allows user space to map an index in the device SID to a virtual SID. Bug: 357781595 Bug: 348382247 Bug: 236685427 Change-Id: I276c504573ed2564becd572e57a0b2710a1cf147 Signed-off-by: Mostafa Saleh --- include/uapi/linux/kvm.h | 20 ++++++++++++++++ virt/kvm/vfio.c | 50 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 3691c349ac85..d401e5abf0b1 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1165,6 +1165,26 @@ struct kvm_vfio_iommu_info { }; #define KVM_DEV_VFIO_PVIOMMU_GET_INFO 2 +/* pvIOMMU fd IOCTLs. */ + +/** + * struct kvm_vfio_iommu_info + * @size: sizeof(struct kvm_vfio_iommu_info) + * @device_fd: File descriptor for VFIO device + * @sid_idx: Index of sid (within number from KVM_DEV_VFIO_PVIOMMU_GET_INFO) + * @vsid: virtual SID visible to guest for this SID + * @__reserved: Must be 0 + * Configure KVM guest virtual view for a device IOMMU endpoints. + */ +struct kvm_vfio_iommu_config { + __u32 size; + __s32 device_fd; + __u32 sid_idx; + __u32 vsid; + __u32 __reserved; +}; +#define KVM_PVIOMMU_SET_CONFIG _IOWR(KVMIO, 0x1, struct kvm_vfio_iommu_config) + enum kvm_device_type { KVM_DEV_TYPE_FSL_MPIC_20 = 1, #define KVM_DEV_TYPE_FSL_MPIC_20 KVM_DEV_TYPE_FSL_MPIC_20 diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c index 5d59f53d17e8..1ebbd40beacf 100644 --- a/virt/kvm/vfio.c +++ b/virt/kvm/vfio.c @@ -357,10 +357,58 @@ static int kvm_vfio_set_file(struct kvm_device *dev, long attr, } #ifdef CONFIG_VFIO_PKVM_IOMMU +static int kvm_vfio_pviommu_set_config(struct file *fiommu, struct kvm_vfio_iommu_config *config) +{ + int vfio_dev_fd = config->device_fd; + struct file *filp; + int ret; + u32 phys_sid; + pkvm_handle_t iommu; + struct kvm_pviommu *pviommu = fiommu->private_data; + struct device *dev; + + filp = fget(vfio_dev_fd); + if (!filp) + return -EBADF; + + dev = kvm_vfio_file_get_device(filp); + if (!dev) { + ret = -ENODEV; + goto err_fput; + } + + ret = kvm_iommu_device_id(dev, config->sid_idx, &iommu, &phys_sid); + if (ret) + goto err_fput; + + ret = kvm_call_hyp_nvhe(__pkvm_pviommu_add_vsid, pviommu->dev->kvm, pviommu->fd, + iommu, phys_sid, config->vsid); + +err_fput: + fput(filp); + return ret; +} + static long pviommufd_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { - return -ENXIO; + struct kvm_vfio_iommu_config config; + __u32 usize; + + switch (ioctl) { + case KVM_PVIOMMU_SET_CONFIG: + if (copy_from_user(&usize, (void *)arg, sizeof(usize))) + return -EFAULT; + if (usize < offsetofend(struct kvm_vfio_iommu_config, __reserved)) + return -EINVAL; + if (copy_struct_from_user(&config, sizeof(config), (void *)arg, usize)) + return -EFAULT; + + return kvm_vfio_pviommu_set_config(filp, &config); + default: + return -ENXIO; + } + return 0; } static int pviommufd_release(struct inode *i, struct file *filp)