Re: [Qemu-devel] [PATCH v7 00/19] Fixing record/replay and adding reverse debugging

2018-10-10 Thread Aleksandr Bezzubikov
gt;  hmp-commands-info.hx  |   14 ++
>  hmp-commands.hx   |   44 ++
>  hmp.h |4 +
>  include/block/snapshot.h  |1
>  include/sysemu/replay.h   |   20 +++
>  migration/savevm.c|   15 +-
>  qapi/block-core.json  |7 +
>  qapi/block.json   |3
>  qapi/misc.json|   77 +++
>  replay/Makefile.objs  |3
>  replay/replay-debugging.c |  319
> +
>  replay/replay-events.c|   16 ++
>  replay/replay-internal.h  |7 +
>  replay/replay-time.c  |   32 ++---
>  replay/replay.c   |   26 
>  stubs/Makefile.objs   |1
>  stubs/replay-user.c   |9 +
>  stubs/replay.c|   10 +
>  vl.c  |   22 ++-
>  33 files changed, 818 insertions(+), 53 deletions(-)
>  create mode 100644 docs/devel/replay.txt
>  create mode 100644 replay/replay-debugging.c
>  create mode 100644 stubs/replay-user.c
>
> --
> Pavel Dovgalyuk
>
-- 
Aleksandr Bezzubikov


Re: [Qemu-devel] Crash with pcie-pci-bridge on qemu-system-s390x

2017-11-02 Thread Aleksandr Bezzubikov
2017-11-02 17:42 GMT+03:00 Marcel Apfelbaum <mar...@redhat.com>:
> On 02/11/2017 16:19, Thomas Huth wrote:
>>
>>   Hi,
>>
>
> Hi Thomas,
>

Hi Thomas, Marcel,

>> seems like there's a new way to crash QEMU with the pcie-pci-bridge
>> device (using QEMU master branch of today):
>>  > $ s390x-softmmu/qemu-system-s390x -nographic -S
>> QEMU 2.10.50 monitor - type 'help' for more information
>> (qemu) device_add pcie-pci-bridge,id=x
>> Segmentation fault (core dumped)
>>
>
> Thanks for noticing it.
>
>> Does anybody have a clue what might be wrong here?
>>
>
> It was tested with X86 and I think aarch64.
> I am not sure how it would work with or if we
> really need it for s390.
>
> We need the device to start a PCI hierarchy by plugging
> it to PCIe Root Port. If I understand correctly s390
> does not use PCIe Root Ports and may not need it.
>

Personally I can see 2 issues here:
1) [Marcel's already mentioned it] It seems that s390x machines have
only pure PCI hosts,
that's why it's a bit weird to put pcie-pci-bridge into the host
2) The actual segfault cause is bridge parent bus not having a parent
device (somehow).
Maybe it's a consequence of point 1)

> If the assumption is correct I suppose we should only
> be compiled into the above archs.
> If you agree, I can post a patch for this.
>
> Thanks,
> Marcel
>
>
>> Backtrace looks like this:
>>
>> #0  0x5577064b in pci_default_write_config (d=d@entry=0x0,
>> addr=addr@entry=26, val_in=1, l=l@entry=1) at
>> /home/thuth/devel/qemu/hw/pci/pci.c:1367
>> #1  0x556c885f in s390_pcihost_hot_plug (hotplug_dev=> out>, dev=0x5639b160, errp=0x7fffc5a0) at
>> /home/thuth/devel/qemu/hw/s390x/s390-pci-bus.c:684
>> #2  0x5575afeb in device_set_realized (obj=,
>> value=, errp=0x7fffc6d8) at
>> /home/thuth/devel/qemu/hw/core/qdev.c:936
>> #3  0x557ee48e in property_set_bool (obj=0x5639b160,
>> v=, name=, opaque=0x56399fe0,
>> errp=0x7fffc6d8)
>>  at /home/thuth/devel/qemu/qom/object.c:1906
>> #4  0x557f25ff in object_property_set_qobject
>> (obj=obj@entry=0x5639b160, value=value@entry=0x5639d170,
>> name=name@entry=0x559a4157 "realized",
>> errp=errp@entry=0x7fffc6d8) at
>> /home/thuth/devel/qemu/qom/qom-qobject.c:27
>> #5  0x557f0270 in object_property_set_bool (obj=0x5639b160,
>> value=, name=0x5555559a4157 "realized",
>> errp=0x7fffc6d8)
>>  at /home/thuth/devel/qemu/qom/object.c:1171
>> #6  0x5570b549 in qdev_device_add
>> (opts=opts@entry=0x5640cb50, errp=errp@entry=0x7fffc7b0) at
>> /home/thuth/devel/qemu/qdev-monitor.c:632
>> ...
>>
>>   Thomas
>>
>

Thanks,
Aleksandr Bezzubikov



Re: [Qemu-devel] Problem in pcie_pci_bridge_realize()

2017-09-27 Thread Aleksandr Bezzubikov
2017-09-27 18:50 GMT+03:00 Thomas Huth <th...@redhat.com>:
>  Hi,
>
> QEMU currently aborts with an assertion when plugging of the
> pcie-pci-bridge fails, e.g.:
>
> $ mips64el-softmmu/qemu-system-mips64el -M malta -nographic -S \
> -device pcie-pci-bridge -bios pc-bios/bios.bin
> qemu-system-mips64el: memory.c:1699: memory_region_finalize:
>  Assertion `!mr->container' failed.
> Aborted (core dumped)
>
> The backtrace points to the pcie_pci_bridge_realize() function:
>
> #0  0x7150f1f7 in raise () at /lib64/libc.so.6
> #1  0x715108e8 in abort () at /lib64/libc.so.6
> #2  0x71508266 in __assert_fail_base () at /lib64/libc.so.6
> #3  0x71508312 in  () at /lib64/libc.so.6
> #4  0x557cedaf in memory_region_finalize (obj=)
> at /home/thuth/devel/qemu/memory.c:1699
> #5  0x55a49852 in object_unref (type=, 
> obj=0x56e68580)
> at /home/thuth/devel/qemu/qom/object.c:453
> #6  0x55a49852 in object_unref (data=0x56e68580) at 
> /home/thuth/devel/qemu/qom/object.c:467
> #7  0x55a49852 in object_unref (obj=0x56e68580) at 
> /home/thuth/devel/qemu/qom/object.c:902
> #8  0x55a48887 in object_property_del_child (obj=0x56dc7760, 
> child=child@entry=0x56e68580, errp=0x0) at 
> /home/thuth/devel/qemu/qom/object.c:427
> #9  0x55a490a4 in object_unparent (obj=obj@entry=0x56e68580)
> at /home/thuth/devel/qemu/qom/object.c:446
> #10 0x559906ae in shpc_free (d=d@entry=0x56dc7760)
> at /home/thuth/devel/qemu/hw/pci/shpc.c:676
> #11 0x55987470 in pcie_pci_bridge_realize (d=0x56dc7760, 
> errp=0x7fffd710)
> at /home/thuth/devel/qemu/hw/pci-bridge/pcie_pci_bridge.c:84
> #12 0x5598ca67 in pci_qdev_realize (qdev=0x56dc7760, 
> errp=0x7fffd7b0)
> at /home/thuth/devel/qemu/hw/pci/pci.c:2024
> #13 0x5590ee4a in device_set_realized (obj=, 
> value=, errp=0x7fffd8e8) at 
> /home/thuth/devel/qemu/hw/core/qdev.c:914
>
> Any clue what might be wrong here?
>
>  Thomas

Hi Thomas,
This bug was already reported by Eduardo with ppc64, try this patch
that is intended to fix it

http://lists.nongnu.org/archive/html/qemu-devel/2017-09/msg06696.html

-- 
Aleksandr Bezzubikov



[Qemu-devel] [PATCH v2] hw/pci-bridge/pcie_pci_bridge: properly handle MSI unavailability case

2017-09-24 Thread Aleksandr Bezzubikov
QEMU with the pcie-pci-bridge device crashes if the guest board doesn't support 
MSI,
e.g. 'qemu-system-ppc64 -M prep -device pcie-pci-bridge'.
This is caused by wrong pcie-pci-bridge instantiation error handling. This 
patch fixes this issue
by falling back to legacy INTx if MSI is not available.
Also set the bridge's 'msi' property default value to 'auto' in order to 
trigger errors 
only when user explicitly set msi=on.

v2:
rewrite the commit message

Reported-by: Eduardo Habkost <ehabk...@redhat.com>
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 hw/pci-bridge/pcie_pci_bridge.c | 24 ++--
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/hw/pci-bridge/pcie_pci_bridge.c b/hw/pci-bridge/pcie_pci_bridge.c
index 9aa5cc3..da562fe 100644
--- a/hw/pci-bridge/pcie_pci_bridge.c
+++ b/hw/pci-bridge/pcie_pci_bridge.c
@@ -65,10 +65,18 @@ static void pcie_pci_bridge_realize(PCIDevice *d, Error 
**errp)
 goto aer_error;
 }
 
+Error *local_err = NULL;
 if (pcie_br->msi != ON_OFF_AUTO_OFF) {
-rc = msi_init(d, 0, 1, true, true, errp);
+rc = msi_init(d, 0, 1, true, true, _err);
 if (rc < 0) {
-goto msi_error;
+assert(rc == -ENOTSUP);
+if (pcie_br->msi != ON_OFF_AUTO_ON) {
+error_free(local_err);
+} else {
+/* failed to satisfy user's explicit request for MSI */
+error_propagate(errp, local_err);
+goto msi_error;
+}
 }
 }
 pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
@@ -81,7 +89,7 @@ aer_error:
 pm_error:
 pcie_cap_exit(d);
 cap_error:
-shpc_free(d);
+shpc_cleanup(d, _br->shpc_bar);
 error:
 pci_bridge_exitfn(d);
 }
@@ -98,7 +106,9 @@ static void pcie_pci_bridge_reset(DeviceState *qdev)
 {
 PCIDevice *d = PCI_DEVICE(qdev);
 pci_bridge_reset(qdev);
-msi_reset(d);
+if (msi_present(d)) {
+msi_reset(d);
+}
 shpc_reset(d);
 }
 
@@ -106,12 +116,14 @@ static void pcie_pci_bridge_write_config(PCIDevice *d,
 uint32_t address, uint32_t val, int len)
 {
 pci_bridge_write_config(d, address, val, len);
-msi_write_config(d, address, val, len);
+if (msi_present(d)) {
+msi_write_config(d, address, val, len);
+}
 shpc_cap_write_config(d, address, val, len);
 }
 
 static Property pcie_pci_bridge_dev_properties[] = {
-DEFINE_PROP_ON_OFF_AUTO("msi", PCIEPCIBridge, msi, ON_OFF_AUTO_ON),
+DEFINE_PROP_ON_OFF_AUTO("msi", PCIEPCIBridge, msi, ON_OFF_AUTO_AUTO),
 DEFINE_PROP_END_OF_LIST(),
 };
 
-- 
2.7.4




Re: [Qemu-devel] [PATCH] hw/pci-bridge/pcie_pci_bridge: properly handle MSI unavailability case

2017-09-21 Thread Aleksandr Bezzubikov
2017-09-21 13:16 GMT+03:00 Marcel Apfelbaum <mar...@redhat.com>:
> Hi Aleksandr,
>
> On 21/09/2017 0:21, Aleksandr Bezzubikov wrote:
>>
>> Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
>> ---
>>   hw/pci-bridge/pcie_pci_bridge.c | 24 ++--
>>   1 file changed, 18 insertions(+), 6 deletions(-)
>>
>
> Please add Eduardo's Reported-by tag and the
> actual failure in the commit message.
> You might even explain in the commit message that you
> moved msi prop to ON_OFF_AUTO_AUTO.

Should I send a new one, or resend, or just reply to this post?

>
>
>> diff --git a/hw/pci-bridge/pcie_pci_bridge.c
>> b/hw/pci-bridge/pcie_pci_bridge.c
>> index 9aa5cc3..da562fe 100644
>> --- a/hw/pci-bridge/pcie_pci_bridge.c
>> +++ b/hw/pci-bridge/pcie_pci_bridge.c
>> @@ -65,10 +65,18 @@ static void pcie_pci_bridge_realize(PCIDevice *d,
>> Error **errp)
>>   goto aer_error;
>>   }
>>   +Error *local_err = NULL;
>>   if (pcie_br->msi != ON_OFF_AUTO_OFF) {
>> -rc = msi_init(d, 0, 1, true, true, errp);
>> +rc = msi_init(d, 0, 1, true, true, _err);
>>   if (rc < 0) {
>> -goto msi_error;
>> +assert(rc == -ENOTSUP);
>> +if (pcie_br->msi != ON_OFF_AUTO_ON) {
>> +error_free(local_err);
>
>
> In that case it will fallback to legacy INTx, right?

Exactly. Maybe I should add this to the commit message.

>
> Thanks,
> Marcel
>
>
>> +} else {
>> +/* failed to satisfy user's explicit request for MSI */
>> +error_propagate(errp, local_err);
>> +goto msi_error;
>> +}
>>   }
>>   }
>>   pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
>> @@ -81,7 +89,7 @@ aer_error:
>>   pm_error:
>>   pcie_cap_exit(d);
>>   cap_error:
>> -shpc_free(d);
>> +shpc_cleanup(d, _br->shpc_bar);
>>   error:
>>   pci_bridge_exitfn(d);
>>   }
>> @@ -98,7 +106,9 @@ static void pcie_pci_bridge_reset(DeviceState *qdev)
>>   {
>>   PCIDevice *d = PCI_DEVICE(qdev);
>>   pci_bridge_reset(qdev);
>> -msi_reset(d);
>> +if (msi_present(d)) {
>> +msi_reset(d);
>> +}
>>   shpc_reset(d);
>>   }
>>   @@ -106,12 +116,14 @@ static void pcie_pci_bridge_write_config(PCIDevice
>> *d,
>>   uint32_t address, uint32_t val, int len)
>>   {
>>   pci_bridge_write_config(d, address, val, len);
>> -msi_write_config(d, address, val, len);
>> +if (msi_present(d)) {
>> +msi_write_config(d, address, val, len);
>> +}
>>   shpc_cap_write_config(d, address, val, len);
>>   }
>> static Property pcie_pci_bridge_dev_properties[] = {
>> -DEFINE_PROP_ON_OFF_AUTO("msi", PCIEPCIBridge, msi,
>> ON_OFF_AUTO_ON),
>> +DEFINE_PROP_ON_OFF_AUTO("msi", PCIEPCIBridge, msi,
>> ON_OFF_AUTO_AUTO),
>>   DEFINE_PROP_END_OF_LIST(),
>>   };
>>
>
>



-- 
Aleksandr Bezzubikov



[Qemu-devel] [PATCH] hw/pci-bridge/pcie_pci_bridge: properly handle MSI unavailability case

2017-09-20 Thread Aleksandr Bezzubikov
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/pci-bridge/pcie_pci_bridge.c | 24 ++--
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/hw/pci-bridge/pcie_pci_bridge.c b/hw/pci-bridge/pcie_pci_bridge.c
index 9aa5cc3..da562fe 100644
--- a/hw/pci-bridge/pcie_pci_bridge.c
+++ b/hw/pci-bridge/pcie_pci_bridge.c
@@ -65,10 +65,18 @@ static void pcie_pci_bridge_realize(PCIDevice *d, Error 
**errp)
 goto aer_error;
 }
 
+Error *local_err = NULL;
 if (pcie_br->msi != ON_OFF_AUTO_OFF) {
-rc = msi_init(d, 0, 1, true, true, errp);
+rc = msi_init(d, 0, 1, true, true, _err);
 if (rc < 0) {
-goto msi_error;
+assert(rc == -ENOTSUP);
+if (pcie_br->msi != ON_OFF_AUTO_ON) {
+error_free(local_err);
+} else {
+/* failed to satisfy user's explicit request for MSI */
+error_propagate(errp, local_err);
+goto msi_error;
+}
 }
 }
 pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
@@ -81,7 +89,7 @@ aer_error:
 pm_error:
 pcie_cap_exit(d);
 cap_error:
-shpc_free(d);
+shpc_cleanup(d, _br->shpc_bar);
 error:
 pci_bridge_exitfn(d);
 }
@@ -98,7 +106,9 @@ static void pcie_pci_bridge_reset(DeviceState *qdev)
 {
 PCIDevice *d = PCI_DEVICE(qdev);
 pci_bridge_reset(qdev);
-msi_reset(d);
+if (msi_present(d)) {
+msi_reset(d);
+}
 shpc_reset(d);
 }
 
@@ -106,12 +116,14 @@ static void pcie_pci_bridge_write_config(PCIDevice *d,
 uint32_t address, uint32_t val, int len)
 {
 pci_bridge_write_config(d, address, val, len);
-msi_write_config(d, address, val, len);
+if (msi_present(d)) {
+msi_write_config(d, address, val, len);
+}
 shpc_cap_write_config(d, address, val, len);
 }
 
 static Property pcie_pci_bridge_dev_properties[] = {
-DEFINE_PROP_ON_OFF_AUTO("msi", PCIEPCIBridge, msi, ON_OFF_AUTO_ON),
+DEFINE_PROP_ON_OFF_AUTO("msi", PCIEPCIBridge, msi, ON_OFF_AUTO_AUTO),
 DEFINE_PROP_END_OF_LIST(),
 };
 
-- 
2.7.4




Re: [Qemu-devel] [PATCH v7 1/4] hw/pci: introduce pcie-pci-bridge device

2017-09-20 Thread Aleksandr Bezzubikov
2017-09-20 17:02 GMT+03:00 Marcel Apfelbaum <mar...@redhat.com>:
> On 20/09/2017 16:57, Eduardo Habkost wrote:
>>
>> On Wed, Sep 20, 2017 at 09:52:01AM +, Aleksandr Bezzubikov wrote:
>>>
>>> ср, 20 сент. 2017 г. в 10:13, Marcel Apfelbaum <mar...@redhat.com>:
>>>
>>>> On 19/09/2017 23:34, Eduardo Habkost wrote:
>>>>>
>>>>> On Fri, Aug 18, 2017 at 02:36:47AM +0300, Aleksandr Bezzubikov wrote:
>>>>>>
>>>>>> Introduce a new PCIExpress-to-PCI Bridge device,
>>>>>> which is a hot-pluggable PCI Express device and
>>>>>> supports devices hot-plug with SHPC.
>>>>>>
>>>>>> This device is intended to replace the DMI-to-PCI Bridge.
>>>>>>
>>>>>> Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
>>>>>> Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
>>>>>
>>>>>
>>>>> It's possible to crash QEMU by instantiating this device, with;
>>>>>
>>>>> $ qemu-system-ppc64 -machine prep -device pcie-pci-bridge
>>>>> qemu-system-ppc64: qemu/memory.c:1533: memory_region_finalize:
>>>>
>>>> Assertion `!mr->container' failed.
>>>>>
>>>>> Aborted
>>>>
>>>>
>>>> Hi Edurado,
>>>>
>>>>>
>>>>> I didn't investigate the root cause.
>>>>>
>>>>
>>>> Thanks for reporting it!
>>>> Aleksandr, can you have a look? Maybe we should not compile
>>>> the device for ppc arch. (x86 and arm is enough)
>>>
>>>
>>>
>>> I will see what can we do. Is x86 and arm really enough?
>>
>>
>> I would investigate the original cause before disabling the device on
>> other
>> architectures, as we could be hiding a bug that's also present in x86.
>
>
> Agreed, it worth finding out the reason. But the restriction
> still makes sense.
>
>
> Thanks,
> Marcel
>
>
>   The
>>
>> backtrace looks like broken error handling logic somewhere:
>>
>> #0  0x7fffea9ff1f7 in __GI_raise (sig=sig@entry=6) at
>> ../nptl/sysdeps/unix/sysv/linux/raise.c:56
>> #1  0x7fffeaa008e8 in __GI_abort () at abort.c:90
>> #2  0x7fffea9f8266 in __assert_fail_base (fmt=0x7fffeab4ae68
>> "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n",
>> assertion=assertion@entry=0x55be4ac1 "!mr->container",
>> file=file@entry=0x55be49c4 "/root/qemu/memory.c", line=line@entry=1533,
>> function=function@entry=0x55be5100 <__PRETTY_FUNCTION__.28908>
>> "memory_region_finalize") at assert.c:92
>> #3  0x7fffea9f8312 in __GI___assert_fail
>> (assertion=assertion@entry=0x55be4ac1 "!mr->container",
>> file=file@entry=0x55be49c4 "/root/qemu/memory.c", line=line@entry=1533,
>> function=function@entry=0x55be5100 <__PRETTY_FUNCTION__.28908>
>> "memory_region_finalize") at assert.c:101
>> #4  0x557ff2df in memory_region_finalize (obj=) at
>> /root/qemu/memory.c:1533
>> #5  0x55ae77a2 in object_unref (type=,
>> obj=0x57c00d80) at /root/qemu/qom/object.c:453
>> #6  0x55ae77a2 in object_unref (data=0x57c00d80) at
>> /root/qemu/qom/object.c:467
>> #7  0x55ae77a2 in object_unref (obj=0x57c00d80) at
>> /root/qemu/qom/object.c:902
>> #8  0x55ae67d7 in object_property_del_child (obj=0x57ab6500,
>> child=child@entry=0x57c00d80, errp=0x0) at /root/qemu/qom/object.c:427
>> #9  0x55ae6ff4 in object_unparent (obj=obj@entry=0x57c00d80)
>> at /root/qemu/qom/object.c:446
>> #10 0x55a1c94e in shpc_free (d=d@entry=0x57ab6500) at
>> /root/qemu/hw/pci/shpc.c:676
>> #11 0x55a12560 in pcie_pci_bridge_realize (d=0x57ab6500,
>> errp=0x7fffd530) at /root/qemu/hw/pci-bridge/pcie_pci_bridge.c:84
>> #12 0x55a18d07 in pci_qdev_realize (qdev=0x57ab6500,
>> errp=0x7fffd5d0) at /root/qemu/hw/pci/pci.c:2024
>> #13 0x559b53aa in device_set_realized (obj=,
>> value=, errp=0x7fffd708) at /root/qemu/hw/core/qdev.c:914
>> #14 0x55ae62fe in property_set_bool (obj=0x57ab6500,
>> v=, name=, opaque=0x57ab7b30,
>> errp=0x7fffd708) at /root/qemu/qom/object.c:1886
>> #15 0x55aea3ef in object_property_set_qobject
>> (obj=obj@entry=0x57ab6500, value=value@entry=0x57ab

Re: [Qemu-devel] [PATCH v7 1/4] hw/pci: introduce pcie-pci-bridge device

2017-09-20 Thread Aleksandr Bezzubikov
ср, 20 сент. 2017 г. в 10:13, Marcel Apfelbaum <mar...@redhat.com>:

> On 19/09/2017 23:34, Eduardo Habkost wrote:
> > On Fri, Aug 18, 2017 at 02:36:47AM +0300, Aleksandr Bezzubikov wrote:
> >> Introduce a new PCIExpress-to-PCI Bridge device,
> >> which is a hot-pluggable PCI Express device and
> >> supports devices hot-plug with SHPC.
> >>
> >> This device is intended to replace the DMI-to-PCI Bridge.
> >>
> >> Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
> >> Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
> >
> > It's possible to crash QEMU by instantiating this device, with;
> >
> >$ qemu-system-ppc64 -machine prep -device pcie-pci-bridge
> >qemu-system-ppc64: qemu/memory.c:1533: memory_region_finalize:
> Assertion `!mr->container' failed.
> >Aborted
>
> Hi Edurado,
>
> >
> > I didn't investigate the root cause.
> >
>
> Thanks for reporting it!
> Aleksandr, can you have a look? Maybe we should not compile
> the device for ppc arch. (x86 and arm is enough)


I will see what can we do. Is x86 and arm really enough?


>
> Appreciated,
> Marcel
>
> --
Aleksandr Bezzubikov


Re: [Qemu-devel] What is the best commit for record-replay?

2017-09-19 Thread Aleksandr Bezzubikov
2017-09-19 12:30 GMT+03:00 Alex Bennée <alex.ben...@linaro.org>:
>
> Pavel Dovgalyuk <dovga...@ispras.ru> writes:
>
>>> From: Aleksandr Bezzubikov [mailto:zuban...@gmail.com]
>>> 2017-09-18 15:02 GMT+03:00 Aleksandr Bezzubikov <zuban...@gmail.com>:
>>> > 2017-05-02 15:42 GMT+03:00 Igor R <boost.li...@gmail.com>:
>>> >>>>>> I'm trying to use the deterministic record/replay feature, and I 
>>> >>>>>> would
>>> >>>>>> like to know which commit I should take to get it work.
>>> >>>>>> In RC0 it seems to be broken. I tried pre-MTTCG commit 2421f381dc, as
>>> >>>>
>>> >>>>> Can you retry with the latest rc? There were some fixes regarding rr 
>>> >>>>> since rc0.
>>> >>>>
>>> >>>>
>>> >>>> I've taken 2.9 release, and RR does not seem to work there.
>>> >>>> I recorded the boot process of x86 Fedora-21 linux and the replay got
>>> >>>> stuck almost immediately.
>>> >>>
>>> >>> What's your command line?
>>> >>>
>>> >>> Does it get stuck at the same place each time?
>>> >>>
>>> >>> Can you boot fine with icount but without record/replay?
>>> >>
>>> >> Here is the exact scenario:
>>> >> - Get 2.9 from git, configure it as follows: "./configure
>>> >> --target-list=i386-softmmu --enable-sdl" and  make.
>>> >> - Download 
>>> >> https://people.debian.org/~aurel32/qemu/i386/debian_squeeze_i386_standard.qcow2
>>> >> - Run qemu with the following command line, until login prompt:
>>> >> -icount shift=7,rr=record,rrfile=replay.bin -drive
>>> >> file=debian_squeeze_i386_standard.qcow2,if=none,id=img-direct -drive
>>> >> driver=blkreplay,if=none,image=img-direct,id=img-blkreplay -device
>>> >> ide-hd,drive=img-blkreplay -monitor stdio
>>> >> - Replay: -icount shift=7,rr=replay,rrfile=replay.bin -drive
>>> >> file=debian_squeeze_i386_standard.qcow2,if=none,id=img-direct -drive
>>> >> driver=blkreplay,if=none,image=img-direct,id=img-blkreplay -device
>>> >> ide-hd,drive=img-blkreplay -monitor stdio
>>> >>
>>> >> Every time I attempt to replay, QEMU gets stuck at the same EIP, at a
>>> >> very early stage.
>>> >>
>>> >>
>>> >>> Can you boot fine with icount but without record/replay?
>>> >>
>>> >> Yes. I can also enable icount and recording - it also boots fine. The
>>> >> problem with the replay.
>>> >
>>> > Hi guys,
>>> > Maybe the thread is a bit outdated, but the problem is still relevant.
>>> > I've just tried to record and replay WinXP boot process, and I've 
>>> > encountered
>>> > exactly the same problem as described above - record is fine, replay
>>> > gets stuck early. I use current master.
>>
>> Maybe this commit will work: cfb2d02be9413d45b30ed6d8e38800250b6b4b48

Unfortunately this one doesn't work either. It seems we need just an
all-in-one fix
for the current implementation to make it work.

>>
>>> > And I've discovered the second problem - recording makes initial snapshot,
>>> > but it doesn't seem to be saved to the disk - replay can't see it.
>>
>> It is ok, because there is a mode where snapshot is created and loaded.

So it shouldn't work properly when I use 'rrsnapshot=' for both
record and replay?
Then how can I enable this mode?

>>
>>> >
>>> > Hope you've already found the solution (as the last post was on 2 May)
>>> > and it's just got missed the mailing list.
>>
>> As I know, RR is still broken in the current version.
>> It was caused by the MTTCG implementation.
>> Alex Bennee tried to fix RR back. Alex, have you found any solution?
>>
>> We also trying to find a way to fix RR. It seems, that we will reinvent BQL 
>> for RR.
>
> I think the method outlined in my RFC is the way to go, essentially the
> RR mutex taking over for the what the BQL did. The RFC patch hadn't
> hoisted the mutex for the additional devices so I'm just re-basing now
> and I'll see if I can make the changes for Igor's test case.
>
> --
> Alex Bennée



-- 
Aleksandr Bezzubikov



Re: [Qemu-devel] What is the best commit for record-replay?

2017-09-18 Thread Aleksandr Bezzubikov
[+CC Pavel Dovgaluk, me]

2017-09-18 15:02 GMT+03:00 Aleksandr Bezzubikov <zuban...@gmail.com>:
> 2017-05-02 15:42 GMT+03:00 Igor R <boost.li...@gmail.com>:
>>>>>> I'm trying to use the deterministic record/replay feature, and I would
>>>>>> like to know which commit I should take to get it work.
>>>>>> In RC0 it seems to be broken. I tried pre-MTTCG commit 2421f381dc, as
>>>>
>>>>> Can you retry with the latest rc? There were some fixes regarding rr 
>>>>> since rc0.
>>>>
>>>>
>>>> I've taken 2.9 release, and RR does not seem to work there.
>>>> I recorded the boot process of x86 Fedora-21 linux and the replay got
>>>> stuck almost immediately.
>>>
>>> What's your command line?
>>>
>>> Does it get stuck at the same place each time?
>>>
>>> Can you boot fine with icount but without record/replay?
>>
>> Here is the exact scenario:
>> - Get 2.9 from git, configure it as follows: "./configure
>> --target-list=i386-softmmu --enable-sdl" and  make.
>> - Download 
>> https://people.debian.org/~aurel32/qemu/i386/debian_squeeze_i386_standard.qcow2
>> - Run qemu with the following command line, until login prompt:
>> -icount shift=7,rr=record,rrfile=replay.bin -drive
>> file=debian_squeeze_i386_standard.qcow2,if=none,id=img-direct -drive
>> driver=blkreplay,if=none,image=img-direct,id=img-blkreplay -device
>> ide-hd,drive=img-blkreplay -monitor stdio
>> - Replay: -icount shift=7,rr=replay,rrfile=replay.bin -drive
>> file=debian_squeeze_i386_standard.qcow2,if=none,id=img-direct -drive
>> driver=blkreplay,if=none,image=img-direct,id=img-blkreplay -device
>> ide-hd,drive=img-blkreplay -monitor stdio
>>
>> Every time I attempt to replay, QEMU gets stuck at the same EIP, at a
>> very early stage.
>>
>>
>>> Can you boot fine with icount but without record/replay?
>>
>> Yes. I can also enable icount and recording - it also boots fine. The
>> problem with the replay.
>
> Hi guys,
> Maybe the thread is a bit outdated, but the problem is still relevant.
> I've just tried to record and replay WinXP boot process, and I've encountered
> exactly the same problem as described above - record is fine, replay
> gets stuck early. I use current master.
> And I've discovered the second problem - recording makes initial snapshot,
> but it doesn't seem to be saved to the disk - replay can't see it.
>
> Hope you've already found the solution (as the last post was on 2 May)
> and it's just got missed the mailing list.
>
>>
>
>
>
> --
> Aleksandr Bezzubikov



-- 
Aleksandr Bezzubikov



Re: [Qemu-devel] What is the best commit for record-replay?

2017-09-18 Thread Aleksandr Bezzubikov
2017-05-02 15:42 GMT+03:00 Igor R <boost.li...@gmail.com>:
>>>>> I'm trying to use the deterministic record/replay feature, and I would
>>>>> like to know which commit I should take to get it work.
>>>>> In RC0 it seems to be broken. I tried pre-MTTCG commit 2421f381dc, as
>>>
>>>> Can you retry with the latest rc? There were some fixes regarding rr since 
>>>> rc0.
>>>
>>>
>>> I've taken 2.9 release, and RR does not seem to work there.
>>> I recorded the boot process of x86 Fedora-21 linux and the replay got
>>> stuck almost immediately.
>>
>> What's your command line?
>>
>> Does it get stuck at the same place each time?
>>
>> Can you boot fine with icount but without record/replay?
>
> Here is the exact scenario:
> - Get 2.9 from git, configure it as follows: "./configure
> --target-list=i386-softmmu --enable-sdl" and  make.
> - Download 
> https://people.debian.org/~aurel32/qemu/i386/debian_squeeze_i386_standard.qcow2
> - Run qemu with the following command line, until login prompt:
> -icount shift=7,rr=record,rrfile=replay.bin -drive
> file=debian_squeeze_i386_standard.qcow2,if=none,id=img-direct -drive
> driver=blkreplay,if=none,image=img-direct,id=img-blkreplay -device
> ide-hd,drive=img-blkreplay -monitor stdio
> - Replay: -icount shift=7,rr=replay,rrfile=replay.bin -drive
> file=debian_squeeze_i386_standard.qcow2,if=none,id=img-direct -drive
> driver=blkreplay,if=none,image=img-direct,id=img-blkreplay -device
> ide-hd,drive=img-blkreplay -monitor stdio
>
> Every time I attempt to replay, QEMU gets stuck at the same EIP, at a
> very early stage.
>
>
>> Can you boot fine with icount but without record/replay?
>
> Yes. I can also enable icount and recording - it also boots fine. The
> problem with the replay.

Hi guys,
Maybe the thread is a bit outdated, but the problem is still relevant.
I've just tried to record and replay WinXP boot process, and I've encountered
exactly the same problem as described above - record is fine, replay
gets stuck early. I use current master.
And I've discovered the second problem - recording makes initial snapshot,
but it doesn't seem to be saved to the disk - replay can't see it.

Hope you've already found the solution (as the last post was on 2 May)
and it's just got missed the mailing list.

>



-- 
Aleksandr Bezzubikov



Re: [Qemu-devel] [PATCH RESEND v7 0/3] Red Hat PCI bridge resource reserve capability

2017-09-14 Thread Aleksandr Bezzubikov
2017-09-10 22:40 GMT+03:00 Marcel Apfelbaum <mar...@redhat.com>:
> On 10/09/2017 21:34, Aleksandr Bezzubikov wrote:
>>
>>
>> пт, 18 авг. 2017 г. в 2:33, Aleksandr Bezzubikov <zuban...@gmail.com
>> <mailto:zuban...@gmail.com>>:
>>
>>
>> Now PCI bridges get a bus range number on a system init,
>> basing on currently plugged devices. That's why when one wants to
>> hotplug another bridge,
>> it needs his child bus, which the parent is unable to provide
>> (speaking about virtual device).
>> The suggested workaround is to have vendor-specific capability in
>> Red Hat PCI bridges
>> that contains number of additional bus to reserve (as well as
>> IO/MEM/PREF space limit hints)
>> on BIOS PCI init.
>> So this capability is intended only for pure QEMU->SeaBIOS usage.
>>
>> Considering all aforesaid, this series is directly connected with
>> QEMU series "Generic PCIE-PCI Bridge".
>>
>> Although the new PCI capability is supposed to contain various
>> limits along with
>> bus number to reserve, now only its full layout is proposed. And
>> only bus_reserve field is used in QEMU and BIOS. Limits usage
>> is still a subject for implementation as now
>> the main goal of this series to provide necessary support from the
>> firmware side to PCIE-PCI bridge hotplug.
>>
>> Changes v6->v7:
>> 0. Resend - fix a bug with incorrect subordinate bus default value.
>> 1. Do not use alignment in case of IO reservation cap usage.
>> 2. Log additional buses reservation events.
>>
>> Changes v5->v6:
>> 1. Remove unnecessary indents and line breaks (addresses Marcel's
>> comments)
>> 2. Count IO/MEM/PREF region size as a maximum of necessary size and
>> one provide in
>>  RESOURCE_RESERVE capability (addresses Marcel's comment).
>> 3. Make the cap debug message more detailed (addresses Marcel's
>> comment).
>> 4. Change pref_32 and pref_64 cap fields comment.
>>
>> Changes v4->v5:
>> 1. Rename capability-related #defines
>> 2. Move capability IO/MEM/PREF fields values usage to the regions
>> creation stage (addresses Marcel's comment)
>> 3. The capability layout change: separate pref_mem into pref_mem_32
>> and pref_mem_64 fields (QEMU side has the same changes) (addresses
>> Laszlo's comment)
>> 4. Extract the capability lookup and check to the separate function
>> (addresses Marcel's comment)
>>  - despite of Marcel's comment do not extract field check
>> for -1 since it increases code length
>>and doesn't look nice because of different field types
>> 5. Fix the capability's comment (addresses Marcel's comment)
>> 6. Fix the 3rd patch message
>>
>> Changes v3->v4:
>> 1. Use all QEMU PCI capability fields - addresses Michael's comment
>> 2. Changes of the capability layout (QEMU side has the same changes):
>>  - change reservation fields types: bus_res - uint32_t,
>> others - uint64_t
>>  - interpret -1 value as 'ignore'
>>
>> Changes v2->v3:
>> 1. Merge commit 2 (Red Hat vendor ID) into commit 4 - addresses
>> Marcel's comment,
>>  and add Generic PCIE Root Port device ID - addresses
>> Michael's comment.
>> 2. Changes of the capability layout  (QEMU side has the same changes):
>>  - add 'type' field to distinguish multiple
>>  RedHat-specific capabilities - addresses Michael's
>> comment
>>  - do not mimiс PCI Config space register layout, but use
>> mutually exclusive differently
>>  sized fields for IO and prefetchable memory limits
>> - addresses Laszlo's comment
>>  - use defines instead of structure and offsetof - addresses
>> Michael's comment
>> 3. Interpret 'bus_reserve' field as a minimum necessary
>>   range to reserve - addresses Gerd's comment
>> 4. pci_find_capability moved to pci.c - addresses Kevin's comment
>> 5. Move capability layout header to src/fw/dev-pci.h - addresses
>> Kevin's comment
>>     6. Add the capability documentation - addresses Michael's comment
>> 7. Add capability length and bus_reserve field sanity checks -
>> addresses Michael's comment
>>
>> Changes v1->v2:
>> 1. New #define for

Re: [Qemu-devel] [PATCH RESEND v7 0/3] Red Hat PCI bridge resource reserve capability

2017-09-10 Thread Aleksandr Bezzubikov
пт, 18 авг. 2017 г. в 2:33, Aleksandr Bezzubikov <zuban...@gmail.com>:

> Now PCI bridges get a bus range number on a system init,
> basing on currently plugged devices. That's why when one wants to hotplug
> another bridge,
> it needs his child bus, which the parent is unable to provide (speaking
> about virtual device).
> The suggested workaround is to have vendor-specific capability in Red Hat
> PCI bridges
> that contains number of additional bus to reserve (as well as IO/MEM/PREF
> space limit hints)
> on BIOS PCI init.
> So this capability is intended only for pure QEMU->SeaBIOS usage.
>
> Considering all aforesaid, this series is directly connected with
> QEMU series "Generic PCIE-PCI Bridge".
>
> Although the new PCI capability is supposed to contain various limits
> along with
> bus number to reserve, now only its full layout is proposed. And
> only bus_reserve field is used in QEMU and BIOS. Limits usage
> is still a subject for implementation as now
> the main goal of this series to provide necessary support from the
> firmware side to PCIE-PCI bridge hotplug.
>
> Changes v6->v7:
> 0. Resend - fix a bug with incorrect subordinate bus default value.
> 1. Do not use alignment in case of IO reservation cap usage.
> 2. Log additional buses reservation events.
>
> Changes v5->v6:
> 1. Remove unnecessary indents and line breaks (addresses Marcel's comments)
> 2. Count IO/MEM/PREF region size as a maximum of necessary size and one
> provide in
> RESOURCE_RESERVE capability (addresses Marcel's comment).
> 3. Make the cap debug message more detailed (addresses Marcel's comment).
> 4. Change pref_32 and pref_64 cap fields comment.
>
> Changes v4->v5:
> 1. Rename capability-related #defines
> 2. Move capability IO/MEM/PREF fields values usage to the regions creation
> stage (addresses Marcel's comment)
> 3. The capability layout change: separate pref_mem into pref_mem_32 and
> pref_mem_64 fields (QEMU side has the same changes) (addresses Laszlo's
> comment)
> 4. Extract the capability lookup and check to the separate function
> (addresses Marcel's comment)
> - despite of Marcel's comment do not extract field check for -1
> since it increases code length
>   and doesn't look nice because of different field types
> 5. Fix the capability's comment (addresses Marcel's comment)
> 6. Fix the 3rd patch message
>
> Changes v3->v4:
> 1. Use all QEMU PCI capability fields - addresses Michael's comment
> 2. Changes of the capability layout (QEMU side has the same changes):
> - change reservation fields types: bus_res - uint32_t, others -
> uint64_t
> - interpret -1 value as 'ignore'
>
> Changes v2->v3:
> 1. Merge commit 2 (Red Hat vendor ID) into commit 4 - addresses Marcel's
> comment,
> and add Generic PCIE Root Port device ID - addresses Michael's
> comment.
> 2. Changes of the capability layout  (QEMU side has the same changes):
> - add 'type' field to distinguish multiple
> RedHat-specific capabilities - addresses Michael's comment
> - do not mimiс PCI Config space register layout, but use mutually
> exclusive differently
> sized fields for IO and prefetchable memory limits -
> addresses Laszlo's comment
> - use defines instead of structure and offsetof - addresses
> Michael's comment
> 3. Interpret 'bus_reserve' field as a minimum necessary
>  range to reserve - addresses Gerd's comment
> 4. pci_find_capability moved to pci.c - addresses Kevin's comment
> 5. Move capability layout header to src/fw/dev-pci.h - addresses Kevin's
> comment
> 6. Add the capability documentation - addresses Michael's comment
> 7. Add capability length and bus_reserve field sanity checks - addresses
> Michael's comment
>
> Changes v1->v2:
> 1. New #define for Red Hat vendor added (addresses Konrad's comment).
> 2. Refactored pci_find_capability function (addresses Marcel's comment).
> 3. Capability reworked:
> - data type added;
> - reserve space in a structure for IO, memory and
>   prefetchable memory limits.
>
>
> Aleksandr Bezzubikov (3):
>   pci: refactor pci_find_capapibilty to get bdf as the first argument
> instead of the whole pci_device
>   pci: add QEMU-specific PCI capability structure
>   pci: enable RedHat PCI bridges to reserve additional resources on PCI
> init
>
>  src/fw/dev-pci.h|  53 ++
>  src/fw/pciinit.c| 108
> +---
>  src/hw/pci.c|  25 
>  src/hw/pci.h|   1 +
>  src/hw/pci_ids.h|   3 ++
>  src/hw/pcidevic

Re: [Qemu-devel] [PATCH v7 0/4] Generic PCIE-PCI Bridge

2017-09-05 Thread Aleksandr Bezzubikov
ср, 23 авг. 2017 г. в 5:46, Michael S. Tsirkin <m...@redhat.com>:

> On Tue, Aug 22, 2017 at 02:43:39PM +0300, Marcel Apfelbaum wrote:
> > On 18/08/2017 2:36, Aleksandr Bezzubikov wrote:
> > > This series introduces a new device - Generic PCI Express to PCI
> bridge,
> > > and also makes all necessary changes to enable hotplug of the bridge
> itself
> > > and any device into the bridge.
> > >
> >
> > Hi,
> >
> > Series
> >Tested-by: Marcel Apfelbaum <mar...@redhat.com>
> > (focused on changes from v6)
> >
> >
> > Michael, will Alecsandr need to re-send it after freeze?
>
> re-send or ping pls.


Michael, it seems that freeze is over, so you can pick this patches.


>
> > I am asking because the GSOC project is ending in a week or so.
> >
> >
> > Thanks,
> > Marcel
> >
> > > Changes v6->v7:
> > > Change IO/MEM/PREF reservation properties type to SIZE.
> > >
> > > Changes v5->v6:
> > > 1. Fix indentation in the cap creation function (addresses Marcel's
> comment)
> > > 2. Simplify capability pref_mem_* fields assignment (addresses
> Marcel's comment)
> > > 3. Documentation fixes:
> > > - fix mutually exclusive fields definition (addresses Laszlo's
> comment)
> > > - fix pcie-pci-bridge usage example (addresses Marcel's comment)
> > >
> > > Changes v4->v5:
> > > 1. Change PCIE-PCI Bridge license (addresses Marcel's comment)
> > > 2. The capability layout changes (adress Laszlo' comments):
> > >  - separate pref_mem into pref_mem_32 and pref_mem_64 fields
> (SeaBIOS side has the same changes)
> > >  - accordingly change the Generic Root Port's properties
> > > 3. Do not add the capability to the root port if no valid values are
> provided (adresses Michael's comment)
> > > 4. Rename the capability type to 'RESOURCE_RESERVE' (addresses
> Marcel's comment)
> > > 5. Remove shpc_present check function (addresses Marcel's comment)
> > > 6. Fix the 4th patch message (adresses Michael's comment)
> > > 7. Patch for SHPC enabling in _OSC method has been already merged
> > >
> > > Changes v3->v4:
> > > 1. PCIE-PCI Bridge device: "msi_enable"->"msi", "shpc"->"shpc_bar",
> remove local_err,
> > > make "msi" property OnOffAuto, shpc_present() is still here
> > > to avoid SHPC_VMSTATE refactoring (address Marcel's comments).
> > > 2. Change QEMU PCI capability layout (SeaBIOS side has the same
> changes):
> > >- change reservation fields types: bus_res - uint32_t, others -
> uint64_t
> > >- rename 'non_pref' and 'pref' fields
> > >- interpret -1 value as 'ignore'
> > > 3. Use parent_realize in Generic PCI Express Root Port properly.
> > > 4. Fix documentation: fully replace the DMI-PCI bridge references with
> the new PCIE-PCI bridge,
> > > "PCIE"->"PCI Express", small mistakes and typos - address Laszlo's and
> Marcel's comments.
> > > 5. Rename QEMU PCI cap creation fucntion - addresses Marcel's comment.
> > >
> > > Changes v2->v3:
> > > (0). 'do_not_use' capability field flag is still _not_ in here since
> we haven't come to consesus on it yet.
> > > 1. Merge commits 5 (bus_reserve property creation) and 6 (property
> usage) together - addresses Michael's comment.
> > > 2. Add 'bus_reserve' property and QEMU PCI capability only to Generic
> PCIE Root Port - addresses Michael's and Marcel's comments.
> > > 3. Change 'bus_reserve' property's default value to 0 - addresses
> Michael's comment.
> > > 4. Rename QEMU bridge-specific PCI capability creation function -
> addresses Michael's comment.
> > > 5. Init the whole QEMU PCI capability with zeroes - addresses
> Michael's and Laszlo's comments.
> > > 6. Change QEMU PCI capability layout (SeaBIOS side has the same
> changes)
> > >- add 'type' field to distinguish multiple
> > >  RedHat-specific capabilities - addresses Michael's comment
> > >- do not mimiс PCI Config space register layout, but use mutually
> exclusive differently
> > >  sized fields for IO and prefetchable memory limits - addresses
> Laszlo's comment
> > > 7. Correct error handling in PCIE-PCI bridge realize function.
> > > 8. Replace a '2' constant with PCI_CAP_FLAGS in the capability
> creation function - addresses Michael's comment.
> > > 9. Remove a comment on _OSC which isn't correct anymore - addres

[Qemu-devel] Generic PCIE-PCI Bridge GSoC Project Report

2017-08-22 Thread Aleksandr Bezzubikov
Hi,
I'm a GSoC student and I have completed my project "Generic PCIE-PCI Bridge".
Its aim was to create a new device to replace existing DMI-PCI bridge
as it isn't
cross-platform and doesn't support hotplugging.
By completing this project next goals were achieved:
1. Introduce a brand new pcie-pci-bridge device.
2. Add SHPC support to the Q35 machine in order to enable device
hotplugging into the PCIE-PCI bridge.
3. Fix disabled BUSMASTER bug in Linux kernel.
4. Add QEMU-specific bridge-only PCI capability for additional
resources reservation, such as additional bus number, IO/MEM/PREF
space. The capability usage was implemented in QEMU and SeaBIOS both.
5. Update documentation according to the changes stated above.

All QEMU and SeaBIOS patches have got reviewed-by and tested-by tags.
Linux kernel patches has been accepted for merge in 4.14 version.
Some QEMU (and therefore all SeaBIOS) patches hasn't been merged yet
because of current freeze. But I'm ready to push the patches when it
becomes possible (even though GSoC ends in a week). At the moment in
QEMU only ACPI refactoring and SHPC-enabling patches are merged
upstream.

QEMU series link:
http://lists.gnu.org/archive/html/qemu-devel/2017-08/msg03288.html
SeaBIOS series link:
https://mail.coreboot.org/pipermail/seabios/2017-August/011728.html
Linux patch link: http://www.spinics.net/lists/linux-pci/msg63052.html

QEMU part github: https://github.com/zuban32/qemu/commits/v7?author=zuban32
SeaBIOS part github:
https://github.com/zuban32/seabios/commits/qemu_res_cap?author=zuban32

 --
Aleksandr Bezzubikov



[Qemu-devel] [PATCH v7 3/4] hw/pci: add QEMU-specific PCI capability to the Generic PCI Express Root Port

2017-08-17 Thread Aleksandr Bezzubikov
To enable hotplugging of a newly created pcie-pci-bridge,
we need to tell firmware (e.g. SeaBIOS) to reserve
additional buses or IO/MEM/PREF space for pcie-root-port.
Additional bus reservation allows us to hotplug pcie-pci-bridge into this root 
port.
The number of buses and IO/MEM/PREF space to reserve are provided to the device 
via
a corresponding property, and to the firmware via new PCI capability.
The properties' default values are -1 to keep default behavior unchanged.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 hw/pci-bridge/gen_pcie_root_port.c | 36 
 include/hw/pci/pcie_port.h |  1 +
 2 files changed, 37 insertions(+)

diff --git a/hw/pci-bridge/gen_pcie_root_port.c 
b/hw/pci-bridge/gen_pcie_root_port.c
index cb694d6..ed03ffc 100644
--- a/hw/pci-bridge/gen_pcie_root_port.c
+++ b/hw/pci-bridge/gen_pcie_root_port.c
@@ -16,6 +16,8 @@
 #include "hw/pci/pcie_port.h"
 
 #define TYPE_GEN_PCIE_ROOT_PORT"pcie-root-port"
+#define GEN_PCIE_ROOT_PORT(obj) \
+OBJECT_CHECK(GenPCIERootPort, (obj), TYPE_GEN_PCIE_ROOT_PORT)
 
 #define GEN_PCIE_ROOT_PORT_AER_OFFSET   0x100
 #define GEN_PCIE_ROOT_PORT_MSIX_NR_VECTOR   1
@@ -26,6 +28,13 @@ typedef struct GenPCIERootPort {
 /*< public >*/
 
 bool migrate_msix;
+
+/* additional resources to reserve on firmware init */
+uint32_t bus_reserve;
+uint64_t io_reserve;
+uint64_t mem_reserve;
+uint64_t pref32_reserve;
+uint64_t pref64_reserve;
 } GenPCIERootPort;
 
 static uint8_t gen_rp_aer_vector(const PCIDevice *d)
@@ -60,6 +69,24 @@ static bool gen_rp_test_migrate_msix(void *opaque, int 
version_id)
 return rp->migrate_msix;
 }
 
+static void gen_rp_realize(DeviceState *dev, Error **errp)
+{
+PCIDevice *d = PCI_DEVICE(dev);
+GenPCIERootPort *grp = GEN_PCIE_ROOT_PORT(d);
+PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(d);
+
+rpc->parent_realize(dev, errp);
+
+int rc = pci_bridge_qemu_reserve_cap_init(d, 0, grp->bus_reserve,
+grp->io_reserve, grp->mem_reserve, grp->pref32_reserve,
+grp->pref64_reserve, errp);
+
+if (rc < 0) {
+rpc->parent_class.exit(d);
+return;
+}
+}
+
 static const VMStateDescription vmstate_rp_dev = {
 .name = "pcie-root-port",
 .version_id = 1,
@@ -78,6 +105,11 @@ static const VMStateDescription vmstate_rp_dev = {
 
 static Property gen_rp_props[] = {
 DEFINE_PROP_BOOL("x-migrate-msix", GenPCIERootPort, migrate_msix, true),
+DEFINE_PROP_UINT32("bus-reserve", GenPCIERootPort, bus_reserve, -1),
+DEFINE_PROP_SIZE("io-reserve", GenPCIERootPort, io_reserve, -1),
+DEFINE_PROP_SIZE("mem-reserve", GenPCIERootPort, mem_reserve, -1),
+DEFINE_PROP_SIZE("pref32-reserve", GenPCIERootPort, pref32_reserve, -1),
+DEFINE_PROP_SIZE("pref64-reserve", GenPCIERootPort, pref64_reserve, -1),
 DEFINE_PROP_END_OF_LIST()
 };
 
@@ -92,6 +124,10 @@ static void gen_rp_dev_class_init(ObjectClass *klass, void 
*data)
 dc->desc = "PCI Express Root Port";
 dc->vmsd = _rp_dev;
 dc->props = gen_rp_props;
+
+rpc->parent_realize = dc->realize;
+dc->realize = gen_rp_realize;
+
 rpc->aer_vector = gen_rp_aer_vector;
 rpc->interrupts_init = gen_rp_interrupts_init;
 rpc->interrupts_uninit = gen_rp_interrupts_uninit;
diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
index 1333266..0736014 100644
--- a/include/hw/pci/pcie_port.h
+++ b/include/hw/pci/pcie_port.h
@@ -65,6 +65,7 @@ void pcie_chassis_del_slot(PCIESlot *s);
 
 typedef struct PCIERootPortClass {
 PCIDeviceClass parent_class;
+DeviceRealize parent_realize;
 
 uint8_t (*aer_vector)(const PCIDevice *dev);
 int (*interrupts_init)(PCIDevice *dev, Error **errp);
-- 
2.7.4




[Qemu-devel] [PATCH v7 4/4] docs: update documentation considering PCIE-PCI bridge

2017-08-17 Thread Aleksandr Bezzubikov
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Laszlo Ersek <ler...@redhat.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 docs/pcie.txt|  49 ++--
 docs/pcie_pci_bridge.txt | 114 +++
 2 files changed, 140 insertions(+), 23 deletions(-)
 create mode 100644 docs/pcie_pci_bridge.txt

diff --git a/docs/pcie.txt b/docs/pcie.txt
index 5bada24..76b85ec 100644
--- a/docs/pcie.txt
+++ b/docs/pcie.txt
@@ -46,7 +46,7 @@ Place only the following kinds of devices directly on the 
Root Complex:
 (2) PCI Express Root Ports (ioh3420), for starting exclusively PCI Express
 hierarchies.
 
-(3) DMI-PCI Bridges (i82801b11-bridge), for starting legacy PCI
+(3) PCI Express to PCI Bridge (pcie-pci-bridge), for starting legacy PCI
 hierarchies.
 
 (4) Extra Root Complexes (pxb-pcie), if multiple PCI Express Root Buses
@@ -55,18 +55,18 @@ Place only the following kinds of devices directly on the 
Root Complex:
pcie.0 bus

 |||  |
-   ---   --   --   --
-   | PCI Dev |   | PCIe Root Port |   | DMI-PCI Bridge |   |  pxb-pcie  |
-   ---   --   --   --
+   ---   --   ---   --
+   | PCI Dev |   | PCIe Root Port |   | PCIe-PCI Bridge |   |  pxb-pcie  |
+   ---   --   ---   --
 
 2.1.1 To plug a device into pcie.0 as a Root Complex Integrated Endpoint use:
   -device [,bus=pcie.0]
 2.1.2 To expose a new PCI Express Root Bus use:
   -device pxb-pcie,id=pcie.1,bus_nr=x[,numa_node=y][,addr=z]
-  Only PCI Express Root Ports and DMI-PCI bridges can be connected
-  to the pcie.1 bus:
+  PCI Express Root Ports and PCI Express to PCI bridges can be
+  connected to the pcie.1 bus:
   -device 
ioh3420,id=root_port1[,bus=pcie.1][,chassis=x][,slot=y][,addr=z]
 \
-  -device i82801b11-bridge,id=dmi_pci_bridge1,bus=pcie.1
+  -device pcie-pci-bridge,id=pcie_pci_bridge1,bus=pcie.1
 
 
 2.2 PCI Express only hierarchy
@@ -130,24 +130,24 @@ Notes:
 Legacy PCI devices can be plugged into pcie.0 as Integrated Endpoints,
 but, as mentioned in section 5, doing so means the legacy PCI
 device in question will be incapable of hot-unplugging.
-Besides that use DMI-PCI Bridges (i82801b11-bridge) in combination
-with PCI-PCI Bridges (pci-bridge) to start PCI hierarchies.
+Besides that use PCI Express to PCI Bridges (pcie-pci-bridge) in
+combination with PCI-PCI Bridges (pci-bridge) to start PCI hierarchies.
 
-Prefer flat hierarchies. For most scenarios a single DMI-PCI Bridge
+Prefer flat hierarchies. For most scenarios a single PCI Express to PCI Bridge
 (having 32 slots) and several PCI-PCI Bridges attached to it
 (each supporting also 32 slots) will support hundreds of legacy devices.
-The recommendation is to populate one PCI-PCI Bridge under the DMI-PCI Bridge
-until is full and then plug a new PCI-PCI Bridge...
+The recommendation is to populate one PCI-PCI Bridge under the
+PCI Express to PCI Bridge until is full and then plug a new PCI-PCI Bridge...
 
pcie.0 bus
--
 ||
-   ---   --
-   | PCI Dev |   | DMI-PCI BRIDGE |
-   ----
+   ---   ---
+   | PCI Dev |   | PCIe-PCI Bridge |
+   ---   ---
||
   ----
-  | PCI-PCI Bridge || PCI-PCI Bridge |   ...
+  | PCI-PCI Bridge || PCI-PCI Bridge |
   ----
  |   |
   --- ---
@@ -157,11 +157,11 @@ until is full and then plug a new PCI-PCI Bridge...
 2.3.1 To plug a PCI device into pcie.0 as an Integrated Endpoint use:
   -device [,bus=pcie.0]
 2.3.2 Plugging a PCI device into a PCI-PCI Bridge:
-  -device i82801b11-bridge,id=dmi_pci_bridge1[,bus=pcie.0] 
   \
-  -device 
pci-bridge,id=pci_bridge1,bus=dmi_pci_bridge1[,chassis_nr=x][,addr=y]   \
+  -device pcie-pci-bridge,id=pcie_pci_bridge1[,bus=pcie.0] \
+  -device 
pci-bridge,id=pci_bridge1,bus=pcie_pci_bridge1[,chassis_nr=x][,addr=y] \
   -device ,bus=pci_bridge1[,addr=x]
   Note that 'addr' cannot be 0 unless shpc=off parameter is passed to
-  the PCI Bridge.
+  the PCI Bridge/PCI Exp

[Qemu-devel] [PATCH v7 2/4] hw/pci: introduce bridge-only vendor-specific capability to provide some hints to firmware

2017-08-17 Thread Aleksandr Bezzubikov
On PCI init PCI bridges may need some extra info about bus number,
IO, memory and prefetchable memory to reserve. QEMU can provide this
with a special vendor-specific PCI capability.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 hw/pci/pci_bridge.c | 46 +
 include/hw/pci/pci_bridge.h | 25 
 2 files changed, 71 insertions(+)

diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 720119b..17feae5 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -408,6 +408,52 @@ void pci_bridge_map_irq(PCIBridge *br, const char* 
bus_name,
 br->bus_name = bus_name;
 }
 
+
+int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
+ uint32_t bus_reserve, uint64_t io_reserve,
+ uint32_t mem_non_pref_reserve,
+ uint32_t mem_pref_32_reserve,
+ uint64_t mem_pref_64_reserve,
+ Error **errp)
+{
+if (mem_pref_32_reserve != (uint32_t)-1 &&
+mem_pref_64_reserve != (uint64_t)-1) {
+error_setg(errp,
+   "PCI resource reserve cap: PREF32 and PREF64 conflict");
+return -EINVAL;
+}
+
+if (bus_reserve == (uint32_t)-1 &&
+io_reserve == (uint64_t)-1 &&
+mem_non_pref_reserve == (uint32_t)-1 &&
+mem_pref_32_reserve == (uint32_t)-1 &&
+mem_pref_64_reserve == (uint64_t)-1) {
+return 0;
+}
+
+size_t cap_len = sizeof(PCIBridgeQemuCap);
+PCIBridgeQemuCap cap = {
+.len = cap_len,
+.type = REDHAT_PCI_CAP_RESOURCE_RESERVE,
+.bus_res = bus_reserve,
+.io = io_reserve,
+.mem = mem_non_pref_reserve,
+.mem_pref_32 = mem_pref_32_reserve,
+.mem_pref_64 = mem_pref_64_reserve
+};
+
+int offset = pci_add_capability(dev, PCI_CAP_ID_VNDR,
+cap_offset, cap_len, errp);
+if (offset < 0) {
+return offset;
+}
+
+memcpy(dev->config + offset + PCI_CAP_FLAGS,
+   (char *) + PCI_CAP_FLAGS,
+   cap_len - PCI_CAP_FLAGS);
+return 0;
+}
+
 static const TypeInfo pci_bridge_type_info = {
 .name = TYPE_PCI_BRIDGE,
 .parent = TYPE_PCI_DEVICE,
diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h
index ff7cbaa..1acadc2 100644
--- a/include/hw/pci/pci_bridge.h
+++ b/include/hw/pci/pci_bridge.h
@@ -67,4 +67,29 @@ void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
 #define  PCI_BRIDGE_CTL_DISCARD_STATUS 0x400   /* Discard timer status */
 #define  PCI_BRIDGE_CTL_DISCARD_SERR   0x800   /* Discard timer SERR# enable */
 
+typedef struct PCIBridgeQemuCap {
+uint8_t id; /* Standard PCI capability header field */
+uint8_t next;   /* Standard PCI capability header field */
+uint8_t len;/* Standard PCI vendor-specific capability header field */
+uint8_t type;   /* Red Hat vendor-specific capability type.
+   Types are defined with REDHAT_PCI_CAP_ prefix */
+
+uint32_t bus_res;   /* Minimum number of buses to reserve */
+uint64_t io;/* IO space to reserve */
+uint32_t mem;   /* Non-prefetchable memory to reserve */
+/* At most one of the following two fields may be set to a value
+ * different from -1 */
+uint32_t mem_pref_32; /* Prefetchable memory to reserve (32-bit MMIO) */
+uint64_t mem_pref_64; /* Prefetchable memory to reserve (64-bit MMIO) */
+} PCIBridgeQemuCap;
+
+#define REDHAT_PCI_CAP_RESOURCE_RESERVE 1
+
+int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
+  uint32_t bus_reserve, uint64_t io_reserve,
+  uint32_t mem_non_pref_reserve,
+  uint32_t mem_pref_32_reserve,
+  uint64_t mem_pref_64_reserve,
+  Error **errp);
+
 #endif /* QEMU_PCI_BRIDGE_H */
-- 
2.7.4




[Qemu-devel] [PATCH v7 0/4] Generic PCIE-PCI Bridge

2017-08-17 Thread Aleksandr Bezzubikov
This series introduces a new device - Generic PCI Express to PCI bridge,
and also makes all necessary changes to enable hotplug of the bridge itself
and any device into the bridge.

Changes v6->v7:
Change IO/MEM/PREF reservation properties type to SIZE.

Changes v5->v6:
1. Fix indentation in the cap creation function (addresses Marcel's comment)
2. Simplify capability pref_mem_* fields assignment (addresses Marcel's comment)
3. Documentation fixes:
- fix mutually exclusive fields definition (addresses Laszlo's comment)
- fix pcie-pci-bridge usage example (addresses Marcel's comment)

Changes v4->v5:
1. Change PCIE-PCI Bridge license (addresses Marcel's comment)
2. The capability layout changes (adress Laszlo' comments): 
- separate pref_mem into pref_mem_32 and pref_mem_64 fields (SeaBIOS side 
has the same changes)
- accordingly change the Generic Root Port's properties
3. Do not add the capability to the root port if no valid values are provided 
(adresses Michael's comment)
4. Rename the capability type to 'RESOURCE_RESERVE' (addresses Marcel's comment)
5. Remove shpc_present check function (addresses Marcel's comment)
6. Fix the 4th patch message (adresses Michael's comment)
7. Patch for SHPC enabling in _OSC method has been already merged

Changes v3->v4:
1. PCIE-PCI Bridge device: "msi_enable"->"msi", "shpc"->"shpc_bar", remove 
local_err,
   make "msi" property OnOffAuto, shpc_present() is still here 
   to avoid SHPC_VMSTATE refactoring (address Marcel's comments). 
2. Change QEMU PCI capability layout (SeaBIOS side has the same changes):
  - change reservation fields types: bus_res - uint32_t, others - uint64_t
  - rename 'non_pref' and 'pref' fields
  - interpret -1 value as 'ignore'
3. Use parent_realize in Generic PCI Express Root Port properly.
4. Fix documentation: fully replace the DMI-PCI bridge references with the new 
PCIE-PCI bridge,
"PCIE"->"PCI Express", small mistakes and typos - address Laszlo's and Marcel's 
comments.
5. Rename QEMU PCI cap creation fucntion - addresses Marcel's comment.

Changes v2->v3:
(0). 'do_not_use' capability field flag is still _not_ in here since we haven't 
come to consesus on it yet.
1. Merge commits 5 (bus_reserve property creation) and 6 (property usage) 
together - addresses Michael's comment.
2. Add 'bus_reserve' property and QEMU PCI capability only to Generic PCIE Root 
Port - addresses Michael's and Marcel's comments.
3. Change 'bus_reserve' property's default value to 0 - addresses Michael's 
comment.
4. Rename QEMU bridge-specific PCI capability creation function - addresses 
Michael's comment.
5. Init the whole QEMU PCI capability with zeroes - addresses Michael's and 
Laszlo's comments.
6. Change QEMU PCI capability layout (SeaBIOS side has the same changes)
  - add 'type' field to distinguish multiple 
RedHat-specific capabilities - addresses Michael's comment
  - do not mimiс PCI Config space register layout, but use mutually exclusive 
differently
sized fields for IO and prefetchable memory limits - addresses Laszlo's 
comment
7. Correct error handling in PCIE-PCI bridge realize function.
8. Replace a '2' constant with PCI_CAP_FLAGS in the capability creation 
function - addresses Michael's comment.
9. Remove a comment on _OSC which isn't correct anymore - address Marcel's 
comment.
10. Add documentation for the Generic PCIE-PCI Bridge and QEMU PCI capability - 
addresses Michael's comment.

Changes v1->v2:
1. Enable SHPC for the bridge.
2. Enable SHPC support for the Q35 machine (ACPI stuff).
3. Introduce PCI capability to help firmware on the system init.
   This allows the bridge to be hotpluggable. Now it's supported 
   only for pcie-root-port. Now it's supposed to used with 
   SeaBIOS only, look at the SeaBIOS corresponding series
   "Allow RedHat PCI bridges reserve more buses than necessary during init".

Aleksandr Bezzubikov (4):
  hw/pci: introduce pcie-pci-bridge device
  hw/pci: introduce bridge-only vendor-specific capability to provide
some hints to firmware
  hw/pci: add QEMU-specific PCI capability to the Generic PCI Express
Root Port
  docs: update documentation considering PCIE-PCI bridge

 docs/pcie.txt  |  49 +-
 docs/pcie_pci_bridge.txt   | 114 ++
 hw/pci-bridge/Makefile.objs|   2 +-
 hw/pci-bridge/gen_pcie_root_port.c |  36 +++
 hw/pci-bridge/pcie_pci_bridge.c| 192 +
 hw/pci/pci_bridge.c|  46 +
 include/hw/pci/pci.h   |   1 +
 include/hw/pci/pci_bridge.h|  25 +
 include/hw/pci/pcie_port.h |   1 +
 9 files changed, 442 insertions(+), 24 deletions(-)
 create mode 100644 docs/pcie_pci_bridge.txt
 create mode 100644 hw/pci-bridge/pcie_pci_bridge.c

-- 
2.7.4




[Qemu-devel] [PATCH v7 1/4] hw/pci: introduce pcie-pci-bridge device

2017-08-17 Thread Aleksandr Bezzubikov
Introduce a new PCIExpress-to-PCI Bridge device,
which is a hot-pluggable PCI Express device and
supports devices hot-plug with SHPC.

This device is intended to replace the DMI-to-PCI Bridge.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 hw/pci-bridge/Makefile.objs |   2 +-
 hw/pci-bridge/pcie_pci_bridge.c | 192 
 include/hw/pci/pci.h|   1 +
 3 files changed, 194 insertions(+), 1 deletion(-)
 create mode 100644 hw/pci-bridge/pcie_pci_bridge.c

diff --git a/hw/pci-bridge/Makefile.objs b/hw/pci-bridge/Makefile.objs
index c4683cf..666db37 100644
--- a/hw/pci-bridge/Makefile.objs
+++ b/hw/pci-bridge/Makefile.objs
@@ -1,4 +1,4 @@
-common-obj-y += pci_bridge_dev.o
+common-obj-y += pci_bridge_dev.o pcie_pci_bridge.o
 common-obj-$(CONFIG_PCIE_PORT) += pcie_root_port.o gen_pcie_root_port.o
 common-obj-$(CONFIG_PXB) += pci_expander_bridge.o
 common-obj-$(CONFIG_XIO3130) += xio3130_upstream.o xio3130_downstream.o
diff --git a/hw/pci-bridge/pcie_pci_bridge.c b/hw/pci-bridge/pcie_pci_bridge.c
new file mode 100644
index 000..9aa5cc3
--- /dev/null
+++ b/hw/pci-bridge/pcie_pci_bridge.c
@@ -0,0 +1,192 @@
+/*
+ * QEMU Generic PCIE-PCI Bridge
+ *
+ * Copyright (c) 2017 Aleksandr Bezzubikov
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/shpc.h"
+#include "hw/pci/slotid_cap.h"
+
+typedef struct PCIEPCIBridge {
+/*< private >*/
+PCIBridge parent_obj;
+
+OnOffAuto msi;
+MemoryRegion shpc_bar;
+/*< public >*/
+} PCIEPCIBridge;
+
+#define TYPE_PCIE_PCI_BRIDGE_DEV "pcie-pci-bridge"
+#define PCIE_PCI_BRIDGE_DEV(obj) \
+OBJECT_CHECK(PCIEPCIBridge, (obj), TYPE_PCIE_PCI_BRIDGE_DEV)
+
+static void pcie_pci_bridge_realize(PCIDevice *d, Error **errp)
+{
+PCIBridge *br = PCI_BRIDGE(d);
+PCIEPCIBridge *pcie_br = PCIE_PCI_BRIDGE_DEV(d);
+int rc, pos;
+
+pci_bridge_initfn(d, TYPE_PCI_BUS);
+
+d->config[PCI_INTERRUPT_PIN] = 0x1;
+memory_region_init(_br->shpc_bar, OBJECT(d), "shpc-bar",
+   shpc_bar_size(d));
+rc = shpc_init(d, >sec_bus, _br->shpc_bar, 0, errp);
+if (rc) {
+goto error;
+}
+
+rc = pcie_cap_init(d, 0, PCI_EXP_TYPE_PCI_BRIDGE, 0, errp);
+if (rc < 0) {
+goto cap_error;
+}
+
+pos = pci_add_capability(d, PCI_CAP_ID_PM, 0, PCI_PM_SIZEOF, errp);
+if (pos < 0) {
+goto pm_error;
+}
+d->exp.pm_cap = pos;
+pci_set_word(d->config + pos + PCI_PM_PMC, 0x3);
+
+pcie_cap_arifwd_init(d);
+pcie_cap_deverr_init(d);
+
+rc = pcie_aer_init(d, PCI_ERR_VER, 0x100, PCI_ERR_SIZEOF, errp);
+if (rc < 0) {
+goto aer_error;
+}
+
+if (pcie_br->msi != ON_OFF_AUTO_OFF) {
+rc = msi_init(d, 0, 1, true, true, errp);
+if (rc < 0) {
+goto msi_error;
+}
+}
+pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
+ PCI_BASE_ADDRESS_MEM_TYPE_64, _br->shpc_bar);
+return;
+
+msi_error:
+pcie_aer_exit(d);
+aer_error:
+pm_error:
+pcie_cap_exit(d);
+cap_error:
+shpc_free(d);
+error:
+pci_bridge_exitfn(d);
+}
+
+static void pcie_pci_bridge_exit(PCIDevice *d)
+{
+PCIEPCIBridge *bridge_dev = PCIE_PCI_BRIDGE_DEV(d);
+pcie_cap_exit(d);
+shpc_cleanup(d, _dev->shpc_bar);
+pci_bridge_exitfn(d);
+}
+
+static void pcie_pci_bridge_reset(DeviceState *qdev)
+{
+PCIDevice *d = PCI_DEVICE(qdev);
+pci_bridge_reset(qdev);
+msi_reset(d);
+shpc_reset(d);
+}
+
+static void pcie_pci_bridge_write_config(PCIDevice *d,
+uint32_t address, uint32_t val, int len)
+{
+pci_bridge_write_config(d, address, val, len);
+msi_write_config(d, address, val, len);
+shpc_cap_write_config(d, address, val, len);
+}
+
+static Property pcie_pci_bridge_dev_properties[] = {
+DEFINE_PROP_ON_OFF_AUTO("msi", PCIEPCIBridge, msi, ON_OFF_AUTO_ON),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static const VMStateDescription pcie_pci_bridge_dev_vmstate = {
+.name = TYPE_PCIE_PCI_BRIDGE_DEV,
+.fields = (VMStateField[]) {
+VMSTATE_PCI_DEVICE(parent_obj, PCIBridge),
+SHPC_VMSTATE(shpc, PCIDevice, NULL),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void pcie_pci_bridge_hotplug_cb(HotplugHandler *hotplug_dev,
+  DeviceState *dev, Error **errp)
+{
+PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);
+
+if (!shpc_present(pci_hotplug_dev)) {
+error_

[Qemu-devel] [PATCH RESEND v7 2/3] pci: add QEMU-specific PCI capability structure

2017-08-17 Thread Aleksandr Bezzubikov
On PCI init PCI bridge devices may need some
extra info about bus number to reserve, IO, memory and
prefetchable memory limits. QEMU can provide this
with special vendor-specific PCI capability.

This capability is intended to be used only
for Red Hat PCI bridges, i.e. QEMU cooperation.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 src/fw/dev-pci.h | 53 +
 1 file changed, 53 insertions(+)
 create mode 100644 src/fw/dev-pci.h

diff --git a/src/fw/dev-pci.h b/src/fw/dev-pci.h
new file mode 100644
index 000..0dc5556
--- /dev/null
+++ b/src/fw/dev-pci.h
@@ -0,0 +1,53 @@
+#ifndef _PCI_CAP_H
+#define _PCI_CAP_H
+
+#include "types.h"
+
+/*
+ *
+ * QEMU-specific vendor(Red Hat)-specific capability.
+ * It's intended to provide some hints for firmware to init PCI devices.
+ *
+ * Its structure is shown below:
+ *
+ * Header:
+ *
+ * u8 id;   Standard PCI Capability Header field
+ * u8 next; Standard PCI Capability Header field
+ * u8 len;  Standard PCI Capability Header field
+ * u8 type; Red Hat vendor-specific capability type
+ * Data:
+ *
+ * u32 bus_res; minimum bus number to reserve;
+ *  this is necessary for PCI Express Root Ports
+ *  to support PCI bridges hotplug
+ * u64 io;  IO space to reserve
+ * u32 mem; non-prefetchable memory to reserve
+ *
+ * At most of the following two fields may be set to a value
+ * different from 0xFF...F:
+ * u32 prefetchable_mem_32; prefetchable memory to reserve (32-bit MMIO)
+ * u64 prefetchable_mem_64; prefetchable memory to reserve (64-bit MMIO)
+ *
+ * If any field value in Data section is 0xFF...F,
+ * it means that such kind of reservation is not needed and must be ignored.
+ *
+*/
+
+/* Offset of vendor-specific capability type field */
+#define PCI_CAP_REDHAT_TYPE_OFFSET  3
+
+/* List of valid Red Hat vendor-specific capability types */
+#define REDHAT_CAP_RESOURCE_RESERVE 1
+
+
+/* Offsets of RESOURCE_RESERVE capability fields */
+#define RES_RESERVE_BUS_RES4
+#define RES_RESERVE_IO 8
+#define RES_RESERVE_MEM16
+#define RES_RESERVE_PREF_MEM_3220
+#define RES_RESERVE_PREF_MEM_6424
+#define RES_RESERVE_CAP_SIZE   32
+
+#endif /* _PCI_CAP_H */
+
-- 
2.7.4




[Qemu-devel] [PATCH RESEND v7 1/3] pci: refactor pci_find_capapibilty to get bdf as the first argument instead of the whole pci_device

2017-08-17 Thread Aleksandr Bezzubikov
Refactor pci_find_capability function to get bdf instead of
a whole pci_device* as the only necessary field for this function
is still bdf.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 src/fw/pciinit.c|  4 ++--
 src/hw/pci.c| 25 +
 src/hw/pci.h|  1 +
 src/hw/pcidevice.c  | 24 
 src/hw/pcidevice.h  |  1 -
 src/hw/virtio-pci.c |  6 +++---
 6 files changed, 31 insertions(+), 30 deletions(-)

diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 08221e6..864954f 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -762,7 +762,7 @@ static int pci_bus_hotplug_support(struct pci_bus *bus, u8 
pcie_cap)
 return downstream_port && slot_implemented;
 }
 
-shpc_cap = pci_find_capability(bus->bus_dev, PCI_CAP_ID_SHPC, 0);
+shpc_cap = pci_find_capability(bus->bus_dev->bdf, PCI_CAP_ID_SHPC, 0);
 return !!shpc_cap;
 }
 
@@ -844,7 +844,7 @@ static int pci_bios_check_devices(struct pci_bus *busses)
  */
 parent = [0];
 int type;
-u8 pcie_cap = pci_find_capability(s->bus_dev, PCI_CAP_ID_EXP, 0);
+u8 pcie_cap = pci_find_capability(s->bus_dev->bdf, PCI_CAP_ID_EXP, 0);
 int hotplug_support = pci_bus_hotplug_support(s, pcie_cap);
 for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
 u64 align = (type == PCI_REGION_TYPE_IO) ?
diff --git a/src/hw/pci.c b/src/hw/pci.c
index 8e3d617..50d9d2d 100644
--- a/src/hw/pci.c
+++ b/src/hw/pci.c
@@ -58,6 +58,30 @@ pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on)
 pci_config_writew(bdf, addr, val);
 }
 
+u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap)
+{
+int i;
+u16 status = pci_config_readw(bdf, PCI_STATUS);
+
+if (!(status & PCI_STATUS_CAP_LIST))
+return 0;
+
+if (cap == 0) {
+/* find first */
+cap = pci_config_readb(bdf, PCI_CAPABILITY_LIST);
+} else {
+/* find next */
+cap = pci_config_readb(bdf, cap + PCI_CAP_LIST_NEXT);
+}
+for (i = 0; cap && i <= 0xff; i++) {
+if (pci_config_readb(bdf, cap + PCI_CAP_LIST_ID) == cap_id)
+return cap;
+cap = pci_config_readb(bdf, cap + PCI_CAP_LIST_NEXT);
+}
+
+return 0;
+}
+
 // Helper function for foreachbdf() macro - return next device
 int
 pci_next(int bdf, int bus)
@@ -107,3 +131,4 @@ pci_reboot(void)
 outb(v|6, PORT_PCI_REBOOT); /* Actually do the reset */
 udelay(50);
 }
+
diff --git a/src/hw/pci.h b/src/hw/pci.h
index ee6e196..2e30e28 100644
--- a/src/hw/pci.h
+++ b/src/hw/pci.h
@@ -39,6 +39,7 @@ u32 pci_config_readl(u16 bdf, u32 addr);
 u16 pci_config_readw(u16 bdf, u32 addr);
 u8 pci_config_readb(u16 bdf, u32 addr);
 void pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on);
+u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap);
 int pci_next(int bdf, int bus);
 int pci_probe_host(void);
 void pci_reboot(void);
diff --git a/src/hw/pcidevice.c b/src/hw/pcidevice.c
index cfebf66..8853cf7 100644
--- a/src/hw/pcidevice.c
+++ b/src/hw/pcidevice.c
@@ -134,30 +134,6 @@ pci_find_init_device(const struct pci_device_id *ids, void 
*arg)
 return NULL;
 }
 
-u8 pci_find_capability(struct pci_device *pci, u8 cap_id, u8 cap)
-{
-int i;
-u16 status = pci_config_readw(pci->bdf, PCI_STATUS);
-
-if (!(status & PCI_STATUS_CAP_LIST))
-return 0;
-
-if (cap == 0) {
-/* find first */
-cap = pci_config_readb(pci->bdf, PCI_CAPABILITY_LIST);
-} else {
-/* find next */
-cap = pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_NEXT);
-}
-for (i = 0; cap && i <= 0xff; i++) {
-if (pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_ID) == cap_id)
-return cap;
-cap = pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_NEXT);
-}
-
-return 0;
-}
-
 // Enable PCI bus-mastering (ie, DMA) support on a pci device
 void
 pci_enable_busmaster(struct pci_device *pci)
diff --git a/src/hw/pcidevice.h b/src/hw/pcidevice.h
index 354b549..225d545 100644
--- a/src/hw/pcidevice.h
+++ b/src/hw/pcidevice.h
@@ -69,7 +69,6 @@ int pci_init_device(const struct pci_device_id *ids
 , struct pci_device *pci, void *arg);
 struct pci_device *pci_find_init_device(const struct pci_device_id *ids
 , void *arg);
-u8 pci_find_capability(struct pci_device *pci, u8 cap_id, u8 cap);
 void pci_enable_busmaster(struct pci_device *pci);
 u16 pci_enable_iobar(struct pci_device *pci, u32 addr);
 void *pci_enable_membar(struct pci_device *pci, u32 addr);
diff --git a/src/hw/virtio-pci.c b/src/hw/virtio-pci.c
index e5c2c33..96f9c6b 100644
--- a/src/hw/virtio-pci.c
+++ b/src/hw/virtio-pci.c
@@ -19,7 +19,7 @@
 #include "malloc.h" // free
 #include "output.h" // dprintf
 #include "pci.h" // pc

[Qemu-devel] [PATCH RESEND v7 0/3] Red Hat PCI bridge resource reserve capability

2017-08-17 Thread Aleksandr Bezzubikov
Now PCI bridges get a bus range number on a system init,
basing on currently plugged devices. That's why when one wants to hotplug 
another bridge,
it needs his child bus, which the parent is unable to provide (speaking about 
virtual device).
The suggested workaround is to have vendor-specific capability in Red Hat PCI 
bridges
that contains number of additional bus to reserve (as well as IO/MEM/PREF space 
limit hints) 
on BIOS PCI init.
So this capability is intended only for pure QEMU->SeaBIOS usage.

Considering all aforesaid, this series is directly connected with
QEMU series "Generic PCIE-PCI Bridge".

Although the new PCI capability is supposed to contain various limits along with
bus number to reserve, now only its full layout is proposed. And
only bus_reserve field is used in QEMU and BIOS. Limits usage
is still a subject for implementation as now
the main goal of this series to provide necessary support from the 
firmware side to PCIE-PCI bridge hotplug. 

Changes v6->v7:
0. Resend - fix a bug with incorrect subordinate bus default value.
1. Do not use alignment in case of IO reservation cap usage.
2. Log additional buses reservation events.

Changes v5->v6:
1. Remove unnecessary indents and line breaks (addresses Marcel's comments)
2. Count IO/MEM/PREF region size as a maximum of necessary size and one provide 
in
RESOURCE_RESERVE capability (addresses Marcel's comment).
3. Make the cap debug message more detailed (addresses Marcel's comment).
4. Change pref_32 and pref_64 cap fields comment.

Changes v4->v5:
1. Rename capability-related #defines
2. Move capability IO/MEM/PREF fields values usage to the regions creation 
stage (addresses Marcel's comment)
3. The capability layout change: separate pref_mem into pref_mem_32 and 
pref_mem_64 fields (QEMU side has the same changes) (addresses Laszlo's comment)
4. Extract the capability lookup and check to the separate function (addresses 
Marcel's comment)
- despite of Marcel's comment do not extract field check for -1 since 
it increases code length
  and doesn't look nice because of different field types 
5. Fix the capability's comment (addresses Marcel's comment)
6. Fix the 3rd patch message

Changes v3->v4:
1. Use all QEMU PCI capability fields - addresses Michael's comment
2. Changes of the capability layout (QEMU side has the same changes):
- change reservation fields types: bus_res - uint32_t, others - uint64_t
- interpret -1 value as 'ignore'

Changes v2->v3:
1. Merge commit 2 (Red Hat vendor ID) into commit 4 - addresses Marcel's 
comment,
and add Generic PCIE Root Port device ID - addresses Michael's comment.
2. Changes of the capability layout  (QEMU side has the same changes):
- add 'type' field to distinguish multiple 
RedHat-specific capabilities - addresses Michael's comment
- do not mimiс PCI Config space register layout, but use mutually 
exclusive differently
sized fields for IO and prefetchable memory limits - addresses 
Laszlo's comment
- use defines instead of structure and offsetof - addresses Michael's 
comment
3. Interpret 'bus_reserve' field as a minimum necessary
 range to reserve - addresses Gerd's comment
4. pci_find_capability moved to pci.c - addresses Kevin's comment
5. Move capability layout header to src/fw/dev-pci.h - addresses Kevin's comment
6. Add the capability documentation - addresses Michael's comment
7. Add capability length and bus_reserve field sanity checks - addresses 
Michael's comment

Changes v1->v2:
1. New #define for Red Hat vendor added (addresses Konrad's comment).
2. Refactored pci_find_capability function (addresses Marcel's comment).
3. Capability reworked:
- data type added;
- reserve space in a structure for IO, memory and 
  prefetchable memory limits.


Aleksandr Bezzubikov (3):
  pci: refactor pci_find_capapibilty to get bdf as the first argument
instead of the whole pci_device
  pci: add QEMU-specific PCI capability structure
  pci: enable RedHat PCI bridges to reserve additional resources on PCI
init

 src/fw/dev-pci.h|  53 ++
 src/fw/pciinit.c| 108 +---
 src/hw/pci.c|  25 
 src/hw/pci.h|   1 +
 src/hw/pci_ids.h|   3 ++
 src/hw/pcidevice.c  |  24 
 src/hw/pcidevice.h  |   1 -
 src/hw/virtio-pci.c |   6 +--
 8 files changed, 188 insertions(+), 33 deletions(-)
 create mode 100644 src/fw/dev-pci.h

-- 
2.7.4




[Qemu-devel] [PATCH RESEND v7 3/3] pci: enable RedHat PCI bridges to reserve additional resources on PCI init

2017-08-17 Thread Aleksandr Bezzubikov
In case of Red Hat Generic PCIE Root Port reserve additional buses
and/or IO/MEM/PREF space, which values are provided in a vendor-specific 
capability.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 src/fw/pciinit.c | 106 ---
 src/hw/pci_ids.h |   3 ++
 2 files changed, 105 insertions(+), 4 deletions(-)

diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 864954f..7f0e439 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -15,6 +15,7 @@
 #include "hw/pcidevice.h" // pci_probe_devices
 #include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
 #include "hw/pci_regs.h" // PCI_COMMAND
+#include "fw/dev-pci.h" // REDHAT_CAP_RESOURCE_RESERVE
 #include "list.h" // struct hlist_node
 #include "malloc.h" // free
 #include "output.h" // dprintf
@@ -522,6 +523,32 @@ static void pci_bios_init_platform(void)
 }
 }
 
+static u8 pci_find_resource_reserve_capability(u16 bdf)
+{
+if (pci_config_readw(bdf, PCI_VENDOR_ID) == PCI_VENDOR_ID_REDHAT &&
+pci_config_readw(bdf, PCI_DEVICE_ID) ==
+PCI_DEVICE_ID_REDHAT_ROOT_PORT) {
+u8 cap = 0;
+do {
+cap = pci_find_capability(bdf, PCI_CAP_ID_VNDR, cap);
+} while (cap &&
+ pci_config_readb(bdf, cap + PCI_CAP_REDHAT_TYPE_OFFSET) !=
+REDHAT_CAP_RESOURCE_RESERVE);
+if (cap) {
+u8 cap_len = pci_config_readb(bdf, cap + PCI_CAP_FLAGS);
+if (cap_len < RES_RESERVE_CAP_SIZE) {
+dprintf(1, "PCI: QEMU resource reserve cap length %d is 
invalid\n",
+cap_len);
+}
+} else {
+dprintf(1, "PCI: invalid QEMU resource reserve cap offset\n");
+}
+return cap;
+} else {
+dprintf(1, "PCI: QEMU resource reserve cap not found\n");
+return 0;
+}
+}
 
 /
  * Bus initialization
@@ -578,9 +605,33 @@ pci_bios_init_bus_rec(int bus, u8 *pci_bus)
 pci_bios_init_bus_rec(secbus, pci_bus);
 
 if (subbus != *pci_bus) {
+u8 res_bus = *pci_bus;
+u8 cap = pci_find_resource_reserve_capability(bdf);
+
+if (cap) {
+u32 tmp_res_bus = pci_config_readl(bdf,
+cap + RES_RESERVE_BUS_RES);
+if (tmp_res_bus != (u32)-1) {
+res_bus = tmp_res_bus & 0xFF;
+if ((u8)(res_bus + secbus) < secbus ||
+(u8)(res_bus + secbus) < res_bus) {
+dprintf(1, "PCI: bus_reserve value %d is invalid\n",
+res_bus);
+res_bus = 0;
+}
+}
+if (secbus + res_bus > *pci_bus) {
+dprintf(1, "PCI: QEMU resource reserve cap: bus = %u\n",
+res_bus);
+res_bus = secbus + res_bus;
+} else {
+res_bus = *pci_bus;
+}
+}
 dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n",
-subbus, *pci_bus);
-subbus = *pci_bus;
+subbus, res_bus);
+subbus = res_bus;
+*pci_bus = res_bus;
 } else {
 dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus);
 }
@@ -844,20 +895,67 @@ static int pci_bios_check_devices(struct pci_bus *busses)
  */
 parent = [0];
 int type;
-u8 pcie_cap = pci_find_capability(s->bus_dev->bdf, PCI_CAP_ID_EXP, 0);
+u16 bdf = s->bus_dev->bdf;
+u8 pcie_cap = pci_find_capability(bdf, PCI_CAP_ID_EXP, 0);
+u8 qemu_cap = pci_find_resource_reserve_capability(bdf);
+
 int hotplug_support = pci_bus_hotplug_support(s, pcie_cap);
 for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
 u64 align = (type == PCI_REGION_TYPE_IO) ?
 PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
 if (!pci_bridge_has_region(s->bus_dev, type))
 continue;
+u64 size = 0;
+if (qemu_cap) {
+u32 tmp_size;
+u64 tmp_size_64;
+switch(type) {
+case PCI_REGION_TYPE_IO:
+tmp_size_64 = (pci_config_readl(bdf, qemu_cap + 
RES_RESERVE_IO) |
+(u64)pci_config_readl(bdf, qemu_cap + 
RES_RESERVE_IO + 4) << 32);
+if (tmp_size_64 != (u64)-1) {
+size = tmp_size_64;
+}
+break;
+   

[Qemu-devel] [PATCH v7 0/3] Red Hat PCI bridge resource reserve capability

2017-08-17 Thread Aleksandr Bezzubikov
Now PCI bridges get a bus range number on a system init,
basing on currently plugged devices. That's why when one wants to hotplug 
another bridge,
it needs his child bus, which the parent is unable to provide (speaking about 
virtual device).
The suggested workaround is to have vendor-specific capability in Red Hat PCI 
bridges
that contains number of additional bus to reserve (as well as IO/MEM/PREF space 
limit hints) 
on BIOS PCI init.
So this capability is intended only for pure QEMU->SeaBIOS usage.

Considering all aforesaid, this series is directly connected with
QEMU series "Generic PCIE-PCI Bridge".

Although the new PCI capability is supposed to contain various limits along with
bus number to reserve, now only its full layout is proposed. And
only bus_reserve field is used in QEMU and BIOS. Limits usage
is still a subject for implementation as now
the main goal of this series to provide necessary support from the 
firmware side to PCIE-PCI bridge hotplug. 

Changes v6->v7:
1. Do not use alignment in case of IO reservation cap usage.
2. Log additional buses reservation events.

Changes v5->v6:
1. Remove unnecessary indents and line breaks (addresses Marcel's comments)
2. Count IO/MEM/PREF region size as a maximum of necessary size and one provide 
in
RESOURCE_RESERVE capability (addresses Marcel's comment).
3. Make the cap debug message more detailed (addresses Marcel's comment).
4. Change pref_32 and pref_64 cap fields comment.

Changes v4->v5:
1. Rename capability-related #defines
2. Move capability IO/MEM/PREF fields values usage to the regions creation 
stage (addresses Marcel's comment)
3. The capability layout change: separate pref_mem into pref_mem_32 and 
pref_mem_64 fields (QEMU side has the same changes) (addresses Laszlo's comment)
4. Extract the capability lookup and check to the separate function (addresses 
Marcel's comment)
- despite of Marcel's comment do not extract field check for -1 since 
it increases code length
  and doesn't look nice because of different field types 
5. Fix the capability's comment (addresses Marcel's comment)
6. Fix the 3rd patch message

Changes v3->v4:
1. Use all QEMU PCI capability fields - addresses Michael's comment
2. Changes of the capability layout (QEMU side has the same changes):
- change reservation fields types: bus_res - uint32_t, others - uint64_t
- interpret -1 value as 'ignore'

Changes v2->v3:
1. Merge commit 2 (Red Hat vendor ID) into commit 4 - addresses Marcel's 
comment,
and add Generic PCIE Root Port device ID - addresses Michael's comment.
2. Changes of the capability layout  (QEMU side has the same changes):
- add 'type' field to distinguish multiple 
RedHat-specific capabilities - addresses Michael's comment
- do not mimiс PCI Config space register layout, but use mutually 
exclusive differently
sized fields for IO and prefetchable memory limits - addresses 
Laszlo's comment
- use defines instead of structure and offsetof - addresses Michael's 
comment
3. Interpret 'bus_reserve' field as a minimum necessary
 range to reserve - addresses Gerd's comment
4. pci_find_capability moved to pci.c - addresses Kevin's comment
5. Move capability layout header to src/fw/dev-pci.h - addresses Kevin's comment
6. Add the capability documentation - addresses Michael's comment
7. Add capability length and bus_reserve field sanity checks - addresses 
Michael's comment

Changes v1->v2:
1. New #define for Red Hat vendor added (addresses Konrad's comment).
2. Refactored pci_find_capability function (addresses Marcel's comment).
3. Capability reworked:
- data type added;
- reserve space in a structure for IO, memory and 
  prefetchable memory limits.

Aleksandr Bezzubikov (3):
  pci: refactor pci_find_capapibilty to get bdf as the first argument
instead of the whole pci_device
  pci: add QEMU-specific PCI capability structure
  pci: enable RedHat PCI bridges to reserve additional resources on PCI
init

 src/fw/dev-pci.h|  53 ++
 src/fw/pciinit.c| 108 +---
 src/hw/pci.c|  25 
 src/hw/pci.h|   1 +
 src/hw/pci_ids.h|   3 ++
 src/hw/pcidevice.c  |  24 
 src/hw/pcidevice.h  |   1 -
 src/hw/virtio-pci.c |   6 +--
 8 files changed, 188 insertions(+), 33 deletions(-)
 create mode 100644 src/fw/dev-pci.h

-- 
2.7.4




[Qemu-devel] [PATCH v7 1/3] pci: refactor pci_find_capapibilty to get bdf as the first argument instead of the whole pci_device

2017-08-17 Thread Aleksandr Bezzubikov
Refactor pci_find_capability function to get bdf instead of
a whole pci_device* as the only necessary field for this function
is still bdf.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 src/fw/pciinit.c|  4 ++--
 src/hw/pci.c| 25 +
 src/hw/pci.h|  1 +
 src/hw/pcidevice.c  | 24 
 src/hw/pcidevice.h  |  1 -
 src/hw/virtio-pci.c |  6 +++---
 6 files changed, 31 insertions(+), 30 deletions(-)

diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 08221e6..864954f 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -762,7 +762,7 @@ static int pci_bus_hotplug_support(struct pci_bus *bus, u8 
pcie_cap)
 return downstream_port && slot_implemented;
 }
 
-shpc_cap = pci_find_capability(bus->bus_dev, PCI_CAP_ID_SHPC, 0);
+shpc_cap = pci_find_capability(bus->bus_dev->bdf, PCI_CAP_ID_SHPC, 0);
 return !!shpc_cap;
 }
 
@@ -844,7 +844,7 @@ static int pci_bios_check_devices(struct pci_bus *busses)
  */
 parent = [0];
 int type;
-u8 pcie_cap = pci_find_capability(s->bus_dev, PCI_CAP_ID_EXP, 0);
+u8 pcie_cap = pci_find_capability(s->bus_dev->bdf, PCI_CAP_ID_EXP, 0);
 int hotplug_support = pci_bus_hotplug_support(s, pcie_cap);
 for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
 u64 align = (type == PCI_REGION_TYPE_IO) ?
diff --git a/src/hw/pci.c b/src/hw/pci.c
index 8e3d617..50d9d2d 100644
--- a/src/hw/pci.c
+++ b/src/hw/pci.c
@@ -58,6 +58,30 @@ pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on)
 pci_config_writew(bdf, addr, val);
 }
 
+u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap)
+{
+int i;
+u16 status = pci_config_readw(bdf, PCI_STATUS);
+
+if (!(status & PCI_STATUS_CAP_LIST))
+return 0;
+
+if (cap == 0) {
+/* find first */
+cap = pci_config_readb(bdf, PCI_CAPABILITY_LIST);
+} else {
+/* find next */
+cap = pci_config_readb(bdf, cap + PCI_CAP_LIST_NEXT);
+}
+for (i = 0; cap && i <= 0xff; i++) {
+if (pci_config_readb(bdf, cap + PCI_CAP_LIST_ID) == cap_id)
+return cap;
+cap = pci_config_readb(bdf, cap + PCI_CAP_LIST_NEXT);
+}
+
+return 0;
+}
+
 // Helper function for foreachbdf() macro - return next device
 int
 pci_next(int bdf, int bus)
@@ -107,3 +131,4 @@ pci_reboot(void)
 outb(v|6, PORT_PCI_REBOOT); /* Actually do the reset */
 udelay(50);
 }
+
diff --git a/src/hw/pci.h b/src/hw/pci.h
index ee6e196..2e30e28 100644
--- a/src/hw/pci.h
+++ b/src/hw/pci.h
@@ -39,6 +39,7 @@ u32 pci_config_readl(u16 bdf, u32 addr);
 u16 pci_config_readw(u16 bdf, u32 addr);
 u8 pci_config_readb(u16 bdf, u32 addr);
 void pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on);
+u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap);
 int pci_next(int bdf, int bus);
 int pci_probe_host(void);
 void pci_reboot(void);
diff --git a/src/hw/pcidevice.c b/src/hw/pcidevice.c
index cfebf66..8853cf7 100644
--- a/src/hw/pcidevice.c
+++ b/src/hw/pcidevice.c
@@ -134,30 +134,6 @@ pci_find_init_device(const struct pci_device_id *ids, void 
*arg)
 return NULL;
 }
 
-u8 pci_find_capability(struct pci_device *pci, u8 cap_id, u8 cap)
-{
-int i;
-u16 status = pci_config_readw(pci->bdf, PCI_STATUS);
-
-if (!(status & PCI_STATUS_CAP_LIST))
-return 0;
-
-if (cap == 0) {
-/* find first */
-cap = pci_config_readb(pci->bdf, PCI_CAPABILITY_LIST);
-} else {
-/* find next */
-cap = pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_NEXT);
-}
-for (i = 0; cap && i <= 0xff; i++) {
-if (pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_ID) == cap_id)
-return cap;
-cap = pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_NEXT);
-}
-
-return 0;
-}
-
 // Enable PCI bus-mastering (ie, DMA) support on a pci device
 void
 pci_enable_busmaster(struct pci_device *pci)
diff --git a/src/hw/pcidevice.h b/src/hw/pcidevice.h
index 354b549..225d545 100644
--- a/src/hw/pcidevice.h
+++ b/src/hw/pcidevice.h
@@ -69,7 +69,6 @@ int pci_init_device(const struct pci_device_id *ids
 , struct pci_device *pci, void *arg);
 struct pci_device *pci_find_init_device(const struct pci_device_id *ids
 , void *arg);
-u8 pci_find_capability(struct pci_device *pci, u8 cap_id, u8 cap);
 void pci_enable_busmaster(struct pci_device *pci);
 u16 pci_enable_iobar(struct pci_device *pci, u32 addr);
 void *pci_enable_membar(struct pci_device *pci, u32 addr);
diff --git a/src/hw/virtio-pci.c b/src/hw/virtio-pci.c
index e5c2c33..96f9c6b 100644
--- a/src/hw/virtio-pci.c
+++ b/src/hw/virtio-pci.c
@@ -19,7 +19,7 @@
 #include "malloc.h" // free
 #include "output.h" // dprintf
 #include "pci.h" // pc

[Qemu-devel] [PATCH v7 3/3] pci: enable RedHat PCI bridges to reserve additional resources on PCI init

2017-08-17 Thread Aleksandr Bezzubikov
In case of Red Hat Generic PCIE Root Port reserve additional buses
and/or IO/MEM/PREF space, which values are provided in a vendor-specific 
capability.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 src/fw/pciinit.c | 106 ---
 src/hw/pci_ids.h |   3 ++
 2 files changed, 105 insertions(+), 4 deletions(-)

diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 864954f..22a12f8 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -15,6 +15,7 @@
 #include "hw/pcidevice.h" // pci_probe_devices
 #include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
 #include "hw/pci_regs.h" // PCI_COMMAND
+#include "fw/dev-pci.h" // REDHAT_CAP_RESOURCE_RESERVE
 #include "list.h" // struct hlist_node
 #include "malloc.h" // free
 #include "output.h" // dprintf
@@ -522,6 +523,32 @@ static void pci_bios_init_platform(void)
 }
 }
 
+static u8 pci_find_resource_reserve_capability(u16 bdf)
+{
+if (pci_config_readw(bdf, PCI_VENDOR_ID) == PCI_VENDOR_ID_REDHAT &&
+pci_config_readw(bdf, PCI_DEVICE_ID) ==
+PCI_DEVICE_ID_REDHAT_ROOT_PORT) {
+u8 cap = 0;
+do {
+cap = pci_find_capability(bdf, PCI_CAP_ID_VNDR, cap);
+} while (cap &&
+ pci_config_readb(bdf, cap + PCI_CAP_REDHAT_TYPE_OFFSET) !=
+REDHAT_CAP_RESOURCE_RESERVE);
+if (cap) {
+u8 cap_len = pci_config_readb(bdf, cap + PCI_CAP_FLAGS);
+if (cap_len < RES_RESERVE_CAP_SIZE) {
+dprintf(1, "PCI: QEMU resource reserve cap length %d is 
invalid\n",
+cap_len);
+}
+} else {
+dprintf(1, "PCI: invalid QEMU resource reserve cap offset\n");
+}
+return cap;
+} else {
+dprintf(1, "PCI: QEMU resource reserve cap not found\n");
+return 0;
+}
+}
 
 /
  * Bus initialization
@@ -578,9 +605,33 @@ pci_bios_init_bus_rec(int bus, u8 *pci_bus)
 pci_bios_init_bus_rec(secbus, pci_bus);
 
 if (subbus != *pci_bus) {
+u8 res_bus = 0;
+u8 cap = pci_find_resource_reserve_capability(bdf);
+
+if (cap) {
+u32 tmp_res_bus = pci_config_readl(bdf,
+cap + RES_RESERVE_BUS_RES);
+if (tmp_res_bus != (u32)-1) {
+res_bus = tmp_res_bus & 0xFF;
+if ((u8)(res_bus + secbus) < secbus ||
+(u8)(res_bus + secbus) < res_bus) {
+dprintf(1, "PCI: bus_reserve value %d is invalid\n",
+res_bus);
+res_bus = 0;
+}
+}
+if (secbus + res_bus > *pci_bus) {
+dprintf(1, "PCI: QEMU resource reserve cap: bus = %u\n",
+res_bus);
+res_bus = secbus + res_bus;
+} else {
+res_bus = *pci_bus;
+}
+}
 dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n",
-subbus, *pci_bus);
-subbus = *pci_bus;
+subbus, res_bus);
+subbus = res_bus;
+*pci_bus = res_bus;
 } else {
 dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus);
 }
@@ -844,20 +895,67 @@ static int pci_bios_check_devices(struct pci_bus *busses)
  */
 parent = [0];
 int type;
-u8 pcie_cap = pci_find_capability(s->bus_dev->bdf, PCI_CAP_ID_EXP, 0);
+u16 bdf = s->bus_dev->bdf;
+u8 pcie_cap = pci_find_capability(bdf, PCI_CAP_ID_EXP, 0);
+u8 qemu_cap = pci_find_resource_reserve_capability(bdf);
+
 int hotplug_support = pci_bus_hotplug_support(s, pcie_cap);
 for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
 u64 align = (type == PCI_REGION_TYPE_IO) ?
 PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
 if (!pci_bridge_has_region(s->bus_dev, type))
 continue;
+u64 size = 0;
+if (qemu_cap) {
+u32 tmp_size;
+u64 tmp_size_64;
+switch(type) {
+case PCI_REGION_TYPE_IO:
+tmp_size_64 = (pci_config_readl(bdf, qemu_cap + 
RES_RESERVE_IO) |
+(u64)pci_config_readl(bdf, qemu_cap + 
RES_RESERVE_IO + 4) << 32);
+if (tmp_size_64 != (u64)-1) {
+size = tmp_size_64;
+}
+break;
+   

[Qemu-devel] [PATCH v7 2/3] pci: add QEMU-specific PCI capability structure

2017-08-17 Thread Aleksandr Bezzubikov
On PCI init PCI bridge devices may need some
extra info about bus number to reserve, IO, memory and
prefetchable memory limits. QEMU can provide this
with special vendor-specific PCI capability.

This capability is intended to be used only
for Red Hat PCI bridges, i.e. QEMU cooperation.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 src/fw/dev-pci.h | 53 +
 1 file changed, 53 insertions(+)
 create mode 100644 src/fw/dev-pci.h

diff --git a/src/fw/dev-pci.h b/src/fw/dev-pci.h
new file mode 100644
index 000..0dc5556
--- /dev/null
+++ b/src/fw/dev-pci.h
@@ -0,0 +1,53 @@
+#ifndef _PCI_CAP_H
+#define _PCI_CAP_H
+
+#include "types.h"
+
+/*
+ *
+ * QEMU-specific vendor(Red Hat)-specific capability.
+ * It's intended to provide some hints for firmware to init PCI devices.
+ *
+ * Its structure is shown below:
+ *
+ * Header:
+ *
+ * u8 id;   Standard PCI Capability Header field
+ * u8 next; Standard PCI Capability Header field
+ * u8 len;  Standard PCI Capability Header field
+ * u8 type; Red Hat vendor-specific capability type
+ * Data:
+ *
+ * u32 bus_res; minimum bus number to reserve;
+ *  this is necessary for PCI Express Root Ports
+ *  to support PCI bridges hotplug
+ * u64 io;  IO space to reserve
+ * u32 mem; non-prefetchable memory to reserve
+ *
+ * At most of the following two fields may be set to a value
+ * different from 0xFF...F:
+ * u32 prefetchable_mem_32; prefetchable memory to reserve (32-bit MMIO)
+ * u64 prefetchable_mem_64; prefetchable memory to reserve (64-bit MMIO)
+ *
+ * If any field value in Data section is 0xFF...F,
+ * it means that such kind of reservation is not needed and must be ignored.
+ *
+*/
+
+/* Offset of vendor-specific capability type field */
+#define PCI_CAP_REDHAT_TYPE_OFFSET  3
+
+/* List of valid Red Hat vendor-specific capability types */
+#define REDHAT_CAP_RESOURCE_RESERVE 1
+
+
+/* Offsets of RESOURCE_RESERVE capability fields */
+#define RES_RESERVE_BUS_RES4
+#define RES_RESERVE_IO 8
+#define RES_RESERVE_MEM16
+#define RES_RESERVE_PREF_MEM_3220
+#define RES_RESERVE_PREF_MEM_6424
+#define RES_RESERVE_CAP_SIZE   32
+
+#endif /* _PCI_CAP_H */
+
-- 
2.7.4




[Qemu-devel] [PATCH v6 3/3] pci: enable RedHat PCI bridges to reserve additional resource on PCI init

2017-08-13 Thread Aleksandr Bezzubikov
In case of Red Hat Generic PCIE Root Port reserve additional buses
and/or IO/MEM/PREF space, which values are provided in a vendor-specific 
capability.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 src/fw/pciinit.c | 99 +---
 src/hw/pci_ids.h |  3 ++
 2 files changed, 98 insertions(+), 4 deletions(-)

diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 864954f..620b187 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -15,6 +15,7 @@
 #include "hw/pcidevice.h" // pci_probe_devices
 #include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
 #include "hw/pci_regs.h" // PCI_COMMAND
+#include "fw/dev-pci.h" // REDHAT_CAP_RESOURCE_RESERVE
 #include "list.h" // struct hlist_node
 #include "malloc.h" // free
 #include "output.h" // dprintf
@@ -522,6 +523,32 @@ static void pci_bios_init_platform(void)
 }
 }
 
+static u8 pci_find_resource_reserve_capability(u16 bdf)
+{
+if (pci_config_readw(bdf, PCI_VENDOR_ID) == PCI_VENDOR_ID_REDHAT &&
+pci_config_readw(bdf, PCI_DEVICE_ID) ==
+PCI_DEVICE_ID_REDHAT_ROOT_PORT) {
+u8 cap = 0;
+do {
+cap = pci_find_capability(bdf, PCI_CAP_ID_VNDR, cap);
+} while (cap &&
+ pci_config_readb(bdf, cap + PCI_CAP_REDHAT_TYPE_OFFSET) !=
+REDHAT_CAP_RESOURCE_RESERVE);
+if (cap) {
+u8 cap_len = pci_config_readb(bdf, cap + PCI_CAP_FLAGS);
+if (cap_len < RES_RESERVE_CAP_SIZE) {
+dprintf(1, "PCI: QEMU resource reserve cap length %d is 
invalid\n",
+cap_len);
+}
+} else {
+dprintf(1, "PCI: invalid QEMU resource reserve cap offset\n");
+}
+return cap;
+} else {
+dprintf(1, "PCI: QEMU resource reserve cap not found\n");
+return 0;
+}
+}
 
 /
  * Bus initialization
@@ -578,9 +605,28 @@ pci_bios_init_bus_rec(int bus, u8 *pci_bus)
 pci_bios_init_bus_rec(secbus, pci_bus);
 
 if (subbus != *pci_bus) {
+u8 res_bus = 0;
+u8 cap = pci_find_resource_reserve_capability(bdf);
+
+if (cap) {
+u32 tmp_res_bus = pci_config_readl(bdf,
+cap + RES_RESERVE_BUS_RES);
+if (tmp_res_bus != (u32)-1) {
+res_bus = tmp_res_bus & 0xFF;
+if ((u8)(res_bus + secbus) < secbus ||
+(u8)(res_bus + secbus) < res_bus) {
+dprintf(1, "PCI: bus_reserve value %d is invalid\n",
+res_bus);
+res_bus = 0;
+}
+}
+res_bus = (*pci_bus > secbus + res_bus) ? *pci_bus
+: secbus + res_bus;
+}
 dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n",
-subbus, *pci_bus);
-subbus = *pci_bus;
+subbus, res_bus);
+subbus = res_bus;
+*pci_bus = res_bus;
 } else {
 dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus);
 }
@@ -844,20 +890,65 @@ static int pci_bios_check_devices(struct pci_bus *busses)
  */
 parent = [0];
 int type;
-u8 pcie_cap = pci_find_capability(s->bus_dev->bdf, PCI_CAP_ID_EXP, 0);
+u16 bdf = s->bus_dev->bdf;
+u8 pcie_cap = pci_find_capability(bdf, PCI_CAP_ID_EXP, 0);
+u8 qemu_cap = pci_find_resource_reserve_capability(bdf);
+
 int hotplug_support = pci_bus_hotplug_support(s, pcie_cap);
 for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
 u64 align = (type == PCI_REGION_TYPE_IO) ?
 PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
 if (!pci_bridge_has_region(s->bus_dev, type))
 continue;
+u64 size = 0;
+if (qemu_cap) {
+u32 tmp_size;
+u64 tmp_size_64;
+switch(type) {
+case PCI_REGION_TYPE_IO:
+tmp_size_64 = (pci_config_readl(bdf, qemu_cap + 
RES_RESERVE_IO) |
+(u64)pci_config_readl(bdf, qemu_cap + 
RES_RESERVE_IO + 4) << 32);
+if (tmp_size_64 != (u64)-1) {
+size = tmp_size_64;
+}
+break;
+case PCI_REGION_TYPE_MEM:
+tmp_size = pci_config_readl(bdf, qemu_cap + 
RES_RESERVE_MEM);
+if (tmp_size != (u32)-1) {
+size = tmp_size;
+}
+break;
+ 

[Qemu-devel] [PATCH v6 0/3] Red Hat PCI bridge resource reserve capability

2017-08-13 Thread Aleksandr Bezzubikov
Now PCI bridges get a bus range number on a system init,
basing on currently plugged devices. That's why when one wants to hotplug 
another bridge,
it needs his child bus, which the parent is unable to provide (speaking about 
virtual device).
The suggested workaround is to have vendor-specific capability in Red Hat PCI 
bridges
that contains number of additional bus to reserve (as well as IO/MEM/PREF space 
limit hints) 
on BIOS PCI init.
So this capability is intended only for pure QEMU->SeaBIOS usage.

Considering all aforesaid, this series is directly connected with
QEMU series "Generic PCIE-PCI Bridge".

Although the new PCI capability is supposed to contain various limits along with
bus number to reserve, now only its full layout is proposed. And
only bus_reserve field is used in QEMU and BIOS. Limits usage
is still a subject for implementation as now
the main goal of this series to provide necessary support from the 
firmware side to PCIE-PCI bridge hotplug. 

Changes v5->v6:
1. Remove unnecessary indents and line breaks (addresses Marcel's comments)
2. Count IO/MEM/PREF region size as a maximum of necessary size and one provide 
in
RESOURCE_RESERVE capability (addresses Marcel's comment).
3. Make the cap debug message more detailed (addresses Marcel's comment).
4. Change pref_32 and pref_64 cap fields comment.

Changes v4->v5:
1. Rename capability-related #defines
2. Move capability IO/MEM/PREF fields values usage to the regions creation 
stage (addresses Marcel's comment)
3. The capability layout change: separate pref_mem into pref_mem_32 and 
pref_mem_64 fields (QEMU side has the same changes) (addresses Laszlo's comment)
4. Extract the capability lookup and check to the separate function (addresses 
Marcel's comment)
- despite of Marcel's comment do not extract field check for -1 since 
it increases code length
  and doesn't look nice because of different field types 
5. Fix the capability's comment (addresses Marcel's comment)
6. Fix the 3rd patch message

Changes v3->v4:
1. Use all QEMU PCI capability fields - addresses Michael's comment
2. Changes of the capability layout (QEMU side has the same changes):
- change reservation fields types: bus_res - uint32_t, others - uint64_t
- interpret -1 value as 'ignore'

Changes v2->v3:
1. Merge commit 2 (Red Hat vendor ID) into commit 4 - addresses Marcel's 
comment,
and add Generic PCIE Root Port device ID - addresses Michael's comment.
2. Changes of the capability layout  (QEMU side has the same changes):
- add 'type' field to distinguish multiple 
RedHat-specific capabilities - addresses Michael's comment
- do not mimiс PCI Config space register layout, but use mutually 
exclusive differently
sized fields for IO and prefetchable memory limits - addresses 
Laszlo's comment
- use defines instead of structure and offsetof - addresses Michael's 
comment
3. Interpret 'bus_reserve' field as a minimum necessary
 range to reserve - addresses Gerd's comment
4. pci_find_capability moved to pci.c - addresses Kevin's comment
5. Move capability layout header to src/fw/dev-pci.h - addresses Kevin's comment
6. Add the capability documentation - addresses Michael's comment
7. Add capability length and bus_reserve field sanity checks - addresses 
Michael's comment

Changes v1->v2:
1. New #define for Red Hat vendor added (addresses Konrad's comment).
2. Refactored pci_find_capability function (addresses Marcel's comment).
3. Capability reworked:
- data type added;
- reserve space in a structure for IO, memory and 
  prefetchable memory limits.

Aleksandr Bezzubikov (3):
  pci: refactor pci_find_capapibilty to get bdf as the first argument
instead of the whole pci_device
  pci: add QEMU-specific PCI capability structure
  pci: enable RedHat PCI bridges to reserve additional resource on PCI
init

 src/fw/dev-pci.h|  53 +++
 src/fw/pciinit.c| 101 +---
 src/hw/pci.c|  25 +
 src/hw/pci.h|   1 +
 src/hw/pci_ids.h|   3 ++
 src/hw/pcidevice.c  |  24 -
 src/hw/pcidevice.h  |   1 -
 src/hw/virtio-pci.c |   6 ++--
 8 files changed, 181 insertions(+), 33 deletions(-)
 create mode 100644 src/fw/dev-pci.h

-- 
2.7.4




[Qemu-devel] [PATCH v6 1/3] pci: refactor pci_find_capapibilty to get bdf as the first argument instead of the whole pci_device

2017-08-13 Thread Aleksandr Bezzubikov
Refactor pci_find_capability function to get bdf instead of
a whole pci_device* as the only necessary field for this function
is still bdf.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 src/fw/pciinit.c|  4 ++--
 src/hw/pci.c| 25 +
 src/hw/pci.h|  1 +
 src/hw/pcidevice.c  | 24 
 src/hw/pcidevice.h  |  1 -
 src/hw/virtio-pci.c |  6 +++---
 6 files changed, 31 insertions(+), 30 deletions(-)

diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 08221e6..864954f 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -762,7 +762,7 @@ static int pci_bus_hotplug_support(struct pci_bus *bus, u8 
pcie_cap)
 return downstream_port && slot_implemented;
 }
 
-shpc_cap = pci_find_capability(bus->bus_dev, PCI_CAP_ID_SHPC, 0);
+shpc_cap = pci_find_capability(bus->bus_dev->bdf, PCI_CAP_ID_SHPC, 0);
 return !!shpc_cap;
 }
 
@@ -844,7 +844,7 @@ static int pci_bios_check_devices(struct pci_bus *busses)
  */
 parent = [0];
 int type;
-u8 pcie_cap = pci_find_capability(s->bus_dev, PCI_CAP_ID_EXP, 0);
+u8 pcie_cap = pci_find_capability(s->bus_dev->bdf, PCI_CAP_ID_EXP, 0);
 int hotplug_support = pci_bus_hotplug_support(s, pcie_cap);
 for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
 u64 align = (type == PCI_REGION_TYPE_IO) ?
diff --git a/src/hw/pci.c b/src/hw/pci.c
index 8e3d617..50d9d2d 100644
--- a/src/hw/pci.c
+++ b/src/hw/pci.c
@@ -58,6 +58,30 @@ pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on)
 pci_config_writew(bdf, addr, val);
 }
 
+u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap)
+{
+int i;
+u16 status = pci_config_readw(bdf, PCI_STATUS);
+
+if (!(status & PCI_STATUS_CAP_LIST))
+return 0;
+
+if (cap == 0) {
+/* find first */
+cap = pci_config_readb(bdf, PCI_CAPABILITY_LIST);
+} else {
+/* find next */
+cap = pci_config_readb(bdf, cap + PCI_CAP_LIST_NEXT);
+}
+for (i = 0; cap && i <= 0xff; i++) {
+if (pci_config_readb(bdf, cap + PCI_CAP_LIST_ID) == cap_id)
+return cap;
+cap = pci_config_readb(bdf, cap + PCI_CAP_LIST_NEXT);
+}
+
+return 0;
+}
+
 // Helper function for foreachbdf() macro - return next device
 int
 pci_next(int bdf, int bus)
@@ -107,3 +131,4 @@ pci_reboot(void)
 outb(v|6, PORT_PCI_REBOOT); /* Actually do the reset */
 udelay(50);
 }
+
diff --git a/src/hw/pci.h b/src/hw/pci.h
index ee6e196..2e30e28 100644
--- a/src/hw/pci.h
+++ b/src/hw/pci.h
@@ -39,6 +39,7 @@ u32 pci_config_readl(u16 bdf, u32 addr);
 u16 pci_config_readw(u16 bdf, u32 addr);
 u8 pci_config_readb(u16 bdf, u32 addr);
 void pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on);
+u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap);
 int pci_next(int bdf, int bus);
 int pci_probe_host(void);
 void pci_reboot(void);
diff --git a/src/hw/pcidevice.c b/src/hw/pcidevice.c
index cfebf66..8853cf7 100644
--- a/src/hw/pcidevice.c
+++ b/src/hw/pcidevice.c
@@ -134,30 +134,6 @@ pci_find_init_device(const struct pci_device_id *ids, void 
*arg)
 return NULL;
 }
 
-u8 pci_find_capability(struct pci_device *pci, u8 cap_id, u8 cap)
-{
-int i;
-u16 status = pci_config_readw(pci->bdf, PCI_STATUS);
-
-if (!(status & PCI_STATUS_CAP_LIST))
-return 0;
-
-if (cap == 0) {
-/* find first */
-cap = pci_config_readb(pci->bdf, PCI_CAPABILITY_LIST);
-} else {
-/* find next */
-cap = pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_NEXT);
-}
-for (i = 0; cap && i <= 0xff; i++) {
-if (pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_ID) == cap_id)
-return cap;
-cap = pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_NEXT);
-}
-
-return 0;
-}
-
 // Enable PCI bus-mastering (ie, DMA) support on a pci device
 void
 pci_enable_busmaster(struct pci_device *pci)
diff --git a/src/hw/pcidevice.h b/src/hw/pcidevice.h
index 354b549..225d545 100644
--- a/src/hw/pcidevice.h
+++ b/src/hw/pcidevice.h
@@ -69,7 +69,6 @@ int pci_init_device(const struct pci_device_id *ids
 , struct pci_device *pci, void *arg);
 struct pci_device *pci_find_init_device(const struct pci_device_id *ids
 , void *arg);
-u8 pci_find_capability(struct pci_device *pci, u8 cap_id, u8 cap);
 void pci_enable_busmaster(struct pci_device *pci);
 u16 pci_enable_iobar(struct pci_device *pci, u32 addr);
 void *pci_enable_membar(struct pci_device *pci, u32 addr);
diff --git a/src/hw/virtio-pci.c b/src/hw/virtio-pci.c
index e5c2c33..96f9c6b 100644
--- a/src/hw/virtio-pci.c
+++ b/src/hw/virtio-pci.c
@@ -19,7 +19,7 @@
 #include "malloc.h" // free
 #include "output.h" // dprintf
 #include "pci.h" // pc

[Qemu-devel] [PATCH v6 2/3] pci: add QEMU-specific PCI capability structure

2017-08-13 Thread Aleksandr Bezzubikov
On PCI init PCI bridge devices may need some
extra info about bus number to reserve, IO, memory and
prefetchable memory limits. QEMU can provide this
with special vendor-specific PCI capability.

This capability is intended to be used only
for Red Hat PCI bridges, i.e. QEMU cooperation.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 src/fw/dev-pci.h | 53 +
 1 file changed, 53 insertions(+)
 create mode 100644 src/fw/dev-pci.h

diff --git a/src/fw/dev-pci.h b/src/fw/dev-pci.h
new file mode 100644
index 000..0dc5556
--- /dev/null
+++ b/src/fw/dev-pci.h
@@ -0,0 +1,53 @@
+#ifndef _PCI_CAP_H
+#define _PCI_CAP_H
+
+#include "types.h"
+
+/*
+ *
+ * QEMU-specific vendor(Red Hat)-specific capability.
+ * It's intended to provide some hints for firmware to init PCI devices.
+ *
+ * Its structure is shown below:
+ *
+ * Header:
+ *
+ * u8 id;   Standard PCI Capability Header field
+ * u8 next; Standard PCI Capability Header field
+ * u8 len;  Standard PCI Capability Header field
+ * u8 type; Red Hat vendor-specific capability type
+ * Data:
+ *
+ * u32 bus_res; minimum bus number to reserve;
+ *  this is necessary for PCI Express Root Ports
+ *  to support PCI bridges hotplug
+ * u64 io;  IO space to reserve
+ * u32 mem; non-prefetchable memory to reserve
+ *
+ * At most of the following two fields may be set to a value
+ * different from 0xFF...F:
+ * u32 prefetchable_mem_32; prefetchable memory to reserve (32-bit MMIO)
+ * u64 prefetchable_mem_64; prefetchable memory to reserve (64-bit MMIO)
+ *
+ * If any field value in Data section is 0xFF...F,
+ * it means that such kind of reservation is not needed and must be ignored.
+ *
+*/
+
+/* Offset of vendor-specific capability type field */
+#define PCI_CAP_REDHAT_TYPE_OFFSET  3
+
+/* List of valid Red Hat vendor-specific capability types */
+#define REDHAT_CAP_RESOURCE_RESERVE 1
+
+
+/* Offsets of RESOURCE_RESERVE capability fields */
+#define RES_RESERVE_BUS_RES4
+#define RES_RESERVE_IO 8
+#define RES_RESERVE_MEM16
+#define RES_RESERVE_PREF_MEM_3220
+#define RES_RESERVE_PREF_MEM_6424
+#define RES_RESERVE_CAP_SIZE   32
+
+#endif /* _PCI_CAP_H */
+
-- 
2.7.4




Re: [Qemu-devel] [PATCH v6 0/4] Generic PCIE-PCI Bridge

2017-08-13 Thread Aleksandr Bezzubikov
2017-08-13 18:49 GMT+03:00 Aleksandr Bezzubikov <zuban...@gmail.com>:
> This series introduces a new device - Generic PCI Express to PCI bridge,
> and also makes all necessary changes to enable hotplug of the bridge itself
> and any device into the bridge.
>
> Changes v5->v6:
> 1. Fix indentation in the cap creation function (addresses Marcel's comment)
> 2. Simplify capability pref_mem_* fields assignment (addresses Marcel's 
> comment)
> 3. Documentation fixes:
> - fix mutually exclusive fields definition (addresses Laszlo's 
> comment)
> - fix pcie-pci-bridge usage example (addresses Marcel's comment)
>
> Changes v4->v5:
> 1. Change PCIE-PCI Bridge license (addresses Marcel's comment)
> 2. The capability layout changes (adress Laszlo' comments):
> - separate pref_mem into pref_mem_32 and pref_mem_64 fields (SeaBIOS side 
> has the same changes)
> - accordingly change the Generic Root Port's properties
> 3. Do not add the capability to the root port if no valid values are provided 
> (adresses Michael's comment)
> 4. Rename the capability type to 'RESOURCE_RESERVE' (addresses Marcel's 
> comment)
> 5. Remove shpc_present check function (addresses Marcel's comment)
> 6. Fix the 4th patch message (adresses Michael's comment)
> 7. Patch for SHPC enabling in _OSC method has been already merged
>
> Changes v3->v4:
> 1. PCIE-PCI Bridge device: "msi_enable"->"msi", "shpc"->"shpc_bar", remove 
> local_err,
>make "msi" property OnOffAuto, shpc_present() is still here
>to avoid SHPC_VMSTATE refactoring (address Marcel's comments).
> 2. Change QEMU PCI capability layout (SeaBIOS side has the same changes):
>   - change reservation fields types: bus_res - uint32_t, others - uint64_t
>   - rename 'non_pref' and 'pref' fields
>   - interpret -1 value as 'ignore'
> 3. Use parent_realize in Generic PCI Express Root Port properly.
> 4. Fix documentation: fully replace the DMI-PCI bridge references with the 
> new PCIE-PCI bridge,
> "PCIE"->"PCI Express", small mistakes and typos - address Laszlo's and 
> Marcel's comments.
> 5. Rename QEMU PCI cap creation fucntion - addresses Marcel's comment.
>
> Changes v2->v3:
> (0). 'do_not_use' capability field flag is still _not_ in here since we 
> haven't come to consesus on it yet.
> 1. Merge commits 5 (bus_reserve property creation) and 6 (property usage) 
> together - addresses Michael's comment.
> 2. Add 'bus_reserve' property and QEMU PCI capability only to Generic PCIE 
> Root Port - addresses Michael's and Marcel's comments.
> 3. Change 'bus_reserve' property's default value to 0 - addresses Michael's 
> comment.
> 4. Rename QEMU bridge-specific PCI capability creation function - addresses 
> Michael's comment.
> 5. Init the whole QEMU PCI capability with zeroes - addresses Michael's and 
> Laszlo's comments.
> 6. Change QEMU PCI capability layout (SeaBIOS side has the same changes)
>   - add 'type' field to distinguish multiple
> RedHat-specific capabilities - addresses Michael's comment
>   - do not mimiс PCI Config space register layout, but use mutually exclusive 
> differently
> sized fields for IO and prefetchable memory limits - addresses Laszlo's 
> comment
> 7. Correct error handling in PCIE-PCI bridge realize function.
> 8. Replace a '2' constant with PCI_CAP_FLAGS in the capability creation 
> function - addresses Michael's comment.
> 9. Remove a comment on _OSC which isn't correct anymore - address Marcel's 
> comment.
> 10. Add documentation for the Generic PCIE-PCI Bridge and QEMU PCI capability 
> - addresses Michael's comment.
>
> Changes v1->v2:
> 1. Enable SHPC for the bridge.
> 2. Enable SHPC support for the Q35 machine (ACPI stuff).
> 3. Introduce PCI capability to help firmware on the system init.
>This allows the bridge to be hotpluggable. Now it's supported
>only for pcie-root-port. Now it's supposed to used with
>SeaBIOS only, look at the SeaBIOS corresponding series
>"Allow RedHat PCI bridges reserve more buses than necessary during init".
>
> Aleksandr Bezzubikov (4):
>   hw/pci: introduce pcie-pci-bridge device
>   hw/pci: introduce bridge-only vendor-specific capability to provide
> some hints to firmware
>   hw/pci: add QEMU-specific PCI capability to the Generic PCI Express
> Root Port
>   docs: update documentation considering PCIE-PCI bridge
>
>  docs/pcie.txt  |  49 +-
>  docs/pcie_pci_bridge.txt   | 114 ++
>  hw/pci-bridge/Makefile.objs|   2 +-
>  hw/pci-bridge/gen_pcie_root_port.c |  36 +++
>  hw/pci-bridge/pcie_pci_bri

[Qemu-devel] [PATCH v6 1/4] hw/pci: introduce pcie-pci-bridge device

2017-08-13 Thread Aleksandr Bezzubikov
Introduce a new PCIExpress-to-PCI Bridge device,
which is a hot-pluggable PCI Express device and
supports devices hot-plug with SHPC.

This device is intended to replace the DMI-to-PCI Bridge.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 hw/pci-bridge/Makefile.objs |   2 +-
 hw/pci-bridge/pcie_pci_bridge.c | 192 
 include/hw/pci/pci.h|   1 +
 3 files changed, 194 insertions(+), 1 deletion(-)
 create mode 100644 hw/pci-bridge/pcie_pci_bridge.c

diff --git a/hw/pci-bridge/Makefile.objs b/hw/pci-bridge/Makefile.objs
index c4683cf..666db37 100644
--- a/hw/pci-bridge/Makefile.objs
+++ b/hw/pci-bridge/Makefile.objs
@@ -1,4 +1,4 @@
-common-obj-y += pci_bridge_dev.o
+common-obj-y += pci_bridge_dev.o pcie_pci_bridge.o
 common-obj-$(CONFIG_PCIE_PORT) += pcie_root_port.o gen_pcie_root_port.o
 common-obj-$(CONFIG_PXB) += pci_expander_bridge.o
 common-obj-$(CONFIG_XIO3130) += xio3130_upstream.o xio3130_downstream.o
diff --git a/hw/pci-bridge/pcie_pci_bridge.c b/hw/pci-bridge/pcie_pci_bridge.c
new file mode 100644
index 000..9aa5cc3
--- /dev/null
+++ b/hw/pci-bridge/pcie_pci_bridge.c
@@ -0,0 +1,192 @@
+/*
+ * QEMU Generic PCIE-PCI Bridge
+ *
+ * Copyright (c) 2017 Aleksandr Bezzubikov
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/shpc.h"
+#include "hw/pci/slotid_cap.h"
+
+typedef struct PCIEPCIBridge {
+/*< private >*/
+PCIBridge parent_obj;
+
+OnOffAuto msi;
+MemoryRegion shpc_bar;
+/*< public >*/
+} PCIEPCIBridge;
+
+#define TYPE_PCIE_PCI_BRIDGE_DEV "pcie-pci-bridge"
+#define PCIE_PCI_BRIDGE_DEV(obj) \
+OBJECT_CHECK(PCIEPCIBridge, (obj), TYPE_PCIE_PCI_BRIDGE_DEV)
+
+static void pcie_pci_bridge_realize(PCIDevice *d, Error **errp)
+{
+PCIBridge *br = PCI_BRIDGE(d);
+PCIEPCIBridge *pcie_br = PCIE_PCI_BRIDGE_DEV(d);
+int rc, pos;
+
+pci_bridge_initfn(d, TYPE_PCI_BUS);
+
+d->config[PCI_INTERRUPT_PIN] = 0x1;
+memory_region_init(_br->shpc_bar, OBJECT(d), "shpc-bar",
+   shpc_bar_size(d));
+rc = shpc_init(d, >sec_bus, _br->shpc_bar, 0, errp);
+if (rc) {
+goto error;
+}
+
+rc = pcie_cap_init(d, 0, PCI_EXP_TYPE_PCI_BRIDGE, 0, errp);
+if (rc < 0) {
+goto cap_error;
+}
+
+pos = pci_add_capability(d, PCI_CAP_ID_PM, 0, PCI_PM_SIZEOF, errp);
+if (pos < 0) {
+goto pm_error;
+}
+d->exp.pm_cap = pos;
+pci_set_word(d->config + pos + PCI_PM_PMC, 0x3);
+
+pcie_cap_arifwd_init(d);
+pcie_cap_deverr_init(d);
+
+rc = pcie_aer_init(d, PCI_ERR_VER, 0x100, PCI_ERR_SIZEOF, errp);
+if (rc < 0) {
+goto aer_error;
+}
+
+if (pcie_br->msi != ON_OFF_AUTO_OFF) {
+rc = msi_init(d, 0, 1, true, true, errp);
+if (rc < 0) {
+goto msi_error;
+}
+}
+pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
+ PCI_BASE_ADDRESS_MEM_TYPE_64, _br->shpc_bar);
+return;
+
+msi_error:
+pcie_aer_exit(d);
+aer_error:
+pm_error:
+pcie_cap_exit(d);
+cap_error:
+shpc_free(d);
+error:
+pci_bridge_exitfn(d);
+}
+
+static void pcie_pci_bridge_exit(PCIDevice *d)
+{
+PCIEPCIBridge *bridge_dev = PCIE_PCI_BRIDGE_DEV(d);
+pcie_cap_exit(d);
+shpc_cleanup(d, _dev->shpc_bar);
+pci_bridge_exitfn(d);
+}
+
+static void pcie_pci_bridge_reset(DeviceState *qdev)
+{
+PCIDevice *d = PCI_DEVICE(qdev);
+pci_bridge_reset(qdev);
+msi_reset(d);
+shpc_reset(d);
+}
+
+static void pcie_pci_bridge_write_config(PCIDevice *d,
+uint32_t address, uint32_t val, int len)
+{
+pci_bridge_write_config(d, address, val, len);
+msi_write_config(d, address, val, len);
+shpc_cap_write_config(d, address, val, len);
+}
+
+static Property pcie_pci_bridge_dev_properties[] = {
+DEFINE_PROP_ON_OFF_AUTO("msi", PCIEPCIBridge, msi, ON_OFF_AUTO_ON),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static const VMStateDescription pcie_pci_bridge_dev_vmstate = {
+.name = TYPE_PCIE_PCI_BRIDGE_DEV,
+.fields = (VMStateField[]) {
+VMSTATE_PCI_DEVICE(parent_obj, PCIBridge),
+SHPC_VMSTATE(shpc, PCIDevice, NULL),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void pcie_pci_bridge_hotplug_cb(HotplugHandler *hotplug_dev,
+  DeviceState *dev, Error **errp)
+{
+PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);
+
+if (!shpc_present(pci_hotplug_dev)) {
+error_

[Qemu-devel] [PATCH v6 2/4] hw/pci: introduce bridge-only vendor-specific capability to provide some hints to firmware

2017-08-13 Thread Aleksandr Bezzubikov
On PCI init PCI bridges may need some extra info about bus number,
IO, memory and prefetchable memory to reserve. QEMU can provide this
with a special vendor-specific PCI capability.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 hw/pci/pci_bridge.c | 46 +
 include/hw/pci/pci_bridge.h | 25 
 2 files changed, 71 insertions(+)

diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 720119b..17feae5 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -408,6 +408,52 @@ void pci_bridge_map_irq(PCIBridge *br, const char* 
bus_name,
 br->bus_name = bus_name;
 }
 
+
+int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
+ uint32_t bus_reserve, uint64_t io_reserve,
+ uint32_t mem_non_pref_reserve,
+ uint32_t mem_pref_32_reserve,
+ uint64_t mem_pref_64_reserve,
+ Error **errp)
+{
+if (mem_pref_32_reserve != (uint32_t)-1 &&
+mem_pref_64_reserve != (uint64_t)-1) {
+error_setg(errp,
+   "PCI resource reserve cap: PREF32 and PREF64 conflict");
+return -EINVAL;
+}
+
+if (bus_reserve == (uint32_t)-1 &&
+io_reserve == (uint64_t)-1 &&
+mem_non_pref_reserve == (uint32_t)-1 &&
+mem_pref_32_reserve == (uint32_t)-1 &&
+mem_pref_64_reserve == (uint64_t)-1) {
+return 0;
+}
+
+size_t cap_len = sizeof(PCIBridgeQemuCap);
+PCIBridgeQemuCap cap = {
+.len = cap_len,
+.type = REDHAT_PCI_CAP_RESOURCE_RESERVE,
+.bus_res = bus_reserve,
+.io = io_reserve,
+.mem = mem_non_pref_reserve,
+.mem_pref_32 = mem_pref_32_reserve,
+.mem_pref_64 = mem_pref_64_reserve
+};
+
+int offset = pci_add_capability(dev, PCI_CAP_ID_VNDR,
+cap_offset, cap_len, errp);
+if (offset < 0) {
+return offset;
+}
+
+memcpy(dev->config + offset + PCI_CAP_FLAGS,
+   (char *) + PCI_CAP_FLAGS,
+   cap_len - PCI_CAP_FLAGS);
+return 0;
+}
+
 static const TypeInfo pci_bridge_type_info = {
 .name = TYPE_PCI_BRIDGE,
 .parent = TYPE_PCI_DEVICE,
diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h
index ff7cbaa..1acadc2 100644
--- a/include/hw/pci/pci_bridge.h
+++ b/include/hw/pci/pci_bridge.h
@@ -67,4 +67,29 @@ void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
 #define  PCI_BRIDGE_CTL_DISCARD_STATUS 0x400   /* Discard timer status */
 #define  PCI_BRIDGE_CTL_DISCARD_SERR   0x800   /* Discard timer SERR# enable */
 
+typedef struct PCIBridgeQemuCap {
+uint8_t id; /* Standard PCI capability header field */
+uint8_t next;   /* Standard PCI capability header field */
+uint8_t len;/* Standard PCI vendor-specific capability header field */
+uint8_t type;   /* Red Hat vendor-specific capability type.
+   Types are defined with REDHAT_PCI_CAP_ prefix */
+
+uint32_t bus_res;   /* Minimum number of buses to reserve */
+uint64_t io;/* IO space to reserve */
+uint32_t mem;   /* Non-prefetchable memory to reserve */
+/* At most one of the following two fields may be set to a value
+ * different from -1 */
+uint32_t mem_pref_32; /* Prefetchable memory to reserve (32-bit MMIO) */
+uint64_t mem_pref_64; /* Prefetchable memory to reserve (64-bit MMIO) */
+} PCIBridgeQemuCap;
+
+#define REDHAT_PCI_CAP_RESOURCE_RESERVE 1
+
+int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
+  uint32_t bus_reserve, uint64_t io_reserve,
+  uint32_t mem_non_pref_reserve,
+  uint32_t mem_pref_32_reserve,
+  uint64_t mem_pref_64_reserve,
+  Error **errp);
+
 #endif /* QEMU_PCI_BRIDGE_H */
-- 
2.7.4




[Qemu-devel] [PATCH v6 4/4] docs: update documentation considering PCIE-PCI bridge

2017-08-13 Thread Aleksandr Bezzubikov
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Laszlo Ersek <ler...@redhat.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 docs/pcie.txt|  49 ++--
 docs/pcie_pci_bridge.txt | 114 +++
 2 files changed, 140 insertions(+), 23 deletions(-)
 create mode 100644 docs/pcie_pci_bridge.txt

diff --git a/docs/pcie.txt b/docs/pcie.txt
index 5bada24..76b85ec 100644
--- a/docs/pcie.txt
+++ b/docs/pcie.txt
@@ -46,7 +46,7 @@ Place only the following kinds of devices directly on the 
Root Complex:
 (2) PCI Express Root Ports (ioh3420), for starting exclusively PCI Express
 hierarchies.
 
-(3) DMI-PCI Bridges (i82801b11-bridge), for starting legacy PCI
+(3) PCI Express to PCI Bridge (pcie-pci-bridge), for starting legacy PCI
 hierarchies.
 
 (4) Extra Root Complexes (pxb-pcie), if multiple PCI Express Root Buses
@@ -55,18 +55,18 @@ Place only the following kinds of devices directly on the 
Root Complex:
pcie.0 bus

 |||  |
-   ---   --   --   --
-   | PCI Dev |   | PCIe Root Port |   | DMI-PCI Bridge |   |  pxb-pcie  |
-   ---   --   --   --
+   ---   --   ---   --
+   | PCI Dev |   | PCIe Root Port |   | PCIe-PCI Bridge |   |  pxb-pcie  |
+   ---   --   ---   --
 
 2.1.1 To plug a device into pcie.0 as a Root Complex Integrated Endpoint use:
   -device [,bus=pcie.0]
 2.1.2 To expose a new PCI Express Root Bus use:
   -device pxb-pcie,id=pcie.1,bus_nr=x[,numa_node=y][,addr=z]
-  Only PCI Express Root Ports and DMI-PCI bridges can be connected
-  to the pcie.1 bus:
+  PCI Express Root Ports and PCI Express to PCI bridges can be
+  connected to the pcie.1 bus:
   -device 
ioh3420,id=root_port1[,bus=pcie.1][,chassis=x][,slot=y][,addr=z]
 \
-  -device i82801b11-bridge,id=dmi_pci_bridge1,bus=pcie.1
+  -device pcie-pci-bridge,id=pcie_pci_bridge1,bus=pcie.1
 
 
 2.2 PCI Express only hierarchy
@@ -130,24 +130,24 @@ Notes:
 Legacy PCI devices can be plugged into pcie.0 as Integrated Endpoints,
 but, as mentioned in section 5, doing so means the legacy PCI
 device in question will be incapable of hot-unplugging.
-Besides that use DMI-PCI Bridges (i82801b11-bridge) in combination
-with PCI-PCI Bridges (pci-bridge) to start PCI hierarchies.
+Besides that use PCI Express to PCI Bridges (pcie-pci-bridge) in
+combination with PCI-PCI Bridges (pci-bridge) to start PCI hierarchies.
 
-Prefer flat hierarchies. For most scenarios a single DMI-PCI Bridge
+Prefer flat hierarchies. For most scenarios a single PCI Express to PCI Bridge
 (having 32 slots) and several PCI-PCI Bridges attached to it
 (each supporting also 32 slots) will support hundreds of legacy devices.
-The recommendation is to populate one PCI-PCI Bridge under the DMI-PCI Bridge
-until is full and then plug a new PCI-PCI Bridge...
+The recommendation is to populate one PCI-PCI Bridge under the
+PCI Express to PCI Bridge until is full and then plug a new PCI-PCI Bridge...
 
pcie.0 bus
--
 ||
-   ---   --
-   | PCI Dev |   | DMI-PCI BRIDGE |
-   ----
+   ---   ---
+   | PCI Dev |   | PCIe-PCI Bridge |
+   ---   ---
||
   ----
-  | PCI-PCI Bridge || PCI-PCI Bridge |   ...
+  | PCI-PCI Bridge || PCI-PCI Bridge |
   ----
  |   |
   --- ---
@@ -157,11 +157,11 @@ until is full and then plug a new PCI-PCI Bridge...
 2.3.1 To plug a PCI device into pcie.0 as an Integrated Endpoint use:
   -device [,bus=pcie.0]
 2.3.2 Plugging a PCI device into a PCI-PCI Bridge:
-  -device i82801b11-bridge,id=dmi_pci_bridge1[,bus=pcie.0] 
   \
-  -device 
pci-bridge,id=pci_bridge1,bus=dmi_pci_bridge1[,chassis_nr=x][,addr=y]   \
+  -device pcie-pci-bridge,id=pcie_pci_bridge1[,bus=pcie.0] \
+  -device 
pci-bridge,id=pci_bridge1,bus=pcie_pci_bridge1[,chassis_nr=x][,addr=y] \
   -device ,bus=pci_bridge1[,addr=x]
   Note that 'addr' cannot be 0 unless shpc=off parameter is passed to
-  the PCI Bridge.
+  the PCI Bridge/PCI Exp

[Qemu-devel] [PATCH v6 0/4] Generic PCIE-PCI Bridge

2017-08-13 Thread Aleksandr Bezzubikov
This series introduces a new device - Generic PCI Express to PCI bridge,
and also makes all necessary changes to enable hotplug of the bridge itself
and any device into the bridge.

Changes v5->v6:
1. Fix indentation in the cap creation function (addresses Marcel's comment)
2. Simplify capability pref_mem_* fields assignment (addresses Marcel's comment)
3. Documentation fixes:
- fix mutually exclusive fields definition (addresses Laszlo's comment)
- fix pcie-pci-bridge usage example (addresses Marcel's comment)

Changes v4->v5:
1. Change PCIE-PCI Bridge license (addresses Marcel's comment)
2. The capability layout changes (adress Laszlo' comments): 
- separate pref_mem into pref_mem_32 and pref_mem_64 fields (SeaBIOS side 
has the same changes)
- accordingly change the Generic Root Port's properties
3. Do not add the capability to the root port if no valid values are provided 
(adresses Michael's comment)
4. Rename the capability type to 'RESOURCE_RESERVE' (addresses Marcel's comment)
5. Remove shpc_present check function (addresses Marcel's comment)
6. Fix the 4th patch message (adresses Michael's comment)
7. Patch for SHPC enabling in _OSC method has been already merged

Changes v3->v4:
1. PCIE-PCI Bridge device: "msi_enable"->"msi", "shpc"->"shpc_bar", remove 
local_err,
   make "msi" property OnOffAuto, shpc_present() is still here 
   to avoid SHPC_VMSTATE refactoring (address Marcel's comments). 
2. Change QEMU PCI capability layout (SeaBIOS side has the same changes):
  - change reservation fields types: bus_res - uint32_t, others - uint64_t
  - rename 'non_pref' and 'pref' fields
  - interpret -1 value as 'ignore'
3. Use parent_realize in Generic PCI Express Root Port properly.
4. Fix documentation: fully replace the DMI-PCI bridge references with the new 
PCIE-PCI bridge,
"PCIE"->"PCI Express", small mistakes and typos - address Laszlo's and Marcel's 
comments.
5. Rename QEMU PCI cap creation fucntion - addresses Marcel's comment.

Changes v2->v3:
(0). 'do_not_use' capability field flag is still _not_ in here since we haven't 
come to consesus on it yet.
1. Merge commits 5 (bus_reserve property creation) and 6 (property usage) 
together - addresses Michael's comment.
2. Add 'bus_reserve' property and QEMU PCI capability only to Generic PCIE Root 
Port - addresses Michael's and Marcel's comments.
3. Change 'bus_reserve' property's default value to 0 - addresses Michael's 
comment.
4. Rename QEMU bridge-specific PCI capability creation function - addresses 
Michael's comment.
5. Init the whole QEMU PCI capability with zeroes - addresses Michael's and 
Laszlo's comments.
6. Change QEMU PCI capability layout (SeaBIOS side has the same changes)
  - add 'type' field to distinguish multiple 
RedHat-specific capabilities - addresses Michael's comment
  - do not mimiс PCI Config space register layout, but use mutually exclusive 
differently
sized fields for IO and prefetchable memory limits - addresses Laszlo's 
comment
7. Correct error handling in PCIE-PCI bridge realize function.
8. Replace a '2' constant with PCI_CAP_FLAGS in the capability creation 
function - addresses Michael's comment.
9. Remove a comment on _OSC which isn't correct anymore - address Marcel's 
comment.
10. Add documentation for the Generic PCIE-PCI Bridge and QEMU PCI capability - 
addresses Michael's comment.

Changes v1->v2:
1. Enable SHPC for the bridge.
2. Enable SHPC support for the Q35 machine (ACPI stuff).
3. Introduce PCI capability to help firmware on the system init.
   This allows the bridge to be hotpluggable. Now it's supported 
   only for pcie-root-port. Now it's supposed to used with 
   SeaBIOS only, look at the SeaBIOS corresponding series
   "Allow RedHat PCI bridges reserve more buses than necessary during init".

Aleksandr Bezzubikov (4):
  hw/pci: introduce pcie-pci-bridge device
  hw/pci: introduce bridge-only vendor-specific capability to provide
some hints to firmware
  hw/pci: add QEMU-specific PCI capability to the Generic PCI Express
Root Port
  docs: update documentation considering PCIE-PCI bridge

 docs/pcie.txt  |  49 +-
 docs/pcie_pci_bridge.txt   | 114 ++
 hw/pci-bridge/Makefile.objs|   2 +-
 hw/pci-bridge/gen_pcie_root_port.c |  36 +++
 hw/pci-bridge/pcie_pci_bridge.c| 192 +
 hw/pci/pci_bridge.c|  46 +
 include/hw/pci/pci.h   |   1 +
 include/hw/pci/pci_bridge.h|  25 +
 include/hw/pci/pcie_port.h |   1 +
 9 files changed, 442 insertions(+), 24 deletions(-)
 create mode 100644 docs/pcie_pci_bridge.txt
 create mode 100644 hw/pci-bridge/pcie_pci_bridge.c

-- 
2.7.4




[Qemu-devel] [PATCH v6 3/4] hw/pci: add QEMU-specific PCI capability to the Generic PCI Express Root Port

2017-08-13 Thread Aleksandr Bezzubikov
To enable hotplugging of a newly created pcie-pci-bridge,
we need to tell firmware (e.g. SeaBIOS) to reserve
additional buses or IO/MEM/PREF space for pcie-root-port.
Additional bus reservation allows us to hotplug pcie-pci-bridge into this root 
port.
The number of buses and IO/MEM/PREF space to reserve are provided to the device 
via
a corresponding property, and to the firmware via new PCI capability.
The properties' default values are -1 to keep default behavior unchanged.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 hw/pci-bridge/gen_pcie_root_port.c | 36 
 include/hw/pci/pcie_port.h |  1 +
 2 files changed, 37 insertions(+)

diff --git a/hw/pci-bridge/gen_pcie_root_port.c 
b/hw/pci-bridge/gen_pcie_root_port.c
index cb694d6..bd65479 100644
--- a/hw/pci-bridge/gen_pcie_root_port.c
+++ b/hw/pci-bridge/gen_pcie_root_port.c
@@ -16,6 +16,8 @@
 #include "hw/pci/pcie_port.h"
 
 #define TYPE_GEN_PCIE_ROOT_PORT"pcie-root-port"
+#define GEN_PCIE_ROOT_PORT(obj) \
+OBJECT_CHECK(GenPCIERootPort, (obj), TYPE_GEN_PCIE_ROOT_PORT)
 
 #define GEN_PCIE_ROOT_PORT_AER_OFFSET   0x100
 #define GEN_PCIE_ROOT_PORT_MSIX_NR_VECTOR   1
@@ -26,6 +28,13 @@ typedef struct GenPCIERootPort {
 /*< public >*/
 
 bool migrate_msix;
+
+/* additional resources to reserve on firmware init */
+uint32_t bus_reserve;
+uint64_t io_reserve;
+uint32_t mem_reserve;
+uint32_t pref32_reserve;
+uint64_t pref64_reserve;
 } GenPCIERootPort;
 
 static uint8_t gen_rp_aer_vector(const PCIDevice *d)
@@ -60,6 +69,24 @@ static bool gen_rp_test_migrate_msix(void *opaque, int 
version_id)
 return rp->migrate_msix;
 }
 
+static void gen_rp_realize(DeviceState *dev, Error **errp)
+{
+PCIDevice *d = PCI_DEVICE(dev);
+GenPCIERootPort *grp = GEN_PCIE_ROOT_PORT(d);
+PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(d);
+
+rpc->parent_realize(dev, errp);
+
+int rc = pci_bridge_qemu_reserve_cap_init(d, 0, grp->bus_reserve,
+grp->io_reserve, grp->mem_reserve, grp->pref32_reserve,
+grp->pref64_reserve, errp);
+
+if (rc < 0) {
+rpc->parent_class.exit(d);
+return;
+}
+}
+
 static const VMStateDescription vmstate_rp_dev = {
 .name = "pcie-root-port",
 .version_id = 1,
@@ -78,6 +105,11 @@ static const VMStateDescription vmstate_rp_dev = {
 
 static Property gen_rp_props[] = {
 DEFINE_PROP_BOOL("x-migrate-msix", GenPCIERootPort, migrate_msix, true),
+DEFINE_PROP_UINT32("bus-reserve", GenPCIERootPort, bus_reserve, -1),
+DEFINE_PROP_UINT64("io-reserve", GenPCIERootPort, io_reserve, -1),
+DEFINE_PROP_UINT32("mem-reserve", GenPCIERootPort, mem_reserve, -1),
+DEFINE_PROP_UINT32("pref32-reserve", GenPCIERootPort, pref32_reserve, -1),
+DEFINE_PROP_UINT64("pref64-reserve", GenPCIERootPort, pref64_reserve, -1),
 DEFINE_PROP_END_OF_LIST()
 };
 
@@ -92,6 +124,10 @@ static void gen_rp_dev_class_init(ObjectClass *klass, void 
*data)
 dc->desc = "PCI Express Root Port";
 dc->vmsd = _rp_dev;
 dc->props = gen_rp_props;
+
+rpc->parent_realize = dc->realize;
+dc->realize = gen_rp_realize;
+
 rpc->aer_vector = gen_rp_aer_vector;
 rpc->interrupts_init = gen_rp_interrupts_init;
 rpc->interrupts_uninit = gen_rp_interrupts_uninit;
diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
index 1333266..0736014 100644
--- a/include/hw/pci/pcie_port.h
+++ b/include/hw/pci/pcie_port.h
@@ -65,6 +65,7 @@ void pcie_chassis_del_slot(PCIESlot *s);
 
 typedef struct PCIERootPortClass {
 PCIDeviceClass parent_class;
+DeviceRealize parent_realize;
 
 uint8_t (*aer_vector)(const PCIDevice *dev);
 int (*interrupts_init)(PCIDevice *dev, Error **errp);
-- 
2.7.4




[Qemu-devel] [PATCH v5 2/4] hw/pci: introduce bridge-only vendor-specific capability to provide some hints to firmware

2017-08-10 Thread Aleksandr Bezzubikov
On PCI init PCI bridges may need some extra info about bus number,
IO, memory and prefetchable memory to reserve. QEMU can provide this
with a special vendor-specific PCI capability.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 hw/pci/pci_bridge.c | 54 +
 include/hw/pci/pci_bridge.h | 24 
 2 files changed, 78 insertions(+)

diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 720119b..2495a51 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -408,6 +408,60 @@ void pci_bridge_map_irq(PCIBridge *br, const char* 
bus_name,
 br->bus_name = bus_name;
 }
 
+
+int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
+  uint32_t bus_reserve, uint64_t io_reserve,
+  uint32_t mem_non_pref_reserve,
+  uint32_t mem_pref_32_reserve,
+  uint64_t mem_pref_64_reserve,
+  Error **errp)
+{
+if (mem_pref_32_reserve != (uint32_t)-1 &&
+mem_pref_64_reserve != (uint64_t) -1) {
+error_setg(errp,
+   "PCI resource reserve cap: PREF32 and PREF64 conflict");
+return -EINVAL;
+}
+
+if (bus_reserve == (uint32_t)-1 &&
+io_reserve == (uint64_t)-1 &&
+mem_non_pref_reserve == (uint32_t)-1 &&
+mem_pref_32_reserve == (uint32_t)-1 &&
+mem_pref_64_reserve == (uint64_t)-1) {
+return 0;
+}
+
+size_t cap_len = sizeof(PCIBridgeQemuCap);
+PCIBridgeQemuCap cap = {
+.len = cap_len,
+.type = REDHAT_PCI_CAP_RESOURCE_RESERVE,
+.bus_res = bus_reserve,
+.io = io_reserve,
+.mem = mem_non_pref_reserve,
+.mem_pref_32 = (uint32_t)-1,
+.mem_pref_64 = (uint64_t)-1
+};
+
+if (mem_pref_32_reserve != (uint32_t)-1 &&
+mem_pref_64_reserve == (uint64_t)-1) {
+cap.mem_pref_32 = mem_pref_32_reserve;
+} else if (mem_pref_32_reserve == (uint32_t)-1 &&
+mem_pref_64_reserve != (uint64_t)-1) {
+cap.mem_pref_64 = mem_pref_64_reserve;
+}
+
+int offset = pci_add_capability(dev, PCI_CAP_ID_VNDR,
+cap_offset, cap_len, errp);
+if (offset < 0) {
+return offset;
+}
+
+memcpy(dev->config + offset + PCI_CAP_FLAGS,
+(char *) + PCI_CAP_FLAGS,
+cap_len - PCI_CAP_FLAGS);
+return 0;
+}
+
 static const TypeInfo pci_bridge_type_info = {
 .name = TYPE_PCI_BRIDGE,
 .parent = TYPE_PCI_DEVICE,
diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h
index ff7cbaa..2d8c635 100644
--- a/include/hw/pci/pci_bridge.h
+++ b/include/hw/pci/pci_bridge.h
@@ -67,4 +67,28 @@ void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
 #define  PCI_BRIDGE_CTL_DISCARD_STATUS 0x400   /* Discard timer status */
 #define  PCI_BRIDGE_CTL_DISCARD_SERR   0x800   /* Discard timer SERR# enable */
 
+typedef struct PCIBridgeQemuCap {
+uint8_t id; /* Standard PCI capability header field */
+uint8_t next;   /* Standard PCI capability header field */
+uint8_t len;/* Standard PCI vendor-specific capability header field */
+uint8_t type;   /* Red Hat vendor-specific capability type.
+   Types are defined with REDHAT_PCI_CAP_ prefix */
+
+uint32_t bus_res;   /* Minimum number of buses to reserve */
+uint64_t io;/* IO space to reserve */
+uint32_t mem;   /* Non-prefetchable memory to reserve */
+/* This two fields are mutually exclusive */
+uint32_t mem_pref_32; /* Prefetchable memory to reserve (32-bit MMIO) */
+uint64_t mem_pref_64; /* Prefetchable memory to reserve (64-bit MMIO) */
+} PCIBridgeQemuCap;
+
+#define REDHAT_PCI_CAP_RESOURCE_RESERVE 1
+
+int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
+  uint32_t bus_reserve, uint64_t io_reserve,
+  uint32_t mem_non_pref_reserve,
+  uint32_t mem_pref_32_reserve,
+  uint64_t mem_pref_64_reserve,
+  Error **errp);
+
 #endif /* QEMU_PCI_BRIDGE_H */
-- 
2.7.4




[Qemu-devel] [PATCH v5 4/4] docs: update documentation considering PCIE-PCI bridge

2017-08-10 Thread Aleksandr Bezzubikov
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 docs/pcie.txt|  49 ++--
 docs/pcie_pci_bridge.txt | 115 +++
 2 files changed, 141 insertions(+), 23 deletions(-)
 create mode 100644 docs/pcie_pci_bridge.txt

diff --git a/docs/pcie.txt b/docs/pcie.txt
index 5bada24..76b85ec 100644
--- a/docs/pcie.txt
+++ b/docs/pcie.txt
@@ -46,7 +46,7 @@ Place only the following kinds of devices directly on the 
Root Complex:
 (2) PCI Express Root Ports (ioh3420), for starting exclusively PCI Express
 hierarchies.
 
-(3) DMI-PCI Bridges (i82801b11-bridge), for starting legacy PCI
+(3) PCI Express to PCI Bridge (pcie-pci-bridge), for starting legacy PCI
 hierarchies.
 
 (4) Extra Root Complexes (pxb-pcie), if multiple PCI Express Root Buses
@@ -55,18 +55,18 @@ Place only the following kinds of devices directly on the 
Root Complex:
pcie.0 bus

 |||  |
-   ---   --   --   --
-   | PCI Dev |   | PCIe Root Port |   | DMI-PCI Bridge |   |  pxb-pcie  |
-   ---   --   --   --
+   ---   --   ---   --
+   | PCI Dev |   | PCIe Root Port |   | PCIe-PCI Bridge |   |  pxb-pcie  |
+   ---   --   ---   --
 
 2.1.1 To plug a device into pcie.0 as a Root Complex Integrated Endpoint use:
   -device [,bus=pcie.0]
 2.1.2 To expose a new PCI Express Root Bus use:
   -device pxb-pcie,id=pcie.1,bus_nr=x[,numa_node=y][,addr=z]
-  Only PCI Express Root Ports and DMI-PCI bridges can be connected
-  to the pcie.1 bus:
+  PCI Express Root Ports and PCI Express to PCI bridges can be
+  connected to the pcie.1 bus:
   -device 
ioh3420,id=root_port1[,bus=pcie.1][,chassis=x][,slot=y][,addr=z]
 \
-  -device i82801b11-bridge,id=dmi_pci_bridge1,bus=pcie.1
+  -device pcie-pci-bridge,id=pcie_pci_bridge1,bus=pcie.1
 
 
 2.2 PCI Express only hierarchy
@@ -130,24 +130,24 @@ Notes:
 Legacy PCI devices can be plugged into pcie.0 as Integrated Endpoints,
 but, as mentioned in section 5, doing so means the legacy PCI
 device in question will be incapable of hot-unplugging.
-Besides that use DMI-PCI Bridges (i82801b11-bridge) in combination
-with PCI-PCI Bridges (pci-bridge) to start PCI hierarchies.
+Besides that use PCI Express to PCI Bridges (pcie-pci-bridge) in
+combination with PCI-PCI Bridges (pci-bridge) to start PCI hierarchies.
 
-Prefer flat hierarchies. For most scenarios a single DMI-PCI Bridge
+Prefer flat hierarchies. For most scenarios a single PCI Express to PCI Bridge
 (having 32 slots) and several PCI-PCI Bridges attached to it
 (each supporting also 32 slots) will support hundreds of legacy devices.
-The recommendation is to populate one PCI-PCI Bridge under the DMI-PCI Bridge
-until is full and then plug a new PCI-PCI Bridge...
+The recommendation is to populate one PCI-PCI Bridge under the
+PCI Express to PCI Bridge until is full and then plug a new PCI-PCI Bridge...
 
pcie.0 bus
--
 ||
-   ---   --
-   | PCI Dev |   | DMI-PCI BRIDGE |
-   ----
+   ---   ---
+   | PCI Dev |   | PCIe-PCI Bridge |
+   ---   ---
||
   ----
-  | PCI-PCI Bridge || PCI-PCI Bridge |   ...
+  | PCI-PCI Bridge || PCI-PCI Bridge |
   ----
  |   |
   --- ---
@@ -157,11 +157,11 @@ until is full and then plug a new PCI-PCI Bridge...
 2.3.1 To plug a PCI device into pcie.0 as an Integrated Endpoint use:
   -device [,bus=pcie.0]
 2.3.2 Plugging a PCI device into a PCI-PCI Bridge:
-  -device i82801b11-bridge,id=dmi_pci_bridge1[,bus=pcie.0] 
   \
-  -device 
pci-bridge,id=pci_bridge1,bus=dmi_pci_bridge1[,chassis_nr=x][,addr=y]   \
+  -device pcie-pci-bridge,id=pcie_pci_bridge1[,bus=pcie.0] \
+  -device 
pci-bridge,id=pci_bridge1,bus=pcie_pci_bridge1[,chassis_nr=x][,addr=y] \
   -device ,bus=pci_bridge1[,addr=x]
   Note that 'addr' cannot be 0 unless shpc=off parameter is passed to
-  the PCI Bridge.
+  the PCI Bridge/PCI Express to PCI Bridge.
 
 3. IO space issues
 ===
@@ -219,14 +219,16 @@ do not support hot-pl

[Qemu-devel] [PATCH v5 1/4] hw/pci: introduce pcie-pci-bridge device

2017-08-10 Thread Aleksandr Bezzubikov
Introduce a new PCIExpress-to-PCI Bridge device,
which is a hot-pluggable PCI Express device and
supports devices hot-plug with SHPC.

This device is intended to replace the DMI-to-PCI Bridge.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/pci-bridge/Makefile.objs |   2 +-
 hw/pci-bridge/pcie_pci_bridge.c | 192 
 include/hw/pci/pci.h|   1 +
 3 files changed, 194 insertions(+), 1 deletion(-)
 create mode 100644 hw/pci-bridge/pcie_pci_bridge.c

diff --git a/hw/pci-bridge/Makefile.objs b/hw/pci-bridge/Makefile.objs
index c4683cf..666db37 100644
--- a/hw/pci-bridge/Makefile.objs
+++ b/hw/pci-bridge/Makefile.objs
@@ -1,4 +1,4 @@
-common-obj-y += pci_bridge_dev.o
+common-obj-y += pci_bridge_dev.o pcie_pci_bridge.o
 common-obj-$(CONFIG_PCIE_PORT) += pcie_root_port.o gen_pcie_root_port.o
 common-obj-$(CONFIG_PXB) += pci_expander_bridge.o
 common-obj-$(CONFIG_XIO3130) += xio3130_upstream.o xio3130_downstream.o
diff --git a/hw/pci-bridge/pcie_pci_bridge.c b/hw/pci-bridge/pcie_pci_bridge.c
new file mode 100644
index 000..9aa5cc3
--- /dev/null
+++ b/hw/pci-bridge/pcie_pci_bridge.c
@@ -0,0 +1,192 @@
+/*
+ * QEMU Generic PCIE-PCI Bridge
+ *
+ * Copyright (c) 2017 Aleksandr Bezzubikov
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/shpc.h"
+#include "hw/pci/slotid_cap.h"
+
+typedef struct PCIEPCIBridge {
+/*< private >*/
+PCIBridge parent_obj;
+
+OnOffAuto msi;
+MemoryRegion shpc_bar;
+/*< public >*/
+} PCIEPCIBridge;
+
+#define TYPE_PCIE_PCI_BRIDGE_DEV "pcie-pci-bridge"
+#define PCIE_PCI_BRIDGE_DEV(obj) \
+OBJECT_CHECK(PCIEPCIBridge, (obj), TYPE_PCIE_PCI_BRIDGE_DEV)
+
+static void pcie_pci_bridge_realize(PCIDevice *d, Error **errp)
+{
+PCIBridge *br = PCI_BRIDGE(d);
+PCIEPCIBridge *pcie_br = PCIE_PCI_BRIDGE_DEV(d);
+int rc, pos;
+
+pci_bridge_initfn(d, TYPE_PCI_BUS);
+
+d->config[PCI_INTERRUPT_PIN] = 0x1;
+memory_region_init(_br->shpc_bar, OBJECT(d), "shpc-bar",
+   shpc_bar_size(d));
+rc = shpc_init(d, >sec_bus, _br->shpc_bar, 0, errp);
+if (rc) {
+goto error;
+}
+
+rc = pcie_cap_init(d, 0, PCI_EXP_TYPE_PCI_BRIDGE, 0, errp);
+if (rc < 0) {
+goto cap_error;
+}
+
+pos = pci_add_capability(d, PCI_CAP_ID_PM, 0, PCI_PM_SIZEOF, errp);
+if (pos < 0) {
+goto pm_error;
+}
+d->exp.pm_cap = pos;
+pci_set_word(d->config + pos + PCI_PM_PMC, 0x3);
+
+pcie_cap_arifwd_init(d);
+pcie_cap_deverr_init(d);
+
+rc = pcie_aer_init(d, PCI_ERR_VER, 0x100, PCI_ERR_SIZEOF, errp);
+if (rc < 0) {
+goto aer_error;
+}
+
+if (pcie_br->msi != ON_OFF_AUTO_OFF) {
+rc = msi_init(d, 0, 1, true, true, errp);
+if (rc < 0) {
+goto msi_error;
+}
+}
+pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
+ PCI_BASE_ADDRESS_MEM_TYPE_64, _br->shpc_bar);
+return;
+
+msi_error:
+pcie_aer_exit(d);
+aer_error:
+pm_error:
+pcie_cap_exit(d);
+cap_error:
+shpc_free(d);
+error:
+pci_bridge_exitfn(d);
+}
+
+static void pcie_pci_bridge_exit(PCIDevice *d)
+{
+PCIEPCIBridge *bridge_dev = PCIE_PCI_BRIDGE_DEV(d);
+pcie_cap_exit(d);
+shpc_cleanup(d, _dev->shpc_bar);
+pci_bridge_exitfn(d);
+}
+
+static void pcie_pci_bridge_reset(DeviceState *qdev)
+{
+PCIDevice *d = PCI_DEVICE(qdev);
+pci_bridge_reset(qdev);
+msi_reset(d);
+shpc_reset(d);
+}
+
+static void pcie_pci_bridge_write_config(PCIDevice *d,
+uint32_t address, uint32_t val, int len)
+{
+pci_bridge_write_config(d, address, val, len);
+msi_write_config(d, address, val, len);
+shpc_cap_write_config(d, address, val, len);
+}
+
+static Property pcie_pci_bridge_dev_properties[] = {
+DEFINE_PROP_ON_OFF_AUTO("msi", PCIEPCIBridge, msi, ON_OFF_AUTO_ON),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static const VMStateDescription pcie_pci_bridge_dev_vmstate = {
+.name = TYPE_PCIE_PCI_BRIDGE_DEV,
+.fields = (VMStateField[]) {
+VMSTATE_PCI_DEVICE(parent_obj, PCIBridge),
+SHPC_VMSTATE(shpc, PCIDevice, NULL),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void pcie_pci_bridge_hotplug_cb(HotplugHandler *hotplug_dev,
+  DeviceState *dev, Error **errp)
+{
+PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);
+
+if (!shpc_present(pci_hotplug_dev)) {
+error_setg(errp, "standard hotplug controller has 

[Qemu-devel] [PATCH v5 0/4] Generic PCIE-PCI Bridge

2017-08-10 Thread Aleksandr Bezzubikov
This series introduces a new device - Generic PCI Express to PCI bridge,
and also makes all necessary changes to enable hotplug of the bridge itself
and any device into the bridge.

Changes v4->v5:
1. Change PCIE-PCI Bridge license (addresses Marcel's comment)
2. The capability layout changes (adress Laszlo' comments): 
- separate pref_mem into pref_mem_32 and pref_mem_64 fields (SeaBIOS side 
has the same changes)
- accordingly change the Generic Root Port's properties
3. Do not add the capability to the root port if no valid values are provided 
(adresses Michael's comment)
4. Rename the capability type to 'RESOURCE_RESERVE' (addresses Marcel's comment)
5. Remove shpc_present check function (addresses Marcel's comment)
6. Fix the 4th patch message (adresses Michael's comment)
7. Patch for SHPC enabling in _OSC method has been already merged

Changes v3->v4:
1. PCIE-PCI Bridge device: "msi_enable"->"msi", "shpc"->"shpc_bar", remove 
local_err,
   make "msi" property OnOffAuto, shpc_present() is still here 
   to avoid SHPC_VMSTATE refactoring (address Marcel's comments). 
2. Change QEMU PCI capability layout (SeaBIOS side has the same changes):
  - change reservation fields types: bus_res - uint32_t, others - uint64_t
  - rename 'non_pref' and 'pref' fields
  - interpret -1 value as 'ignore'
3. Use parent_realize in Generic PCI Express Root Port properly.
4. Fix documentation: fully replace the DMI-PCI bridge references with the new 
PCIE-PCI bridge,
"PCIE"->"PCI Express", small mistakes and typos - address Laszlo's and Marcel's 
comments.
5. Rename QEMU PCI cap creation fucntion - addresses Marcel's comment.

Changes v2->v3:
(0). 'do_not_use' capability field flag is still _not_ in here since we haven't 
come to consesus on it yet.
1. Merge commits 5 (bus_reserve property creation) and 6 (property usage) 
together - addresses Michael's comment.
2. Add 'bus_reserve' property and QEMU PCI capability only to Generic PCIE Root 
Port - addresses Michael's and Marcel's comments.
3. Change 'bus_reserve' property's default value to 0 - addresses Michael's 
comment.
4. Rename QEMU bridge-specific PCI capability creation function - addresses 
Michael's comment.
5. Init the whole QEMU PCI capability with zeroes - addresses Michael's and 
Laszlo's comments.
6. Change QEMU PCI capability layout (SeaBIOS side has the same changes)
  - add 'type' field to distinguish multiple 
RedHat-specific capabilities - addresses Michael's comment
  - do not mimiс PCI Config space register layout, but use mutually exclusive 
differently
sized fields for IO and prefetchable memory limits - addresses Laszlo's 
comment
7. Correct error handling in PCIE-PCI bridge realize function.
8. Replace a '2' constant with PCI_CAP_FLAGS in the capability creation 
function - addresses Michael's comment.
9. Remove a comment on _OSC which isn't correct anymore - address Marcel's 
comment.
10. Add documentation for the Generic PCIE-PCI Bridge and QEMU PCI capability - 
addresses Michael's comment.

Changes v1->v2:
1. Enable SHPC for the bridge.
2. Enable SHPC support for the Q35 machine (ACPI stuff).
3. Introduce PCI capability to help firmware on the system init.
   This allows the bridge to be hotpluggable. Now it's supported 
   only for pcie-root-port. Now it's supposed to used with 
   SeaBIOS only, look at the SeaBIOS corresponding series
   "Allow RedHat PCI bridges reserve more buses than necessary during init".

Aleksandr Bezzubikov (4):
  hw/pci: introduce pcie-pci-bridge device
  hw/pci: introduce bridge-only vendor-specific capability to provide
some hints to firmware
  hw/pci: add QEMU-specific PCI capability to the Generic PCI Express
Root Port
  docs: update documentation considering PCIE-PCI bridge

 docs/pcie.txt  |  49 +-
 docs/pcie_pci_bridge.txt   | 115 ++
 hw/pci-bridge/Makefile.objs|   2 +-
 hw/pci-bridge/gen_pcie_root_port.c |  36 +++
 hw/pci-bridge/pcie_pci_bridge.c| 192 +
 hw/pci/pci_bridge.c|  54 +++
 include/hw/pci/pci.h   |   1 +
 include/hw/pci/pci_bridge.h|  24 +
 include/hw/pci/pcie_port.h |   1 +
 9 files changed, 450 insertions(+), 24 deletions(-)
 create mode 100644 docs/pcie_pci_bridge.txt
 create mode 100644 hw/pci-bridge/pcie_pci_bridge.c

-- 
2.7.4




[Qemu-devel] [PATCH v5 3/4] hw/pci: add QEMU-specific PCI capability to the Generic PCI Express Root Port

2017-08-10 Thread Aleksandr Bezzubikov
To enable hotplugging of a newly created pcie-pci-bridge,
we need to tell firmware (e.g. SeaBIOS) to reserve
additional buses or IO/MEM/PREF space for pcie-root-port.
Additional bus reservation allows us to hotplug pcie-pci-bridge into this root 
port.
The number of buses and IO/MEM/PREF space to reserve are provided to the device 
via
a corresponding property, and to the firmware via new PCI capability.
The properties' default values are -1 to keep default behavior unchanged.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 hw/pci-bridge/gen_pcie_root_port.c | 36 
 include/hw/pci/pcie_port.h |  1 +
 2 files changed, 37 insertions(+)

diff --git a/hw/pci-bridge/gen_pcie_root_port.c 
b/hw/pci-bridge/gen_pcie_root_port.c
index cb694d6..bd65479 100644
--- a/hw/pci-bridge/gen_pcie_root_port.c
+++ b/hw/pci-bridge/gen_pcie_root_port.c
@@ -16,6 +16,8 @@
 #include "hw/pci/pcie_port.h"
 
 #define TYPE_GEN_PCIE_ROOT_PORT"pcie-root-port"
+#define GEN_PCIE_ROOT_PORT(obj) \
+OBJECT_CHECK(GenPCIERootPort, (obj), TYPE_GEN_PCIE_ROOT_PORT)
 
 #define GEN_PCIE_ROOT_PORT_AER_OFFSET   0x100
 #define GEN_PCIE_ROOT_PORT_MSIX_NR_VECTOR   1
@@ -26,6 +28,13 @@ typedef struct GenPCIERootPort {
 /*< public >*/
 
 bool migrate_msix;
+
+/* additional resources to reserve on firmware init */
+uint32_t bus_reserve;
+uint64_t io_reserve;
+uint32_t mem_reserve;
+uint32_t pref32_reserve;
+uint64_t pref64_reserve;
 } GenPCIERootPort;
 
 static uint8_t gen_rp_aer_vector(const PCIDevice *d)
@@ -60,6 +69,24 @@ static bool gen_rp_test_migrate_msix(void *opaque, int 
version_id)
 return rp->migrate_msix;
 }
 
+static void gen_rp_realize(DeviceState *dev, Error **errp)
+{
+PCIDevice *d = PCI_DEVICE(dev);
+GenPCIERootPort *grp = GEN_PCIE_ROOT_PORT(d);
+PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(d);
+
+rpc->parent_realize(dev, errp);
+
+int rc = pci_bridge_qemu_reserve_cap_init(d, 0, grp->bus_reserve,
+grp->io_reserve, grp->mem_reserve, grp->pref32_reserve,
+grp->pref64_reserve, errp);
+
+if (rc < 0) {
+rpc->parent_class.exit(d);
+return;
+}
+}
+
 static const VMStateDescription vmstate_rp_dev = {
 .name = "pcie-root-port",
 .version_id = 1,
@@ -78,6 +105,11 @@ static const VMStateDescription vmstate_rp_dev = {
 
 static Property gen_rp_props[] = {
 DEFINE_PROP_BOOL("x-migrate-msix", GenPCIERootPort, migrate_msix, true),
+DEFINE_PROP_UINT32("bus-reserve", GenPCIERootPort, bus_reserve, -1),
+DEFINE_PROP_UINT64("io-reserve", GenPCIERootPort, io_reserve, -1),
+DEFINE_PROP_UINT32("mem-reserve", GenPCIERootPort, mem_reserve, -1),
+DEFINE_PROP_UINT32("pref32-reserve", GenPCIERootPort, pref32_reserve, -1),
+DEFINE_PROP_UINT64("pref64-reserve", GenPCIERootPort, pref64_reserve, -1),
 DEFINE_PROP_END_OF_LIST()
 };
 
@@ -92,6 +124,10 @@ static void gen_rp_dev_class_init(ObjectClass *klass, void 
*data)
 dc->desc = "PCI Express Root Port";
 dc->vmsd = _rp_dev;
 dc->props = gen_rp_props;
+
+rpc->parent_realize = dc->realize;
+dc->realize = gen_rp_realize;
+
 rpc->aer_vector = gen_rp_aer_vector;
 rpc->interrupts_init = gen_rp_interrupts_init;
 rpc->interrupts_uninit = gen_rp_interrupts_uninit;
diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
index 1333266..0736014 100644
--- a/include/hw/pci/pcie_port.h
+++ b/include/hw/pci/pcie_port.h
@@ -65,6 +65,7 @@ void pcie_chassis_del_slot(PCIESlot *s);
 
 typedef struct PCIERootPortClass {
 PCIDeviceClass parent_class;
+DeviceRealize parent_realize;
 
 uint8_t (*aer_vector)(const PCIDevice *dev);
 int (*interrupts_init)(PCIDevice *dev, Error **errp);
-- 
2.7.4




[Qemu-devel] [PATCH v5 3/3] pci: enable RedHat PCI bridges to reserve additional resource on PCI init

2017-08-10 Thread Aleksandr Bezzubikov
In case of Red Hat Generic PCIE Root Port reserve additional buses
and/or IO/MEM/PREF space, which values are provided in a vendor-specific 
capability.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 src/fw/dev-pci.h |   2 +-
 src/fw/pciinit.c | 125 +--
 src/hw/pci_ids.h |   3 ++
 3 files changed, 116 insertions(+), 14 deletions(-)

diff --git a/src/fw/dev-pci.h b/src/fw/dev-pci.h
index cf16b2e..99ccc12 100644
--- a/src/fw/dev-pci.h
+++ b/src/fw/dev-pci.h
@@ -38,7 +38,7 @@
 #define PCI_CAP_REDHAT_TYPE_OFFSET  3
 
 /* List of valid Red Hat vendor-specific capability types */
-#define REDHAT_CAP_RESOURCE_RESERVE1
+#define REDHAT_CAP_RESOURCE_RESERVE 1
 
 
 /* Offsets of RESOURCE_RESERVE capability fields */
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 864954f..d9aef56 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -15,6 +15,7 @@
 #include "hw/pcidevice.h" // pci_probe_devices
 #include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
 #include "hw/pci_regs.h" // PCI_COMMAND
+#include "fw/dev-pci.h" // REDHAT_CAP_RESOURCE_RESERVE
 #include "list.h" // struct hlist_node
 #include "malloc.h" // free
 #include "output.h" // dprintf
@@ -522,6 +523,32 @@ static void pci_bios_init_platform(void)
 }
 }
 
+static u8 pci_find_resource_reserve_capability(u16 bdf)
+{
+if (pci_config_readw(bdf, PCI_VENDOR_ID) == PCI_VENDOR_ID_REDHAT &&
+pci_config_readw(bdf, PCI_DEVICE_ID) ==
+PCI_DEVICE_ID_REDHAT_ROOT_PORT) {
+u8 cap = 0;
+do {
+cap = pci_find_capability(bdf, PCI_CAP_ID_VNDR, cap);
+} while (cap &&
+ pci_config_readb(bdf, cap + PCI_CAP_REDHAT_TYPE_OFFSET) !=
+REDHAT_CAP_RESOURCE_RESERVE);
+if (cap) {
+u8 cap_len = pci_config_readb(bdf, cap + PCI_CAP_FLAGS);
+if (cap_len < RES_RESERVE_CAP_SIZE) {
+dprintf(1, "PCI: QEMU resource reserve cap length %d is 
invalid\n",
+cap_len);
+}
+} else {
+dprintf(1, "PCI: invalid QEMU resource reserve cap offset\n");
+}
+return cap;
+} else {
+dprintf(1, "PCI: QEMU resource reserve cap not found\n");
+return 0;
+}
+}
 
 /
  * Bus initialization
@@ -578,9 +605,28 @@ pci_bios_init_bus_rec(int bus, u8 *pci_bus)
 pci_bios_init_bus_rec(secbus, pci_bus);
 
 if (subbus != *pci_bus) {
+u8 res_bus = 0;
+u8 cap = pci_find_resource_reserve_capability(bdf);
+
+if (cap) {
+u32 tmp_res_bus = pci_config_readl(bdf,
+cap + RES_RESERVE_BUS_RES);
+if (tmp_res_bus != (u32)-1) {
+res_bus = tmp_res_bus & 0xFF;
+if ((u8)(res_bus + secbus) < secbus ||
+(u8)(res_bus + secbus) < res_bus) {
+dprintf(1, "PCI: bus_reserve value %d is invalid\n",
+res_bus);
+res_bus = 0;
+}
+}
+res_bus = (*pci_bus > secbus + res_bus) ? *pci_bus
+: secbus + res_bus;
+}
 dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n",
-subbus, *pci_bus);
-subbus = *pci_bus;
+subbus, res_bus);
+subbus = res_bus;
+*pci_bus = res_bus;
 } else {
 dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus);
 }
@@ -844,22 +890,74 @@ static int pci_bios_check_devices(struct pci_bus *busses)
  */
 parent = [0];
 int type;
-u8 pcie_cap = pci_find_capability(s->bus_dev->bdf, PCI_CAP_ID_EXP, 0);
+u16 bdf = s->bus_dev->bdf;
+u8 pcie_cap = pci_find_capability(bdf, PCI_CAP_ID_EXP, 0);
+u8 qemu_cap = pci_find_resource_reserve_capability(bdf);
+
 int hotplug_support = pci_bus_hotplug_support(s, pcie_cap);
 for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
 u64 align = (type == PCI_REGION_TYPE_IO) ?
-PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
+PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
 if (!pci_bridge_has_region(s->bus_dev, type))
 continue;
-if (pci_region_align(>r[type]) > align)
- align = pci_region_align(>r[type]);
-u64 sum = pci_region_sum(>r[type]);
-int resource_optional = pcie_cap && (type == PCI_REGION_TYPE_IO);
-if (!sum && hotplug_support && !resource_optional)
-  

[Qemu-devel] [PATCH v5 2/3] pci: add QEMU-specific PCI capability structure

2017-08-10 Thread Aleksandr Bezzubikov
On PCI init PCI bridge devices may need some
extra info about bus number to reserve, IO, memory and
prefetchable memory limits. QEMU can provide this
with special vendor-specific PCI capability.

This capability is intended to be used only
for Red Hat PCI bridges, i.e. QEMU cooperation.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 src/fw/dev-pci.h | 52 
 1 file changed, 52 insertions(+)
 create mode 100644 src/fw/dev-pci.h

diff --git a/src/fw/dev-pci.h b/src/fw/dev-pci.h
new file mode 100644
index 000..cf16b2e
--- /dev/null
+++ b/src/fw/dev-pci.h
@@ -0,0 +1,52 @@
+#ifndef _PCI_CAP_H
+#define _PCI_CAP_H
+
+#include "types.h"
+
+/*
+ *
+ * QEMU-specific vendor(Red Hat)-specific capability.
+ * It's intended to provide some hints for firmware to init PCI devices.
+ *
+ * Its structure is shown below:
+ *
+ * Header:
+ *
+ * u8 id;   Standard PCI Capability Header field
+ * u8 next; Standard PCI Capability Header field
+ * u8 len;  Standard PCI Capability Header field
+ * u8 type; Red Hat vendor-specific capability type
+ * Data:
+ *
+ * u32 bus_res; minimum bus number to reserve;
+ *  this is necessary for PCI Express Root Ports
+ *  to support PCI bridges hotplug
+ * u64 io;  IO space to reserve
+ * u32 mem; non-prefetchable memory to reserve
+ *
+ * this two fields are mutually exclusive:
+ * u32 prefetchable_mem_32; prefetchable memory to reserve (32-bit MMIO)
+ * u64 prefetchable_mem_64; prefetchable memory to reserve (64-bit MMIO)
+ *
+ *
+ * If any field value in Data section is 0xFF...F,
+ * it means that such kind of reservation is not needed and must be ignored.
+ *
+*/
+
+/* Offset of vendor-specific capability type field */
+#define PCI_CAP_REDHAT_TYPE_OFFSET  3
+
+/* List of valid Red Hat vendor-specific capability types */
+#define REDHAT_CAP_RESOURCE_RESERVE1
+
+
+/* Offsets of RESOURCE_RESERVE capability fields */
+#define RES_RESERVE_BUS_RES4
+#define RES_RESERVE_IO 8
+#define RES_RESERVE_MEM16
+#define RES_RESERVE_PREF_MEM_3220
+#define RES_RESERVE_PREF_MEM_6424
+#define RES_RESERVE_CAP_SIZE   32
+
+#endif /* _PCI_CAP_H */
-- 
2.7.4




[Qemu-devel] [PATCH v5 0/3] Red Hat PCI bridge resource reserve capability (was: Allow RedHat PCI bridges reserve more buses than necessary during init)

2017-08-10 Thread Aleksandr Bezzubikov
Now PCI bridges get a bus range number on a system init,
basing on currently plugged devices. That's why when one wants to hotplug 
another bridge,
it needs his child bus, which the parent is unable to provide (speaking about 
virtual device).
The suggested workaround is to have vendor-specific capability in Red Hat PCI 
bridges
that contains number of additional bus to reserve (as well as IO/MEM/PREF space 
limit hints) 
on BIOS PCI init.
So this capability is intended only for pure QEMU->SeaBIOS usage.

Considering all aforesaid, this series is directly connected with
QEMU series "Generic PCIE-PCI Bridge".

Although the new PCI capability is supposed to contain various limits along with
bus number to reserve, now only its full layout is proposed. And
only bus_reserve field is used in QEMU and BIOS. Limits usage
is still a subject for implementation as now
the main goal of this series to provide necessary support from the 
firmware side to PCIE-PCI bridge hotplug. 

Changes v4->v5:
1. Rename capability-related #defines
2. Move capability IO/MEM/PREF fields values usage to the regions creation 
stage (addresses Marcel's comment)
3. The capability layout change: separate pref_mem into pref_mem_32 and 
pref_mem_64 fields (QEMU side has the same changes) (addresses Laszlo's comment)
4. Extract the capability lookup and check to the separate function (addresses 
Marcel's comment)
- despite of Marcel's comment do not extract field check for -1 since 
it increases code length
  and doesn't look nice because of different field types 
5. Fix the capability's comment (addresses Marcel's comment)
6. Fix the 3rd patch message

Changes v3->v4:
1. Use all QEMU PCI capability fields - addresses Michael's comment
2. Changes of the capability layout (QEMU side has the same changes):
- change reservation fields types: bus_res - uint32_t, others - uint64_t
- interpret -1 value as 'ignore'

Changes v2->v3:
1. Merge commit 2 (Red Hat vendor ID) into commit 4 - addresses Marcel's 
comment,
and add Generic PCIE Root Port device ID - addresses Michael's comment.
2. Changes of the capability layout  (QEMU side has the same changes):
- add 'type' field to distinguish multiple 
RedHat-specific capabilities - addresses Michael's comment
- do not mimiс PCI Config space register layout, but use mutually 
exclusive differently
sized fields for IO and prefetchable memory limits - addresses 
Laszlo's comment
- use defines instead of structure and offsetof - addresses Michael's 
comment
3. Interpret 'bus_reserve' field as a minimum necessary
 range to reserve - addresses Gerd's comment
4. pci_find_capability moved to pci.c - addresses Kevin's comment
5. Move capability layout header to src/fw/dev-pci.h - addresses Kevin's comment
6. Add the capability documentation - addresses Michael's comment
7. Add capability length and bus_reserve field sanity checks - addresses 
Michael's comment

Changes v1->v2:
1. New #define for Red Hat vendor added (addresses Konrad's comment).
2. Refactored pci_find_capability function (addresses Marcel's comment).
3. Capability reworked:
- data type added;
- reserve space in a structure for IO, memory and 
  prefetchable memory limits.

Aleksandr Bezzubikov (3):
  pci: refactor pci_find_capapibilty to get bdf as the first argument
instead of the whole pci_device
  pci: add QEMU-specific PCI capability structure
  pci: enable RedHat PCI bridges to reserve additional resource on PCI
init

 src/fw/dev-pci.h|  52 +
 src/fw/pciinit.c| 127 ++--
 src/hw/pci.c|  25 +++
 src/hw/pci.h|   1 +
 src/hw/pci_ids.h|   3 ++
 src/hw/pcidevice.c  |  24 --
 src/hw/pcidevice.h  |   1 -
 src/hw/virtio-pci.c |   6 +--
 8 files changed, 197 insertions(+), 42 deletions(-)
 create mode 100644 src/fw/dev-pci.h

-- 
2.7.4




Re: [Qemu-devel] [PATCH v4 5/5] docs: update documentation considering PCIE-PCI bridge

2017-08-09 Thread Aleksandr Bezzubikov
2017-08-09 13:18 GMT+03:00 Laszlo Ersek <ler...@redhat.com>:
> On 08/08/17 21:21, Aleksandr Bezzubikov wrote:
>> 2017-08-08 18:11 GMT+03:00 Laszlo Ersek <ler...@redhat.com>:
>>> one comment below
>>>
>>> On 08/05/17 22:27, Aleksandr Bezzubikov wrote:
>>>
>>>> +Capability layout (defined in include/hw/pci/pci_bridge.h):
>>>> +
>>>> +uint8_t id; Standard PCI capability header field
>>>> +uint8_t next;   Standard PCI capability header field
>>>> +uint8_t len;Standard PCI vendor-specific capability header field
>>>> +
>>>> +uint8_t type;   Red Hat vendor-specific capability type
>>>> +List of currently existing types:
>>>> +QEMU_RESERVE = 1
>>>> +
>>>> +
>>>> +uint32_t bus_res;   Minimum number of buses to reserve
>>>> +
>>>> +uint64_t io;IO space to reserve
>>>> +uint64_t memNon-prefetchable memory to reserve
>>>> +uint64_t mem_pref;  Prefetchable memory to reserve
>>>
>>> (I apologize if I missed any concrete points from the past messages
>>> regarding this structure.)
>>>
>>> How is the firmware supposed to know whether the prefetchable MMIO
>>> reservation should be made in 32-bit or 64-bit address space? If we
>>> reserve prefetchable MMIO outside of the 32-bit address space, then
>>> hot-plugging a device without 64-bit MMIO support could fail.
>>>
>>> My earlier request, to distinguish "prefetchable_32" from
>>> "prefetchable_64" (mutually exclusively), was so that firmware would
>>> know whether to restrict the MMIO reservation to 32-bit address
>>> space.
>>
>> IIUC now (in SeaBIOS at least) we just assign this PREF registers
>> unconditionally,
>> so the decision about the mode can be made basing on !=0
>> UPPER_PREF_LIMIT register.
>> My idea was the same - we can just check if the value doesn't fit into
>> 16-bit (PREF_LIMIT reg size, 32-bit MMIO). Do we really need separate
>> fields for that?
>
> The PciBusDxe driver in edk2 tracks 32-bit and 64-bit MMIO resources
> separately from each other, and other (independent) logic exists in it
> that, on some conditions, allocates 64-bit MMIO BARs from 32-bit address
> space. This is just to say that the distinction is intentional in
> PciBusDxe.
>
> Furthermore, the Platform Init spec v1.6 says the following (this is
> what OVMF will have to comply with, in the "platform hook" called by
> PciBusDxe):
>
>> 12.6 PCI Hot Plug PCI Initialization Protocol
>> EFI_PCI_HOT_PLUG_INIT_PROTOCOL.GetResourcePadding()
>> ...
>> Padding  The amount of resource padding that is required by the PCI
>>  bus under the control of the specified HPC. Because the
>>  caller does not know the size of this buffer, this buffer is
>>  allocated by the callee and freed by the caller.
>> ...
>> The padding is returned in the form of ACPI (2.0 & 3.0) resource
>> descriptors. The exact definition of each of the fields is the same as
>> in the
>> EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.SubmitResources()
>> function. See the section 10.8 for the definition of this function.
>
> Following that pointer:
>
>> 10.8 PCI HostBridge Code Definitions
>> 10.8.2 PCI Host Bridge Resource Allocation Protocol
>>
>> Table 8. ACPI 2.0 & 3.0 QWORD Address Space Descriptor Usage
>>
>> ByteByteData  Description
>> Offset  Length
>> ...
>> 0x030x01  Resource type:
>> 0: Memory range
>> 1: I/O range
>> 2: Bus number range
>> ...
>> 0x050x01  Type-specific flags. Ignored except as defined
>>   in Table 3-3 and Table 3-4 below.
>>
>> 0x060x08  Address Space Granularity. Used to differentiate
>>   between a 32-bit memory request and a 64-bit
>>   memory request. For a 32-bit memory request,
>>   this field should be set to 32. For a 64-bit
>>   memory request, this field should be set to 64.
>>   Ignored for I/O and bus resource requests.
>>   Ignored during GetProposedResources().
>
> The "Table 3-3" and "Table 3-4" references under "Type-specific flags"
> are out of date (spec bu

Re: [Qemu-devel] [PATCH v4 4/5] hw/pci: add QEMU-specific PCI capability to the Generic PCI Express Root Port

2017-08-08 Thread Aleksandr Bezzubikov
2017-08-08 22:54 GMT+03:00 Michael S. Tsirkin <m...@redhat.com>:
> On Sat, Aug 05, 2017 at 11:27:37PM +0300, Aleksandr Bezzubikov wrote:
>> To enable hotplugging of a newly created pcie-pci-bridge,
>> we need to tell firmware (SeaBIOS in this case)
>
> Why SeaBIOS is this case?
>

It is the default BIOS for QEMU and therefore it is the best place to
try out a new feature like this reservation cap.

>> to reserve
>> additional buses or IO/MEM/PREF space for pcie-root-port.
>> Additional bus reservation allows us to hotplug pcie-pci-bridge into this 
>> root port.
>> The number of buses to reserve is provided to the device via a corresponding
>> property, and to the firmware via new PCI capability.
>> The properties' default value is -1 to keep default behavior unchanged.
>>
>> Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
>> ---
>>  hw/pci-bridge/gen_pcie_root_port.c | 33 +
>>  include/hw/pci/pcie_port.h |  1 +
>>  2 files changed, 34 insertions(+)
>>
>> diff --git a/hw/pci-bridge/gen_pcie_root_port.c 
>> b/hw/pci-bridge/gen_pcie_root_port.c
>> index cb694d6..ff8d04c 100644
>> --- a/hw/pci-bridge/gen_pcie_root_port.c
>> +++ b/hw/pci-bridge/gen_pcie_root_port.c
>> @@ -16,6 +16,8 @@
>>  #include "hw/pci/pcie_port.h"
>>
>>  #define TYPE_GEN_PCIE_ROOT_PORT"pcie-root-port"
>> +#define GEN_PCIE_ROOT_PORT(obj) \
>> +OBJECT_CHECK(GenPCIERootPort, (obj), TYPE_GEN_PCIE_ROOT_PORT)
>>
>>  #define GEN_PCIE_ROOT_PORT_AER_OFFSET   0x100
>>  #define GEN_PCIE_ROOT_PORT_MSIX_NR_VECTOR   1
>> @@ -26,6 +28,12 @@ typedef struct GenPCIERootPort {
>>  /*< public >*/
>>
>>  bool migrate_msix;
>> +
>> +/* additional buses to reserve on firmware init */
>> +uint32_t bus_reserve;
>> +uint64_t io_reserve;
>> +uint64_t mem_reserve;
>> +uint64_t pref_reserve;
>>  } GenPCIERootPort;
>>
>>  static uint8_t gen_rp_aer_vector(const PCIDevice *d)
>> @@ -60,6 +68,23 @@ static bool gen_rp_test_migrate_msix(void *opaque, int 
>> version_id)
>>  return rp->migrate_msix;
>>  }
>>
>> +static void gen_rp_realize(DeviceState *dev, Error **errp)
>> +{
>> +PCIDevice *d = PCI_DEVICE(dev);
>> +GenPCIERootPort *grp = GEN_PCIE_ROOT_PORT(d);
>> +PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(d);
>> +
>> +rpc->parent_realize(dev, errp);
>> +
>> +int rc = pci_bridge_qemu_reserve_cap_init(d, 0, grp->bus_reserve,
>> +grp->io_reserve, grp->mem_reserve, grp->pref_reserve, errp);
>
> You have to skip adding this capability by default to avoid
> breaking migration to/from old QEMU. A simple way to do this is
> to check whether any have been specified as != -1.
>

Agreed, I can't understand how the capability that is brand new
and unused by another code except mine can break migration.

>> +
>> +if (rc < 0) {
>> +rpc->parent_class.exit(d);
>> +return;
>> +}
>> +}
>> +
>>  static const VMStateDescription vmstate_rp_dev = {
>>  .name = "pcie-root-port",
>>  .version_id = 1,
>> @@ -78,6 +103,10 @@ static const VMStateDescription vmstate_rp_dev = {
>>
>>  static Property gen_rp_props[] = {
>>  DEFINE_PROP_BOOL("x-migrate-msix", GenPCIERootPort, migrate_msix, true),
>> +DEFINE_PROP_UINT32("bus-reserve", GenPCIERootPort, bus_reserve, -1),
>> +DEFINE_PROP_UINT64("io-reserve", GenPCIERootPort, io_reserve, -1),
>> +DEFINE_PROP_UINT64("mem-reserve", GenPCIERootPort, mem_reserve, -1),
>> +DEFINE_PROP_UINT64("pref-reserve", GenPCIERootPort, pref_reserve, -1),
>>  DEFINE_PROP_END_OF_LIST()
>>  };
>>
>> @@ -92,6 +121,10 @@ static void gen_rp_dev_class_init(ObjectClass *klass, 
>> void *data)
>>  dc->desc = "PCI Express Root Port";
>>  dc->vmsd = _rp_dev;
>>  dc->props = gen_rp_props;
>> +
>> +rpc->parent_realize = dc->realize;
>> +dc->realize = gen_rp_realize;
>> +
>>  rpc->aer_vector = gen_rp_aer_vector;
>>  rpc->interrupts_init = gen_rp_interrupts_init;
>>  rpc->interrupts_uninit = gen_rp_interrupts_uninit;
>> diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
>> index 1333266..0736014 100644
>> --- a/include/hw/pci/pcie_port.h
>> +++ b/include/hw/pci/pcie_port.h
>> @@ -65,6 +65,7 @@ void pcie_chassis_del_slot(PCIESlot *s);
>>
>>  typedef struct PCIERootPortClass {
>>  PCIDeviceClass parent_class;
>> +DeviceRealize parent_realize;
>>
>>  uint8_t (*aer_vector)(const PCIDevice *dev);
>>  int (*interrupts_init)(PCIDevice *dev, Error **errp);
>> --
>> 2.7.4



-- 
Aleksandr Bezzubikov



Re: [Qemu-devel] [PATCH v4 5/5] docs: update documentation considering PCIE-PCI bridge

2017-08-08 Thread Aleksandr Bezzubikov
2017-08-08 18:11 GMT+03:00 Laszlo Ersek <ler...@redhat.com>:
> one comment below
>
> On 08/05/17 22:27, Aleksandr Bezzubikov wrote:
>
>> +Capability layout (defined in include/hw/pci/pci_bridge.h):
>> +
>> +uint8_t id; Standard PCI capability header field
>> +uint8_t next;   Standard PCI capability header field
>> +uint8_t len;Standard PCI vendor-specific capability header field
>> +
>> +uint8_t type;   Red Hat vendor-specific capability type
>> +List of currently existing types:
>> +QEMU_RESERVE = 1
>> +
>> +
>> +uint32_t bus_res;   Minimum number of buses to reserve
>> +
>> +uint64_t io;IO space to reserve
>> +uint64_t memNon-prefetchable memory to reserve
>> +uint64_t mem_pref;  Prefetchable memory to reserve
>
> (I apologize if I missed any concrete points from the past messages
> regarding this structure.)
>
> How is the firmware supposed to know whether the prefetchable MMIO
> reservation should be made in 32-bit or 64-bit address space? If we
> reserve prefetchable MMIO outside of the 32-bit address space, then
> hot-plugging a device without 64-bit MMIO support could fail.
>
> My earlier request, to distinguish "prefetchable_32" from
> "prefetchable_64" (mutually exclusively), was so that firmware would
> know whether to restrict the MMIO reservation to 32-bit address space.

IIUC now (in SeaBIOS at least) we just assign this PREF registers
unconditionally,
so the decision about the mode can be made basing on !=0
UPPER_PREF_LIMIT register.
My idea was the same - we can just check if the value doesn't fit into
16-bit (PREF_LIMIT reg size, 32-bit MMIO). Do we really need separate
fields for that?

>
> This is based on an earlier email from Alex to me:
>
> On 10/03/16 18:01, Alex Williamson wrote:
>> I don't think there's such a thing as a 64-bit non-prefetchable
>> aperture.  In fact, there are not separate 32 and 64 bit prefetchable
>> apertures.  The apertures are:
>>
>> I/O base/limit - (default 16bit, may be 32bit)
>> Memory base/limit - (32bit only, non-prefetchable)
>> Prefetchable Memory base/limit - (default 32bit, may be 64bit)
>>
>> This is according to Table 3-2 in the PCI-to-PCI bridge spec rev 1.2.
>
> I don't care much about the 16-bit vs. 32-bit IO difference (that's
> entirely academic and the Platform Spec init doesn't even provide a way
> for OVMF to express such a difference). However, the optional
> restriction to 32-bit matters for the prefetchable MMIO aperture.
>
> Other than this, the patch looks good to me, and I'm ready to R-b.
>
> Thanks!
> Laszlo



-- 
Aleksandr Bezzubikov



[Qemu-devel] [PATCH v4 3/3] pci: enable RedHat PCI bridges to reserve additional buses on PCI init

2017-08-05 Thread Aleksandr Bezzubikov
In case of Red Hat Generic PCIE Root Port reserve additional buses,
which number is provided in a vendor-specific capability.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 src/fw/pciinit.c | 69 
 src/hw/pci_ids.h |  3 +++
 2 files changed, 68 insertions(+), 4 deletions(-)

diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 864954f..d241d66 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -15,6 +15,7 @@
 #include "hw/pcidevice.h" // pci_probe_devices
 #include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
 #include "hw/pci_regs.h" // PCI_COMMAND
+#include "fw/dev-pci.h" // qemu_pci_cap
 #include "list.h" // struct hlist_node
 #include "malloc.h" // free
 #include "output.h" // dprintf
@@ -578,9 +579,42 @@ pci_bios_init_bus_rec(int bus, u8 *pci_bus)
 pci_bios_init_bus_rec(secbus, pci_bus);
 
 if (subbus != *pci_bus) {
+u8 res_bus = 0;
+if (pci_config_readw(bdf, PCI_VENDOR_ID) == PCI_VENDOR_ID_REDHAT &&
+pci_config_readw(bdf, PCI_DEVICE_ID) ==
+PCI_DEVICE_ID_REDHAT_ROOT_PORT) {
+u8 cap;
+do {
+cap = pci_find_capability(bdf, PCI_CAP_ID_VNDR, 0);
+} while (cap &&
+ pci_config_readb(bdf, cap + PCI_CAP_REDHAT_TYPE) !=
+REDHAT_CAP_TYPE_QEMU);
+if (cap) {
+u8 cap_len = pci_config_readb(bdf, cap + PCI_CAP_FLAGS);
+if (cap_len != QEMU_PCI_CAP_SIZE) {
+dprintf(1, "PCI: QEMU cap length %d is invalid\n",
+cap_len);
+} else {
+u32 tmp_res_bus = pci_config_readl(bdf,
+   cap + QEMU_PCI_CAP_BUS_RES);
+if (tmp_res_bus != (u32)-1) {
+res_bus = tmp_res_bus & 0xFF;
+if ((u8)(res_bus + secbus) < secbus ||
+(u8)(res_bus + secbus) < res_bus) {
+dprintf(1, "PCI: bus_reserve value %d is 
invalid\n",
+res_bus);
+res_bus = 0;
+}
+}
+}
+}
+res_bus = (*pci_bus > secbus + res_bus) ? *pci_bus
+  : secbus + res_bus;
+}
 dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n",
-subbus, *pci_bus);
-subbus = *pci_bus;
+subbus, res_bus);
+subbus = res_bus;
+*pci_bus = res_bus;
 } else {
 dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus);
 }
@@ -951,11 +985,38 @@ pci_region_map_one_entry(struct pci_region_entry *entry, 
u64 addr)
 
 u16 bdf = entry->dev->bdf;
 u64 limit = addr + entry->size - 1;
+
+if (pci_config_readw(bdf, PCI_VENDOR_ID) == PCI_VENDOR_ID_REDHAT &&
+pci_config_readw(bdf, PCI_DEVICE_ID) ==
+PCI_DEVICE_ID_REDHAT_ROOT_PORT) {
+u8 cap;
+do {
+cap = pci_find_capability(bdf, PCI_CAP_ID_VNDR, 0);
+} while (cap &&
+ pci_config_readb(bdf, cap + PCI_CAP_REDHAT_TYPE) !=
+REDHAT_CAP_TYPE_QEMU);
+if (cap) {
+u8 cap_len = pci_config_readb(bdf, cap + PCI_CAP_FLAGS);
+if (cap_len != QEMU_PCI_CAP_SIZE) {
+dprintf(1, "PCI: QEMU cap length %d is invalid\n",
+cap_len);
+} else {
+u32 offset = cap + QEMU_PCI_CAP_LIMITS_OFFSET + entry->type * 
8;
+u64 tmp_limit = (pci_config_readl(bdf, offset) |
+(u64)pci_config_readl(bdf, offset + 4) << 32);
+if (tmp_limit != (u64)-1) {
+tmp_limit += addr - 1;
+limit = (limit > tmp_limit) ? limit : tmp_limit;
+}
+}
+}
+}
+
 if (entry->type == PCI_REGION_TYPE_IO) {
 pci_config_writeb(bdf, PCI_IO_BASE, addr >> PCI_IO_SHIFT);
-pci_config_writew(bdf, PCI_IO_BASE_UPPER16, 0);
+pci_config_writew(bdf, PCI_IO_BASE_UPPER16, limit >> 16);
 pci_config_writeb(bdf, PCI_IO_LIMIT, limit >> PCI_IO_SHIFT);
-pci_config_writew(bdf, PCI_IO_LIMIT_UPPER16, 0);
+pci_config_writew(bdf, PCI_IO_LIMIT_UPPER16, limit >> 16);
 }
 if (entry->type == PCI_REGION_TYPE_MEM) {
 pci_config_writew(bdf, PCI_MEMORY_BASE, addr >>

[Qemu-devel] [PATCH v4 0/3] Allow RedHat PCI bridges reserve more buses than necessary during init

2017-08-05 Thread Aleksandr Bezzubikov
Now PCI bridges get a bus range number on a system init,
basing on currently plugged devices. That's why when one wants to hotplug 
another bridge,
it needs his child bus, which the parent is unable to provide (speaking about 
virtual device).
The suggested workaround is to have vendor-specific capability in Red Hat PCI 
bridges
that contains number of additional bus to reserve (as well as IO/MEM/PREF space 
limit hints) 
on BIOS PCI init.
So this capability is intented only for pure QEMU->SeaBIOS usage.

Considering all aforesaid, this series is directly connected with
QEMU series "Generic PCIE-PCI Bridge".

Although the new PCI capability is supposed to contain various limits along with
bus number to reserve, now only its full layout is proposed. And
only bus_reserve field is used in QEMU and BIOS. Limits usage
is still a subject for implementation as now
the main goal of this series to provide necessary support from the 
firmware side to PCIE-PCI bridge hotplug. 

Changes v3->v4:
1. Use all QEMU PCI capability fields - addresses Michael's comment
2. Changes of the capability layout (QEMU side has the same changes):
- change reservation fields types: bus_res - uint32_t, others - uint64_t
- interpret -1 value as 'ignore'

Changes v2->v3:
1. Merge commit 2 (Red Hat vendor ID) into commit 4 - addresses Marcel's 
comment,
and add Generic PCIE Root Port device ID - addresses Michael's comment.
2. Changes of the capability layout  (QEMU side has the same changes):
- add 'type' field to distinguish multiple 
RedHat-specific capabilities - addresses Michael's comment
- do not mimiс PCI Config space register layout, but use mutually 
exclusive differently
sized fields for IO and prefetchable memory limits - addresses 
Laszlo's comment
- use defines instead of structure and offsetof - addresses Michael's 
comment
3. Interpret 'bus_reserve' field as a minimum necessary
 range to reserve - addresses Gerd's comment
4. pci_find_capability moved to pci.c - addresses Kevin's comment
5. Move capability layout header to src/fw/dev-pci.h - addresses Kevin's comment
6. Add the capability documentation - addresses Michael's comment
7. Add capability length and bus_reserve field sanity checks - addresses 
Michael's comment

Changes v1->v2:
1. New #define for Red Hat vendor added (addresses Konrad's comment).
2. Refactored pci_find_capability function (addresses Marcel's comment).
3. Capability reworked:
- data type added;
- reserve space in a structure for IO, memory and 
  prefetchable memory limits.

Aleksandr Bezzubikov (3):
  pci: refactor pci_find_capapibilty to get bdf as the first argument
instead of the whole pci_device
  pci: add QEMU-specific PCI capability structure
  pci: enable RedHat PCI bridges to reserve additional buses on PCI init

 src/fw/dev-pci.h| 50 
 src/fw/pciinit.c| 73 -
 src/hw/pci.c| 25 ++
 src/hw/pci.h|  1 +
 src/hw/pci_ids.h|  3 +++
 src/hw/pcidevice.c  | 24 --
 src/hw/pcidevice.h  |  1 -
 src/hw/virtio-pci.c |  6 ++---
 8 files changed, 149 insertions(+), 34 deletions(-)
 create mode 100644 src/fw/dev-pci.h

-- 
2.7.4




[Qemu-devel] [PATCH v4 2/3] pci: add QEMU-specific PCI capability structure

2017-08-05 Thread Aleksandr Bezzubikov
On PCI init PCI bridge devices may need some
extra info about bus number to reserve, IO, memory and
prefetchable memory limits. QEMU can provide this
with special vendor-specific PCI capability.

This capability is intended to be used only
for Red Hat PCI bridges, i.e. QEMU cooperation.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 src/fw/dev-pci.h | 50 ++
 1 file changed, 50 insertions(+)
 create mode 100644 src/fw/dev-pci.h

diff --git a/src/fw/dev-pci.h b/src/fw/dev-pci.h
new file mode 100644
index 000..2c8ddb0
--- /dev/null
+++ b/src/fw/dev-pci.h
@@ -0,0 +1,50 @@
+#ifndef _PCI_CAP_H
+#define _PCI_CAP_H
+
+#include "types.h"
+
+/*
+
+QEMU-specific vendor(Red Hat)-specific capability.
+It's intended to provide some hints for firmware to init PCI devices.
+
+Its structure is shown below:
+
+Header:
+
+u8 id;   Standard PCI Capability Header field
+u8 next; Standard PCI Capability Header field
+u8 len;  Standard PCI Capability Header field
+u8 type; Red Hat vendor-specific capability type:
+   now only REDHAT_CAP_TYP_QEMU=1 exists
+Data:
+
+u32 bus_res;minimum bus number to reserve;
+this is necessary for PCI Express Root Ports
+to support PCIE-to-PCI bridge hotplug
+u64 io; IO space to reserve
+u64 mem;non-prefetchable memory space to reserve
+u64 prefetchable_mem;   prefetchable memory space to reserve
+
+If any field value in Data section is -1,
+it means that such kind of reservation
+is not needed and must be ignored.
+
+*/
+
+/* Offset of vendor-specific capability type field */
+#define PCI_CAP_REDHAT_TYPE  3
+
+/* List of valid Red Hat vendor-specific capability types */
+#define REDHAT_CAP_TYPE_QEMU1
+
+
+/* Offsets of QEMU capability fields */
+#define QEMU_PCI_CAP_BUS_RES4
+#define QEMU_PCI_CAP_LIMITS_OFFSET  8
+#define QEMU_PCI_CAP_IO 8
+#define QEMU_PCI_CAP_MEM16
+#define QEMU_PCI_CAP_PREF_MEM   24
+#define QEMU_PCI_CAP_SIZE   32
+
+#endif /* _PCI_CAP_H */
-- 
2.7.4




[Qemu-devel] [PATCH v4 3/5] hw/pci: introduce bridge-only vendor-specific capability to provide some hints to firmware

2017-08-05 Thread Aleksandr Bezzubikov
On PCI init PCI bridges may need some extra info about bus number,
IO, memory and prefetchable memory to reserve. QEMU can provide this
with a special vendor-specific PCI capability.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/pci/pci_bridge.c | 29 +
 include/hw/pci/pci_bridge.h | 21 +
 2 files changed, 50 insertions(+)

diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 720119b..889950d 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -408,6 +408,35 @@ void pci_bridge_map_irq(PCIBridge *br, const char* 
bus_name,
 br->bus_name = bus_name;
 }
 
+
+int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
+  uint32_t bus_reserve, uint64_t io_reserve,
+  uint64_t non_pref_mem_reserve,
+  uint64_t pref_mem_reserve,
+  Error **errp)
+{
+size_t cap_len = sizeof(PCIBridgeQemuCap);
+PCIBridgeQemuCap cap = {
+.len = cap_len,
+.type = REDHAT_PCI_CAP_QEMU_RESERVE,
+.bus_res = bus_reserve,
+.io = io_reserve,
+.mem = non_pref_mem_reserve,
+.mem_pref = pref_mem_reserve
+};
+
+int offset = pci_add_capability(dev, PCI_CAP_ID_VNDR,
+cap_offset, cap_len, errp);
+if (offset < 0) {
+return offset;
+}
+
+memcpy(dev->config + offset + PCI_CAP_FLAGS,
+(char *) + PCI_CAP_FLAGS,
+cap_len - PCI_CAP_FLAGS);
+return 0;
+}
+
 static const TypeInfo pci_bridge_type_info = {
 .name = TYPE_PCI_BRIDGE,
 .parent = TYPE_PCI_DEVICE,
diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h
index ff7cbaa..be565f7 100644
--- a/include/hw/pci/pci_bridge.h
+++ b/include/hw/pci/pci_bridge.h
@@ -67,4 +67,25 @@ void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
 #define  PCI_BRIDGE_CTL_DISCARD_STATUS 0x400   /* Discard timer status */
 #define  PCI_BRIDGE_CTL_DISCARD_SERR   0x800   /* Discard timer SERR# enable */
 
+typedef struct PCIBridgeQemuCap {
+uint8_t id; /* Standard PCI capability header field */
+uint8_t next;   /* Standard PCI capability header field */
+uint8_t len;/* Standard PCI vendor-specific capability header field */
+uint8_t type;   /* Red Hat vendor-specific capability type.
+   Types are defined with REDHAT_PCI_CAP_ prefix */
+
+uint32_t bus_res;   /* Minimum number of buses to reserve */
+uint64_t io;/* IO space to reserve */
+uint64_t mem;   /* Non-prefetchable memory to reserve */
+uint64_t mem_pref;  /* Prefetchable memory to reserve */
+} PCIBridgeQemuCap;
+
+#define REDHAT_PCI_CAP_QEMU_RESERVE 1
+
+int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
+  uint32_t bus_reserve, uint64_t io_reserve,
+  uint64_t non_pref_mem_reserve,
+  uint64_t pref_mem_reserve,
+  Error **errp);
+
 #endif /* QEMU_PCI_BRIDGE_H */
-- 
2.7.4




[Qemu-devel] [PATCH v4 5/5] docs: update documentation considering PCIE-PCI bridge

2017-08-05 Thread Aleksandr Bezzubikov
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 docs/pcie.txt|  49 +++--
 docs/pcie_pci_bridge.txt | 110 +++
 2 files changed, 136 insertions(+), 23 deletions(-)
 create mode 100644 docs/pcie_pci_bridge.txt

diff --git a/docs/pcie.txt b/docs/pcie.txt
index 5bada24..76b85ec 100644
--- a/docs/pcie.txt
+++ b/docs/pcie.txt
@@ -46,7 +46,7 @@ Place only the following kinds of devices directly on the 
Root Complex:
 (2) PCI Express Root Ports (ioh3420), for starting exclusively PCI Express
 hierarchies.
 
-(3) DMI-PCI Bridges (i82801b11-bridge), for starting legacy PCI
+(3) PCI Express to PCI Bridge (pcie-pci-bridge), for starting legacy PCI
 hierarchies.
 
 (4) Extra Root Complexes (pxb-pcie), if multiple PCI Express Root Buses
@@ -55,18 +55,18 @@ Place only the following kinds of devices directly on the 
Root Complex:
pcie.0 bus

 |||  |
-   ---   --   --   --
-   | PCI Dev |   | PCIe Root Port |   | DMI-PCI Bridge |   |  pxb-pcie  |
-   ---   --   --   --
+   ---   --   ---   --
+   | PCI Dev |   | PCIe Root Port |   | PCIe-PCI Bridge |   |  pxb-pcie  |
+   ---   --   ---   --
 
 2.1.1 To plug a device into pcie.0 as a Root Complex Integrated Endpoint use:
   -device [,bus=pcie.0]
 2.1.2 To expose a new PCI Express Root Bus use:
   -device pxb-pcie,id=pcie.1,bus_nr=x[,numa_node=y][,addr=z]
-  Only PCI Express Root Ports and DMI-PCI bridges can be connected
-  to the pcie.1 bus:
+  PCI Express Root Ports and PCI Express to PCI bridges can be
+  connected to the pcie.1 bus:
   -device 
ioh3420,id=root_port1[,bus=pcie.1][,chassis=x][,slot=y][,addr=z]
 \
-  -device i82801b11-bridge,id=dmi_pci_bridge1,bus=pcie.1
+  -device pcie-pci-bridge,id=pcie_pci_bridge1,bus=pcie.1
 
 
 2.2 PCI Express only hierarchy
@@ -130,24 +130,24 @@ Notes:
 Legacy PCI devices can be plugged into pcie.0 as Integrated Endpoints,
 but, as mentioned in section 5, doing so means the legacy PCI
 device in question will be incapable of hot-unplugging.
-Besides that use DMI-PCI Bridges (i82801b11-bridge) in combination
-with PCI-PCI Bridges (pci-bridge) to start PCI hierarchies.
+Besides that use PCI Express to PCI Bridges (pcie-pci-bridge) in
+combination with PCI-PCI Bridges (pci-bridge) to start PCI hierarchies.
 
-Prefer flat hierarchies. For most scenarios a single DMI-PCI Bridge
+Prefer flat hierarchies. For most scenarios a single PCI Express to PCI Bridge
 (having 32 slots) and several PCI-PCI Bridges attached to it
 (each supporting also 32 slots) will support hundreds of legacy devices.
-The recommendation is to populate one PCI-PCI Bridge under the DMI-PCI Bridge
-until is full and then plug a new PCI-PCI Bridge...
+The recommendation is to populate one PCI-PCI Bridge under the
+PCI Express to PCI Bridge until is full and then plug a new PCI-PCI Bridge...
 
pcie.0 bus
--
 ||
-   ---   --
-   | PCI Dev |   | DMI-PCI BRIDGE |
-   ----
+   ---   ---
+   | PCI Dev |   | PCIe-PCI Bridge |
+   ---   ---
||
   ----
-  | PCI-PCI Bridge || PCI-PCI Bridge |   ...
+  | PCI-PCI Bridge || PCI-PCI Bridge |
   ----
  |   |
   --- ---
@@ -157,11 +157,11 @@ until is full and then plug a new PCI-PCI Bridge...
 2.3.1 To plug a PCI device into pcie.0 as an Integrated Endpoint use:
   -device [,bus=pcie.0]
 2.3.2 Plugging a PCI device into a PCI-PCI Bridge:
-  -device i82801b11-bridge,id=dmi_pci_bridge1[,bus=pcie.0] 
   \
-  -device 
pci-bridge,id=pci_bridge1,bus=dmi_pci_bridge1[,chassis_nr=x][,addr=y]   \
+  -device pcie-pci-bridge,id=pcie_pci_bridge1[,bus=pcie.0] \
+  -device 
pci-bridge,id=pci_bridge1,bus=pcie_pci_bridge1[,chassis_nr=x][,addr=y] \
   -device ,bus=pci_bridge1[,addr=x]
   Note that 'addr' cannot be 0 unless shpc=off parameter is passed to
-  the PCI Bridge.
+  the PCI Bridge/PCI Express to PCI Bridge.
 
 3. IO space issues
 ===
@@ -219,14 +219,16 @@ do not support hot-pl

[Qemu-devel] [PATCH v4 4/5] hw/pci: add QEMU-specific PCI capability to the Generic PCI Express Root Port

2017-08-05 Thread Aleksandr Bezzubikov
To enable hotplugging of a newly created pcie-pci-bridge,
we need to tell firmware (SeaBIOS in this case) to reserve
additional buses or IO/MEM/PREF space for pcie-root-port.
Additional bus reservation allows us to hotplug pcie-pci-bridge into this root 
port.
The number of buses to reserve is provided to the device via a corresponding
property, and to the firmware via new PCI capability.
The properties' default value is -1 to keep default behavior unchanged.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/pci-bridge/gen_pcie_root_port.c | 33 +
 include/hw/pci/pcie_port.h |  1 +
 2 files changed, 34 insertions(+)

diff --git a/hw/pci-bridge/gen_pcie_root_port.c 
b/hw/pci-bridge/gen_pcie_root_port.c
index cb694d6..ff8d04c 100644
--- a/hw/pci-bridge/gen_pcie_root_port.c
+++ b/hw/pci-bridge/gen_pcie_root_port.c
@@ -16,6 +16,8 @@
 #include "hw/pci/pcie_port.h"
 
 #define TYPE_GEN_PCIE_ROOT_PORT"pcie-root-port"
+#define GEN_PCIE_ROOT_PORT(obj) \
+OBJECT_CHECK(GenPCIERootPort, (obj), TYPE_GEN_PCIE_ROOT_PORT)
 
 #define GEN_PCIE_ROOT_PORT_AER_OFFSET   0x100
 #define GEN_PCIE_ROOT_PORT_MSIX_NR_VECTOR   1
@@ -26,6 +28,12 @@ typedef struct GenPCIERootPort {
 /*< public >*/
 
 bool migrate_msix;
+
+/* additional buses to reserve on firmware init */
+uint32_t bus_reserve;
+uint64_t io_reserve;
+uint64_t mem_reserve;
+uint64_t pref_reserve;
 } GenPCIERootPort;
 
 static uint8_t gen_rp_aer_vector(const PCIDevice *d)
@@ -60,6 +68,23 @@ static bool gen_rp_test_migrate_msix(void *opaque, int 
version_id)
 return rp->migrate_msix;
 }
 
+static void gen_rp_realize(DeviceState *dev, Error **errp)
+{
+PCIDevice *d = PCI_DEVICE(dev);
+GenPCIERootPort *grp = GEN_PCIE_ROOT_PORT(d);
+PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(d);
+
+rpc->parent_realize(dev, errp);
+
+int rc = pci_bridge_qemu_reserve_cap_init(d, 0, grp->bus_reserve,
+grp->io_reserve, grp->mem_reserve, grp->pref_reserve, errp);
+
+if (rc < 0) {
+rpc->parent_class.exit(d);
+return;
+}
+}
+
 static const VMStateDescription vmstate_rp_dev = {
 .name = "pcie-root-port",
 .version_id = 1,
@@ -78,6 +103,10 @@ static const VMStateDescription vmstate_rp_dev = {
 
 static Property gen_rp_props[] = {
 DEFINE_PROP_BOOL("x-migrate-msix", GenPCIERootPort, migrate_msix, true),
+DEFINE_PROP_UINT32("bus-reserve", GenPCIERootPort, bus_reserve, -1),
+DEFINE_PROP_UINT64("io-reserve", GenPCIERootPort, io_reserve, -1),
+DEFINE_PROP_UINT64("mem-reserve", GenPCIERootPort, mem_reserve, -1),
+DEFINE_PROP_UINT64("pref-reserve", GenPCIERootPort, pref_reserve, -1),
 DEFINE_PROP_END_OF_LIST()
 };
 
@@ -92,6 +121,10 @@ static void gen_rp_dev_class_init(ObjectClass *klass, void 
*data)
 dc->desc = "PCI Express Root Port";
 dc->vmsd = _rp_dev;
 dc->props = gen_rp_props;
+
+rpc->parent_realize = dc->realize;
+dc->realize = gen_rp_realize;
+
 rpc->aer_vector = gen_rp_aer_vector;
 rpc->interrupts_init = gen_rp_interrupts_init;
 rpc->interrupts_uninit = gen_rp_interrupts_uninit;
diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
index 1333266..0736014 100644
--- a/include/hw/pci/pcie_port.h
+++ b/include/hw/pci/pcie_port.h
@@ -65,6 +65,7 @@ void pcie_chassis_del_slot(PCIESlot *s);
 
 typedef struct PCIERootPortClass {
 PCIDeviceClass parent_class;
+DeviceRealize parent_realize;
 
 uint8_t (*aer_vector)(const PCIDevice *dev);
 int (*interrupts_init)(PCIDevice *dev, Error **errp);
-- 
2.7.4




[Qemu-devel] [PATCH v4 2/5] hw/pci: introduce pcie-pci-bridge device

2017-08-05 Thread Aleksandr Bezzubikov
Introduce a new PCIExpress-to-PCI Bridge device,
which is a hot-pluggable PCI Express device and
supports devices hot-plug with SHPC.

This device is intended to replace the DMI-to-PCI
Bridge in an overwhelming majority of use-cases.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/pci-bridge/Makefile.objs |   2 +-
 hw/pci-bridge/pcie_pci_bridge.c | 212 
 include/hw/pci/pci.h|   1 +
 3 files changed, 214 insertions(+), 1 deletion(-)
 create mode 100644 hw/pci-bridge/pcie_pci_bridge.c

diff --git a/hw/pci-bridge/Makefile.objs b/hw/pci-bridge/Makefile.objs
index c4683cf..666db37 100644
--- a/hw/pci-bridge/Makefile.objs
+++ b/hw/pci-bridge/Makefile.objs
@@ -1,4 +1,4 @@
-common-obj-y += pci_bridge_dev.o
+common-obj-y += pci_bridge_dev.o pcie_pci_bridge.o
 common-obj-$(CONFIG_PCIE_PORT) += pcie_root_port.o gen_pcie_root_port.o
 common-obj-$(CONFIG_PXB) += pci_expander_bridge.o
 common-obj-$(CONFIG_XIO3130) += xio3130_upstream.o xio3130_downstream.o
diff --git a/hw/pci-bridge/pcie_pci_bridge.c b/hw/pci-bridge/pcie_pci_bridge.c
new file mode 100644
index 000..4127725
--- /dev/null
+++ b/hw/pci-bridge/pcie_pci_bridge.c
@@ -0,0 +1,212 @@
+/*
+ * QEMU Generic PCIE-PCI Bridge
+ *
+ * Copyright (c) 2017 Aleksandr Bezzubikov
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/shpc.h"
+#include "hw/pci/slotid_cap.h"
+
+typedef struct PCIEPCIBridge {
+/*< private >*/
+PCIBridge parent_obj;
+
+OnOffAuto msi;
+MemoryRegion shpc_bar;
+/*< public >*/
+} PCIEPCIBridge;
+
+#define TYPE_PCIE_PCI_BRIDGE_DEV  "pcie-pci-bridge"
+#define PCIE_PCI_BRIDGE_DEV(obj) \
+OBJECT_CHECK(PCIEPCIBridge, (obj), TYPE_PCIE_PCI_BRIDGE_DEV)
+
+static void pcie_pci_bridge_realize(PCIDevice *d, Error **errp)
+{
+PCIBridge *br = PCI_BRIDGE(d);
+PCIEPCIBridge *pcie_br = PCIE_PCI_BRIDGE_DEV(d);
+int rc, pos;
+
+pci_bridge_initfn(d, TYPE_PCI_BUS);
+
+d->config[PCI_INTERRUPT_PIN] = 0x1;
+memory_region_init(_br->shpc_bar, OBJECT(d), "shpc-bar",
+   shpc_bar_size(d));
+rc = shpc_init(d, >sec_bus, _br->shpc_bar, 0, errp);
+if (rc) {
+goto error;
+}
+
+rc = pcie_cap_init(d, 0, PCI_EXP_TYPE_PCI_BRIDGE, 0, errp);
+if (rc < 0) {
+goto cap_error;
+}
+
+pos = pci_add_capability(d, PCI_CAP_ID_PM, 0, PCI_PM_SIZEOF, errp);
+if (pos < 0) {
+goto pm_error;
+}
+d->exp.pm_cap = pos;
+pci_set_word(d->config + pos + PCI_PM_PMC, 0x3);
+
+pcie_cap_arifwd_init(d);
+pcie_cap_deverr_init(d);
+
+rc = pcie_aer_init(d, PCI_ERR_VER, 0x100, PCI_ERR_SIZEOF, errp);
+if (rc < 0) {
+goto aer_error;
+}
+
+if (pcie_br->msi != ON_OFF_AUTO_OFF) {
+rc = msi_init(d, 0, 1, true, true, errp);
+if (rc < 0) {
+goto msi_error;
+}
+}
+pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
+ PCI_BASE_ADDRESS_MEM_TYPE_64, _br->shpc_bar);
+return;
+
+msi_error:
+pcie_aer_exit(d);
+aer_error:
+pm_error:
+pcie_cap_exit(d);
+cap_error:
+shpc_free(d);
+error:
+pci_bridge_exitfn(d);
+}
+
+static void pcie_pci_bridge_exit(PCIDevice *d)
+{
+PCIEPCIBridge *bridge_dev = PCIE_PCI_BRIDGE_DEV(d);
+pcie_cap_exit(d);
+shpc_cleanup(d, _dev->shpc_bar);
+pci_bridge_exitfn(d);
+}
+
+static void pcie_pci_bridge_reset(DeviceState *qdev)
+{
+PCIDevice *d = PCI_DEVICE(qdev);
+pci_bridge_reset(qdev);
+msi_reset(d);
+shpc_reset(d);
+}
+
+static void pcie_pci_brid

[Qemu-devel] [PATCH v4 1/5] hw/i386: allow SHPC for Q35 machine

2017-08-05 Thread Aleksandr Bezzubikov
Unmask previously masked SHPC feature in _OSC method.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>
---
 hw/i386/acpi-build.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index b9c245c..98dd424 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1862,9 +1862,9 @@ static Aml *build_q35_osc_method(void)
 
 /*
  * Always allow native PME, AER (no dependencies)
- * Never allow SHPC (no SHPC controller in this system)
+ * Allow SHPC (PCI bridges can have SHPC controller)
  */
-aml_append(if_ctx, aml_and(a_ctrl, aml_int(0x1D), a_ctrl));
+aml_append(if_ctx, aml_and(a_ctrl, aml_int(0x1F), a_ctrl));
 
 if_ctx2 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(1;
 /* Unknown revision */
-- 
2.7.4




[Qemu-devel] [PATCH v4 0/5] Generic PCIE-PCI Bridge

2017-08-05 Thread Aleksandr Bezzubikov
This series introduces a new device - Generic PCI Express to PCI bridge,
and also makes all necessary changes to enable hotplug of the bridge itself
and any device into the bridge.

Changes v3->v4:
1. PCIE-PCI Bridge device: "msi_enable"->"msi", "shpc"->"shpc_bar", remove 
local_err,
   make "msi" property OnOffAuto, shpc_present() is still here 
   to avoid SHPC_VMSTATE refactoring (address Marcel's comments). 
2. Change QEMU PCI capability layout (SeaBIOS side has the same changes):
  - change reservation fields types: bus_res - uint32_t, others - uint64_t
  - rename 'non_pref' and 'pref' fields
  - interpret -1 value as 'ignore'
3. Use parent_realize in Generic PCI Express Root Port properly.
4. Fix documentation: fully replace the DMI-PCI bridge references with the new 
PCIE-PCI bridge,
"PCIE"->"PCI Express", small mistakes and typos - address Laszlo's and Marcel's 
comments.
5. Rename QEMU PCI cap creation fucntion - addresses Marcel's comment.

Changes v2->v3:
(0). 'do_not_use' capability field flag is still _not_ in here since we haven't 
come to consesus on it yet.
1. Merge commits 5 (bus_reserve property creation) and 6 (property usage) 
together - addresses Michael's comment.
2. Add 'bus_reserve' property and QEMU PCI capability only to Generic PCIE Root 
Port - addresses Michael's and Marcel's comments.
3. Change 'bus_reserve' property's default value to 0 - addresses Michael's 
comment.
4. Rename QEMU bridge-specific PCI capability creation function - addresses 
Michael's comment.
5. Init the whole QEMU PCI capability with zeroes - addresses Michael's and 
Laszlo's comments.
6. Change QEMU PCI capability layout (SeaBIOS side has the same changes)
  - add 'type' field to distinguish multiple 
RedHat-specific capabilities - addresses Michael's comment
  - do not mimiс PCI Config space register layout, but use mutually exclusive 
differently
sized fields for IO and prefetchable memory limits - addresses Laszlo's 
comment
7. Correct error handling in PCIE-PCI bridge realize function.
8. Replace a '2' constant with PCI_CAP_FLAGS in the capability creation 
function - addresses Michael's comment.
9. Remove a comment on _OSC which isn't correct anymore - address Marcel's 
comment.
10. Add documentation for the Generic PCIE-PCI Bridge and QEMU PCI capability - 
addresses Michael's comment.

Changes v1->v2:
1. Enable SHPC for the bridge.
2. Enable SHPC support for the Q35 machine (ACPI stuff).
3. Introduce PCI capability to help firmware on the system init.
   This allows the bridge to be hotpluggable. Now it's supported 
   only for pcie-root-port. Now it's supposed to used with 
   SeaBIOS only, look at the SeaBIOS corresponding series
   "Allow RedHat PCI bridges reserve more buses than necessary during init".

Aleksandr Bezzubikov (5):
  hw/i386: allow SHPC for Q35 machine
  hw/pci: introduce pcie-pci-bridge device
  hw/pci: introduce bridge-only vendor-specific capability to provide
some hints to firmware
  hw/pci: add QEMU-specific PCI capability to the Generic PCI Express
Root Port
  docs: update documentation considering PCIE-PCI bridge

 docs/pcie.txt  |  49 +
 docs/pcie_pci_bridge.txt   | 110 +++
 hw/i386/acpi-build.c   |   4 +-
 hw/pci-bridge/Makefile.objs|   2 +-
 hw/pci-bridge/gen_pcie_root_port.c |  33 ++
 hw/pci-bridge/pcie_pci_bridge.c| 212 +
 hw/pci/pci_bridge.c|  29 +
 include/hw/pci/pci.h   |   1 +
 include/hw/pci/pci_bridge.h|  21 
 include/hw/pci/pcie_port.h |   1 +
 10 files changed, 436 insertions(+), 26 deletions(-)
 create mode 100644 docs/pcie_pci_bridge.txt
 create mode 100644 hw/pci-bridge/pcie_pci_bridge.c

-- 
2.7.4




[Qemu-devel] [PATCH v3 3/5] hw/pci: introduce bridge-only vendor-specific capability to provide some hints to firmware

2017-07-28 Thread Aleksandr Bezzubikov
On PCI init PCI bridges may need some
extra info about bus number to reserve, IO, memory and
prefetchable memory limits. QEMU can provide this
with a special vendor-specific PCI capability.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/pci/pci_bridge.c | 37 +
 include/hw/pci/pci_bridge.h | 28 
 2 files changed, 65 insertions(+)

diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 720119b..e9f12d6 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -408,6 +408,43 @@ void pci_bridge_map_irq(PCIBridge *br, const char* 
bus_name,
 br->bus_name = bus_name;
 }
 
+
+int pci_bridge_qemu_cap_init(PCIDevice *dev, int cap_offset,
+  uint8_t bus_reserve, uint32_t io_reserve,
+  uint16_t non_pref_reserve, uint64_t pref_reserve,
+  Error **errp)
+{
+size_t cap_len = sizeof(PCIBridgeQemuCap);
+PCIBridgeQemuCap cap = {
+.len = cap_len,
+.type = REDHAT_PCI_CAP_QEMU,
+.bus_res = bus_reserve,
+.non_pref_16 = non_pref_reserve
+};
+
+if ((uint8_t)io_reserve == io_reserve) {
+cap.io_8 = io_reserve;
+} else {
+cap.io_32 = io_reserve;
+}
+if ((uint16_t)pref_reserve == pref_reserve) {
+cap.pref_32 = pref_reserve;
+} else {
+cap.pref_64 = pref_reserve;
+}
+
+int offset = pci_add_capability(dev, PCI_CAP_ID_VNDR,
+cap_offset, cap_len, errp);
+if (offset < 0) {
+return offset;
+}
+
+memcpy(dev->config + offset + PCI_CAP_FLAGS,
+(char *) + PCI_CAP_FLAGS,
+cap_len - PCI_CAP_FLAGS);
+return 0;
+}
+
 static const TypeInfo pci_bridge_type_info = {
 .name = TYPE_PCI_BRIDGE,
 .parent = TYPE_PCI_DEVICE,
diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h
index ff7cbaa..e9b7cf4 100644
--- a/include/hw/pci/pci_bridge.h
+++ b/include/hw/pci/pci_bridge.h
@@ -67,4 +67,32 @@ void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
 #define  PCI_BRIDGE_CTL_DISCARD_STATUS 0x400   /* Discard timer status */
 #define  PCI_BRIDGE_CTL_DISCARD_SERR   0x800   /* Discard timer SERR# enable */
 
+typedef struct PCIBridgeQemuCap {
+uint8_t id; /* Standard PCI capability header field */
+uint8_t next;   /* Standard PCI capability header field */
+uint8_t len;/* Standard PCI vendor-specific capability header field */
+uint8_t type;   /* Red Hat vendor-specific capability type.
+   Types are defined with REDHAT_PCI_CAP_ prefix */
+
+uint16_t non_pref_16;   /* Non-prefetchable memory limit */
+uint8_t bus_res;/* Minimum number of buses to reserve */
+uint8_t io_8;   /* IO space limit in case of 8-bit value */
+uint32_t io_32; /* IO space limit in case of 32-bit value
+   This 2 values are mutually exclusive,
+   i.e. they can't be  >0 both*/
+uint32_t pref_32;   /* Prefetchable memory limit
+   in case of 32-bit value */
+uint64_t pref_64;   /* Prefetchable memory limit
+   in case of 64-bit value
+   This 2 values are mutually exclusive (just as
+   IO limit), i.e. they can't be  >0 both */
+} PCIBridgeQemuCap;
+
+#define REDHAT_PCI_CAP_QEMU 1
+
+int pci_bridge_qemu_cap_init(PCIDevice *dev, int cap_offset,
+  uint8_t bus_reserve, uint32_t io_reserve,
+  uint16_t mem_reserve, uint64_t pref_reserve,
+  Error **errp);
+
 #endif /* QEMU_PCI_BRIDGE_H */
-- 
2.7.4




[Qemu-devel] [PATCH v3 1/3] pci: refactor pci_find_capapibilty to get bdf as the first argument instead of the whole pci_device

2017-07-28 Thread Aleksandr Bezzubikov
Refactor pci_find_capability function to get bdf instead of
a whole pci_device* as the only necessary field for this function
is still bdf.

Reviewed-by: Marcel Apfelbaum <mar...@redhat.com>

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 src/fw/pciinit.c|  4 ++--
 src/hw/pci.c| 25 +
 src/hw/pci.h|  1 +
 src/hw/pcidevice.c  | 24 
 src/hw/pcidevice.h  |  1 -
 src/hw/virtio-pci.c |  6 +++---
 6 files changed, 31 insertions(+), 30 deletions(-)

diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 08221e6..864954f 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -762,7 +762,7 @@ static int pci_bus_hotplug_support(struct pci_bus *bus, u8 
pcie_cap)
 return downstream_port && slot_implemented;
 }
 
-shpc_cap = pci_find_capability(bus->bus_dev, PCI_CAP_ID_SHPC, 0);
+shpc_cap = pci_find_capability(bus->bus_dev->bdf, PCI_CAP_ID_SHPC, 0);
 return !!shpc_cap;
 }
 
@@ -844,7 +844,7 @@ static int pci_bios_check_devices(struct pci_bus *busses)
  */
 parent = [0];
 int type;
-u8 pcie_cap = pci_find_capability(s->bus_dev, PCI_CAP_ID_EXP, 0);
+u8 pcie_cap = pci_find_capability(s->bus_dev->bdf, PCI_CAP_ID_EXP, 0);
 int hotplug_support = pci_bus_hotplug_support(s, pcie_cap);
 for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
 u64 align = (type == PCI_REGION_TYPE_IO) ?
diff --git a/src/hw/pci.c b/src/hw/pci.c
index 8e3d617..50d9d2d 100644
--- a/src/hw/pci.c
+++ b/src/hw/pci.c
@@ -58,6 +58,30 @@ pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on)
 pci_config_writew(bdf, addr, val);
 }
 
+u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap)
+{
+int i;
+u16 status = pci_config_readw(bdf, PCI_STATUS);
+
+if (!(status & PCI_STATUS_CAP_LIST))
+return 0;
+
+if (cap == 0) {
+/* find first */
+cap = pci_config_readb(bdf, PCI_CAPABILITY_LIST);
+} else {
+/* find next */
+cap = pci_config_readb(bdf, cap + PCI_CAP_LIST_NEXT);
+}
+for (i = 0; cap && i <= 0xff; i++) {
+if (pci_config_readb(bdf, cap + PCI_CAP_LIST_ID) == cap_id)
+return cap;
+cap = pci_config_readb(bdf, cap + PCI_CAP_LIST_NEXT);
+}
+
+return 0;
+}
+
 // Helper function for foreachbdf() macro - return next device
 int
 pci_next(int bdf, int bus)
@@ -107,3 +131,4 @@ pci_reboot(void)
 outb(v|6, PORT_PCI_REBOOT); /* Actually do the reset */
 udelay(50);
 }
+
diff --git a/src/hw/pci.h b/src/hw/pci.h
index ee6e196..2e30e28 100644
--- a/src/hw/pci.h
+++ b/src/hw/pci.h
@@ -39,6 +39,7 @@ u32 pci_config_readl(u16 bdf, u32 addr);
 u16 pci_config_readw(u16 bdf, u32 addr);
 u8 pci_config_readb(u16 bdf, u32 addr);
 void pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on);
+u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap);
 int pci_next(int bdf, int bus);
 int pci_probe_host(void);
 void pci_reboot(void);
diff --git a/src/hw/pcidevice.c b/src/hw/pcidevice.c
index cfebf66..8853cf7 100644
--- a/src/hw/pcidevice.c
+++ b/src/hw/pcidevice.c
@@ -134,30 +134,6 @@ pci_find_init_device(const struct pci_device_id *ids, void 
*arg)
 return NULL;
 }
 
-u8 pci_find_capability(struct pci_device *pci, u8 cap_id, u8 cap)
-{
-int i;
-u16 status = pci_config_readw(pci->bdf, PCI_STATUS);
-
-if (!(status & PCI_STATUS_CAP_LIST))
-return 0;
-
-if (cap == 0) {
-/* find first */
-cap = pci_config_readb(pci->bdf, PCI_CAPABILITY_LIST);
-} else {
-/* find next */
-cap = pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_NEXT);
-}
-for (i = 0; cap && i <= 0xff; i++) {
-if (pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_ID) == cap_id)
-return cap;
-cap = pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_NEXT);
-}
-
-return 0;
-}
-
 // Enable PCI bus-mastering (ie, DMA) support on a pci device
 void
 pci_enable_busmaster(struct pci_device *pci)
diff --git a/src/hw/pcidevice.h b/src/hw/pcidevice.h
index 354b549..225d545 100644
--- a/src/hw/pcidevice.h
+++ b/src/hw/pcidevice.h
@@ -69,7 +69,6 @@ int pci_init_device(const struct pci_device_id *ids
 , struct pci_device *pci, void *arg);
 struct pci_device *pci_find_init_device(const struct pci_device_id *ids
 , void *arg);
-u8 pci_find_capability(struct pci_device *pci, u8 cap_id, u8 cap);
 void pci_enable_busmaster(struct pci_device *pci);
 u16 pci_enable_iobar(struct pci_device *pci, u32 addr);
 void *pci_enable_membar(struct pci_device *pci, u32 addr);
diff --git a/src/hw/virtio-pci.c b/src/hw/virtio-pci.c
index e5c2c33..96f9c6b 100644
--- a/src/hw/virtio-pci.c
+++ b/src/hw/virtio-pci.c
@@ -19,7 +19,7 @@
 #include "malloc.h" // free
 #include "output.h" // dprintf
 #include "pci.h" // pc

[Qemu-devel] [PATCH v3 5/5] docs: update documentation considering PCIE-PCI bridge

2017-07-28 Thread Aleksandr Bezzubikov
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 docs/pcie.txt|  46 ++
 docs/pcie_pci_bridge.txt | 121 +++
 2 files changed, 147 insertions(+), 20 deletions(-)
 create mode 100644 docs/pcie_pci_bridge.txt

diff --git a/docs/pcie.txt b/docs/pcie.txt
index 5bada24..338b50e 100644
--- a/docs/pcie.txt
+++ b/docs/pcie.txt
@@ -46,7 +46,7 @@ Place only the following kinds of devices directly on the 
Root Complex:
 (2) PCI Express Root Ports (ioh3420), for starting exclusively PCI Express
 hierarchies.
 
-(3) DMI-PCI Bridges (i82801b11-bridge), for starting legacy PCI
+(3) PCIE-PCI Bridge (pcie-pci-bridge), for starting legacy PCI
 hierarchies.
 
 (4) Extra Root Complexes (pxb-pcie), if multiple PCI Express Root Buses
@@ -55,18 +55,18 @@ Place only the following kinds of devices directly on the 
Root Complex:
pcie.0 bus

 |||  |
-   ---   --   --   --
-   | PCI Dev |   | PCIe Root Port |   | DMI-PCI Bridge |   |  pxb-pcie  |
-   ---   --   --   --
+   ---   --   ---   --
+   | PCI Dev |   | PCIe Root Port |   | PCIE-PCI Bridge |   |  pxb-pcie  |
+   ---   --   ---   --
 
 2.1.1 To plug a device into pcie.0 as a Root Complex Integrated Endpoint use:
   -device [,bus=pcie.0]
 2.1.2 To expose a new PCI Express Root Bus use:
   -device pxb-pcie,id=pcie.1,bus_nr=x[,numa_node=y][,addr=z]
-  Only PCI Express Root Ports and DMI-PCI bridges can be connected
+  Only PCI Express Root Ports, PCIE-PCI bridges and DMI-PCI bridges can be 
connected
   to the pcie.1 bus:
   -device 
ioh3420,id=root_port1[,bus=pcie.1][,chassis=x][,slot=y][,addr=z]
 \
-  -device i82801b11-bridge,id=dmi_pci_bridge1,bus=pcie.1
+  -device pcie-pci-bridge,id=pcie_pci_bridge1,bus=pcie.1
 
 
 2.2 PCI Express only hierarchy
@@ -130,21 +130,25 @@ Notes:
 Legacy PCI devices can be plugged into pcie.0 as Integrated Endpoints,
 but, as mentioned in section 5, doing so means the legacy PCI
 device in question will be incapable of hot-unplugging.
-Besides that use DMI-PCI Bridges (i82801b11-bridge) in combination
+Besides that use PCIE-PCI Bridges (pcie-pci-bridge) in combination
 with PCI-PCI Bridges (pci-bridge) to start PCI hierarchies.
+Instead of the PCIE-PCI Bridge DMI-PCI one can be used,
+but it doens't support hot-plug, is not crossplatform and since that
+is obsolete and deprecated. Use the PCIE-PCI Bridge if you're not 
+absolutely sure you need the DMI-PCI Bridge.
 
-Prefer flat hierarchies. For most scenarios a single DMI-PCI Bridge
+Prefer flat hierarchies. For most scenarios a single PCIE-PCI Bridge
 (having 32 slots) and several PCI-PCI Bridges attached to it
 (each supporting also 32 slots) will support hundreds of legacy devices.
-The recommendation is to populate one PCI-PCI Bridge under the DMI-PCI Bridge
+The recommendation is to populate one PCI-PCI Bridge under the PCIE-PCI Bridge
 until is full and then plug a new PCI-PCI Bridge...
 
pcie.0 bus
--
 ||
-   ---   --
-   | PCI Dev |   | DMI-PCI BRIDGE |
-   ----
+   ---   ---
+   | PCI Dev |   | PCIE-PCI BRIDGE |
+   -----
||
   ----
   | PCI-PCI Bridge || PCI-PCI Bridge |   ...
@@ -157,11 +161,11 @@ until is full and then plug a new PCI-PCI Bridge...
 2.3.1 To plug a PCI device into pcie.0 as an Integrated Endpoint use:
   -device [,bus=pcie.0]
 2.3.2 Plugging a PCI device into a PCI-PCI Bridge:
-  -device i82801b11-bridge,id=dmi_pci_bridge1[,bus=pcie.0] 
   \
-  -device 
pci-bridge,id=pci_bridge1,bus=dmi_pci_bridge1[,chassis_nr=x][,addr=y]   \
+  -device pcie-pci-bridge,id=pcie_pci_bridge1[,bus=pcie.0] 
   \
+  -device 
pci-bridge,id=pci_bridge1,bus=pcie_pci_bridge1[,chassis_nr=x][,addr=y]   \
   -device ,bus=pci_bridge1[,addr=x]
   Note that 'addr' cannot be 0 unless shpc=off parameter is passed to
-  the PCI Bridge.
+  the PCI Bridge, and can never be 0 when plugging into the PCIE-PCI 
Bridge.
 
 3. IO space issues
 ===
@@ -219,25 +223,27 @@ do not support hot-plug, so any devices plugged into Root 
Complexes
 cannot be hot-plugged/hot-unplugged:
 (1) PCI E

[Qemu-devel] [PATCH v3 2/3] pci: add QEMU-specific PCI capability structure

2017-07-28 Thread Aleksandr Bezzubikov
On PCI init PCI bridge devices may need some
extra info about bus number to reserve, IO, memory and
prefetchable memory limits. QEMU can provide this
with special vendor-specific PCI capability.

This capability is intended to be used only
for Red Hat PCI bridges, i.e. QEMU cooperation.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 src/fw/dev-pci.h | 62 
 1 file changed, 62 insertions(+)
 create mode 100644 src/fw/dev-pci.h

diff --git a/src/fw/dev-pci.h b/src/fw/dev-pci.h
new file mode 100644
index 000..fbd49ed
--- /dev/null
+++ b/src/fw/dev-pci.h
@@ -0,0 +1,62 @@
+#ifndef _PCI_CAP_H
+#define _PCI_CAP_H
+
+#include "types.h"
+
+/*
+
+QEMU-specific vendor(Red Hat)-specific capability.
+It's intended to provide some hints for firmware to init PCI devices.
+
+Its is shown below:
+
+Header:
+
+u8 id;   Standard PCI Capability Header field
+u8 next; Standard PCI Capability Header field
+u8 len;  Standard PCI Capability Header field
+u8 type; Red Hat vendor-specific capability type:
+   now only REDHAT_QEMU_CAP 1 exists
+Data:
+
+u16 non_prefetchable_16; non-prefetchable memory limit
+
+u8 bus_res;  minimum bus number to reserve;
+ this is necessary for PCI Express Root Ports
+ to support PCIE-to-PCI bridge hotplug
+
+u8 io_8; IO limit in case of 8-bit limit value
+u32 io_32;   IO limit in case of 16-bit limit value
+ io_8 and io_16 are mutually exclusive, in other words,
+ they can't be non-zero simultaneously
+
+u32 prefetchable_32; non-prefetchable memory limit
+ in case of 32-bit limit value
+u64 prefetchable_64; non-prefetchable memory limit
+ in case of 64-bit limit value
+ prefetachable_32 and prefetchable_64 are
+ mutually exclusive, in other words,
+ they can't be non-zero simultaneously
+If any field in Data section is 0,
+it means that such kind of reservation
+is not needed.
+
+*/
+
+/* Offset of vendor-specific capability type field */
+#define PCI_CAP_VNDR_SPEC_TYPE  3
+
+/* List of valid Red Hat vendor-specific capability types */
+#define REDHAT_CAP_TYPE_QEMU1
+
+
+/* Offsets of QEMU capability fields */
+#define QEMU_PCI_CAP_NON_PREF   4
+#define QEMU_PCI_CAP_BUS_RES6
+#define QEMU_PCI_CAP_IO_8   7
+#define QEMU_PCI_CAP_IO_32  8
+#define QEMU_PCI_CAP_PREF_3212
+#define QEMU_PCI_CAP_PREF_6416
+#define QEMU_PCI_CAP_SIZE   24
+
+#endif /* _PCI_CAP_H */
-- 
2.7.4




[Qemu-devel] [PATCH v3 4/5] hw/pci: add QEMU-specific PCI capability to Generic PCI Express Root Port

2017-07-28 Thread Aleksandr Bezzubikov
From: Aleksandr Bezzubikov <abezzubi...@ispras.ru>

To enable hotplugging of a newly created pcie-pci-bridge,
we need to tell firmware (SeaBIOS in this case) to reserve
additional buses for pcie-root-port, that allows us to
hotplug pcie-pci-bridge into this root port.
The number of buses to reserve is provided to the device via a corresponding
property, and to the firmware via new PCI capability.
The property's default value is 0 to keep default behavior unchanged.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/pci-bridge/gen_pcie_root_port.c | 23 +++
 hw/pci-bridge/pcie_root_port.c |  2 +-
 include/hw/pci/pcie_port.h |  2 ++
 3 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/hw/pci-bridge/gen_pcie_root_port.c 
b/hw/pci-bridge/gen_pcie_root_port.c
index cb694d6..da3caa1 100644
--- a/hw/pci-bridge/gen_pcie_root_port.c
+++ b/hw/pci-bridge/gen_pcie_root_port.c
@@ -16,6 +16,8 @@
 #include "hw/pci/pcie_port.h"
 
 #define TYPE_GEN_PCIE_ROOT_PORT"pcie-root-port"
+#define GEN_PCIE_ROOT_PORT(obj) \
+OBJECT_CHECK(GenPCIERootPort, (obj), TYPE_GEN_PCIE_ROOT_PORT)
 
 #define GEN_PCIE_ROOT_PORT_AER_OFFSET   0x100
 #define GEN_PCIE_ROOT_PORT_MSIX_NR_VECTOR   1
@@ -26,6 +28,9 @@ typedef struct GenPCIERootPort {
 /*< public >*/
 
 bool migrate_msix;
+
+/* additional buses to reserve on firmware init */
+uint8_t bus_reserve;
 } GenPCIERootPort;
 
 static uint8_t gen_rp_aer_vector(const PCIDevice *d)
@@ -60,6 +65,21 @@ static bool gen_rp_test_migrate_msix(void *opaque, int 
version_id)
 return rp->migrate_msix;
 }
 
+static void gen_rp_realize(PCIDevice *d, Error **errp)
+{
+rp_realize(d, errp);
+PCIESlot *s = PCIE_SLOT(d);
+GenPCIERootPort *grp = GEN_PCIE_ROOT_PORT(d);
+
+int rc = pci_bridge_qemu_cap_init(d, 0, grp->bus_reserve, 0, 0, 0, errp);
+if (rc < 0) {
+pcie_chassis_del_slot(s);
+pcie_cap_exit(d);
+gen_rp_interrupts_uninit(d);
+pci_bridge_exitfn(d);
+}
+}
+
 static const VMStateDescription vmstate_rp_dev = {
 .name = "pcie-root-port",
 .version_id = 1,
@@ -78,6 +98,7 @@ static const VMStateDescription vmstate_rp_dev = {
 
 static Property gen_rp_props[] = {
 DEFINE_PROP_BOOL("x-migrate-msix", GenPCIERootPort, migrate_msix, true),
+DEFINE_PROP_UINT8("bus-reserve", GenPCIERootPort, bus_reserve, 0),
 DEFINE_PROP_END_OF_LIST()
 };
 
@@ -89,6 +110,8 @@ static void gen_rp_dev_class_init(ObjectClass *klass, void 
*data)
 
 k->vendor_id = PCI_VENDOR_ID_REDHAT;
 k->device_id = PCI_DEVICE_ID_REDHAT_PCIE_RP;
+k->realize = gen_rp_realize;
+
 dc->desc = "PCI Express Root Port";
 dc->vmsd = _rp_dev;
 dc->props = gen_rp_props;
diff --git a/hw/pci-bridge/pcie_root_port.c b/hw/pci-bridge/pcie_root_port.c
index 4d588cb..2f3bcb1 100644
--- a/hw/pci-bridge/pcie_root_port.c
+++ b/hw/pci-bridge/pcie_root_port.c
@@ -52,7 +52,7 @@ static void rp_reset(DeviceState *qdev)
 pci_bridge_disable_base_limit(d);
 }
 
-static void rp_realize(PCIDevice *d, Error **errp)
+void rp_realize(PCIDevice *d, Error **errp)
 {
 PCIEPort *p = PCIE_PORT(d);
 PCIESlot *s = PCIE_SLOT(d);
diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
index 1333266..febd96a 100644
--- a/include/hw/pci/pcie_port.h
+++ b/include/hw/pci/pcie_port.h
@@ -63,6 +63,8 @@ void pcie_chassis_del_slot(PCIESlot *s);
 #define PCIE_ROOT_PORT_GET_CLASS(obj) \
  OBJECT_GET_CLASS(PCIERootPortClass, (obj), TYPE_PCIE_ROOT_PORT)
 
+void rp_realize(PCIDevice *d, Error **errp);
+
 typedef struct PCIERootPortClass {
 PCIDeviceClass parent_class;
 
-- 
2.7.4




[Qemu-devel] [PATCH v3 0/5] Generic PCIE-PCI Bridge

2017-07-28 Thread Aleksandr Bezzubikov
This series introduces a new device - generic PCI Express to PCI bridge,
and also makes all necessary changes to enable hotplug of the bridge itself
and any device into the bridge.

Changes v2->v3:
(0). 'do_not_use' capability field flag is still _not_ in here since we haven't 
come to consesus on it yet.
1. Merge commits 5 (bus_reserve property creation) and 6 (property usage) 
together - addresses Michael's comment.
2. Add 'bus_reserve' property and QEMU PCI capability only to Generic PCIE Root 
Port - addresses Michael's and Marcel's comments.
3. Change 'bus_reserve' property's default value to 0 - addresses Michael's 
comment.
4. Rename QEMU bridge-specific PCI capability creation function - addresses 
Michael's comment.
5. Init the whole QEMU PCI capability with zeroes - addresses Michael's and 
Laszlo's comments.
6. Change QEMU PCI capability layout (SeaBIOS side has the same changes)
- add 'type' field to distinguish multiple 
RedHat-specific capabilities - addresses Michael's comment
- do not mimiс PCI Config space register layout, but use mutually 
exclusive differently
sized fields for IO and prefetchable memory limits - addresses 
Laszlo's comment
7. Correct error handling in PCIE-PCI bridge realize function.
8. Replace a '2' constant with PCI_CAP_FLAGS in the capability creation 
function - addresses Michael's comment.
9. Remove a comment on _OSC which isn't correct anymore - address Marcel's 
comment.
10. Add documentation for the Generic PCIE-PCI Bridge and QEMU PCI capability - 
addresses Michael's comment.

Changes v1->v2:
1. Enable SHPC for the bridge.
2. Enable SHPC support for the Q35 machine (ACPI stuff).
3. Introduce PCI capability to help firmware on the system init.
   This allows the bridge to be hotpluggable. Now it's supported 
   only for pcie-root-port. Now it's supposed to used with 
   SeaBIOS only, look at the SeaBIOS corresponding series
   "".

Aleksandr Bezzubikov (5):
  hw/i386: allow SHPC for Q35 machine
  hw/pci: introduce pcie-pci-bridge device
  hw/pci: introduce bridge-only vendor-specific capability to provide
some hints to firmware
  hw/pci: add QEMU-specific PCI capability to Generic PCI Express Root
Port
  docs: update documentation considering PCIE-PCI bridge

 docs/pcie.txt  |  46 
 docs/pcie_pci_bridge.txt   | 121 
 hw/i386/acpi-build.c   |   4 +-
 hw/pci-bridge/Makefile.objs|   2 +-
 hw/pci-bridge/gen_pcie_root_port.c |  23 
 hw/pci-bridge/pcie_pci_bridge.c| 220 +
 hw/pci-bridge/pcie_root_port.c |   2 +-
 hw/pci/pci_bridge.c|  37 +++
 include/hw/pci/pci.h   |   1 +
 include/hw/pci/pci_bridge.h|  28 +
 include/hw/pci/pcie_port.h |   2 +
 11 files changed, 462 insertions(+), 24 deletions(-)
 create mode 100644 docs/pcie_pci_bridge.txt
 create mode 100644 hw/pci-bridge/pcie_pci_bridge.c

-- 
2.7.4




[Qemu-devel] [PATCH v3 1/5] hw/i386: allow SHPC for Q35 machine

2017-07-28 Thread Aleksandr Bezzubikov
Unmask previously masked SHPC feature in _OSC method.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/i386/acpi-build.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 6b7bade..2ab32f9 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1848,9 +1848,9 @@ static Aml *build_q35_osc_method(void)
 
 /*
  * Always allow native PME, AER (no dependencies)
- * Never allow SHPC (no SHPC controller in this system)
+ * Allow SHPC (PCI bridges can have SHPC controller)
  */
-aml_append(if_ctx, aml_and(a_ctrl, aml_int(0x1D), a_ctrl));
+aml_append(if_ctx, aml_and(a_ctrl, aml_int(0x1F), a_ctrl));
 
 if_ctx2 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(1;
 /* Unknown revision */
-- 
2.7.4




[Qemu-devel] [PATCH v3 2/5] hw/pci: introduce pcie-pci-bridge device

2017-07-28 Thread Aleksandr Bezzubikov
Introduce a new PCIExpress-to-PCI Bridge device,
which is a hot-pluggable PCI Express device and
supports devices hot-plug with SHPC.

This device is intended to replace the DMI-to-PCI
Bridge in an overwhelming majority of use-cases.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/pci-bridge/Makefile.objs |   2 +-
 hw/pci-bridge/pcie_pci_bridge.c | 220 
 include/hw/pci/pci.h|   1 +
 3 files changed, 222 insertions(+), 1 deletion(-)
 create mode 100644 hw/pci-bridge/pcie_pci_bridge.c

diff --git a/hw/pci-bridge/Makefile.objs b/hw/pci-bridge/Makefile.objs
index c4683cf..666db37 100644
--- a/hw/pci-bridge/Makefile.objs
+++ b/hw/pci-bridge/Makefile.objs
@@ -1,4 +1,4 @@
-common-obj-y += pci_bridge_dev.o
+common-obj-y += pci_bridge_dev.o pcie_pci_bridge.o
 common-obj-$(CONFIG_PCIE_PORT) += pcie_root_port.o gen_pcie_root_port.o
 common-obj-$(CONFIG_PXB) += pci_expander_bridge.o
 common-obj-$(CONFIG_XIO3130) += xio3130_upstream.o xio3130_downstream.o
diff --git a/hw/pci-bridge/pcie_pci_bridge.c b/hw/pci-bridge/pcie_pci_bridge.c
new file mode 100644
index 000..c28f820
--- /dev/null
+++ b/hw/pci-bridge/pcie_pci_bridge.c
@@ -0,0 +1,220 @@
+/*
+ * QEMU Generic PCIE-PCI Bridge
+ *
+ * Copyright (c) 2017 Aleksandr Bezzubikov
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/shpc.h"
+#include "hw/pci/slotid_cap.h"
+
+typedef struct PCIEPCIBridge {
+/*< private >*/
+PCIBridge parent_obj;
+
+bool msi_enable;
+MemoryRegion bar;
+/*< public >*/
+} PCIEPCIBridge;
+
+#define TYPE_PCIE_PCI_BRIDGE_DEV  "pcie-pci-bridge"
+#define PCIE_PCI_BRIDGE_DEV(obj) \
+OBJECT_CHECK(PCIEPCIBridge, (obj), TYPE_PCIE_PCI_BRIDGE_DEV)
+
+static void pciepci_bridge_realize(PCIDevice *d, Error **errp)
+{
+PCIBridge *br = PCI_BRIDGE(d);
+PCIEPCIBridge *pcie_br = PCIE_PCI_BRIDGE_DEV(d);
+int rc, pos;
+Error *local_err = NULL;
+
+pci_bridge_initfn(d, TYPE_PCI_BUS);
+
+d->config[PCI_INTERRUPT_PIN] = 0x1;
+memory_region_init(_br->bar, OBJECT(d), "shpc-bar",
+   shpc_bar_size(d));
+rc = shpc_init(d, >sec_bus, _br->bar, 0, _err);
+if (rc) {
+error_propagate(errp, local_err);
+goto error;
+}
+
+rc = pcie_cap_init(d, 0, PCI_EXP_TYPE_PCI_BRIDGE, 0, _err);
+if (rc < 0) {
+error_propagate(errp, local_err);
+goto cap_error;
+}
+
+pos = pci_add_capability(d, PCI_CAP_ID_PM, 0, PCI_PM_SIZEOF, _err);
+if (pos < 0) {
+error_propagate(errp, local_err);
+goto pm_error;
+}
+d->exp.pm_cap = pos;
+pci_set_word(d->config + pos + PCI_PM_PMC, 0x3);
+
+pcie_cap_arifwd_init(d);
+pcie_cap_deverr_init(d);
+
+rc = pcie_aer_init(d, PCI_ERR_VER, 0x100, PCI_ERR_SIZEOF, _err);
+if (rc < 0) {
+error_propagate(errp, local_err);
+goto aer_error;
+}
+
+if (pcie_br->msi_enable) {
+rc = msi_init(d, 0, 1, true, true, _err);
+if (rc < 0) {
+error_propagate(errp, local_err);
+goto msi_error;
+}
+}
+pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
+ PCI_BASE_ADDRESS_MEM_TYPE_64, _br->bar);
+return;
+
+msi_error:
+pcie_aer_exit(d);
+aer_error:
+pm_error:
+pcie_cap_exit(d);
+cap_error:
+shpc_free(d);
+error:
+pci_bridge_exitfn(d);
+}
+
+static void pciepci_bridge_exit(PCIDevice *d)
+{
+PCIEPCIBridge *bridge_dev = PCIE_PCI_BRIDGE_DEV(d);
+pcie_cap_exit(d);
+shpc_cleanup(d, _dev->bar);
+pci_bridge_exitfn(d);
+}
+
+s

[Qemu-devel] [PATCH v3 3/3] pci: enable RedHat PCI bridges to reserve additional buses on PCI init

2017-07-28 Thread Aleksandr Bezzubikov
In case of Red Hat Generic PCIE Root Port reserve additional buses,
which number is provided in a vendor-specific capability.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 src/fw/pciinit.c | 37 +++--
 src/hw/pci_ids.h |  3 +++
 src/types.h  |  2 ++
 3 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 864954f..a302a85 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -15,6 +15,7 @@
 #include "hw/pcidevice.h" // pci_probe_devices
 #include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
 #include "hw/pci_regs.h" // PCI_COMMAND
+#include "fw/dev-pci.h" // qemu_pci_cap
 #include "list.h" // struct hlist_node
 #include "malloc.h" // free
 #include "output.h" // dprintf
@@ -578,9 +579,41 @@ pci_bios_init_bus_rec(int bus, u8 *pci_bus)
 pci_bios_init_bus_rec(secbus, pci_bus);
 
 if (subbus != *pci_bus) {
+u8 res_bus = 0;
+if (pci_config_readw(bdf, PCI_VENDOR_ID) == PCI_VENDOR_ID_REDHAT &&
+pci_config_readw(bdf, PCI_DEVICE_ID) ==
+PCI_DEVICE_ID_REDHAT_ROOT_PORT) {
+u8 cap;
+do {
+cap = pci_find_capability(bdf, PCI_CAP_ID_VNDR, 0);
+} while (cap &&
+ pci_config_readb(bdf, cap + PCI_CAP_VNDR_SPEC_TYPE) !=
+REDHAT_CAP_TYPE_QEMU);
+if (cap) {
+u8 cap_len = pci_config_readb(bdf, cap + PCI_CAP_FLAGS);
+if (cap_len != QEMU_PCI_CAP_SIZE) {
+dprintf(1, "PCI: QEMU cap length %d is invalid\n",
+cap_len);
+} else {
+res_bus = pci_config_readb(bdf,
+   cap + QEMU_PCI_CAP_BUS_RES);
+if ((u8)(res_bus + secbus) < secbus ||
+(u8)(res_bus + secbus) < res_bus) {
+dprintf(1, "PCI: bus_reserve value %d is 
invalid\n",
+res_bus);
+res_bus = 0;
+} else {
+dprintf(1, "PCI: QEMU cap is found, value = %u\n",
+res_bus);
+}
+}
+}
+res_bus = MAX(*pci_bus, secbus + res_bus);
+}
 dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n",
-subbus, *pci_bus);
-subbus = *pci_bus;
+subbus, res_bus);
+subbus = res_bus;
+*pci_bus = res_bus;
 } else {
 dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus);
 }
diff --git a/src/hw/pci_ids.h b/src/hw/pci_ids.h
index 4ac73b4..38fa2ca 100644
--- a/src/hw/pci_ids.h
+++ b/src/hw/pci_ids.h
@@ -2263,6 +2263,9 @@
 #define PCI_DEVICE_ID_KORENIX_JETCARDF00x1600
 #define PCI_DEVICE_ID_KORENIX_JETCARDF10x16ff
 
+#define PCI_VENDOR_ID_REDHAT   0x1b36
+#define PCI_DEVICE_ID_REDHAT_ROOT_PORT 0x000C
+
 #define PCI_VENDOR_ID_TEKRAM   0x1de1
 #define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29
 
diff --git a/src/types.h b/src/types.h
index 19d9f6c..75d9108 100644
--- a/src/types.h
+++ b/src/types.h
@@ -122,6 +122,8 @@ extern void __force_link_error__only_in_16bit(void) 
__noreturn;
 typeof(divisor) __divisor = divisor;\
 (((x) + ((__divisor) / 2)) / (__divisor));  \
 })
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
 #define ALIGN(x,a)  __ALIGN_MASK(x,(typeof(x))(a)-1)
 #define __ALIGN_MASK(x,mask)(((x)+(mask))&~(mask))
 #define ALIGN_DOWN(x,a) ((x) & ~((typeof(x))(a)-1))
-- 
2.7.4




[Qemu-devel] [PATCH v3 0/3] Allow RedHat PCI bridges reserve more buses than necessary during init

2017-07-28 Thread Aleksandr Bezzubikov
Now PCI bridges get a bus range number on a system init,
basing on currently plugged devices. That's why when one wants to hotplug 
another bridge,
it needs his child bus, which the parent is unable to provide (speaking about 
virtual device).
The suggested workaround is to have vendor-specific capability in Red Hat PCI 
bridges
that contains number of additional bus to reserve (as well as various space 
limit hints,
unused for now) on BIOS PCI init.
So this capability is intented only for pure QEMU->SeaBIOS usage.

Considering all aforesaid, this series is directly connected with
QEMU series (v3) "Generic PCIE-PCI Bridge".

Although the new PCI capability is supposed to contain various limits along with
bus number to reserve, now only its full layout is proposed. And
only bus_reserve field is used in QEMU and BIOS. Limits usage
is still a subject for implementation as now
the main goal of this series to provide necessary support from the 
firmware side to PCIE-PCI bridge hotplug. 

Changes v2->v3:
1. Merge commit 2 (Red Hat vendor ID) into commit 4 - addresses Marcel's 
comment,
and add Generic PCIE Root Port device ID - addresses Michael's comment.
2. Changes of the capability layout  (QEMU side has the same changes):
- add 'type' field to distinguish multiple 
RedHat-specific capabilities - addresses Michael's comment
- do not mimiс PCI Config space register layout, but use mutually 
exclusive differently
sized fields for IO and prefetchable memory limits - addresses 
Laszlo's comment
- use defines instead of structure and offsetof - addresses Michael's 
comment
3. Interpret 'bus_reserve' field as a minimum necessary
 range to reserve - addresses Gerd's comment
4. pci_find_capability moved to pci.c - addresses Kevin's comment
5. Move capability layout header to src/fw/dev-pci.h - addresses Kevin's comment
6. Add the capability documentation - addresses Michael's comment
7. Add capability length and bus_reserve field sanity checks - addresses 
Michael's comment

Changes v1->v2:
1. New #define for Red Hat vendor added (addresses Konrad's comment).
2. Refactored pci_find_capability function (addresses Marcel's comment).
3. Capability reworked:
- data type added;
- reserve space in a structure for IO, memory and 
  prefetchable memory limits.

Aleksandr Bezzubikov (3):
  pci: refactor pci_find_capapibilty to get bdf as the first argument
instead of the whole pci_device
  pci: add QEMU-specific PCI capability structure
  pci: enable RedHat PCI bridges to reserve additional buses on PCI init

 src/fw/dev-pci.h| 62 +
 src/fw/pciinit.c| 41 +++
 src/hw/pci.c| 25 +
 src/hw/pci.h|  1 +
 src/hw/pci_ids.h|  3 +++
 src/hw/pcidevice.c  | 24 -
 src/hw/pcidevice.h  |  1 -
 src/hw/virtio-pci.c |  6 +++---
 src/types.h |  2 ++
 9 files changed, 133 insertions(+), 32 deletions(-)
 create mode 100644 src/fw/dev-pci.h

-- 
2.7.4




[Qemu-devel] [RFC PATCH v2 5/6] hw/pci: add bus_reserve property to pcie-root-port

2017-07-22 Thread Aleksandr Bezzubikov
To enable hotplugging of a newly created pcie-pci-bridge,
we need to tell firmware (SeaBIOS in this case) to reserve
additional buses for pcie-root-port, that allows us to 
hotplug pcie-pci-bridge into this root port.
The number of buses to reserve is provided to the device via a corresponding
property, and to the firmware via new PCI capability (next patch).
The property's default value is 1 as we want to hotplug at least 1 bridge.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/pci-bridge/pcie_root_port.c | 1 +
 include/hw/pci/pcie_port.h | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/hw/pci-bridge/pcie_root_port.c b/hw/pci-bridge/pcie_root_port.c
index 4d588cb..b0e49e1 100644
--- a/hw/pci-bridge/pcie_root_port.c
+++ b/hw/pci-bridge/pcie_root_port.c
@@ -137,6 +137,7 @@ static void rp_exit(PCIDevice *d)
 static Property rp_props[] = {
 DEFINE_PROP_BIT(COMPAT_PROP_PCP, PCIDevice, cap_present,
 QEMU_PCIE_SLTCAP_PCP_BITNR, true),
+DEFINE_PROP_UINT8("bus_reserve", PCIEPort, bus_reserve, 1),
 DEFINE_PROP_END_OF_LIST()
 };
 
diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
index 1333266..1b2dd1f 100644
--- a/include/hw/pci/pcie_port.h
+++ b/include/hw/pci/pcie_port.h
@@ -34,6 +34,9 @@ struct PCIEPort {
 
 /* pci express switch port */
 uint8_t port;
+
+/* additional buses to reserve on firmware init */
+uint8_t bus_reserve;
 };
 
 void pcie_port_init_reg(PCIDevice *d);
-- 
2.7.4




[Qemu-devel] [RFC PATCH v2 6/6] hw/pci: add hint capabilty for additional bus reservation to pcie-root-port

2017-07-22 Thread Aleksandr Bezzubikov
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/pci-bridge/pcie_root_port.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/hw/pci-bridge/pcie_root_port.c b/hw/pci-bridge/pcie_root_port.c
index b0e49e1..ca92d85 100644
--- a/hw/pci-bridge/pcie_root_port.c
+++ b/hw/pci-bridge/pcie_root_port.c
@@ -106,6 +106,11 @@ static void rp_realize(PCIDevice *d, Error **errp)
 pcie_aer_root_init(d);
 rp_aer_vector_update(d);
 
+rc = pci_bridge_help_cap_init(d, 0, p->bus_reserve, 0, 0, 0, errp);
+if (rc < 0) {
+goto err;
+}
+
 return;
 
 err:
-- 
2.7.4




[Qemu-devel] [RFC PATCH v2 4/6] hw/pci: introduce bridge-only vendor-specific capability to provide some hints to firmware

2017-07-22 Thread Aleksandr Bezzubikov
On PCI init PCI bridges may need some
extra info about bus number to reserve, IO, memory and
prefetchable memory limits. QEMU can provide this
with special vendor-specific PCI capability.

Sizes of limits match ones from
PCI Type 1 Configuration Space Header,
number of buses to reserve occupies only 1 byte 
since it is the size of Subordinate Bus Number register.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/pci/pci_bridge.c | 27 +++
 include/hw/pci/pci_bridge.h | 18 ++
 2 files changed, 45 insertions(+)

diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 720119b..8ec6c2c 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -408,6 +408,33 @@ void pci_bridge_map_irq(PCIBridge *br, const char* 
bus_name,
 br->bus_name = bus_name;
 }
 
+
+int pci_bridge_help_cap_init(PCIDevice *dev, int cap_offset,
+  uint8_t bus_reserve, uint32_t io_limit,
+  uint16_t mem_limit, uint64_t pref_limit,
+  Error **errp)
+{
+size_t cap_len = sizeof(PCIBridgeQemuCap);
+PCIBridgeQemuCap cap;
+
+cap.len = cap_len;
+cap.bus_res = bus_reserve;
+cap.io_lim = io_limit & 0xFF;
+cap.io_lim_upper = io_limit >> 8 & 0x;
+cap.mem_lim = mem_limit;
+cap.pref_lim = pref_limit & 0x;
+cap.pref_lim_upper = pref_limit >> 16 & 0x;
+
+int offset = pci_add_capability(dev, PCI_CAP_ID_VNDR,
+cap_offset, cap_len, errp);
+if (offset < 0) {
+return offset;
+}
+
+memcpy(dev->config + offset + 2, (char *) + 2, cap_len - 2);
+return 0;
+}
+
 static const TypeInfo pci_bridge_type_info = {
 .name = TYPE_PCI_BRIDGE,
 .parent = TYPE_PCI_DEVICE,
diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h
index ff7cbaa..c9f642c 100644
--- a/include/hw/pci/pci_bridge.h
+++ b/include/hw/pci/pci_bridge.h
@@ -67,4 +67,22 @@ void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
 #define  PCI_BRIDGE_CTL_DISCARD_STATUS 0x400   /* Discard timer status */
 #define  PCI_BRIDGE_CTL_DISCARD_SERR   0x800   /* Discard timer SERR# enable */
 
+typedef struct PCIBridgeQemuCap {
+uint8_t id; /* Standard PCI capability header field */
+uint8_t next;   /* Standard PCI capability header field */
+uint8_t len;/* Standard PCI vendor-specific capability header field */
+uint8_t bus_res;
+uint32_t pref_lim_upper;
+uint16_t pref_lim;
+uint16_t mem_lim;
+uint16_t io_lim_upper;
+uint8_t io_lim;
+uint8_t padding;
+} PCIBridgeQemuCap;
+
+int pci_bridge_help_cap_init(PCIDevice *dev, int cap_offset,
+  uint8_t bus_reserve, uint32_t io_limit,
+  uint16_t mem_limit, uint64_t pref_limit,
+  Error **errp);
+
 #endif /* QEMU_PCI_BRIDGE_H */
-- 
2.7.4




[Qemu-devel] [RFC PATCH v2 0/6] Generic PCIE-PCI Bridge

2017-07-22 Thread Aleksandr Bezzubikov
This series introduces a new device - generic PCI Express to PCI bridge,
and also makes all necessary changes to enable hotplug of the bridge itself
and any device into the bridge.

Obvious reasons to remain RFC:
1. The new PCI capability: layout, creation interface.
2. Windows SHPC issue - devices hotplugging into the bridge
   doens't work on Windows 7 (unlike Windows 10),
   whereas an old pci-bridge usage is fine.
3. Hot-unplug not completely tested.

Changes v1->v2:
1. Enable SHPC for the bridge.
2. Enable SHPC support for the Q35 machine (ACPI stuff).
3. Introduce PCI capability to help firmware on the system init.
   This allows the bridge to be hotpluggable. Now it's supported 
   only for pcie-root-port. Now it's supposed to used with 
   SeaBIOS only, look at the SeaBIOS corresponding series
   "".

Aleksandr Bezzubikov (6):
  hw/pci: introduce pcie-pci-bridge device
  hw/i386: allow SHPC for Q35 machine
  hw/pci: enable SHPC for PCIE-PCI bridge
  hw/pci: introduce bridge-only vendor-specific capability to provide
some hints to firmware
  hw/pci: add bus_reserve property to pcie-root-port
  hw/pci: add hint capabilty for additional bus reservation to
pcie-root-port

 hw/i386/acpi-build.c|   2 +-
 hw/pci-bridge/Makefile.objs |   2 +-
 hw/pci-bridge/pcie_pci_bridge.c | 212 
 hw/pci-bridge/pcie_root_port.c  |   6 ++
 hw/pci/pci_bridge.c |  27 +
 include/hw/pci/pci.h|   1 +
 include/hw/pci/pci_bridge.h |  18 
 include/hw/pci/pcie_port.h  |   3 +
 8 files changed, 269 insertions(+), 2 deletions(-)
 create mode 100644 hw/pci-bridge/pcie_pci_bridge.c

-- 
2.7.4




[Qemu-devel] [RFC PATCH v2 1/6] hw/pci: introduce pcie-pci-bridge device

2017-07-22 Thread Aleksandr Bezzubikov
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/pci-bridge/Makefile.objs |   2 +-
 hw/pci-bridge/pcie_pci_bridge.c | 151 
 include/hw/pci/pci.h|   1 +
 3 files changed, 153 insertions(+), 1 deletion(-)
 create mode 100644 hw/pci-bridge/pcie_pci_bridge.c

diff --git a/hw/pci-bridge/Makefile.objs b/hw/pci-bridge/Makefile.objs
index c4683cf..666db37 100644
--- a/hw/pci-bridge/Makefile.objs
+++ b/hw/pci-bridge/Makefile.objs
@@ -1,4 +1,4 @@
-common-obj-y += pci_bridge_dev.o
+common-obj-y += pci_bridge_dev.o pcie_pci_bridge.o
 common-obj-$(CONFIG_PCIE_PORT) += pcie_root_port.o gen_pcie_root_port.o
 common-obj-$(CONFIG_PXB) += pci_expander_bridge.o
 common-obj-$(CONFIG_XIO3130) += xio3130_upstream.o xio3130_downstream.o
diff --git a/hw/pci-bridge/pcie_pci_bridge.c b/hw/pci-bridge/pcie_pci_bridge.c
new file mode 100644
index 000..0991a7b
--- /dev/null
+++ b/hw/pci-bridge/pcie_pci_bridge.c
@@ -0,0 +1,151 @@
+/*
+ * QEMU Generic PCIE-PCI Bridge
+ *
+ * Copyright (c) 2017 Aleksandr Bezzubikov
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/slotid_cap.h"
+
+typedef struct PCIEPCIBridge {
+/*< private >*/
+PCIBridge parent_obj;
+uint32_t flags;
+
+/*< public >*/
+} PCIEPCIBridge;
+
+#define TYPE_PCIE_PCI_BRIDGE_DEV  "pcie-pci-bridge"
+#define PCIE_PCI_BRIDGE_DEV(obj) \
+OBJECT_CHECK(PCIEPCIBridge, (obj), TYPE_PCIE_PCI_BRIDGE_DEV)
+
+static void pciepci_bridge_realize(PCIDevice *d, Error **errp)
+{
+int rc, pos;
+Error *local_err = NULL;
+
+pci_bridge_initfn(d, TYPE_PCI_BUS);
+
+rc = pcie_cap_init(d, 0, PCI_EXP_TYPE_PCI_BRIDGE, 0, _err);
+if (rc < 0) {
+error_propagate(errp, local_err);
+goto error;
+}
+
+pos = pci_add_capability(d, PCI_CAP_ID_PM, 0, PCI_PM_SIZEOF, _err);
+if (pos < 0) {
+error_propagate(errp, local_err);
+goto error;
+}
+d->exp.pm_cap = pos;
+pci_set_word(d->config + pos + PCI_PM_PMC, 0x3);
+
+pcie_cap_arifwd_init(d);
+pcie_cap_deverr_init(d);
+
+rc = pcie_aer_init(d, PCI_ERR_VER, 0x100, PCI_ERR_SIZEOF, _err);
+if (rc < 0) {
+error_propagate(errp, local_err);
+goto error;
+}
+
+rc = msi_init(d, 0, 1, true, true, _err);
+if (rc < 0) {
+error_propagate(errp, local_err);
+goto error;
+}
+
+return;
+
+error:
+pci_bridge_exitfn(d);
+}
+
+static void pciepci_bridge_exit(PCIDevice *d)
+{
+pcie_cap_exit(d);
+pci_bridge_exitfn(d);
+}
+
+static void pciepci_bridge_reset(DeviceState *qdev)
+{
+PCIDevice *d = PCI_DEVICE(qdev);
+pci_bridge_reset(qdev);
+msi_reset(d);
+}
+
+static void pcie_pci_bridge_write_config(PCIDevice *d,
+uint32_t address, uint32_t val, int len)
+{
+pci_bridge_write_config(d, address, val, len);
+msi_write_config(d, address, val, len);
+}
+
+
+static Property pcie_pci_bridge_dev_properties[] = {
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static const VMStateDescription pciepci_bridge_dev_vmstate = {
+.name = TYPE_PCIE_PCI_BRIDGE_DEV,
+.fields = (VMStateField[]) {
+VMSTATE_PCI_DEVICE(parent_obj, PCIBridge),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void pciepci_bridge_class_init(ObjectClass *klass, void *data)
+{
+PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+k->is_express = 1;
+k->is_bridge = 1;
+k->vendor_id = PCI_VENDOR_ID_REDHAT;
+k->device_id = PCI_DEVICE_ID_REDHAT_PCIE_BRIDGE;
+k->realize = pciepci_bridg

[Qemu-devel] [RFC PATCH v2 2/6] hw/i386: allow SHPC for Q35 machine

2017-07-22 Thread Aleksandr Bezzubikov
Unmask previously masked SHPC feature in _OSC method.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/i386/acpi-build.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 6b7bade..0d99585 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1850,7 +1850,7 @@ static Aml *build_q35_osc_method(void)
  * Always allow native PME, AER (no dependencies)
  * Never allow SHPC (no SHPC controller in this system)
  */
-aml_append(if_ctx, aml_and(a_ctrl, aml_int(0x1D), a_ctrl));
+aml_append(if_ctx, aml_and(a_ctrl, aml_int(0x1F), a_ctrl));
 
 if_ctx2 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(1;
 /* Unknown revision */
-- 
2.7.4




[Qemu-devel] [RFC PATCH v2 3/6] hw/pci: enable SHPC for PCIE-PCI bridge

2017-07-22 Thread Aleksandr Bezzubikov
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/pci-bridge/pcie_pci_bridge.c | 63 -
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/hw/pci-bridge/pcie_pci_bridge.c b/hw/pci-bridge/pcie_pci_bridge.c
index 0991a7b..38f665f 100644
--- a/hw/pci-bridge/pcie_pci_bridge.c
+++ b/hw/pci-bridge/pcie_pci_bridge.c
@@ -28,6 +28,7 @@
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_bridge.h"
 #include "hw/pci/msi.h"
+#include "hw/pci/shpc.h"
 #include "hw/pci/slotid_cap.h"
 
 typedef struct PCIEPCIBridge {
@@ -35,6 +36,7 @@ typedef struct PCIEPCIBridge {
 PCIBridge parent_obj;
 uint32_t flags;
 
+MemoryRegion bar;
 /*< public >*/
 } PCIEPCIBridge;
 
@@ -44,11 +46,22 @@ typedef struct PCIEPCIBridge {
 
 static void pciepci_bridge_realize(PCIDevice *d, Error **errp)
 {
+PCIBridge *br = PCI_BRIDGE(d);
+PCIEPCIBridge *bridge_dev = PCIE_PCI_BRIDGE_DEV(d);
 int rc, pos;
 Error *local_err = NULL;
 
 pci_bridge_initfn(d, TYPE_PCI_BUS);
 
+d->config[PCI_INTERRUPT_PIN] = 0x1;
+memory_region_init(_dev->bar, OBJECT(d), "shpc-bar",
+   shpc_bar_size(d));
+rc = shpc_init(d, >sec_bus, _dev->bar, 0, _err);
+if (rc) {
+error_propagate(errp, local_err);
+goto error;
+}
+
 rc = pcie_cap_init(d, 0, PCI_EXP_TYPE_PCI_BRIDGE, 0, _err);
 if (rc < 0) {
 error_propagate(errp, local_err);
@@ -78,6 +91,9 @@ static void pciepci_bridge_realize(PCIDevice *d, Error **errp)
 goto error;
 }
 
+pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
+ PCI_BASE_ADDRESS_MEM_TYPE_64, _dev->bar);
+
 return;
 
 error:
@@ -86,7 +102,9 @@ static void pciepci_bridge_realize(PCIDevice *d, Error 
**errp)
 
 static void pciepci_bridge_exit(PCIDevice *d)
 {
+PCIEPCIBridge *bridge_dev = PCIE_PCI_BRIDGE_DEV(d);
 pcie_cap_exit(d);
+shpc_cleanup(d, _dev->bar);
 pci_bridge_exitfn(d);
 }
 
@@ -95,6 +113,7 @@ static void pciepci_bridge_reset(DeviceState *qdev)
 PCIDevice *d = PCI_DEVICE(qdev);
 pci_bridge_reset(qdev);
 msi_reset(d);
+shpc_reset(d);
 }
 
 static void pcie_pci_bridge_write_config(PCIDevice *d,
@@ -102,8 +121,15 @@ static void pcie_pci_bridge_write_config(PCIDevice *d,
 {
 pci_bridge_write_config(d, address, val, len);
 msi_write_config(d, address, val, len);
+shpc_cap_write_config(d, address, val, len);
 }
 
+static bool pci_device_shpc_present(void *opaque, int version_id)
+{
+PCIDevice *dev = opaque;
+
+return shpc_present(dev);
+}
 
 static Property pcie_pci_bridge_dev_properties[] = {
 DEFINE_PROP_END_OF_LIST(),
@@ -113,14 +139,43 @@ static const VMStateDescription 
pciepci_bridge_dev_vmstate = {
 .name = TYPE_PCIE_PCI_BRIDGE_DEV,
 .fields = (VMStateField[]) {
 VMSTATE_PCI_DEVICE(parent_obj, PCIBridge),
+SHPC_VMSTATE(shpc, PCIDevice, pci_device_shpc_present),
 VMSTATE_END_OF_LIST()
 }
 };
 
+static void pcie_pci_bridge_hotplug_cb(HotplugHandler *hotplug_dev,
+  DeviceState *dev, Error **errp)
+{
+PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);
+
+if (!shpc_present(pci_hotplug_dev)) {
+error_setg(errp, "standard hotplug controller has been disabled for "
+   "this %s", TYPE_PCIE_PCI_BRIDGE_DEV);
+return;
+}
+shpc_device_hotplug_cb(hotplug_dev, dev, errp);
+}
+
+static void pcie_pci_bridge_hot_unplug_request_cb(HotplugHandler *hotplug_dev,
+ DeviceState *dev,
+ Error **errp)
+{
+PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);
+
+if (!shpc_present(pci_hotplug_dev)) {
+error_setg(errp, "standard hotplug controller has been disabled for "
+   "this %s", TYPE_PCIE_PCI_BRIDGE_DEV);
+return;
+}
+shpc_device_hot_unplug_request_cb(hotplug_dev, dev, errp);
+}
+
 static void pciepci_bridge_class_init(ObjectClass *klass, void *data)
 {
 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 DeviceClass *dc = DEVICE_CLASS(klass);
+HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
 
 k->is_express = 1;
 k->is_bridge = 1;
@@ -134,13 +189,19 @@ static void pciepci_bridge_class_init(ObjectClass *klass, 
void *data)
 dc->vmsd = _bridge_dev_vmstate;
 dc->reset = _bridge_reset;
 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+hc->plug = pcie_pci_bridge_hotplug_cb;
+hc->unplug_request = pcie_pci_bridge_hot_unplug_request_cb;
 }
 
 static const TypeInfo pciepci_bridge_info = {
 .name = TYPE_PCIE_PCI_BRIDGE_DEV,
 .parent = TYPE_PCI_BRIDGE,
 .instance_size = sizeo

[Qemu-devel] [RFC PATCH v2 3/4] pci: add QEMU-specific PCI capability structure

2017-07-22 Thread Aleksandr Bezzubikov
On PCI init PCI bridge devices may need some
extra info about bus number to reserve, IO, memory and
prefetchable memory limits. QEMU can provide this
with special vendor-specific PCI capability.

This capability is intended to be used only
for Red Hat PCI bridges, i.e. QEMU cooperation.

Sizes of limits match ones from 
PCI Type 1 Configuration Space Header,
number of buses to reserve occupies only 1 byte 
since it is the size of Subordinate Bus Number register.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 src/hw/pci_cap.h | 23 +++
 1 file changed, 23 insertions(+)
 create mode 100644 src/hw/pci_cap.h

diff --git a/src/hw/pci_cap.h b/src/hw/pci_cap.h
new file mode 100644
index 000..1382b0b
--- /dev/null
+++ b/src/hw/pci_cap.h
@@ -0,0 +1,23 @@
+#ifndef _PCI_CAP_H
+#define _PCI_CAP_H
+
+#include "types.h"
+
+struct vendor_pci_cap {
+u8 id;
+u8 next;
+u8 len;
+};
+
+struct redhat_pci_bridge_cap {
+struct vendor_pci_cap hdr;
+u8 bus_res;
+u32 pref_lim_upper;
+u16 pref_lim;
+u16 mem_lim;
+u16 io_lim_upper;
+u8 io_lim;
+u8 padd;
+};
+
+#endif /* _PCI_CAP_H */
-- 
2.7.4




[Qemu-devel] [RFC PATCH v2 4/4] pci: enable RedHat PCI bridges to reserve additional buses on PCI init

2017-07-22 Thread Aleksandr Bezzubikov
In case of Red Hat PCI bridges reserve additional buses, which number is 
provided
in a vendor-specific capability. 

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 src/fw/pciinit.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 864954f..f05a8b9 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -15,6 +15,7 @@
 #include "hw/pcidevice.h" // pci_probe_devices
 #include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
 #include "hw/pci_regs.h" // PCI_COMMAND
+#include "hw/pci_cap.h" // qemu_pci_cap
 #include "list.h" // struct hlist_node
 #include "malloc.h" // free
 #include "output.h" // dprintf
@@ -578,9 +579,18 @@ pci_bios_init_bus_rec(int bus, u8 *pci_bus)
 pci_bios_init_bus_rec(secbus, pci_bus);
 
 if (subbus != *pci_bus) {
+u8 res_bus = 0;
+if (pci_config_readw(bdf, PCI_VENDOR_ID) == PCI_VENDOR_ID_REDHAT) {
+u8 cap = pci_find_capability(bdf, PCI_CAP_ID_VNDR, 0);
+if (cap) {
+res_bus = pci_config_readb(bdf,
+cap + offsetof(struct redhat_pci_bridge_cap,
+   bus_res));
+}
+}
 dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n",
-subbus, *pci_bus);
-subbus = *pci_bus;
+subbus, *pci_bus + res_bus);
+subbus = *pci_bus + res_bus;
 } else {
 dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus);
 }
-- 
2.7.4




[Qemu-devel] [RFC PATCH v2 0/4] Allow RedHat PCI bridges reserve more buses than necessary during init

2017-07-22 Thread Aleksandr Bezzubikov
Now PCI bridges get a bus range number on a system init,
basing on currently plugged devices. That's why when one wants to hotplug 
another bridge,
it needs his child bus, which the parent is unable to provide (speaking about 
virtual device).
The suggested workaround is to have vendor-specific capability in Red Hat PCI 
bridges
that contains number of additional bus to reserve on BIOS PCI init.
So this capability is intented only for pure QEMU->SeaBIOS usage.

Considering all aforesaid, this series is directly connected with
QEMU RFC series (v2) "Generic PCIE-PCI Bridge".

Although the new PCI capability is supposed to contain various limits along with
bus number to reserve, now only its full layout is proposed, but
only bus_reserve field is used in QEMU and BIOS. Limits usage
is still a subject for implementation as now
the main goal of this series to provide necessary support from the 
firmware side to PCIE-PCI bridge hotplug. 

Changes v1->v2:
1. New #define for Red Hat vendor added (addresses Konrad's comment).
2. Refactored pci_find_capability function (addresses Marcel's comment).
3. Capability reworked:
- data type added;
- reserve space in a structure for IO, memory and 
  prefetchable memory limits.


Aleksandr Bezzubikov (4):
  pci: refactor pci_find_capapibilty to get bdf as the first argument
instead of the whole pci_device
  pci: add RedHat vendor ID
  pci: add QEMU-specific PCI capability structure
  pci: enable RedHat PCI bridges to reserve additional buses on PCI init

 src/fw/pciinit.c| 18 ++
 src/hw/pci_cap.h| 23 +++
 src/hw/pci_ids.h|  2 ++
 src/hw/pcidevice.c  | 12 ++--
 src/hw/pcidevice.h  |  2 +-
 src/hw/virtio-pci.c |  4 ++--
 6 files changed, 48 insertions(+), 13 deletions(-)
 create mode 100644 src/hw/pci_cap.h

-- 
2.7.4




[Qemu-devel] [RFC PATCH v2 1/4] pci: refactor pci_find_capapibilty to get bdf as the first argument instead of the whole pci_device

2017-07-22 Thread Aleksandr Bezzubikov
Refactor pci_find_capability function to get bdf instead of
a whole pci_device* as the only necessary field for this function 
is still bdf.
It greatly helps when we have bdf but not pci_device.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 src/fw/pciinit.c|  4 ++--
 src/hw/pcidevice.c  | 12 ++--
 src/hw/pcidevice.h  |  2 +-
 src/hw/virtio-pci.c |  4 ++--
 4 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 08221e6..864954f 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -762,7 +762,7 @@ static int pci_bus_hotplug_support(struct pci_bus *bus, u8 
pcie_cap)
 return downstream_port && slot_implemented;
 }
 
-shpc_cap = pci_find_capability(bus->bus_dev, PCI_CAP_ID_SHPC, 0);
+shpc_cap = pci_find_capability(bus->bus_dev->bdf, PCI_CAP_ID_SHPC, 0);
 return !!shpc_cap;
 }
 
@@ -844,7 +844,7 @@ static int pci_bios_check_devices(struct pci_bus *busses)
  */
 parent = [0];
 int type;
-u8 pcie_cap = pci_find_capability(s->bus_dev, PCI_CAP_ID_EXP, 0);
+u8 pcie_cap = pci_find_capability(s->bus_dev->bdf, PCI_CAP_ID_EXP, 0);
 int hotplug_support = pci_bus_hotplug_support(s, pcie_cap);
 for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
 u64 align = (type == PCI_REGION_TYPE_IO) ?
diff --git a/src/hw/pcidevice.c b/src/hw/pcidevice.c
index cfebf66..d01e27b 100644
--- a/src/hw/pcidevice.c
+++ b/src/hw/pcidevice.c
@@ -134,25 +134,25 @@ pci_find_init_device(const struct pci_device_id *ids, 
void *arg)
 return NULL;
 }
 
-u8 pci_find_capability(struct pci_device *pci, u8 cap_id, u8 cap)
+u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap)
 {
 int i;
-u16 status = pci_config_readw(pci->bdf, PCI_STATUS);
+u16 status = pci_config_readw(bdf, PCI_STATUS);
 
 if (!(status & PCI_STATUS_CAP_LIST))
 return 0;
 
 if (cap == 0) {
 /* find first */
-cap = pci_config_readb(pci->bdf, PCI_CAPABILITY_LIST);
+cap = pci_config_readb(bdf, PCI_CAPABILITY_LIST);
 } else {
 /* find next */
-cap = pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_NEXT);
+cap = pci_config_readb(bdf, cap + PCI_CAP_LIST_NEXT);
 }
 for (i = 0; cap && i <= 0xff; i++) {
-if (pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_ID) == cap_id)
+if (pci_config_readb(bdf, cap + PCI_CAP_LIST_ID) == cap_id)
 return cap;
-cap = pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_NEXT);
+cap = pci_config_readb(bdf, cap + PCI_CAP_LIST_NEXT);
 }
 
 return 0;
diff --git a/src/hw/pcidevice.h b/src/hw/pcidevice.h
index 354b549..adcc75a 100644
--- a/src/hw/pcidevice.h
+++ b/src/hw/pcidevice.h
@@ -69,7 +69,7 @@ int pci_init_device(const struct pci_device_id *ids
 , struct pci_device *pci, void *arg);
 struct pci_device *pci_find_init_device(const struct pci_device_id *ids
 , void *arg);
-u8 pci_find_capability(struct pci_device *pci, u8 cap_id, u8 cap);
+u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap);
 void pci_enable_busmaster(struct pci_device *pci);
 u16 pci_enable_iobar(struct pci_device *pci, u32 addr);
 void *pci_enable_membar(struct pci_device *pci, u32 addr);
diff --git a/src/hw/virtio-pci.c b/src/hw/virtio-pci.c
index e5c2c33..4e33033 100644
--- a/src/hw/virtio-pci.c
+++ b/src/hw/virtio-pci.c
@@ -381,7 +381,7 @@ fail:
 
 void vp_init_simple(struct vp_device *vp, struct pci_device *pci)
 {
-u8 cap = pci_find_capability(pci, PCI_CAP_ID_VNDR, 0);
+u8 cap = pci_find_capability(pci->bdf, PCI_CAP_ID_VNDR, 0);
 struct vp_cap *vp_cap;
 const char *mode;
 u32 offset, base, mul;
@@ -479,7 +479,7 @@ void vp_init_simple(struct vp_device *vp, struct pci_device 
*pci)
 vp_cap->cap, type, vp_cap->bar, addr, offset, mode);
 }
 
-cap = pci_find_capability(pci, PCI_CAP_ID_VNDR, cap);
+cap = pci_find_capability(pci->bdf, PCI_CAP_ID_VNDR, cap);
 }
 
 if (vp->common.cap && vp->notify.cap && vp->isr.cap && vp->device.cap) {
-- 
2.7.4




[Qemu-devel] [RFC PATCH v2 2/4] pci: add RedHat vendor ID

2017-07-22 Thread Aleksandr Bezzubikov
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 src/hw/pci_ids.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/hw/pci_ids.h b/src/hw/pci_ids.h
index 4ac73b4..db2e694 100644
--- a/src/hw/pci_ids.h
+++ b/src/hw/pci_ids.h
@@ -2263,6 +2263,8 @@
 #define PCI_DEVICE_ID_KORENIX_JETCARDF00x1600
 #define PCI_DEVICE_ID_KORENIX_JETCARDF10x16ff
 
+#define PCI_VENDOR_ID_REDHAT   0x1b36
+
 #define PCI_VENDOR_ID_TEKRAM   0x1de1
 #define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29
 
-- 
2.7.4




[Qemu-devel] [RFC PATCH 0/2] Allow RedHat PCI bridges reserve more buses than necessary during init

2017-07-19 Thread Aleksandr Bezzubikov
Now PCI bridges (and PCIE root port too) get a bus range number in system init,
basing on currently plugged devices. That's why when one wants to hotplug 
another bridge,
it needs his child bus, which the parent is unable to provide.
The suggested workaround is to have vendor-specific capability in RedHat 
generic pcie-root-port
that contains number of additional bus to reserve on BIOS PCI init.

Aleksandr Bezzubikov (2):
  pci: add support for direct usage of bdf for capability lookup
  pci: enable RedHat pci bridges to reserve more buses

 src/fw/pciinit.c   | 12 ++--
 src/hw/pcidevice.c | 24 
 src/hw/pcidevice.h |  1 +
 3 files changed, 35 insertions(+), 2 deletions(-)

-- 
2.7.4




[Qemu-devel] [RFC PATCH 2/2] pci: enable RedHat pci bridges to reserve more buses

2017-07-19 Thread Aleksandr Bezzubikov
In case of RedHat PCI bridges reserve additional buses, which number is provided
in a vendor-specific capability.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 src/fw/pciinit.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 08221e6..b6f3a01 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -578,9 +578,17 @@ pci_bios_init_bus_rec(int bus, u8 *pci_bus)
 pci_bios_init_bus_rec(secbus, pci_bus);
 
 if (subbus != *pci_bus) {
+u16 vendor = pci_config_readw(bdf, PCI_VENDOR_ID);
+u8 res_bus = 0;
+if (vendor == 0x1b36) {
+u8 cap = pci_find_capability_bdf(bdf, PCI_CAP_ID_VNDR, 0);
+if (cap) {
+res_bus = pci_config_readb(bdf, cap + 16);
+}
+}
 dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n",
-subbus, *pci_bus);
-subbus = *pci_bus;
+subbus, *pci_bus + res_bus);
+subbus = *pci_bus + res_bus;
 } else {
 dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus);
 }
-- 
2.7.4




[Qemu-devel] [RFC PATCH 1/2] pci: add support for direct usage of bdf for capability lookup

2017-07-19 Thread Aleksandr Bezzubikov
Add a capability lookup function which gets bdf instead of pci_device
as its first argument. It may be useful when we have bdf,
but don't have the whole pci_device structure.

Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 src/hw/pcidevice.c | 24 
 src/hw/pcidevice.h |  1 +
 2 files changed, 25 insertions(+)

diff --git a/src/hw/pcidevice.c b/src/hw/pcidevice.c
index cfebf66..3fa240e 100644
--- a/src/hw/pcidevice.c
+++ b/src/hw/pcidevice.c
@@ -158,6 +158,30 @@ u8 pci_find_capability(struct pci_device *pci, u8 cap_id, 
u8 cap)
 return 0;
 }
 
+u8 pci_find_capability_bdf(int bdf, u8 cap_id, u8 cap)
+{
+int i;
+u16 status = pci_config_readw(bdf, PCI_STATUS);
+
+if (!(status & PCI_STATUS_CAP_LIST))
+return 0;
+
+if (cap == 0) {
+/* find first */
+cap = pci_config_readb(bdf, PCI_CAPABILITY_LIST);
+} else {
+/* find next */
+cap = pci_config_readb(bdf, cap + PCI_CAP_LIST_NEXT);
+}
+for (i = 0; cap && i <= 0xff; i++) {
+if (pci_config_readb(bdf, cap + PCI_CAP_LIST_ID) == cap_id)
+return cap;
+cap = pci_config_readb(bdf, cap + PCI_CAP_LIST_NEXT);
+}
+
+return 0;
+}
+
 // Enable PCI bus-mastering (ie, DMA) support on a pci device
 void
 pci_enable_busmaster(struct pci_device *pci)
diff --git a/src/hw/pcidevice.h b/src/hw/pcidevice.h
index 354b549..e4ed5cf 100644
--- a/src/hw/pcidevice.h
+++ b/src/hw/pcidevice.h
@@ -70,6 +70,7 @@ int pci_init_device(const struct pci_device_id *ids
 struct pci_device *pci_find_init_device(const struct pci_device_id *ids
 , void *arg);
 u8 pci_find_capability(struct pci_device *pci, u8 cap_id, u8 cap);
+u8 pci_find_capability_bdf(int bdf, u8 cap_id, u8 cap);
 void pci_enable_busmaster(struct pci_device *pci);
 u16 pci_enable_iobar(struct pci_device *pci, u32 addr);
 void *pci_enable_membar(struct pci_device *pci, u32 addr);
-- 
2.7.4




[Qemu-devel] [PATCH RFC 5/6] hw/acpi: extend acpi pci hotplug support for pci express

2017-06-29 Thread Aleksandr Bezzubikov
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/i386/acpi-build.c | 47 +++
 1 file changed, 31 insertions(+), 16 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index e434efe..8bbece5 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -254,6 +254,11 @@ static void acpi_get_pci_holes(Range *hole, Range *hole64)
   NULL));
 }
 
+static void acpi_test_pci_bus(PCIBus *bus, void *opaque)
+{
+*(bool *)opaque |= !pci_bus_is_express(bus);
+}
+
 #define ACPI_PORT_SMI_CMD   0x00b2 /* TODO: this is APM_CNT_IOPORT */
 
 static void acpi_align_size(GArray *blob, unsigned align)
@@ -489,7 +494,7 @@ static void *acpi_set_bsel(PCIBus *bus, void *opaque)
 unsigned *bsel_alloc = opaque;
 unsigned *bus_bsel;
 
-if (qbus_is_hotpluggable(BUS(bus))) {
+if (qbus_is_hotpluggable(BUS(bus)) && !pci_bus_is_express(bus)) {
 bus_bsel = g_malloc(sizeof *bus_bsel);
 
 *bus_bsel = (*bsel_alloc)++;
@@ -500,15 +505,12 @@ static void *acpi_set_bsel(PCIBus *bus, void *opaque)
 return bsel_alloc;
 }
 
-static void acpi_set_pci_info(void)
+static void acpi_set_pci_info(PCIBus *bus)
 {
-PCIBus *bus = find_i440fx(); /* TODO: Q35 support */
 unsigned bsel_alloc = ACPI_PCIHP_BSEL_DEFAULT;
 
-if (bus) {
-/* Scan all PCI buses. Set property to enable acpi based hotplug. */
-pci_for_each_bus_depth_first(bus, acpi_set_bsel, NULL, _alloc);
-}
+/* Scan all PCI buses. Set property to enable acpi based hotplug. */
+pci_for_each_bus_depth_first(bus, acpi_set_bsel, NULL, _alloc);
 }
 
 static void build_append_pcihp_notify_entry(Aml *method, int slot)
@@ -570,7 +572,7 @@ static void build_append_pci_bus_devices(Aml *parent_scope, 
PCIBus *bus,
  * In this case they aren't themselves hot-pluggable.
  * Hotplugged bridges *are* hot-pluggable.
  */
-bridge_in_acpi = pc->is_bridge && pcihp_bridge_en &&
+bridge_in_acpi = pc->is_bridge && !pc->is_express && pcihp_bridge_en &&
 !DEVICE(pdev)->hotplugged;
 
 hotplug_enabled_dev = bsel && dc->hotpluggable && !bridge_in_acpi;
@@ -1787,7 +1789,7 @@ static void build_piix4_isa_bridge(Aml *table)
 aml_append(table, scope);
 }
 
-static void build_piix4_pci_hotplug(Aml *table)
+static void build_acpi_pci_hotplug(Aml *table)
 {
 Aml *scope;
 Aml *field;
@@ -1889,6 +1891,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 uint32_t nr_mem = machine->ram_slots;
 int root_bus_limit = 0xFF;
 PCIBus *root_bus = NULL;
+bool has_pci_bus = false;
 int i;
 
 dsdt = init_aml_allocator();
@@ -1910,7 +1913,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 build_piix4_pm(dsdt);
 build_piix4_isa_bridge(dsdt);
 build_isa_devices_aml(dsdt);
-build_piix4_pci_hotplug(dsdt);
 build_piix4_pci0_int(dsdt);
 } else {
 sb_scope = aml_scope("_SB");
@@ -1932,6 +1934,11 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 root_bus = PC_MACHINE(machine)->bus;
 assert(root_bus);
 
+pci_for_each_bus(root_bus, acpi_test_pci_bus, _pci_bus);
+if (pm->pcihp_bridge_en && has_pci_bus) {
+build_acpi_pci_hotplug(dsdt);
+}
+
 if (pcmc->legacy_cpu_hotplug) {
 build_legacy_cpu_hotplug_aml(dsdt, machine, pm->cpu_hp_io_base);
 } else {
@@ -1947,7 +1954,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 {
 aml_append(scope, aml_name_decl("_HID", aml_string("ACPI0006")));
 
-if (misc->is_piix4) {
+if (pm->pcihp_bridge_en && has_pci_bus) {
 method = aml_method("_E01", 0, AML_NOTSERIALIZED);
 aml_append(method,
 aml_acquire(aml_name("\\_SB.PCI0.BLCK"), 0x));
@@ -2080,7 +2087,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 crs_range_set_free(_range_set);
 
 /* reserve PCIHP resources */
-if (pm->pcihp_io_len) {
+if (pm->pcihp_bridge_en && has_pci_bus && pm->pcihp_io_len) {
 dev = aml_device("PHPR");
 aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A06")));
 aml_append(dev,
@@ -2212,8 +2219,13 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 sb_scope = aml_scope("\\_SB");
 {
 Aml *scope = aml_scope("PCI0");
-/* Scan all PCI buses. Generate tables to support hotplug. */
-build_append_pci_bus_devices(scope, root_bus, pm->pcihp_bridge_en);
+bool scope_used = false;
+
+if (pm->pcihp_bridge_en && has_pci_bus) {
+/* Scan all PCI buses. Generate tables to support hotplug. */
+bu

[Qemu-devel] [PATCH RFC 6/6] hw/ich9: enable acpi pci hotplug

2017-06-29 Thread Aleksandr Bezzubikov
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/acpi/ich9.c | 31 +++
 hw/isa/lpc_ich9.c  | 12 
 include/hw/acpi/ich9.h |  4 
 include/hw/i386/pc.h   |  7 ++-
 4 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 5c279bb..25339eb 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -258,6 +258,7 @@ static void pm_reset(void *opaque)
 }
 pm->smi_en_wmask = ~0;
 
+acpi_pcihp_reset(>acpi_pci_hotplug);
 acpi_update_sci(>acpi_regs, pm->irq);
 }
 
@@ -301,6 +302,10 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
 pm->powerdown_notifier.notify = pm_powerdown_req;
 qemu_register_powerdown_notifier(>powerdown_notifier);
 
+acpi_pcihp_init(OBJECT(lpc_pci), >acpi_pci_hotplug, lpc_pci->bus,
+pci_address_space_io(lpc_pci),
+pm->use_acpi_pci_hotplug);
+
 legacy_acpi_cpu_hotplug_init(pci_address_space_io(lpc_pci),
 OBJECT(lpc_pci), >gpe_cpu, ICH9_CPU_HOTPLUG_IO_BASE);
 
@@ -335,6 +340,21 @@ static void ich9_pm_set_memory_hotplug_support(Object 
*obj, bool value,
 s->pm.acpi_memory_hotplug.is_enabled = value;
 }
 
+static bool ich9_pm_get_acpi_pci_hotplug_support(Object *obj, Error **errp)
+{
+ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
+
+return s->pm.use_acpi_pci_hotplug;
+}
+
+static void ich9_pm_set_acpi_pci_hotplug_support(Object *obj, bool value,
+ Error **errp)
+{
+ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
+
+s->pm.use_acpi_pci_hotplug = value;
+}
+
 static bool ich9_pm_get_cpu_hotplug_legacy(Object *obj, Error **errp)
 {
 ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
@@ -446,6 +466,7 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, 
Error **errp)
 {
 static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN;
 pm->acpi_memory_hotplug.is_enabled = true;
+pm->use_acpi_pci_hotplug = true;
 pm->cpu_hotplug_legacy = true;
 pm->disable_s3 = 0;
 pm->disable_s4 = 0;
@@ -462,6 +483,10 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs 
*pm, Error **errp)
  ich9_pm_get_memory_hotplug_support,
  ich9_pm_set_memory_hotplug_support,
  NULL);
+object_property_add_bool(obj, "acpi-pci-hotplug-with-bridge-support",
+ ich9_pm_get_acpi_pci_hotplug_support,
+ ich9_pm_set_acpi_pci_hotplug_support,
+ NULL);
 object_property_add_bool(obj, "cpu-hotplug-legacy",
  ich9_pm_get_cpu_hotplug_legacy,
  ich9_pm_set_cpu_hotplug_legacy,
@@ -497,6 +522,9 @@ void ich9_pm_device_plug_cb(HotplugHandler *hotplug_dev, 
DeviceState *dev,
 acpi_memory_plug_cb(hotplug_dev, >pm.acpi_memory_hotplug,
 dev, errp);
 }
+} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
+acpi_pcihp_device_plug_cb(hotplug_dev, >pm.acpi_pci_hotplug,
+  dev, errp);
 } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
 if (lpc->pm.cpu_hotplug_legacy) {
 legacy_acpi_cpu_plug_cb(hotplug_dev, >pm.gpe_cpu, dev, errp);
@@ -519,6 +547,9 @@ void ich9_pm_device_unplug_request_cb(HotplugHandler 
*hotplug_dev,
 acpi_memory_unplug_request_cb(hotplug_dev,
   >pm.acpi_memory_hotplug, dev,
   errp);
+} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
+acpi_pcihp_device_unplug_cb(hotplug_dev, >pm.acpi_pci_hotplug,
+dev, errp);
 } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU) &&
!lpc->pm.cpu_hotplug_legacy) {
 acpi_cpu_unplug_request_cb(hotplug_dev, >pm.cpuhp_state,
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index e2215dc..13574d0 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -33,6 +33,7 @@
 #include "hw/hw.h"
 #include "qapi/visitor.h"
 #include "qemu/range.h"
+#include "qapi/error.h"
 #include "hw/isa/isa.h"
 #include "hw/sysbus.h"
 #include "hw/i386/pc.h"
@@ -574,6 +575,15 @@ static const MemoryRegionOps rcrb_mmio_ops = {
 .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
+static void ich9_update_bus_hotplug(PCIBus *pci_bus, void *opaque)
+{
+ICH9LPCState *s = opaque;
+
+if (!pci_bus_is_express(pci_bus)) {
+qbus_set_hotplug_handler(BUS(pci_bus), DEVICE(s), _abort);
+}
+}
+
 static void ich9_lpc_machine_ready(Notifier *n, void *opaque)
 {
 ICH9LPCState *s = container_of(n, ICH9LPCState, machine_ready);
@@ -597,6 +607,8 @@ sta

[Qemu-devel] [PATCH RFC 3/6] hw/acpi: fix pcihp io initialization

2017-06-29 Thread Aleksandr Bezzubikov
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/i386/acpi-build.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index b0dcd34..c99dbcc 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -129,17 +129,18 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
 Object *lpc = ich9_lpc_find();
 Object *obj = NULL;
 QObject *o;
+int pcihp_io_len, pcihp_io_base;
 
 pm->cpu_hp_io_base = 0;
-pm->pcihp_io_base = 0;
-pm->pcihp_io_len = 0;
 if (piix) {
 obj = piix;
 pm->cpu_hp_io_base = PIIX4_CPU_HOTPLUG_IO_BASE;
-pm->pcihp_io_base =
+pcihp_io_base =
 object_property_get_int(obj, ACPI_PCIHP_IO_BASE_PROP, NULL);
-pm->pcihp_io_len =
+pcihp_io_len =
 object_property_get_int(obj, ACPI_PCIHP_IO_LEN_PROP, NULL);
+pm->pcihp_io_base = (pcihp_io_base == -1) ? 0 : pcihp_io_base;
+pm->pcihp_io_len = (pcihp_io_len == -1) ? 0 : pcihp_io_len;
 }
 if (lpc) {
 obj = lpc;
-- 
2.7.4




[Qemu-devel] [PATCH RFC 1/6] hw/acpi: remove dead acpi code

2017-06-29 Thread Aleksandr Bezzubikov
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/i386/acpi-build.c | 10 --
 1 file changed, 10 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index afcadac..6fce967 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1912,16 +1912,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 build_piix4_pci0_int(dsdt);
 } else {
 sb_scope = aml_scope("_SB");
-aml_append(sb_scope,
-aml_operation_region("PCST", AML_SYSTEM_IO, aml_int(0xae00), 
0x0c));
-aml_append(sb_scope,
-aml_operation_region("PCSB", AML_SYSTEM_IO, aml_int(0xae0c), 
0x01));
-field = aml_field("PCSB", AML_ANY_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
-aml_append(field, aml_named_field("PCIB", 8));
-aml_append(sb_scope, field);
-aml_append(dsdt, sb_scope);
-
-sb_scope = aml_scope("_SB");
 dev = aml_device("PCI0");
 aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08")));
 aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03")));
-- 
2.7.4




[Qemu-devel] [PATCH RFC 0/6] q35: add acpi pci hotplug support

2017-06-29 Thread Aleksandr Bezzubikov
The series adds hotplug support to legacy PCI buses for Q35 machines.
The ACPI hotplug code is emitted if at least one legacy pci-bridge is present.

This series is mostly based on past Marcel's series 
https://lists.gnu.org/archive/html/qemu-devel/2016-05/msg05681.html,
but rebased on current master with some minor changes according to current 
codebase.

ACPI code emission approach used in this series can be called "static", 
because it checkswhether a bridge exists only at initial DSDT generation 
moment. 
The main goal is to enable AML PCI hotplug-related code to be generated 
dynamically. 
In other words, the bridge plugged in - a new acpi definition block is
loaded (using LoadTable method). 
This is necessary for PCIE-PCI bridge hotplugging feature. 

Aleksandr Bezzubikov (6):
  hw/acpi: remove dead acpi code
  hw/acpi: simplify dsdt building code
  hw/acpi: fix pcihp io initialization
  hw/acpi: prepare pci hotplug IO for ich9
  hw/acpi: extend acpi pci hotplug support for pci express
  hw/ich9: enable acpi pci hotplug

 hw/acpi/ich9.c |  31 +
 hw/i386/acpi-build.c   | 116 -
 hw/isa/lpc_ich9.c  |  12 +
 include/hw/acpi/ich9.h |   4 ++
 include/hw/i386/pc.h   |   7 ++-
 5 files changed, 111 insertions(+), 59 deletions(-)

-- 
2.7.4




[Qemu-devel] [PATCH RFC 2/6] hw/acpi: simplify dsdt building code

2017-06-29 Thread Aleksandr Bezzubikov
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/i386/acpi-build.c | 59 +++-
 1 file changed, 26 insertions(+), 33 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 6fce967..b0dcd34 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1886,7 +1886,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(machine);
 uint32_t nr_mem = machine->ram_slots;
 int root_bus_limit = 0xFF;
-PCIBus *bus = NULL;
+PCIBus *root_bus = NULL;
 int i;
 
 dsdt = init_aml_allocator();
@@ -1927,6 +1927,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 build_q35_pci0_int(dsdt);
 }
 
+root_bus = PC_MACHINE(machine)->bus;
+assert(root_bus);
+
 if (pcmc->legacy_cpu_hotplug) {
 build_legacy_cpu_hotplug_aml(dsdt, machine, pm->cpu_hp_io_base);
 } else {
@@ -1961,8 +1964,8 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 aml_append(dsdt, scope);
 
 crs_range_set_init(_range_set);
-bus = PC_MACHINE(machine)->bus;
-if (bus) {
+{
+PCIBus *bus = root_bus;
 QLIST_FOREACH(bus, >child, sibling) {
 uint8_t bus_num = pci_bus_num(bus);
 uint8_t numa_node = pci_bus_numa_node(bus);
@@ -2206,38 +2209,28 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 
 sb_scope = aml_scope("\\_SB");
 {
-Object *pci_host;
-PCIBus *bus = NULL;
-
-pci_host = acpi_get_i386_pci_host();
-if (pci_host) {
-bus = PCI_HOST_BRIDGE(pci_host)->bus;
+Aml *scope = aml_scope("PCI0");
+/* Scan all PCI buses. Generate tables to support hotplug. */
+build_append_pci_bus_devices(scope, root_bus, pm->pcihp_bridge_en);
+
+if (misc->tpm_version != TPM_VERSION_UNSPEC) {
+dev = aml_device("ISA.TPM");
+aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31")));
+aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
+crs = aml_resource_template();
+aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
+   TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
+/*
+FIXME: TPM_TIS_IRQ=5 conflicts with PNP0C0F irqs,
+Rewrite to take IRQ from TPM device model and
+fix default IRQ value there to use some unused IRQ
+ */
+/* aml_append(crs, aml_irq_no_flags(TPM_TIS_IRQ)); */
+aml_append(dev, aml_name_decl("_CRS", crs));
+aml_append(scope, dev);
 }
 
-if (bus) {
-Aml *scope = aml_scope("PCI0");
-/* Scan all PCI buses. Generate tables to support hotplug. */
-build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
-
-if (misc->tpm_version != TPM_VERSION_UNSPEC) {
-dev = aml_device("ISA.TPM");
-aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31")));
-aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
-crs = aml_resource_template();
-aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
-   TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
-/*
-FIXME: TPM_TIS_IRQ=5 conflicts with PNP0C0F irqs,
-Rewrite to take IRQ from TPM device model and
-fix default IRQ value there to use some unused IRQ
- */
-/* aml_append(crs, aml_irq_no_flags(TPM_TIS_IRQ)); */
-aml_append(dev, aml_name_decl("_CRS", crs));
-aml_append(scope, dev);
-}
-
-aml_append(sb_scope, scope);
-}
+aml_append(sb_scope, scope);
 }
 aml_append(dsdt, sb_scope);
 
-- 
2.7.4




[Qemu-devel] [PATCH RFC 4/6] hw/acpi: prepare pci hotplug IO for ich9

2017-06-29 Thread Aleksandr Bezzubikov
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/i386/acpi-build.c | 13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index c99dbcc..e434efe 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -135,12 +135,6 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
 if (piix) {
 obj = piix;
 pm->cpu_hp_io_base = PIIX4_CPU_HOTPLUG_IO_BASE;
-pcihp_io_base =
-object_property_get_int(obj, ACPI_PCIHP_IO_BASE_PROP, NULL);
-pcihp_io_len =
-object_property_get_int(obj, ACPI_PCIHP_IO_LEN_PROP, NULL);
-pm->pcihp_io_base = (pcihp_io_base == -1) ? 0 : pcihp_io_base;
-pm->pcihp_io_len = (pcihp_io_len == -1) ? 0 : pcihp_io_len;
 }
 if (lpc) {
 obj = lpc;
@@ -148,6 +142,13 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
 }
 assert(obj);
 
+pcihp_io_base =
+object_property_get_int(obj, ACPI_PCIHP_IO_BASE_PROP, NULL);
+pcihp_io_len =
+object_property_get_int(obj, ACPI_PCIHP_IO_LEN_PROP, NULL);
+pm->pcihp_io_base = (pcihp_io_base == -1) ? 0 : pcihp_io_base;
+pm->pcihp_io_len = (pcihp_io_len == -1) ? 0 : pcihp_io_len;
+
 /* Fill in optional s3/s4 related properties */
 o = object_property_get_qobject(obj, ACPI_PM_PROP_S3_DISABLED, NULL);
 if (o) {
-- 
2.7.4




[Qemu-devel] [PATCH RFC] hw/pci-bridge: implement pcie-pci-bridge device

2017-06-25 Thread Aleksandr Bezzubikov
Signed-off-by: Aleksandr Bezzubikov <zuban...@gmail.com>
---
 hw/pci-bridge/Makefile.objs |   2 +-
 hw/pci-bridge/pcie_pci_bridge.c | 152 
 include/hw/pci/pci.h|   1 +
 3 files changed, 154 insertions(+), 1 deletion(-)
 create mode 100644 hw/pci-bridge/pcie_pci_bridge.c

diff --git a/hw/pci-bridge/Makefile.objs b/hw/pci-bridge/Makefile.objs
index c4683cf..666db37 100644
--- a/hw/pci-bridge/Makefile.objs
+++ b/hw/pci-bridge/Makefile.objs
@@ -1,4 +1,4 @@
-common-obj-y += pci_bridge_dev.o
+common-obj-y += pci_bridge_dev.o pcie_pci_bridge.o
 common-obj-$(CONFIG_PCIE_PORT) += pcie_root_port.o gen_pcie_root_port.o
 common-obj-$(CONFIG_PXB) += pci_expander_bridge.o
 common-obj-$(CONFIG_XIO3130) += xio3130_upstream.o xio3130_downstream.o
diff --git a/hw/pci-bridge/pcie_pci_bridge.c b/hw/pci-bridge/pcie_pci_bridge.c
new file mode 100644
index 000..06b19d6
--- /dev/null
+++ b/hw/pci-bridge/pcie_pci_bridge.c
@@ -0,0 +1,152 @@
+/*
+ * QEMU Generic PCIE-PCI Bridge
+ *
+ * Copyright (c) 2017 Aleksandr Bezzubikov
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/slotid_cap.h"
+
+typedef struct PCIEPCIBridge {
+/*< private >*/
+PCIBridge parent_obj;
+
+#define PCI_BRIDGE_DEV_F_SHPC_REQ 0
+uint32_t flags;
+/*< public >*/
+} PCIEPCIBridge;
+
+#define TYPE_PCIE_PCI_BRIDGE_DEV  "pcie-pci-bridge"
+#define PCIE_PCI_BRIDGE_DEV(obj) \
+OBJECT_CHECK(PCIEPCIBridge, (obj), TYPE_PCIE_PCI_BRIDGE_DEV)
+
+static void pciepci_bridge_realize(PCIDevice *d, Error **errp)
+{
+int rc, pos;
+Error *local_err = NULL;
+
+pci_bridge_initfn(d, TYPE_PCI_BUS);
+
+rc = pci_bridge_ssvid_init(d, 0, 0, 0x32);
+if (rc < 0) {
+error_setg(errp, "Can't add SSVID, error %d", rc);
+goto error;
+}
+
+rc = pcie_cap_init(d, 0, PCI_EXP_TYPE_PCI_BRIDGE, 0);
+if (rc < 0) {
+error_setg(errp, "Can't add PCIE-PCI bridge capability, error %d", rc);
+goto error;
+}
+
+pos = pci_add_capability(d, PCI_CAP_ID_PM, 0, PCI_PM_SIZEOF);
+assert(pos > 0);
+d->exp.pm_cap = pos;
+pci_set_word(d->config + pos + PCI_PM_PMC, 0x3);
+
+pcie_cap_arifwd_init(d);
+pcie_cap_deverr_init(d);
+
+rc = pcie_aer_init(d, PCI_ERR_VER, 0x100, PCI_ERR_SIZEOF, _err);
+if (rc < 0) {
+error_propagate(errp, local_err);
+goto error;
+}
+
+rc = msi_init(d, 0, 1, 1, 1, _err);
+if (rc < 0) {
+error_propagate(errp, local_err);
+}
+
+return;
+
+error:
+pci_bridge_exitfn(d);
+}
+
+static void pciepci_bridge_exit(PCIDevice *d)
+{
+pcie_cap_exit(d);
+pci_bridge_exitfn(d);
+}
+
+static void pciepci_bridge_reset(DeviceState *qdev)
+{
+pci_bridge_reset(qdev);
+}
+
+static void pcie_pci_bridge_write_config(PCIDevice *d,
+uint32_t address, uint32_t val, int len)
+{
+pci_bridge_write_config(d, address, val, len);
+msi_write_config(d, address, val, len);
+}
+
+
+static Property pcie_pci_bridge_dev_properties[] = {
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static const VMStateDescription pciepci_bridge_dev_vmstate = {
+.name = TYPE_PCIE_PCI_BRIDGE_DEV,
+.fields = (VMStateField[]) {
+VMSTATE_PCI_DEVICE(parent_obj, PCIBridge),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void pciepci_bridge_class_init(ObjectClass *klass, void *data)
+{
+PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+k->is_express = 1;
+k->is_bridge = 1;
+k->vendor_id = PCI_VENDOR_ID_REDHAT;
+k->device_id = P

[Qemu-devel] [PATCH RFC] Generic PCIE-to-PCI Bridge

2017-06-25 Thread Aleksandr Bezzubikov
This patch introduces a new device - generic PCI Express to PCI bridge.

Now only x86-specific DMI-to-PCI bridge can be used to enable 
usage of legacy PCI devices on Q35 machine. But this bridge isn't 
cross-platform 
and doesn't support hotplugging.
That's why we need a new generic cross-platform bridge device, which supports 
hotplugging.

This patch creates device only for static CLI usage, 
the next goal is to add ACPI hotplug support.  It will utilize 
in some way past Marcel's RFC series for Q35 ACPI PCI hotplug support 
https://lists.gnu.org/archive/html/qemu-devel/2016-05/msg05681.html, 
but will require dynamic ACPI code emission in case when the bridge was 
hotplugged itself.

Aleksandr Bezzubikov (1):
  hw/pci-bridge: implement pcie-pci-bridge device

 hw/pci-bridge/Makefile.objs |   2 +-
 hw/pci-bridge/pcie_pci_bridge.c | 152 
 include/hw/pci/pci.h|   1 +
 3 files changed, 154 insertions(+), 1 deletion(-)
 create mode 100644 hw/pci-bridge/pcie_pci_bridge.c

-- 
2.7.4