|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2] x86/msi: fix locking for SR-IOV devices
Hi Jan,
Thanks for the feedback.
On 8/7/24 11:21, Jan Beulich wrote:
> On 07.08.2024 07:20, Stewart Hildebrand wrote:
>> --- a/xen/arch/x86/msi.c
>> +++ b/xen/arch/x86/msi.c
>> @@ -662,7 +662,8 @@ static int msi_capability_init(struct pci_dev *dev,
>> return 0;
>> }
>>
>> -static u64 read_pci_mem_bar(u16 seg, u8 bus, u8 slot, u8 func, u8 bir, int
>> vf)
>> +static u64 read_pci_mem_bar(struct pci_dev *pdev, u16 seg, u8 bus, u8 slot,
>> + u8 func, u8 bir, int vf)
>> {
>
> First I thought this was a leftover from the earlier version. But you need
> it for accessing the vf_rlen[] field. Yet that's properly misleading,
> especially when considering that the fix also wants backporting. What pdev
> represents here changes. I think you want to pass in just vf_rlen (if we
> really want to go this route; I'm a little wary of this repurposing of the
> field, albeit I see no real technical issue).
I like your idea below of using a struct, so I'll pass a pointer to the
new struct.
> Of course there's a BUILD_BUG_ON() which we need to get creative with, in
> order to now outright drop it (see also below).
I suppose this BUILD_BUG_ON() is redundant with the one in
pci_add_device()...
>> @@ -670,19 +671,15 @@ static u64 read_pci_mem_bar(u16 seg, u8 bus, u8 slot,
>> u8 func, u8 bir, int vf)
>>
>> if ( vf >= 0 )
>> {
>> - struct pci_dev *pdev = pci_get_pdev(NULL,
>> - PCI_SBDF(seg, bus, slot, func));
>> + pci_sbdf_t pf_sbdf = PCI_SBDF(seg, bus, slot, func);
>
> I think this wants naming just "sbdf" and moving to function scope. There
> are more places in the function which, in a subsequent change, could also
> benefit from this new local variable.
Will do.
>> --- a/xen/drivers/passthrough/pci.c
>> +++ b/xen/drivers/passthrough/pci.c
>> @@ -654,6 +654,7 @@ int pci_add_device(u16 seg, u8 bus, u8 devfn,
>> const char *type;
>> int ret;
>> bool pf_is_extfn = false;
>> + uint64_t vf_rlen[6] = { 0 };
>
> The type of this variable needs to be tied to that of the struct field
> you copy to/from. Otherwise, if the struct field changes type ...
>
>> @@ -664,7 +665,10 @@ int pci_add_device(u16 seg, u8 bus, u8 devfn,
>> PCI_SBDF(seg, info->physfn.bus,
>> info->physfn.devfn));
>> if ( pdev )
>> + {
>> pf_is_extfn = pdev->info.is_extfn;
>> + memcpy(vf_rlen, pdev->vf_rlen, sizeof(pdev->vf_rlen));
>
> ... there'll be nothing for the compiler to tell us. Taken together with
> the BUILD_BUG_ON() related remark further up, I think you want to
> introduce a typedef and/or struct here to make things properly typesafe
> (as then you can avoid the use of memcpy()).
Here's what I'm thinking:
struct vf_info {
uint64_t vf_rlen[PCI_SRIOV_NUM_BARS];
unsigned int refcnt;
};
struct pci_dev {
...
struct vf_info *vf_info;
...
};
> Seeing the conditional we're in, what if we take ...
>
>> + }
>> pcidevs_unlock();
>> if ( !pdev )
>> pci_add_device(seg, info->physfn.bus, info->physfn.devfn,
>
> ... this fallback path?
It seems we need another call to pci_get_pdev() here to obtain a
reference to the newly allocated vf_info from the PF's pdev.
>> @@ -700,7 +704,10 @@ int pci_add_device(u16 seg, u8 bus, u8 devfn,
>> * extended function.
>> */
>> if ( pdev->info.is_virtfn )
>> + {
>> pdev->info.is_extfn = pf_is_extfn;
>> + memcpy(pdev->vf_rlen, vf_rlen, sizeof(pdev->vf_rlen));
>> + }
>> }
>
> Similarly here - what if the enclosing if()'s condition is false? Even
> if these cases couldn't be properly taken care of, they'd at least need
> discussing in the description. In this context note how in a subsequent
> invocation of pci_add_device() for the PF the missing data in vf_rlen[]
> would actually be populated into the placeholder struct that the
> fallback invocation of pci_add_device() would have created. Yet the
> previously created VF's struct wouldn't be updated (afaict). This was,
> iirc, the main reason to always consult the PF's ->vf_rlen[].
Right. If info is NULL, either it's a PF in the fallback case, or the
toolstack invoked PHYSDEVOP_manage_pci_add, in which case we treat it as
a PF or non-SR-IOV device. Using PHYSDEVOP_manage_pci_add for a VF is
not a case we handle. We only know if it's a VF if the toolstack has
told us so.
> An alternative approach might be to add a link from VF to PF, while
> making sure that the PF struct won't be de-allocated until all its VFs
> have gone away. That would then also allow to eliminate the problematic
> pci_get_pdev().
I think I can add a link to a new reference-counted struct with just the
info needed (see the proposed struct above).
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |