diff mbox series

[v1,4/8] vfio: Check nesting iommu uAPI version

Message ID 1584880325-10561-5-git-send-email-yi.l.liu@intel.com (mailing list archive)
State New, archived
Headers show
Series vfio: expose virtual Shared Virtual Addressing to VMs | expand

Commit Message

Yi Liu March 22, 2020, 12:32 p.m. UTC
From: Liu Yi L <yi.l.liu@intel.com>

In Linux Kernel, the IOMMU nesting translation (a.k.a dual stage address
translation) capability is abstracted in uapi/iommu.h, in which the uAPIs
like bind_gpasid/iommu_cache_invalidate/fault_report/pgreq_resp are defined.

VFIO_TYPE1_NESTING_IOMMU stands for the vfio iommu type which is backed by
hardware IOMMU w/ dual stage translation capability. For such vfio iommu
type, userspace is able to setup dual stage DMA translation in host side
via VFIO's ABI. However, such VFIO ABIs rely on the uAPIs defined in uapi/
iommu.h. So VFIO needs to provide an API to userspace for the uapi/iommu.h
version check to ensure the iommu uAPI compatibility.

This patch reports the iommu uAPI version to userspace in VFIO_CHECK_EXTENSION
IOCTL. Applications could do version check before further setup dual stage
translation in host IOMMU.

Cc: Kevin Tian <kevin.tian@intel.com>
CC: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Signed-off-by: Liu Yi L <yi.l.liu@intel.com>
---
 drivers/vfio/vfio_iommu_type1.c | 2 ++
 include/uapi/linux/vfio.h       | 9 +++++++++
 2 files changed, 11 insertions(+)

Comments

kernel test robot March 22, 2020, 6:30 p.m. UTC | #1
Hi Yi,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on vfio/next]
[also build test ERROR on v5.6-rc6 next-20200320]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Liu-Yi-L/vfio-expose-virtual-Shared-Virtual-Addressing-to-VMs/20200322-213259
base:   https://github.com/awilliam/linux-vfio.git next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gcc (GCC) 9.2.0
reproduce:
        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
        GCC_VERSION=9.2.0 make.cross ARCH=arm64 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/vfio/vfio_iommu_type1.c: In function 'vfio_iommu_type1_ioctl':
>> drivers/vfio/vfio_iommu_type1.c:2299:11: error: implicit declaration of function 'iommu_get_uapi_version' [-Werror=implicit-function-declaration]
    2299 |    return iommu_get_uapi_version();
         |           ^~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/iommu_get_uapi_version +2299 drivers/vfio/vfio_iommu_type1.c

  2281	
  2282	static long vfio_iommu_type1_ioctl(void *iommu_data,
  2283					   unsigned int cmd, unsigned long arg)
  2284	{
  2285		struct vfio_iommu *iommu = iommu_data;
  2286		unsigned long minsz;
  2287	
  2288		if (cmd == VFIO_CHECK_EXTENSION) {
  2289			switch (arg) {
  2290			case VFIO_TYPE1_IOMMU:
  2291			case VFIO_TYPE1v2_IOMMU:
  2292			case VFIO_TYPE1_NESTING_IOMMU:
  2293				return 1;
  2294			case VFIO_DMA_CC_IOMMU:
  2295				if (!iommu)
  2296					return 0;
  2297				return vfio_domains_have_iommu_cache(iommu);
  2298			case VFIO_NESTING_IOMMU_UAPI:
> 2299				return iommu_get_uapi_version();
  2300			default:
  2301				return 0;
  2302			}
  2303		} else if (cmd == VFIO_IOMMU_GET_INFO) {
  2304			struct vfio_iommu_type1_info info;
  2305			struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
  2306			unsigned long capsz;
  2307			int ret;
  2308	
  2309			minsz = offsetofend(struct vfio_iommu_type1_info, iova_pgsizes);
  2310	
  2311			/* For backward compatibility, cannot require this */
  2312			capsz = offsetofend(struct vfio_iommu_type1_info, cap_offset);
  2313	
  2314			if (copy_from_user(&info, (void __user *)arg, minsz))
  2315				return -EFAULT;
  2316	
  2317			if (info.argsz < minsz)
  2318				return -EINVAL;
  2319	
  2320			if (info.argsz >= capsz) {
  2321				minsz = capsz;
  2322				info.cap_offset = 0; /* output, no-recopy necessary */
  2323			}
  2324	
  2325			info.flags = VFIO_IOMMU_INFO_PGSIZES;
  2326	
  2327			info.iova_pgsizes = vfio_pgsize_bitmap(iommu);
  2328	
  2329			ret = vfio_iommu_iova_build_caps(iommu, &caps);
  2330			if (ret)
  2331				return ret;
  2332	
  2333			ret = vfio_iommu_info_add_nesting_cap(iommu, &caps);
  2334			if (ret)
  2335				return ret;
  2336	
  2337			if (caps.size) {
  2338				info.flags |= VFIO_IOMMU_INFO_CAPS;
  2339	
  2340				if (info.argsz < sizeof(info) + caps.size) {
  2341					info.argsz = sizeof(info) + caps.size;
  2342				} else {
  2343					vfio_info_cap_shift(&caps, sizeof(info));
  2344					if (copy_to_user((void __user *)arg +
  2345							sizeof(info), caps.buf,
  2346							caps.size)) {
  2347						kfree(caps.buf);
  2348						return -EFAULT;
  2349					}
  2350					info.cap_offset = sizeof(info);
  2351				}
  2352	
  2353				kfree(caps.buf);
  2354			}
  2355	
  2356			return copy_to_user((void __user *)arg, &info, minsz) ?
  2357				-EFAULT : 0;
  2358	
  2359		} else if (cmd == VFIO_IOMMU_MAP_DMA) {
  2360			struct vfio_iommu_type1_dma_map map;
  2361			uint32_t mask = VFIO_DMA_MAP_FLAG_READ |
  2362					VFIO_DMA_MAP_FLAG_WRITE;
  2363	
  2364			minsz = offsetofend(struct vfio_iommu_type1_dma_map, size);
  2365	
  2366			if (copy_from_user(&map, (void __user *)arg, minsz))
  2367				return -EFAULT;
  2368	
  2369			if (map.argsz < minsz || map.flags & ~mask)
  2370				return -EINVAL;
  2371	
  2372			return vfio_dma_do_map(iommu, &map);
  2373	
  2374		} else if (cmd == VFIO_IOMMU_UNMAP_DMA) {
  2375			struct vfio_iommu_type1_dma_unmap unmap;
  2376			long ret;
  2377	
  2378			minsz = offsetofend(struct vfio_iommu_type1_dma_unmap, size);
  2379	
  2380			if (copy_from_user(&unmap, (void __user *)arg, minsz))
  2381				return -EFAULT;
  2382	
  2383			if (unmap.argsz < minsz || unmap.flags)
  2384				return -EINVAL;
  2385	
  2386			ret = vfio_dma_do_unmap(iommu, &unmap);
  2387			if (ret)
  2388				return ret;
  2389	
  2390			return copy_to_user((void __user *)arg, &unmap, minsz) ?
  2391				-EFAULT : 0;
  2392	
  2393		} else if (cmd == VFIO_IOMMU_PASID_REQUEST) {
  2394			struct vfio_iommu_type1_pasid_request req;
  2395			unsigned long offset;
  2396	
  2397			minsz = offsetofend(struct vfio_iommu_type1_pasid_request,
  2398					    flags);
  2399	
  2400			if (copy_from_user(&req, (void __user *)arg, minsz))
  2401				return -EFAULT;
  2402	
  2403			if (req.argsz < minsz ||
  2404			    !vfio_iommu_type1_pasid_req_valid(req.flags))
  2405				return -EINVAL;
  2406	
  2407			if (copy_from_user((void *)&req + minsz,
  2408					   (void __user *)arg + minsz,
  2409					   sizeof(req) - minsz))
  2410				return -EFAULT;
  2411	
  2412			switch (req.flags & VFIO_PASID_REQUEST_MASK) {
  2413			case VFIO_IOMMU_PASID_ALLOC:
  2414			{
  2415				int ret = 0, result;
  2416	
  2417				result = vfio_iommu_type1_pasid_alloc(iommu,
  2418								req.alloc_pasid.min,
  2419								req.alloc_pasid.max);
  2420				if (result > 0) {
  2421					offset = offsetof(
  2422						struct vfio_iommu_type1_pasid_request,
  2423						alloc_pasid.result);
  2424					ret = copy_to_user(
  2425						      (void __user *) (arg + offset),
  2426						      &result, sizeof(result));
  2427				} else {
  2428					pr_debug("%s: PASID alloc failed\n", __func__);
  2429					ret = -EFAULT;
  2430				}
  2431				return ret;
  2432			}
  2433			case VFIO_IOMMU_PASID_FREE:
  2434				return vfio_iommu_type1_pasid_free(iommu,
  2435								   req.free_pasid);
  2436			default:
  2437				return -EINVAL;
  2438			}
  2439		}
  2440	
  2441		return -ENOTTY;
  2442	}
  2443	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index ddd1ffe..9aa2a67 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -2274,6 +2274,8 @@  static long vfio_iommu_type1_ioctl(void *iommu_data,
 			if (!iommu)
 				return 0;
 			return vfio_domains_have_iommu_cache(iommu);
+		case VFIO_NESTING_IOMMU_UAPI:
+			return iommu_get_uapi_version();
 		default:
 			return 0;
 		}
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 8837219..ed9881d 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -47,6 +47,15 @@ 
 #define VFIO_NOIOMMU_IOMMU		8
 
 /*
+ * Hardware IOMMUs with two-stage translation capability give userspace
+ * the ownership of stage-1 translation structures (e.g. page tables).
+ * VFIO exposes the two-stage IOMMU programming capability to userspace
+ * based on the IOMMU UAPIs. Therefore user of VFIO_TYPE1_NESTING should
+ * check the IOMMU UAPI version compatibility.
+ */
+#define VFIO_NESTING_IOMMU_UAPI		9
+
+/*
  * The IOCTL interface is designed for extensibility by embedding the
  * structure length (argsz) and flags into structures passed between
  * kernel and userspace.  We therefore use the _IO() macro for these