|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH] [RFC] xen/vpci: modify pci_get_pdev_by_domain() & pci_get_pdev()
Hi Jan,
> On 9 Aug 2022, at 11:02 am, Jan Beulich <jbeulich@xxxxxxxx> wrote:
>
> On 05.08.2022 17:43, Rahul Singh wrote:
>> pci_get_pdev_by_domain() and pci_get_pdev() functions find the pdev in
>> the pseg list. If pdev is not in the pseg list, the functions will try
>> to find the pdev in the next segment. It is not right to find the pdev
>> in the next segment as this will result in the corruption of another
>> device in a different segment with the same BDF.
>>
>> An issue that was observed when implementing the PCI passthrough on ARM.
>> When we deassign the device from domU guest, the device is assigned
>> to dom_io and not to dom0, but the tool stack that runs in dom0 will try
>> to configure the device from dom0. vpci will find the device based on
>> conversion of GPA to SBDF and will try to find the device in dom0, but
>> because device is assigned to dom_io, pci_get_pdev_by_domain() will
>> return pdev with same BDF from next segment.
>>
>> Signed-off-by: Rahul Singh <rahul.singh@xxxxxxx>
>
> This wants a Fixes: tag.
Ack.
>
>> --- a/xen/drivers/passthrough/pci.c
>> +++ b/xen/drivers/passthrough/pci.c
>> @@ -593,13 +593,10 @@ struct pci_dev *pci_get_pdev(int seg, int bus, int
>> devfn)
>> return NULL;
>> }
>>
>> - do {
>> - list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
>> - if ( (pdev->bus == bus || bus == -1) &&
>> - (pdev->devfn == devfn || devfn == -1) )
>> - return pdev;
>> - } while ( radix_tree_gang_lookup(&pci_segments, (void **)&pseg,
>> - pseg->nr + 1, 1) );
>> + list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
>> + if ( (pdev->bus == bus || bus == -1) &&
>> + (pdev->devfn == devfn || devfn == -1) )
>> + return pdev;
>>
>> return NULL;
>> }
>> @@ -642,14 +639,11 @@ struct pci_dev *pci_get_pdev_by_domain(const struct
>> domain *d, int seg,
>> return NULL;
>> }
>>
>> - do {
>> - list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
>> - if ( (pdev->bus == bus || bus == -1) &&
>> - (pdev->devfn == devfn || devfn == -1) &&
>> - (pdev->domain == d) )
>> - return pdev;
>> - } while ( radix_tree_gang_lookup(&pci_segments, (void **)&pseg,
>> - pseg->nr + 1, 1) );
>> + list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
>> + if ( (pdev->bus == bus || bus == -1) &&
>> + (pdev->devfn == devfn || devfn == -1) &&
>> + (pdev->domain == d) )
>> + return pdev;
>>
>> return NULL;
>> }
>
> Indeed present behavior is wrong - thanks for spotting. However in
> both cases you're moving us from one wrongness to another: The
> lookup of further segments _is_ necessary when the incoming "seg"
> is -1 (and apparently when this logic was introduced that was the
> only case considered).
If I understand correctly then fixed code should be like this:
—snip—
….
if ( !pseg )
{
if ( seg == -1 )
radix_tree_gang_lookup(&pci_segments, (void **)&pseg, 0, 1);
if ( !pseg )
return NULL;
do {
list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
if ( (pdev->bus == bus || bus == -1) &&
(pdev->devfn == devfn || devfn == -1) )
return pdev;
} while ( radix_tree_gang_lookup(&pci_segments, (void **)&pseg,
pseg->nr + 1, 1) );
return NULL;
}
list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
if ( (pdev->bus == bus || bus == -1) &&
(pdev->devfn == devfn || devfn == -1) )
return pdev;
return NULL;
}
>
> As an aside - my mail UI shows me unexpected threading between
> this patch and two subsequent ones. If they were actually meant
> to be a series, can they please be marked n/3?
Sorry for the confusion all the patches are independent of each other.
Maybe this is because I send them via a single git send-mail command.
I will fix that in the next version.
Regards,
Rahul
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |