Hi All: This series introduces API for reporing IOVA range. This is a must for userspace to work correclty: - for the process that uses vhost-vDPA directly to properly allocate IOVA - for VM(qemu), when vIOMMU is not enabled, fail early if GPA is out of range - for VM(qemu), when vIOMMU is enabled, determine a valid guest address width Please review. Changes from V1: - do not mandate get_iova_range() for device with its own DMA translation logic and assume a [0, ULLONG_MAX] range - mandate IOVA range only for IOMMU that forcing aperture - forbid the map which is out of the IOVA range in vhost-vDPA Thanks Jason Wang (3): vdpa: introduce config op to get valid iova range vhost: vdpa: report iova range vdpa_sim: implement get_iova_range() drivers/vdpa/vdpa_sim/vdpa_sim.c | 12 ++++++++++ drivers/vhost/vdpa.c | 41 ++++++++++++++++++++++++++++++++ include/linux/vdpa.h | 15 ++++++++++++ include/uapi/linux/vhost.h | 4 ++++ include/uapi/linux/vhost_types.h | 9 +++++++ 5 files changed, 81 insertions(+) -- 2.18.1
Jason Wang
2020-Aug-21 09:28 UTC
[PATCH V2 1/3] vdpa: introduce config op to get valid iova range
This patch introduce a config op to get valid iova range from the vDPA device. Signed-off-by: Jason Wang <jasowang at redhat.com> --- include/linux/vdpa.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/linux/vdpa.h b/include/linux/vdpa.h index eae0bfd87d91..30bc7a7223bb 100644 --- a/include/linux/vdpa.h +++ b/include/linux/vdpa.h @@ -52,6 +52,16 @@ struct vdpa_device { int nvqs; }; +/** + * vDPA IOVA range - the IOVA range support by the device + * @first: start of the IOVA range + * @last: end of the IOVA range + */ +struct vdpa_iova_range { + u64 first; + u64 last; +}; + /** * vDPA_config_ops - operations for configuring a vDPA device. * Note: vDPA device drivers are required to implement all of the @@ -151,6 +161,10 @@ struct vdpa_device { * @get_generation: Get device config generation (optional) * @vdev: vdpa device * Returns u32: device generation + * @get_iova_range: Get supported iova range (optional) + * @vdev: vdpa device + * Returns the iova range supported by + * the device. * @set_map: Set device memory mapping (optional) * Needed for device that using device * specific DMA translation (on-chip IOMMU) @@ -216,6 +230,7 @@ struct vdpa_config_ops { void (*set_config)(struct vdpa_device *vdev, unsigned int offset, const void *buf, unsigned int len); u32 (*get_generation)(struct vdpa_device *vdev); + struct vdpa_iova_range (*get_iova_range)(struct vdpa_device *vdev); /* DMA ops */ int (*set_map)(struct vdpa_device *vdev, struct vhost_iotlb *iotlb); -- 2.18.1
This patch introduces a new ioctl for vhost-vdpa device that can report the iova range by the device. For device that implements get_iova_range() method, we fetch it from the vDPA device. If device doesn't implement get_iova_range() but depends on platform IOMMU, we will query via DOMAIN_ATTR_GEOMETRY, otherwise [0, ULLONG_MAX] is assumed. For safety, this patch also rules out the map request which is not in the valid range. Signed-off-by: Jason Wang <jasowang at redhat.com> --- drivers/vhost/vdpa.c | 41 ++++++++++++++++++++++++++++++++ include/uapi/linux/vhost.h | 4 ++++ include/uapi/linux/vhost_types.h | 9 +++++++ 3 files changed, 54 insertions(+) diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index 3fab94f88894..1adb4adb0345 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -48,6 +48,7 @@ struct vhost_vdpa { int minor; struct eventfd_ctx *config_ctx; int in_batch; + struct vdpa_iova_range range; }; static DEFINE_IDA(vhost_vdpa_ida); @@ -344,6 +345,16 @@ static long vhost_vdpa_set_config_call(struct vhost_vdpa *v, u32 __user *argp) return 0; } +static long vhost_vdpa_get_iova_range(struct vhost_vdpa *v, u32 __user *argp) +{ + struct vhost_vdpa_iova_range range = { + .first = v->range.first, + .last = v->range.last, + }; + + return copy_to_user(argp, &range, sizeof(range)); +} + static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd, void __user *argp) { @@ -476,6 +487,9 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep, case VHOST_VDPA_SET_CONFIG_CALL: r = vhost_vdpa_set_config_call(v, argp); break; + case VHOST_VDPA_GET_IOVA_RANGE: + r = vhost_vdpa_get_iova_range(v, argp); + break; default: r = vhost_dev_ioctl(&v->vdev, cmd, argp); if (r == -ENOIOCTLCMD) @@ -597,6 +611,10 @@ static int vhost_vdpa_process_iotlb_update(struct vhost_vdpa *v, u64 iova = msg->iova; int ret = 0; + if (msg->iova < v->range.first || + msg->iova + msg->size - 1 > v->range.last) + return -EINVAL; + if (vhost_iotlb_itree_first(iotlb, msg->iova, msg->iova + msg->size - 1)) return -EEXIST; @@ -762,6 +780,27 @@ static void vhost_vdpa_free_domain(struct vhost_vdpa *v) v->domain = NULL; } +static void vhost_vdpa_set_iova_range(struct vhost_vdpa *v) +{ + struct vdpa_iova_range *range = &v->range; + struct iommu_domain_geometry geo; + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + + if (ops->get_iova_range) { + *range = ops->get_iova_range(vdpa); + } else if (v->domain && + !iommu_domain_get_attr(v->domain, + DOMAIN_ATTR_GEOMETRY, &geo) && + geo.force_aperture) { + range->first = geo.aperture_start; + range->last = geo.aperture_end; + } else { + range->first = 0; + range->last = ULLONG_MAX; + } +} + static int vhost_vdpa_open(struct inode *inode, struct file *filep) { struct vhost_vdpa *v; @@ -802,6 +841,8 @@ static int vhost_vdpa_open(struct inode *inode, struct file *filep) if (r) goto err_init_iotlb; + vhost_vdpa_set_iova_range(v); + filep->private_data = v; return 0; diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h index 75232185324a..c998860d7bbc 100644 --- a/include/uapi/linux/vhost.h +++ b/include/uapi/linux/vhost.h @@ -146,4 +146,8 @@ /* Set event fd for config interrupt*/ #define VHOST_VDPA_SET_CONFIG_CALL _IOW(VHOST_VIRTIO, 0x77, int) + +/* Get the valid iova range */ +#define VHOST_VDPA_GET_IOVA_RANGE _IOR(VHOST_VIRTIO, 0x78, \ + struct vhost_vdpa_iova_range) #endif diff --git a/include/uapi/linux/vhost_types.h b/include/uapi/linux/vhost_types.h index 9a269a88a6ff..f7f6a3a28977 100644 --- a/include/uapi/linux/vhost_types.h +++ b/include/uapi/linux/vhost_types.h @@ -138,6 +138,15 @@ struct vhost_vdpa_config { __u8 buf[0]; }; +/* vhost vdpa IOVA range + * @first: First address that can be mapped by vhost-vDPA + * @last: Last address that can be mapped by vhost-vDPA + */ +struct vhost_vdpa_iova_range { + __u64 first; + __u64 last; +}; + /* Feature bits */ /* Log all write descriptors. Can be changed while device is active. */ #define VHOST_F_LOG_ALL 26 -- 2.18.1
Signed-off-by: Jason Wang <jasowang at redhat.com> --- drivers/vdpa/vdpa_sim/vdpa_sim.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c index 62d640327145..89854e17c3c2 100644 --- a/drivers/vdpa/vdpa_sim/vdpa_sim.c +++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c @@ -574,6 +574,16 @@ static u32 vdpasim_get_generation(struct vdpa_device *vdpa) return vdpasim->generation; } +struct vdpa_iova_range vdpasim_get_iova_range(struct vdpa_device *vdpa) +{ + struct vdpa_iova_range range = { + .first = 0ULL, + .last = ULLONG_MAX, + }; + + return range; +} + static int vdpasim_set_map(struct vdpa_device *vdpa, struct vhost_iotlb *iotlb) { @@ -657,6 +667,7 @@ static const struct vdpa_config_ops vdpasim_net_config_ops = { .get_config = vdpasim_get_config, .set_config = vdpasim_set_config, .get_generation = vdpasim_get_generation, + .get_iova_range = vdpasim_get_iova_range, .dma_map = vdpasim_dma_map, .dma_unmap = vdpasim_dma_unmap, .free = vdpasim_free, @@ -683,6 +694,7 @@ static const struct vdpa_config_ops vdpasim_net_batch_config_ops = { .get_config = vdpasim_get_config, .set_config = vdpasim_set_config, .get_generation = vdpasim_get_generation, + .get_iova_range = vdpasim_get_iova_range, .set_map = vdpasim_set_map, .free = vdpasim_free, }; -- 2.18.1
kernel test robot
2020-Aug-21 10:33 UTC
[PATCH V2 3/3] vdpa_sim: implement get_iova_range()
Hi Jason, I love your patch! Perhaps something to improve: [auto build test WARNING on vhost/linux-next] [also build test WARNING on linus/master v5.9-rc1 next-20200821] [cannot apply to linux/master] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Jason-Wang/vDPA-API-for-reporting-IOVA-range/20200821-173030 base: https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git linux-next config: ia64-allmodconfig (attached as .config) compiler: ia64-linux-gcc (GCC) 9.3.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=ia64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp at intel.com> All warnings (new ones prefixed by >>):>> drivers/vdpa/vdpa_sim/vdpa_sim.c:577:24: warning: no previous prototype for 'vdpasim_get_iova_range' [-Wmissing-prototypes]577 | struct vdpa_iova_range vdpasim_get_iova_range(struct vdpa_device *vdpa) | ^~~~~~~~~~~~~~~~~~~~~~ # https://github.com/0day-ci/linux/commit/fba5ff6281e9d46144860bcc558068b5516e5e62 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Jason-Wang/vDPA-API-for-reporting-IOVA-range/20200821-173030 git checkout fba5ff6281e9d46144860bcc558068b5516e5e62 vim +/vdpasim_get_iova_range +577 drivers/vdpa/vdpa_sim/vdpa_sim.c 576 > 577 struct vdpa_iova_range vdpasim_get_iova_range(struct vdpa_device *vdpa) 578 { 579 struct vdpa_iova_range range = { 580 .first = 0ULL, 581 .last = ULLONG_MAX, 582 }; 583 584 return range; 585 } 586 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all at lists.01.org -------------- next part -------------- A non-text attachment was scrubbed... Name: .config.gz Type: application/gzip Size: 61150 bytes Desc: not available URL: <http://lists.linuxfoundation.org/pipermail/virtualization/attachments/20200821/014b732e/attachment-0001.gz>
kernel test robot
2020-Aug-21 12:20 UTC
[PATCH V2 3/3] vdpa_sim: implement get_iova_range()
Hi Jason, I love your patch! Perhaps something to improve: [auto build test WARNING on vhost/linux-next] [also build test WARNING on linus/master v5.9-rc1 next-20200821] [cannot apply to linux/master] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Jason-Wang/vDPA-API-for-reporting-IOVA-range/20200821-173030 base: https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git linux-next config: i386-randconfig-s001-20200820 (attached as .config) compiler: gcc-9 (Debian 9.3.0-15) 9.3.0 reproduce: # apt-get install sparse # sparse version: v0.6.2-191-g10164920-dirty # save the attached .config to linux build tree make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=i386 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp at intel.com> sparse warnings: (new ones prefixed by >>)>> drivers/vdpa/vdpa_sim/vdpa_sim.c:577:24: sparse: sparse: symbol 'vdpasim_get_iova_range' was not declared. Should it be static?Please review and possibly fold the followup patch. --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all at lists.01.org -------------- next part -------------- A non-text attachment was scrubbed... Name: .config.gz Type: application/gzip Size: 31826 bytes Desc: not available URL: <http://lists.linuxfoundation.org/pipermail/virtualization/attachments/20200821/2c1cc7e2/attachment-0001.gz>
kernel test robot
2020-Aug-21 12:20 UTC
[RFC PATCH] vdpa_sim: vdpasim_get_iova_range() can be static
Signed-off-by: kernel test robot <lkp at intel.com> --- vdpa_sim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c index 89854e17c3c27b..ff6c9fd8d879bd 100644 --- a/drivers/vdpa/vdpa_sim/vdpa_sim.c +++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c @@ -574,7 +574,7 @@ static u32 vdpasim_get_generation(struct vdpa_device *vdpa) return vdpasim->generation; } -struct vdpa_iova_range vdpasim_get_iova_range(struct vdpa_device *vdpa) +static struct vdpa_iova_range vdpasim_get_iova_range(struct vdpa_device *vdpa) { struct vdpa_iova_range range = { .first = 0ULL,
kernel test robot
2020-Aug-21 12:51 UTC
[PATCH V2 3/3] vdpa_sim: implement get_iova_range()
Hi Jason, I love your patch! Perhaps something to improve: [auto build test WARNING on vhost/linux-next] [also build test WARNING on linus/master v5.9-rc1 next-20200821] [cannot apply to linux/master] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Jason-Wang/vDPA-API-for-reporting-IOVA-range/20200821-173030 base: https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git linux-next config: arm-randconfig-r026-20200820 (attached as .config) compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project b587ca93be114d07ec3bf654add97d7872325281) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install arm cross compiling tool for clang build # apt-get install binutils-arm-linux-gnueabi # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=arm If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp at intel.com> All warnings (new ones prefixed by >>):>> drivers/vdpa/vdpa_sim/vdpa_sim.c:577:24: warning: no previous prototype for function 'vdpasim_get_iova_range' [-Wmissing-prototypes]struct vdpa_iova_range vdpasim_get_iova_range(struct vdpa_device *vdpa) ^ drivers/vdpa/vdpa_sim/vdpa_sim.c:577:1: note: declare 'static' if the function is not intended to be used outside of this translation unit struct vdpa_iova_range vdpasim_get_iova_range(struct vdpa_device *vdpa) ^ static drivers/vdpa/vdpa_sim/vdpa_sim.c:89:19: warning: unused function 'vdpasim16_to_cpu' [-Wunused-function] static inline u16 vdpasim16_to_cpu(struct vdpasim *vdpasim, __virtio16 val) ^ 2 warnings generated. # https://github.com/0day-ci/linux/commit/fba5ff6281e9d46144860bcc558068b5516e5e62 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Jason-Wang/vDPA-API-for-reporting-IOVA-range/20200821-173030 git checkout fba5ff6281e9d46144860bcc558068b5516e5e62 vim +/vdpasim_get_iova_range +577 drivers/vdpa/vdpa_sim/vdpa_sim.c 576 > 577 struct vdpa_iova_range vdpasim_get_iova_range(struct vdpa_device *vdpa) 578 { 579 struct vdpa_iova_range range = { 580 .first = 0ULL, 581 .last = ULLONG_MAX, 582 }; 583 584 return range; 585 } 586 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all at lists.01.org -------------- next part -------------- A non-text attachment was scrubbed... Name: .config.gz Type: application/gzip Size: 29940 bytes Desc: not available URL: <http://lists.linuxfoundation.org/pipermail/virtualization/attachments/20200821/2e08eb49/attachment-0001.gz>
kernel test robot
2020-Aug-21 12:59 UTC
[PATCH V2 3/3] vdpa_sim: implement get_iova_range()
Hi Jason, I love your patch! Perhaps something to improve: [auto build test WARNING on vhost/linux-next] [also build test WARNING on linus/master v5.9-rc1 next-20200821] [cannot apply to linux/master] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Jason-Wang/vDPA-API-for-reporting-IOVA-range/20200821-173030 base: https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git linux-next config: x86_64-randconfig-a002-20200820 (attached as .config) compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project b587ca93be114d07ec3bf654add97d7872325281) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install x86_64 cross compiling tool for clang build # apt-get install binutils-x86-64-linux-gnu # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp at intel.com> All warnings (new ones prefixed by >>):>> drivers/vdpa/vdpa_sim/vdpa_sim.c:577:24: warning: no previous prototype for function 'vdpasim_get_iova_range' [-Wmissing-prototypes]struct vdpa_iova_range vdpasim_get_iova_range(struct vdpa_device *vdpa) ^ drivers/vdpa/vdpa_sim/vdpa_sim.c:577:1: note: declare 'static' if the function is not intended to be used outside of this translation unit struct vdpa_iova_range vdpasim_get_iova_range(struct vdpa_device *vdpa) ^ static drivers/vdpa/vdpa_sim/vdpa_sim.c:89:19: warning: unused function 'vdpasim16_to_cpu' [-Wunused-function] static inline u16 vdpasim16_to_cpu(struct vdpasim *vdpasim, __virtio16 val) ^ 2 warnings generated. # https://github.com/0day-ci/linux/commit/fba5ff6281e9d46144860bcc558068b5516e5e62 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Jason-Wang/vDPA-API-for-reporting-IOVA-range/20200821-173030 git checkout fba5ff6281e9d46144860bcc558068b5516e5e62 vim +/vdpasim_get_iova_range +577 drivers/vdpa/vdpa_sim/vdpa_sim.c 576 > 577 struct vdpa_iova_range vdpasim_get_iova_range(struct vdpa_device *vdpa) 578 { 579 struct vdpa_iova_range range = { 580 .first = 0ULL, 581 .last = ULLONG_MAX, 582 }; 583 584 return range; 585 } 586 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all at lists.01.org -------------- next part -------------- A non-text attachment was scrubbed... Name: .config.gz Type: application/gzip Size: 41815 bytes Desc: not available URL: <http://lists.linuxfoundation.org/pipermail/virtualization/attachments/20200821/f627d3dd/attachment-0001.gz>
On 2020/8/23 ??2:40, Eli Cohen wrote:>> +static void vhost_vdpa_set_iova_range(struct vhost_vdpa *v) >> +{ >> + struct vdpa_iova_range *range = &v->range; >> + struct iommu_domain_geometry geo; >> + struct vdpa_device *vdpa = v->vdpa; >> + const struct vdpa_config_ops *ops = vdpa->config; >> + >> + if (ops->get_iova_range) { >> + *range = ops->get_iova_range(vdpa); >> + } else if (v->domain && >> + !iommu_domain_get_attr(v->domain, >> + DOMAIN_ATTR_GEOMETRY, &geo) && >> + geo.force_aperture) { >> + range->first = geo.aperture_start; >> + range->last = geo.aperture_end; >> + } else { >> + range->first = 0; >> + range->last = ULLONG_MAX; >> + } > Shouldn't we require drivers that publish VIRTIO_F_ACCESS_PLATFORM to > implement get_iova_range?Probably not, since ACCESS_PLATFORM does not exclude the device that depends on the chipset IOMMU to work. So in that case, we should query IOMMU driver instead of vDPA device driver. Thanks> >> +}