Re: [PATCH v1 0/2] vfio/pci: expose device's PASID capability to VMs

From: Lu, Baolu
Date: Tue Mar 31 2020 - 03:08:38 EST


On 2020/3/31 14:35, Tian, Kevin wrote:
From: Liu, Yi L<yi.l.liu@xxxxxxxxx>
Sent: Sunday, March 22, 2020 8:33 PM

From: Liu Yi L<yi.l.liu@xxxxxxxxx>

Shared Virtual Addressing (SVA), a.k.a, Shared Virtual Memory (SVM) on
Intel platforms allows address space sharing between device DMA and
applications. SVA can reduce programming complexity and enhance security.

To enable SVA, device needs to have PASID capability, which is a key
capability for SVA. This patchset exposes the device's PASID capability
to guest instead of hiding it from guest.

The second patch emulates PASID capability for VFs (Virtual Function) since
VFs don't implement such capability per PCIe spec. This patch emulates such
capability and expose to VM if the capability is enabled in PF (Physical
Function).

However, there is an open for PASID emulation. If PF driver disables PASID
capability at runtime, then it may be an issue. e.g. PF should not disable
PASID capability if there is guest using this capability on any VF related
to this PF. To solve it, may need to introduce a generic communication
framework between vfio-pci driver and PF drivers. Please feel free to give
your suggestions on it.
I'm not sure how this is addressed on bate metal today, i.e. between normal
kernel PF and VF drivers. I look at pasid enable/disable code in intel-iommu.c.
There is no check on PF/VF dependency so far. The cap is toggled when
attaching/detaching the PF to its domain. Let's see how IOMMU guys
respond, and if there is a way for VF driver to block PF driver from disabling
the pasid cap when it's being actively used by VF driver, then we may
leverage the same trick in VFIO when emulation is provided to guest.

IOMMU subsystem doesn't expose any APIs for pasid enabling/disabling.
The PCI subsystem does. It handles VF/PF like below.

/**
* pci_enable_pasid - Enable the PASID capability
* @pdev: PCI device structure
* @features: Features to enable
*
* Returns 0 on success, negative value on error. This function checks
* whether the features are actually supported by the device and returns
* an error if not.
*/
int pci_enable_pasid(struct pci_dev *pdev, int features)
{
u16 control, supported;
int pasid = pdev->pasid_cap;

/*
* VFs must not implement the PASID Capability, but if a PF
* supports PASID, its VFs share the PF PASID configuration.
*/
if (pdev->is_virtfn) {
if (pci_physfn(pdev)->pasid_enabled)
return 0;
return -EINVAL;
}

/**
* pci_disable_pasid - Disable the PASID capability
* @pdev: PCI device structure
*/
void pci_disable_pasid(struct pci_dev *pdev)
{
u16 control = 0;
int pasid = pdev->pasid_cap;

/* VFs share the PF PASID configuration */
if (pdev->is_virtfn)
return;


It doesn't block disabling PASID on PF even VFs are possibly using it.

Best regards,
baolu