All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gleb Natapov <gleb@redhat.com>
To: Scott Wood <scottwood@freescale.com>
Cc: Alexander Graf <agraf@suse.de>,
	kvm-ppc@vger.kernel.org, kvm@vger.kernel.org, paulus@samba.org
Subject: Re: [PATCH v4 1/6] kvm: add device control API
Date: Thu, 25 Apr 2013 09:43:24 +0000	[thread overview]
Message-ID: <20130425094324.GY12401@redhat.com> (raw)
In-Reply-To: <1365811727-24431-2-git-send-email-scottwood@freescale.com>

On Fri, Apr 12, 2013 at 07:08:42PM -0500, Scott Wood wrote:
> Currently, devices that are emulated inside KVM are configured in a
> hardcoded manner based on an assumption that any given architecture
> only has one way to do it.  If there's any need to access device state,
> it is done through inflexible one-purpose-only IOCTLs (e.g.
> KVM_GET/SET_LAPIC).  Defining new IOCTLs for every little thing is
> cumbersome and depletes a limited numberspace.
> 
> This API provides a mechanism to instantiate a device of a certain
> type, returning an ID that can be used to set/get attributes of the
> device.  Attributes may include configuration parameters (e.g.
> register base address), device state, operational commands, etc.  It
> is similar to the ONE_REG API, except that it acts on devices rather
> than vcpus.
> 
> Both device types and individual attributes can be tested without having
> to create the device or get/set the attribute, without the need for
> separately managing enumerated capabilities.
> 
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---
> v4:
>  - Move some boilerplate back into generic code, as requested by Gleb.
>    File descriptor management and reference counting is no longer the
>    concern of the device implementation.
> 
>  - Don't hold kvm->lock during create.  The original reasons
>    for doing so have vanished as for as MPIC is concerned, and
>    this avoids needing to answer the question of whether to
>    hold the lock during destroy as well.
> 
>    Paul, you may need to acquire the lock yourself in kvm_create_xics()
>    to protect the -EEXIST check.
> 
> v3: remove some changes that were merged into this patch by accident,
> and fix the error documentation for KVM_CREATE_DEVICE.
> ---
>  Documentation/virtual/kvm/api.txt        |   70 ++++++++++++++++
>  Documentation/virtual/kvm/devices/README |    1 +
>  include/linux/kvm_host.h                 |   35 ++++++++
>  include/uapi/linux/kvm.h                 |   27 +++++++
>  virt/kvm/kvm_main.c                      |  129 ++++++++++++++++++++++++++++++
>  5 files changed, 262 insertions(+)
>  create mode 100644 Documentation/virtual/kvm/devices/README
> 
> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> index 976eb65..d52f3f9 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -2173,6 +2173,76 @@ header; first `n_valid' valid entries with contents from the data
>  written, then `n_invalid' invalid entries, invalidating any previously
>  valid entries found.
>  
> +4.79 KVM_CREATE_DEVICE
> +
> +Capability: KVM_CAP_DEVICE_CTRL
> +Type: vm ioctl
> +Parameters: struct kvm_create_device (in/out)
> +Returns: 0 on success, -1 on error
> +Errors:
> +  ENODEV: The device type is unknown or unsupported
> +  EEXIST: Device already created, and this type of device may not
> +          be instantiated multiple times
> +
> +  Other error conditions may be defined by individual device types or
> +  have their standard meanings.
> +
> +Creates an emulated device in the kernel.  The file descriptor returned
> +in fd can be used with KVM_SET/GET/HAS_DEVICE_ATTR.
> +
> +If the KVM_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).
> +
> +Individual devices should not define flags.  Attributes should be used
> +for specifying any behavior that is not implied by the device type
> +number.
> +
> +struct kvm_create_device {
> +	__u32	type;	/* in: KVM_DEV_TYPE_xxx */
> +	__u32	fd;	/* out: device handle */
> +	__u32	flags;	/* in: KVM_CREATE_DEVICE_xxx */
> +};
Should we add __u32 padding here to make struct size multiple of u64?

> +
> +4.80 KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR
> +
> +Capability: KVM_CAP_DEVICE_CTRL
> +Type: device ioctl
> +Parameters: struct kvm_device_attr
> +Returns: 0 on success, -1 on error
> +Errors:
> +  ENXIO:  The group or attribute is unknown/unsupported for this device
> +  EPERM:  The attribute cannot (currently) be accessed this way
> +          (e.g. read-only attribute, or attribute that only makes
> +          sense when the device is in a different state)
> +
> +  Other error conditions may be defined by individual device types.
> +
> +Gets/sets a specified piece of device configuration and/or state.  The
> +semantics are device-specific.  See individual device documentation in
> +the "devices" directory.  As with ONE_REG, the size of the data
> +transferred is defined by the particular attribute.
> +
> +struct kvm_device_attr {
> +	__u32	flags;		/* no flags currently defined */
> +	__u32	group;		/* device-defined */
> +	__u64	attr;		/* group-defined */
> +	__u64	addr;		/* userspace address of attr data */
> +};
> +
> +4.81 KVM_HAS_DEVICE_ATTR
> +
> +Capability: KVM_CAP_DEVICE_CTRL
> +Type: device ioctl
> +Parameters: struct kvm_device_attr
> +Returns: 0 on success, -1 on error
> +Errors:
> +  ENXIO:  The group or attribute is unknown/unsupported for this device
> +
> +Tests whether a device supports a particular attribute.  A successful
> +return indicates the attribute is implemented.  It does not necessarily
> +indicate that the attribute can be read or written in the device's
> +current state.  "addr" is ignored.
>  
>  4.77 KVM_ARM_VCPU_INIT
>  
> diff --git a/Documentation/virtual/kvm/devices/README b/Documentation/virtual/kvm/devices/README
> new file mode 100644
> index 0000000..34a6983
> --- /dev/null
> +++ b/Documentation/virtual/kvm/devices/README
> @@ -0,0 +1 @@
> +This directory contains specific device bindings for KVM_CAP_DEVICE_CTRL.
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 20d77d2..8fce9bc 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -1063,6 +1063,41 @@ static inline bool kvm_check_request(int req, struct kvm_vcpu *vcpu)
>  
>  extern bool kvm_rebooting;
>  
> +struct kvm_device_ops;
> +
> +struct kvm_device {
> +	struct kvm_device_ops *ops;
> +	struct kvm *kvm;
> +	atomic_t users;
> +	void *private;
> +};
> +
> +/* create, destroy, and name are mandatory */
> +struct kvm_device_ops {
> +	const char *name;
> +	int (*create)(struct kvm_device *dev, u32 type);
> +
> +	/*
> +	 * 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 kvm component that gets destroyed
> +	 * after the emulated I/O.
> +	 */
> +	void (*destroy)(struct kvm_device *dev);
> +
> +	int (*set_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
> +	int (*get_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
> +	int (*has_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
> +	long (*ioctl)(struct kvm_device *dev, unsigned int ioctl,
> +		      unsigned long arg);
> +};
> +
> +void kvm_device_get(struct kvm_device *dev);
> +void kvm_device_put(struct kvm_device *dev);
> +struct kvm_device *kvm_device_from_filp(struct file *filp);
> +
>  #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT
>  
>  static inline void kvm_vcpu_set_in_spin_loop(struct kvm_vcpu *vcpu, bool val)
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 74d0ff3..20ce2d2 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -668,6 +668,7 @@ struct kvm_ppc_smmu_info {
>  #define KVM_CAP_PPC_EPR 86
>  #define KVM_CAP_ARM_PSCI 87
>  #define KVM_CAP_ARM_SET_DEVICE_ADDR 88
> +#define KVM_CAP_DEVICE_CTRL 89
>  
>  #ifdef KVM_CAP_IRQ_ROUTING
>  
> @@ -909,6 +910,32 @@ struct kvm_s390_ucas_mapping {
>  #define KVM_ARM_SET_DEVICE_ADDR	  _IOW(KVMIO,  0xab, struct kvm_arm_device_addr)
>  
>  /*
> + * Device control API, available with KVM_CAP_DEVICE_CTRL
> + */
> +#define KVM_CREATE_DEVICE_TEST		1
> +
> +struct kvm_create_device {
> +	__u32	type;	/* in: KVM_DEV_TYPE_xxx */
> +	__u32	fd;	/* out: device handle */
> +	__u32	flags;	/* in: KVM_CREATE_DEVICE_xxx */
> +};
> +
> +struct kvm_device_attr {
> +	__u32	flags;		/* no flags currently defined */
> +	__u32	group;		/* device-defined */
> +	__u64	attr;		/* group-defined */
> +	__u64	addr;		/* userspace address of attr data */
> +};
Please move struct definitions and KVM_CREATE_DEVICE_TEST define out
from ioctl definition block.

> +
> +/* ioctl for vm fd */
> +#define KVM_CREATE_DEVICE	  _IOWR(KVMIO,  0xe0, struct kvm_create_device)
> +
> +/* ioctls for fds returned by KVM_CREATE_DEVICE */
> +#define KVM_SET_DEVICE_ATTR	  _IOW(KVMIO,  0xe1, struct kvm_device_attr)
> +#define KVM_GET_DEVICE_ATTR	  _IOW(KVMIO,  0xe2, struct kvm_device_attr)
> +#define KVM_HAS_DEVICE_ATTR	  _IOW(KVMIO,  0xe3, struct kvm_device_attr)
> +
> +/*
>   * ioctls for vcpu fds
>   */
>  #define KVM_RUN                   _IO(KVMIO,   0x80)
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 5cc53c9..e2b18af 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -2158,6 +2158,117 @@ out:
>  }
>  #endif
>  
> +static int kvm_device_ioctl_attr(struct kvm_device *dev,
> +				 int (*accessor)(struct kvm_device *dev,
> +						 struct kvm_device_attr *attr),
> +				 unsigned long arg)
> +{
> +	struct kvm_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 kvm_device_ioctl(struct file *filp, unsigned int ioctl,
> +			     unsigned long arg)
> +{
> +	struct kvm_device *dev = filp->private_data;
> +
> +	switch (ioctl) {
> +	case KVM_SET_DEVICE_ATTR:
> +		return kvm_device_ioctl_attr(dev, dev->ops->set_attr, arg);
> +	case KVM_GET_DEVICE_ATTR:
> +		return kvm_device_ioctl_attr(dev, dev->ops->get_attr, arg);
> +	case KVM_HAS_DEVICE_ATTR:
> +		return kvm_device_ioctl_attr(dev, dev->ops->has_attr, arg);
> +	default:
> +		if (dev->ops->ioctl)
> +			return dev->ops->ioctl(dev, ioctl, arg);
> +
> +		return -ENOTTY;
> +	}
> +}
> +
> +void kvm_device_get(struct kvm_device *dev)
> +{
> +	atomic_inc(&dev->users);
> +}
> +
> +void kvm_device_put(struct kvm_device *dev)
> +{
> +	if (atomic_dec_and_test(&dev->users))
> +		dev->ops->destroy(dev);
> +}
> +
> +static int kvm_device_release(struct inode *inode, struct file *filp)
> +{
> +	struct kvm_device *dev = filp->private_data;
> +	struct kvm *kvm = dev->kvm;
> +
> +	kvm_device_put(dev);
> +	kvm_put_kvm(kvm);
We may put kvm only if users goes to zero, otherwise kvm can be
freed while something holds a reference to a device. Why not make
kvm_device_put() do it?

> +	return 0;
> +}
> +
> +static const struct file_operations kvm_device_fops = {
> +	.unlocked_ioctl = kvm_device_ioctl,
> +	.release = kvm_device_release,
> +};
> +
> +struct kvm_device *kvm_device_from_filp(struct file *filp)
> +{
> +	if (filp->f_op != &kvm_device_fops)
> +		return NULL;
> +
> +	return filp->private_data;
> +}
> +
> +static int kvm_ioctl_create_device(struct kvm *kvm,
> +				   struct kvm_create_device *cd)
> +{
> +	struct kvm_device_ops *ops = NULL;
> +	struct kvm_device *dev;
> +	bool test = cd->flags & KVM_CREATE_DEVICE_TEST;
> +	int ret;
> +
> +	switch (cd->type) {
> +	default:
> +		return -ENODEV;
> +	}
> +
> +	if (test)
> +		return 0;
> +
> +	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
> +	if (!dev)
> +		return -ENOMEM;
> +
> +	dev->ops = ops;
> +	dev->kvm = kvm;
> +	atomic_set(&dev->users, 1);
> +
> +	ret = ops->create(dev, cd->type);
> +	if (ret < 0) {
> +		kfree(dev);
> +		return ret;
> +	}
> +
> +	ret = anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR);
> +	if (ret < 0) {
> +		ops->destroy(dev);
> +		return ret;
> +	}
> +
> +	kvm_get_kvm(kvm);
> +	cd->fd = ret;
> +	return 0;
> +}
> +
>  static long kvm_vm_ioctl(struct file *filp,
>  			   unsigned int ioctl, unsigned long arg)
>  {
> @@ -2272,6 +2383,24 @@ static long kvm_vm_ioctl(struct file *filp,
>  		break;
>  	}
>  #endif
> +	case KVM_CREATE_DEVICE: {
> +		struct kvm_create_device cd;
> +
> +		r = -EFAULT;
> +		if (copy_from_user(&cd, argp, sizeof(cd)))
> +			goto out;
> +
> +		r = kvm_ioctl_create_device(kvm, &cd);
> +		if (r)
> +			goto out;
> +
> +		r = -EFAULT;
> +		if (copy_to_user(argp, &cd, sizeof(cd)))
> +			goto out;
> +
> +		r = 0;
> +		break;
> +	}
>  	default:
>  		r = kvm_arch_vm_ioctl(filp, ioctl, arg);
>  		if (r = -ENOTTY)
> -- 
> 1.7.10.4
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
			Gleb.

WARNING: multiple messages have this Message-ID (diff)
From: Gleb Natapov <gleb@redhat.com>
To: Scott Wood <scottwood@freescale.com>
Cc: Alexander Graf <agraf@suse.de>,
	kvm-ppc@vger.kernel.org, kvm@vger.kernel.org, paulus@samba.org
Subject: Re: [PATCH v4 1/6] kvm: add device control API
Date: Thu, 25 Apr 2013 12:43:24 +0300	[thread overview]
Message-ID: <20130425094324.GY12401@redhat.com> (raw)
In-Reply-To: <1365811727-24431-2-git-send-email-scottwood@freescale.com>

On Fri, Apr 12, 2013 at 07:08:42PM -0500, Scott Wood wrote:
> Currently, devices that are emulated inside KVM are configured in a
> hardcoded manner based on an assumption that any given architecture
> only has one way to do it.  If there's any need to access device state,
> it is done through inflexible one-purpose-only IOCTLs (e.g.
> KVM_GET/SET_LAPIC).  Defining new IOCTLs for every little thing is
> cumbersome and depletes a limited numberspace.
> 
> This API provides a mechanism to instantiate a device of a certain
> type, returning an ID that can be used to set/get attributes of the
> device.  Attributes may include configuration parameters (e.g.
> register base address), device state, operational commands, etc.  It
> is similar to the ONE_REG API, except that it acts on devices rather
> than vcpus.
> 
> Both device types and individual attributes can be tested without having
> to create the device or get/set the attribute, without the need for
> separately managing enumerated capabilities.
> 
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---
> v4:
>  - Move some boilerplate back into generic code, as requested by Gleb.
>    File descriptor management and reference counting is no longer the
>    concern of the device implementation.
> 
>  - Don't hold kvm->lock during create.  The original reasons
>    for doing so have vanished as for as MPIC is concerned, and
>    this avoids needing to answer the question of whether to
>    hold the lock during destroy as well.
> 
>    Paul, you may need to acquire the lock yourself in kvm_create_xics()
>    to protect the -EEXIST check.
> 
> v3: remove some changes that were merged into this patch by accident,
> and fix the error documentation for KVM_CREATE_DEVICE.
> ---
>  Documentation/virtual/kvm/api.txt        |   70 ++++++++++++++++
>  Documentation/virtual/kvm/devices/README |    1 +
>  include/linux/kvm_host.h                 |   35 ++++++++
>  include/uapi/linux/kvm.h                 |   27 +++++++
>  virt/kvm/kvm_main.c                      |  129 ++++++++++++++++++++++++++++++
>  5 files changed, 262 insertions(+)
>  create mode 100644 Documentation/virtual/kvm/devices/README
> 
> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> index 976eb65..d52f3f9 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -2173,6 +2173,76 @@ header; first `n_valid' valid entries with contents from the data
>  written, then `n_invalid' invalid entries, invalidating any previously
>  valid entries found.
>  
> +4.79 KVM_CREATE_DEVICE
> +
> +Capability: KVM_CAP_DEVICE_CTRL
> +Type: vm ioctl
> +Parameters: struct kvm_create_device (in/out)
> +Returns: 0 on success, -1 on error
> +Errors:
> +  ENODEV: The device type is unknown or unsupported
> +  EEXIST: Device already created, and this type of device may not
> +          be instantiated multiple times
> +
> +  Other error conditions may be defined by individual device types or
> +  have their standard meanings.
> +
> +Creates an emulated device in the kernel.  The file descriptor returned
> +in fd can be used with KVM_SET/GET/HAS_DEVICE_ATTR.
> +
> +If the KVM_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).
> +
> +Individual devices should not define flags.  Attributes should be used
> +for specifying any behavior that is not implied by the device type
> +number.
> +
> +struct kvm_create_device {
> +	__u32	type;	/* in: KVM_DEV_TYPE_xxx */
> +	__u32	fd;	/* out: device handle */
> +	__u32	flags;	/* in: KVM_CREATE_DEVICE_xxx */
> +};
Should we add __u32 padding here to make struct size multiple of u64?

> +
> +4.80 KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR
> +
> +Capability: KVM_CAP_DEVICE_CTRL
> +Type: device ioctl
> +Parameters: struct kvm_device_attr
> +Returns: 0 on success, -1 on error
> +Errors:
> +  ENXIO:  The group or attribute is unknown/unsupported for this device
> +  EPERM:  The attribute cannot (currently) be accessed this way
> +          (e.g. read-only attribute, or attribute that only makes
> +          sense when the device is in a different state)
> +
> +  Other error conditions may be defined by individual device types.
> +
> +Gets/sets a specified piece of device configuration and/or state.  The
> +semantics are device-specific.  See individual device documentation in
> +the "devices" directory.  As with ONE_REG, the size of the data
> +transferred is defined by the particular attribute.
> +
> +struct kvm_device_attr {
> +	__u32	flags;		/* no flags currently defined */
> +	__u32	group;		/* device-defined */
> +	__u64	attr;		/* group-defined */
> +	__u64	addr;		/* userspace address of attr data */
> +};
> +
> +4.81 KVM_HAS_DEVICE_ATTR
> +
> +Capability: KVM_CAP_DEVICE_CTRL
> +Type: device ioctl
> +Parameters: struct kvm_device_attr
> +Returns: 0 on success, -1 on error
> +Errors:
> +  ENXIO:  The group or attribute is unknown/unsupported for this device
> +
> +Tests whether a device supports a particular attribute.  A successful
> +return indicates the attribute is implemented.  It does not necessarily
> +indicate that the attribute can be read or written in the device's
> +current state.  "addr" is ignored.
>  
>  4.77 KVM_ARM_VCPU_INIT
>  
> diff --git a/Documentation/virtual/kvm/devices/README b/Documentation/virtual/kvm/devices/README
> new file mode 100644
> index 0000000..34a6983
> --- /dev/null
> +++ b/Documentation/virtual/kvm/devices/README
> @@ -0,0 +1 @@
> +This directory contains specific device bindings for KVM_CAP_DEVICE_CTRL.
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 20d77d2..8fce9bc 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -1063,6 +1063,41 @@ static inline bool kvm_check_request(int req, struct kvm_vcpu *vcpu)
>  
>  extern bool kvm_rebooting;
>  
> +struct kvm_device_ops;
> +
> +struct kvm_device {
> +	struct kvm_device_ops *ops;
> +	struct kvm *kvm;
> +	atomic_t users;
> +	void *private;
> +};
> +
> +/* create, destroy, and name are mandatory */
> +struct kvm_device_ops {
> +	const char *name;
> +	int (*create)(struct kvm_device *dev, u32 type);
> +
> +	/*
> +	 * 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 kvm component that gets destroyed
> +	 * after the emulated I/O.
> +	 */
> +	void (*destroy)(struct kvm_device *dev);
> +
> +	int (*set_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
> +	int (*get_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
> +	int (*has_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
> +	long (*ioctl)(struct kvm_device *dev, unsigned int ioctl,
> +		      unsigned long arg);
> +};
> +
> +void kvm_device_get(struct kvm_device *dev);
> +void kvm_device_put(struct kvm_device *dev);
> +struct kvm_device *kvm_device_from_filp(struct file *filp);
> +
>  #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT
>  
>  static inline void kvm_vcpu_set_in_spin_loop(struct kvm_vcpu *vcpu, bool val)
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 74d0ff3..20ce2d2 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -668,6 +668,7 @@ struct kvm_ppc_smmu_info {
>  #define KVM_CAP_PPC_EPR 86
>  #define KVM_CAP_ARM_PSCI 87
>  #define KVM_CAP_ARM_SET_DEVICE_ADDR 88
> +#define KVM_CAP_DEVICE_CTRL 89
>  
>  #ifdef KVM_CAP_IRQ_ROUTING
>  
> @@ -909,6 +910,32 @@ struct kvm_s390_ucas_mapping {
>  #define KVM_ARM_SET_DEVICE_ADDR	  _IOW(KVMIO,  0xab, struct kvm_arm_device_addr)
>  
>  /*
> + * Device control API, available with KVM_CAP_DEVICE_CTRL
> + */
> +#define KVM_CREATE_DEVICE_TEST		1
> +
> +struct kvm_create_device {
> +	__u32	type;	/* in: KVM_DEV_TYPE_xxx */
> +	__u32	fd;	/* out: device handle */
> +	__u32	flags;	/* in: KVM_CREATE_DEVICE_xxx */
> +};
> +
> +struct kvm_device_attr {
> +	__u32	flags;		/* no flags currently defined */
> +	__u32	group;		/* device-defined */
> +	__u64	attr;		/* group-defined */
> +	__u64	addr;		/* userspace address of attr data */
> +};
Please move struct definitions and KVM_CREATE_DEVICE_TEST define out
from ioctl definition block.

> +
> +/* ioctl for vm fd */
> +#define KVM_CREATE_DEVICE	  _IOWR(KVMIO,  0xe0, struct kvm_create_device)
> +
> +/* ioctls for fds returned by KVM_CREATE_DEVICE */
> +#define KVM_SET_DEVICE_ATTR	  _IOW(KVMIO,  0xe1, struct kvm_device_attr)
> +#define KVM_GET_DEVICE_ATTR	  _IOW(KVMIO,  0xe2, struct kvm_device_attr)
> +#define KVM_HAS_DEVICE_ATTR	  _IOW(KVMIO,  0xe3, struct kvm_device_attr)
> +
> +/*
>   * ioctls for vcpu fds
>   */
>  #define KVM_RUN                   _IO(KVMIO,   0x80)
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 5cc53c9..e2b18af 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -2158,6 +2158,117 @@ out:
>  }
>  #endif
>  
> +static int kvm_device_ioctl_attr(struct kvm_device *dev,
> +				 int (*accessor)(struct kvm_device *dev,
> +						 struct kvm_device_attr *attr),
> +				 unsigned long arg)
> +{
> +	struct kvm_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 kvm_device_ioctl(struct file *filp, unsigned int ioctl,
> +			     unsigned long arg)
> +{
> +	struct kvm_device *dev = filp->private_data;
> +
> +	switch (ioctl) {
> +	case KVM_SET_DEVICE_ATTR:
> +		return kvm_device_ioctl_attr(dev, dev->ops->set_attr, arg);
> +	case KVM_GET_DEVICE_ATTR:
> +		return kvm_device_ioctl_attr(dev, dev->ops->get_attr, arg);
> +	case KVM_HAS_DEVICE_ATTR:
> +		return kvm_device_ioctl_attr(dev, dev->ops->has_attr, arg);
> +	default:
> +		if (dev->ops->ioctl)
> +			return dev->ops->ioctl(dev, ioctl, arg);
> +
> +		return -ENOTTY;
> +	}
> +}
> +
> +void kvm_device_get(struct kvm_device *dev)
> +{
> +	atomic_inc(&dev->users);
> +}
> +
> +void kvm_device_put(struct kvm_device *dev)
> +{
> +	if (atomic_dec_and_test(&dev->users))
> +		dev->ops->destroy(dev);
> +}
> +
> +static int kvm_device_release(struct inode *inode, struct file *filp)
> +{
> +	struct kvm_device *dev = filp->private_data;
> +	struct kvm *kvm = dev->kvm;
> +
> +	kvm_device_put(dev);
> +	kvm_put_kvm(kvm);
We may put kvm only if users goes to zero, otherwise kvm can be
freed while something holds a reference to a device. Why not make
kvm_device_put() do it?

> +	return 0;
> +}
> +
> +static const struct file_operations kvm_device_fops = {
> +	.unlocked_ioctl = kvm_device_ioctl,
> +	.release = kvm_device_release,
> +};
> +
> +struct kvm_device *kvm_device_from_filp(struct file *filp)
> +{
> +	if (filp->f_op != &kvm_device_fops)
> +		return NULL;
> +
> +	return filp->private_data;
> +}
> +
> +static int kvm_ioctl_create_device(struct kvm *kvm,
> +				   struct kvm_create_device *cd)
> +{
> +	struct kvm_device_ops *ops = NULL;
> +	struct kvm_device *dev;
> +	bool test = cd->flags & KVM_CREATE_DEVICE_TEST;
> +	int ret;
> +
> +	switch (cd->type) {
> +	default:
> +		return -ENODEV;
> +	}
> +
> +	if (test)
> +		return 0;
> +
> +	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
> +	if (!dev)
> +		return -ENOMEM;
> +
> +	dev->ops = ops;
> +	dev->kvm = kvm;
> +	atomic_set(&dev->users, 1);
> +
> +	ret = ops->create(dev, cd->type);
> +	if (ret < 0) {
> +		kfree(dev);
> +		return ret;
> +	}
> +
> +	ret = anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR);
> +	if (ret < 0) {
> +		ops->destroy(dev);
> +		return ret;
> +	}
> +
> +	kvm_get_kvm(kvm);
> +	cd->fd = ret;
> +	return 0;
> +}
> +
>  static long kvm_vm_ioctl(struct file *filp,
>  			   unsigned int ioctl, unsigned long arg)
>  {
> @@ -2272,6 +2383,24 @@ static long kvm_vm_ioctl(struct file *filp,
>  		break;
>  	}
>  #endif
> +	case KVM_CREATE_DEVICE: {
> +		struct kvm_create_device cd;
> +
> +		r = -EFAULT;
> +		if (copy_from_user(&cd, argp, sizeof(cd)))
> +			goto out;
> +
> +		r = kvm_ioctl_create_device(kvm, &cd);
> +		if (r)
> +			goto out;
> +
> +		r = -EFAULT;
> +		if (copy_to_user(argp, &cd, sizeof(cd)))
> +			goto out;
> +
> +		r = 0;
> +		break;
> +	}
>  	default:
>  		r = kvm_arch_vm_ioctl(filp, ioctl, arg);
>  		if (r == -ENOTTY)
> -- 
> 1.7.10.4
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
			Gleb.

  reply	other threads:[~2013-04-25  9:43 UTC|newest]

Thread overview: 261+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-02-14  5:49 [RFC PATCH 0/6] kvm/ppc/mpic: in-kernel irqchip Scott Wood
2013-02-14  5:49 ` Scott Wood
2013-02-14  5:49 ` [RFC PATCH 1/6] kvm: add device control API Scott Wood
2013-02-14  5:49   ` Scott Wood
2013-02-18 12:21   ` Gleb Natapov
2013-02-18 12:21     ` Gleb Natapov
2013-02-18 23:01     ` Scott Wood
2013-02-18 23:01       ` Scott Wood
2013-02-19  0:43       ` Christoffer Dall
2013-02-19  0:43         ` Christoffer Dall
2013-02-19 12:24       ` Gleb Natapov
2013-02-19 12:24         ` Gleb Natapov
2013-02-19 15:51         ` Christoffer Dall
2013-02-19 15:51           ` Christoffer Dall
2013-02-19 21:16         ` Scott Wood
2013-02-19 21:16           ` Scott Wood
2013-02-20 13:09           ` Gleb Natapov
2013-02-20 13:09             ` Gleb Natapov
2013-02-20 21:28             ` Marcelo Tosatti
2013-02-20 21:28               ` Marcelo Tosatti
2013-02-20 22:44               ` Marcelo Tosatti
2013-02-20 22:44                 ` Marcelo Tosatti
2013-02-20 23:53               ` Scott Wood
2013-02-20 23:53                 ` Scott Wood
2013-02-21  0:14                 ` Marcelo Tosatti
2013-02-21  0:14                   ` Marcelo Tosatti
2013-02-21  1:28                   ` Scott Wood
2013-02-21  1:28                     ` Scott Wood
2013-02-21  6:39                     ` Gleb Natapov
2013-02-21  6:39                       ` Gleb Natapov
2013-02-21 23:03                     ` Marcelo Tosatti
2013-02-21 23:03                       ` Marcelo Tosatti
2013-02-22  2:00                       ` Scott Wood
2013-02-22  2:00                         ` Scott Wood
2013-02-23 15:04                         ` Marcelo Tosatti
2013-02-23 15:04                           ` Marcelo Tosatti
2013-02-26  0:27                           ` Scott Wood
2013-02-26  0:27                             ` Scott Wood
2013-02-21  2:05             ` Scott Wood
2013-02-21  2:05               ` Scott Wood
2013-02-21  8:22               ` Gleb Natapov
2013-02-21  8:22                 ` Gleb Natapov
2013-02-22  2:17                 ` Scott Wood
2013-02-22  2:17                   ` Scott Wood
2013-02-24 15:46                   ` Gleb Natapov
2013-02-24 15:46                     ` Gleb Natapov
2013-02-25 15:23                     ` Alexander Graf
2013-02-25 15:23                       ` Alexander Graf
2013-02-26  2:38                     ` Scott Wood
2013-02-26  2:38                       ` Scott Wood
2013-02-20 21:17       ` Marcelo Tosatti
2013-02-20 21:17         ` Marcelo Tosatti
2013-02-20 23:20         ` Scott Wood
2013-02-20 23:20           ` Scott Wood
2013-02-21  0:01           ` Marcelo Tosatti
2013-02-21  0:01             ` Marcelo Tosatti
2013-02-21  0:33             ` Scott Wood
2013-02-21  0:33               ` Scott Wood
2013-02-25  1:11     ` Paul Mackerras
2013-02-25  1:11       ` Paul Mackerras
2013-02-25 13:09       ` Gleb Natapov
2013-02-25 13:09         ` Gleb Natapov
2013-02-25 15:29         ` Alexander Graf
2013-02-25 15:29           ` Alexander Graf
2013-02-19  0:44   ` Christoffer Dall
2013-02-19  0:44     ` Christoffer Dall
2013-02-19  0:53     ` Scott Wood
2013-02-19  0:53       ` Scott Wood
2013-02-19  5:50       ` Christoffer Dall
2013-02-19  5:50         ` Christoffer Dall
2013-02-19 12:45         ` Gleb Natapov
2013-02-19 12:45           ` Gleb Natapov
2013-02-19 20:16         ` Scott Wood
2013-02-19 20:16           ` Scott Wood
2013-02-20  2:16           ` Christoffer Dall
2013-02-20  2:16             ` Christoffer Dall
2013-02-24 13:12             ` Marc Zyngier
2013-02-24 13:12               ` Marc Zyngier
2013-03-06  0:59   ` Paul Mackerras
2013-03-06  0:59     ` Paul Mackerras
2013-03-06  1:20     ` Scott Wood
2013-03-06  1:20       ` Scott Wood
2013-03-06  2:48   ` Benjamin Herrenschmidt
2013-03-06  2:48     ` Benjamin Herrenschmidt
2013-03-06  3:36     ` Scott Wood
2013-03-06  3:36       ` Scott Wood
2013-03-06  4:28       ` Benjamin Herrenschmidt
2013-03-06  4:28         ` Benjamin Herrenschmidt
2013-03-06 10:18     ` Gleb Natapov
2013-03-06 10:18       ` Gleb Natapov
2013-02-14  5:49 ` [RFC PATCH 2/6] kvm/ppc: add a notifier chain for vcpu creation/destruction Scott Wood
2013-02-14  5:49   ` Scott Wood
2013-02-14  5:49 ` [RFC PATCH 3/6] kvm/ppc/mpic: import hw/openpic.c from QEMU Scott Wood
2013-02-14  5:49   ` Scott Wood
2013-02-14  5:49 ` [RFC PATCH 4/6] kvm/ppc/mpic: remove some obviously unneeded code Scott Wood
2013-02-14  5:49   ` Scott Wood
2013-02-14  5:49 ` [RFC PATCH 5/6] kvm/ppc/mpic: adapt to kernel style and environment Scott Wood
2013-02-14  5:49   ` Scott Wood
2013-02-14  5:49 ` [RFC PATCH 6/6] kvm/ppc/mpic: in-kernel MPIC emulation Scott Wood
2013-02-14  5:49   ` Scott Wood
2013-03-21  8:28   ` Alexander Graf
2013-03-21  8:28     ` Alexander Graf
2013-03-21 14:43     ` Scott Wood
2013-03-21 14:43       ` Scott Wood
2013-03-21 14:52       ` Alexander Graf
2013-03-21 14:52         ` Alexander Graf
2013-02-18 12:04 ` [RFC PATCH 0/6] kvm/ppc/mpic: in-kernel irqchip Gleb Natapov
2013-02-18 12:04   ` Gleb Natapov
2013-02-18 23:05   ` Scott Wood
2013-02-18 23:05     ` Scott Wood
2013-04-01 22:47 ` [RFC PATCH v2 0/6] device control and in-kernel MPIC Scott Wood
2013-04-01 22:47   ` Scott Wood
2013-04-01 22:47   ` [RFC PATCH v2 1/6] kvm: add device control API Scott Wood
2013-04-01 22:47     ` Scott Wood
2013-04-02  6:59     ` tiejun.chen
2013-04-02  6:59       ` tiejun.chen
     [not found]       ` <1364923807.24520.2@snotra>
2013-04-03  1:28         ` tiejun.chen
2013-04-03  1:28           ` tiejun.chen
     [not found]           ` <1364952853.8690.3@snotra>
2013-04-03  1:42             ` tiejun.chen
2013-04-03  1:42               ` tiejun.chen
2013-04-03  1:02     ` Paul Mackerras
2013-04-03  1:02       ` Paul Mackerras
2013-04-03  1:19       ` Scott Wood
2013-04-03  1:19         ` Scott Wood
2013-04-03  2:17         ` Paul Mackerras
2013-04-03  2:17           ` Paul Mackerras
2013-04-03 13:22           ` Alexander Graf
2013-04-03 13:22             ` Alexander Graf
2013-04-03 17:37             ` Scott Wood
2013-04-03 17:37               ` Scott Wood
2013-04-03 17:39               ` Alexander Graf
2013-04-03 17:39                 ` Alexander Graf
2013-04-04  9:58                 ` Gleb Natapov
2013-04-04  9:58                   ` Gleb Natapov
2013-04-03 21:03           ` Scott Wood
2013-04-03 21:03             ` Scott Wood
2013-04-01 22:47   ` [RFC PATCH v2 2/6] kvm/ppc/mpic: import hw/openpic.c from QEMU Scott Wood
2013-04-01 22:47     ` Scott Wood
2013-04-01 22:47   ` [RFC PATCH v2 3/6] kvm/ppc/mpic: remove some obviously unneeded code Scott Wood
2013-04-01 22:47     ` Scott Wood
2013-04-01 22:47   ` [RFC PATCH v2 4/6] kvm/ppc/mpic: adapt to kernel style and environment Scott Wood
2013-04-01 22:47     ` Scott Wood
2013-04-01 22:47   ` [RFC PATCH v2 5/6] kvm/ppc/mpic: in-kernel MPIC emulation Scott Wood
2013-04-01 22:47     ` Scott Wood
2013-04-01 22:47   ` [RFC PATCH v2 6/6] kvm/ppc/mpic: add KVM_CAP_IRQ_MPIC Scott Wood
2013-04-01 22:47     ` Scott Wood
2013-04-03  1:57   ` [RFC PATCH v3 0/6] device control and in-kernel MPIC Scott Wood
2013-04-03  1:57     ` Scott Wood
2013-04-03  1:57     ` [RFC PATCH v3 1/6] kvm: add device control API Scott Wood
2013-04-03  1:57       ` Scott Wood
2013-04-03 15:13       ` Alexander Graf
2013-04-03 15:13         ` Alexander Graf
2013-04-04 10:41       ` Gleb Natapov
2013-04-04 10:41         ` Gleb Natapov
2013-04-04 23:47         ` Scott Wood
2013-04-04 23:47           ` Scott Wood
2013-04-08 10:34           ` Gleb Natapov
2013-04-08 10:34             ` Gleb Natapov
2013-04-05  1:02         ` Paul Mackerras
2013-04-05  1:02           ` Paul Mackerras
2013-04-08 10:37           ` Gleb Natapov
2013-04-08 10:37             ` Gleb Natapov
2013-04-08  5:33       ` Paul Mackerras
2013-04-08  5:33         ` Paul Mackerras
2013-04-09  0:50         ` Scott Wood
2013-04-09  0:50           ` Scott Wood
2013-04-03  1:57     ` [RFC PATCH v3 2/6] kvm/ppc/mpic: import hw/openpic.c from QEMU Scott Wood
2013-04-03  1:57       ` Scott Wood
2013-04-03  1:57     ` [RFC PATCH v3 3/6] kvm/ppc/mpic: remove some obviously unneeded code Scott Wood
2013-04-03  1:57       ` Scott Wood
2013-04-03  1:57     ` [RFC PATCH v3 4/6] kvm/ppc/mpic: adapt to kernel style and environment Scott Wood
2013-04-03  1:57       ` Scott Wood
2013-04-03  1:57     ` [RFC PATCH v3 5/6] kvm/ppc/mpic: in-kernel MPIC emulation Scott Wood
2013-04-03  1:57       ` Scott Wood
2013-04-03 15:55       ` Gleb Natapov
2013-04-03 15:55         ` Gleb Natapov
2013-04-03 20:58         ` Scott Wood
2013-04-03 20:58           ` Scott Wood
2013-04-04  5:59           ` Gleb Natapov
2013-04-04  5:59             ` Gleb Natapov
2013-04-04 23:33             ` Scott Wood
2013-04-04 23:33               ` Scott Wood
2013-04-08 10:39               ` Gleb Natapov
2013-04-08 10:39                 ` Gleb Natapov
2013-04-03 16:19       ` Alexander Graf
2013-04-03 16:19         ` Alexander Graf
2013-04-03 21:38         ` Scott Wood
2013-04-03 21:38           ` Scott Wood
2013-04-03 21:58           ` Alexander Graf
2013-04-03 21:58             ` Alexander Graf
2013-04-03 22:07             ` Scott Wood
2013-04-03 22:07               ` Scott Wood
2013-04-03 22:12               ` Alexander Graf
2013-04-03 22:12                 ` Alexander Graf
2013-04-03 22:54                 ` Scott Wood
2013-04-03 22:54                   ` Scott Wood
2013-04-04  9:42                   ` Alexander Graf
2013-04-04  9:42                     ` Alexander Graf
2013-04-03 23:23               ` Scott Wood
2013-04-03 23:23                 ` Scott Wood
2013-04-03 23:23                 ` Scott Wood
2013-04-08  6:30       ` Paul Mackerras
2013-04-08  6:30         ` Paul Mackerras
2013-04-09  0:49         ` Scott Wood
2013-04-09  0:49           ` Scott Wood
2013-04-03  1:57     ` [RFC PATCH v3 6/6] kvm/ppc/mpic: add KVM_CAP_IRQ_MPIC Scott Wood
2013-04-03  1:57       ` Scott Wood
2013-04-04 12:54       ` Alexander Graf
2013-04-04 12:54         ` Alexander Graf
2013-04-04 18:41         ` Scott Wood
2013-04-04 18:41           ` Scott Wood
2013-04-04 22:30           ` Alexander Graf
2013-04-04 22:30             ` Alexander Graf
2013-04-04 22:35             ` Scott Wood
2013-04-04 22:35               ` Scott Wood
2013-04-05  6:09               ` Alexander Graf
2013-04-05  6:09                 ` Alexander Graf
2013-04-05 17:11                 ` Scott Wood
2013-04-05 17:11                   ` Scott Wood
2013-04-13  0:08     ` [PATCH v4 0/6] device-control and in-kernel MPIC Scott Wood
2013-04-13  0:08       ` Scott Wood
2013-04-13  0:08       ` [PATCH v4 1/6] kvm: add device control API Scott Wood
2013-04-13  0:08         ` Scott Wood
2013-04-25  9:43         ` Gleb Natapov [this message]
2013-04-25  9:43           ` Gleb Natapov
2013-04-25 10:47           ` Alexander Graf
2013-04-25 10:47             ` Alexander Graf
2013-04-25 12:07             ` Gleb Natapov
2013-04-25 12:07               ` Gleb Natapov
2013-04-25 13:45               ` Alexander Graf
2013-04-25 13:45                 ` Alexander Graf
2013-04-25 13:51                 ` Gleb Natapov
2013-04-25 13:51                   ` Gleb Natapov
2013-04-25 16:51             ` Scott Wood
2013-04-25 16:51               ` Scott Wood
2013-04-25 18:22               ` Gleb Natapov
2013-04-25 18:22                 ` Gleb Natapov
2013-04-25 18:59                 ` Scott Wood
2013-04-25 18:59                   ` Scott Wood
2013-04-26  9:53                   ` Gleb Natapov
2013-04-26  9:53                     ` Gleb Natapov
2013-04-26  9:55                     ` Alexander Graf
2013-04-26  9:55                       ` Alexander Graf
2013-04-26  9:57                       ` Gleb Natapov
2013-04-26  9:57                         ` Gleb Natapov
2013-04-13  0:08       ` [PATCH v4 2/6] kvm/ppc/mpic: import hw/openpic.c from QEMU Scott Wood
2013-04-13  0:08         ` Scott Wood
2013-04-13  0:08       ` [PATCH v4 3/6] kvm/ppc/mpic: remove some obviously unneeded code Scott Wood
2013-04-13  0:08         ` Scott Wood
2013-04-13  0:08       ` [PATCH v4 4/6] kvm/ppc/mpic: adapt to kernel style and environment Scott Wood
2013-04-13  0:08         ` Scott Wood
2013-04-13  0:08       ` [PATCH v4 5/6] kvm/ppc/mpic: in-kernel MPIC emulation Scott Wood
2013-04-13  0:08         ` Scott Wood
2013-04-13  0:08       ` [PATCH v4 6/6] kvm/ppc/mpic: add KVM_CAP_IRQ_MPIC Scott Wood
2013-04-13  0:08         ` Scott Wood
2013-04-15  5:23         ` Paul Mackerras
2013-04-15  5:23           ` Paul Mackerras
2013-04-15 17:52           ` Scott Wood
2013-04-15 17:52             ` Scott Wood
2013-04-16  3:59             ` Paul Mackerras
2013-04-16  3:59               ` Paul Mackerras

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130425094324.GY12401@redhat.com \
    --to=gleb@redhat.com \
    --cc=agraf@suse.de \
    --cc=kvm-ppc@vger.kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=paulus@samba.org \
    --cc=scottwood@freescale.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.