Linux Documentation
 help / color / mirror / Atom feed
* [RFC v1 7/8] mshv: implement in-kernel device framework
       [not found] <20210709114339.3467637-1-wei.liu@kernel.org>
@ 2021-07-09 11:43 ` Wei Liu
  2021-07-09 13:02   ` Matthew Wilcox
  2021-08-03 19:12   ` Praveen Kumar
  0 siblings, 2 replies; 11+ messages in thread
From: Wei Liu @ 2021-07-09 11:43 UTC (permalink / raw)
  To: Linux on Hyper-V List
  Cc: virtualization, Linux Kernel List, Michael Kelley, Vineeth Pillai,
	Sunil Muthuswamy, Nuno Das Neves, kumarpraveen, pasha.tatashin,
	Wei Liu, Jonathan Corbet, K. Y. Srinivasan, Haiyang Zhang,
	Stephen Hemminger, Dexuan Cui, Lillian Grassin-Drake,
	Muminul Islam, open list:DOCUMENTATION

This is basically the same code adopted from KVM. The main user case is
the future MSHV-VFIO bridge device. We don't have any plan to support
in-kernel device emulation yet, but it wouldn't hurt to make the code
more flexible.

Signed-off-by: Wei Liu <wei.liu@kernel.org>
---
 Documentation/virt/mshv/api.rst |  12 +++
 drivers/hv/mshv_main.c          | 181 ++++++++++++++++++++++++++++++++
 include/linux/mshv.h            |  57 ++++++++++
 include/uapi/linux/mshv.h       |  36 +++++++
 4 files changed, 286 insertions(+)

diff --git a/Documentation/virt/mshv/api.rst b/Documentation/virt/mshv/api.rst
index 56a6edfcfe29..7d35dd589831 100644
--- a/Documentation/virt/mshv/api.rst
+++ b/Documentation/virt/mshv/api.rst
@@ -170,4 +170,16 @@ Can be used to get/set various properties of a partition.
 Some properties can only be set at partition creation. For these, there are
 parameters in MSHV_CREATE_PARTITION.
 
+3.12 MSHV_CREATE_DEVICE
+-----------------------
+:Type: partition ioctl
+:Parameters: struct mshv_create_device
+:Returns: 0 on success
+
+Can be used to create an in-kernel device.
+
+If the MSHV_CREATE_DEVICE_TEST flag is set, only test whether the
+device type is supported (not necessarily whether it can be created
+in the current vm).
 
+Currently only supports VFIO type device.
diff --git a/drivers/hv/mshv_main.c b/drivers/hv/mshv_main.c
index 4cbc520471e4..84c774a561de 100644
--- a/drivers/hv/mshv_main.c
+++ b/drivers/hv/mshv_main.c
@@ -20,6 +20,8 @@
 #include <linux/random.h>
 #include <linux/mshv.h>
 #include <linux/mshv_eventfd.h>
+#include <linux/hyperv.h>
+#include <linux/nospec.h>
 #include <asm/mshyperv.h>
 
 #include "mshv.h"
@@ -33,6 +35,7 @@ static int mshv_vp_release(struct inode *inode, struct file *filp);
 static long mshv_vp_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg);
 static struct mshv_partition *mshv_partition_get(struct mshv_partition *partition);
 static void mshv_partition_put(struct mshv_partition *partition);
+static void mshv_partition_put_no_destroy(struct mshv_partition *partition);
 static int mshv_partition_release(struct inode *inode, struct file *filp);
 static long mshv_partition_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg);
 static int mshv_dev_open(struct inode *inode, struct file *filp);
@@ -912,6 +915,172 @@ mshv_partition_ioctl_set_msi_routing(struct mshv_partition *partition,
 	return ret;
 }
 
+static int mshv_device_ioctl_attr(struct mshv_device *dev,
+				 int (*accessor)(struct mshv_device *dev,
+						 struct mshv_device_attr *attr),
+				 unsigned long arg)
+{
+	struct mshv_device_attr attr;
+
+	if (!accessor)
+		return -EPERM;
+
+	if (copy_from_user(&attr, (void __user *)arg, sizeof(attr)))
+		return -EFAULT;
+
+	return accessor(dev, &attr);
+}
+
+static long mshv_device_ioctl(struct file *filp, unsigned int ioctl,
+			      unsigned long arg)
+{
+	struct mshv_device *dev = filp->private_data;
+
+	switch (ioctl) {
+	case MSHV_SET_DEVICE_ATTR:
+		return mshv_device_ioctl_attr(dev, dev->ops->set_attr, arg);
+	case MSHV_GET_DEVICE_ATTR:
+		return mshv_device_ioctl_attr(dev, dev->ops->get_attr, arg);
+	case MSHV_HAS_DEVICE_ATTR:
+		return mshv_device_ioctl_attr(dev, dev->ops->has_attr, arg);
+	default:
+		if (dev->ops->ioctl)
+			return dev->ops->ioctl(dev, ioctl, arg);
+
+		return -ENOTTY;
+	}
+}
+
+static int mshv_device_release(struct inode *inode, struct file *filp)
+{
+	struct mshv_device *dev = filp->private_data;
+	struct mshv_partition *partition = dev->partition;
+
+	if (dev->ops->release) {
+		mutex_lock(&partition->mutex);
+		list_del(&dev->partition_node);
+		dev->ops->release(dev);
+		mutex_unlock(&partition->mutex);
+	}
+
+	mshv_partition_put(partition);
+	return 0;
+}
+
+static const struct file_operations mshv_device_fops = {
+	.unlocked_ioctl = mshv_device_ioctl,
+	.release = mshv_device_release,
+};
+
+static const struct mshv_device_ops *mshv_device_ops_table[MSHV_DEV_TYPE_MAX];
+
+int mshv_register_device_ops(const struct mshv_device_ops *ops, u32 type)
+{
+	if (type >= ARRAY_SIZE(mshv_device_ops_table))
+		return -ENOSPC;
+
+	if (mshv_device_ops_table[type] != NULL)
+		return -EEXIST;
+
+	mshv_device_ops_table[type] = ops;
+	return 0;
+}
+
+void mshv_unregister_device_ops(u32 type)
+{
+	if (type >= ARRAY_SIZE(mshv_device_ops_table))
+		return;
+	mshv_device_ops_table[type] = NULL;
+}
+
+static long
+mshv_partition_ioctl_create_device(struct mshv_partition *partition,
+	void __user *user_args)
+{
+	long r;
+	struct mshv_create_device tmp, *cd;
+	struct mshv_device *dev;
+	const struct mshv_device_ops *ops;
+	int type;
+
+	if (copy_from_user(&tmp, user_args, sizeof(tmp))) {
+		r = -EFAULT;
+		goto out;
+	}
+
+	cd = &tmp;
+
+	if (cd->type >= ARRAY_SIZE(mshv_device_ops_table)) {
+		r = -ENODEV;
+		goto out;
+	}
+
+	type = array_index_nospec(cd->type, ARRAY_SIZE(mshv_device_ops_table));
+	ops = mshv_device_ops_table[type];
+	if (ops == NULL) {
+		r = -ENODEV;
+		goto out;
+	}
+
+	if (cd->flags & MSHV_CREATE_DEVICE_TEST) {
+		r = 0;
+		goto out;
+	}
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL_ACCOUNT);
+	if (!dev) {
+		r = -ENOMEM;
+		goto out;
+	}
+
+	dev->ops = ops;
+	dev->partition = partition;
+
+	r = ops->create(dev, type);
+	if (r < 0) {
+		kfree(dev);
+		goto out;
+	}
+
+	list_add(&dev->partition_node, &partition->devices);
+
+	if (ops->init)
+		ops->init(dev);
+
+	mshv_partition_get(partition);
+	r = anon_inode_getfd(ops->name, &mshv_device_fops, dev, O_RDWR | O_CLOEXEC);
+	if (r < 0) {
+		mshv_partition_put_no_destroy(partition);
+		list_del(&dev->partition_node);
+		ops->destroy(dev);
+		goto out;
+	}
+
+	cd->fd = r;
+	r = 0;
+
+	if (copy_to_user(user_args, &tmp, sizeof(tmp))) {
+		r = -EFAULT;
+		goto out;
+	}
+out:
+	return r;
+}
+
+static void mshv_destroy_devices(struct mshv_partition *partition)
+{
+	struct mshv_device *dev, *tmp;
+
+	/*
+	 * No need to take any lock since at this point nobody else can
+	 * reference this partition.
+	 */
+	list_for_each_entry_safe(dev, tmp, &partition->devices, partition_node) {
+		list_del(&dev->partition_node);
+		dev->ops->destroy(dev);
+	}
+}
+
 static long
 mshv_partition_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
 {
@@ -965,6 +1134,9 @@ mshv_partition_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
 	case MSHV_GET_GPA_ACCESS_STATES:
 		ret = mshv_partition_ioctl_get_gpa_access_state(partition,
 							   (void __user *)arg);
+	case MSHV_CREATE_DEVICE:
+		ret = mshv_partition_ioctl_create_device(partition,
+							 (void __user *)arg);
 		break;
 	default:
 		ret = -ENOTTY;
@@ -1033,6 +1205,7 @@ destroy_partition(struct mshv_partition *partition)
 		vfree(region->pages);
 	}
 
+	mshv_destroy_devices(partition);
 	mshv_free_msi_routing(partition);
 	kfree(partition);
 }
@@ -1052,6 +1225,12 @@ mshv_partition_put(struct mshv_partition *partition)
 		destroy_partition(partition);
 }
 
+static void
+mshv_partition_put_no_destroy(struct mshv_partition *partition)
+{
+	WARN_ON(refcount_dec_and_test(&partition->ref_count));
+}
+
 static int
 mshv_partition_release(struct inode *inode, struct file *filp)
 {
@@ -1122,6 +1301,8 @@ mshv_ioctl_create_partition(void __user *user_arg)
 
 	INIT_HLIST_HEAD(&partition->irq_ack_notifier_list);
 
+	INIT_LIST_HEAD(&partition->devices);
+
 	fd = get_unused_fd_flags(O_CLOEXEC);
 	if (fd < 0) {
 		ret = fd;
diff --git a/include/linux/mshv.h b/include/linux/mshv.h
index fc655b60c5cd..c557ffeec90c 100644
--- a/include/linux/mshv.h
+++ b/include/linux/mshv.h
@@ -59,6 +59,8 @@ struct mshv_partition {
 	struct srcu_struct irq_srcu;
 	struct hlist_head irq_ack_notifier_list;
 
+	struct list_head devices;
+
 	struct {
 		spinlock_t        lock;
 		struct list_head  items;
@@ -121,4 +123,59 @@ struct mshv {
 	} partitions;
 };
 
+struct mshv_device {
+	const struct mshv_device_ops *ops;
+	struct mshv_partition *partition;
+	void *private;
+	struct list_head partition_node;
+
+};
+
+/* create, destroy, and name are mandatory */
+struct mshv_device_ops {
+	const char *name;
+
+	/*
+	 * create is called holding partition->mutex and any operations not suitable
+	 * to do while holding the lock should be deferred to init (see
+	 * below).
+	 */
+	int (*create)(struct mshv_device *dev, u32 type);
+
+	/*
+	 * init is called after create if create is successful and is called
+	 * outside of holding partition->mutex.
+	 */
+	void (*init)(struct mshv_device *dev);
+
+	/*
+	 * Destroy is responsible for freeing dev.
+	 *
+	 * Destroy may be called before or after destructors are called
+	 * on emulated I/O regions, depending on whether a reference is
+	 * held by a vcpu or other mshv component that gets destroyed
+	 * after the emulated I/O.
+	 */
+	void (*destroy)(struct mshv_device *dev);
+
+	/*
+	 * Release is an alternative method to free the device. It is
+	 * called when the device file descriptor is closed. Once
+	 * release is called, the destroy method will not be called
+	 * anymore as the device is removed from the device list of
+	 * the VM. partition->mutex is held.
+	 */
+	void (*release)(struct mshv_device *dev);
+
+	int (*set_attr)(struct mshv_device *dev, struct mshv_device_attr *attr);
+	int (*get_attr)(struct mshv_device *dev, struct mshv_device_attr *attr);
+	int (*has_attr)(struct mshv_device *dev, struct mshv_device_attr *attr);
+	long (*ioctl)(struct mshv_device *dev, unsigned int ioctl,
+		      unsigned long arg);
+	int (*mmap)(struct mshv_device *dev, struct vm_area_struct *vma);
+};
+
+int mshv_register_device_ops(const struct mshv_device_ops *ops, u32 type);
+void mshv_unregister_device_ops(u32 type);
+
 #endif
diff --git a/include/uapi/linux/mshv.h b/include/uapi/linux/mshv.h
index cba318ee7cf5..ed110109492f 100644
--- a/include/uapi/linux/mshv.h
+++ b/include/uapi/linux/mshv.h
@@ -158,6 +158,14 @@ struct mshv_msi_routing {
 #define MSHV_SET_VP_STATE	_IOWR(MSHV_IOCTL, 0x0B, struct mshv_vp_state)
 #define MSHV_TRANSLATE_GVA	_IOWR(MSHV_IOCTL, 0x0E, struct mshv_translate_gva)
 
+/* ioctl for device fd */
+#define MSHV_CREATE_DEVICE	  _IOWR(MSHV_IOCTL, 0x13, struct mshv_create_device)
+
+/* ioctls for fds returned by MSHV_CREATE_DEVICE */
+#define MSHV_SET_DEVICE_ATTR	  _IOW(MSHV_IOCTL, 0x14, struct mshv_device_attr)
+#define MSHV_GET_DEVICE_ATTR	  _IOW(MSHV_IOCTL, 0x15, struct mshv_device_attr)
+#define MSHV_HAS_DEVICE_ATTR	  _IOW(MSHV_IOCTL, 0x16, struct mshv_device_attr)
+
 /* register page mapping example:
  * struct hv_vp_register_page *regs = mmap(NULL,
  *					   4096,
@@ -184,4 +192,32 @@ union mshv_partition_property_page_access_tracking_config {
 	__u64 as_uint64;
 } __packed;
 
+/*
+ * Device control API.
+ */
+#define MSHV_CREATE_DEVICE_TEST		1
+
+struct mshv_create_device {
+	__u32	type;	/* in: MSHV_DEV_TYPE_xxx */
+	__u32	fd;	/* out: device handle */
+	__u32	flags;	/* in: MSHV_CREATE_DEVICE_xxx */
+};
+
+#define  MSHV_DEV_VFIO_GROUP			1
+#define   MSHV_DEV_VFIO_GROUP_ADD			1
+#define   MSHV_DEV_VFIO_GROUP_DEL			2
+
+enum mshv_device_type {
+	MSHV_DEV_TYPE_VFIO,
+#define MSHV_DEV_TYPE_VFIO		MSHV_DEV_TYPE_VFIO
+	MSHV_DEV_TYPE_MAX,
+};
+
+struct mshv_device_attr {
+	__u32	flags;		/* no flags currently defined */
+	__u32	group;		/* device-defined */
+	__u64	attr;		/* group-defined */
+	__u64	addr;		/* userspace address of attr data */
+};
+
 #endif
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [RFC v1 7/8] mshv: implement in-kernel device framework
  2021-07-09 11:43 ` [RFC v1 7/8] mshv: implement in-kernel device framework Wei Liu
@ 2021-07-09 13:02   ` Matthew Wilcox
  2021-07-09 13:50     ` Wei Liu
  2021-08-03 19:12   ` Praveen Kumar
  1 sibling, 1 reply; 11+ messages in thread
From: Matthew Wilcox @ 2021-07-09 13:02 UTC (permalink / raw)
  To: Wei Liu
  Cc: Linux on Hyper-V List, virtualization, Linux Kernel List,
	Michael Kelley, Vineeth Pillai, Sunil Muthuswamy, Nuno Das Neves,
	kumarpraveen, pasha.tatashin, Jonathan Corbet, K. Y. Srinivasan,
	Haiyang Zhang, Stephen Hemminger, Dexuan Cui,
	Lillian Grassin-Drake, Muminul Islam, open list:DOCUMENTATION

On Fri, Jul 09, 2021 at 11:43:38AM +0000, Wei Liu wrote:
> +static long
> +mshv_partition_ioctl_create_device(struct mshv_partition *partition,
> +	void __user *user_args)
> +{
[...]
> +	mshv_partition_get(partition);
> +	r = anon_inode_getfd(ops->name, &mshv_device_fops, dev, O_RDWR | O_CLOEXEC);
> +	if (r < 0) {
> +		mshv_partition_put_no_destroy(partition);
> +		list_del(&dev->partition_node);
> +		ops->destroy(dev);
> +		goto out;
> +	}
> +
> +	cd->fd = r;
> +	r = 0;

Why return the fd in memory instead of returning the fd as the return
value from the ioctl?

> +	if (copy_to_user(user_args, &tmp, sizeof(tmp))) {
> +		r = -EFAULT;
> +		goto out;
> +	}

... this could then disappear.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC v1 7/8] mshv: implement in-kernel device framework
  2021-07-09 13:02   ` Matthew Wilcox
@ 2021-07-09 13:50     ` Wei Liu
  2021-07-09 15:32       ` Matthew Wilcox
  0 siblings, 1 reply; 11+ messages in thread
From: Wei Liu @ 2021-07-09 13:50 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Wei Liu, Linux on Hyper-V List, virtualization, Linux Kernel List,
	Michael Kelley, Vineeth Pillai, Sunil Muthuswamy, Nuno Das Neves,
	kumarpraveen, pasha.tatashin, Jonathan Corbet, K. Y. Srinivasan,
	Haiyang Zhang, Stephen Hemminger, Dexuan Cui,
	Lillian Grassin-Drake, Muminul Islam, open list:DOCUMENTATION

On Fri, Jul 09, 2021 at 02:02:04PM +0100, Matthew Wilcox wrote:
> On Fri, Jul 09, 2021 at 11:43:38AM +0000, Wei Liu wrote:
> > +static long
> > +mshv_partition_ioctl_create_device(struct mshv_partition *partition,
> > +	void __user *user_args)
> > +{
> [...]
> > +	mshv_partition_get(partition);
> > +	r = anon_inode_getfd(ops->name, &mshv_device_fops, dev, O_RDWR | O_CLOEXEC);
> > +	if (r < 0) {
> > +		mshv_partition_put_no_destroy(partition);
> > +		list_del(&dev->partition_node);
> > +		ops->destroy(dev);
> > +		goto out;
> > +	}
> > +
> > +	cd->fd = r;
> > +	r = 0;
> 
> Why return the fd in memory instead of returning the fd as the return
> value from the ioctl?
> 
> > +	if (copy_to_user(user_args, &tmp, sizeof(tmp))) {
> > +		r = -EFAULT;
> > +		goto out;
> > +	}
> 
> ... this could then disappear.

Thanks for your comment, Matthew.

This is intentionally because I didn't want to deviate from KVM's API.
The fewer differences the better.

Wei.


> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC v1 7/8] mshv: implement in-kernel device framework
  2021-07-09 13:50     ` Wei Liu
@ 2021-07-09 15:32       ` Matthew Wilcox
  2021-07-09 16:27         ` Wei Liu
  0 siblings, 1 reply; 11+ messages in thread
From: Matthew Wilcox @ 2021-07-09 15:32 UTC (permalink / raw)
  To: Wei Liu
  Cc: Linux on Hyper-V List, virtualization, Linux Kernel List,
	Michael Kelley, Vineeth Pillai, Sunil Muthuswamy, Nuno Das Neves,
	kumarpraveen, pasha.tatashin, Jonathan Corbet, K. Y. Srinivasan,
	Haiyang Zhang, Stephen Hemminger, Dexuan Cui,
	Lillian Grassin-Drake, Muminul Islam, open list:DOCUMENTATION

On Fri, Jul 09, 2021 at 01:50:13PM +0000, Wei Liu wrote:
> On Fri, Jul 09, 2021 at 02:02:04PM +0100, Matthew Wilcox wrote:
> > On Fri, Jul 09, 2021 at 11:43:38AM +0000, Wei Liu wrote:
> > > +static long
> > > +mshv_partition_ioctl_create_device(struct mshv_partition *partition,
> > > +	void __user *user_args)
> > > +{
> > [...]
> > > +	mshv_partition_get(partition);
> > > +	r = anon_inode_getfd(ops->name, &mshv_device_fops, dev, O_RDWR | O_CLOEXEC);
> > > +	if (r < 0) {
> > > +		mshv_partition_put_no_destroy(partition);
> > > +		list_del(&dev->partition_node);
> > > +		ops->destroy(dev);
> > > +		goto out;
> > > +	}
> > > +
> > > +	cd->fd = r;
> > > +	r = 0;
> > 
> > Why return the fd in memory instead of returning the fd as the return
> > value from the ioctl?
> > 
> > > +	if (copy_to_user(user_args, &tmp, sizeof(tmp))) {
> > > +		r = -EFAULT;
> > > +		goto out;
> > > +	}
> > 
> > ... this could then disappear.
> 
> Thanks for your comment, Matthew.
> 
> This is intentionally because I didn't want to deviate from KVM's API.
> The fewer differences the better.

Then don't define your own structure.  Use theirs.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC v1 7/8] mshv: implement in-kernel device framework
  2021-07-09 15:32       ` Matthew Wilcox
@ 2021-07-09 16:27         ` Wei Liu
  2021-07-09 16:38           ` Matthew Wilcox
  0 siblings, 1 reply; 11+ messages in thread
From: Wei Liu @ 2021-07-09 16:27 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Wei Liu, Linux on Hyper-V List, virtualization, Linux Kernel List,
	Michael Kelley, Vineeth Pillai, Sunil Muthuswamy, Nuno Das Neves,
	kumarpraveen, pasha.tatashin, Jonathan Corbet, K. Y. Srinivasan,
	Haiyang Zhang, Stephen Hemminger, Dexuan Cui,
	Lillian Grassin-Drake, Muminul Islam, open list:DOCUMENTATION

On Fri, Jul 09, 2021 at 04:32:48PM +0100, Matthew Wilcox wrote:
> On Fri, Jul 09, 2021 at 01:50:13PM +0000, Wei Liu wrote:
> > On Fri, Jul 09, 2021 at 02:02:04PM +0100, Matthew Wilcox wrote:
> > > On Fri, Jul 09, 2021 at 11:43:38AM +0000, Wei Liu wrote:
> > > > +static long
> > > > +mshv_partition_ioctl_create_device(struct mshv_partition *partition,
> > > > +	void __user *user_args)
> > > > +{
> > > [...]
> > > > +	mshv_partition_get(partition);
> > > > +	r = anon_inode_getfd(ops->name, &mshv_device_fops, dev, O_RDWR | O_CLOEXEC);
> > > > +	if (r < 0) {
> > > > +		mshv_partition_put_no_destroy(partition);
> > > > +		list_del(&dev->partition_node);
> > > > +		ops->destroy(dev);
> > > > +		goto out;
> > > > +	}
> > > > +
> > > > +	cd->fd = r;
> > > > +	r = 0;
> > > 
> > > Why return the fd in memory instead of returning the fd as the return
> > > value from the ioctl?
> > > 
> > > > +	if (copy_to_user(user_args, &tmp, sizeof(tmp))) {
> > > > +		r = -EFAULT;
> > > > +		goto out;
> > > > +	}
> > > 
> > > ... this could then disappear.
> > 
> > Thanks for your comment, Matthew.
> > 
> > This is intentionally because I didn't want to deviate from KVM's API.
> > The fewer differences the better.
> 
> Then don't define your own structure.  Use theirs.

I specifically mentioned in the cover letter I didn't do it because I
was not sure if that would be acceptable. I guess I will find out.

Wei.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC v1 7/8] mshv: implement in-kernel device framework
  2021-07-09 16:27         ` Wei Liu
@ 2021-07-09 16:38           ` Matthew Wilcox
  2021-07-09 19:14             ` Wei Liu
  0 siblings, 1 reply; 11+ messages in thread
From: Matthew Wilcox @ 2021-07-09 16:38 UTC (permalink / raw)
  To: Wei Liu
  Cc: Linux on Hyper-V List, virtualization, Linux Kernel List,
	Michael Kelley, Vineeth Pillai, Sunil Muthuswamy, Nuno Das Neves,
	kumarpraveen, pasha.tatashin, Jonathan Corbet, K. Y. Srinivasan,
	Haiyang Zhang, Stephen Hemminger, Dexuan Cui,
	Lillian Grassin-Drake, Muminul Islam, open list:DOCUMENTATION

On Fri, Jul 09, 2021 at 04:27:32PM +0000, Wei Liu wrote:
> > Then don't define your own structure.  Use theirs.
> 
> I specifically mentioned in the cover letter I didn't do it because I
> was not sure if that would be acceptable. I guess I will find out.

I only got patch 7/8.  You can't blame me for not reading 0/8 if you
didn't send me 0/8.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC v1 7/8] mshv: implement in-kernel device framework
  2021-07-09 16:38           ` Matthew Wilcox
@ 2021-07-09 19:14             ` Wei Liu
  2021-07-09 19:48               ` Matthew Wilcox
  0 siblings, 1 reply; 11+ messages in thread
From: Wei Liu @ 2021-07-09 19:14 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Wei Liu, Linux on Hyper-V List, virtualization, Linux Kernel List,
	Michael Kelley, Vineeth Pillai, Sunil Muthuswamy, Nuno Das Neves,
	kumarpraveen, pasha.tatashin, Jonathan Corbet, K. Y. Srinivasan,
	Haiyang Zhang, Stephen Hemminger, Dexuan Cui,
	Lillian Grassin-Drake, Muminul Islam, open list:DOCUMENTATION

specifically On Fri, Jul 09, 2021 at 05:38:24PM +0100, Matthew Wilcox wrote:
> On Fri, Jul 09, 2021 at 04:27:32PM +0000, Wei Liu wrote:
> > > Then don't define your own structure.  Use theirs.
> > 
> > I specifically mentioned in the cover letter I didn't do it because I
> > was not sure if that would be acceptable. I guess I will find out.
> 
> I only got patch 7/8.  You can't blame me for not reading 0/8 if you
> didn't send me 0/8.

To be clear I did not blame you.

You were not CC'ed on this patch, so presumably you got it via one of
the mailing lists. I'm not sure why you only got this one patch. Perhaps
if you wait a bit you will get the rest.

But it is all good. I appreciate the fact that you took the time to go
over this patch and voiced your opinion.

Wei.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC v1 7/8] mshv: implement in-kernel device framework
  2021-07-09 19:14             ` Wei Liu
@ 2021-07-09 19:48               ` Matthew Wilcox
  2021-07-09 20:11                 ` Wei Liu
  0 siblings, 1 reply; 11+ messages in thread
From: Matthew Wilcox @ 2021-07-09 19:48 UTC (permalink / raw)
  To: Wei Liu
  Cc: Linux on Hyper-V List, virtualization, Linux Kernel List,
	Michael Kelley, Vineeth Pillai, Sunil Muthuswamy, Nuno Das Neves,
	kumarpraveen, pasha.tatashin, Jonathan Corbet, K. Y. Srinivasan,
	Haiyang Zhang, Stephen Hemminger, Dexuan Cui,
	Lillian Grassin-Drake, Muminul Islam, open list:DOCUMENTATION

On Fri, Jul 09, 2021 at 07:14:05PM +0000, Wei Liu wrote:
> You were not CC'ed on this patch, so presumably you got it via one of
> the mailing lists. I'm not sure why you only got this one patch. Perhaps
> if you wait a bit you will get the rest.

No, I won't.  You only cc'd linux-doc on this one patch and not on any
of the others.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC v1 7/8] mshv: implement in-kernel device framework
  2021-07-09 19:48               ` Matthew Wilcox
@ 2021-07-09 20:11                 ` Wei Liu
  0 siblings, 0 replies; 11+ messages in thread
From: Wei Liu @ 2021-07-09 20:11 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Wei Liu, Linux on Hyper-V List, virtualization, Linux Kernel List,
	Michael Kelley, Vineeth Pillai, Sunil Muthuswamy, Nuno Das Neves,
	kumarpraveen, pasha.tatashin, Jonathan Corbet, K. Y. Srinivasan,
	Haiyang Zhang, Stephen Hemminger, Dexuan Cui,
	Lillian Grassin-Drake, Muminul Islam, open list:DOCUMENTATION

On Fri, Jul 09, 2021 at 08:48:36PM +0100, Matthew Wilcox wrote:
> On Fri, Jul 09, 2021 at 07:14:05PM +0000, Wei Liu wrote:
> > You were not CC'ed on this patch, so presumably you got it via one of
> > the mailing lists. I'm not sure why you only got this one patch. Perhaps
> > if you wait a bit you will get the rest.
> 
> No, I won't.  You only cc'd linux-doc on this one patch and not on any
> of the others.

I see. That's because get_maintainers.pl only detected changes to the
doc in this file.

If you're interested in having a look at the other patches, they can
be fetched via at the following url. 

https://lore.kernel.org/linux-hyperv/20210709114339.3467637-1-wei.liu@kernel.org/

Thanks for your attention.

Wei.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC v1 7/8] mshv: implement in-kernel device framework
  2021-07-09 11:43 ` [RFC v1 7/8] mshv: implement in-kernel device framework Wei Liu
  2021-07-09 13:02   ` Matthew Wilcox
@ 2021-08-03 19:12   ` Praveen Kumar
  2021-08-03 22:04     ` Wei Liu
  1 sibling, 1 reply; 11+ messages in thread
From: Praveen Kumar @ 2021-08-03 19:12 UTC (permalink / raw)
  To: Wei Liu, Linux on Hyper-V List
  Cc: virtualization, Linux Kernel List, Michael Kelley, Vineeth Pillai,
	Sunil Muthuswamy, Nuno Das Neves, pasha.tatashin, Jonathan Corbet,
	K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger, Dexuan Cui,
	Lillian Grassin-Drake, Muminul Islam, open list:DOCUMENTATION

On 09-07-2021 17:13, Wei Liu wrote:
> This is basically the same code adopted from KVM. The main user case is
> the future MSHV-VFIO bridge device. We don't have any plan to support
> in-kernel device emulation yet, but it wouldn't hurt to make the code
> more flexible.
> 
> Signed-off-by: Wei Liu <wei.liu@kernel.org>
> ---
>  Documentation/virt/mshv/api.rst |  12 +++
>  drivers/hv/mshv_main.c          | 181 ++++++++++++++++++++++++++++++++
>  include/linux/mshv.h            |  57 ++++++++++
>  include/uapi/linux/mshv.h       |  36 +++++++
>  4 files changed, 286 insertions(+)
> 
> diff --git a/Documentation/virt/mshv/api.rst b/Documentation/virt/mshv/api.rst
> index 56a6edfcfe29..7d35dd589831 100644
> --- a/Documentation/virt/mshv/api.rst
> +++ b/Documentation/virt/mshv/api.rst
> @@ -170,4 +170,16 @@ Can be used to get/set various properties of a partition.
>  Some properties can only be set at partition creation. For these, there are
>  parameters in MSHV_CREATE_PARTITION.
>  
> +3.12 MSHV_CREATE_DEVICE
> +-----------------------
> +:Type: partition ioctl
> +:Parameters: struct mshv_create_device
> +:Returns: 0 on success
> +
> +Can be used to create an in-kernel device.
> +
> +If the MSHV_CREATE_DEVICE_TEST flag is set, only test whether the
> +device type is supported (not necessarily whether it can be created
> +in the current vm).
>  
> +Currently only supports VFIO type device.
> diff --git a/drivers/hv/mshv_main.c b/drivers/hv/mshv_main.c
> index 4cbc520471e4..84c774a561de 100644
> --- a/drivers/hv/mshv_main.c
> +++ b/drivers/hv/mshv_main.c
> @@ -20,6 +20,8 @@
>  #include <linux/random.h>
>  #include <linux/mshv.h>
>  #include <linux/mshv_eventfd.h>
> +#include <linux/hyperv.h>
> +#include <linux/nospec.h>
>  #include <asm/mshyperv.h>
>  
>  #include "mshv.h"
> @@ -33,6 +35,7 @@ static int mshv_vp_release(struct inode *inode, struct file *filp);
>  static long mshv_vp_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg);
>  static struct mshv_partition *mshv_partition_get(struct mshv_partition *partition);
>  static void mshv_partition_put(struct mshv_partition *partition);
> +static void mshv_partition_put_no_destroy(struct mshv_partition *partition);
>  static int mshv_partition_release(struct inode *inode, struct file *filp);
>  static long mshv_partition_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg);
>  static int mshv_dev_open(struct inode *inode, struct file *filp);
> @@ -912,6 +915,172 @@ mshv_partition_ioctl_set_msi_routing(struct mshv_partition *partition,
>  	return ret;
>  }
>  
> +static int mshv_device_ioctl_attr(struct mshv_device *dev,
> +				 int (*accessor)(struct mshv_device *dev,
> +						 struct mshv_device_attr *attr),
> +				 unsigned long arg)
> +{
> +	struct mshv_device_attr attr;
> +
> +	if (!accessor)
> +		return -EPERM;
> +
> +	if (copy_from_user(&attr, (void __user *)arg, sizeof(attr)))
> +		return -EFAULT;
> +
> +	return accessor(dev, &attr);
> +}
> +
> +static long mshv_device_ioctl(struct file *filp, unsigned int ioctl,
> +			      unsigned long arg)
> +{
> +	struct mshv_device *dev = filp->private_data;
> +
> +	switch (ioctl) {
> +	case MSHV_SET_DEVICE_ATTR:
> +		return mshv_device_ioctl_attr(dev, dev->ops->set_attr, arg);
> +	case MSHV_GET_DEVICE_ATTR:
> +		return mshv_device_ioctl_attr(dev, dev->ops->get_attr, arg);
> +	case MSHV_HAS_DEVICE_ATTR:
> +		return mshv_device_ioctl_attr(dev, dev->ops->has_attr, arg);
> +	default:
> +		if (dev->ops->ioctl)
> +			return dev->ops->ioctl(dev, ioctl, arg);
> +
> +		return -ENOTTY;
> +	}

Have seen some static analyzer tool cribbing here of not returning any error.
If you feel OK, please move the 'return -ENOTTY' down after switch block. Thanks.

> +}
> +
> +static int mshv_device_release(struct inode *inode, struct file *filp)
> +{
> +	struct mshv_device *dev = filp->private_data;
> +	struct mshv_partition *partition = dev->partition;
> +
> +	if (dev->ops->release) {
> +		mutex_lock(&partition->mutex);
> +		list_del(&dev->partition_node);
> +		dev->ops->release(dev);
> +		mutex_unlock(&partition->mutex);
> +	}
> +
> +	mshv_partition_put(partition);
> +	return 0;
> +}
> +
> +static const struct file_operations mshv_device_fops = {
> +	.unlocked_ioctl = mshv_device_ioctl,
> +	.release = mshv_device_release,
> +};
> +
> +static const struct mshv_device_ops *mshv_device_ops_table[MSHV_DEV_TYPE_MAX];
> +
> +int mshv_register_device_ops(const struct mshv_device_ops *ops, u32 type)
> +{
> +	if (type >= ARRAY_SIZE(mshv_device_ops_table))
> +		return -ENOSPC;
> +
> +	if (mshv_device_ops_table[type] != NULL)
> +		return -EEXIST;
> +
> +	mshv_device_ops_table[type] = ops;
> +	return 0;
> +}
> +
> +void mshv_unregister_device_ops(u32 type)
> +{
> +	if (type >= ARRAY_SIZE(mshv_device_ops_table))
> +		return;
> +	mshv_device_ops_table[type] = NULL;
> +}
> +
> +static long
> +mshv_partition_ioctl_create_device(struct mshv_partition *partition,
> +	void __user *user_args)
> +{
> +	long r;
> +	struct mshv_create_device tmp, *cd;
> +	struct mshv_device *dev;
> +	const struct mshv_device_ops *ops;
> +	int type;
> +
> +	if (copy_from_user(&tmp, user_args, sizeof(tmp))) {
> +		r = -EFAULT;
> +		goto out;
> +	}
> +
> +	cd = &tmp;
> +
> +	if (cd->type >= ARRAY_SIZE(mshv_device_ops_table)) {
> +		r = -ENODEV;
> +		goto out;
> +	}
> +
> +	type = array_index_nospec(cd->type, ARRAY_SIZE(mshv_device_ops_table));
> +	ops = mshv_device_ops_table[type];
> +	if (ops == NULL) {
> +		r = -ENODEV;
> +		goto out;
> +	}
> +
> +	if (cd->flags & MSHV_CREATE_DEVICE_TEST) {
> +		r = 0;
> +		goto out;
> +	}
> +
> +	dev = kzalloc(sizeof(*dev), GFP_KERNEL_ACCOUNT);
> +	if (!dev) {
> +		r = -ENOMEM;
> +		goto out;
> +	}
> +
> +	dev->ops = ops;
> +	dev->partition = partition;
> +
> +	r = ops->create(dev, type);
> +	if (r < 0) {
> +		kfree(dev);
> +		goto out;
> +	}
> +
> +	list_add(&dev->partition_node, &partition->devices);
> +
> +	if (ops->init)
> +		ops->init(dev);
> +
> +	mshv_partition_get(partition);
> +	r = anon_inode_getfd(ops->name, &mshv_device_fops, dev, O_RDWR | O_CLOEXEC);
> +	if (r < 0) {
> +		mshv_partition_put_no_destroy(partition);
> +		list_del(&dev->partition_node);
> +		ops->destroy(dev);

I hope ops->destroy will free dev as well ?

> +		goto out;
> +	}
> +
> +	cd->fd = r;
> +	r = 0;
> +
> +	if (copy_to_user(user_args, &tmp, sizeof(tmp))) {
> +		r = -EFAULT;

I don't think we will be cleaning up anything ? Or do we need to?
> +		goto out;
> +	}
> +out:
> +	return r;
> +}
> +

Regards,

~Praveen.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC v1 7/8] mshv: implement in-kernel device framework
  2021-08-03 19:12   ` Praveen Kumar
@ 2021-08-03 22:04     ` Wei Liu
  0 siblings, 0 replies; 11+ messages in thread
From: Wei Liu @ 2021-08-03 22:04 UTC (permalink / raw)
  To: Praveen Kumar
  Cc: Wei Liu, Linux on Hyper-V List, virtualization, Linux Kernel List,
	Michael Kelley, Vineeth Pillai, Sunil Muthuswamy, Nuno Das Neves,
	pasha.tatashin, Jonathan Corbet, K. Y. Srinivasan, Haiyang Zhang,
	Stephen Hemminger, Dexuan Cui, Lillian Grassin-Drake,
	Muminul Islam, open list:DOCUMENTATION

On Wed, Aug 04, 2021 at 12:42:22AM +0530, Praveen Kumar wrote:
> On 09-07-2021 17:13, Wei Liu wrote:
[...]
> > +static long mshv_device_ioctl(struct file *filp, unsigned int ioctl,
> > +			      unsigned long arg)
> > +{
> > +	struct mshv_device *dev = filp->private_data;
> > +
> > +	switch (ioctl) {
> > +	case MSHV_SET_DEVICE_ATTR:
> > +		return mshv_device_ioctl_attr(dev, dev->ops->set_attr, arg);
> > +	case MSHV_GET_DEVICE_ATTR:
> > +		return mshv_device_ioctl_attr(dev, dev->ops->get_attr, arg);
> > +	case MSHV_HAS_DEVICE_ATTR:
> > +		return mshv_device_ioctl_attr(dev, dev->ops->has_attr, arg);
> > +	default:
> > +		if (dev->ops->ioctl)
> > +			return dev->ops->ioctl(dev, ioctl, arg);
> > +
> > +		return -ENOTTY;
> > +	}
> 
> Have seen some static analyzer tool cribbing here of not returning any error.
> If you feel OK, please move the 'return -ENOTTY' down after switch block. Thanks.
> 

Fair point. I will make the change.

> > +}
> > +
[...]
> > +static long
> > +mshv_partition_ioctl_create_device(struct mshv_partition *partition,
> > +	void __user *user_args)
> > +{
> > +	long r;
> > +	struct mshv_create_device tmp, *cd;
> > +	struct mshv_device *dev;
> > +	const struct mshv_device_ops *ops;
> > +	int type;
> > +
> > +	if (copy_from_user(&tmp, user_args, sizeof(tmp))) {
> > +		r = -EFAULT;
> > +		goto out;
> > +	}
> > +
> > +	cd = &tmp;
> > +
> > +	if (cd->type >= ARRAY_SIZE(mshv_device_ops_table)) {
> > +		r = -ENODEV;
> > +		goto out;
> > +	}
> > +
> > +	type = array_index_nospec(cd->type, ARRAY_SIZE(mshv_device_ops_table));
> > +	ops = mshv_device_ops_table[type];
> > +	if (ops == NULL) {
> > +		r = -ENODEV;
> > +		goto out;
> > +	}
> > +
> > +	if (cd->flags & MSHV_CREATE_DEVICE_TEST) {
> > +		r = 0;
> > +		goto out;
> > +	}
> > +
> > +	dev = kzalloc(sizeof(*dev), GFP_KERNEL_ACCOUNT);
> > +	if (!dev) {
> > +		r = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	dev->ops = ops;
> > +	dev->partition = partition;
> > +
> > +	r = ops->create(dev, type);
> > +	if (r < 0) {
> > +		kfree(dev);
> > +		goto out;
> > +	}
> > +
> > +	list_add(&dev->partition_node, &partition->devices);
> > +
> > +	if (ops->init)
> > +		ops->init(dev);
> > +
> > +	mshv_partition_get(partition);
> > +	r = anon_inode_getfd(ops->name, &mshv_device_fops, dev, O_RDWR | O_CLOEXEC);
> > +	if (r < 0) {
> > +		mshv_partition_put_no_destroy(partition);
> > +		list_del(&dev->partition_node);
> > +		ops->destroy(dev);
> 
> I hope ops->destroy will free dev as well ?

Yes. It is clearly written in the preceding comment of that hook. I hope
that's prominent enough.

> 
> > +		goto out;
> > +	}
> > +
> > +	cd->fd = r;
> > +	r = 0;
> > +
> > +	if (copy_to_user(user_args, &tmp, sizeof(tmp))) {
> > +		r = -EFAULT;
> 
> I don't think we will be cleaning up anything ? Or do we need to?

No need. Whatever residuals left will be cleaned up once the VM is
destroyed.

Wei.

> > +		goto out;
> > +	}
> > +out:
> > +	return r;
> > +}
> > +
> 
> Regards,
> 
> ~Praveen.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2021-08-03 22:04 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20210709114339.3467637-1-wei.liu@kernel.org>
2021-07-09 11:43 ` [RFC v1 7/8] mshv: implement in-kernel device framework Wei Liu
2021-07-09 13:02   ` Matthew Wilcox
2021-07-09 13:50     ` Wei Liu
2021-07-09 15:32       ` Matthew Wilcox
2021-07-09 16:27         ` Wei Liu
2021-07-09 16:38           ` Matthew Wilcox
2021-07-09 19:14             ` Wei Liu
2021-07-09 19:48               ` Matthew Wilcox
2021-07-09 20:11                 ` Wei Liu
2021-08-03 19:12   ` Praveen Kumar
2021-08-03 22:04     ` Wei Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox