Message ID | 20230213151348.56451-4-yi.l.liu@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add vfio_device cdev for iommufd support | expand |
On Mon, 13 Feb 2023 07:13:36 -0800 Yi Liu <yi.l.liu@intel.com> wrote: > This makes the vfio file kAPIs to accepte vfio device files, also a > preparation for vfio device cdev support. > > For the kvm set with vfio device file, kvm pointer is stored in struct > vfio_device_file, and use kvm_ref_lock to protect kvm set and kvm > pointer usage within VFIO. This kvm pointer will be set to vfio_device > after device file is bound to iommufd in the cdev path. > > Signed-off-by: Yi Liu <yi.l.liu@intel.com> > Reviewed-by: Kevin Tian <kevin.tian@intel.com> > --- > drivers/vfio/vfio.h | 2 ++ > drivers/vfio/vfio_main.c | 51 ++++++++++++++++++++++++++++++++++++---- > 2 files changed, 49 insertions(+), 4 deletions(-) This subtly changes the behavior of the vfio-pci hot reset functions without updating the uAPI description or implementation to use less group-centric variables. The new behavior appears to be that cdev fds can also be passed to prove ownership of the affected set of devices for a hot reset, but this probably needs to be examined for gaps. Thanks, Alex
On Mon, Feb 13, 2023 at 07:13:36AM -0800, Yi Liu wrote: > +static struct vfio_device *vfio_device_from_file(struct file *file) > +{ > + struct vfio_device_file *df = file->private_data; > + > + if (file->f_op != &vfio_device_fops) > + return NULL; > + return df->device; > +} > + > /** > * vfio_file_is_valid - True if the file is usable with VFIO APIS > * @file: VFIO group file or VFIO device file > */ > bool vfio_file_is_valid(struct file *file) > { > - return vfio_group_from_file(file); > + return vfio_group_from_file(file) || > + vfio_device_from_file(file); > } > EXPORT_SYMBOL_GPL(vfio_file_is_valid); This can only succeed on a device cdev that has been fully opened. Jason
> From: Jason Gunthorpe <jgg@nvidia.com> > Sent: Tuesday, February 14, 2023 7:44 AM > > On Mon, Feb 13, 2023 at 07:13:36AM -0800, Yi Liu wrote: > > +static struct vfio_device *vfio_device_from_file(struct file *file) > > +{ > > + struct vfio_device_file *df = file->private_data; > > + > > + if (file->f_op != &vfio_device_fops) > > + return NULL; > > + return df->device; > > +} > > + > > /** > > * vfio_file_is_valid - True if the file is usable with VFIO APIS > > * @file: VFIO group file or VFIO device file > > */ > > bool vfio_file_is_valid(struct file *file) > > { > > - return vfio_group_from_file(file); > > + return vfio_group_from_file(file) || > > + vfio_device_from_file(file); > > } > > EXPORT_SYMBOL_GPL(vfio_file_is_valid); > > This can only succeed on a device cdev that has been fully opened. Actually, we cannot. This is used in the kvm-vfio code to see if the user-provided fd is vfio fds in the SET_KVM path. And we don't have the device cdev fully opened until BIND_IOMMUFD. But we do need to invoke SET_KVM before issuing BIND_IOMMUFD as the device open needs kvm pointer. So if we cannot apply fully opened limit to this interface. Maybe an updated function comment is needed. " vfio_file_is_valid - True if the file is vfio files (group or device)" Regards, Yi Liu
> From: Alex Williamson <alex.williamson@redhat.com> > Sent: Tuesday, February 14, 2023 7:22 AM > > On Mon, 13 Feb 2023 07:13:36 -0800 > Yi Liu <yi.l.liu@intel.com> wrote: > > > This makes the vfio file kAPIs to accepte vfio device files, also a > > preparation for vfio device cdev support. > > > > For the kvm set with vfio device file, kvm pointer is stored in struct > > vfio_device_file, and use kvm_ref_lock to protect kvm set and kvm > > pointer usage within VFIO. This kvm pointer will be set to vfio_device > > after device file is bound to iommufd in the cdev path. > > > > Signed-off-by: Yi Liu <yi.l.liu@intel.com> > > Reviewed-by: Kevin Tian <kevin.tian@intel.com> > > --- > > drivers/vfio/vfio.h | 2 ++ > > drivers/vfio/vfio_main.c | 51 > ++++++++++++++++++++++++++++++++++++---- > > 2 files changed, 49 insertions(+), 4 deletions(-) > > This subtly changes the behavior of the vfio-pci hot reset functions > without updating the uAPI description or implementation to use less > group-centric variables. The new behavior appears to be that cdev fds > can also be passed to prove ownership of the affected set of devices > for a hot reset, but this probably needs to be examined for gaps. Yes. user could pass cdev fds afterward. I suppose the VFIO_DEVICE_GET_PCI_HOT_RESET_INFO will report the existing info (group_id, segment, bus, devfn). While userspace passes device fds to the kernel for resetting. Need to update struct vfio_pci_hot_reset and the kernel reset code accordingly. Probably, it is a following series for it.
> From: Liu, Yi L <yi.l.liu@intel.com> > Sent: Tuesday, February 14, 2023 10:03 AM > > > From: Jason Gunthorpe <jgg@nvidia.com> > > Sent: Tuesday, February 14, 2023 7:44 AM > > > > On Mon, Feb 13, 2023 at 07:13:36AM -0800, Yi Liu wrote: > > > +static struct vfio_device *vfio_device_from_file(struct file *file) > > > +{ > > > + struct vfio_device_file *df = file->private_data; > > > + > > > + if (file->f_op != &vfio_device_fops) > > > + return NULL; > > > + return df->device; > > > +} > > > + > > > /** > > > * vfio_file_is_valid - True if the file is usable with VFIO APIS > > > * @file: VFIO group file or VFIO device file > > > */ > > > bool vfio_file_is_valid(struct file *file) > > > { > > > - return vfio_group_from_file(file); > > > + return vfio_group_from_file(file) || > > > + vfio_device_from_file(file); > > > } > > > EXPORT_SYMBOL_GPL(vfio_file_is_valid); > > > > This can only succeed on a device cdev that has been fully opened. > > Actually, we cannot. This is used in the kvm-vfio code to see if the > user-provided fd is vfio fds in the SET_KVM path. And we don't > have the device cdev fully opened until BIND_IOMMUFD. But we do > need to invoke SET_KVM before issuing BIND_IOMMUFD as the device > open needs kvm pointer. So if we cannot apply fully opened limit to this > interface. Maybe an updated function comment is needed. > > " vfio_file_is_valid - True if the file is vfio files (group or device)" I guess your point is this is also called in the pci hot reset path. And in the reset path, the device referred by the device fd should be fully opened. vfio_file_is_valid() only checks f_ops, which is not enough to show the device is fully-opened for cdev fd. However, view the high-level flow, for cdev fd, the device access (neither VFIO_DEVICE_PCI_HOT_RESET nor VFIO_DEVICE_GET_PCI_HOT_RESET_INFO) is not allowed until the device is fully-opened (done in the bind_iommufd). So if the VFIO_DEVICE_PCI_HOT_RESET path goes such far to call vfio_file_is_valid(), the device should have been fully-opened. Regards, Yi Liu
On Tue, Feb 14, 2023 at 02:02:37AM +0000, Liu, Yi L wrote: > > From: Jason Gunthorpe <jgg@nvidia.com> > > Sent: Tuesday, February 14, 2023 7:44 AM > > > > On Mon, Feb 13, 2023 at 07:13:36AM -0800, Yi Liu wrote: > > > +static struct vfio_device *vfio_device_from_file(struct file *file) > > > +{ > > > + struct vfio_device_file *df = file->private_data; > > > + > > > + if (file->f_op != &vfio_device_fops) > > > + return NULL; > > > + return df->device; > > > +} > > > + > > > /** > > > * vfio_file_is_valid - True if the file is usable with VFIO APIS > > > * @file: VFIO group file or VFIO device file > > > */ > > > bool vfio_file_is_valid(struct file *file) > > > { > > > - return vfio_group_from_file(file); > > > + return vfio_group_from_file(file) || > > > + vfio_device_from_file(file); > > > } > > > EXPORT_SYMBOL_GPL(vfio_file_is_valid); > > > > This can only succeed on a device cdev that has been fully opened. > > Actually, we cannot. This is used in the kvm-vfio code to see if the > user-provided fd is vfio fds in the SET_KVM path. And we don't > have the device cdev fully opened until BIND_IOMMUFD. But we do > need to invoke SET_KVM before issuing BIND_IOMMUFD as the device > open needs kvm pointer. So if we cannot apply fully opened limit to this > interface. Maybe an updated function comment is needed. This also seems sketchy, KVM is using the VFIO fd as a "proof" to enable the wbinvd stuff. A half opened cdev should not be used as that proof. Regardless it needs to be fixed for the pci usage. Jason
> From: Jason Gunthorpe <jgg@nvidia.com> > Sent: Wednesday, February 15, 2023 8:39 PM > > On Tue, Feb 14, 2023 at 02:02:37AM +0000, Liu, Yi L wrote: > > > From: Jason Gunthorpe <jgg@nvidia.com> > > > Sent: Tuesday, February 14, 2023 7:44 AM > > > > > > On Mon, Feb 13, 2023 at 07:13:36AM -0800, Yi Liu wrote: > > > > +static struct vfio_device *vfio_device_from_file(struct file *file) > > > > +{ > > > > + struct vfio_device_file *df = file->private_data; > > > > + > > > > + if (file->f_op != &vfio_device_fops) > > > > + return NULL; > > > > + return df->device; > > > > +} > > > > + > > > > /** > > > > * vfio_file_is_valid - True if the file is usable with VFIO APIS > > > > * @file: VFIO group file or VFIO device file > > > > */ > > > > bool vfio_file_is_valid(struct file *file) > > > > { > > > > - return vfio_group_from_file(file); > > > > + return vfio_group_from_file(file) || > > > > + vfio_device_from_file(file); > > > > } > > > > EXPORT_SYMBOL_GPL(vfio_file_is_valid); > > > > > > This can only succeed on a device cdev that has been fully opened. > > > > Actually, we cannot. This is used in the kvm-vfio code to see if the > > user-provided fd is vfio fds in the SET_KVM path. And we don't > > have the device cdev fully opened until BIND_IOMMUFD. But we do > > need to invoke SET_KVM before issuing BIND_IOMMUFD as the device > > open needs kvm pointer. So if we cannot apply fully opened limit to this > > interface. Maybe an updated function comment is needed. > > This also seems sketchy, KVM is using the VFIO fd as a "proof" to > enable the wbinvd stuff. A half opened cdev should not be used as that > proof. From this angle, the group path seems has the same concern. Device is not opened until VFIO_GROUP_GET_DEVICE_FD. GROUP_ADD happens before VFIO_GROUP_GET_DEVICE_FD. But group path has one advantage, which make it ok. Group can only be opened by one application. So once it is opened, the devices within the group are somehow obtained by the application until group fd close. Cdev path may also do similar thing. E.g. one cdev can be opened by one application. Then it should be ok to use the cdev fd as proof to enable the wbinvd stuff even the device is not opened yet.. > Regardless it needs to be fixed for the pci usage. For the pci usage, does my below reply make any sense? https://lore.kernel.org/kvm/DS0PR11MB7529CFCE99E8A77AAC76DC7CC3A39@DS0PR11MB7529.namprd11.prod.outlook.com/T/#m7c00ae5dcae15f42b6dc0b3767c7037b99f53a56 Thanks, Yi Liu
On Wed, Feb 15, 2023 at 02:43:20PM +0000, Liu, Yi L wrote: > > From: Jason Gunthorpe <jgg@nvidia.com> > > Sent: Wednesday, February 15, 2023 8:39 PM > > > > On Tue, Feb 14, 2023 at 02:02:37AM +0000, Liu, Yi L wrote: > > > > From: Jason Gunthorpe <jgg@nvidia.com> > > > > Sent: Tuesday, February 14, 2023 7:44 AM > > > > > > > > On Mon, Feb 13, 2023 at 07:13:36AM -0800, Yi Liu wrote: > > > > > +static struct vfio_device *vfio_device_from_file(struct file *file) > > > > > +{ > > > > > + struct vfio_device_file *df = file->private_data; > > > > > + > > > > > + if (file->f_op != &vfio_device_fops) > > > > > + return NULL; > > > > > + return df->device; > > > > > +} > > > > > + > > > > > /** > > > > > * vfio_file_is_valid - True if the file is usable with VFIO APIS > > > > > * @file: VFIO group file or VFIO device file > > > > > */ > > > > > bool vfio_file_is_valid(struct file *file) > > > > > { > > > > > - return vfio_group_from_file(file); > > > > > + return vfio_group_from_file(file) || > > > > > + vfio_device_from_file(file); > > > > > } > > > > > EXPORT_SYMBOL_GPL(vfio_file_is_valid); > > > > > > > > This can only succeed on a device cdev that has been fully opened. > > > > > > Actually, we cannot. This is used in the kvm-vfio code to see if the > > > user-provided fd is vfio fds in the SET_KVM path. And we don't > > > have the device cdev fully opened until BIND_IOMMUFD. But we do > > > need to invoke SET_KVM before issuing BIND_IOMMUFD as the device > > > open needs kvm pointer. So if we cannot apply fully opened limit to this > > > interface. Maybe an updated function comment is needed. > > > > This also seems sketchy, KVM is using the VFIO fd as a "proof" to > > enable the wbinvd stuff. A half opened cdev should not be used as that > > proof. > > From this angle, the group path seems has the same concern. Device is not > opened until VFIO_GROUP_GET_DEVICE_FD. Well, classically the device was DMA ownership claimed at least. > But group path has one advantage, which make it ok. Group can only be > opened by one application. So once it is opened, the devices within the > group are somehow obtained by the application until group fd close. It depends on what do we want the KVM proof to actually mean. Is simply having permissions on the cdev node sufficient proof for wbinvd? I admit I poorly understand the threat model for this in kvm beyond that kvm doesn't want everyone to use wbinvd. > > Regardless it needs to be fixed for the pci usage. > > For the pci usage, does my below reply make any sense? > > https://lore.kernel.org/kvm/DS0PR11MB7529CFCE99E8A77AAC76DC7CC3A39@DS0PR11MB7529.namprd11.prod.outlook.com/T/#m7c00ae5dcae15f42b6dc0b3767c7037b99f53a56 You basically end up with two APIs that test two different levels of openeness (I have permissions vs I actually am the driver owning this device) Document it carefully at least Jason
[Cc +Paolo] On Wed, 15 Feb 2023 10:46:34 -0400 Jason Gunthorpe <jgg@nvidia.com> wrote: > On Wed, Feb 15, 2023 at 02:43:20PM +0000, Liu, Yi L wrote: > > > From: Jason Gunthorpe <jgg@nvidia.com> > > > Sent: Wednesday, February 15, 2023 8:39 PM > > > > > > On Tue, Feb 14, 2023 at 02:02:37AM +0000, Liu, Yi L wrote: > > > > > From: Jason Gunthorpe <jgg@nvidia.com> > > > > > Sent: Tuesday, February 14, 2023 7:44 AM > > > > > > > > > > On Mon, Feb 13, 2023 at 07:13:36AM -0800, Yi Liu wrote: > > > > > > +static struct vfio_device *vfio_device_from_file(struct file *file) > > > > > > +{ > > > > > > + struct vfio_device_file *df = file->private_data; > > > > > > + > > > > > > + if (file->f_op != &vfio_device_fops) > > > > > > + return NULL; > > > > > > + return df->device; > > > > > > +} > > > > > > + > > > > > > /** > > > > > > * vfio_file_is_valid - True if the file is usable with VFIO APIS > > > > > > * @file: VFIO group file or VFIO device file > > > > > > */ > > > > > > bool vfio_file_is_valid(struct file *file) > > > > > > { > > > > > > - return vfio_group_from_file(file); > > > > > > + return vfio_group_from_file(file) || > > > > > > + vfio_device_from_file(file); > > > > > > } > > > > > > EXPORT_SYMBOL_GPL(vfio_file_is_valid); > > > > > > > > > > This can only succeed on a device cdev that has been fully opened. > > > > > > > > Actually, we cannot. This is used in the kvm-vfio code to see if the > > > > user-provided fd is vfio fds in the SET_KVM path. And we don't > > > > have the device cdev fully opened until BIND_IOMMUFD. But we do > > > > need to invoke SET_KVM before issuing BIND_IOMMUFD as the device > > > > open needs kvm pointer. So if we cannot apply fully opened limit to this > > > > interface. Maybe an updated function comment is needed. > > > > > > This also seems sketchy, KVM is using the VFIO fd as a "proof" to > > > enable the wbinvd stuff. A half opened cdev should not be used as that > > > proof. > > > > From this angle, the group path seems has the same concern. Device is not > > opened until VFIO_GROUP_GET_DEVICE_FD. > > Well, classically the device was DMA ownership claimed at least. > > > But group path has one advantage, which make it ok. Group can only be > > opened by one application. So once it is opened, the devices within the > > group are somehow obtained by the application until group fd close. > > It depends on what do we want the KVM proof to actually mean. > > Is simply having permissions on the cdev node sufficient proof for > wbinvd? > > I admit I poorly understand the threat model for this in kvm beyond > that kvm doesn't want everyone to use wbinvd. We've discussed this with Paolo before and I believe the bar of proof is not very high. I suspect it's not a problem that the device itself is not yet accessible, so long as the user can prove they have the ability to access the device, such as access to a restricted file. In most cases this isn't going to turn on wbinvd anyway since DMA will be coherent. Thanks, Alex
On Wed, Feb 15, 2023 at 08:32:34AM -0700, Alex Williamson wrote: > We've discussed this with Paolo before and I believe the bar of proof > is not very high. I suspect it's not a problem that the device itself > is not yet accessible, so long as the user can prove they have the > ability to access the device, such as access to a restricted file. In > most cases this isn't going to turn on wbinvd anyway since DMA will be > coherent. Thanks, Isn't that a second problem, we don't know if the device is coherent until it is bound? Jason
On Wed, 15 Feb 2023 13:04:13 -0400 Jason Gunthorpe <jgg@nvidia.com> wrote: > On Wed, Feb 15, 2023 at 08:32:34AM -0700, Alex Williamson wrote: > > > We've discussed this with Paolo before and I believe the bar of proof > > is not very high. I suspect it's not a problem that the device itself > > is not yet accessible, so long as the user can prove they have the > > ability to access the device, such as access to a restricted file. In > > most cases this isn't going to turn on wbinvd anyway since DMA will be > > coherent. Thanks, > > Isn't that a second problem, we don't know if the device is coherent > until it is bound? I think this is already accounted for in the conversion to device level IOMMU ops, ie. device_iommu_capable() follows the dev->iommu->iommu_dev->ops, where for example intel_iommu_capable() is only looking at the capabilities of the IOMMU managing the device. We did some hand waving simplifications that was sufficient at some point, IIRC. Thanks, Alex
On Wed, Feb 15, 2023 at 10:19:35AM -0700, Alex Williamson wrote: > On Wed, 15 Feb 2023 13:04:13 -0400 > Jason Gunthorpe <jgg@nvidia.com> wrote: > > > On Wed, Feb 15, 2023 at 08:32:34AM -0700, Alex Williamson wrote: > > > > > We've discussed this with Paolo before and I believe the bar of proof > > > is not very high. I suspect it's not a problem that the device itself > > > is not yet accessible, so long as the user can prove they have the > > > ability to access the device, such as access to a restricted file. In > > > most cases this isn't going to turn on wbinvd anyway since DMA will be > > > coherent. Thanks, > > > > Isn't that a second problem, we don't know if the device is coherent > > until it is bound? > > I think this is already accounted for in the conversion to device level > IOMMU ops, ie. device_iommu_capable() follows the > dev->iommu->iommu_dev->ops, where for example intel_iommu_capable() is > only looking at the capabilities of the IOMMU managing the device. We > did some hand waving simplifications that was sufficient at some point, > IIRC. Thanks, Oh right, I remember this now :) Jason
Hi Alex, Jason, > From: Liu, Yi L <yi.l.liu@intel.com> > Sent: Tuesday, February 14, 2023 3:19 PM > > > From: Liu, Yi L <yi.l.liu@intel.com> > > Sent: Tuesday, February 14, 2023 10:03 AM > > > > > From: Jason Gunthorpe <jgg@nvidia.com> > > > Sent: Tuesday, February 14, 2023 7:44 AM > > > > > > On Mon, Feb 13, 2023 at 07:13:36AM -0800, Yi Liu wrote: > > > > +static struct vfio_device *vfio_device_from_file(struct file *file) > > > > +{ > > > > + struct vfio_device_file *df = file->private_data; > > > > + > > > > + if (file->f_op != &vfio_device_fops) > > > > + return NULL; > > > > + return df->device; > > > > +} > > > > + > > > > /** > > > > * vfio_file_is_valid - True if the file is usable with VFIO APIS > > > > * @file: VFIO group file or VFIO device file > > > > */ > > > > bool vfio_file_is_valid(struct file *file) > > > > { > > > > - return vfio_group_from_file(file); > > > > + return vfio_group_from_file(file) || > > > > + vfio_device_from_file(file); > > > > } > > > > EXPORT_SYMBOL_GPL(vfio_file_is_valid); > > > > > > This can only succeed on a device cdev that has been fully opened. > > > > Actually, we cannot. This is used in the kvm-vfio code to see if the > > user-provided fd is vfio fds in the SET_KVM path. And we don't > > have the device cdev fully opened until BIND_IOMMUFD. But we do > > need to invoke SET_KVM before issuing BIND_IOMMUFD as the device > > open needs kvm pointer. So if we cannot apply fully opened limit to this > > interface. Maybe an updated function comment is needed. > > > > " vfio_file_is_valid - True if the file is vfio files (group or device)" > > I guess your point is this is also called in the pci hot reset path. And > in the reset path, the device referred by the device fd should be fully > opened. vfio_file_is_valid() only checks f_ops, which is not enough to > show the device is fully-opened for cdev fd. However, view the high-level > flow, for cdev fd, the device access (neither VFIO_DEVICE_PCI_HOT_RESET > nor VFIO_DEVICE_GET_PCI_HOT_RESET_INFO) is not allowed until the > device is fully-opened (done in the bind_iommufd). So if the > VFIO_DEVICE_PCI_HOT_RESET path goes such far to call vfio_file_is_valid(), > the device should have been fully-opened. One more thinking on this. For a single device, my above reply is true. The device should have been fully-opened when its GET_PCI_HOT_RESET_INFO and HOT_RESET path have been unblocked. However, when there are multiple devices that have been affected by the hotreset. User may only have one device that is fully opened while others are not yet. In such case, existing vfio_file_is_valid() is not enough. Shall we have another API for this purpose? E.g. if it's cdev fd, then the new API return true only when the device is fully opened. Any suggestion here? Regards, Yi Liu
On Fri, Feb 17, 2023 at 10:55:08AM +0000, Liu, Yi L wrote: > One more thinking on this. For a single device, my above reply is true. > The device should have been fully-opened when its GET_PCI_HOT_RESET_INFO > and HOT_RESET path have been unblocked. However, when there are > multiple devices that have been affected by the hotreset. User may only > have one device that is fully opened while others are not yet. In such case, > existing vfio_file_is_valid() is not enough. Shall we have another API for > this purpose? E.g. if it's cdev fd, then the new API return true only when > the device is fully opened. Any suggestion here? I think what I heard is you need two APIs, one for pci and one for KVM and the PCI one requires binding to succeed. Jason
> From: Jason Gunthorpe <jgg@nvidia.com> > Sent: Friday, February 17, 2023 11:59 PM > > On Fri, Feb 17, 2023 at 10:55:08AM +0000, Liu, Yi L wrote: > > > One more thinking on this. For a single device, my above reply is true. > > The device should have been fully-opened when its > GET_PCI_HOT_RESET_INFO > > and HOT_RESET path have been unblocked. However, when there are > > multiple devices that have been affected by the hotreset. User may only > > have one device that is fully opened while others are not yet. In such case, > > existing vfio_file_is_valid() is not enough. Shall we have another API for > > this purpose? E.g. if it's cdev fd, then the new API return true only when > > the device is fully opened. Any suggestion here? > > I think what I heard is you need two APIs, one for pci and one for KVM > and the PCI one requires binding to succeed. Yes. One is vfio_file_is_valid() - for KVM Another one is vfio_file_device_opened() - for PCI. Regards, Yi Liu
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h index f237e9410d1e..cee979a1b90f 100644 --- a/drivers/vfio/vfio.h +++ b/drivers/vfio/vfio.h @@ -18,6 +18,8 @@ struct vfio_container; struct vfio_device_file { struct vfio_device *device; + spinlock_t kvm_ref_lock; /* protect kvm field */ + struct kvm *kvm; }; void vfio_device_put_registration(struct vfio_device *device); diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c index 8612ba112e7f..c529f609fecc 100644 --- a/drivers/vfio/vfio_main.c +++ b/drivers/vfio/vfio_main.c @@ -406,6 +406,7 @@ vfio_allocate_device_file(struct vfio_device *device) return ERR_PTR(-ENOMEM); df->device = device; + spin_lock_init(&df->kvm_ref_lock); return df; } @@ -1167,13 +1168,23 @@ const struct file_operations vfio_device_fops = { .mmap = vfio_device_fops_mmap, }; +static struct vfio_device *vfio_device_from_file(struct file *file) +{ + struct vfio_device_file *df = file->private_data; + + if (file->f_op != &vfio_device_fops) + return NULL; + return df->device; +} + /** * vfio_file_is_valid - True if the file is usable with VFIO APIS * @file: VFIO group file or VFIO device file */ bool vfio_file_is_valid(struct file *file) { - return vfio_group_from_file(file); + return vfio_group_from_file(file) || + vfio_device_from_file(file); } EXPORT_SYMBOL_GPL(vfio_file_is_valid); @@ -1188,15 +1199,36 @@ EXPORT_SYMBOL_GPL(vfio_file_is_valid); */ bool vfio_file_enforced_coherent(struct file *file) { - struct vfio_group *group = vfio_group_from_file(file); + struct vfio_group *group; + struct vfio_device *device; + group = vfio_group_from_file(file); if (group) return vfio_group_enforced_coherent(group); + device = vfio_device_from_file(file); + if (device) + return device_iommu_capable(device->dev, + IOMMU_CAP_ENFORCE_CACHE_COHERENCY); + return true; } EXPORT_SYMBOL_GPL(vfio_file_enforced_coherent); +static void vfio_device_file_set_kvm(struct file *file, struct kvm *kvm) +{ + struct vfio_device_file *df = file->private_data; + + /* + * The kvm is first recorded in the vfio_device_file, and will + * be propagated to vfio_device::kvm when the file is bound to + * iommufd successfully in the vfio device cdev path. + */ + spin_lock(&df->kvm_ref_lock); + df->kvm = kvm; + spin_unlock(&df->kvm_ref_lock); +} + /** * vfio_file_set_kvm - Link a kvm with VFIO drivers * @file: VFIO group file or VFIO device file @@ -1205,10 +1237,14 @@ EXPORT_SYMBOL_GPL(vfio_file_enforced_coherent); */ void vfio_file_set_kvm(struct file *file, struct kvm *kvm) { - struct vfio_group *group = vfio_group_from_file(file); + struct vfio_group *group; + group = vfio_group_from_file(file); if (group) vfio_group_set_kvm(group, kvm); + + if (vfio_device_from_file(file)) + vfio_device_file_set_kvm(file, kvm); } EXPORT_SYMBOL_GPL(vfio_file_set_kvm); @@ -1221,10 +1257,17 @@ EXPORT_SYMBOL_GPL(vfio_file_set_kvm); */ bool vfio_file_has_dev(struct file *file, struct vfio_device *device) { - struct vfio_group *group = vfio_group_from_file(file); + struct vfio_group *group; + struct vfio_device *vdev; + group = vfio_group_from_file(file); if (group) return vfio_group_has_dev(group, device); + + vdev = vfio_device_from_file(file); + if (device) + return vdev == device; + return false; } EXPORT_SYMBOL_GPL(vfio_file_has_dev);