qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2] pci: Introduce helper to retrieve a PCI device's DMA address space
@ 2013-08-09  8:49 Alexey Kardashevskiy
  2013-08-09  9:40 ` Paolo Bonzini
  0 siblings, 1 reply; 13+ messages in thread
From: Alexey Kardashevskiy @ 2013-08-09  8:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: Anthony Liguori, Michael S . Tsirkin, Alexey Kardashevskiy,
	Paolo Bonzini, David Gibson

A PCI device's DMA address space (possibly an IOMMU) is returned by a
method on the PCIBus.  At the moment that only has one caller, so the
method is simply open coded.  We'll need another caller for VFIO, so
this patch introduces a helper/wrapper function.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
[aik: added inheritance from parent if iommu is not set for the current bus]
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>

---
Changes:
v2:
* added inheritance, needed for a pci-bridge on spapr-ppc64
* pci_iommu_as renamed to pci_device_iommu_address_space
---
 hw/pci/pci.c         | 22 ++++++++++++++++------
 include/hw/pci/pci.h |  1 +
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 4c004f5..0072b54 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -812,12 +812,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     }
 
     pci_dev->bus = bus;
-    if (bus->iommu_fn) {
-        dma_as = bus->iommu_fn(bus, bus->iommu_opaque, devfn);
-    } else {
-        /* FIXME: inherit memory region from bus creator */
-        dma_as = &address_space_memory;
-    }
+    dma_as = pci_device_iommu_address_space(pci_dev);
 
     memory_region_init_alias(&pci_dev->bus_master_enable_region,
                              OBJECT(pci_dev), "bus master",
@@ -2239,6 +2234,21 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
     k->props = pci_props;
 }
 
+AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
+{
+    PCIBus *bus = PCI_BUS(dev->bus);
+
+    if (bus->iommu_fn) {
+        return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
+    }
+
+    if (bus->parent_dev) {
+        return pci_device_iommu_address_space(bus->parent_dev);
+    }
+
+    return &address_space_memory;
+}
+
 void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque)
 {
     bus->iommu_fn = fn;
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index ccec2ba..2374aa9 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -405,6 +405,7 @@ void pci_device_deassert_intx(PCIDevice *dev);
 
 typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void *, int);
 
+AddressSpace *pci_device_iommu_address_space(PCIDevice *dev);
 void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque);
 
 static inline void
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v2] pci: Introduce helper to retrieve a PCI device's DMA address space
  2013-08-09  8:49 [Qemu-devel] [PATCH v2] pci: Introduce helper to retrieve a PCI device's DMA address space Alexey Kardashevskiy
@ 2013-08-09  9:40 ` Paolo Bonzini
  2013-08-09  9:48   ` Alexey Kardashevskiy
  2013-08-09 10:20   ` Benjamin Herrenschmidt
  0 siblings, 2 replies; 13+ messages in thread
From: Paolo Bonzini @ 2013-08-09  9:40 UTC (permalink / raw)
  To: Alexey Kardashevskiy
  Cc: Anthony Liguori, Michael S . Tsirkin, qemu-devel, David Gibson

Il 09/08/2013 10:49, Alexey Kardashevskiy ha scritto:
> A PCI device's DMA address space (possibly an IOMMU) is returned by a
> method on the PCIBus.  At the moment that only has one caller, so the
> method is simply open coded.  We'll need another caller for VFIO, so
> this patch introduces a helper/wrapper function.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> [aik: added inheritance from parent if iommu is not set for the current bus]
> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
> 
> ---
> Changes:
> v2:
> * added inheritance, needed for a pci-bridge on spapr-ppc64
> * pci_iommu_as renamed to pci_device_iommu_address_space
> ---
>  hw/pci/pci.c         | 22 ++++++++++++++++------
>  include/hw/pci/pci.h |  1 +
>  2 files changed, 17 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> index 4c004f5..0072b54 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -812,12 +812,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
>      }
>  
>      pci_dev->bus = bus;
> -    if (bus->iommu_fn) {
> -        dma_as = bus->iommu_fn(bus, bus->iommu_opaque, devfn);
> -    } else {
> -        /* FIXME: inherit memory region from bus creator */
> -        dma_as = &address_space_memory;
> -    }
> +    dma_as = pci_device_iommu_address_space(pci_dev);
>  
>      memory_region_init_alias(&pci_dev->bus_master_enable_region,
>                               OBJECT(pci_dev), "bus master",
> @@ -2239,6 +2234,21 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
>      k->props = pci_props;
>  }
>  
> +AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
> +{
> +    PCIBus *bus = PCI_BUS(dev->bus);
> +
> +    if (bus->iommu_fn) {
> +        return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
> +    }
> +
> +    if (bus->parent_dev) {
> +        return pci_device_iommu_address_space(bus->parent_dev);
> +    }

No, this would fail if bus->parent_dev is not NULL but not a PCI device
either.  You can use object_dynamic_cast to convert the parent_dev to
PCIDevice, and if the cast succeeds you call the new function.

Perhaps you could make the new function take a PCIBus instead.
Accessing the PCIDevice's IOMMU address space (as opposed to the
bus-master address space) doesn't make much sense, VFIO is really a
special case.  Putting the new API on the bus side instead looks better.

(BTW, do you need to enable bus-master DMA on PCI bridges, to do DMA for
devices sitting on the secondary bus?)

Paolo

> +    return &address_space_memory;
> +}
> +
>  void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque)
>  {
>      bus->iommu_fn = fn;
> diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
> index ccec2ba..2374aa9 100644
> --- a/include/hw/pci/pci.h
> +++ b/include/hw/pci/pci.h
> @@ -405,6 +405,7 @@ void pci_device_deassert_intx(PCIDevice *dev);
>  
>  typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void *, int);
>  
> +AddressSpace *pci_device_iommu_address_space(PCIDevice *dev);
>  void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque);
>  
>  static inline void
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v2] pci: Introduce helper to retrieve a PCI device's DMA address space
  2013-08-09  9:40 ` Paolo Bonzini
@ 2013-08-09  9:48   ` Alexey Kardashevskiy
  2013-08-09  9:53     ` Paolo Bonzini
  2013-08-09 10:44     ` David Gibson
  2013-08-09 10:20   ` Benjamin Herrenschmidt
  1 sibling, 2 replies; 13+ messages in thread
From: Alexey Kardashevskiy @ 2013-08-09  9:48 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Anthony Liguori, Michael S . Tsirkin, qemu-devel, David Gibson

On 08/09/2013 07:40 PM, Paolo Bonzini wrote:
> Il 09/08/2013 10:49, Alexey Kardashevskiy ha scritto:
>> A PCI device's DMA address space (possibly an IOMMU) is returned by a
>> method on the PCIBus.  At the moment that only has one caller, so the
>> method is simply open coded.  We'll need another caller for VFIO, so
>> this patch introduces a helper/wrapper function.
>>
>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>> [aik: added inheritance from parent if iommu is not set for the current bus]
>> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
>>
>> ---
>> Changes:
>> v2:
>> * added inheritance, needed for a pci-bridge on spapr-ppc64
>> * pci_iommu_as renamed to pci_device_iommu_address_space
>> ---
>>  hw/pci/pci.c         | 22 ++++++++++++++++------
>>  include/hw/pci/pci.h |  1 +
>>  2 files changed, 17 insertions(+), 6 deletions(-)
>>
>> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
>> index 4c004f5..0072b54 100644
>> --- a/hw/pci/pci.c
>> +++ b/hw/pci/pci.c
>> @@ -812,12 +812,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
>>      }
>>  
>>      pci_dev->bus = bus;
>> -    if (bus->iommu_fn) {
>> -        dma_as = bus->iommu_fn(bus, bus->iommu_opaque, devfn);
>> -    } else {
>> -        /* FIXME: inherit memory region from bus creator */
>> -        dma_as = &address_space_memory;
>> -    }
>> +    dma_as = pci_device_iommu_address_space(pci_dev);
>>  
>>      memory_region_init_alias(&pci_dev->bus_master_enable_region,
>>                               OBJECT(pci_dev), "bus master",
>> @@ -2239,6 +2234,21 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
>>      k->props = pci_props;
>>  }
>>  
>> +AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
>> +{
>> +    PCIBus *bus = PCI_BUS(dev->bus);
>> +
>> +    if (bus->iommu_fn) {
>> +        return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
>> +    }
>> +
>> +    if (bus->parent_dev) {
>> +        return pci_device_iommu_address_space(bus->parent_dev);
>> +    }
> 
> No, this would fail if bus->parent_dev is not NULL but not a PCI device
> either.

parent_dev is of the PCIDevice* type, how can it be not a PCI device? :-/


> You can use object_dynamic_cast to convert the parent_dev to
> PCIDevice, and if the cast succeeds you call the new function.
> 
> Perhaps you could make the new function take a PCIBus instead.
> Accessing the PCIDevice's IOMMU address space (as opposed to the
> bus-master address space) doesn't make much sense, VFIO is really a
> special case.  Putting the new API on the bus side instead looks better.
> 
> (BTW, do you need to enable bus-master DMA on PCI bridges, to do DMA for
> devices sitting on the secondary bus?)


It happens naturally I guess when linux enables devices.


-- 
Alexey

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v2] pci: Introduce helper to retrieve a PCI device's DMA address space
  2013-08-09  9:48   ` Alexey Kardashevskiy
@ 2013-08-09  9:53     ` Paolo Bonzini
  2013-08-09 10:13       ` Alexey Kardashevskiy
  2013-08-09 10:44     ` David Gibson
  1 sibling, 1 reply; 13+ messages in thread
From: Paolo Bonzini @ 2013-08-09  9:53 UTC (permalink / raw)
  To: Alexey Kardashevskiy
  Cc: Anthony Liguori, Michael S . Tsirkin, qemu-devel, David Gibson

Il 09/08/2013 11:48, Alexey Kardashevskiy ha scritto:
> On 08/09/2013 07:40 PM, Paolo Bonzini wrote:
>> Il 09/08/2013 10:49, Alexey Kardashevskiy ha scritto:
>>> A PCI device's DMA address space (possibly an IOMMU) is returned by a
>>> method on the PCIBus.  At the moment that only has one caller, so the
>>> method is simply open coded.  We'll need another caller for VFIO, so
>>> this patch introduces a helper/wrapper function.
>>>
>>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>>> [aik: added inheritance from parent if iommu is not set for the current bus]
>>> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
>>>
>>> ---
>>> Changes:
>>> v2:
>>> * added inheritance, needed for a pci-bridge on spapr-ppc64
>>> * pci_iommu_as renamed to pci_device_iommu_address_space
>>> ---
>>>  hw/pci/pci.c         | 22 ++++++++++++++++------
>>>  include/hw/pci/pci.h |  1 +
>>>  2 files changed, 17 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
>>> index 4c004f5..0072b54 100644
>>> --- a/hw/pci/pci.c
>>> +++ b/hw/pci/pci.c
>>> @@ -812,12 +812,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
>>>      }
>>>  
>>>      pci_dev->bus = bus;
>>> -    if (bus->iommu_fn) {
>>> -        dma_as = bus->iommu_fn(bus, bus->iommu_opaque, devfn);
>>> -    } else {
>>> -        /* FIXME: inherit memory region from bus creator */
>>> -        dma_as = &address_space_memory;
>>> -    }
>>> +    dma_as = pci_device_iommu_address_space(pci_dev);
>>>  
>>>      memory_region_init_alias(&pci_dev->bus_master_enable_region,
>>>                               OBJECT(pci_dev), "bus master",
>>> @@ -2239,6 +2234,21 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
>>>      k->props = pci_props;
>>>  }
>>>  
>>> +AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
>>> +{
>>> +    PCIBus *bus = PCI_BUS(dev->bus);
>>> +
>>> +    if (bus->iommu_fn) {
>>> +        return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
>>> +    }
>>> +
>>> +    if (bus->parent_dev) {
>>> +        return pci_device_iommu_address_space(bus->parent_dev);
>>> +    }
>>
>> No, this would fail if bus->parent_dev is not NULL but not a PCI device
>> either.
> 
> parent_dev is of the PCIDevice* type, how can it be not a PCI device? :-/

Doh, I misread the code, I thought it was the "parent" field in
BusState.  Why do we have parent_dev at all?

>> You can use object_dynamic_cast to convert the parent_dev to
>> PCIDevice, and if the cast succeeds you call the new function.
>>
>> Perhaps you could make the new function take a PCIBus instead.
>> Accessing the PCIDevice's IOMMU address space (as opposed to the
>> bus-master address space) doesn't make much sense, VFIO is really a
>> special case.  Putting the new API on the bus side instead looks better.
>>
>> (BTW, do you need to enable bus-master DMA on PCI bridges, to do DMA for
>> devices sitting on the secondary bus?)
> 
> It happens naturally I guess when linux enables devices.

Yes, but then using the IOMMU address space would be wrong; you would
have to use the bus-master address space as a base for the child's
bus-master address space.

Also, we would have to fix the x86 firmware.

Paolo

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v2] pci: Introduce helper to retrieve a PCI device's DMA address space
  2013-08-09  9:53     ` Paolo Bonzini
@ 2013-08-09 10:13       ` Alexey Kardashevskiy
  2013-08-09 10:19         ` Paolo Bonzini
  0 siblings, 1 reply; 13+ messages in thread
From: Alexey Kardashevskiy @ 2013-08-09 10:13 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Anthony Liguori, Michael S . Tsirkin, qemu-devel, David Gibson

On 08/09/2013 07:53 PM, Paolo Bonzini wrote:
> Il 09/08/2013 11:48, Alexey Kardashevskiy ha scritto:
>> On 08/09/2013 07:40 PM, Paolo Bonzini wrote:
>>> Il 09/08/2013 10:49, Alexey Kardashevskiy ha scritto:
>>>> A PCI device's DMA address space (possibly an IOMMU) is returned by a
>>>> method on the PCIBus.  At the moment that only has one caller, so the
>>>> method is simply open coded.  We'll need another caller for VFIO, so
>>>> this patch introduces a helper/wrapper function.
>>>>
>>>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>>>> [aik: added inheritance from parent if iommu is not set for the current bus]
>>>> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
>>>>
>>>> ---
>>>> Changes:
>>>> v2:
>>>> * added inheritance, needed for a pci-bridge on spapr-ppc64
>>>> * pci_iommu_as renamed to pci_device_iommu_address_space
>>>> ---
>>>>  hw/pci/pci.c         | 22 ++++++++++++++++------
>>>>  include/hw/pci/pci.h |  1 +
>>>>  2 files changed, 17 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
>>>> index 4c004f5..0072b54 100644
>>>> --- a/hw/pci/pci.c
>>>> +++ b/hw/pci/pci.c
>>>> @@ -812,12 +812,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
>>>>      }
>>>>  
>>>>      pci_dev->bus = bus;
>>>> -    if (bus->iommu_fn) {
>>>> -        dma_as = bus->iommu_fn(bus, bus->iommu_opaque, devfn);
>>>> -    } else {
>>>> -        /* FIXME: inherit memory region from bus creator */
>>>> -        dma_as = &address_space_memory;
>>>> -    }
>>>> +    dma_as = pci_device_iommu_address_space(pci_dev);
>>>>  
>>>>      memory_region_init_alias(&pci_dev->bus_master_enable_region,
>>>>                               OBJECT(pci_dev), "bus master",
>>>> @@ -2239,6 +2234,21 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
>>>>      k->props = pci_props;
>>>>  }
>>>>  
>>>> +AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
>>>> +{
>>>> +    PCIBus *bus = PCI_BUS(dev->bus);
>>>> +
>>>> +    if (bus->iommu_fn) {
>>>> +        return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
>>>> +    }
>>>> +
>>>> +    if (bus->parent_dev) {
>>>> +        return pci_device_iommu_address_space(bus->parent_dev);
>>>> +    }
>>>
>>> No, this would fail if bus->parent_dev is not NULL but not a PCI device
>>> either.
>>
>> parent_dev is of the PCIDevice* type, how can it be not a PCI device? :-/
> 
> Doh, I misread the code, I thought it was the "parent" field in
> BusState.  Why do we have parent_dev at all?

The code is too old? Don't know.


>>> You can use object_dynamic_cast to convert the parent_dev to
>>> PCIDevice, and if the cast succeeds you call the new function.
>>>
>>> Perhaps you could make the new function take a PCIBus instead.
>>> Accessing the PCIDevice's IOMMU address space (as opposed to the
>>> bus-master address space) doesn't make much sense, VFIO is really a
>>> special case.  Putting the new API on the bus side instead looks better.
>>>
>>> (BTW, do you need to enable bus-master DMA on PCI bridges, to do DMA for
>>> devices sitting on the secondary bus?)
>>
>> It happens naturally I guess when linux enables devices.
> 
> Yes, but then using the IOMMU address space would be wrong; you would
> have to use the bus-master address space as a base for the child's
> bus-master address space.


Like this? Works too.

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 8bdcedc..a4c70e6 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -2247,23 +2247,23 @@ AddressSpace
*pci_device_iommu_address_space(PCIDevice *dev)
 {
     PCIBus *bus = PCI_BUS(dev->bus);

     if (bus->iommu_fn) {
         return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
     }

     if (bus->parent_dev) {
         return pci_device_iommu_address_space(bus->parent_dev);
     }

-    return &address_space_memory;
+    return &dev->bus_master_as;
 }



> Also, we would have to fix the x86 firmware.
> 
> Paolo
> 


-- 
Alexey

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v2] pci: Introduce helper to retrieve a PCI device's DMA address space
  2013-08-09 10:13       ` Alexey Kardashevskiy
@ 2013-08-09 10:19         ` Paolo Bonzini
  2013-08-09 10:58           ` Alexey Kardashevskiy
  0 siblings, 1 reply; 13+ messages in thread
From: Paolo Bonzini @ 2013-08-09 10:19 UTC (permalink / raw)
  To: Alexey Kardashevskiy
  Cc: Anthony Liguori, Michael S . Tsirkin, qemu-devel, David Gibson

Il 09/08/2013 12:13, Alexey Kardashevskiy ha scritto:
> On 08/09/2013 07:53 PM, Paolo Bonzini wrote:
>> Il 09/08/2013 11:48, Alexey Kardashevskiy ha scritto:
>>> On 08/09/2013 07:40 PM, Paolo Bonzini wrote:
>>>> Il 09/08/2013 10:49, Alexey Kardashevskiy ha scritto:
>>>>> A PCI device's DMA address space (possibly an IOMMU) is returned by a
>>>>> method on the PCIBus.  At the moment that only has one caller, so the
>>>>> method is simply open coded.  We'll need another caller for VFIO, so
>>>>> this patch introduces a helper/wrapper function.
>>>>>
>>>>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>>>>> [aik: added inheritance from parent if iommu is not set for the current bus]
>>>>> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
>>>>>
>>>>> ---
>>>>> Changes:
>>>>> v2:
>>>>> * added inheritance, needed for a pci-bridge on spapr-ppc64
>>>>> * pci_iommu_as renamed to pci_device_iommu_address_space
>>>>> ---
>>>>>  hw/pci/pci.c         | 22 ++++++++++++++++------
>>>>>  include/hw/pci/pci.h |  1 +
>>>>>  2 files changed, 17 insertions(+), 6 deletions(-)
>>>>>
>>>>> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
>>>>> index 4c004f5..0072b54 100644
>>>>> --- a/hw/pci/pci.c
>>>>> +++ b/hw/pci/pci.c
>>>>> @@ -812,12 +812,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
>>>>>      }
>>>>>  
>>>>>      pci_dev->bus = bus;
>>>>> -    if (bus->iommu_fn) {
>>>>> -        dma_as = bus->iommu_fn(bus, bus->iommu_opaque, devfn);
>>>>> -    } else {
>>>>> -        /* FIXME: inherit memory region from bus creator */
>>>>> -        dma_as = &address_space_memory;
>>>>> -    }
>>>>> +    dma_as = pci_device_iommu_address_space(pci_dev);
>>>>>  
>>>>>      memory_region_init_alias(&pci_dev->bus_master_enable_region,
>>>>>                               OBJECT(pci_dev), "bus master",
>>>>> @@ -2239,6 +2234,21 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
>>>>>      k->props = pci_props;
>>>>>  }
>>>>>  
>>>>> +AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
>>>>> +{
>>>>> +    PCIBus *bus = PCI_BUS(dev->bus);
>>>>> +
>>>>> +    if (bus->iommu_fn) {
>>>>> +        return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
>>>>> +    }
>>>>> +
>>>>> +    if (bus->parent_dev) {
>>>>> +        return pci_device_iommu_address_space(bus->parent_dev);
>>>>> +    }
>>>>
>>>> No, this would fail if bus->parent_dev is not NULL but not a PCI device
>>>> either.
>>>
>>> parent_dev is of the PCIDevice* type, how can it be not a PCI device? :-/
>>
>> Doh, I misread the code, I thought it was the "parent" field in
>> BusState.  Why do we have parent_dev at all?
> 
> The code is too old? Don't know.
> 
> 
>>>> You can use object_dynamic_cast to convert the parent_dev to
>>>> PCIDevice, and if the cast succeeds you call the new function.
>>>>
>>>> Perhaps you could make the new function take a PCIBus instead.
>>>> Accessing the PCIDevice's IOMMU address space (as opposed to the
>>>> bus-master address space) doesn't make much sense, VFIO is really a
>>>> special case.  Putting the new API on the bus side instead looks better.
>>>>
>>>> (BTW, do you need to enable bus-master DMA on PCI bridges, to do DMA for
>>>> devices sitting on the secondary bus?)
>>>
>>> It happens naturally I guess when linux enables devices.
>>
>> Yes, but then using the IOMMU address space would be wrong; you would
>> have to use the bus-master address space as a base for the child's
>> bus-master address space.
> 
> 
> Like this? Works too.
> 
> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> index 8bdcedc..a4c70e6 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -2247,23 +2247,23 @@ AddressSpace
> *pci_device_iommu_address_space(PCIDevice *dev)
>  {
>      PCIBus *bus = PCI_BUS(dev->bus);
> 
>      if (bus->iommu_fn) {
>          return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
>      }
> 
>      if (bus->parent_dev) {
>          return pci_device_iommu_address_space(bus->parent_dev);
>      }
> 
> -    return &address_space_memory;
> +    return &dev->bus_master_as;
>  }

I was thinking more like this:

     if (bus->parent_dev) {
-        return pci_device_iommu_address_space(bus->parent_dev);
+        /* Take parent device's bus-master enable bit into account.  */
+        return pci_get_address_space(bus->parent_dev);
     }

+    /* Not a secondary bus and no IOMMU.  Use system memory.  */
     return &address_space_memory;

Paolo

> 
> 
>> Also, we would have to fix the x86 firmware.
>>
>> Paolo
>>
> 
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v2] pci: Introduce helper to retrieve a PCI device's DMA address space
  2013-08-09  9:40 ` Paolo Bonzini
  2013-08-09  9:48   ` Alexey Kardashevskiy
@ 2013-08-09 10:20   ` Benjamin Herrenschmidt
  2013-08-09 10:29     ` Paolo Bonzini
  1 sibling, 1 reply; 13+ messages in thread
From: Benjamin Herrenschmidt @ 2013-08-09 10:20 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Alexey Kardashevskiy, Anthony Liguori, Michael S . Tsirkin,
	qemu-devel, David Gibson

On Fri, 2013-08-09 at 11:40 +0200, Paolo Bonzini wrote:
> (BTW, do you need to enable bus-master DMA on PCI bridges, to do DMA
> for devices sitting on the secondary bus?)

In theory yes though I have seen bridges who ignore it...

Cheers,
Ben.
 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v2] pci: Introduce helper to retrieve a PCI device's DMA address space
  2013-08-09 10:20   ` Benjamin Herrenschmidt
@ 2013-08-09 10:29     ` Paolo Bonzini
  0 siblings, 0 replies; 13+ messages in thread
From: Paolo Bonzini @ 2013-08-09 10:29 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Alexey Kardashevskiy, Anthony Liguori, David Gibson, qemu-devel,
	Michael S . Tsirkin

Il 09/08/2013 12:20, Benjamin Herrenschmidt ha scritto:
> On Fri, 2013-08-09 at 11:40 +0200, Paolo Bonzini wrote:
>> (BTW, do you need to enable bus-master DMA on PCI bridges, to do DMA
>> for devices sitting on the secondary bus?)
> 
> In theory yes though I have seen bridges who ignore it...

And we would need a compatibility property anyway.  So let's choose to
be among the ones who ignore it (i.e. the same as this patch).  But it
needs a comment.

Paolo

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v2] pci: Introduce helper to retrieve a PCI device's DMA address space
  2013-08-09  9:48   ` Alexey Kardashevskiy
  2013-08-09  9:53     ` Paolo Bonzini
@ 2013-08-09 10:44     ` David Gibson
  1 sibling, 0 replies; 13+ messages in thread
From: David Gibson @ 2013-08-09 10:44 UTC (permalink / raw)
  To: Alexey Kardashevskiy
  Cc: Paolo Bonzini, Anthony Liguori, Michael S . Tsirkin, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 2989 bytes --]

On Fri, Aug 09, 2013 at 07:48:16PM +1000, Alexey Kardashevskiy wrote:
> On 08/09/2013 07:40 PM, Paolo Bonzini wrote:
> > Il 09/08/2013 10:49, Alexey Kardashevskiy ha scritto:
> >> A PCI device's DMA address space (possibly an IOMMU) is returned by a
> >> method on the PCIBus.  At the moment that only has one caller, so the
> >> method is simply open coded.  We'll need another caller for VFIO, so
> >> this patch introduces a helper/wrapper function.
> >>
> >> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> >> [aik: added inheritance from parent if iommu is not set for the current bus]
> >> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
> >>
> >> ---
> >> Changes:
> >> v2:
> >> * added inheritance, needed for a pci-bridge on spapr-ppc64
> >> * pci_iommu_as renamed to pci_device_iommu_address_space
> >> ---
> >>  hw/pci/pci.c         | 22 ++++++++++++++++------
> >>  include/hw/pci/pci.h |  1 +
> >>  2 files changed, 17 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> >> index 4c004f5..0072b54 100644
> >> --- a/hw/pci/pci.c
> >> +++ b/hw/pci/pci.c
> >> @@ -812,12 +812,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
> >>      }
> >>  
> >>      pci_dev->bus = bus;
> >> -    if (bus->iommu_fn) {
> >> -        dma_as = bus->iommu_fn(bus, bus->iommu_opaque, devfn);
> >> -    } else {
> >> -        /* FIXME: inherit memory region from bus creator */
> >> -        dma_as = &address_space_memory;
> >> -    }
> >> +    dma_as = pci_device_iommu_address_space(pci_dev);
> >>  
> >>      memory_region_init_alias(&pci_dev->bus_master_enable_region,
> >>                               OBJECT(pci_dev), "bus master",
> >> @@ -2239,6 +2234,21 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
> >>      k->props = pci_props;
> >>  }
> >>  
> >> +AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
> >> +{
> >> +    PCIBus *bus = PCI_BUS(dev->bus);
> >> +
> >> +    if (bus->iommu_fn) {
> >> +        return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
> >> +    }
> >> +
> >> +    if (bus->parent_dev) {
> >> +        return pci_device_iommu_address_space(bus->parent_dev);
> >> +    }
> > 
> > No, this would fail if bus->parent_dev is not NULL but not a PCI device
> > either.
> 
> parent_dev is of the PCIDevice* type, how can it be not a PCI device? :-/

It will be a PCI device, though the confusion is understandable.
There is a parent_dev in both PCIBus, which is always a PCI device if
non-NULL, as well as a parent_dev in BusState, which can be any sort
of device.  If both are non-NULL they will be equal apart from type.

So bus->parent_dev is safe here, bus->qbus.parent_dev would not be.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v2] pci: Introduce helper to retrieve a PCI device's DMA address space
  2013-08-09 10:19         ` Paolo Bonzini
@ 2013-08-09 10:58           ` Alexey Kardashevskiy
  2013-08-09 11:07             ` Paolo Bonzini
  0 siblings, 1 reply; 13+ messages in thread
From: Alexey Kardashevskiy @ 2013-08-09 10:58 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Anthony Liguori, Michael S . Tsirkin, qemu-devel, Alex Williamson,
	David Gibson

On 08/09/2013 08:19 PM, Paolo Bonzini wrote:
> Il 09/08/2013 12:13, Alexey Kardashevskiy ha scritto:
>> On 08/09/2013 07:53 PM, Paolo Bonzini wrote:
>>> Il 09/08/2013 11:48, Alexey Kardashevskiy ha scritto:
>>>> On 08/09/2013 07:40 PM, Paolo Bonzini wrote:
>>>>> Il 09/08/2013 10:49, Alexey Kardashevskiy ha scritto:
>>>>>> A PCI device's DMA address space (possibly an IOMMU) is returned by a
>>>>>> method on the PCIBus.  At the moment that only has one caller, so the
>>>>>> method is simply open coded.  We'll need another caller for VFIO, so
>>>>>> this patch introduces a helper/wrapper function.
>>>>>>
>>>>>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>>>>>> [aik: added inheritance from parent if iommu is not set for the current bus]
>>>>>> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
>>>>>>
>>>>>> ---
>>>>>> Changes:
>>>>>> v2:
>>>>>> * added inheritance, needed for a pci-bridge on spapr-ppc64
>>>>>> * pci_iommu_as renamed to pci_device_iommu_address_space
>>>>>> ---
>>>>>>  hw/pci/pci.c         | 22 ++++++++++++++++------
>>>>>>  include/hw/pci/pci.h |  1 +
>>>>>>  2 files changed, 17 insertions(+), 6 deletions(-)
>>>>>>
>>>>>> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
>>>>>> index 4c004f5..0072b54 100644
>>>>>> --- a/hw/pci/pci.c
>>>>>> +++ b/hw/pci/pci.c
>>>>>> @@ -812,12 +812,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
>>>>>>      }
>>>>>>  
>>>>>>      pci_dev->bus = bus;
>>>>>> -    if (bus->iommu_fn) {
>>>>>> -        dma_as = bus->iommu_fn(bus, bus->iommu_opaque, devfn);
>>>>>> -    } else {
>>>>>> -        /* FIXME: inherit memory region from bus creator */
>>>>>> -        dma_as = &address_space_memory;
>>>>>> -    }
>>>>>> +    dma_as = pci_device_iommu_address_space(pci_dev);
>>>>>>  
>>>>>>      memory_region_init_alias(&pci_dev->bus_master_enable_region,
>>>>>>                               OBJECT(pci_dev), "bus master",
>>>>>> @@ -2239,6 +2234,21 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
>>>>>>      k->props = pci_props;
>>>>>>  }
>>>>>>  
>>>>>> +AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
>>>>>> +{
>>>>>> +    PCIBus *bus = PCI_BUS(dev->bus);
>>>>>> +
>>>>>> +    if (bus->iommu_fn) {
>>>>>> +        return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
>>>>>> +    }
>>>>>> +
>>>>>> +    if (bus->parent_dev) {
>>>>>> +        return pci_device_iommu_address_space(bus->parent_dev);
>>>>>> +    }
>>>>>
>>>>> No, this would fail if bus->parent_dev is not NULL but not a PCI device
>>>>> either.
>>>>
>>>> parent_dev is of the PCIDevice* type, how can it be not a PCI device? :-/
>>>
>>> Doh, I misread the code, I thought it was the "parent" field in
>>> BusState.  Why do we have parent_dev at all?
>>
>> The code is too old? Don't know.
>>
>>
>>>>> You can use object_dynamic_cast to convert the parent_dev to
>>>>> PCIDevice, and if the cast succeeds you call the new function.
>>>>>
>>>>> Perhaps you could make the new function take a PCIBus instead.
>>>>> Accessing the PCIDevice's IOMMU address space (as opposed to the
>>>>> bus-master address space) doesn't make much sense, VFIO is really a
>>>>> special case.  Putting the new API on the bus side instead looks better.
>>>>>
>>>>> (BTW, do you need to enable bus-master DMA on PCI bridges, to do DMA for
>>>>> devices sitting on the secondary bus?)
>>>>
>>>> It happens naturally I guess when linux enables devices.
>>>
>>> Yes, but then using the IOMMU address space would be wrong; you would
>>> have to use the bus-master address space as a base for the child's
>>> bus-master address space.
>>
>>
>> Like this? Works too.
>>
>> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
>> index 8bdcedc..a4c70e6 100644
>> --- a/hw/pci/pci.c
>> +++ b/hw/pci/pci.c
>> @@ -2247,23 +2247,23 @@ AddressSpace
>> *pci_device_iommu_address_space(PCIDevice *dev)
>>  {
>>      PCIBus *bus = PCI_BUS(dev->bus);
>>
>>      if (bus->iommu_fn) {
>>          return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
>>      }
>>
>>      if (bus->parent_dev) {
>>          return pci_device_iommu_address_space(bus->parent_dev);
>>      }
>>
>> -    return &address_space_memory;
>> +    return &dev->bus_master_as;
>>  }
> 
> I was thinking more like this:
> 
>      if (bus->parent_dev) {
> -        return pci_device_iommu_address_space(bus->parent_dev);
> +        /* Take parent device's bus-master enable bit into account.  */
> +        return pci_get_address_space(bus->parent_dev);
>      }
> 
> +    /* Not a secondary bus and no IOMMU.  Use system memory.  */
>      return &address_space_memory;

Ok.

Oh. BTW. This "bus master" thing now breaks VFIO's check for all devices
being in the same address space as every single device has its own "bus
master" AddressSpace.


> 
> Paolo
> 
>>
>>
>>> Also, we would have to fix the x86 firmware.

btw what would it mean? :)


>>>
>>> Paolo
>>>
>>
>>
> 


-- 
Alexey

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v2] pci: Introduce helper to retrieve a PCI device's DMA address space
  2013-08-09 10:58           ` Alexey Kardashevskiy
@ 2013-08-09 11:07             ` Paolo Bonzini
  2013-08-09 11:21               ` Alexey Kardashevskiy
  0 siblings, 1 reply; 13+ messages in thread
From: Paolo Bonzini @ 2013-08-09 11:07 UTC (permalink / raw)
  To: Alexey Kardashevskiy
  Cc: Anthony Liguori, Michael S . Tsirkin, qemu-devel, Alex Williamson,
	David Gibson

Il 09/08/2013 12:58, Alexey Kardashevskiy ha scritto:
> On 08/09/2013 08:19 PM, Paolo Bonzini wrote:
>> Il 09/08/2013 12:13, Alexey Kardashevskiy ha scritto:
>>> On 08/09/2013 07:53 PM, Paolo Bonzini wrote:
>>>> Il 09/08/2013 11:48, Alexey Kardashevskiy ha scritto:
>>>>> On 08/09/2013 07:40 PM, Paolo Bonzini wrote:
>>>>>> Il 09/08/2013 10:49, Alexey Kardashevskiy ha scritto:
>>>>>>> A PCI device's DMA address space (possibly an IOMMU) is returned by a
>>>>>>> method on the PCIBus.  At the moment that only has one caller, so the
>>>>>>> method is simply open coded.  We'll need another caller for VFIO, so
>>>>>>> this patch introduces a helper/wrapper function.
>>>>>>>
>>>>>>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>>>>>>> [aik: added inheritance from parent if iommu is not set for the current bus]
>>>>>>> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
>>>>>>>
>>>>>>> ---
>>>>>>> Changes:
>>>>>>> v2:
>>>>>>> * added inheritance, needed for a pci-bridge on spapr-ppc64
>>>>>>> * pci_iommu_as renamed to pci_device_iommu_address_space
>>>>>>> ---
>>>>>>>  hw/pci/pci.c         | 22 ++++++++++++++++------
>>>>>>>  include/hw/pci/pci.h |  1 +
>>>>>>>  2 files changed, 17 insertions(+), 6 deletions(-)
>>>>>>>
>>>>>>> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
>>>>>>> index 4c004f5..0072b54 100644
>>>>>>> --- a/hw/pci/pci.c
>>>>>>> +++ b/hw/pci/pci.c
>>>>>>> @@ -812,12 +812,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
>>>>>>>      }
>>>>>>>  
>>>>>>>      pci_dev->bus = bus;
>>>>>>> -    if (bus->iommu_fn) {
>>>>>>> -        dma_as = bus->iommu_fn(bus, bus->iommu_opaque, devfn);
>>>>>>> -    } else {
>>>>>>> -        /* FIXME: inherit memory region from bus creator */
>>>>>>> -        dma_as = &address_space_memory;
>>>>>>> -    }
>>>>>>> +    dma_as = pci_device_iommu_address_space(pci_dev);
>>>>>>>  
>>>>>>>      memory_region_init_alias(&pci_dev->bus_master_enable_region,
>>>>>>>                               OBJECT(pci_dev), "bus master",
>>>>>>> @@ -2239,6 +2234,21 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
>>>>>>>      k->props = pci_props;
>>>>>>>  }
>>>>>>>  
>>>>>>> +AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
>>>>>>> +{
>>>>>>> +    PCIBus *bus = PCI_BUS(dev->bus);
>>>>>>> +
>>>>>>> +    if (bus->iommu_fn) {
>>>>>>> +        return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
>>>>>>> +    }
>>>>>>> +
>>>>>>> +    if (bus->parent_dev) {
>>>>>>> +        return pci_device_iommu_address_space(bus->parent_dev);
>>>>>>> +    }
>>>>>>
>>>>>> No, this would fail if bus->parent_dev is not NULL but not a PCI device
>>>>>> either.
>>>>>
>>>>> parent_dev is of the PCIDevice* type, how can it be not a PCI device? :-/
>>>>
>>>> Doh, I misread the code, I thought it was the "parent" field in
>>>> BusState.  Why do we have parent_dev at all?
>>>
>>> The code is too old? Don't know.
>>>
>>>
>>>>>> You can use object_dynamic_cast to convert the parent_dev to
>>>>>> PCIDevice, and if the cast succeeds you call the new function.
>>>>>>
>>>>>> Perhaps you could make the new function take a PCIBus instead.
>>>>>> Accessing the PCIDevice's IOMMU address space (as opposed to the
>>>>>> bus-master address space) doesn't make much sense, VFIO is really a
>>>>>> special case.  Putting the new API on the bus side instead looks better.
>>>>>>
>>>>>> (BTW, do you need to enable bus-master DMA on PCI bridges, to do DMA for
>>>>>> devices sitting on the secondary bus?)
>>>>>
>>>>> It happens naturally I guess when linux enables devices.
>>>>
>>>> Yes, but then using the IOMMU address space would be wrong; you would
>>>> have to use the bus-master address space as a base for the child's
>>>> bus-master address space.
>>>
>>>
>>> Like this? Works too.
>>>
>>> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
>>> index 8bdcedc..a4c70e6 100644
>>> --- a/hw/pci/pci.c
>>> +++ b/hw/pci/pci.c
>>> @@ -2247,23 +2247,23 @@ AddressSpace
>>> *pci_device_iommu_address_space(PCIDevice *dev)
>>>  {
>>>      PCIBus *bus = PCI_BUS(dev->bus);
>>>
>>>      if (bus->iommu_fn) {
>>>          return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
>>>      }
>>>
>>>      if (bus->parent_dev) {
>>>          return pci_device_iommu_address_space(bus->parent_dev);
>>>      }
>>>
>>> -    return &address_space_memory;
>>> +    return &dev->bus_master_as;
>>>  }
>>
>> I was thinking more like this:
>>
>>      if (bus->parent_dev) {
>> -        return pci_device_iommu_address_space(bus->parent_dev);
>> +        /* Take parent device's bus-master enable bit into account.  */
>> +        return pci_get_address_space(bus->parent_dev);
>>      }
>>
>> +    /* Not a secondary bus and no IOMMU.  Use system memory.  */
>>      return &address_space_memory;
> 
> Ok.
> 
> Oh. BTW. This "bus master" thing now breaks VFIO's check for all devices
> being in the same address space as every single device has its own "bus
> master" AddressSpace.

Yes, fixing that check is another good use of the new API you introduced.

But after Ben's answer, I guess the above change is not really needed.
It would add complication for VFIO, too.  Proper emulation would require
QEMU to trap writes to the device's bus-master bit.  QEMU would have to
take of the value that the guest writes, AND it with the bus-master
bit(s) of all bridges between the host bridge and the VFIO device, and
write the result to the passed-through device.  This is because the
bridges are emulated, and do not exist in real hardware.

>>>> Also, we would have to fix the x86 firmware.
> 
> btw what would it mean? :)

Firmware would have to look for bridges and enable bus master DMA on
them.  Otherwise, for example a SCSI controller below a bridge (not
virtio-scsi) would fail to boot.

Paolo

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v2] pci: Introduce helper to retrieve a PCI device's DMA address space
  2013-08-09 11:07             ` Paolo Bonzini
@ 2013-08-09 11:21               ` Alexey Kardashevskiy
  2013-08-09 11:30                 ` Paolo Bonzini
  0 siblings, 1 reply; 13+ messages in thread
From: Alexey Kardashevskiy @ 2013-08-09 11:21 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Anthony Liguori, Michael S . Tsirkin, qemu-devel, Alex Williamson,
	David Gibson

On 08/09/2013 09:07 PM, Paolo Bonzini wrote:
> Il 09/08/2013 12:58, Alexey Kardashevskiy ha scritto:
>> On 08/09/2013 08:19 PM, Paolo Bonzini wrote:
>>> Il 09/08/2013 12:13, Alexey Kardashevskiy ha scritto:
>>>> On 08/09/2013 07:53 PM, Paolo Bonzini wrote:
>>>>> Il 09/08/2013 11:48, Alexey Kardashevskiy ha scritto:
>>>>>> On 08/09/2013 07:40 PM, Paolo Bonzini wrote:
>>>>>>> Il 09/08/2013 10:49, Alexey Kardashevskiy ha scritto:
>>>>>>>> A PCI device's DMA address space (possibly an IOMMU) is returned by a
>>>>>>>> method on the PCIBus.  At the moment that only has one caller, so the
>>>>>>>> method is simply open coded.  We'll need another caller for VFIO, so
>>>>>>>> this patch introduces a helper/wrapper function.
>>>>>>>>
>>>>>>>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>>>>>>>> [aik: added inheritance from parent if iommu is not set for the current bus]
>>>>>>>> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
>>>>>>>>
>>>>>>>> ---
>>>>>>>> Changes:
>>>>>>>> v2:
>>>>>>>> * added inheritance, needed for a pci-bridge on spapr-ppc64
>>>>>>>> * pci_iommu_as renamed to pci_device_iommu_address_space
>>>>>>>> ---
>>>>>>>>  hw/pci/pci.c         | 22 ++++++++++++++++------
>>>>>>>>  include/hw/pci/pci.h |  1 +
>>>>>>>>  2 files changed, 17 insertions(+), 6 deletions(-)
>>>>>>>>
>>>>>>>> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
>>>>>>>> index 4c004f5..0072b54 100644
>>>>>>>> --- a/hw/pci/pci.c
>>>>>>>> +++ b/hw/pci/pci.c
>>>>>>>> @@ -812,12 +812,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
>>>>>>>>      }
>>>>>>>>  
>>>>>>>>      pci_dev->bus = bus;
>>>>>>>> -    if (bus->iommu_fn) {
>>>>>>>> -        dma_as = bus->iommu_fn(bus, bus->iommu_opaque, devfn);
>>>>>>>> -    } else {
>>>>>>>> -        /* FIXME: inherit memory region from bus creator */
>>>>>>>> -        dma_as = &address_space_memory;
>>>>>>>> -    }
>>>>>>>> +    dma_as = pci_device_iommu_address_space(pci_dev);
>>>>>>>>  
>>>>>>>>      memory_region_init_alias(&pci_dev->bus_master_enable_region,
>>>>>>>>                               OBJECT(pci_dev), "bus master",
>>>>>>>> @@ -2239,6 +2234,21 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
>>>>>>>>      k->props = pci_props;
>>>>>>>>  }
>>>>>>>>  
>>>>>>>> +AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
>>>>>>>> +{
>>>>>>>> +    PCIBus *bus = PCI_BUS(dev->bus);
>>>>>>>> +
>>>>>>>> +    if (bus->iommu_fn) {
>>>>>>>> +        return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
>>>>>>>> +    }
>>>>>>>> +
>>>>>>>> +    if (bus->parent_dev) {
>>>>>>>> +        return pci_device_iommu_address_space(bus->parent_dev);
>>>>>>>> +    }
>>>>>>>
>>>>>>> No, this would fail if bus->parent_dev is not NULL but not a PCI device
>>>>>>> either.
>>>>>>
>>>>>> parent_dev is of the PCIDevice* type, how can it be not a PCI device? :-/
>>>>>
>>>>> Doh, I misread the code, I thought it was the "parent" field in
>>>>> BusState.  Why do we have parent_dev at all?
>>>>
>>>> The code is too old? Don't know.
>>>>
>>>>
>>>>>>> You can use object_dynamic_cast to convert the parent_dev to
>>>>>>> PCIDevice, and if the cast succeeds you call the new function.
>>>>>>>
>>>>>>> Perhaps you could make the new function take a PCIBus instead.
>>>>>>> Accessing the PCIDevice's IOMMU address space (as opposed to the
>>>>>>> bus-master address space) doesn't make much sense, VFIO is really a
>>>>>>> special case.  Putting the new API on the bus side instead looks better.
>>>>>>>
>>>>>>> (BTW, do you need to enable bus-master DMA on PCI bridges, to do DMA for
>>>>>>> devices sitting on the secondary bus?)
>>>>>>
>>>>>> It happens naturally I guess when linux enables devices.
>>>>>
>>>>> Yes, but then using the IOMMU address space would be wrong; you would
>>>>> have to use the bus-master address space as a base for the child's
>>>>> bus-master address space.
>>>>
>>>>
>>>> Like this? Works too.
>>>>
>>>> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
>>>> index 8bdcedc..a4c70e6 100644
>>>> --- a/hw/pci/pci.c
>>>> +++ b/hw/pci/pci.c
>>>> @@ -2247,23 +2247,23 @@ AddressSpace
>>>> *pci_device_iommu_address_space(PCIDevice *dev)
>>>>  {
>>>>      PCIBus *bus = PCI_BUS(dev->bus);
>>>>
>>>>      if (bus->iommu_fn) {
>>>>          return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
>>>>      }
>>>>
>>>>      if (bus->parent_dev) {
>>>>          return pci_device_iommu_address_space(bus->parent_dev);
>>>>      }
>>>>
>>>> -    return &address_space_memory;
>>>> +    return &dev->bus_master_as;
>>>>  }
>>>
>>> I was thinking more like this:
>>>
>>>      if (bus->parent_dev) {
>>> -        return pci_device_iommu_address_space(bus->parent_dev);
>>> +        /* Take parent device's bus-master enable bit into account.  */
>>> +        return pci_get_address_space(bus->parent_dev);
>>>      }
>>>
>>> +    /* Not a secondary bus and no IOMMU.  Use system memory.  */
>>>      return &address_space_memory;
>>
>> Ok.
>>
>> Oh. BTW. This "bus master" thing now breaks VFIO's check for all devices
>> being in the same address space as every single device has its own "bus
>> master" AddressSpace.
> 
> Yes, fixing that check is another good use of the new API you introduced.
> 
> But after Ben's answer, I guess the above change is not really needed.
> It would add complication for VFIO, too.  Proper emulation would require
> QEMU to trap writes to the device's bus-master bit.  QEMU would have to
> take of the value that the guest writes, AND it with the bus-master
> bit(s) of all bridges between the host bridge and the VFIO device, and
> write the result to the passed-through device.  This is because the
> bridges are emulated, and do not exist in real hardware.


So does this mean that we go with the original patch and ignore bus master
address space here?


I guess I could overcome that VFIO check by comparing not just AddressSpace
but AddressSpace->root if AddressSpace is different but it does not make a
lot of sense.

> 
>>>>> Also, we would have to fix the x86 firmware.
>>
>> btw what would it mean? :)
> 
> Firmware would have to look for bridges and enable bus master DMA on
> them.  Otherwise, for example a SCSI controller below a bridge (not
> virtio-scsi) would fail to boot.
> 
> Paolo
> 


-- 
Alexey

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v2] pci: Introduce helper to retrieve a PCI device's DMA address space
  2013-08-09 11:21               ` Alexey Kardashevskiy
@ 2013-08-09 11:30                 ` Paolo Bonzini
  0 siblings, 0 replies; 13+ messages in thread
From: Paolo Bonzini @ 2013-08-09 11:30 UTC (permalink / raw)
  To: Alexey Kardashevskiy
  Cc: Anthony Liguori, Michael S . Tsirkin, qemu-devel, Alex Williamson,
	David Gibson

Il 09/08/2013 13:21, Alexey Kardashevskiy ha scritto:
> On 08/09/2013 09:07 PM, Paolo Bonzini wrote:
>> Il 09/08/2013 12:58, Alexey Kardashevskiy ha scritto:
>>> On 08/09/2013 08:19 PM, Paolo Bonzini wrote:
>>>> Il 09/08/2013 12:13, Alexey Kardashevskiy ha scritto:
>>>>> On 08/09/2013 07:53 PM, Paolo Bonzini wrote:
>>>>>> Il 09/08/2013 11:48, Alexey Kardashevskiy ha scritto:
>>>>>>> On 08/09/2013 07:40 PM, Paolo Bonzini wrote:
>>>>>>>> Il 09/08/2013 10:49, Alexey Kardashevskiy ha scritto:
>>>>>>>>> A PCI device's DMA address space (possibly an IOMMU) is returned by a
>>>>>>>>> method on the PCIBus.  At the moment that only has one caller, so the
>>>>>>>>> method is simply open coded.  We'll need another caller for VFIO, so
>>>>>>>>> this patch introduces a helper/wrapper function.
>>>>>>>>>
>>>>>>>>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>>>>>>>>> [aik: added inheritance from parent if iommu is not set for the current bus]
>>>>>>>>> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
>>>>>>>>>
>>>>>>>>> ---
>>>>>>>>> Changes:
>>>>>>>>> v2:
>>>>>>>>> * added inheritance, needed for a pci-bridge on spapr-ppc64
>>>>>>>>> * pci_iommu_as renamed to pci_device_iommu_address_space
>>>>>>>>> ---
>>>>>>>>>  hw/pci/pci.c         | 22 ++++++++++++++++------
>>>>>>>>>  include/hw/pci/pci.h |  1 +
>>>>>>>>>  2 files changed, 17 insertions(+), 6 deletions(-)
>>>>>>>>>
>>>>>>>>> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
>>>>>>>>> index 4c004f5..0072b54 100644
>>>>>>>>> --- a/hw/pci/pci.c
>>>>>>>>> +++ b/hw/pci/pci.c
>>>>>>>>> @@ -812,12 +812,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
>>>>>>>>>      }
>>>>>>>>>  
>>>>>>>>>      pci_dev->bus = bus;
>>>>>>>>> -    if (bus->iommu_fn) {
>>>>>>>>> -        dma_as = bus->iommu_fn(bus, bus->iommu_opaque, devfn);
>>>>>>>>> -    } else {
>>>>>>>>> -        /* FIXME: inherit memory region from bus creator */
>>>>>>>>> -        dma_as = &address_space_memory;
>>>>>>>>> -    }
>>>>>>>>> +    dma_as = pci_device_iommu_address_space(pci_dev);
>>>>>>>>>  
>>>>>>>>>      memory_region_init_alias(&pci_dev->bus_master_enable_region,
>>>>>>>>>                               OBJECT(pci_dev), "bus master",
>>>>>>>>> @@ -2239,6 +2234,21 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
>>>>>>>>>      k->props = pci_props;
>>>>>>>>>  }
>>>>>>>>>  
>>>>>>>>> +AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
>>>>>>>>> +{
>>>>>>>>> +    PCIBus *bus = PCI_BUS(dev->bus);
>>>>>>>>> +
>>>>>>>>> +    if (bus->iommu_fn) {
>>>>>>>>> +        return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
>>>>>>>>> +    }
>>>>>>>>> +
>>>>>>>>> +    if (bus->parent_dev) {
>>>>>>>>> +        return pci_device_iommu_address_space(bus->parent_dev);
>>>>>>>>> +    }
>>>>>>>>
>>>>>>>> No, this would fail if bus->parent_dev is not NULL but not a PCI device
>>>>>>>> either.
>>>>>>>
>>>>>>> parent_dev is of the PCIDevice* type, how can it be not a PCI device? :-/
>>>>>>
>>>>>> Doh, I misread the code, I thought it was the "parent" field in
>>>>>> BusState.  Why do we have parent_dev at all?
>>>>>
>>>>> The code is too old? Don't know.
>>>>>
>>>>>
>>>>>>>> You can use object_dynamic_cast to convert the parent_dev to
>>>>>>>> PCIDevice, and if the cast succeeds you call the new function.
>>>>>>>>
>>>>>>>> Perhaps you could make the new function take a PCIBus instead.
>>>>>>>> Accessing the PCIDevice's IOMMU address space (as opposed to the
>>>>>>>> bus-master address space) doesn't make much sense, VFIO is really a
>>>>>>>> special case.  Putting the new API on the bus side instead looks better.
>>>>>>>>
>>>>>>>> (BTW, do you need to enable bus-master DMA on PCI bridges, to do DMA for
>>>>>>>> devices sitting on the secondary bus?)
>>>>>>>
>>>>>>> It happens naturally I guess when linux enables devices.
>>>>>>
>>>>>> Yes, but then using the IOMMU address space would be wrong; you would
>>>>>> have to use the bus-master address space as a base for the child's
>>>>>> bus-master address space.
>>>>>
>>>>>
>>>>> Like this? Works too.
>>>>>
>>>>> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
>>>>> index 8bdcedc..a4c70e6 100644
>>>>> --- a/hw/pci/pci.c
>>>>> +++ b/hw/pci/pci.c
>>>>> @@ -2247,23 +2247,23 @@ AddressSpace
>>>>> *pci_device_iommu_address_space(PCIDevice *dev)
>>>>>  {
>>>>>      PCIBus *bus = PCI_BUS(dev->bus);
>>>>>
>>>>>      if (bus->iommu_fn) {
>>>>>          return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
>>>>>      }
>>>>>
>>>>>      if (bus->parent_dev) {
>>>>>          return pci_device_iommu_address_space(bus->parent_dev);
>>>>>      }
>>>>>
>>>>> -    return &address_space_memory;
>>>>> +    return &dev->bus_master_as;
>>>>>  }
>>>>
>>>> I was thinking more like this:
>>>>
>>>>      if (bus->parent_dev) {
>>>> -        return pci_device_iommu_address_space(bus->parent_dev);
>>>> +        /* Take parent device's bus-master enable bit into account.  */
>>>> +        return pci_get_address_space(bus->parent_dev);
>>>>      }
>>>>
>>>> +    /* Not a secondary bus and no IOMMU.  Use system memory.  */
>>>>      return &address_space_memory;
>>>
>>> Ok.
>>>
>>> Oh. BTW. This "bus master" thing now breaks VFIO's check for all devices
>>> being in the same address space as every single device has its own "bus
>>> master" AddressSpace.
>>
>> Yes, fixing that check is another good use of the new API you introduced.
>>
>> But after Ben's answer, I guess the above change is not really needed.
>> It would add complication for VFIO, too.  Proper emulation would require
>> QEMU to trap writes to the device's bus-master bit.  QEMU would have to
>> take of the value that the guest writes, AND it with the bus-master
>> bit(s) of all bridges between the host bridge and the VFIO device, and
>> write the result to the passed-through device.  This is because the
>> bridges are emulated, and do not exist in real hardware.
> 
> So does this mean that we go with the original patch and ignore bus master
> address space here?

Yes.  Just add a comment that we are ignoring the bus master DMA bit of
the bridge.

> I guess I could overcome that VFIO check by comparing not just AddressSpace
> but AddressSpace->root if AddressSpace is different but it does not make a
> lot of sense.

Paolo

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2013-08-09 11:30 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-09  8:49 [Qemu-devel] [PATCH v2] pci: Introduce helper to retrieve a PCI device's DMA address space Alexey Kardashevskiy
2013-08-09  9:40 ` Paolo Bonzini
2013-08-09  9:48   ` Alexey Kardashevskiy
2013-08-09  9:53     ` Paolo Bonzini
2013-08-09 10:13       ` Alexey Kardashevskiy
2013-08-09 10:19         ` Paolo Bonzini
2013-08-09 10:58           ` Alexey Kardashevskiy
2013-08-09 11:07             ` Paolo Bonzini
2013-08-09 11:21               ` Alexey Kardashevskiy
2013-08-09 11:30                 ` Paolo Bonzini
2013-08-09 10:44     ` David Gibson
2013-08-09 10:20   ` Benjamin Herrenschmidt
2013-08-09 10:29     ` Paolo Bonzini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).