* [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).