All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support.
@ 2009-10-05 10:06 Isaku Yamahata
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 01/23] pci: fix PCI_DPRINTF() wrt variadic macro Isaku Yamahata
                   ` (25 more replies)
  0 siblings, 26 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

Thanks to Michael's review, patches have been much improved
and became much readable.
I believe I covered almost all the points from him except two.
The rest issues are PRI macros and writing to PCI config space.

- PRI macros
  I think that PRI is already widely used in qemu, so I decided to use it.
  However Michael dislike those macros wanting to convert uintN_t to 
  unsigned int/long/long long.
  Since my main motivation is pci express, this isn't essential for me.
  So I don't insist on uintN_t as long as the patches are accepted.
  However I also prefer consistent coding style, so I'd like to hear
  other's opinion.

- writing to PCI config space
  I eventually introduced some helper functions and a structure
  which can be used by each pci device.
  Maybe there would be a discussion on them.


This patch set is preliminary for q35 based chipset support.
This patch sets does various pci related clean ups and 
64bit bar, pciemmconfig and pci bridge support.

I'm aware that some of patches are already conflicting with
other's patch. It is appriciated to merge some first part of
patches which doesn't conflict.

thanks,

changes from V3:
- indentation
- reworked helper function to update pci configuration space
- dropped pci_conf_init[blw]()
- pci: use PCI_SLOT() and PCI_FUNC(). two more use.
  I kept the acked-by hoping Michael won't be against it.
- pci 64bit bar
  - comment
  - s/PCI_BASE_ADDRESS_SPACE_MEM_64/PCI_BASE_ADDRESS_MEM_TYPE_64/g
  - s/pci_bar_is_64big/pci_bar_is_mem64/g
- pci bridge
  - refined pci_bar_config_offset(). 
- bridge/qdevfy
  - pass -1 for vmstate_register()
  - use pci_create_simple()
  - some clean up
- pci/monitor: print out bridge's filtering values and so on. 
  - fixed io range calculation
  - unified case
  - indentation

changes from V2:
- bug fix pointed out by Gerd Hoffmann
  pci_find_devie()
  pci: make pci configuration transaction more accurate.

changes from V1:
- introduced pcibus_t
- dropped pci_config_[sg]et_xxx()
- many code clean up
- reworked pci_host.h
- reworked pci bus search to introduce tree representation for pci bus
- dropped some non essential patches

Isaku Yamahata (23):
  pci: fix PCI_DPRINTF() wrt variadic macro.
  pci: use appropriate PRIs in PCI_DPRINTF() for portability.
  pci: introduce constant PCI_NUM_PINS for the number of interrupt
    pins, 4.
  pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1.
  pci: use PCI_SLOT() and PCI_FUNC().
  pci: define a constant to represent a unmapped bar and use it.
  pci: helper functions to access PCIDevice::config
  pci: use helper functions to access pci config space.
  pci: introduce pcibus_t to represent pci bus address/size instead of
    uint32_t
  pci: introduce FMT_PCIBUS for printf format for pcibus_t.
  pci: typedef pcibus_t as uint64_t instead of uint32_t.
  pci: 64bit bar support.
  pci: make pci configuration transaction more accurate.
  pci: factor out the logic to get pci device from address.
  pci_host.h: split non-inline static function in pci_host.h into
    pci_host.c
  pci: pcie host and mmcfg support.
  pci: fix pci_default_write_config()
  pci: add helper functions for pci config write function.
  pci: use helper function in pci_default_write_config()
  pci: make bar update function aware of pci bridge.
  pci/brdige: qdevfy and initialize secondary bus and subordinate bus.
  pci: initialize wmask according to pci header type.
  pci/monitor: print out bridge's filtering values and so on.

 Makefile.target               |    8 +-
 hw/ac97.c                     |    2 +-
 hw/apb_pci.c                  |   31 +-
 hw/cirrus_vga.c               |    8 +-
 hw/e1000.c                    |   12 +-
 hw/eepro100.c                 |   10 +-
 hw/es1370.c                   |    2 +-
 hw/grackle_pci.c              |   24 +-
 hw/gt64xxx.c                  |   11 +-
 hw/hw.h                       |   12 +
 hw/ide/pci.c                  |    4 +-
 hw/lsi53c895a.c               |    6 +-
 hw/macio.c                    |    2 +-
 hw/msix.c                     |    2 +-
 hw/msix.h                     |    3 +-
 hw/ne2000.c                   |    2 +-
 hw/openpic.c                  |    2 +-
 hw/pci-hotplug.c              |    6 +-
 hw/pci.c                      |  845 ++++++++++++++++++++++++++++++++---------
 hw/pci.h                      |  187 +++++++++-
 hw/{pci_host.h => pci_host.c} |   61 +++-
 hw/pci_host.h                 |  110 ++----
 hw/pcnet.c                    |    9 +-
 hw/piix_pci.c                 |   16 +-
 hw/ppc4xx_pci.c               |   18 +-
 hw/ppce500_pci.c              |   17 +-
 hw/prep_pci.c                 |   14 +-
 hw/rtl8139.c                  |    4 +-
 hw/sun4u.c                    |    2 +-
 hw/unin_pci.c                 |   47 +--
 hw/usb-ohci.c                 |    2 +-
 hw/usb-uhci.c                 |    2 +-
 hw/vga-pci.c                  |    2 +-
 hw/virtio-pci.c               |    2 +-
 hw/vmware_vga.c               |    4 +-
 hw/wdt_i6300esb.c             |    5 +-
 36 files changed, 1031 insertions(+), 463 deletions(-)
 copy hw/{pci_host.h => pci_host.c} (69%)

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

* [Qemu-devel] [PATCH 01/23] pci: fix PCI_DPRINTF() wrt variadic macro.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 02/23] pci: use appropriate PRIs in PCI_DPRINTF() for portability Isaku Yamahata
                   ` (24 subsequent siblings)
  25 siblings, 0 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

add missing ## in PCI_DPRINTF() to compile.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/pci.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 64d70ed..4392574 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -29,7 +29,7 @@
 
 //#define DEBUG_PCI
 #ifdef DEBUG_PCI
-# define PCI_DPRINTF(format, ...)       printf(format, __VA_ARGS__)
+# define PCI_DPRINTF(format, ...)       printf(format, ## __VA_ARGS__)
 #else
 # define PCI_DPRINTF(format, ...)       do { } while (0)
 #endif
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 02/23] pci: use appropriate PRIs in PCI_DPRINTF() for portability.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 01/23] pci: fix PCI_DPRINTF() wrt variadic macro Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 03/23] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4 Isaku Yamahata
                   ` (23 subsequent siblings)
  25 siblings, 0 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

use appropriate PRIs in PCI_DPRINTF() to print pci config space offset
and value for portability.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 4392574..d281ee2 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -561,7 +561,7 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
     int config_addr, bus_num;
 
 #if 0
-    PCI_DPRINTF("pci_data_write: addr=%08x val=%08x len=%d\n",
+    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
                 addr, val, len);
 #endif
     bus_num = (addr >> 16) & 0xff;
@@ -573,7 +573,8 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
     if (!pci_dev)
         return;
     config_addr = addr & 0xff;
-    PCI_DPRINTF("pci_config_write: %s: addr=%02x val=%08x len=%d\n",
+    PCI_DPRINTF("pci_config_write: %s: "
+                "addr=%02x val=%08"PRI32x" len=%d\n",
                 pci_dev->name, config_addr, val, len);
     pci_dev->config_write(pci_dev, config_addr, val, len);
 }
@@ -609,11 +610,12 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
     }
     config_addr = addr & 0xff;
     val = pci_dev->config_read(pci_dev, config_addr, len);
-    PCI_DPRINTF("pci_config_read: %s: addr=%02x val=%08x len=%d\n",
+    PCI_DPRINTF("pci_config_read: %s: "
+                "addr=%02x val=%08"PRIx32" len=%d\n",
                 pci_dev->name, config_addr, val, len);
  the_end:
 #if 0
-    PCI_DPRINTF("pci_data_read: addr=%08x val=%08x len=%d\n",
+    PCI_DPRINTF("pci_data_read: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
                 addr, val, len);
 #endif
     return val;
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 03/23] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 01/23] pci: fix PCI_DPRINTF() wrt variadic macro Isaku Yamahata
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 02/23] pci: use appropriate PRIs in PCI_DPRINTF() for portability Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 04/23] pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1 Isaku Yamahata
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

introduce constant PCI_NUM_PINS for the number of interrupt pins, 4.
and use it.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/pci.c |    4 ++--
 hw/pci.h |    4 +++-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index d281ee2..40035e6 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -177,7 +177,7 @@ const VMStateDescription vmstate_pci_device = {
         VMSTATE_INT32_LE(version_id, PCIDevice),
         VMSTATE_SINGLE(config, PCIDevice, 0, vmstate_info_pci_config,
                        typeof_field(PCIDevice,config)),
-        VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, 4, 2),
+        VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -337,7 +337,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     pci_dev->config_read = config_read;
     pci_dev->config_write = config_write;
     bus->devices[devfn] = pci_dev;
-    pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, 4);
+    pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, PCI_NUM_PINS);
     pci_dev->version_id = 2; /* Current pci device vmstate version */
     return pci_dev;
 }
diff --git a/hw/pci.h b/hw/pci.h
index caba5c8..37df4ef 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -156,6 +156,8 @@ typedef struct PCIIORegion {
 /* Size of the standard PCI config space */
 #define PCI_CONFIG_SPACE_SIZE 0x100
 
+#define PCI_NUM_PINS 4 /* A-D */
+
 /* Bits in cap_present field. */
 enum {
     QEMU_PCI_CAP_MSIX = 0x1,
@@ -191,7 +193,7 @@ struct PCIDevice {
     qemu_irq *irq;
 
     /* Current IRQ levels.  Used internally by the generic PCI code.  */
-    int irq_state[4];
+    int irq_state[PCI_NUM_PINS];
 
     /* Capability bits */
     uint32_t cap_present;
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 04/23] pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (2 preceding siblings ...)
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 03/23] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4 Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 05/23] pci: use PCI_SLOT() and PCI_FUNC() Isaku Yamahata
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1.
And also define PCI_ROM_ADDRESS which will be used later.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/pci.c |    2 +-
 hw/pci.h |    3 +++
 2 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 40035e6..1016893 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -422,7 +422,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     if (region_num == PCI_ROM_SLOT) {
         addr = 0x30;
         /* ROM enable bit is writeable */
-        wmask |= 1;
+        wmask |= PCI_ROM_ADDRESS_ENABLE;
     } else {
         addr = 0x10 + region_num * 4;
     }
diff --git a/hw/pci.h b/hw/pci.h
index 37df4ef..6144978 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -131,6 +131,9 @@ typedef struct PCIIORegion {
 #define PCI_SUBVENDOR_ID        0x2c    /* obsolete, use PCI_SUBSYSTEM_VENDOR_ID */
 #define PCI_SUBDEVICE_ID        0x2e    /* obsolete, use PCI_SUBSYSTEM_ID */
 
+#define PCI_ROM_ADDRESS         0x30    /* Bits 31..11 are address, 10..1 reserved */
+#define  PCI_ROM_ADDRESS_ENABLE 0x01
+
 /* Bits in the PCI Status Register (PCI 2.3 spec) */
 #define PCI_STATUS_RESERVED1	0x007
 #define PCI_STATUS_INT_STATUS	0x008
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 05/23] pci: use PCI_SLOT() and PCI_FUNC().
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (3 preceding siblings ...)
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 04/23] pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1 Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 06/23] pci: define a constant to represent a unmapped bar and use it Isaku Yamahata
                   ` (20 subsequent siblings)
  25 siblings, 0 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

use PCI_SLOT() and PCI_FUNC() where appropriate instead of
direct use of bit operation.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/apb_pci.c |   10 ++++++----
 hw/pci.c     |    4 ++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index eb77042..9d9f5fc 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -252,11 +252,13 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
                                          0, 32);
     pci_create_simple(d->host_state.bus, 0, "pbm");
     /* APB secondary busses */
-    *bus2 = pci_bridge_init(d->host_state.bus, 8, PCI_VENDOR_ID_SUN,
-                            PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
+    *bus2 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 0),
+                            PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
+                            pci_apb_map_irq,
                             "Advanced PCI Bus secondary bridge 1");
-    *bus3 = pci_bridge_init(d->host_state.bus, 9, PCI_VENDOR_ID_SUN,
-                            PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
+    *bus3 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 1),
+                            PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
+                            pci_apb_map_irq,
                             "Advanced PCI Bus secondary bridge 2");
 
     return d->host_state.bus;
diff --git a/hw/pci.c b/hw/pci.c
index 1016893..3bbc7e3 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -703,7 +703,7 @@ static void pci_info_device(PCIDevice *d)
     const pci_class_desc *desc;
 
     monitor_printf(mon, "  Bus %2d, device %3d, function %d:\n",
-                   d->bus->bus_num, d->devfn >> 3, d->devfn & 7);
+                   d->bus->bus_num, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
     class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE)));
     monitor_printf(mon, "    ");
     desc = pci_class_descriptions;
@@ -1039,7 +1039,7 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
     monitor_printf(mon, "%*sclass %s, addr %02x:%02x.%x, "
                    "pci id %04x:%04x (sub %04x:%04x)\n",
                    indent, "", ctxt,
-                   d->bus->bus_num, d->devfn >> 3, d->devfn & 7,
+                   d->bus->bus_num, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
                    le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))),
                    le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID))),
                    le16_to_cpu(*((uint16_t *)(d->config + PCI_SUBSYSTEM_VENDOR_ID))),
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 06/23] pci: define a constant to represent a unmapped bar and use it.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (4 preceding siblings ...)
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 05/23] pci: use PCI_SLOT() and PCI_FUNC() Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 07/23] pci: helper functions to access PCIDevice::config Isaku Yamahata
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

define a constant to represent a unmapped bar instead of -1 and use it.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/cirrus_vga.c |    2 +-
 hw/pci.c        |   18 +++++++++---------
 hw/pci.h        |    1 +
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 7e95f10..fd2367a 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3206,7 +3206,7 @@ static void pci_cirrus_write_config(PCIDevice *d,
     CirrusVGAState *s = &pvs->cirrus_vga;
 
     pci_default_write_config(d, address, val, len);
-    if (s->vga.map_addr && d->io_regions[0].addr == -1)
+    if (s->vga.map_addr && d->io_regions[0].addr == PCI_BAR_UNMAPPED)
         s->vga.map_addr = 0;
     cirrus_update_memory_access(s);
 }
diff --git a/hw/pci.c b/hw/pci.c
index 3bbc7e3..39791d0 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -366,7 +366,7 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
 
     for(i = 0; i < PCI_NUM_REGIONS; i++) {
         r = &pci_dev->io_regions[i];
-        if (!r->size || r->addr == -1)
+        if (!r->size || r->addr == PCI_BAR_UNMAPPED)
             continue;
         if (r->type == PCI_ADDRESS_SPACE_IO) {
             isa_unassign_ioport(r->addr, r->size);
@@ -413,7 +413,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     }
 
     r = &pci_dev->io_regions[region_num];
-    r->addr = -1;
+    r->addr = PCI_BAR_UNMAPPED;
     r->size = size;
     r->type = type;
     r->map_func = map_func;
@@ -455,10 +455,10 @@ static void pci_update_mappings(PCIDevice *d)
                     /* NOTE: we have only 64K ioports on PC */
                     if (last_addr <= new_addr || new_addr == 0 ||
                         last_addr >= 0x10000) {
-                        new_addr = -1;
+                        new_addr = PCI_BAR_UNMAPPED;
                     }
                 } else {
-                    new_addr = -1;
+                    new_addr = PCI_BAR_UNMAPPED;
                 }
             } else {
                 if (cmd & PCI_COMMAND_MEMORY) {
@@ -474,17 +474,17 @@ static void pci_update_mappings(PCIDevice *d)
                        mappings, we handle specific values as invalid
                        mappings. */
                     if (last_addr <= new_addr || new_addr == 0 ||
-                        last_addr == -1) {
-                        new_addr = -1;
+                        last_addr == PCI_BAR_UNMAPPED) {
+                        new_addr = PCI_BAR_UNMAPPED;
                     }
                 } else {
                 no_mem_map:
-                    new_addr = -1;
+                    new_addr = PCI_BAR_UNMAPPED;
                 }
             }
             /* now do the real mapping */
             if (new_addr != r->addr) {
-                if (r->addr != -1) {
+                if (r->addr != PCI_BAR_UNMAPPED) {
                     if (r->type & PCI_ADDRESS_SPACE_IO) {
                         int class;
                         /* NOTE: specific hack for IDE in PC case:
@@ -503,7 +503,7 @@ static void pci_update_mappings(PCIDevice *d)
                     }
                 }
                 r->addr = new_addr;
-                if (r->addr != -1) {
+                if (r->addr != PCI_BAR_UNMAPPED) {
                     r->map_func(d, i, r->addr, r->size, r->type);
                 }
             }
diff --git a/hw/pci.h b/hw/pci.h
index 6144978..1bbaf6e 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -85,6 +85,7 @@ typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
 
 typedef struct PCIIORegion {
     uint32_t addr; /* current PCI mapping address. -1 means not mapped */
+#define PCI_BAR_UNMAPPED (~(uint32_t)0)
     uint32_t size;
     uint8_t type;
     PCIMapIORegionFunc *map_func;
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 07/23] pci: helper functions to access PCIDevice::config
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (5 preceding siblings ...)
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 06/23] pci: define a constant to represent a unmapped bar and use it Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 08/23] pci: use helper functions to access pci config space Isaku Yamahata
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

add helper functions to get/set PCIDevice::config
Those will be used later.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/pci.h |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/hw/pci.h b/hw/pci.h
index 1bbaf6e..6d2172c 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -311,6 +311,18 @@ pci_get_long(uint8_t *config)
 }
 
 static inline void
+pci_set_quad(uint8_t *config, uint64_t val)
+{
+    cpu_to_le64w((uint64_t *)config, val);
+}
+
+static inline uint64_t
+pci_get_quad(uint8_t *config)
+{
+    return le64_to_cpup((uint64_t *)config);
+}
+
+static inline void
 pci_config_set_vendor_id(uint8_t *pci_config, uint16_t val)
 {
     pci_set_word(&pci_config[PCI_VENDOR_ID], val);
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 08/23] pci: use helper functions to access pci config space.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (6 preceding siblings ...)
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 07/23] pci: helper functions to access PCIDevice::config Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 09/23] pci: introduce pcibus_t to represent pci bus address/size instead of uint32_t Isaku Yamahata
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

use pci_[gs]et_{byte, word, long}() to access pci configuration
space.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/pci.c |   38 ++++++++++++++++++--------------------
 1 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 39791d0..21e23b0 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -426,9 +426,9 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     } else {
         addr = 0x10 + region_num * 4;
     }
-    *(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type);
-    *(uint32_t *)(pci_dev->wmask + addr) = cpu_to_le32(wmask);
-    *(uint32_t *)(pci_dev->cmask + addr) = 0xffffffff;
+    pci_set_long(pci_dev->config + addr, type);
+    pci_set_long(pci_dev->wmask + addr, wmask);
+    pci_set_long(pci_dev->cmask + addr, 0xffffffff);
 }
 
 static void pci_update_mappings(PCIDevice *d)
@@ -437,7 +437,7 @@ static void pci_update_mappings(PCIDevice *d)
     int cmd, i;
     uint32_t last_addr, new_addr, config_ofs;
 
-    cmd = le16_to_cpu(*(uint16_t *)(d->config + PCI_COMMAND));
+    cmd = pci_get_word(d->config + PCI_COMMAND);
     for(i = 0; i < PCI_NUM_REGIONS; i++) {
         r = &d->io_regions[i];
         if (i == PCI_ROM_SLOT) {
@@ -448,8 +448,7 @@ static void pci_update_mappings(PCIDevice *d)
         if (r->size != 0) {
             if (r->type & PCI_ADDRESS_SPACE_IO) {
                 if (cmd & PCI_COMMAND_IO) {
-                    new_addr = le32_to_cpu(*(uint32_t *)(d->config +
-                                                         config_ofs));
+                    new_addr = pci_get_long(d->config + config_ofs);
                     new_addr = new_addr & ~(r->size - 1);
                     last_addr = new_addr + r->size - 1;
                     /* NOTE: we have only 64K ioports on PC */
@@ -462,8 +461,7 @@ static void pci_update_mappings(PCIDevice *d)
                 }
             } else {
                 if (cmd & PCI_COMMAND_MEMORY) {
-                    new_addr = le32_to_cpu(*(uint32_t *)(d->config +
-                                                         config_ofs));
+                    new_addr = pci_get_long(d->config + config_ofs);
                     /* the ROM slot has a specific enable bit */
                     if (i == PCI_ROM_SLOT && !(new_addr & 1))
                         goto no_mem_map;
@@ -489,7 +487,7 @@ static void pci_update_mappings(PCIDevice *d)
                         int class;
                         /* NOTE: specific hack for IDE in PC case:
                            only one byte must be mapped. */
-                        class = d->config[0x0a] | (d->config[0x0b] << 8);
+                        class = pci_get_word(d->config + PCI_CLASS_DEVICE);
                         if (class == 0x0101 && r->size == 4) {
                             isa_unassign_ioport(r->addr + 2, 1);
                         } else {
@@ -520,18 +518,18 @@ uint32_t pci_default_read_config(PCIDevice *d,
     default:
     case 4:
 	if (address <= 0xfc) {
-	    val = le32_to_cpu(*(uint32_t *)(d->config + address));
+            val = pci_get_long(d->config + address);
 	    break;
 	}
 	/* fall through */
     case 2:
         if (address <= 0xfe) {
-	    val = le16_to_cpu(*(uint16_t *)(d->config + address));
+            val = pci_get_word(d->config + address);
 	    break;
 	}
 	/* fall through */
     case 1:
-        val = d->config[address];
+        val = pci_get_byte(d->config + address);
         break;
     }
     return val;
@@ -704,7 +702,7 @@ static void pci_info_device(PCIDevice *d)
 
     monitor_printf(mon, "  Bus %2d, device %3d, function %d:\n",
                    d->bus->bus_num, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
-    class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE)));
+    class = pci_get_word(d->config + PCI_CLASS_DEVICE);
     monitor_printf(mon, "    ");
     desc = pci_class_descriptions;
     while (desc->desc && class != desc->class)
@@ -715,8 +713,8 @@ static void pci_info_device(PCIDevice *d)
         monitor_printf(mon, "Class %04x", class);
     }
     monitor_printf(mon, ": PCI device %04x:%04x\n",
-           le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))),
-           le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID))));
+           pci_get_word(d->config + PCI_VENDOR_ID),
+           pci_get_word(d->config + PCI_DEVICE_ID));
 
     if (d->config[PCI_INTERRUPT_PIN] != 0) {
         monitor_printf(mon, "      IRQ %d.\n",
@@ -1026,7 +1024,7 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
     PCIIORegion *r;
     int i, class;
 
-    class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE)));
+    class = pci_get_word(d->config + PCI_CLASS_DEVICE);
     desc = pci_class_descriptions;
     while (desc->desc && class != desc->class)
         desc++;
@@ -1040,10 +1038,10 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
                    "pci id %04x:%04x (sub %04x:%04x)\n",
                    indent, "", ctxt,
                    d->bus->bus_num, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
-                   le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))),
-                   le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID))),
-                   le16_to_cpu(*((uint16_t *)(d->config + PCI_SUBSYSTEM_VENDOR_ID))),
-                   le16_to_cpu(*((uint16_t *)(d->config + PCI_SUBSYSTEM_ID))));
+                   pci_get_word(d->config + PCI_VENDOR_ID),
+                   pci_get_word(d->config + PCI_DEVICE_ID),
+                   pci_get_word(d->config + PCI_SUBSYSTEM_VENDOR_ID),
+                   pci_get_word(d->config + PCI_SUBSYSTEM_ID));
     for (i = 0; i < PCI_NUM_REGIONS; i++) {
         r = &d->io_regions[i];
         if (!r->size)
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 09/23] pci: introduce pcibus_t to represent pci bus address/size instead of uint32_t
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (7 preceding siblings ...)
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 08/23] pci: use helper functions to access pci config space Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 10/23] pci: introduce FMT_PCIBUS for printf format for pcibus_t Isaku Yamahata
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

This patch is preliminary for 64 bit BAR support.
Introduce dedicated type, pcibus_t, to represent pci bus address/size
instead of uint32_t.
Later this type will be changed to uint64_t.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/ac97.c         |    2 +-
 hw/cirrus_vga.c   |    4 ++--
 hw/e1000.c        |    6 +++---
 hw/eepro100.c     |    4 ++--
 hw/es1370.c       |    2 +-
 hw/ide/pci.c      |    4 ++--
 hw/lsi53c895a.c   |    6 +++---
 hw/macio.c        |    2 +-
 hw/msix.c         |    2 +-
 hw/msix.h         |    3 ++-
 hw/ne2000.c       |    2 +-
 hw/openpic.c      |    2 +-
 hw/pci.c          |    7 ++++---
 hw/pci.h          |   12 +++++++-----
 hw/pcnet.c        |    4 ++--
 hw/rtl8139.c      |    4 ++--
 hw/sun4u.c        |    2 +-
 hw/usb-ohci.c     |    2 +-
 hw/usb-uhci.c     |    2 +-
 hw/vga-pci.c      |    2 +-
 hw/virtio-pci.c   |    2 +-
 hw/vmware_vga.c   |    4 ++--
 hw/wdt_i6300esb.c |    2 +-
 23 files changed, 43 insertions(+), 39 deletions(-)

diff --git a/hw/ac97.c b/hw/ac97.c
index 610ca60..e3f0dbc 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -1250,7 +1250,7 @@ static int ac97_load (QEMUFile *f, void *opaque, int version_id)
 }
 
 static void ac97_map (PCIDevice *pci_dev, int region_num,
-                      uint32_t addr, uint32_t size, int type)
+                      pcibus_t addr, pcibus_t size, int type)
 {
     AC97LinkState *s = DO_UPCAST (AC97LinkState, dev, pci_dev);
     PCIDevice *d = &s->dev;
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index fd2367a..2a6aba8 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3170,7 +3170,7 @@ void isa_cirrus_vga_init(void)
  ***************************************/
 
 static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
-			       uint32_t addr, uint32_t size, int type)
+			       pcibus_t addr, pcibus_t size, int type)
 {
     CirrusVGAState *s = &DO_UPCAST(PCICirrusVGAState, dev, d)->cirrus_vga;
 
@@ -3191,7 +3191,7 @@ static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
 }
 
 static void cirrus_pci_mmio_map(PCIDevice *d, int region_num,
-				uint32_t addr, uint32_t size, int type)
+				pcibus_t addr, pcibus_t size, int type)
 {
     CirrusVGAState *s = &DO_UPCAST(PCICirrusVGAState, dev, d)->cirrus_vga;
 
diff --git a/hw/e1000.c b/hw/e1000.c
index 95c471c..c07eb42 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -142,8 +142,8 @@ static const char phy_regcap[0x20] = {
 };
 
 static void
-ioport_map(PCIDevice *pci_dev, int region_num, uint32_t addr,
-           uint32_t size, int type)
+ioport_map(PCIDevice *pci_dev, int region_num, pcibus_t addr,
+           pcibus_t size, int type)
 {
     DBGOUT(IO, "e1000_ioport_map addr=0x%04x size=0x%08x\n", addr, size);
 }
@@ -1030,7 +1030,7 @@ static CPUReadMemoryFunc * const e1000_mmio_read[] = {
 
 static void
 e1000_mmio_map(PCIDevice *pci_dev, int region_num,
-                uint32_t addr, uint32_t size, int type)
+                pcibus_t addr, pcibus_t size, int type)
 {
     E1000State *d = DO_UPCAST(E1000State, dev, pci_dev);
     int i;
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 3f84e26..1a1a0da 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1374,7 +1374,7 @@ static void ioport_write4(void *opaque, uint32_t addr, uint32_t val)
 /* PCI EEPRO100 definitions */
 
 static void pci_map(PCIDevice * pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    pcibus_t addr, pcibus_t size, int type)
 {
     EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
 
@@ -1453,7 +1453,7 @@ static CPUReadMemoryFunc * const pci_mmio_read[] = {
 };
 
 static void pci_mmio_map(PCIDevice * pci_dev, int region_num,
-                         uint32_t addr, uint32_t size, int type)
+                         pcibus_t addr, pcibus_t size, int type)
 {
     EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
 
diff --git a/hw/es1370.c b/hw/es1370.c
index 9071a48..b42809d 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -907,7 +907,7 @@ static void es1370_adc_callback (void *opaque, int avail)
 }
 
 static void es1370_map (PCIDevice *pci_dev, int region_num,
-                        uint32_t addr, uint32_t size, int type)
+                        pcibus_t addr, pcibus_t size, int type)
 {
     ES1370State *s = DO_UPCAST (ES1370State, dev, pci_dev);
 
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 89ecd44..125f04d 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -60,7 +60,7 @@ typedef struct PCIIDEState {
 static void cmd646_update_irq(PCIIDEState *d);
 
 static void ide_map(PCIDevice *pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    pcibus_t addr, pcibus_t size, int type)
 {
     PCIIDEState *d = (PCIIDEState *)pci_dev;
     IDEBus *bus;
@@ -245,7 +245,7 @@ static void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val)
 }
 
 static void bmdma_map(PCIDevice *pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    pcibus_t addr, pcibus_t size, int type)
 {
     PCIIDEState *d = (PCIIDEState *)pci_dev;
     int i;
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 62bdca8..d62581a 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -1926,7 +1926,7 @@ static void lsi_io_writel(void *opaque, uint32_t addr, uint32_t val)
 }
 
 static void lsi_io_mapfunc(PCIDevice *pci_dev, int region_num,
-                           uint32_t addr, uint32_t size, int type)
+                           pcibus_t addr, pcibus_t size, int type)
 {
     LSIState *s = DO_UPCAST(LSIState, dev, pci_dev);
 
@@ -1941,7 +1941,7 @@ static void lsi_io_mapfunc(PCIDevice *pci_dev, int region_num,
 }
 
 static void lsi_ram_mapfunc(PCIDevice *pci_dev, int region_num,
-                            uint32_t addr, uint32_t size, int type)
+                            pcibus_t addr, pcibus_t size, int type)
 {
     LSIState *s = DO_UPCAST(LSIState, dev, pci_dev);
 
@@ -1951,7 +1951,7 @@ static void lsi_ram_mapfunc(PCIDevice *pci_dev, int region_num,
 }
 
 static void lsi_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
-                             uint32_t addr, uint32_t size, int type)
+                             pcibus_t addr, pcibus_t size, int type)
 {
     LSIState *s = DO_UPCAST(LSIState, dev, pci_dev);
 
diff --git a/hw/macio.c b/hw/macio.c
index 8cfadfc..f3340da 100644
--- a/hw/macio.c
+++ b/hw/macio.c
@@ -40,7 +40,7 @@ struct macio_state_t {
 };
 
 static void macio_map (PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       pcibus_t addr, pcibus_t size, int type)
 {
     macio_state_t *macio_state;
     int i;
diff --git a/hw/msix.c b/hw/msix.c
index 3782994..4300c4e 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -201,7 +201,7 @@ static CPUReadMemoryFunc * const msix_mmio_read[] = {
 
 /* Should be called from device's map method. */
 void msix_mmio_map(PCIDevice *d, int region_num,
-                   uint32_t addr, uint32_t size, int type)
+                   pcibus_t addr, pcibus_t size, int type)
 {
     uint8_t *config = d->config + d->msix_cap;
     uint32_t table = pci_get_long(config + MSIX_TABLE_OFFSET);
diff --git a/hw/msix.h b/hw/msix.h
index 9367ba3..2ff754a 100644
--- a/hw/msix.h
+++ b/hw/msix.h
@@ -2,6 +2,7 @@
 #define QEMU_MSIX_H
 
 #include "qemu-common.h"
+#include "pci.h"
 
 int msix_init(struct PCIDevice *dev, unsigned short nentries,
               unsigned bar_nr, unsigned bar_size,
@@ -11,7 +12,7 @@ void msix_write_config(PCIDevice *pci_dev, uint32_t address,
                        uint32_t val, int len);
 
 void msix_mmio_map(PCIDevice *pci_dev, int region_num,
-                   uint32_t addr, uint32_t size, int type);
+                   pcibus_t addr, pcibus_t size, int type);
 
 int msix_uninit(PCIDevice *d);
 
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 87f1e59..d77ea73 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -715,7 +715,7 @@ static int pci_ne2000_load(QEMUFile* f, void* opaque, int version_id)
 /* PCI NE2000 definitions */
 
 static void ne2000_map(PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       pcibus_t addr, pcibus_t size, int type)
 {
     PCINE2000State *d = DO_UPCAST(PCINE2000State, dev, pci_dev);
     NE2000State *s = &d->ne2000;
diff --git a/hw/openpic.c b/hw/openpic.c
index 74dde6d..a2f3990 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -1026,7 +1026,7 @@ static CPUReadMemoryFunc * const openpic_read[] = {
 };
 
 static void openpic_map(PCIDevice *pci_dev, int region_num,
-                        uint32_t addr, uint32_t size, int type)
+                        pcibus_t addr, pcibus_t size, int type)
 {
     openpic_t *opp;
 
diff --git a/hw/pci.c b/hw/pci.c
index 21e23b0..674daba 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -396,12 +396,12 @@ int pci_unregister_device(PCIDevice *pci_dev)
 }
 
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
-                            uint32_t size, int type,
+                            pcibus_t size, int type,
                             PCIMapIORegionFunc *map_func)
 {
     PCIIORegion *r;
     uint32_t addr;
-    uint32_t wmask;
+    pcibus_t wmask;
 
     if ((unsigned int)region_num >= PCI_NUM_REGIONS)
         return;
@@ -435,7 +435,8 @@ static void pci_update_mappings(PCIDevice *d)
 {
     PCIIORegion *r;
     int cmd, i;
-    uint32_t last_addr, new_addr, config_ofs;
+    pcibus_t last_addr, new_addr;
+    uint32_t config_ofs;
 
     cmd = pci_get_word(d->config + PCI_COMMAND);
     for(i = 0; i < PCI_NUM_REGIONS; i++) {
diff --git a/hw/pci.h b/hw/pci.h
index 6d2172c..2796c1d 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -71,12 +71,14 @@ extern target_phys_addr_t pci_mem_base;
 #define PCI_DEVICE_ID_VIRTIO_BALLOON     0x1002
 #define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003
 
+typedef uint32_t pcibus_t;
+
 typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
                                 uint32_t address, uint32_t data, int len);
 typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev,
                                    uint32_t address, int len);
 typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
-                                uint32_t addr, uint32_t size, int type);
+                                pcibus_t addr, pcibus_t size, int type);
 typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
 
 #define PCI_ADDRESS_SPACE_MEM		0x00
@@ -84,9 +86,9 @@ typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
 #define PCI_ADDRESS_SPACE_MEM_PREFETCH	0x08
 
 typedef struct PCIIORegion {
-    uint32_t addr; /* current PCI mapping address. -1 means not mapped */
-#define PCI_BAR_UNMAPPED (~(uint32_t)0)
-    uint32_t size;
+    pcibus_t addr; /* current PCI mapping address. -1 means not mapped */
+#define PCI_BAR_UNMAPPED (~(pcibus_t)0)
+    pcibus_t size;
     uint8_t type;
     PCIMapIORegionFunc *map_func;
 } PCIIORegion;
@@ -233,7 +235,7 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
 int pci_unregister_device(PCIDevice *pci_dev);
 
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
-                            uint32_t size, int type,
+                            pcibus_t size, int type,
                             PCIMapIORegionFunc *map_func);
 
 int pci_add_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size);
diff --git a/hw/pcnet.c b/hw/pcnet.c
index ae98a20..2789574 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -1761,7 +1761,7 @@ static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
 }
 
 static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
-                             uint32_t addr, uint32_t size, int type)
+                             pcibus_t addr, pcibus_t size, int type)
 {
     PCNetState *d = &DO_UPCAST(PCIPCNetState, pci_dev, pci_dev)->state;
 
@@ -1989,7 +1989,7 @@ static CPUReadMemoryFunc * const pcnet_mmio_read[] = {
 };
 
 static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
-                            uint32_t addr, uint32_t size, int type)
+                            pcibus_t addr, pcibus_t size, int type)
 {
     PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
 
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 83cb1ff..6856b23 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3324,7 +3324,7 @@ static int rtl8139_load(QEMUFile* f,void* opaque,int version_id)
 /* PCI RTL8139 definitions */
 
 static void rtl8139_mmio_map(PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       pcibus_t addr, pcibus_t size, int type)
 {
     RTL8139State *s = DO_UPCAST(RTL8139State, dev, pci_dev);
 
@@ -3332,7 +3332,7 @@ static void rtl8139_mmio_map(PCIDevice *pci_dev, int region_num,
 }
 
 static void rtl8139_ioport_map(PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       pcibus_t addr, pcibus_t size, int type)
 {
     RTL8139State *s = DO_UPCAST(RTL8139State, dev, pci_dev);
 
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 2c97d9d..5812782 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -344,7 +344,7 @@ static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
 static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 
 static void ebus_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
-                              uint32_t addr, uint32_t size, int type)
+                              pcibus_t addr, pcibus_t size, int type)
 {
     DPRINTF("Mapping region %d registers at %08x\n", region_num, addr);
     switch (region_num) {
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 6e428c4..7a92efd 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1707,7 +1707,7 @@ typedef struct {
 } OHCIPCIState;
 
 static void ohci_mapfunc(PCIDevice *pci_dev, int i,
-            uint32_t addr, uint32_t size, int type)
+            pcibus_t addr, pcibus_t size, int type)
 {
     OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, pci_dev);
     cpu_register_physical_memory(addr, size, ohci->state.mem);
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 6807413..abeb552 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1059,7 +1059,7 @@ static void uhci_frame_timer(void *opaque)
 }
 
 static void uhci_map(PCIDevice *pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    pcibus_t addr, pcibus_t size, int type)
 {
     UHCIState *s = (UHCIState *)pci_dev;
 
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index 6038cec..b0e4262 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -71,7 +71,7 @@ void vga_dirty_log_start(VGACommonState *s)
 }
 
 static void vga_map(PCIDevice *pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    pcibus_t addr, pcibus_t size, int type)
 {
     PCIVGAState *d = (PCIVGAState *)pci_dev;
     VGACommonState *s = &d->vga;
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index bd5a7c4..e68823a 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -342,7 +342,7 @@ static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
 }
 
 static void virtio_map(PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       pcibus_t addr, pcibus_t size, int type)
 {
     VirtIOPCIProxy *proxy = container_of(pci_dev, VirtIOPCIProxy, pci_dev);
     VirtIODevice *vdev = proxy->vdev;
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index a273f35..945d57e 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1174,7 +1174,7 @@ static int pci_vmsvga_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
-                uint32_t addr, uint32_t size, int type)
+                pcibus_t addr, pcibus_t size, int type)
 {
     struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
     struct vmsvga_state_s *s = &d->chip;
@@ -1194,7 +1194,7 @@ static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
 }
 
 static void pci_vmsvga_map_mem(PCIDevice *pci_dev, int region_num,
-                uint32_t addr, uint32_t size, int type)
+                pcibus_t addr, pcibus_t size, int type)
 {
     struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
     struct vmsvga_state_s *s = &d->chip;
diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c
index 3abaa87..d3ab3c8 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -347,7 +347,7 @@ static void i6300esb_mem_writel(void *vp, target_phys_addr_t addr, uint32_t val)
 }
 
 static void i6300esb_map(PCIDevice *dev, int region_num,
-                         uint32_t addr, uint32_t size, int type)
+                         pcibus_t addr, pcibus_t size, int type)
 {
     static CPUReadMemoryFunc * const mem_read[3] = {
         i6300esb_mem_readb,
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 10/23] pci: introduce FMT_PCIBUS for printf format for pcibus_t.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (8 preceding siblings ...)
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 09/23] pci: introduce pcibus_t to represent pci bus address/size instead of uint32_t Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 13:41   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 11/23] pci: typedef pcibus_t as uint64_t instead of uint32_t Isaku Yamahata
                   ` (15 subsequent siblings)
  25 siblings, 1 reply; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

This patch is preliminary for 64bit BAR.
Later pcibus_t will be changed from uint32_t to uint64_t.
Introduce FMT_PCIBUS for printf format for pcibus_t.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/e1000.c        |    6 ++++--
 hw/eepro100.c     |    6 ++++--
 hw/pci.c          |   11 ++++++-----
 hw/pci.h          |    1 +
 hw/pcnet.c        |    5 +++--
 hw/wdt_i6300esb.c |    3 ++-
 6 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/hw/e1000.c b/hw/e1000.c
index c07eb42..8721e0e 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -145,7 +145,8 @@ static void
 ioport_map(PCIDevice *pci_dev, int region_num, pcibus_t addr,
            pcibus_t size, int type)
 {
-    DBGOUT(IO, "e1000_ioport_map addr=0x%04x size=0x%08x\n", addr, size);
+    DBGOUT(IO, "e1000_ioport_map addr=0x%04"FMT_PCIBUS" size=0x%08"FMT_PCIBUS"\n",
+           addr, size);
 }
 
 static void
@@ -1040,7 +1041,8 @@ e1000_mmio_map(PCIDevice *pci_dev, int region_num,
     };
 
 
-    DBGOUT(MMIO, "e1000_mmio_map addr=0x%08x 0x%08x\n", addr, size);
+    DBGOUT(MMIO, "e1000_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n",
+           addr, size);
 
     cpu_register_physical_memory(addr, PNPMMIO_SIZE, d->mmio_index);
     qemu_register_coalesced_mmio(addr, excluded_regs[0]);
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 1a1a0da..52bfb1f 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1378,7 +1378,8 @@ static void pci_map(PCIDevice * pci_dev, int region_num,
 {
     EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
 
-    TRACE(OTHER, logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n",
+    TRACE(OTHER, logout("region %d, addr=0x%08"FMT_PCIBUS", "
+          "size=0x%08"FMT_PCIBUS", type=%d\n",
           region_num, addr, size, type));
 
     assert(region_num == 1);
@@ -1457,7 +1458,8 @@ static void pci_mmio_map(PCIDevice * pci_dev, int region_num,
 {
     EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
 
-    TRACE(OTHER, logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n",
+    TRACE(OTHER, logout("region %d, addr=0x%08"FMT_PCIBUS", "
+          "size=0x%08"FMT_PCIBUS", type=%d\n",
           region_num, addr, size, type));
 
     if (region_num == 0) {
diff --git a/hw/pci.c b/hw/pci.c
index 674daba..8d6e8ea 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -408,7 +408,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
 
     if (size & (size-1)) {
         fprintf(stderr, "ERROR: PCI region size must be pow2 "
-                    "type=0x%x, size=0x%x\n", type, size);
+                    "type=0x%x, size=0x%"FMT_PCIBUS"\n", type, size);
         exit(1);
     }
 
@@ -427,7 +427,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
         addr = 0x10 + region_num * 4;
     }
     pci_set_long(pci_dev->config + addr, type);
-    pci_set_long(pci_dev->wmask + addr, wmask);
+    pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
     pci_set_long(pci_dev->cmask + addr, 0xffffffff);
 }
 
@@ -729,10 +729,10 @@ static void pci_info_device(PCIDevice *d)
         if (r->size != 0) {
             monitor_printf(mon, "      BAR%d: ", i);
             if (r->type & PCI_ADDRESS_SPACE_IO) {
-                monitor_printf(mon, "I/O at 0x%04x [0x%04x].\n",
+                monitor_printf(mon, "I/O at 0x%04"FMT_PCIBUS" [0x%04"FMT_PCIBUS"].\n",
                                r->addr, r->addr + r->size - 1);
             } else {
-                monitor_printf(mon, "32 bit memory at 0x%08x [0x%08x].\n",
+                monitor_printf(mon, "32 bit memory at 0x%08"FMT_PCIBUS" [0x%08"FMT_PCIBUS"].\n",
                                r->addr, r->addr + r->size - 1);
             }
         }
@@ -1047,7 +1047,8 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
         r = &d->io_regions[i];
         if (!r->size)
             continue;
-        monitor_printf(mon, "%*sbar %d: %s at 0x%x [0x%x]\n", indent, "",
+        monitor_printf(mon, "%*sbar %d: %s at 0x%"FMT_PCIBUS" [0x%"FMT_PCIBUS"]\n",
+                       indent, "",
                        i, r->type & PCI_ADDRESS_SPACE_IO ? "i/o" : "mem",
                        r->addr, r->addr + r->size - 1);
     }
diff --git a/hw/pci.h b/hw/pci.h
index 2796c1d..359fce1 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -72,6 +72,7 @@ extern target_phys_addr_t pci_mem_base;
 #define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003
 
 typedef uint32_t pcibus_t;
+#define FMT_PCIBUS                      PRIx32
 
 typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
                                 uint32_t address, uint32_t data, int len);
diff --git a/hw/pcnet.c b/hw/pcnet.c
index 2789574..b4d85a5 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -1766,7 +1766,8 @@ static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
     PCNetState *d = &DO_UPCAST(PCIPCNetState, pci_dev, pci_dev)->state;
 
 #ifdef PCNET_DEBUG_IO
-    printf("pcnet_ioport_map addr=0x%04x size=0x%04x\n", addr, size);
+    printf("pcnet_ioport_map addr=0x%04"FMT_PCIBUS" size=0x%04"FMT_PCIBUS"\n",
+           addr, size);
 #endif
 
     register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
@@ -1994,7 +1995,7 @@ static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
     PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
 
 #ifdef PCNET_DEBUG_IO
-    printf("pcnet_mmio_map addr=0x%08x 0x%08x\n", addr, size);
+    printf("pcnet_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n", addr, size);
 #endif
 
     cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->state.mmio_index);
diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c
index d3ab3c8..88450a8 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -362,7 +362,8 @@ static void i6300esb_map(PCIDevice *dev, int region_num,
     I6300State *d = DO_UPCAST(I6300State, dev, dev);
     int io_mem;
 
-    i6300esb_debug("addr = %x, size = %x, type = %d\n", addr, size, type);
+    i6300esb_debug("addr = %"FMT_PCIBUS", size = %"FMT_PCIBUS", type = %d\n",
+                   addr, size, type);
 
     io_mem = cpu_register_io_memory(mem_read, mem_write, d);
     cpu_register_physical_memory (addr, 0x10, io_mem);
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 11/23] pci: typedef pcibus_t as uint64_t instead of uint32_t.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (9 preceding siblings ...)
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 10/23] pci: introduce FMT_PCIBUS for printf format for pcibus_t Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 20:18   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 12/23] pci: 64bit bar support Isaku Yamahata
                   ` (14 subsequent siblings)
  25 siblings, 1 reply; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

This patch is preliminary for 64bit bar.
For 64bit bar support, change pcibus_t which represents
pci bus addr/size from uint32_t to uint64_t.
And also change FMT_pcibus for printf.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |    6 +++++-
 hw/pci.h |    4 ++--
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 8d6e8ea..21565f5 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -473,7 +473,11 @@ static void pci_update_mappings(PCIDevice *d)
                        mappings, we handle specific values as invalid
                        mappings. */
                     if (last_addr <= new_addr || new_addr == 0 ||
-                        last_addr == PCI_BAR_UNMAPPED) {
+                        last_addr == PCI_BAR_UNMAPPED ||
+
+                        /* keep old behaviour
+                         * without this, PC ide doesn't work well. */
+                        last_addr >= UINT32_MAX) {
                         new_addr = PCI_BAR_UNMAPPED;
                     }
                 } else {
diff --git a/hw/pci.h b/hw/pci.h
index 359fce1..cbf80c0 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -71,8 +71,8 @@ extern target_phys_addr_t pci_mem_base;
 #define PCI_DEVICE_ID_VIRTIO_BALLOON     0x1002
 #define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003
 
-typedef uint32_t pcibus_t;
-#define FMT_PCIBUS                      PRIx32
+typedef uint64_t pcibus_t;
+#define FMT_PCIBUS                      PRIx64
 
 typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
                                 uint32_t address, uint32_t data, int len);
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 12/23] pci: 64bit bar support.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (10 preceding siblings ...)
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 11/23] pci: typedef pcibus_t as uint64_t instead of uint32_t Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 12:06   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-05 12:47   ` Michael S. Tsirkin
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 13/23] pci: make pci configuration transaction more accurate Isaku Yamahata
                   ` (13 subsequent siblings)
  25 siblings, 2 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

implemented pci 64bit bar support.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++--------
 hw/pci.h |    2 ++
 2 files changed, 48 insertions(+), 8 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 21565f5..09a6816 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -395,6 +395,13 @@ int pci_unregister_device(PCIDevice *pci_dev)
     return 0;
 }
 
+static inline int pci_bar_is_mem64(const PCIIORegion *r)
+{
+    return !(r->type & PCI_ADDRESS_SPACE_IO) &&
+        (r->type & PCI_ADDRESS_SPACE_MEM_TYPE_MASK) ==
+        PCI_ADDRESS_SPACE_MEM_TYPE_64;
+}
+
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
                             pcibus_t size, int type,
                             PCIMapIORegionFunc *map_func)
@@ -427,8 +434,13 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
         addr = 0x10 + region_num * 4;
     }
     pci_set_long(pci_dev->config + addr, type);
-    pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
-    pci_set_long(pci_dev->cmask + addr, 0xffffffff);
+    if (pci_bar_is_mem64(r)) {
+        pci_set_quad(pci_dev->wmask + addr, wmask);
+        pci_set_quad(pci_dev->cmask + addr, ~0ULL);
+    } else {
+        pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
+        pci_set_long(pci_dev->cmask + addr, 0xffffffff);
+    }
 }
 
 static void pci_update_mappings(PCIDevice *d)
@@ -462,7 +474,11 @@ static void pci_update_mappings(PCIDevice *d)
                 }
             } else {
                 if (cmd & PCI_COMMAND_MEMORY) {
-                    new_addr = pci_get_long(d->config + config_ofs);
+                    if (pci_bar_is_mem64(r)) {
+                        new_addr = pci_get_quad(d->config + config_ofs);
+                    } else {
+                        new_addr = pci_get_long(d->config + config_ofs);
+                    }
                     /* the ROM slot has a specific enable bit */
                     if (i == PCI_ROM_SLOT && !(new_addr & 1))
                         goto no_mem_map;
@@ -473,11 +489,24 @@ static void pci_update_mappings(PCIDevice *d)
                        mappings, we handle specific values as invalid
                        mappings. */
                     if (last_addr <= new_addr || new_addr == 0 ||
-                        last_addr == PCI_BAR_UNMAPPED ||
+                        last_addr == PCI_BAR_UNMAPPED) {
+                        new_addr = PCI_BAR_UNMAPPED;
+                    }
 
-                        /* keep old behaviour
-                         * without this, PC ide doesn't work well. */
-                        last_addr >= UINT32_MAX) {
+                    /*
+                     * work around: without this, PC ide and other devices
+                     * don't work well.
+                     * OS writes all 1 bits to 32 BAR to find its size
+                     * resulting in setting UINT32_MAX - alignemnt,
+                     * and then OS sets the BAR to where they really want
+                     * the BAR to sit.
+                     * On the other hand, there are some important areas
+                     * blow 4G on i386/x86_64. So setting BAR over those area
+                     * below 4G causes troubles.
+                     * We work around the issues by prohibitting BAR
+                     * from sitting right blow 4G.
+                     */
+                    if (!pci_bar_is_mem64(r) && last_addr >= UINT32_MAX) {
                         new_addr = PCI_BAR_UNMAPPED;
                     }
                 } else {
@@ -736,7 +765,16 @@ static void pci_info_device(PCIDevice *d)
                 monitor_printf(mon, "I/O at 0x%04"FMT_PCIBUS" [0x%04"FMT_PCIBUS"].\n",
                                r->addr, r->addr + r->size - 1);
             } else {
-                monitor_printf(mon, "32 bit memory at 0x%08"FMT_PCIBUS" [0x%08"FMT_PCIBUS"].\n",
+                const char *type = pci_bar_is_mem64(r)? "64 bit": "32 bit";
+                const char *prefetch = "";
+
+                if (r->type & PCI_ADDRESS_SPACE_MEM_PREFETCH) {
+                    prefetch = " prefetchable";
+                }
+
+                monitor_printf(mon, "%s%s memory at "
+                               "0x%08"FMT_PCIBUS" [0x%08"FMT_PCIBUS"].\n",
+                               type, prefetch,
                                r->addr, r->addr + r->size - 1);
             }
         }
diff --git a/hw/pci.h b/hw/pci.h
index cbf80c0..b65ce03 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -84,6 +84,8 @@ typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
 
 #define PCI_ADDRESS_SPACE_MEM		0x00
 #define PCI_ADDRESS_SPACE_IO		0x01
+#define PCI_ADDRESS_SPACE_MEM_TYPE_MASK 0x06
+#define PCI_ADDRESS_SPACE_MEM_TYPE_64   0x04    /* 64 bit address */
 #define PCI_ADDRESS_SPACE_MEM_PREFETCH	0x08
 
 typedef struct PCIIORegion {
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 13/23] pci: make pci configuration transaction more accurate.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (11 preceding siblings ...)
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 12/23] pci: 64bit bar support Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 12:26   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 14/23] pci: factor out the logic to get pci device from address Isaku Yamahata
                   ` (12 subsequent siblings)
  25 siblings, 1 reply; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

This patch sorts out/enhances pci code to track pci bus topology
accurately.
- Track host bus bridge with pci domain number. Although the
  current qemu support only pci domian 0 yet.
- Track pci bridge parent-child relationship.
When looking down from pci host bus for pci sub bus, be aware of
secondary bus/subordinate bus.
Thus pci configuration transaction is more accurately emulated.

This patch adds new member to PCIBus to track pci bus topology.
Since qdev already tracks down bus relationship, those new member
wouldn't be necessary.
However it would be addressed later because not all the pci device
isn't converted to qdev yet.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/apb_pci.c     |    4 +-
 hw/pci-hotplug.c |    6 +-
 hw/pci.c         |  121 ++++++++++++++++++++++++++++++++++++++++--------------
 hw/pci.h         |   11 ++++-
 4 files changed, 103 insertions(+), 39 deletions(-)

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 9d9f5fc..381b924 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -254,11 +254,11 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
     /* APB secondary busses */
     *bus2 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 0),
                             PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
-                            pci_apb_map_irq,
+                            1, 1, pci_apb_map_irq,
                             "Advanced PCI Bus secondary bridge 1");
     *bus3 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 1),
                             PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
-                            pci_apb_map_irq,
+                            2, 2, pci_apb_map_irq,
                             "Advanced PCI Bus secondary bridge 2");
 
     return d->host_state.bus;
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index f3dc421..890ecc3 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -65,7 +65,7 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
         return;
     }
 
-    dev = pci_find_device(pci_bus, slot, 0);
+    dev = pci_find_device(pci_find_host_bus(0), pci_bus, slot, 0);
     if (!dev) {
         monitor_printf(mon, "no pci device with address %s\n", pci_addr);
         return;
@@ -201,7 +201,7 @@ void pci_device_hot_remove(Monitor *mon, const char *pci_addr)
         return;
     }
 
-    d = pci_find_device(bus, slot, 0);
+    d = pci_find_device(pci_find_host_bus(0), bus, slot, 0);
     if (!d) {
         monitor_printf(mon, "slot %d empty\n", slot);
         return;
@@ -228,7 +228,7 @@ static int pci_match_fn(void *dev_private, void *arg)
  */
 void pci_device_hot_remove_success(int pcibus, int slot)
 {
-    PCIDevice *d = pci_find_device(pcibus, slot, 0);
+    PCIDevice *d = pci_find_device(pci_find_host_bus(0), pcibus, slot, 0);
     int class_code;
 
     if (!d) {
diff --git a/hw/pci.c b/hw/pci.c
index 09a6816..6ddd256 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -34,9 +34,12 @@
 # define PCI_DPRINTF(format, ...)       do { } while (0)
 #endif
 
+#define PCI_BUS_NUM_MAX 255
 struct PCIBus {
     BusState qbus;
     int bus_num;
+    int sub_bus;
+
     int devfn_min;
     pci_set_irq_fn set_irq;
     pci_map_irq_fn map_irq;
@@ -44,7 +47,10 @@ struct PCIBus {
     void *irq_opaque;
     PCIDevice *devices[256];
     PCIDevice *parent_dev;
-    PCIBus *next;
+
+    QLIST_HEAD(, PCIBus) child; /* this will be replaced by qdev later */
+    QLIST_ENTRY(PCIBus) sibling;/* this will be replaced by qdev later */
+
     /* The bus IRQ state is the logical OR of the connected devices.
        Keep a count of the number of devices with raised IRQs.  */
     int nirq;
@@ -69,7 +75,13 @@ static void pci_set_irq(void *opaque, int irq_num, int level);
 target_phys_addr_t pci_mem_base;
 static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
 static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
-static PCIBus *first_bus;
+
+struct PCIHostBus {
+    int domain;
+    struct PCIBus *bus;
+    QLIST_ENTRY(PCIHostBus) next;
+};
+static QLIST_HEAD(, PCIHostBus) host_buses;
 
 static const VMStateDescription vmstate_pcibus = {
     .name = "PCIBUS",
@@ -98,6 +110,28 @@ static void pci_bus_reset(void *opaque)
     }
 }
 
+static void pci_host_bus_register(int domain, PCIBus *bus)
+{
+    struct PCIHostBus *host;
+    host = qemu_mallocz(sizeof(*host));
+    host->domain = domain;
+    host->bus = bus;
+    QLIST_INSERT_HEAD(&host_buses, host, next);
+}
+
+PCIBus *pci_find_host_bus(int domain)
+{
+    struct PCIHostBus *host;
+
+    QLIST_FOREACH(host, &host_buses, next) {
+        if (host->domain == domain) {
+            return host->bus;
+        }
+    }
+
+    return NULL;
+}
+
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                          void *irq_opaque, int devfn_min, int nirq)
@@ -112,14 +146,20 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
     bus->devfn_min = devfn_min;
     bus->nirq = nirq;
     bus->irq_count = qemu_mallocz(nirq * sizeof(bus->irq_count[0]));
-    bus->next = first_bus;
-    first_bus = bus;
+
+    /* host bridge */
+    bus->bus_num = 0;
+    bus->sub_bus = PCI_BUS_NUM_MAX;
+    QLIST_INIT(&bus->child);
+    pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */
+
     vmstate_register(nbus++, &vmstate_pcibus, bus);
     qemu_register_reset(pci_bus_reset, bus);
     return bus;
 }
 
-static PCIBus *pci_register_secondary_bus(PCIDevice *dev,
+static PCIBus *pci_register_secondary_bus(PCIBus *parent,
+                                          PCIDevice *dev,
                                           pci_map_irq_fn map_irq,
                                           const char *name)
 {
@@ -128,8 +168,11 @@ static PCIBus *pci_register_secondary_bus(PCIDevice *dev,
     bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, &dev->qdev, name));
     bus->map_irq = map_irq;
     bus->parent_dev = dev;
-    bus->next = dev->bus->next;
-    dev->bus->next = bus;
+
+    bus->bus_num = dev->config[PCI_SECONDARY_BUS];
+    bus->sub_bus = dev->config[PCI_SUBORDINATE_BUS];
+    QLIST_INIT(&bus->child);
+    QLIST_INSERT_HEAD(&parent->child, bus, sibling);
     return bus;
 }
 
@@ -242,7 +285,7 @@ static int pci_parse_devaddr(const char *addr, int *domp, int *busp, unsigned *s
 	return -1;
 
     /* Note: QEMU doesn't implement domains other than 0 */
-    if (dom != 0 || pci_find_bus(bus) == NULL)
+    if (dom != 0 || pci_find_bus(pci_find_host_bus(0), bus) == NULL)
 	return -1;
 
     *domp = dom;
@@ -272,7 +315,7 @@ static PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
 
     if (!devaddr) {
         *devfnp = -1;
-        return pci_find_bus(0);
+        return pci_find_bus(pci_find_host_bus(0), 0);
     }
 
     if (pci_parse_devaddr(devaddr, &dom, &bus, &slot) < 0) {
@@ -280,7 +323,7 @@ static PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
     }
 
     *devfnp = slot << 3;
-    return pci_find_bus(bus);
+    return pci_find_bus(pci_find_host_bus(0), bus);
 }
 
 static void pci_init_cmask(PCIDevice *dev)
@@ -597,8 +640,7 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
                 addr, val, len);
 #endif
     bus_num = (addr >> 16) & 0xff;
-    while (s && s->bus_num != bus_num)
-        s = s->next;
+    s = pci_find_bus(s, bus_num);
     if (!s)
         return;
     pci_dev = s->devices[(addr >> 8) & 0xff];
@@ -619,8 +661,7 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
     uint32_t val;
 
     bus_num = (addr >> 16) & 0xff;
-    while (s && s->bus_num != bus_num)
-        s= s->next;
+    s = pci_find_bus(s, bus_num);
     if (!s)
         goto fail;
     pci_dev = s->devices[(addr >> 8) & 0xff];
@@ -727,7 +768,7 @@ static const pci_class_desc pci_class_descriptions[] =
     { 0, NULL}
 };
 
-static void pci_info_device(PCIDevice *d)
+static void pci_info_device(PCIBus *bus, PCIDevice *d)
 {
     Monitor *mon = cur_mon;
     int i, class;
@@ -781,30 +822,32 @@ static void pci_info_device(PCIDevice *d)
     }
     monitor_printf(mon, "      id \"%s\"\n", d->qdev.id ? d->qdev.id : "");
     if (class == 0x0604 && d->config[0x19] != 0) {
-        pci_for_each_device(d->config[0x19], pci_info_device);
+        pci_for_each_device(bus, d->config[0x19], pci_info_device);
     }
 }
 
-void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
+void pci_for_each_device(PCIBus *bus, int bus_num,
+                         void (*fn)(PCIBus *b, PCIDevice *d))
 {
-    PCIBus *bus = first_bus;
     PCIDevice *d;
     int devfn;
 
-    while (bus && bus->bus_num != bus_num)
-        bus = bus->next;
+    bus = pci_find_bus(bus, bus_num);
     if (bus) {
         for(devfn = 0; devfn < 256; devfn++) {
             d = bus->devices[devfn];
             if (d)
-                fn(d);
+                fn(bus, d);
         }
     }
 }
 
 void pci_info(Monitor *mon)
 {
-    pci_for_each_device(0, pci_info_device);
+    struct PCIHostBus *host;
+    QLIST_FOREACH(host, &host_buses, next) {
+        pci_for_each_device(host->bus, 0, pci_info_device);
+    }
 }
 
 PCIDevice *pci_create(const char *name, const char *devaddr)
@@ -888,22 +931,33 @@ static void pci_bridge_write_config(PCIDevice *d,
 
     pci_default_write_config(d, address, val, len);
     s->bus->bus_num = d->config[PCI_SECONDARY_BUS];
+    s->bus->sub_bus = d->config[PCI_SUBORDINATE_BUS];
 }
 
-PCIBus *pci_find_bus(int bus_num)
+PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
 {
-    PCIBus *bus = first_bus;
+    PCIBus *sec;
 
-    while (bus && bus->bus_num != bus_num)
-        bus = bus->next;
+    if (!bus)
+        return NULL;
 
-    return bus;
+    if (bus->bus_num == bus_num) {
+        return bus;
+    }
+
+    /* try child bus */
+    QLIST_FOREACH(sec, &bus->child, sibling) {
+        if (sec->bus_num <= bus_num && bus_num <= sec->sub_bus) {
+            return pci_find_bus(sec, bus_num);
+        }
+    }
+
+    return NULL;
 }
 
-PCIDevice *pci_find_device(int bus_num, int slot, int function)
+PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function)
 {
-    PCIBus *bus = pci_find_bus(bus_num);
-
+    bus = pci_find_bus(bus, bus_num);
     if (!bus)
         return NULL;
 
@@ -911,6 +965,7 @@ PCIDevice *pci_find_device(int bus_num, int slot, int function)
 }
 
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
+                        uint8_t sec_bus, uint8_t sub_bus,
                         pci_map_irq_fn map_irq, const char *name)
 {
     PCIBridge *s;
@@ -932,7 +987,11 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
         PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE; // header_type
     s->dev.config[0x1E] = 0xa0; // secondary status
 
-    s->bus = pci_register_secondary_bus(&s->dev, map_irq, name);
+    assert(sec_bus <= sub_bus);
+    s->dev.config[PCI_SECONDARY_BUS] = sec_bus;
+    s->dev.config[PCI_SUBORDINATE_BUS] = sub_bus;
+
+    s->bus = pci_register_secondary_bus(bus, &s->dev, map_irq, name);
     return s->bus;
 }
 
diff --git a/hw/pci.h b/hw/pci.h
index b65ce03..00f2b78 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -160,6 +160,9 @@ typedef struct PCIIORegion {
 
 #define PCI_COMMAND_RESERVED_MASK_HI (PCI_COMMAND_RESERVED >> 8)
 
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
+
 /* Size of the standard PCI config header */
 #define PCI_CONFIG_HEADER_SIZE 0x40
 /* Size of the standard PCI config space */
@@ -268,15 +271,17 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
 void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
 uint32_t pci_data_read(void *opaque, uint32_t addr, int len);
 int pci_bus_num(PCIBus *s);
-void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d));
-PCIBus *pci_find_bus(int bus_num);
-PCIDevice *pci_find_device(int bus_num, int slot, int function);
+void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDevice *d));
+PCIBus *pci_find_host_bus(int domain);
+PCIBus *pci_find_bus(PCIBus *bus, int bus_num);
+PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function);
 
 int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
                      unsigned *slotp);
 
 void pci_info(Monitor *mon);
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
+                        uint8_t sec_bus, uint8_t sub_bus,
                         pci_map_irq_fn map_irq, const char *name);
 
 static inline void
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 14/23] pci: factor out the logic to get pci device from address.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (12 preceding siblings ...)
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 13/23] pci: make pci configuration transaction more accurate Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 12:45   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 15/23] pci_host.h: split non-inline static function in pci_host.h into pci_host.c Isaku Yamahata
                   ` (11 subsequent siblings)
  25 siblings, 1 reply; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

factor out conversion logic from io port address into bus+dev+func
with bit shift operation and conversion bus+dev+func into pci device.
They will be used later by pcie support.
This patch also eliminates the logic duplication.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   83 ++++++++++++++++++++++++++++++++++---------------------------
 1 files changed, 46 insertions(+), 37 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 6ddd256..5f808ff 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -629,44 +629,25 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
         pci_update_mappings(d);
 }
 
-void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
+static void pci_data_write_common(PCIDevice *pci_dev,
+                                  uint32_t config_addr, uint32_t val, int len)
 {
-    PCIBus *s = opaque;
-    PCIDevice *pci_dev;
-    int config_addr, bus_num;
-
-#if 0
-    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
-                addr, val, len);
-#endif
-    bus_num = (addr >> 16) & 0xff;
-    s = pci_find_bus(s, bus_num);
-    if (!s)
-        return;
-    pci_dev = s->devices[(addr >> 8) & 0xff];
+    assert(len == 1 || len == 2 || len == 4);
     if (!pci_dev)
         return;
-    config_addr = addr & 0xff;
-    PCI_DPRINTF("pci_config_write: %s: "
-                "addr=%02x val=%08"PRI32x" len=%d\n",
-                pci_dev->name, config_addr, val, len);
+
+    PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRI32x" len=%d\n",
+                __func__, pci_dev->name, config_addr, val, len);
     pci_dev->config_write(pci_dev, config_addr, val, len);
 }
 
-uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
+static uint32_t pci_data_read_common(PCIDevice *pci_dev,
+                                     uint32_t config_addr, int len)
 {
-    PCIBus *s = opaque;
-    PCIDevice *pci_dev;
-    int config_addr, bus_num;
     uint32_t val;
 
-    bus_num = (addr >> 16) & 0xff;
-    s = pci_find_bus(s, bus_num);
-    if (!s)
-        goto fail;
-    pci_dev = s->devices[(addr >> 8) & 0xff];
+    assert(len == 1 || len == 2 || len == 4);
     if (!pci_dev) {
-    fail:
         switch(len) {
         case 1:
             val = 0xff;
@@ -679,21 +660,49 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
             val = 0xffffffff;
             break;
         }
-        goto the_end;
+    } else {
+        val = pci_dev->config_read(pci_dev, config_addr, len);
+        PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
+                    __func__, pci_dev->name, config_addr, val, len);
     }
-    config_addr = addr & 0xff;
-    val = pci_dev->config_read(pci_dev, config_addr, len);
-    PCI_DPRINTF("pci_config_read: %s: "
-                "addr=%02x val=%08"PRIx32" len=%d\n",
-                pci_dev->name, config_addr, val, len);
- the_end:
+
 #if 0
-    PCI_DPRINTF("pci_data_read: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
-                addr, val, len);
+    PCI_DPRINTF("%s: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
+                __func__, addr, val, len);
 #endif
     return val;
 }
 
+static inline PCIDevice *pci_addr_to_dev(PCIBus *bus, uint32_t addr)
+{
+    uint8_t bus_num = (addr >> 16) & 0xff;
+    uint8_t devfn = (addr >> 8) & 0xff;
+    return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
+}
+
+static inline uint32_t pci_addr_to_config(uint32_t addr)
+{
+    return addr & 0xff;
+}
+
+void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
+{
+    PCIBus *s = opaque;
+#if 0
+    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
+                addr, val, len);
+#endif
+
+    pci_data_write_common(pci_addr_to_dev(s, addr), pci_addr_to_config(addr),
+                          val, len);
+}
+
+uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
+{
+    PCIBus *s = opaque;
+    return pci_data_read_common(pci_addr_to_dev(s, addr),
+                                pci_addr_to_config(addr), len);
+}
 /***********************************************************/
 /* generic PCI irq support */
 
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 15/23] pci_host.h: split non-inline static function in pci_host.h into pci_host.c
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (13 preceding siblings ...)
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 14/23] pci: factor out the logic to get pci device from address Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 14:35   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 16/23] pci: pcie host and mmcfg support Isaku Yamahata
                   ` (10 subsequent siblings)
  25 siblings, 1 reply; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

Later a structures declared in pci_host.h, PCIHostState, will be used.
However pci_host.h doesn't allow to include itself easily. This patches
addresses it.

pci_host.h includes non-inline static functions which are instantiated
in .c by including pci_host.h. That prevents from including pci_host.h
to use PCIHostState.
So split pci_host.h non-inline static functions into pci_host.c.
Its purpose to include is to instantiate io function for mmio or ioio.
To avoid including code, we always instantiate both version.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 Makefile.target               |    8 ++--
 hw/apb_pci.c                  |   21 ++-------
 hw/grackle_pci.c              |   24 ++--------
 hw/gt64xxx.c                  |   11 +----
 hw/{pci_host.h => pci_host.c} |   61 +++++++++++++++++++++-----
 hw/pci_host.h                 |   96 ++++++-----------------------------------
 hw/piix_pci.c                 |   16 +++----
 hw/ppc4xx_pci.c               |   18 +-------
 hw/ppce500_pci.c              |   17 +------
 hw/prep_pci.c                 |   14 +++---
 hw/unin_pci.c                 |   47 +++++---------------
 11 files changed, 105 insertions(+), 228 deletions(-)
 copy hw/{pci_host.h => pci_host.c} (69%)

diff --git a/Makefile.target b/Makefile.target
index 1f4518c..2da39b7 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -186,11 +186,11 @@ obj-i386-y += fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
 obj-i386-y += cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
 obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
-obj-i386-y += ne2000-isa.o
+obj-i386-y += ne2000-isa.o pci_host.o
 
 # shared objects
 obj-ppc-y = ppc.o ide/core.o ide/qdev.o ide/isa.o ide/pci.o ide/macio.o
-obj-ppc-y += vga.o vga-pci.o $(sound-obj-y) dma.o openpic.o
+obj-ppc-y += vga.o vga-pci.o $(sound-obj-y) dma.o openpic.o pci_host.o
 # PREP target
 obj-ppc-y += pckbd.o serial.o i8259.o i8254.o fdc.o mc146818rtc.o
 obj-ppc-y += prep_pci.o ppc_prep.o ne2000-isa.o
@@ -217,7 +217,7 @@ obj-mips-y += gt64xxx.o pckbd.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o
 obj-mips-y += piix4.o parallel.o cirrus_vga.o pcspk.o $(sound-obj-y)
 obj-mips-y += mipsnet.o ne2000-isa.o
 obj-mips-y += pflash_cfi01.o
-obj-mips-y += vmware_vga.o
+obj-mips-y += vmware_vga.o pci_host.o
 
 obj-microblaze-y = petalogix_s3adsp1800_mmu.o
 
@@ -244,7 +244,7 @@ obj-cris-y += etraxfs_ser.o
 obj-cris-y += pflash_cfi02.o
 
 ifeq ($(TARGET_ARCH), sparc64)
-obj-sparc-y = sun4u.o pckbd.o apb_pci.o
+obj-sparc-y = sun4u.o pckbd.o apb_pci.o pci_host.o
 obj-sparc-y += ide/core.o ide/qdev.o ide/pci.o
 obj-sparc-y += vga.o vga-pci.o
 obj-sparc-y += fdc.o mc146818rtc.o serial.o
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 381b924..89413b1 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -28,6 +28,7 @@
 
 #include "sysbus.h"
 #include "pci.h"
+#include "pci_host.h"
 
 /* debug APB */
 //#define DEBUG_APB
@@ -39,9 +40,6 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
 #define APB_DPRINTF(fmt, ...)
 #endif
 
-typedef target_phys_addr_t pci_addr_t;
-#include "pci_host.h"
-
 typedef struct APBState {
     SysBusDevice busdev;
     PCIHostState host_state;
@@ -136,18 +134,6 @@ static CPUReadMemoryFunc * const apb_config_read[] = {
     &apb_config_readl,
 };
 
-static CPUWriteMemoryFunc * const pci_apb_write[] = {
-    &pci_host_data_writeb,
-    &pci_host_data_writew,
-    &pci_host_data_writel,
-};
-
-static CPUReadMemoryFunc * const pci_apb_read[] = {
-    &pci_host_data_readb,
-    &pci_host_data_readw,
-    &pci_host_data_readl,
-};
-
 static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
                                   uint32_t val)
 {
@@ -284,8 +270,9 @@ static int pci_pbm_init_device(SysBusDevice *dev)
                                             pci_apb_config_write, s);
     sysbus_init_mmio(dev, 0x10ULL, pci_mem_config);
     /* mem_data */
-    pci_mem_data = cpu_register_io_memory(pci_apb_read,
-                                          pci_apb_write, &s->host_state);
+    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
+                                          pci_host_data_write_mmio,
+                                          &s->host_state);
     sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data);
     return 0;
 }
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index d878cf6..d29175b 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -26,6 +26,7 @@
 #include "sysbus.h"
 #include "ppc_mac.h"
 #include "pci.h"
+#include "pci_host.h"
 
 /* debug Grackle */
 //#define DEBUG_GRACKLE
@@ -37,9 +38,6 @@
 #define GRACKLE_DPRINTF(fmt, ...)
 #endif
 
-typedef target_phys_addr_t pci_addr_t;
-#include "pci_host.h"
-
 typedef struct GrackleState {
     SysBusDevice busdev;
     PCIHostState host_state;
@@ -84,18 +82,6 @@ static CPUReadMemoryFunc * const pci_grackle_config_read[] = {
     &pci_grackle_config_readl,
 };
 
-static CPUWriteMemoryFunc * const pci_grackle_write[] = {
-    &pci_host_data_writeb,
-    &pci_host_data_writew,
-    &pci_host_data_writel,
-};
-
-static CPUReadMemoryFunc * const pci_grackle_read[] = {
-    &pci_host_data_readb,
-    &pci_host_data_readw,
-    &pci_host_data_readl,
-};
-
 /* Don't know if this matches real hardware, but it agrees with OHW.  */
 static int pci_grackle_map_irq(PCIDevice *pci_dev, int irq_num)
 {
@@ -163,8 +149,8 @@ static int pci_grackle_init_device(SysBusDevice *dev)
 
     pci_mem_config = cpu_register_io_memory(pci_grackle_config_read,
                                             pci_grackle_config_write, s);
-    pci_mem_data = cpu_register_io_memory(pci_grackle_read,
-                                          pci_grackle_write,
+    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
+                                          pci_host_data_write_mmio,
                                           &s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
@@ -185,8 +171,8 @@ static int pci_dec_21154_init_device(SysBusDevice *dev)
 
     pci_mem_config = cpu_register_io_memory(pci_grackle_config_read,
                                             pci_grackle_config_write, s);
-    pci_mem_data = cpu_register_io_memory(pci_grackle_read,
-                                          pci_grackle_write,
+    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
+                                          pci_host_data_write_mmio,
                                           &s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 8f9ae4a..fb7f5bd 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -25,10 +25,8 @@
 #include "hw.h"
 #include "mips.h"
 #include "pci.h"
-#include "pc.h"
-
-typedef target_phys_addr_t pci_addr_t;
 #include "pci_host.h"
+#include "pc.h"
 
 //#define DEBUG
 
@@ -1119,13 +1117,6 @@ PCIBus *pci_gt64120_init(qemu_irq *pic)
     GT64120State *s;
     PCIDevice *d;
 
-    (void)&pci_host_data_writeb; /* avoid warning */
-    (void)&pci_host_data_writew; /* avoid warning */
-    (void)&pci_host_data_writel; /* avoid warning */
-    (void)&pci_host_data_readb; /* avoid warning */
-    (void)&pci_host_data_readw; /* avoid warning */
-    (void)&pci_host_data_readl; /* avoid warning */
-
     s = qemu_mallocz(sizeof(GT64120State));
     s->pci = qemu_mallocz(sizeof(GT64120PCIState));
 
diff --git a/hw/pci_host.h b/hw/pci_host.c
similarity index 69%
copy from hw/pci_host.h
copy to hw/pci_host.c
index 48862b5..5c06f03 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.c
@@ -25,10 +25,13 @@
 /* Worker routines for a PCI host controller that uses an {address,data}
    register pair to access PCI configuration space.  */
 
+#ifndef PCI_HOST_C
+
 /* debug PCI */
 //#define DEBUG_PCI
 
-#include "sysbus.h"
+#include "pci.h"
+#include "pci_host.h"
 
 #ifdef DEBUG_PCI
 #define PCI_DPRINTF(fmt, ...) \
@@ -37,13 +40,40 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
 #define PCI_DPRINTF(fmt, ...)
 #endif
 
-typedef struct {
-    SysBusDevice busdev;
-    uint32_t config_reg;
-    PCIBus *bus;
-} PCIHostState;
+#define PCI_HOST_C
+
+#define PCI_ADDR_T      target_phys_addr_t
+#define PCI_HOST_SUFFIX _mmio
+#define PCI_HOST_STATIC static
+
+#include "pci_host.c"
+
+CPUWriteMemoryFunc * const pci_host_data_write_mmio[] = {
+    &glue(pci_host_data_writeb, PCI_HOST_SUFFIX),
+    &glue(pci_host_data_writew, PCI_HOST_SUFFIX),
+    &glue(pci_host_data_writel, PCI_HOST_SUFFIX),
+};
+
+CPUReadMemoryFunc * const pci_host_data_read_mmio[] = {
+    &glue(pci_host_data_readb, PCI_HOST_SUFFIX),
+    &glue(pci_host_data_readw, PCI_HOST_SUFFIX),
+    &glue(pci_host_data_readl, PCI_HOST_SUFFIX),
+};
+
+#undef PCI_ADDR_T
+#undef PCI_HOST_SUFFIX
+#undef PCI_HOST_STATIC
 
-static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
+#define PCI_ADDR_T      uint32_t
+#define PCI_HOST_SUFFIX _ioport
+#define PCI_HOST_STATIC /* nothing. export this function */
+
+#include "pci_host.c"
+
+#else
+
+PCI_HOST_STATIC void glue(pci_host_data_writeb, PCI_HOST_SUFFIX)(
+    void* opaque, PCI_ADDR_T addr, uint32_t val)
 {
     PCIHostState *s = opaque;
 
@@ -53,7 +83,8 @@ static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
         pci_data_write(s->bus, s->config_reg | (addr & 3), val, 1);
 }
 
-static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val)
+PCI_HOST_STATIC void glue(pci_host_data_writew, PCI_HOST_SUFFIX)(
+    void* opaque, PCI_ADDR_T addr, uint32_t val)
 {
     PCIHostState *s = opaque;
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -65,7 +96,8 @@ static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val)
         pci_data_write(s->bus, s->config_reg | (addr & 3), val, 2);
 }
 
-static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
+PCI_HOST_STATIC void glue(pci_host_data_writel, PCI_HOST_SUFFIX)(
+    void* opaque, PCI_ADDR_T addr, uint32_t val)
 {
     PCIHostState *s = opaque;
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -77,7 +109,8 @@ static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
         pci_data_write(s->bus, s->config_reg, val, 4);
 }
 
-static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr)
+PCI_HOST_STATIC uint32_t glue(pci_host_data_readb, PCI_HOST_SUFFIX)(
+    void* opaque, PCI_ADDR_T addr)
 {
     PCIHostState *s = opaque;
     uint32_t val;
@@ -90,7 +123,8 @@ static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr)
     return val;
 }
 
-static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
+PCI_HOST_STATIC uint32_t glue(pci_host_data_readw, PCI_HOST_SUFFIX)(
+    void* opaque, PCI_ADDR_T addr)
 {
     PCIHostState *s = opaque;
     uint32_t val;
@@ -105,7 +139,8 @@ static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
     return val;
 }
 
-static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr)
+PCI_HOST_STATIC uint32_t glue(pci_host_data_readl, PCI_HOST_SUFFIX)(
+    void* opaque, PCI_ADDR_T addr)
 {
     PCIHostState *s = opaque;
     uint32_t val;
@@ -119,3 +154,5 @@ static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr)
 #endif
     return val;
 }
+
+#endif
diff --git a/hw/pci_host.h b/hw/pci_host.h
index 48862b5..ea98ed2 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -25,97 +25,27 @@
 /* Worker routines for a PCI host controller that uses an {address,data}
    register pair to access PCI configuration space.  */
 
-/* debug PCI */
-//#define DEBUG_PCI
+#ifndef PCI_HOST_H
+#define PCI_HOST_H
 
 #include "sysbus.h"
 
-#ifdef DEBUG_PCI
-#define PCI_DPRINTF(fmt, ...) \
-do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define PCI_DPRINTF(fmt, ...)
-#endif
-
 typedef struct {
     SysBusDevice busdev;
     uint32_t config_reg;
     PCIBus *bus;
 } PCIHostState;
 
-static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
-{
-    PCIHostState *s = opaque;
-
-    PCI_DPRINTF("writeb addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-    if (s->config_reg & (1u << 31))
-        pci_data_write(s->bus, s->config_reg | (addr & 3), val, 1);
-}
-
-static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val)
-{
-    PCIHostState *s = opaque;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
-    PCI_DPRINTF("writew addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-    if (s->config_reg & (1u << 31))
-        pci_data_write(s->bus, s->config_reg | (addr & 3), val, 2);
-}
-
-static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
-{
-    PCIHostState *s = opaque;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    PCI_DPRINTF("writel addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-    if (s->config_reg & (1u << 31))
-        pci_data_write(s->bus, s->config_reg, val, 4);
-}
-
-static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr)
-{
-    PCIHostState *s = opaque;
-    uint32_t val;
-
-    if (!(s->config_reg & (1 << 31)))
-        return 0xff;
-    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 1);
-    PCI_DPRINTF("readb addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-    return val;
-}
+/* for mmio */
+extern CPUWriteMemoryFunc * const pci_host_data_write_mmio[];
+extern CPUReadMemoryFunc * const pci_host_data_read_mmio[];
 
-static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
-{
-    PCIHostState *s = opaque;
-    uint32_t val;
-    if (!(s->config_reg & (1 << 31)))
-        return 0xffff;
-    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 2);
-    PCI_DPRINTF("readw addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
-    return val;
-}
+/* for ioio */
+void pci_host_data_writeb_ioport(void* opaque, uint32_t addr, uint32_t val);
+void pci_host_data_writew_ioport(void* opaque, uint32_t addr, uint32_t val);
+void pci_host_data_writel_ioport(void* opaque, uint32_t addr, uint32_t val);
+uint32_t pci_host_data_readb_ioport(void* opaque, uint32_t addr);
+uint32_t pci_host_data_readw_ioport(void* opaque, uint32_t addr);
+uint32_t pci_host_data_readl_ioport(void* opaque, uint32_t addr);
 
-static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr)
-{
-    PCIHostState *s = opaque;
-    uint32_t val;
-    if (!(s->config_reg & (1 << 31)))
-        return 0xffffffff;
-    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 4);
-    PCI_DPRINTF("readl addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    return val;
-}
+#endif /* PCI_HOST_H */
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index edd6df0..c8db791 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -25,12 +25,10 @@
 #include "hw.h"
 #include "pc.h"
 #include "pci.h"
+#include "pci_host.h"
 #include "isa.h"
 #include "sysbus.h"
 
-typedef uint32_t pci_addr_t;
-#include "pci_host.h"
-
 typedef PCIHostState I440FXState;
 
 typedef struct PIIX3State {
@@ -201,12 +199,12 @@ static int i440fx_pcihost_initfn(SysBusDevice *dev)
     register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
     register_ioport_read(0xcf8, 4, 4, i440fx_addr_readl, s);
 
-    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb, s);
-    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew, s);
-    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel, s);
-    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
-    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
-    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
+    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb_ioport, s);
+    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew_ioport, s);
+    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel_ioport, s);
+    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb_ioport, s);
+    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw_ioport, s);
+    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl_ioport, s);
     return 0;
 }
 
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index 655fe86..953e6b6 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -22,8 +22,6 @@
 #include "hw.h"
 #include "ppc.h"
 #include "ppc4xx.h"
-
-typedef target_phys_addr_t pci_addr_t;
 #include "pci.h"
 #include "pci_host.h"
 #include "bswap.h"
@@ -117,18 +115,6 @@ static CPUWriteMemoryFunc * const pci4xx_cfgaddr_write[] = {
     &pci4xx_cfgaddr_writel,
 };
 
-static CPUReadMemoryFunc * const pci4xx_cfgdata_read[] = {
-    &pci_host_data_readb,
-    &pci_host_data_readw,
-    &pci_host_data_readl,
-};
-
-static CPUWriteMemoryFunc * const pci4xx_cfgdata_write[] = {
-    &pci_host_data_writeb,
-    &pci_host_data_writew,
-    &pci_host_data_writel,
-};
-
 static void ppc4xx_pci_reg_write4(void *opaque, target_phys_addr_t offset,
                                   uint32_t value)
 {
@@ -392,8 +378,8 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
     cpu_register_physical_memory(config_space + PCIC0_CFGADDR, 4, index);
 
     /* CFGDATA */
-    index = cpu_register_io_memory(pci4xx_cfgdata_read,
-                                   pci4xx_cfgdata_write,
+    index = cpu_register_io_memory(pci_host_data_read_mmio,
+                                   pci_host_data_write_mmio,
                                    &controller->pci_state);
     if (index < 0)
         goto free;
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 64fccfd..4920837 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -17,7 +17,6 @@
 #include "hw.h"
 #include "ppc.h"
 #include "ppce500.h"
-typedef target_phys_addr_t pci_addr_t;
 #include "pci.h"
 #include "pci_host.h"
 #include "bswap.h"
@@ -116,18 +115,6 @@ static CPUWriteMemoryFunc * const pcie500_cfgaddr_write[] = {
     &pcie500_cfgaddr_writel,
 };
 
-static CPUReadMemoryFunc * const pcie500_cfgdata_read[] = {
-    &pci_host_data_readb,
-    &pci_host_data_readw,
-    &pci_host_data_readl,
-};
-
-static CPUWriteMemoryFunc * const pcie500_cfgdata_write[] = {
-    &pci_host_data_writeb,
-    &pci_host_data_writew,
-    &pci_host_data_writel,
-};
-
 static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
 {
     PPCE500PCIState *pci = opaque;
@@ -344,8 +331,8 @@ PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
     cpu_register_physical_memory(registers + PCIE500_CFGADDR, 4, index);
 
     /* CFGDATA */
-    index = cpu_register_io_memory(pcie500_cfgdata_read,
-                                   pcie500_cfgdata_write,
+    index = cpu_register_io_memory(pci_host_data_read_mmio,
+                                   pci_host_data_write_mmio,
                                    &controller->pci_state);
     if (index < 0)
         goto free;
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index 2d8a0fa..943de90 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -24,8 +24,6 @@
 
 #include "hw.h"
 #include "pci.h"
-
-typedef uint32_t pci_addr_t;
 #include "pci_host.h"
 
 typedef PCIHostState PREPPCIState;
@@ -144,12 +142,12 @@ PCIBus *pci_prep_init(qemu_irq *pic)
     register_ioport_write(0xcf8, 4, 4, pci_prep_addr_writel, s);
     register_ioport_read(0xcf8, 4, 4, pci_prep_addr_readl, s);
 
-    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb, s);
-    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew, s);
-    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel, s);
-    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
-    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
-    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
+    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb_ioport, s);
+    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew_ioport, s);
+    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel_ioport, s);
+    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb_ioport, s);
+    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw_ioport, s);
+    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl_ioport, s);
 
     PPC_io_memory = cpu_register_io_memory(PPC_PCIIO_read,
                                            PPC_PCIIO_write, s);
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index a202153..1d11816 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -24,6 +24,7 @@
 #include "hw.h"
 #include "ppc_mac.h"
 #include "pci.h"
+#include "pci_host.h"
 
 /* debug UniNorth */
 //#define DEBUG_UNIN
@@ -35,9 +36,6 @@
 #define UNIN_DPRINTF(fmt, ...)
 #endif
 
-typedef target_phys_addr_t pci_addr_t;
-#include "pci_host.h"
-
 typedef struct UNINState {
     SysBusDevice busdev;
     PCIHostState host_state;
@@ -83,18 +81,6 @@ static CPUReadMemoryFunc * const pci_unin_main_config_read[] = {
     &pci_unin_main_config_readl,
 };
 
-static CPUWriteMemoryFunc * const pci_unin_main_write[] = {
-    &pci_host_data_writeb,
-    &pci_host_data_writew,
-    &pci_host_data_writel,
-};
-
-static CPUReadMemoryFunc * const pci_unin_main_read[] = {
-    &pci_host_data_readb,
-    &pci_host_data_readw,
-    &pci_host_data_readl,
-};
-
 static void pci_unin_config_writel (void *opaque, target_phys_addr_t addr,
                                     uint32_t val)
 {
@@ -123,18 +109,6 @@ static CPUReadMemoryFunc * const pci_unin_config_read[] = {
     &pci_unin_config_readl,
 };
 
-static CPUWriteMemoryFunc * const pci_unin_write[] = {
-    &pci_host_data_writeb,
-    &pci_host_data_writew,
-    &pci_host_data_writel,
-};
-
-static CPUReadMemoryFunc * const pci_unin_read[] = {
-    &pci_host_data_readb,
-    &pci_host_data_readw,
-    &pci_host_data_readl,
-};
-
 /* Don't know if this matches real hardware, but it agrees with OHW.  */
 static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
 {
@@ -180,8 +154,9 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
 
     pci_mem_config = cpu_register_io_memory(pci_unin_main_config_read,
                                             pci_unin_main_config_write, s);
-    pci_mem_data = cpu_register_io_memory(pci_unin_main_read,
-                                          pci_unin_main_write, &s->host_state);
+    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
+                                          pci_host_data_write_mmio,
+                                          &s->host_state);
 
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
@@ -203,8 +178,9 @@ static int pci_dec_21154_init_device(SysBusDevice *dev)
     // XXX: s = &pci_bridge[2];
     pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
                                             pci_unin_config_write, s);
-    pci_mem_data = cpu_register_io_memory(pci_unin_main_read,
-                                          pci_unin_main_write, &s->host_state);
+    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
+                                          pci_host_data_write_mmio,
+                                          &s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
     return 0;
@@ -220,8 +196,9 @@ static int pci_unin_agp_init_device(SysBusDevice *dev)
 
     pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
                                             pci_unin_config_write, s);
-    pci_mem_data = cpu_register_io_memory(pci_unin_main_read,
-                                          pci_unin_main_write, &s->host_state);
+    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
+                                          pci_host_data_write_mmio,
+                                          &s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
     return 0;
@@ -237,8 +214,8 @@ static int pci_unin_internal_init_device(SysBusDevice *dev)
 
     pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
                                             pci_unin_config_write, s);
-    pci_mem_data = cpu_register_io_memory(pci_unin_read,
-                                          pci_unin_write, s);
+    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
+                                          pci_host_data_write_mmio, s);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
     return 0;
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 16/23] pci: pcie host and mmcfg support.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (14 preceding siblings ...)
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 15/23] pci_host.h: split non-inline static function in pci_host.h into pci_host.c Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 11:01   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-05 11:41   ` Michael S. Tsirkin
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 17/23] pci: fix pci_default_write_config() Isaku Yamahata
                   ` (9 subsequent siblings)
  25 siblings, 2 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

This patch adds common routines for pcie host bridge and pcie mmcfg.
This will be used by q35 based chipset emulation.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/hw.h       |   12 +++
 hw/pci.c      |  247 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
 hw/pci.h      |   36 ++++++++-
 hw/pci_host.h |   22 +++++
 4 files changed, 285 insertions(+), 32 deletions(-)

diff --git a/hw/hw.h b/hw/hw.h
index cf266b3..478b0b2 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -428,6 +428,18 @@ extern const VMStateDescription vmstate_pci_device;
             + type_check(PCIDevice,typeof_field(_state, _field))     \
 }
 
+extern const VMStateDescription vmstate_pcie_device;
+
+#define VMSTATE_PCIE_DEVICE(_field, _state) {                        \
+    .name       = (stringify(_field)),                               \
+    .version_id = 2,                                                 \
+    .size       = sizeof(PCIDevice),                                 \
+    .vmsd       = &vmstate_pcie_device,                              \
+    .flags      = VMS_STRUCT,                                        \
+    .offset     = offsetof(_state, _field)                           \
+            + type_check(PCIDevice,typeof_field(_state, _field))     \
+}
+
 /* _f : field name
    _f_n : num of elements field_name
    _n : num of elements
diff --git a/hw/pci.c b/hw/pci.c
index 5f808ff..12260da 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -23,6 +23,7 @@
  */
 #include "hw.h"
 #include "pci.h"
+#include "pci_host.h"
 #include "monitor.h"
 #include "net.h"
 #include "sysemu.h"
@@ -184,9 +185,12 @@ int pci_bus_num(PCIBus *s)
 static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
 {
     PCIDevice *s = container_of(pv, PCIDevice, config);
-    uint8_t config[size];
+    uint8_t *config;
     int i;
 
+    assert(size == pcie_config_size(s));
+    config = qemu_malloc(size * sizeof(config[0]));
+
     qemu_get_buffer(f, config, size);
     for (i = 0; i < size; ++i)
         if ((config[i] ^ s->config[i]) & s->cmask[i] & ~s->wmask[i])
@@ -195,6 +199,7 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
 
     pci_update_mappings(s);
 
+    qemu_free(config);
     return 0;
 }
 
@@ -202,6 +207,7 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
 static void put_pci_config_device(QEMUFile *f, const void *pv, size_t size)
 {
     const uint8_t *v = pv;
+    assert(size == pcie_config_size(container_of(pv, PCIDevice, config)));
     qemu_put_buffer(f, v, size);
 }
 
@@ -211,6 +217,17 @@ static VMStateInfo vmstate_info_pci_config = {
     .put  = put_pci_config_device,
 };
 
+#define VMSTATE_PCI_CONFIG(_field, _state, _version, _info, _type,   \
+                           _size) {                                  \
+    .name       = (stringify(_field)),                               \
+    .version_id = (_version),                                        \
+    .size       = (_size),                                           \
+    .info       = &(_info),                                          \
+    .flags      = VMS_SINGLE | VMS_POINTER,                          \
+    .offset     = offsetof(_state, _field)                           \
+            + type_check(_type,typeof_field(_state, _field))         \
+}
+
 const VMStateDescription vmstate_pci_device = {
     .name = "PCIDevice",
     .version_id = 2,
@@ -218,21 +235,46 @@ const VMStateDescription vmstate_pci_device = {
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
         VMSTATE_INT32_LE(version_id, PCIDevice),
-        VMSTATE_SINGLE(config, PCIDevice, 0, vmstate_info_pci_config,
-                       typeof_field(PCIDevice,config)),
+        VMSTATE_PCI_CONFIG(config, PCIDevice, 0, vmstate_info_pci_config,
+                           typeof_field(PCIDevice, config),
+                           PCI_CONFIG_SPACE_SIZE),
+        VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+const VMStateDescription vmstate_pcie_device = {
+    .name = "PCIDevice",
+    .version_id = 2,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_INT32_LE(version_id, PCIDevice),
+        VMSTATE_PCI_CONFIG(config, PCIDevice, 0, vmstate_info_pci_config,
+                           typeof_field(PCIDevice, config),
+                           PCIE_CONFIG_SPACE_SIZE),
         VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
         VMSTATE_END_OF_LIST()
     }
 };
 
+static const VMStateDescription *pci_get_vmstate(PCIDevice *s)
+{
+    if (pci_is_pcie(s)) {
+        return &vmstate_pcie_device;
+    }
+
+    return &vmstate_pci_device;
+}
+
 void pci_device_save(PCIDevice *s, QEMUFile *f)
 {
-    vmstate_save_state(f, &vmstate_pci_device, s);
+    vmstate_save_state(f, pci_get_vmstate(s), s);
 }
 
 int pci_device_load(PCIDevice *s, QEMUFile *f)
 {
-    return vmstate_load_state(f, &vmstate_pci_device, s, s->version_id);
+    return vmstate_load_state(f, pci_get_vmstate(s), s, s->version_id);
 }
 
 static int pci_set_default_subsystem_id(PCIDevice *pci_dev)
@@ -341,14 +383,31 @@ static void pci_init_cmask(PCIDevice *dev)
 static void pci_init_wmask(PCIDevice *dev)
 {
     int i;
+    uint32_t config_size = pcie_config_size(dev);
+
     dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
     dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
     dev->wmask[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY
                               | PCI_COMMAND_MASTER;
-    for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i)
+    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
         dev->wmask[i] = 0xff;
 }
 
+static void pci_config_alloc(PCIDevice *pci_dev)
+{
+    int config_size = pcie_config_size(pci_dev);
+#define PCI_CONFIG_ALLOC(d, member, size)                               \
+    do {                                                                \
+        (d)->member =                                                   \
+            (typeof((d)->member))qemu_mallocz(sizeof((d)->member[0]) *  \
+                                              size);                    \
+    } while (0)
+    PCI_CONFIG_ALLOC(pci_dev, config, config_size);
+    PCI_CONFIG_ALLOC(pci_dev, cmask, config_size);
+    PCI_CONFIG_ALLOC(pci_dev, wmask, config_size);
+    PCI_CONFIG_ALLOC(pci_dev, used, config_size);
+}
+
 /* -1 for devfn means auto assign */
 static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
                                          const char *name, int devfn,
@@ -369,6 +428,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     pci_dev->devfn = devfn;
     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
     memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
+    pci_config_alloc(pci_dev);
     pci_set_default_subsystem_id(pci_dev);
     pci_init_cmask(pci_dev);
     pci_init_wmask(pci_dev);
@@ -586,40 +646,48 @@ static void pci_update_mappings(PCIDevice *d)
     }
 }
 
+static uint8_t pcie_config_get_byte(PCIDevice *d, uint32_t addr)
+{
+    uint8_t *conf = &d->config[addr];
+    if (conf != NULL)
+        return *conf;
+    return 0;
+}
+
+static uint32_t pcie_config_get(PCIDevice *d, uint32_t addr, int len)
+{
+    int i;
+    union {
+        uint8_t val8[4];
+        uint32_t val32;
+    } v = { .val32 = 0 };
+
+    for (i = 0; i < len; i++) {
+        v.val8[i] = pcie_config_get_byte(d, addr + i);
+    }
+
+    return le32_to_cpu(v.val32);
+}
+
 uint32_t pci_default_read_config(PCIDevice *d,
                                  uint32_t address, int len)
 {
-    uint32_t val;
+    uint32_t config_size = pcie_config_size(d);
 
-    switch(len) {
-    default:
-    case 4:
-	if (address <= 0xfc) {
-            val = pci_get_long(d->config + address);
-	    break;
-	}
-	/* fall through */
-    case 2:
-        if (address <= 0xfe) {
-            val = pci_get_word(d->config + address);
-	    break;
-	}
-	/* fall through */
-    case 1:
-        val = pci_get_byte(d->config + address);
-        break;
-    }
-    return val;
+    assert(len == 1 || len == 2 || len == 4);
+    len = MIN(len, config_size - MIN(config_size, address));
+    return pcie_config_get(d, address, len);
 }
 
 void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
 {
     uint8_t orig[PCI_CONFIG_SPACE_SIZE];
     int i;
+    uint32_t config_size = pcie_config_size(d);
 
     /* not efficient, but simple */
     memcpy(orig, d->config, PCI_CONFIG_SPACE_SIZE);
-    for(i = 0; i < l && addr < PCI_CONFIG_SPACE_SIZE; val >>= 8, ++i, ++addr) {
+    for(i = 0; i < l && addr < config_size; val >>= 8, ++i, ++addr) {
         uint8_t wmask = d->wmask[addr];
         d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
     }
@@ -703,6 +771,128 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
     return pci_data_read_common(pci_addr_to_dev(s, addr),
                                 pci_addr_to_config(addr), len);
 }
+
+#define PCIE_MASK(val, hi_bit, low_bit)                 \
+    (((val) & (((1ULL << (hi_bit)) - 1))) >> (low_bit))
+#define PCIE_VAL(VAL, val)                                              \
+    PCIE_MASK((val), PCIE_MMCFG_ ## VAL ## _HI, PCIE_MMCFG_ ## VAL ## _LOW)
+#define PCIE_MMCFG_BUS_HI               28
+#define PCIE_MMCFG_BUS_LOW              20
+#define PCIE_MMCFG_DEV_HI               19
+#define PCIE_MMCFG_DEV_LOW              15
+#define PCIE_MMCFG_FUNC_HI              14
+#define PCIE_MMCFG_FUNC_LOW             12
+#define PCIE_MMCFG_CONFADDR_HI          11
+#define PCIE_MMCFG_CONFADDR_LOW         0
+#define PCIE_MMCFG_BUS(addr)            PCIE_VAL(BUS, (addr))
+#define PCIE_MMCFG_DEV(addr)            PCIE_VAL(DEV, (addr))
+#define PCIE_MMCFG_FUNC(addr)           PCIE_VAL(FUNC, (addr))
+#define PCIE_MMCFG_CONFADDR(addr)       PCIE_VAL(CONFADDR, (addr))
+
+void pcie_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
+{
+    PCIBus *s = opaque;
+    pci_data_write_common(pci_find_device(s, PCIE_MMCFG_BUS(addr),
+                                          PCIE_MMCFG_DEV(addr),
+                                          PCIE_MMCFG_FUNC(addr)),
+                          PCIE_MMCFG_CONFADDR(addr),
+                          val, len);
+}
+
+uint32_t pcie_data_read(void *opaque, uint32_t addr, int len)
+{
+    PCIBus *s = opaque;
+    return pci_data_read_common(pci_find_device(s, PCIE_MMCFG_BUS(addr),
+                                                PCIE_MMCFG_DEV(addr),
+                                                PCIE_MMCFG_FUNC(addr)),
+                                PCIE_MMCFG_CONFADDR(addr),
+                                len);
+}
+
+#define DEFINE_PCIE_HOST_DATA_READ(len)                         \
+    static uint32_t pcie_host_data_read_ ## len (               \
+        void *opaque, target_phys_addr_t addr)                  \
+    {                                                           \
+        PCIExpressHost *e = (PCIExpressHost *)opaque;           \
+        return pcie_data_read(e->pci.bus,                       \
+                              addr - e->base_addr, (len));      \
+    }
+
+#define DEFINE_PCIE_HOST_DATA_WRITE(len)                        \
+    static void pcie_host_data_write_ ## len (                  \
+        void *opaque, target_phys_addr_t addr, uint32_t value)  \
+    {                                                           \
+        PCIExpressHost *e = (PCIExpressHost *)opaque;           \
+        pcie_data_write(e->pci.bus,                             \
+                        addr - e->base_addr, value, (len));     \
+    }
+
+#define DEFINE_PCIE_HOST_DATA_MMIO(len)      \
+        DEFINE_PCIE_HOST_DATA_READ(len)      \
+        DEFINE_PCIE_HOST_DATA_WRITE(len)
+
+DEFINE_PCIE_HOST_DATA_MMIO(1)
+DEFINE_PCIE_HOST_DATA_MMIO(2)
+DEFINE_PCIE_HOST_DATA_MMIO(4)
+
+#define DEFINE_PCIE_MEMORY_FUNCS(Type, type)                            \
+    static CPU ## Type ## MemoryFunc *pcie_host_data_ ## type [] =      \
+    {                                                                   \
+        &pcie_host_data_ ## type ## _1,                                 \
+        &pcie_host_data_ ## type ## _2,                                 \
+        &pcie_host_data_ ## type ## _4,                                 \
+    };
+
+DEFINE_PCIE_MEMORY_FUNCS(Read, read)
+DEFINE_PCIE_MEMORY_FUNCS(Write, write)
+
+int pcie_host_init(PCIExpressHost *e,
+                   CPUReadMemoryFunc **mmcfg_read,
+                   CPUWriteMemoryFunc **mmcfg_write)
+{
+    e->base_addr = PCIE_BASE_ADDR_INVALID;
+
+    if (mmcfg_read == NULL)
+        mmcfg_read = pcie_host_data_read;
+    if (mmcfg_write == NULL)
+        mmcfg_write = pcie_host_data_write;
+    e->mmio_index = cpu_register_io_memory(mmcfg_read, mmcfg_write, e);
+    if (e->mmio_index < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+void pcie_host_mmcfg_unmap(PCIExpressHost *e)
+{
+    if (e->base_addr != PCIE_BASE_ADDR_INVALID) {
+        cpu_register_physical_memory(e->base_addr, e->size, IO_MEM_UNASSIGNED);
+    }
+}
+
+void pcie_host_mmcfg_map(PCIExpressHost *e,
+                         target_phys_addr_t addr, uint32_t size)
+{
+    assert((size & (size - 1)) == 0); /* power of 2 */
+    assert(size >= (1ULL << PCIE_MMCFG_BUS_LOW));
+    assert(size <= (1ULL << PCIE_MMCFG_BUS_HI));
+
+    e->base_addr = addr;
+    e->size = size;
+    cpu_register_physical_memory(e->base_addr, e->size, e->mmio_index);
+}
+
+void pcie_host_mmcfg_update(PCIExpressHost *e,
+                            int enable,
+                            target_phys_addr_t addr, uint32_t size)
+{
+    pcie_host_mmcfg_unmap(e);
+    if (enable) {
+        pcie_host_mmcfg_map(e, addr, size);
+    }
+}
+
 /***********************************************************/
 /* generic PCI irq support */
 
@@ -1052,9 +1242,10 @@ PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
 
 static int pci_find_space(PCIDevice *pdev, uint8_t size)
 {
+    int config_size = pcie_config_size(pdev);
     int offset = PCI_CONFIG_HEADER_SIZE;
     int i;
-    for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i)
+    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
         if (pdev->used[i])
             offset = i + 1;
         else if (i - offset + 1 == size)
diff --git a/hw/pci.h b/hw/pci.h
index 00f2b78..1f402d2 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -175,20 +175,26 @@ enum {
     QEMU_PCI_CAP_MSIX = 0x1,
 };
 
+/* Size of the standart PCIe config space: 4KB */
+#define PCIE_CONFIG_SPACE_SIZE  0x1000
+#define PCIE_EXT_CONFIG_SPACE_SIZE                      \
+    (PCIE_CONFIG_SPACE_SIZE - PCI_CONFIG_SPACE_SIZE)
+
 struct PCIDevice {
     DeviceState qdev;
+
     /* PCI config space */
-    uint8_t config[PCI_CONFIG_SPACE_SIZE];
+    uint8_t *config;
 
     /* Used to enable config checks on load. Note that writeable bits are
      * never checked even if set in cmask. */
-    uint8_t cmask[PCI_CONFIG_SPACE_SIZE];
+    uint8_t *cmask;
 
     /* Used to implement R/W bytes */
-    uint8_t wmask[PCI_CONFIG_SPACE_SIZE];
+    uint8_t *wmask;
 
     /* Used to allocate config space for capabilities. */
-    uint8_t used[PCI_CONFIG_SPACE_SIZE];
+    uint8_t *used;
 
     /* the following fields are read only */
     PCIBus *bus;
@@ -270,6 +276,8 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
                         const char *default_devaddr);
 void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
 uint32_t pci_data_read(void *opaque, uint32_t addr, int len);
+void pcie_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
+uint32_t pcie_data_read(void *opaque, uint32_t addr, int len);
 int pci_bus_num(PCIBus *s);
 void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDevice *d));
 PCIBus *pci_find_host_bus(int domain);
@@ -356,6 +364,9 @@ typedef struct {
     pci_qdev_initfn init;
     PCIConfigReadFunc *config_read;
     PCIConfigWriteFunc *config_write;
+
+    /* pcie stuff */
+    int pcie;
 } PCIDeviceInfo;
 
 void pci_qdev_register(PCIDeviceInfo *info);
@@ -365,6 +376,23 @@ PCIDevice *pci_create(const char *name, const char *devaddr);
 PCIDevice *pci_create_noinit(PCIBus *bus, int devfn, const char *name);
 PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
 
+static inline int pci_is_pcie(PCIDevice *d)
+{
+    /*
+     * At the moment, all the pci devices aren't qdevfied. So
+     * d->qdev.info might be NULL.
+     * Given that pcie device emulator hasn't exist, we conclude that
+     * such a device isn't pcie.
+     */
+    return d->qdev.info != NULL &&
+        container_of(d->qdev.info, PCIDeviceInfo, qdev)->pcie;
+}
+
+static inline uint32_t pcie_config_size(PCIDevice *d)
+{
+    return pci_is_pcie(d)? PCIE_CONFIG_SPACE_SIZE: PCI_CONFIG_SPACE_SIZE;
+}
+
 /* lsi53c895a.c */
 #define LSI_MAX_DEVS 7
 
diff --git a/hw/pci_host.h b/hw/pci_host.h
index ea98ed2..59147cf 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -48,4 +48,26 @@ uint32_t pci_host_data_readb_ioport(void* opaque, uint32_t addr);
 uint32_t pci_host_data_readw_ioport(void* opaque, uint32_t addr);
 uint32_t pci_host_data_readl_ioport(void* opaque, uint32_t addr);
 
+typedef struct {
+    PCIHostState pci;
+
+    /* express part */
+    target_phys_addr_t  base_addr;
+#define PCIE_BASE_ADDR_INVALID  ((target_phys_addr_t)-1ULL)
+    target_phys_addr_t  size;
+    int bus_num_order;
+    int mmio_index;
+} PCIExpressHost;
+
+int pcie_host_init(PCIExpressHost *e,
+                   CPUReadMemoryFunc **mmcfg_read,
+                   CPUWriteMemoryFunc **mmcfg_write);
+
+void pcie_host_mmcfg_unmap(PCIExpressHost *e);
+void pcie_host_mmcfg_map(PCIExpressHost *e,
+                         target_phys_addr_t addr, uint32_t size);
+void pcie_host_mmcfg_update(PCIExpressHost *e,
+                            int enable,
+                            target_phys_addr_t addr, uint32_t size);
+
 #endif /* PCI_HOST_H */
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 17/23] pci: fix pci_default_write_config()
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (15 preceding siblings ...)
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 16/23] pci: pcie host and mmcfg support Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 18/23] pci: add helper functions for pci config write function Isaku Yamahata
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

When updated ROM expantion address of header type 0, it missed
to update mappings.
Add PCI_ROM_ADDRESS check whether to call pci_update_mappings()

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/pci.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 12260da..65afbd2 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -691,7 +691,8 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
         uint8_t wmask = d->wmask[addr];
         d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
     }
-    if (memcmp(orig + PCI_BASE_ADDRESS_0, d->config + PCI_BASE_ADDRESS_0, 24)
+    if ((memcmp(orig + PCI_BASE_ADDRESS_0, d->config + PCI_BASE_ADDRESS_0, 24) ||
+         memcmp(orig + PCI_ROM_ADDRESS, d->config + PCI_ROM_ADDRESS, 4))
         || ((orig[PCI_COMMAND] ^ d->config[PCI_COMMAND])
             & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)))
         pci_update_mappings(d);
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 18/23] pci: add helper functions for pci config write function.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (16 preceding siblings ...)
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 17/23] pci: fix pci_default_write_config() Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 19/23] pci: use helper function in pci_default_write_config() Isaku Yamahata
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

add helper functions for pci config write function to check
if its configuration space is changed.
Those function will be used later and generic enough for specific
pci device to use.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.h |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/hw/pci.h b/hw/pci.h
index 1f402d2..0ea08b7 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -393,6 +393,65 @@ static inline uint32_t pcie_config_size(PCIDevice *d)
     return pci_is_pcie(d)? PCIE_CONFIG_SPACE_SIZE: PCI_CONFIG_SPACE_SIZE;
 }
 
+struct pci_config_update {
+    PCIDevice *d;
+    uint32_t addr;
+    uint32_t val;
+    int len;
+
+    uint8_t orig[4];
+};
+
+static inline void pci_write_config_init(struct pci_config_update *update,
+                                         PCIDevice *d,
+                                         uint32_t addr, uint32_t val, int len)
+{
+    assert(len == 1 || len == 2 || len == 4);
+
+    update->d = d;
+    update->addr = addr;
+    update->val = val;
+    update->len = len;
+    memcpy(update->orig, &d->config[addr], len);
+}
+
+static inline void pci_write_config_update(struct pci_config_update *update)
+{
+    PCIDevice *d = update->d;
+    uint32_t addr = update->addr;
+    uint32_t val = update->val;
+    uint32_t config_size = pcie_config_size(d);
+    int i;
+
+    for(i = 0; i < update->len && addr < config_size; val >>= 8, ++i, ++addr) {
+        uint8_t wmask = d->wmask[addr];
+        d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
+    }
+}
+
+static inline int pci_config_changed(const struct pci_config_update *update,
+                                     uint32_t base, uint32_t end)
+{
+    uint32_t low = MAX(update->addr, base);
+    uint32_t high = MIN(update->addr + update->len, end);
+
+    /* Check if [addr, addr + len) intersects [base, end).
+       The intersection is [low, high), so see if it's empty or not */
+    if (low >= high)
+        return 0;
+
+    return memcmp(update->orig + (low - update->addr),
+                  update->d->config + low,
+                  high - low);
+}
+
+/* for convinience not to type symbol constant twice */
+static inline int pci_config_changed_with_size(
+    const struct pci_config_update *update, uint32_t base, uint32_t size)
+{
+    return pci_config_changed(update, base, base + size);
+}
+
 /* lsi53c895a.c */
 #define LSI_MAX_DEVS 7
 
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 19/23] pci: use helper function in pci_default_write_config()
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (17 preceding siblings ...)
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 18/23] pci: add helper functions for pci config write function Isaku Yamahata
@ 2009-10-05 10:06 ` Isaku Yamahata
  2009-10-05 10:07 ` [Qemu-devel] [PATCH 20/23] pci: make bar update function aware of pci bridge Isaku Yamahata
                   ` (6 subsequent siblings)
  25 siblings, 0 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:06 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

use helper function in pci_default_write_config() to
check whether the configuration space is changed.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   23 +++++++++--------------
 hw/pci.h |    1 +
 2 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 65afbd2..b8d2f8f 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -681,21 +681,16 @@ uint32_t pci_default_read_config(PCIDevice *d,
 
 void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
 {
-    uint8_t orig[PCI_CONFIG_SPACE_SIZE];
-    int i;
-    uint32_t config_size = pcie_config_size(d);
-
-    /* not efficient, but simple */
-    memcpy(orig, d->config, PCI_CONFIG_SPACE_SIZE);
-    for(i = 0; i < l && addr < config_size; val >>= 8, ++i, ++addr) {
-        uint8_t wmask = d->wmask[addr];
-        d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
-    }
-    if ((memcmp(orig + PCI_BASE_ADDRESS_0, d->config + PCI_BASE_ADDRESS_0, 24) ||
-         memcmp(orig + PCI_ROM_ADDRESS, d->config + PCI_ROM_ADDRESS, 4))
-        || ((orig[PCI_COMMAND] ^ d->config[PCI_COMMAND])
-            & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)))
+    struct pci_config_update update;
+
+    pci_write_config_init(&update, d, addr, val, l);
+    pci_write_config_update(&update);
+    if (pci_config_changed(&update,
+                           PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_5 + 4) ||
+        pci_config_changed_with_size(&update, PCI_ROM_ADDRESS, 4) ||
+        pci_config_changed_with_size(&update, PCI_COMMAND, 1)) {
         pci_update_mappings(d);
+    }
 }
 
 static void pci_data_write_common(PCIDevice *pci_dev,
diff --git a/hw/pci.h b/hw/pci.h
index 0ea08b7..37c2c23 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -118,6 +118,7 @@ typedef struct PCIIORegion {
 #define  PCI_HEADER_TYPE_CARDBUS	2
 #define  PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
 #define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
+#define PCI_BASE_ADDRESS_5	0x24	/* 32 bits */
 #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
 #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
 #define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 20/23] pci: make bar update function aware of pci bridge.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (18 preceding siblings ...)
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 19/23] pci: use helper function in pci_default_write_config() Isaku Yamahata
@ 2009-10-05 10:07 ` Isaku Yamahata
  2009-10-05 11:59   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-05 10:07 ` [Qemu-devel] [PATCH 21/23] pci/brdige: qdevfy and initialize secondary bus and subordinate bus Isaku Yamahata
                   ` (5 subsequent siblings)
  25 siblings, 1 reply; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:07 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

header type of 01 has differenct BAR to type 00.
It has only BAR0,1 and expantion rom whose offset address
is different from type 00 one.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   56 +++++++++++++++++++++++++++++++++++++++++++++-----------
 hw/pci.h |    2 ++
 2 files changed, 47 insertions(+), 11 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index b8d2f8f..af864c6 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -505,6 +505,33 @@ static inline int pci_bar_is_mem64(const PCIIORegion *r)
         PCI_ADDRESS_SPACE_MEM_TYPE_64;
 }
 
+/*
+ * return offset in pci configuration space for a given BAR of region_num.
+ * header type
+ * normal  = 0: bar 0-5 and rom
+ * bridge  = 1: bar 0,1 and rom
+ * cardbus = 2: bar 0
+ */
+static uint32_t pci_bar_config_offset(PCIDevice *d, int region_num)
+{
+    uint8_t header_type =
+        d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
+
+    assert((header_type == PCI_HEADER_TYPE_NORMAL &&
+            ((0 <= region_num && region_num < 6) ||
+             region_num == PCI_ROM_SLOT)) ||
+           (header_type == PCI_HEADER_TYPE_BRIDGE &&
+            ((0 <= region_num && region_num < 2) ||
+             region_num == PCI_ROM_SLOT)) ||
+           (header_type == PCI_HEADER_TYPE_CARDBUS && region_num == 0));
+
+    if (region_num != PCI_ROM_ADDRESS)
+        return PCI_BASE_ADDRESS_0 + region_num * 4;
+
+    return header_type == PCI_HEADER_TYPE_BRIDGE?
+        PCI_ROM_ADDRESS1: PCI_ROM_ADDRESS;
+}
+
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
                             pcibus_t size, int type,
                             PCIMapIORegionFunc *map_func)
@@ -528,13 +555,11 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     r->type = type;
     r->map_func = map_func;
 
+    addr = pci_bar_config_offset(pci_dev, region_num);
     wmask = ~(size - 1);
     if (region_num == PCI_ROM_SLOT) {
-        addr = 0x30;
         /* ROM enable bit is writeable */
         wmask |= PCI_ROM_ADDRESS_ENABLE;
-    } else {
-        addr = 0x10 + region_num * 4;
     }
     pci_set_long(pci_dev->config + addr, type);
     if (pci_bar_is_mem64(r)) {
@@ -556,11 +581,7 @@ static void pci_update_mappings(PCIDevice *d)
     cmd = pci_get_word(d->config + PCI_COMMAND);
     for(i = 0; i < PCI_NUM_REGIONS; i++) {
         r = &d->io_regions[i];
-        if (i == PCI_ROM_SLOT) {
-            config_ofs = 0x30;
-        } else {
-            config_ofs = 0x10 + i * 4;
-        }
+        config_ofs = pci_bar_config_offset(d, i);
         if (r->size != 0) {
             if (r->type & PCI_ADDRESS_SPACE_IO) {
                 if (cmd & PCI_COMMAND_IO) {
@@ -1123,10 +1144,23 @@ static void pci_bridge_write_config(PCIDevice *d,
                              uint32_t address, uint32_t val, int len)
 {
     PCIBridge *s = (PCIBridge *)d;
+    PCIBus *bus = s->bus;
+    struct pci_config_update update;
 
-    pci_default_write_config(d, address, val, len);
-    s->bus->bus_num = d->config[PCI_SECONDARY_BUS];
-    s->bus->sub_bus = d->config[PCI_SUBORDINATE_BUS];
+    pci_write_config_init(&update, d, address, val, len);
+    pci_write_config_update(&update);
+    if (pci_config_changed(&update,
+                           PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_2 + 4) ||
+        pci_config_changed_with_size(&update, PCI_ROM_ADDRESS1, 4) ||
+        pci_config_changed_with_size(&update, PCI_COMMAND, 1)) {
+        pci_update_mappings(d);
+    }
+    if (pci_config_changed_with_size(&update, PCI_SECONDARY_BUS, 1)) {
+        bus->bus_num = d->config[PCI_SECONDARY_BUS];
+    }
+    if (pci_config_changed_with_size(&update, PCI_SUBORDINATE_BUS, 1)) {
+        bus->sub_bus = d->config[PCI_SUBORDINATE_BUS];
+    }
 }
 
 PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
diff --git a/hw/pci.h b/hw/pci.h
index 37c2c23..1d45437 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -118,6 +118,7 @@ typedef struct PCIIORegion {
 #define  PCI_HEADER_TYPE_CARDBUS	2
 #define  PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
 #define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
+#define PCI_BASE_ADDRESS_2	0x18	/* 32 bits */
 #define PCI_BASE_ADDRESS_5	0x24	/* 32 bits */
 #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
 #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
@@ -163,6 +164,7 @@ typedef struct PCIIORegion {
 
 /* Header type 1 (PCI-to-PCI bridges) */
 #define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
+#define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
 
 /* Size of the standard PCI config header */
 #define PCI_CONFIG_HEADER_SIZE 0x40
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 21/23] pci/brdige: qdevfy and initialize secondary bus and subordinate bus.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (19 preceding siblings ...)
  2009-10-05 10:07 ` [Qemu-devel] [PATCH 20/23] pci: make bar update function aware of pci bridge Isaku Yamahata
@ 2009-10-05 10:07 ` Isaku Yamahata
  2009-10-05 13:49   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-05 14:58   ` Michael S. Tsirkin
  2009-10-05 10:07 ` [Qemu-devel] [PATCH 22/23] pci: initialize wmask according to pci header type Isaku Yamahata
                   ` (4 subsequent siblings)
  25 siblings, 2 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:07 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

qdevfy pci bridge, and initialize secondary bus and subordinate bus
in configuration space.
And some clean up to use symbolic constant and to remove // comments.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   85 +++++++++++++++++++++++++++++++++++++++++++-------------------
 hw/pci.h |    9 ++++++
 2 files changed, 68 insertions(+), 26 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index af864c6..fb93b99 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -174,6 +174,7 @@ static PCIBus *pci_register_secondary_bus(PCIBus *parent,
     bus->sub_bus = dev->config[PCI_SUBORDINATE_BUS];
     QLIST_INIT(&bus->child);
     QLIST_INSERT_HEAD(&parent->child, bus, sibling);
+    vmstate_register(-1, &vmstate_pcibus, bus);
     return bus;
 }
 
@@ -1140,7 +1141,7 @@ typedef struct {
     PCIBus *bus;
 } PCIBridge;
 
-static void pci_bridge_write_config(PCIDevice *d,
+void pci_bridge_write_config(PCIDevice *d,
                              uint32_t address, uint32_t val, int len)
 {
     PCIBridge *s = (PCIBridge *)d;
@@ -1193,35 +1194,67 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function)
     return bus->devices[PCI_DEVFN(slot, function)];
 }
 
-PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
-                        uint8_t sec_bus, uint8_t sub_bus,
-                        pci_map_irq_fn map_irq, const char *name)
+int pci_bridge_initfn(PCIDevice *pci_dev)
+{
+    uint8_t *pci_conf = pci_dev->config;
+
+    /* secondary bus, subordinate bus and vid/did will be set
+       by pci_bridge_create_simple(), the caller of qdev_init() */
+    pci_conf[PCI_COMMAND] = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+    pci_conf[PCI_STATUS] = PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK;
+    pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_PCI);
+    pci_conf[PCI_LATENCY_TIMER] = 0x10;
+    pci_conf[PCI_HEADER_TYPE] =
+        PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE;
+    pci_conf[PCI_PRIMARY_BUS] = pci_dev->bus->bus_num;
+    pci_conf[PCI_SEC_STATUS] = PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK;
+
+    return 0;
+}
+
+#define PCI_BRIDGE_DEFAULT      "default PCI to PCI bridge"
+static PCIDeviceInfo pci_bridge_info_default = {
+    .qdev.name = PCI_BRIDGE_DEFAULT,
+    .qdev.size = sizeof(PCIBridge),
+    .config_write = pci_bridge_write_config,
+    .init = pci_bridge_initfn,
+    .pcie = 0,
+};
+
+static void pci_bridge_register_device(void)
 {
-    PCIBridge *s;
-    s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge),
-                                         devfn, NULL, pci_bridge_write_config);
-
-    pci_config_set_vendor_id(s->dev.config, vid);
-    pci_config_set_device_id(s->dev.config, did);
-
-    s->dev.config[0x04] = 0x06; // command = bus master, pci mem
-    s->dev.config[0x05] = 0x00;
-    s->dev.config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
-    s->dev.config[0x07] = 0x00; // status = fast devsel
-    s->dev.config[0x08] = 0x00; // revision
-    s->dev.config[0x09] = 0x00; // programming i/f
-    pci_config_set_class(s->dev.config, PCI_CLASS_BRIDGE_PCI);
-    s->dev.config[0x0D] = 0x10; // latency_timer
-    s->dev.config[PCI_HEADER_TYPE] =
-        PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE; // header_type
-    s->dev.config[0x1E] = 0xa0; // secondary status
+    pci_qdev_register(&pci_bridge_info_default);
+}
+device_init(pci_bridge_register_device);
+
+PCIBus *pci_bridge_create_simple(PCIBus *bus, int devfn,
+                                 uint16_t vid, uint16_t did,
+                                 uint8_t sec_bus, uint8_t sub_bus,
+                                 pci_map_irq_fn map_irq, const char *bus_name,
+                                 const char *name)
+{
+    PCIDevice *d;
+    PCIBridge *br;
+
+    d = pci_create_simple(bus, devfn, name);
 
+    pci_config_set_vendor_id(d->config, vid);
+    pci_config_set_device_id(d->config, did);
     assert(sec_bus <= sub_bus);
-    s->dev.config[PCI_SECONDARY_BUS] = sec_bus;
-    s->dev.config[PCI_SUBORDINATE_BUS] = sub_bus;
+    d->config[PCI_SECONDARY_BUS] = sec_bus;
+    d->config[PCI_SUBORDINATE_BUS] = sub_bus;
 
-    s->bus = pci_register_secondary_bus(bus, &s->dev, map_irq, name);
-    return s->bus;
+    br = DO_UPCAST(PCIBridge, dev, d);
+    br->bus = pci_register_secondary_bus(bus, d, map_irq, name);
+    return br->bus;
+}
+
+PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid,
+                        uint16_t did, uint8_t sec_bus, uint8_t sub_bus,
+                        pci_map_irq_fn map_irq, const char *name)
+{
+    return pci_bridge_create_simple(bus, devfn, vid, did, sec_bus, sub_bus,
+                                    map_irq, name, PCI_BRIDGE_DEFAULT);
 }
 
 static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
diff --git a/hw/pci.h b/hw/pci.h
index 1d45437..5cf0b59 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -294,6 +294,15 @@ void pci_info(Monitor *mon);
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
                         uint8_t sec_bus, uint8_t sub_bus,
                         pci_map_irq_fn map_irq, const char *name);
+PCIBus *pci_bridge_create_simple(PCIBus *bus, int devfn,
+                                 uint16_t vid, uint16_t did,
+                                 uint8_t sec_bus, uint8_t sub_bus,
+                                 pci_map_irq_fn map_irq, const char *bus_name,
+                                 const char *name);
+void pci_bridge_write_config(PCIDevice *d,
+                             uint32_t address, uint32_t val, int len);
+int pci_bridge_initfn(PCIDevice *pci_dev);
+void pci_bridge_set_map_irq(PCIBus *bus, pci_map_irq_fn map_irq);
 
 static inline void
 pci_set_byte(uint8_t *config, uint8_t val)
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 22/23] pci: initialize wmask according to pci header type.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (20 preceding siblings ...)
  2009-10-05 10:07 ` [Qemu-devel] [PATCH 21/23] pci/brdige: qdevfy and initialize secondary bus and subordinate bus Isaku Yamahata
@ 2009-10-05 10:07 ` Isaku Yamahata
  2009-10-05 14:09   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-05 10:07 ` [Qemu-devel] [PATCH 23/23] pci/monitor: print out bridge's filtering values and so on Isaku Yamahata
                   ` (3 subsequent siblings)
  25 siblings, 1 reply; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:07 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

- initialize wmask according to pci header type.
  So far, header of type 01  was not correctly initialized.
- only sets default subsystem id for header type 00.
  header type 01 doesn't have subsystem id, and uses the register
  for other purpose. So setting default subsystem id doesn't make sense.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/cirrus_vga.c |    2 +-
 hw/pci.c        |   98 +++++++++++++++++++++++++++++++++++++++++++++++++-----
 hw/pci.h        |   36 ++++++++++++++++++++
 3 files changed, 126 insertions(+), 10 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 2a6aba8..55ef4c1 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -180,7 +180,7 @@
 #define PCI_COMMAND_PALETTESNOOPING         0x0020
 #define PCI_COMMAND_PARITYDETECTION         0x0040
 #define PCI_COMMAND_ADDRESSDATASTEPPING     0x0080
-#define PCI_COMMAND_SERR                    0x0100
+// #define PCI_COMMAND_SERR                    0x0100 /* duplicated */
 #define PCI_COMMAND_BACKTOBACKTRANS         0x0200
 // PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev)
 #define PCI_CLASS_BASE_DISPLAY        0x03
diff --git a/hw/pci.c b/hw/pci.c
index fb93b99..2694e83 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -381,16 +381,32 @@ static void pci_init_cmask(PCIDevice *dev)
     dev->cmask[PCI_CAPABILITY_LIST] = 0xff;
 }
 
-static void pci_init_wmask(PCIDevice *dev)
+static void pci_conf_init_type00(PCIDevice *dev)
 {
     int i;
     uint32_t config_size = pcie_config_size(dev);
 
+    pci_set_default_subsystem_id(dev);
+
+    pci_set_word(&dev->wmask[PCI_COMMAND],
+                 PCI_COMMAND_IO |
+                 PCI_COMMAND_MEMORY |
+                 PCI_COMMAND_MASTER |
+                 PCI_COMMAND_SPECIAL |
+                 PCI_COMMAND_INVALIDATE |
+                 PCI_COMMAND_VGA_PALETTE |
+                 PCI_COMMAND_PARITY |
+                 PCI_COMMAND_WAIT |
+                 PCI_COMMAND_SERR |
+                 PCI_COMMAND_FAST_BACK |
+                 PCI_COMMAND_INTX_DISABLE);
+
     dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
+    dev->wmask[PCI_LATENCY_TIMER] = 0xff;
     dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
-    dev->wmask[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY
-                              | PCI_COMMAND_MASTER;
-    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
+
+    /* device dependent part */
+    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; i++)
         dev->wmask[i] = 0xff;
 }
 
@@ -410,10 +426,12 @@ static void pci_config_alloc(PCIDevice *pci_dev)
 }
 
 /* -1 for devfn means auto assign */
+typedef void (*pci_conf_init_t)(PCIDevice *d);
 static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
                                          const char *name, int devfn,
                                          PCIConfigReadFunc *config_read,
-                                         PCIConfigWriteFunc *config_write)
+                                         PCIConfigWriteFunc *config_write,
+                                         pci_conf_init_t conf_init)
 {
     if (devfn < 0) {
         for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) {
@@ -430,9 +448,8 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
     memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
     pci_config_alloc(pci_dev);
-    pci_set_default_subsystem_id(pci_dev);
     pci_init_cmask(pci_dev);
-    pci_init_wmask(pci_dev);
+    conf_init(pci_dev);
 
     if (!config_read)
         config_read = pci_default_read_config;
@@ -455,9 +472,11 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
 
     pci_dev = qemu_mallocz(instance_size);
     pci_dev = do_pci_register_device(pci_dev, bus, name, devfn,
-                                     config_read, config_write);
+                                     config_read, config_write,
+                                     pci_conf_init_type00);
     return pci_dev;
 }
+
 static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
 {
     return addr + pci_mem_base;
@@ -1194,6 +1213,59 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function)
     return bus->devices[PCI_DEVFN(slot, function)];
 }
 
+static void pci_conf_init_type01(PCIDevice *d)
+{
+    uint32_t addr;
+    uint32_t config_size = pcie_config_size(d);
+
+    pci_set_word(&d->wmask[PCI_COMMAND],
+                 PCI_COMMAND_IO |
+                 PCI_COMMAND_MEMORY |
+                 PCI_COMMAND_MASTER |
+                 PCI_COMMAND_SPECIAL |
+                 PCI_COMMAND_INVALIDATE |
+                 PCI_COMMAND_VGA_PALETTE |
+                 PCI_COMMAND_PARITY |
+                 PCI_COMMAND_WAIT |
+                 PCI_COMMAND_SERR |
+                 PCI_COMMAND_FAST_BACK |
+                 PCI_COMMAND_INTX_DISABLE);
+
+    d->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
+    d->wmask[PCI_LATENCY_TIMER] = 0xff;
+
+    d->wmask[PCI_PRIMARY_BUS] = 0xff;
+    d->wmask[PCI_SECONDARY_BUS] = 0xff;
+    d->wmask[PCI_SUBORDINATE_BUS] = 0xff;
+    d->wmask[PCI_SEC_LATENCY_TIMER] = 0xff;
+    d->wmask[PCI_IO_BASE] = PCI_IO_RANGE_MASK & 0xff;
+    d->wmask[PCI_IO_LIMIT] = PCI_IO_RANGE_MASK & 0xff;
+
+    /* sec status isn't emulated (yet) */
+    d->wmask[PCI_SEC_STATUS] = 0;
+
+    pci_set_word(&d->wmask[PCI_MEMORY_BASE], PCI_MEMORY_RANGE_MASK & 0xffff);
+    pci_set_word(&d->wmask[PCI_MEMORY_LIMIT], PCI_MEMORY_RANGE_MASK & 0xffff);
+    pci_set_word(&d->wmask[PCI_PREF_MEMORY_BASE], PCI_PREF_RANGE_MASK & 0xffff);
+    pci_set_word(&d->wmask[PCI_PREF_MEMORY_LIMIT], PCI_PREF_RANGE_MASK & 0xffff);
+    pci_set_long(&d->wmask[PCI_PREF_BASE_UPPER32], 0xffffffff);
+    pci_set_long(&d->wmask[PCI_PREF_LIMIT_UPPER32], 0xffffffff);
+
+    d->wmask[PCI_INTERRUPT_LINE] = 0xff;
+    pci_set_word(&d->wmask[PCI_BRIDGE_CONTROL], 0xffff);
+
+    /* device dependent part */
+    for (addr = PCI_CONFIG_HEADER_SIZE; addr < config_size; addr++)
+        d->wmask[addr] = 0xff;
+}
+
+static void pci_conf_init_type02(PCIDevice *d)
+{
+    fprintf(stderr,
+            "ERROR: pci header type 02(CARDBUS) isn't supported yet.\n");
+    abort();
+}
+
 int pci_bridge_initfn(PCIDevice *pci_dev)
 {
     uint8_t *pci_conf = pci_dev->config;
@@ -1263,11 +1335,19 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
     PCIDeviceInfo *info = container_of(base, PCIDeviceInfo, qdev);
     PCIBus *bus;
     int devfn;
+    const pci_conf_init_t conf_init[] = {
+        pci_conf_init_type00,
+        pci_conf_init_type01,
+        pci_conf_init_type02,
+    };
 
     bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
     devfn = pci_dev->devfn;
+    assert(0 <= info->header_type);
+    assert(info->header_type <= ARRAY_SIZE(conf_init));
     pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn,
-                                     info->config_read, info->config_write);
+                                     info->config_read, info->config_write,
+                                     conf_init[info->header_type]);
     assert(pci_dev);
     return info->init(pci_dev);
 }
diff --git a/hw/pci.h b/hw/pci.h
index 5cf0b59..aadd1a5 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -106,6 +106,14 @@ typedef struct PCIIORegion {
 #define  PCI_COMMAND_IO		0x1	/* Enable response in I/O space */
 #define  PCI_COMMAND_MEMORY	0x2	/* Enable response in Memory space */
 #define  PCI_COMMAND_MASTER	0x4	/* Enable bus master */
+#define  PCI_COMMAND_SPECIAL	0x8	/* Enable response to special cycles */
+#define  PCI_COMMAND_INVALIDATE 0x10	/* Use memory write and invalidate */
+#define  PCI_COMMAND_VGA_PALETTE 0x20	/* Enable palette snooping */
+#define  PCI_COMMAND_PARITY	0x40	/* Enable parity checking */
+#define  PCI_COMMAND_WAIT	0x80	/* Enable address/data stepping */
+#define  PCI_COMMAND_SERR	0x100	/* Enable SERR */
+#define  PCI_COMMAND_FAST_BACK	0x200	/* Enable back-to-back writes */
+#define  PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
 #define PCI_STATUS              0x06    /* 16 bits */
 #define PCI_REVISION_ID         0x08    /* 8 bits  */
 #define PCI_CLASS_PROG		0x09	/* Reg. Level Programming Interface */
@@ -164,7 +172,32 @@ typedef struct PCIIORegion {
 
 /* Header type 1 (PCI-to-PCI bridges) */
 #define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER   0x1b    /* Latency timer for secondary interface */
+#define PCI_IO_BASE             0x1c    /* I/O range behind the bridge */
+#define PCI_IO_LIMIT            0x1d
+#define  PCI_IO_RANGE_TYPE_MASK 0x0fUL  /* I/O bridging type */
+#define  PCI_IO_RANGE_TYPE_16   0x00
+#define  PCI_IO_RANGE_TYPE_32   0x01
+#define  PCI_IO_RANGE_MASK      (~0x0fUL)
+#define PCI_MEMORY_BASE         0x20    /* Memory range behind */
+#define PCI_MEMORY_LIMIT        0x22
+#define  PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL
+#define  PCI_MEMORY_RANGE_MASK  (~0x0fUL)
+#define PCI_PREF_MEMORY_BASE    0x24    /* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT   0x26
+#define  PCI_PREF_RANGE_TYPE_MASK 0x0fUL
+#define  PCI_PREF_RANGE_TYPE_32 0x00
+#define  PCI_PREF_RANGE_TYPE_64 0x01
+#define  PCI_PREF_RANGE_MASK    (~0x0fUL)
+#define PCI_PREF_BASE_UPPER32   0x28    /* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32  0x2c
+#define PCI_IO_BASE_UPPER16     0x30    /* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16    0x32
+/* 0x34 same as for htype 0 */
+/* 0x35-0x3b is reserved */
 #define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL      0x3e
 
 /* Size of the standard PCI config header */
 #define PCI_CONFIG_HEADER_SIZE 0x40
@@ -377,6 +410,9 @@ typedef struct {
     PCIConfigReadFunc *config_read;
     PCIConfigWriteFunc *config_write;
 
+    /* pci config header type */
+    uint8_t header_type;
+
     /* pcie stuff */
     int pcie;
 } PCIDeviceInfo;
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 23/23] pci/monitor: print out bridge's filtering values and so on.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (21 preceding siblings ...)
  2009-10-05 10:07 ` [Qemu-devel] [PATCH 22/23] pci: initialize wmask according to pci header type Isaku Yamahata
@ 2009-10-05 10:07 ` Isaku Yamahata
  2009-10-05 14:24   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-05 10:14 ` [Qemu-devel] Re: [PATCH v4 00/23] pci: various pci clean up and pci express support Michael S. Tsirkin
                   ` (2 subsequent siblings)
  25 siblings, 1 reply; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-05 10:07 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

make pci_info_device() print out bridge's filtering value like
io base/limit, subbus and subordinate bus.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   39 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 2694e83..570531c 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1032,7 +1032,46 @@ static void pci_info_device(PCIBus *bus, PCIDevice *d)
                        d->config[PCI_INTERRUPT_LINE]);
     }
     if (class == 0x0604) {
+        uint64_t base;
+        uint64_t limit;
+
         monitor_printf(mon, "      BUS %d.\n", d->config[0x19]);
+        monitor_printf(mon, "      secondary bus %d.\n",
+                       d->config[PCI_SECONDARY_BUS]);
+        monitor_printf(mon, "      subordinate bus %d.\n",
+                       d->config[PCI_SUBORDINATE_BUS]);
+
+        base =
+            ((uint32_t)d->config[PCI_IO_BASE] & ~PCI_IO_RANGE_TYPE_MASK) << 8;
+        limit =
+            ((uint32_t)d->config[PCI_IO_LIMIT] & ~PCI_IO_RANGE_TYPE_MASK) << 8;
+        if (d->config[PCI_IO_BASE] & PCI_IO_RANGE_TYPE_32) {
+            base |= pci_get_word(d->config + PCI_IO_BASE_UPPER16) << 16;
+            limit |= pci_get_word(d->config + PCI_IO_LIMIT_UPPER16) << 16;
+        }
+        limit |= 0xfff;
+        monitor_printf(mon, "      IO range [0x%04"PRIx64", 0x%04"PRIx64"]\n",
+                       base, limit);
+
+        base = (pci_get_word(d->config + PCI_MEMORY_BASE) &
+                PCI_MEMORY_RANGE_MASK) << 16;
+        limit = (pci_get_word(d->config + PCI_MEMORY_LIMIT) &
+                 PCI_MEMORY_RANGE_MASK) << 16;
+        limit |= 0xfffff;
+        monitor_printf(mon,
+                       "      memory range [0x%08"PRIx64", 0x%08"PRIx64"]\n",
+                       base, limit);
+        base = ((uint64_t)pci_get_word(d->config + PCI_PREF_MEMORY_BASE) &
+                PCI_PREF_RANGE_MASK) << 16;
+        limit = ((uint64_t)pci_get_word(d->config + PCI_PREF_MEMORY_LIMIT) &
+                 PCI_PREF_RANGE_MASK) << 16;
+        base |=
+            (uint64_t)pci_get_long(d->config + PCI_PREF_BASE_UPPER32) << 32;
+        limit |=
+            (uint64_t)pci_get_long(d->config + PCI_PREF_LIMIT_UPPER32) << 32;
+        limit |= 0xfffff;
+        monitor_printf(mon, "      prefetchable memory range "
+                       "[0x%08"PRIx64", 0x%08"PRIx64"]\n", base, limit);
     }
     for(i = 0;i < PCI_NUM_REGIONS; i++) {
         r = &d->io_regions[i];
-- 
1.6.0.2

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

* [Qemu-devel] Re: [PATCH v4 00/23] pci: various pci clean up and pci express support.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (22 preceding siblings ...)
  2009-10-05 10:07 ` [Qemu-devel] [PATCH 23/23] pci/monitor: print out bridge's filtering values and so on Isaku Yamahata
@ 2009-10-05 10:14 ` Michael S. Tsirkin
  2009-10-05 13:34 ` Michael S. Tsirkin
  2009-10-06 14:40 ` Michael S. Tsirkin
  25 siblings, 0 replies; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 10:14 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 07:06:40PM +0900, Isaku Yamahata wrote:
> Thanks to Michael's review, patches have been much improved
> and became much readable.
> I believe I covered almost all the points from him except two.
> The rest issues are PRI macros and writing to PCI config space.
> 
> - PRI macros
>   I think that PRI is already widely used in qemu, so I decided to use it.
>   However Michael dislike those macros wanting to convert uintN_t to 
>   unsigned int/long/long long.

Not all over.  Only where we do not care about width, such as in address
for pci config, which is what this patch was touching.

>   Since my main motivation is pci express, this isn't essential for me.
>   So I don't insist on uintN_t as long as the patches are accepted.
>   However I also prefer consistent coding style, so I'd like to hear
>   other's opinion.
> 
> - writing to PCI config space
>   I eventually introduced some helper functions and a structure
>   which can be used by each pci device.
>   Maybe there would be a discussion on them.
> 
> 
> This patch set is preliminary for q35 based chipset support.
> This patch sets does various pci related clean ups and 
> 64bit bar, pciemmconfig and pci bridge support.
> 
> I'm aware that some of patches are already conflicting with
> other's patch. It is appriciated to merge some first part of
> patches which doesn't conflict.
> 
> thanks,
> 
> changes from V3:
> - indentation
> - reworked helper function to update pci configuration space
> - dropped pci_conf_init[blw]()
> - pci: use PCI_SLOT() and PCI_FUNC(). two more use.
>   I kept the acked-by hoping Michael won't be against it.
> - pci 64bit bar
>   - comment
>   - s/PCI_BASE_ADDRESS_SPACE_MEM_64/PCI_BASE_ADDRESS_MEM_TYPE_64/g
>   - s/pci_bar_is_64big/pci_bar_is_mem64/g
> - pci bridge
>   - refined pci_bar_config_offset(). 
> - bridge/qdevfy
>   - pass -1 for vmstate_register()
>   - use pci_create_simple()
>   - some clean up
> - pci/monitor: print out bridge's filtering values and so on. 
>   - fixed io range calculation
>   - unified case
>   - indentation
> 
> changes from V2:
> - bug fix pointed out by Gerd Hoffmann
>   pci_find_devie()
>   pci: make pci configuration transaction more accurate.
> 
> changes from V1:
> - introduced pcibus_t
> - dropped pci_config_[sg]et_xxx()
> - many code clean up
> - reworked pci_host.h
> - reworked pci bus search to introduce tree representation for pci bus
> - dropped some non essential patches
> 
> Isaku Yamahata (23):
>   pci: fix PCI_DPRINTF() wrt variadic macro.
>   pci: use appropriate PRIs in PCI_DPRINTF() for portability.
>   pci: introduce constant PCI_NUM_PINS for the number of interrupt
>     pins, 4.
>   pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1.
>   pci: use PCI_SLOT() and PCI_FUNC().
>   pci: define a constant to represent a unmapped bar and use it.
>   pci: helper functions to access PCIDevice::config
>   pci: use helper functions to access pci config space.
>   pci: introduce pcibus_t to represent pci bus address/size instead of
>     uint32_t
>   pci: introduce FMT_PCIBUS for printf format for pcibus_t.
>   pci: typedef pcibus_t as uint64_t instead of uint32_t.
>   pci: 64bit bar support.
>   pci: make pci configuration transaction more accurate.
>   pci: factor out the logic to get pci device from address.
>   pci_host.h: split non-inline static function in pci_host.h into
>     pci_host.c
>   pci: pcie host and mmcfg support.
>   pci: fix pci_default_write_config()
>   pci: add helper functions for pci config write function.
>   pci: use helper function in pci_default_write_config()
>   pci: make bar update function aware of pci bridge.
>   pci/brdige: qdevfy and initialize secondary bus and subordinate bus.
>   pci: initialize wmask according to pci header type.
>   pci/monitor: print out bridge's filtering values and so on.
> 
>  Makefile.target               |    8 +-
>  hw/ac97.c                     |    2 +-
>  hw/apb_pci.c                  |   31 +-
>  hw/cirrus_vga.c               |    8 +-
>  hw/e1000.c                    |   12 +-
>  hw/eepro100.c                 |   10 +-
>  hw/es1370.c                   |    2 +-
>  hw/grackle_pci.c              |   24 +-
>  hw/gt64xxx.c                  |   11 +-
>  hw/hw.h                       |   12 +
>  hw/ide/pci.c                  |    4 +-
>  hw/lsi53c895a.c               |    6 +-
>  hw/macio.c                    |    2 +-
>  hw/msix.c                     |    2 +-
>  hw/msix.h                     |    3 +-
>  hw/ne2000.c                   |    2 +-
>  hw/openpic.c                  |    2 +-
>  hw/pci-hotplug.c              |    6 +-
>  hw/pci.c                      |  845 ++++++++++++++++++++++++++++++++---------
>  hw/pci.h                      |  187 +++++++++-
>  hw/{pci_host.h => pci_host.c} |   61 +++-
>  hw/pci_host.h                 |  110 ++----
>  hw/pcnet.c                    |    9 +-
>  hw/piix_pci.c                 |   16 +-
>  hw/ppc4xx_pci.c               |   18 +-
>  hw/ppce500_pci.c              |   17 +-
>  hw/prep_pci.c                 |   14 +-
>  hw/rtl8139.c                  |    4 +-
>  hw/sun4u.c                    |    2 +-
>  hw/unin_pci.c                 |   47 +--
>  hw/usb-ohci.c                 |    2 +-
>  hw/usb-uhci.c                 |    2 +-
>  hw/vga-pci.c                  |    2 +-
>  hw/virtio-pci.c               |    2 +-
>  hw/vmware_vga.c               |    4 +-
>  hw/wdt_i6300esb.c             |    5 +-
>  36 files changed, 1031 insertions(+), 463 deletions(-)
>  copy hw/{pci_host.h => pci_host.c} (69%)

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

* [Qemu-devel] Re: [PATCH 16/23] pci: pcie host and mmcfg support.
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 16/23] pci: pcie host and mmcfg support Isaku Yamahata
@ 2009-10-05 11:01   ` Michael S. Tsirkin
  2009-10-06  8:48     ` Isaku Yamahata
  2009-10-05 11:41   ` Michael S. Tsirkin
  1 sibling, 1 reply; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 11:01 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 07:06:56PM +0900, Isaku Yamahata wrote:
> This patch adds common routines for pcie host bridge and pcie mmcfg.
> This will be used by q35 based chipset emulation.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Looks like most my comments on this patch were ignored.
I started repeating them here but then I grew tired,
so only partially repeated them. Are you going to address this?

Generally, pci express code isn't well separated from pci, here.  Please
try to generalize pci code, then express support would only touch a
couple of places.  Maybe even a separate file like msix.  Also, pci
express spec requires pci express capability to be present. I expected
to see this code using capability machinery.

> ---
>  hw/hw.h       |   12 +++
>  hw/pci.c      |  247 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
>  hw/pci.h      |   36 ++++++++-
>  hw/pci_host.h |   22 +++++
>  4 files changed, 285 insertions(+), 32 deletions(-)
> 
> diff --git a/hw/hw.h b/hw/hw.h
> index cf266b3..478b0b2 100644
> --- a/hw/hw.h
> +++ b/hw/hw.h
> @@ -428,6 +428,18 @@ extern const VMStateDescription vmstate_pci_device;
>              + type_check(PCIDevice,typeof_field(_state, _field))     \
>  }
>  
> +extern const VMStateDescription vmstate_pcie_device;
> +
> +#define VMSTATE_PCIE_DEVICE(_field, _state) {                        \
> +    .name       = (stringify(_field)),                               \
> +    .version_id = 2,                                                 \
> +    .size       = sizeof(PCIDevice),                                 \
> +    .vmsd       = &vmstate_pcie_device,                              \
> +    .flags      = VMS_STRUCT,                                        \
> +    .offset     = offsetof(_state, _field)                           \
> +            + type_check(PCIDevice,typeof_field(_state, _field))     \
> +}
> +
>  /* _f : field name
>     _f_n : num of elements field_name
>     _n : num of elements
> diff --git a/hw/pci.c b/hw/pci.c
> index 5f808ff..12260da 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -23,6 +23,7 @@
>   */
>  #include "hw.h"
>  #include "pci.h"
> +#include "pci_host.h"
>  #include "monitor.h"
>  #include "net.h"
>  #include "sysemu.h"
> @@ -184,9 +185,12 @@ int pci_bus_num(PCIBus *s)
>  static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
>  {
>      PCIDevice *s = container_of(pv, PCIDevice, config);
> -    uint8_t config[size];
> +    uint8_t *config;
>      int i;
>  
> +    assert(size == pcie_config_size(s));
> +    config = qemu_malloc(size * sizeof(config[0]));
> +
>      qemu_get_buffer(f, config, size);
>      for (i = 0; i < size; ++i)
>          if ((config[i] ^ s->config[i]) & s->cmask[i] & ~s->wmask[i])
> @@ -195,6 +199,7 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
>  
>      pci_update_mappings(s);
>  
> +    qemu_free(config);
>      return 0;
>  }
>  
> @@ -202,6 +207,7 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
>  static void put_pci_config_device(QEMUFile *f, const void *pv, size_t size)
>  {
>      const uint8_t *v = pv;
> +    assert(size == pcie_config_size(container_of(pv, PCIDevice, config)));
>      qemu_put_buffer(f, v, size);
>  }
>  
> @@ -211,6 +217,17 @@ static VMStateInfo vmstate_info_pci_config = {
>      .put  = put_pci_config_device,
>  };
>  
> +#define VMSTATE_PCI_CONFIG(_field, _state, _version, _info, _type,   \
> +                           _size) {                                  \
> +    .name       = (stringify(_field)),                               \
> +    .version_id = (_version),                                        \
> +    .size       = (_size),                                           \
> +    .info       = &(_info),                                          \
> +    .flags      = VMS_SINGLE | VMS_POINTER,                          \
> +    .offset     = offsetof(_state, _field)                           \
> +            + type_check(_type,typeof_field(_state, _field))         \
> +}
> +
>  const VMStateDescription vmstate_pci_device = {
>      .name = "PCIDevice",
>      .version_id = 2,
> @@ -218,21 +235,46 @@ const VMStateDescription vmstate_pci_device = {
>      .minimum_version_id_old = 1,
>      .fields      = (VMStateField []) {
>          VMSTATE_INT32_LE(version_id, PCIDevice),
> -        VMSTATE_SINGLE(config, PCIDevice, 0, vmstate_info_pci_config,
> -                       typeof_field(PCIDevice,config)),
> +        VMSTATE_PCI_CONFIG(config, PCIDevice, 0, vmstate_info_pci_config,
> +                           typeof_field(PCIDevice, config),
> +                           PCI_CONFIG_SPACE_SIZE),
> +        VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +const VMStateDescription vmstate_pcie_device = {
> +    .name = "PCIDevice",
> +    .version_id = 2,
> +    .minimum_version_id = 1,
> +    .minimum_version_id_old = 1,
> +    .fields      = (VMStateField []) {
> +        VMSTATE_INT32_LE(version_id, PCIDevice),
> +        VMSTATE_PCI_CONFIG(config, PCIDevice, 0, vmstate_info_pci_config,
> +                           typeof_field(PCIDevice, config),
> +                           PCIE_CONFIG_SPACE_SIZE),
>          VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
>          VMSTATE_END_OF_LIST()
>      }
>  };
>  
> +static const VMStateDescription *pci_get_vmstate(PCIDevice *s)
> +{
> +    if (pci_is_pcie(s)) {
> +        return &vmstate_pcie_device;
> +    }
> +
> +    return &vmstate_pci_device;
> +}
> +
>  void pci_device_save(PCIDevice *s, QEMUFile *f)
>  {
> -    vmstate_save_state(f, &vmstate_pci_device, s);
> +    vmstate_save_state(f, pci_get_vmstate(s), s);
>  }
>  
>  int pci_device_load(PCIDevice *s, QEMUFile *f)
>  {
> -    return vmstate_load_state(f, &vmstate_pci_device, s, s->version_id);
> +    return vmstate_load_state(f, pci_get_vmstate(s), s, s->version_id);
>  }
>  
>  static int pci_set_default_subsystem_id(PCIDevice *pci_dev)
> @@ -341,14 +383,31 @@ static void pci_init_cmask(PCIDevice *dev)
>  static void pci_init_wmask(PCIDevice *dev)
>  {
>      int i;
> +    uint32_t config_size = pcie_config_size(dev);
> +
>      dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
>      dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
>      dev->wmask[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY
>                                | PCI_COMMAND_MASTER;
> -    for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i)
> +    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
>          dev->wmask[i] = 0xff;
>  }
>  
> +static void pci_config_alloc(PCIDevice *pci_dev)
> +{
> +    int config_size = pcie_config_size(pci_dev);
> +#define PCI_CONFIG_ALLOC(d, member, size)                               \
> +    do {                                                                \
> +        (d)->member =                                                   \
> +            (typeof((d)->member))qemu_mallocz(sizeof((d)->member[0]) *  \
> +                                              size);                    \
> +    } while (0)
> +    PCI_CONFIG_ALLOC(pci_dev, config, config_size);
> +    PCI_CONFIG_ALLOC(pci_dev, cmask, config_size);
> +    PCI_CONFIG_ALLOC(pci_dev, wmask, config_size);
> +    PCI_CONFIG_ALLOC(pci_dev, used, config_size);

Please don't abuse macros in this way.
And sizeof is a single byte anyway, so just qemu_mallocz(config_size)
is all you need.

Also, I don't see this memory freed anywhere.

> +}
> +
>  /* -1 for devfn means auto assign */
>  static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
>                                           const char *name, int devfn,
> @@ -369,6 +428,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
>      pci_dev->devfn = devfn;
>      pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
>      memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
> +    pci_config_alloc(pci_dev);
>      pci_set_default_subsystem_id(pci_dev);
>      pci_init_cmask(pci_dev);
>      pci_init_wmask(pci_dev);
> @@ -586,40 +646,48 @@ static void pci_update_mappings(PCIDevice *d)
>      }
>  }
>  
> +static uint8_t pcie_config_get_byte(PCIDevice *d, uint32_t addr)
> +{
> +    uint8_t *conf = &d->config[addr];
> +    if (conf != NULL)
> +        return *conf;
> +    return 0;
> +}
> +

config is never NULL here.

> +static uint32_t pcie_config_get(PCIDevice *d, uint32_t addr, int len)
> +{
> +    int i;
> +    union {
> +        uint8_t val8[4];
> +        uint32_t val32;
> +    } v = { .val32 = 0 };
> +
> +    for (i = 0; i < len; i++) {
> +        v.val8[i] = pcie_config_get_byte(d, addr + i);
> +    }
> +
> +    return le32_to_cpu(v.val32);
> +}
> +

You seem to displike memcpy :) It's more readbable and generates better
code than an open loop. I already posted a single-line replacement for
this function:
uint32_t val = 0;
memcpy(&val, d->config + addr, len);
return le32_to_cpu(val);

which is now small enough to be open-coded.
Also, names starting with pcie are inappropriate for
generic pci code.


>  uint32_t pci_default_read_config(PCIDevice *d,
>                                   uint32_t address, int len)
>  {
> -    uint32_t val;
> +    uint32_t config_size = pcie_config_size(d);
>  
> -    switch(len) {
> -    default:
> -    case 4:
> -	if (address <= 0xfc) {
> -            val = pci_get_long(d->config + address);
> -	    break;
> -	}
> -	/* fall through */
> -    case 2:
> -        if (address <= 0xfe) {
> -            val = pci_get_word(d->config + address);
> -	    break;
> -	}
> -	/* fall through */
> -    case 1:
> -        val = pci_get_byte(d->config + address);
> -        break;
> -    }
> -    return val;
> +    assert(len == 1 || len == 2 || len == 4);
> +    len = MIN(len, config_size - MIN(config_size, address));
> +    return pcie_config_get(d, address, len);
>  }
>  
>  void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
>  {
>      uint8_t orig[PCI_CONFIG_SPACE_SIZE];
>      int i;
> +    uint32_t config_size = pcie_config_size(d);
>  
>      /* not efficient, but simple */
>      memcpy(orig, d->config, PCI_CONFIG_SPACE_SIZE);
> -    for(i = 0; i < l && addr < PCI_CONFIG_SPACE_SIZE; val >>= 8, ++i, ++addr) {
> +    for(i = 0; i < l && addr < config_size; val >>= 8, ++i, ++addr) {
>          uint8_t wmask = d->wmask[addr];
>          d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
>      }
> @@ -703,6 +771,128 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
>      return pci_data_read_common(pci_addr_to_dev(s, addr),
>                                  pci_addr_to_config(addr), len);
>  }
> +
> +#define PCIE_MASK(val, hi_bit, low_bit)                 \
> +    (((val) & (((1ULL << (hi_bit)) - 1))) >> (low_bit))

Why long long? Should be 1UL?

> +#define PCIE_VAL(VAL, val)                                              \
> +    PCIE_MASK((val), PCIE_MMCFG_ ## VAL ## _HI, PCIE_MMCFG_ ## VAL ## _LOW)

Please kill these macros.

> +#define PCIE_MMCFG_BUS_HI               28
> +#define PCIE_MMCFG_BUS_LOW              20
> +#define PCIE_MMCFG_DEV_HI               19
> +#define PCIE_MMCFG_DEV_LOW              15
> +#define PCIE_MMCFG_FUNC_HI              14
> +#define PCIE_MMCFG_FUNC_LOW             12
> +#define PCIE_MMCFG_CONFADDR_HI          11
> +#define PCIE_MMCFG_CONFADDR_LOW         0

HI/LOW are confusing: you don't know whether HI is last bit or one after
last. _BIT and _MASK are unambigious and would be better.

> +#define PCIE_MMCFG_BUS(addr)            PCIE_VAL(BUS, (addr))
> +#define PCIE_MMCFG_DEV(addr)            PCIE_VAL(DEV, (addr))
> +#define PCIE_MMCFG_FUNC(addr)           PCIE_VAL(FUNC, (addr))
> +#define PCIE_MMCFG_CONFADDR(addr)       PCIE_VAL(CONFADDR, (addr))
> +
> +void pcie_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> +{
> +    PCIBus *s = opaque;
> +    pci_data_write_common(pci_find_device(s, PCIE_MMCFG_BUS(addr),
> +                                          PCIE_MMCFG_DEV(addr),
> +                                          PCIE_MMCFG_FUNC(addr)),
> +                          PCIE_MMCFG_CONFADDR(addr),
> +                          val, len);
> +}
> +
> +uint32_t pcie_data_read(void *opaque, uint32_t addr, int len)
> +{
> +    PCIBus *s = opaque;
> +    return pci_data_read_common(pci_find_device(s, PCIE_MMCFG_BUS(addr),
> +                                                PCIE_MMCFG_DEV(addr),
> +                                                PCIE_MMCFG_FUNC(addr)),
> +                                PCIE_MMCFG_CONFADDR(addr),
> +                                len);
> +}

These are only for mmcfg, right? So please name these
pcie_mmcfg_data_read.

> +
> +#define DEFINE_PCIE_HOST_DATA_READ(len)                         \
> +    static uint32_t pcie_host_data_read_ ## len (               \
> +        void *opaque, target_phys_addr_t addr)                  \
> +    {                                                           \
> +        PCIExpressHost *e = (PCIExpressHost *)opaque;           \


Do not cast void * values. This way if type is changed
at some point, you get compiler error.

> +        return pcie_data_read(e->pci.bus,                       \
> +                              addr - e->base_addr, (len));      \
> +    }
> +
> +#define DEFINE_PCIE_HOST_DATA_WRITE(len)                        \
> +    static void pcie_host_data_write_ ## len (                  \
> +        void *opaque, target_phys_addr_t addr, uint32_t value)  \
> +    {                                                           \
> +        PCIExpressHost *e = (PCIExpressHost *)opaque;           \
> +        pcie_data_write(e->pci.bus,                             \
> +                        addr - e->base_addr, value, (len));     \
> +    }
> +
> +#define DEFINE_PCIE_HOST_DATA_MMIO(len)      \
> +        DEFINE_PCIE_HOST_DATA_READ(len)      \
> +        DEFINE_PCIE_HOST_DATA_WRITE(len)
> +
> +DEFINE_PCIE_HOST_DATA_MMIO(1)
> +DEFINE_PCIE_HOST_DATA_MMIO(2)
> +DEFINE_PCIE_HOST_DATA_MMIO(4)
> +
> +#define DEFINE_PCIE_MEMORY_FUNCS(Type, type)                            \
> +    static CPU ## Type ## MemoryFunc *pcie_host_data_ ## type [] =      \
> +    {                                                                   \
> +        &pcie_host_data_ ## type ## _1,                                 \
> +        &pcie_host_data_ ## type ## _2,                                 \
> +        &pcie_host_data_ ## type ## _4,                                 \
> +    };
> +
> +DEFINE_PCIE_MEMORY_FUNCS(Read, read)
> +DEFINE_PCIE_MEMORY_FUNCS(Write, write)

Please just init structures in the plain way.  Then editors, taggers
have a chance in hell to figure out how a function gets called.  These
macros obfuscate code terribly, and do not really buy us anything.

> +
> +int pcie_host_init(PCIExpressHost *e,
> +                   CPUReadMemoryFunc **mmcfg_read,
> +                   CPUWriteMemoryFunc **mmcfg_write)
> +{
> +    e->base_addr = PCIE_BASE_ADDR_INVALID;
> +
> +    if (mmcfg_read == NULL)

Replace == NULL with !

> +        mmcfg_read = pcie_host_data_read;
> +    if (mmcfg_write == NULL)
> +        mmcfg_write = pcie_host_data_write;

Do you already need special casing reads/writes?
It seems unlikely that anyone would override these.

> +    e->mmio_index = cpu_register_io_memory(mmcfg_read, mmcfg_write, e);
> +    if (e->mmio_index < 0) {
> +        return -1;
> +    }
> +
> +    return 0;
> +}
> +
> +void pcie_host_mmcfg_unmap(PCIExpressHost *e)
> +{
> +    if (e->base_addr != PCIE_BASE_ADDR_INVALID) {
> +        cpu_register_physical_memory(e->base_addr, e->size, IO_MEM_UNASSIGNED);
> +    }
> +}
> +
> +void pcie_host_mmcfg_map(PCIExpressHost *e,
> +                         target_phys_addr_t addr, uint32_t size)
> +{
> +    assert((size & (size - 1)) == 0); /* power of 2 */

Replace == 0 with !

> +    assert(size >= (1ULL << PCIE_MMCFG_BUS_LOW));
> +    assert(size <= (1ULL << PCIE_MMCFG_BUS_HI));
> +
> +    e->base_addr = addr;
> +    e->size = size;
> +    cpu_register_physical_memory(e->base_addr, e->size, e->mmio_index);
> +}
> +
> +void pcie_host_mmcfg_update(PCIExpressHost *e,
> +                            int enable,
> +                            target_phys_addr_t addr, uint32_t size)
> +{
> +    pcie_host_mmcfg_unmap(e);
> +    if (enable) {
> +        pcie_host_mmcfg_map(e, addr, size);
> +    }
> +}
> +
>  /***********************************************************/
>  /* generic PCI irq support */
>  
> @@ -1052,9 +1242,10 @@ PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
>  
>  static int pci_find_space(PCIDevice *pdev, uint8_t size)
>  {
> +    int config_size = pcie_config_size(pdev);
>      int offset = PCI_CONFIG_HEADER_SIZE;
>      int i;
> -    for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i)
> +    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
>          if (pdev->used[i])
>              offset = i + 1;
>          else if (i - offset + 1 == size)
> diff --git a/hw/pci.h b/hw/pci.h
> index 00f2b78..1f402d2 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -175,20 +175,26 @@ enum {
>      QEMU_PCI_CAP_MSIX = 0x1,
>  };
>  
> +/* Size of the standart PCIe config space: 4KB */
> +#define PCIE_CONFIG_SPACE_SIZE  0x1000
> +#define PCIE_EXT_CONFIG_SPACE_SIZE                      \
> +    (PCIE_CONFIG_SPACE_SIZE - PCI_CONFIG_SPACE_SIZE)
> +

where's this used?

>  struct PCIDevice {
>      DeviceState qdev;
> +
>      /* PCI config space */
> -    uint8_t config[PCI_CONFIG_SPACE_SIZE];
> +    uint8_t *config;
>  
>      /* Used to enable config checks on load. Note that writeable bits are
>       * never checked even if set in cmask. */
> -    uint8_t cmask[PCI_CONFIG_SPACE_SIZE];
> +    uint8_t *cmask;
>  
>      /* Used to implement R/W bytes */
> -    uint8_t wmask[PCI_CONFIG_SPACE_SIZE];
> +    uint8_t *wmask;
>  
>      /* Used to allocate config space for capabilities. */
> -    uint8_t used[PCI_CONFIG_SPACE_SIZE];
> +    uint8_t *used;
>  
>      /* the following fields are read only */
>      PCIBus *bus;
> @@ -270,6 +276,8 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
>                          const char *default_devaddr);
>  void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
>  uint32_t pci_data_read(void *opaque, uint32_t addr, int len);
> +void pcie_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
> +uint32_t pcie_data_read(void *opaque, uint32_t addr, int len);
>  int pci_bus_num(PCIBus *s);
>  void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDevice *d));
>  PCIBus *pci_find_host_bus(int domain);
> @@ -356,6 +364,9 @@ typedef struct {
>      pci_qdev_initfn init;
>      PCIConfigReadFunc *config_read;
>      PCIConfigWriteFunc *config_write;
> +
> +    /* pcie stuff */
> +    int pcie;
>  } PCIDeviceInfo;
>  
>  void pci_qdev_register(PCIDeviceInfo *info);
> @@ -365,6 +376,23 @@ PCIDevice *pci_create(const char *name, const char *devaddr);
>  PCIDevice *pci_create_noinit(PCIBus *bus, int devfn, const char *name);
>  PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
>  
> +static inline int pci_is_pcie(PCIDevice *d)
> +{
> +    /*
> +     * At the moment, all the pci devices aren't qdevfied. So
> +     * d->qdev.info might be NULL.
> +     * Given that pcie device emulator hasn't exist, we conclude that
> +     * such a device isn't pcie.
> +     */
> +    return d->qdev.info != NULL &&

kill != NULL

> +        container_of(d->qdev.info, PCIDeviceInfo, qdev)->pcie;
> +}
> +

I think this should use capabilities just like msix does.
So you would have a bit set in the cap_present field
instead of adding and using an extra field.


> +static inline uint32_t pcie_config_size(PCIDevice *d)
> +{
> +    return pci_is_pcie(d)? PCIE_CONFIG_SPACE_SIZE: PCI_CONFIG_SPACE_SIZE;

space before ?

> +}
> +

Should be pci_config_size. Generally pcie_xxx should be for
express only, generic stuff should be pci_xxx.

>  /* lsi53c895a.c */
>  #define LSI_MAX_DEVS 7
>  
> diff --git a/hw/pci_host.h b/hw/pci_host.h
> index ea98ed2..59147cf 100644
> --- a/hw/pci_host.h
> +++ b/hw/pci_host.h
> @@ -48,4 +48,26 @@ uint32_t pci_host_data_readb_ioport(void* opaque, uint32_t addr);
>  uint32_t pci_host_data_readw_ioport(void* opaque, uint32_t addr);
>  uint32_t pci_host_data_readl_ioport(void* opaque, uint32_t addr);
>  
> +typedef struct {
> +    PCIHostState pci;
> +
> +    /* express part */
> +    target_phys_addr_t  base_addr;
> +#define PCIE_BASE_ADDR_INVALID  ((target_phys_addr_t)-1ULL)

Isn't this the same as PCI? Let's reuse it?

> +    target_phys_addr_t  size;
> +    int bus_num_order;
> +    int mmio_index;
> +} PCIExpressHost;
> +
> +int pcie_host_init(PCIExpressHost *e,
> +                   CPUReadMemoryFunc **mmcfg_read,
> +                   CPUWriteMemoryFunc **mmcfg_write);
> +
> +void pcie_host_mmcfg_unmap(PCIExpressHost *e);
> +void pcie_host_mmcfg_map(PCIExpressHost *e,
> +                         target_phys_addr_t addr, uint32_t size);
> +void pcie_host_mmcfg_update(PCIExpressHost *e,
> +                            int enable,
> +                            target_phys_addr_t addr, uint32_t size);
> +
>  #endif /* PCI_HOST_H */
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH 16/23] pci: pcie host and mmcfg support.
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 16/23] pci: pcie host and mmcfg support Isaku Yamahata
  2009-10-05 11:01   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-05 11:41   ` Michael S. Tsirkin
  2009-10-06 10:02     ` Isaku Yamahata
  1 sibling, 1 reply; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 11:41 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 07:06:56PM +0900, Isaku Yamahata wrote:
> @@ -1052,9 +1242,10 @@ PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
>  
>  static int pci_find_space(PCIDevice *pdev, uint8_t size)
>  {
> +    int config_size = pcie_config_size(pdev);
>      int offset = PCI_CONFIG_HEADER_SIZE;
>      int i;
> -    for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i)
> +    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
>          if (pdev->used[i])
>              offset = i + 1;
>          else if (i - offset + 1 == size)
> diff --git a/hw/pci.h b/hw/pci.h
> index 00f2b78..1f402d2 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -175,20 +175,26 @@ enum {
>      QEMU_PCI_CAP_MSIX = 0x1,
>  };
>  
> +/* Size of the standart PCIe config space: 4KB */
> +#define PCIE_CONFIG_SPACE_SIZE  0x1000
> +#define PCIE_EXT_CONFIG_SPACE_SIZE                      \
> +    (PCIE_CONFIG_SPACE_SIZE - PCI_CONFIG_SPACE_SIZE)
> +
>  struct PCIDevice {
>      DeviceState qdev;
> +
>      /* PCI config space */
> -    uint8_t config[PCI_CONFIG_SPACE_SIZE];
> +    uint8_t *config;
>  
>      /* Used to enable config checks on load. Note that writeable bits are
>       * never checked even if set in cmask. */
> -    uint8_t cmask[PCI_CONFIG_SPACE_SIZE];
> +    uint8_t *cmask;
>  
>      /* Used to implement R/W bytes */
> -    uint8_t wmask[PCI_CONFIG_SPACE_SIZE];
> +    uint8_t *wmask;
>  
>      /* Used to allocate config space for capabilities. */
> -    uint8_t used[PCI_CONFIG_SPACE_SIZE];
> +    uint8_t *used;
>  
>      /* the following fields are read only */
>      PCIBus *bus;


So I thought about this some more, and I think that this change
in unnecessary. PCI Express adds support for extended 4K
configuration space, but the only thing that must reside
there is the optional advanced error reporting capability,
which I don't think we'll need to implement, ever.

Everything else can reside in the first 256 bytes, just as for regular
PCI. And pci code already returns 0 for accesses outside the first 256
bytes, so express specific code is necessary.

If we do this, we can keep memcpy for the full original
space (it's just 4 cache lines) and simple memcmp
with no overlap checks will be enough to figure out
if something changed. To make that also possible for
bridges, we'll then just put the orig array inside
PCIDevice. Not sure I explain this last point clearly -
would you like to see a patch?

-- 
MST

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

* [Qemu-devel] Re: [PATCH 20/23] pci: make bar update function aware of pci bridge.
  2009-10-05 10:07 ` [Qemu-devel] [PATCH 20/23] pci: make bar update function aware of pci bridge Isaku Yamahata
@ 2009-10-05 11:59   ` Michael S. Tsirkin
  2009-10-09  3:27     ` Isaku Yamahata
  0 siblings, 1 reply; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 11:59 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 07:07:00PM +0900, Isaku Yamahata wrote:
> header type of 01 has differenct BAR to type 00.
> It has only BAR0,1 and expantion rom whose offset address
> is different from type 00 one.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

The existing code is actually correct, and I think this breaks it.  I
think it's a good idea to add pci_bar_config_offset, though.
Split this up to a separate patch?

> ---
>  hw/pci.c |   56 +++++++++++++++++++++++++++++++++++++++++++++-----------
>  hw/pci.h |    2 ++
>  2 files changed, 47 insertions(+), 11 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index b8d2f8f..af864c6 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -505,6 +505,33 @@ static inline int pci_bar_is_mem64(const PCIIORegion *r)
>          PCI_ADDRESS_SPACE_MEM_TYPE_64;
>  }
>  
> +/*
> + * return offset in pci configuration space for a given BAR of region_num.
> + * header type
> + * normal  = 0: bar 0-5 and rom
> + * bridge  = 1: bar 0,1 and rom
> + * cardbus = 2: bar 0
> + */
> +static uint32_t pci_bar_config_offset(PCIDevice *d, int region_num)
> +{
> +    uint8_t header_type =
> +        d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
> +
> +    assert((header_type == PCI_HEADER_TYPE_NORMAL &&
> +            ((0 <= region_num && region_num < 6) ||
> +             region_num == PCI_ROM_SLOT)) ||

&& already binds stronger than ||, so don't put () around &&

> +           (header_type == PCI_HEADER_TYPE_BRIDGE &&
> +            ((0 <= region_num && region_num < 2) ||
> +             region_num == PCI_ROM_SLOT)) ||
> +           (header_type == PCI_HEADER_TYPE_CARDBUS && region_num == 0));

This is not the best place to put assertions.
If you really need them, pci_register_bar is a better place.

> +
> +    if (region_num != PCI_ROM_ADDRESS)
> +        return PCI_BASE_ADDRESS_0 + region_num * 4;

BTW, how does it work for 64 bit regions?

> +
> +    return header_type == PCI_HEADER_TYPE_BRIDGE?
> +        PCI_ROM_ADDRESS1: PCI_ROM_ADDRESS;

space before :

> +}
> +
>  void pci_register_bar(PCIDevice *pci_dev, int region_num,
>                              pcibus_t size, int type,
>                              PCIMapIORegionFunc *map_func)
> @@ -528,13 +555,11 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
>      r->type = type;
>      r->map_func = map_func;
>  
> +    addr = pci_bar_config_offset(pci_dev, region_num);
>      wmask = ~(size - 1);
>      if (region_num == PCI_ROM_SLOT) {
> -        addr = 0x30;
>          /* ROM enable bit is writeable */
>          wmask |= PCI_ROM_ADDRESS_ENABLE;
> -    } else {
> -        addr = 0x10 + region_num * 4;
>      }
>      pci_set_long(pci_dev->config + addr, type);
>      if (pci_bar_is_mem64(r)) {
> @@ -556,11 +581,7 @@ static void pci_update_mappings(PCIDevice *d)
>      cmd = pci_get_word(d->config + PCI_COMMAND);
>      for(i = 0; i < PCI_NUM_REGIONS; i++) {
>          r = &d->io_regions[i];
> -        if (i == PCI_ROM_SLOT) {
> -            config_ofs = 0x30;
> -        } else {
> -            config_ofs = 0x10 + i * 4;
> -        }
> +        config_ofs = pci_bar_config_offset(d, i);
>          if (r->size != 0) {
>              if (r->type & PCI_ADDRESS_SPACE_IO) {
>                  if (cmd & PCI_COMMAND_IO) {
> @@ -1123,10 +1144,23 @@ static void pci_bridge_write_config(PCIDevice *d,
>                               uint32_t address, uint32_t val, int len)
>  {
>      PCIBridge *s = (PCIBridge *)d;
> +    PCIBus *bus = s->bus;
> +    struct pci_config_update update;
>  
> -    pci_default_write_config(d, address, val, len);
> -    s->bus->bus_num = d->config[PCI_SECONDARY_BUS];
> -    s->bus->sub_bus = d->config[PCI_SUBORDINATE_BUS];
> +    pci_write_config_init(&update, d, address, val, len);
> +    pci_write_config_update(&update);
> +    if (pci_config_changed(&update,
> +                           PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_2 + 4) ||
> +        pci_config_changed_with_size(&update, PCI_ROM_ADDRESS1, 4) ||
> +        pci_config_changed_with_size(&update, PCI_COMMAND, 1)) {
> +        pci_update_mappings(d);
> +    }

This is wrong I think. You must also take into account memory
base/limit registers, and redo mapping when these change.
If you do, you should note several things:
- BARs for devices placed behind a bridge who's memory
  is outside the bridge base/limit are effectively disabled.
- Base addresses for pci devices overlap base/limit for
  bridge. For this reason, default_write_config
  was already doing the right thing, doing update
  when the bridge base/limit are changed.

> +    if (pci_config_changed_with_size(&update, PCI_SECONDARY_BUS, 1)) {
> +        bus->bus_num = d->config[PCI_SECONDARY_BUS];
> +    }
> +    if (pci_config_changed_with_size(&update, PCI_SUBORDINATE_BUS, 1)) {
> +        bus->sub_bus = d->config[PCI_SUBORDINATE_BUS];
> +    }
>  }
>  
>  PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
> diff --git a/hw/pci.h b/hw/pci.h
> index 37c2c23..1d45437 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -118,6 +118,7 @@ typedef struct PCIIORegion {
>  #define  PCI_HEADER_TYPE_CARDBUS	2
>  #define  PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
>  #define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
> +#define PCI_BASE_ADDRESS_2	0x18	/* 32 bits */
>  #define PCI_BASE_ADDRESS_5	0x24	/* 32 bits */
>  #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
>  #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
> @@ -163,6 +164,7 @@ typedef struct PCIIORegion {
>  
>  /* Header type 1 (PCI-to-PCI bridges) */
>  #define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
> +#define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
>  
>  /* Size of the standard PCI config header */
>  #define PCI_CONFIG_HEADER_SIZE 0x40
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH 12/23] pci: 64bit bar support.
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 12/23] pci: 64bit bar support Isaku Yamahata
@ 2009-10-05 12:06   ` Michael S. Tsirkin
  2009-10-06  9:38     ` Isaku Yamahata
  2009-10-05 12:47   ` Michael S. Tsirkin
  1 sibling, 1 reply; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 12:06 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 07:06:52PM +0900, Isaku Yamahata wrote:
> implemented pci 64bit bar support.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++--------
>  hw/pci.h |    2 ++
>  2 files changed, 48 insertions(+), 8 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 21565f5..09a6816 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -395,6 +395,13 @@ int pci_unregister_device(PCIDevice *pci_dev)
>      return 0;
>  }
>  
> +static inline int pci_bar_is_mem64(const PCIIORegion *r)
> +{
> +    return !(r->type & PCI_ADDRESS_SPACE_IO) &&
> +        (r->type & PCI_ADDRESS_SPACE_MEM_TYPE_MASK) ==
> +        PCI_ADDRESS_SPACE_MEM_TYPE_64;
> +}
> +

why are we checking PCI_ADDRESS_SPACE_IO? Let's not.

>  void pci_register_bar(PCIDevice *pci_dev, int region_num,
>                              pcibus_t size, int type,
>                              PCIMapIORegionFunc *map_func)
> @@ -427,8 +434,13 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
>          addr = 0x10 + region_num * 4;
>      }
>      pci_set_long(pci_dev->config + addr, type);
> -    pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
> -    pci_set_long(pci_dev->cmask + addr, 0xffffffff);
> +    if (pci_bar_is_mem64(r)) {
> +        pci_set_quad(pci_dev->wmask + addr, wmask);
> +        pci_set_quad(pci_dev->cmask + addr, ~0ULL);
> +    } else {
> +        pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
> +        pci_set_long(pci_dev->cmask + addr, 0xffffffff);
> +    }
>  }
>  
>  static void pci_update_mappings(PCIDevice *d)
> @@ -462,7 +474,11 @@ static void pci_update_mappings(PCIDevice *d)
>                  }
>              } else {
>                  if (cmd & PCI_COMMAND_MEMORY) {
> -                    new_addr = pci_get_long(d->config + config_ofs);
> +                    if (pci_bar_is_mem64(r)) {
> +                        new_addr = pci_get_quad(d->config + config_ofs);
> +                    } else {
> +                        new_addr = pci_get_long(d->config + config_ofs);
> +                    }
>                      /* the ROM slot has a specific enable bit */
>                      if (i == PCI_ROM_SLOT && !(new_addr & 1))
>                          goto no_mem_map;
> @@ -473,11 +489,24 @@ static void pci_update_mappings(PCIDevice *d)
>                         mappings, we handle specific values as invalid
>                         mappings. */
>                      if (last_addr <= new_addr || new_addr == 0 ||
> -                        last_addr == PCI_BAR_UNMAPPED ||
> +                        last_addr == PCI_BAR_UNMAPPED) {
> +                        new_addr = PCI_BAR_UNMAPPED;
> +                    }
>  
> -                        /* keep old behaviour
> -                         * without this, PC ide doesn't work well. */
> -                        last_addr >= UINT32_MAX) {
> +                    /*
> +                     * work around: without this, PC ide and other devices
> +                     * don't work well.
> +                     * OS writes all 1 bits to 32 BAR to find its size

Isn't memory disabled then? PCI spec says it should be ...

> +                     * resulting in setting UINT32_MAX - alignemnt,

typo

> +                     * and then OS sets the BAR to where they really want
> +                     * the BAR to sit.
> +                     * On the other hand, there are some important areas
> +                     * blow 4G on i386/x86_64. So setting BAR over those area

typo

> +                     * below 4G causes troubles.
> +                     * We work around the issues by prohibitting BAR

typo.

> +                     * from sitting right blow 4G.

typo

> +                     */
> +                    if (!pci_bar_is_mem64(r) && last_addr >= UINT32_MAX) {
>                          new_addr = PCI_BAR_UNMAPPED;
>                      }
>                  } else {
> @@ -736,7 +765,16 @@ static void pci_info_device(PCIDevice *d)
>                  monitor_printf(mon, "I/O at 0x%04"FMT_PCIBUS" [0x%04"FMT_PCIBUS"].\n",
>                                 r->addr, r->addr + r->size - 1);
>              } else {
> -                monitor_printf(mon, "32 bit memory at 0x%08"FMT_PCIBUS" [0x%08"FMT_PCIBUS"].\n",
> +                const char *type = pci_bar_is_mem64(r)? "64 bit": "32 bit";
> +                const char *prefetch = "";
> +
> +                if (r->type & PCI_ADDRESS_SPACE_MEM_PREFETCH) {
> +                    prefetch = " prefetchable";
> +                }
> +
> +                monitor_printf(mon, "%s%s memory at "
> +                               "0x%08"FMT_PCIBUS" [0x%08"FMT_PCIBUS"].\n",
> +                               type, prefetch,
>                                 r->addr, r->addr + r->size - 1);
>              }
>          }
> diff --git a/hw/pci.h b/hw/pci.h
> index cbf80c0..b65ce03 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -84,6 +84,8 @@ typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
>  
>  #define PCI_ADDRESS_SPACE_MEM		0x00
>  #define PCI_ADDRESS_SPACE_IO		0x01
> +#define PCI_ADDRESS_SPACE_MEM_TYPE_MASK 0x06
> +#define PCI_ADDRESS_SPACE_MEM_TYPE_64   0x04    /* 64 bit address */

something wrong with text alignment here. pls align with tabs as the
rest of surrounding code does.

And I thought we were switching to names from pci_regs.h?

>  #define PCI_ADDRESS_SPACE_MEM_PREFETCH	0x08
>  
>  typedef struct PCIIORegion {
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH 13/23] pci: make pci configuration transaction more accurate.
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 13/23] pci: make pci configuration transaction more accurate Isaku Yamahata
@ 2009-10-05 12:26   ` Michael S. Tsirkin
  0 siblings, 0 replies; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 12:26 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 07:06:53PM +0900, Isaku Yamahata wrote:
> This patch sorts out/enhances pci code to track pci bus topology
> accurately.
> - Track host bus bridge with pci domain number. Although the
>   current qemu support only pci domian 0 yet.

try running ispell on comments :)

> - Track pci bridge parent-child relationship.
> When looking down from pci host bus for pci sub bus, be aware of
> secondary bus/subordinate bus.
> Thus pci configuration transaction is more accurately emulated.
> 
> This patch adds new member to PCIBus to track pci bus topology.
> Since qdev already tracks down bus relationship, those new member
> wouldn't be necessary.

In fact, I think qdev tracks physical topology, sub_bus is
guest-assignable, it can get any value within limits.

> However it would be addressed later because not all the pci device
> isn't converted to qdev yet.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/apb_pci.c     |    4 +-
>  hw/pci-hotplug.c |    6 +-
>  hw/pci.c         |  121 ++++++++++++++++++++++++++++++++++++++++--------------
>  hw/pci.h         |   11 ++++-
>  4 files changed, 103 insertions(+), 39 deletions(-)
> 
> diff --git a/hw/apb_pci.c b/hw/apb_pci.c
> index 9d9f5fc..381b924 100644
> --- a/hw/apb_pci.c
> +++ b/hw/apb_pci.c
> @@ -254,11 +254,11 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
>      /* APB secondary busses */
>      *bus2 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 0),
>                              PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
> -                            pci_apb_map_irq,
> +                            1, 1, pci_apb_map_irq,
>                              "Advanced PCI Bus secondary bridge 1");
>      *bus3 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 1),
>                              PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
> -                            pci_apb_map_irq,
> +                            2, 2, pci_apb_map_irq,
>                              "Advanced PCI Bus secondary bridge 2");
>  
>      return d->host_state.bus;

How come we need to set these up?  I thought we should init to 0
and BIOS will set them up for us?

> diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
> index f3dc421..890ecc3 100644
> --- a/hw/pci-hotplug.c
> +++ b/hw/pci-hotplug.c
> @@ -65,7 +65,7 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
>          return;
>      }
>  
> -    dev = pci_find_device(pci_bus, slot, 0);
> +    dev = pci_find_device(pci_find_host_bus(0), pci_bus, slot, 0);
>      if (!dev) {
>          monitor_printf(mon, "no pci device with address %s\n", pci_addr);
>          return;


Actually, what we do here is already pretty broken:
monitor commands should get topology info, bus number
is not topology.

> @@ -201,7 +201,7 @@ void pci_device_hot_remove(Monitor *mon, const char *pci_addr)
>          return;
>      }
>  
> -    d = pci_find_device(bus, slot, 0);
> +    d = pci_find_device(pci_find_host_bus(0), bus, slot, 0);
>      if (!d) {
>          monitor_printf(mon, "slot %d empty\n", slot);
>          return;
> @@ -228,7 +228,7 @@ static int pci_match_fn(void *dev_private, void *arg)
>   */
>  void pci_device_hot_remove_success(int pcibus, int slot)
>  {
> -    PCIDevice *d = pci_find_device(pcibus, slot, 0);
> +    PCIDevice *d = pci_find_device(pci_find_host_bus(0), pcibus, slot, 0);
>      int class_code;
>  
>      if (!d) {
> diff --git a/hw/pci.c b/hw/pci.c
> index 09a6816..6ddd256 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -34,9 +34,12 @@
>  # define PCI_DPRINTF(format, ...)       do { } while (0)
>  #endif
>  
> +#define PCI_BUS_NUM_MAX 255
>  struct PCIBus {
>      BusState qbus;
>      int bus_num;
> +    int sub_bus;
> +
>      int devfn_min;
>      pci_set_irq_fn set_irq;
>      pci_map_irq_fn map_irq;
> @@ -44,7 +47,10 @@ struct PCIBus {
>      void *irq_opaque;
>      PCIDevice *devices[256];
>      PCIDevice *parent_dev;
> -    PCIBus *next;
> +
> +    QLIST_HEAD(, PCIBus) child; /* this will be replaced by qdev later */
> +    QLIST_ENTRY(PCIBus) sibling;/* this will be replaced by qdev later */
> +
>      /* The bus IRQ state is the logical OR of the connected devices.
>         Keep a count of the number of devices with raised IRQs.  */
>      int nirq;
> @@ -69,7 +75,13 @@ static void pci_set_irq(void *opaque, int irq_num, int level);
>  target_phys_addr_t pci_mem_base;
>  static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
>  static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
> -static PCIBus *first_bus;
> +
> +struct PCIHostBus {
> +    int domain;
> +    struct PCIBus *bus;
> +    QLIST_ENTRY(PCIHostBus) next;
> +};
> +static QLIST_HEAD(, PCIHostBus) host_buses;
>  
>  static const VMStateDescription vmstate_pcibus = {
>      .name = "PCIBUS",
> @@ -98,6 +110,28 @@ static void pci_bus_reset(void *opaque)
>      }
>  }
>  
> +static void pci_host_bus_register(int domain, PCIBus *bus)
> +{
> +    struct PCIHostBus *host;
> +    host = qemu_mallocz(sizeof(*host));
> +    host->domain = domain;
> +    host->bus = bus;
> +    QLIST_INSERT_HEAD(&host_buses, host, next);
> +}
> +
> +PCIBus *pci_find_host_bus(int domain)
> +{
> +    struct PCIHostBus *host;
> +
> +    QLIST_FOREACH(host, &host_buses, next) {
> +        if (host->domain == domain) {
> +            return host->bus;
> +        }
> +    }
> +
> +    return NULL;
> +}
> +
>  PCIBus *pci_register_bus(DeviceState *parent, const char *name,
>                           pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
>                           void *irq_opaque, int devfn_min, int nirq)
> @@ -112,14 +146,20 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
>      bus->devfn_min = devfn_min;
>      bus->nirq = nirq;
>      bus->irq_count = qemu_mallocz(nirq * sizeof(bus->irq_count[0]));
> -    bus->next = first_bus;
> -    first_bus = bus;
> +
> +    /* host bridge */
> +    bus->bus_num = 0;
> +    bus->sub_bus = PCI_BUS_NUM_MAX;
> +    QLIST_INIT(&bus->child);
> +    pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */
> +
>      vmstate_register(nbus++, &vmstate_pcibus, bus);
>      qemu_register_reset(pci_bus_reset, bus);
>      return bus;
>  }
>  
> -static PCIBus *pci_register_secondary_bus(PCIDevice *dev,
> +static PCIBus *pci_register_secondary_bus(PCIBus *parent,
> +                                          PCIDevice *dev,
>                                            pci_map_irq_fn map_irq,
>                                            const char *name)
>  {
> @@ -128,8 +168,11 @@ static PCIBus *pci_register_secondary_bus(PCIDevice *dev,
>      bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, &dev->qdev, name));
>      bus->map_irq = map_irq;
>      bus->parent_dev = dev;
> -    bus->next = dev->bus->next;
> -    dev->bus->next = bus;
> +
> +    bus->bus_num = dev->config[PCI_SECONDARY_BUS];
> +    bus->sub_bus = dev->config[PCI_SUBORDINATE_BUS];
> +    QLIST_INIT(&bus->child);
> +    QLIST_INSERT_HEAD(&parent->child, bus, sibling);
>      return bus;
>  }
>  
> @@ -242,7 +285,7 @@ static int pci_parse_devaddr(const char *addr, int *domp, int *busp, unsigned *s
>  	return -1;
>  
>      /* Note: QEMU doesn't implement domains other than 0 */
> -    if (dom != 0 || pci_find_bus(bus) == NULL)
> +    if (dom != 0 || pci_find_bus(pci_find_host_bus(0), bus) == NULL)
>  	return -1;
>  
>      *domp = dom;
> @@ -272,7 +315,7 @@ static PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
>  
>      if (!devaddr) {
>          *devfnp = -1;
> -        return pci_find_bus(0);
> +        return pci_find_bus(pci_find_host_bus(0), 0);
>      }
>  
>      if (pci_parse_devaddr(devaddr, &dom, &bus, &slot) < 0) {
> @@ -280,7 +323,7 @@ static PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
>      }
>  
>      *devfnp = slot << 3;
> -    return pci_find_bus(bus);
> +    return pci_find_bus(pci_find_host_bus(0), bus);
>  }
>  
>  static void pci_init_cmask(PCIDevice *dev)
> @@ -597,8 +640,7 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
>                  addr, val, len);
>  #endif
>      bus_num = (addr >> 16) & 0xff;
> -    while (s && s->bus_num != bus_num)
> -        s = s->next;
> +    s = pci_find_bus(s, bus_num);
>      if (!s)
>          return;
>      pci_dev = s->devices[(addr >> 8) & 0xff];
> @@ -619,8 +661,7 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
>      uint32_t val;
>  
>      bus_num = (addr >> 16) & 0xff;
> -    while (s && s->bus_num != bus_num)
> -        s= s->next;
> +    s = pci_find_bus(s, bus_num);
>      if (!s)
>          goto fail;
>      pci_dev = s->devices[(addr >> 8) & 0xff];
> @@ -727,7 +768,7 @@ static const pci_class_desc pci_class_descriptions[] =
>      { 0, NULL}
>  };
>  
> -static void pci_info_device(PCIDevice *d)
> +static void pci_info_device(PCIBus *bus, PCIDevice *d)
>  {
>      Monitor *mon = cur_mon;
>      int i, class;
> @@ -781,30 +822,32 @@ static void pci_info_device(PCIDevice *d)
>      }
>      monitor_printf(mon, "      id \"%s\"\n", d->qdev.id ? d->qdev.id : "");
>      if (class == 0x0604 && d->config[0x19] != 0) {
> -        pci_for_each_device(d->config[0x19], pci_info_device);
> +        pci_for_each_device(bus, d->config[0x19], pci_info_device);
>      }
>  }
>  
> -void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
> +void pci_for_each_device(PCIBus *bus, int bus_num,
> +                         void (*fn)(PCIBus *b, PCIDevice *d))
>  {
> -    PCIBus *bus = first_bus;
>      PCIDevice *d;
>      int devfn;
>  
> -    while (bus && bus->bus_num != bus_num)
> -        bus = bus->next;
> +    bus = pci_find_bus(bus, bus_num);
>      if (bus) {
>          for(devfn = 0; devfn < 256; devfn++) {
>              d = bus->devices[devfn];
>              if (d)
> -                fn(d);
> +                fn(bus, d);
>          }
>      }
>  }
>  
>  void pci_info(Monitor *mon)
>  {
> -    pci_for_each_device(0, pci_info_device);
> +    struct PCIHostBus *host;
> +    QLIST_FOREACH(host, &host_buses, next) {
> +        pci_for_each_device(host->bus, 0, pci_info_device);
> +    }
>  }
>  
>  PCIDevice *pci_create(const char *name, const char *devaddr)
> @@ -888,22 +931,33 @@ static void pci_bridge_write_config(PCIDevice *d,
>  
>      pci_default_write_config(d, address, val, len);
>      s->bus->bus_num = d->config[PCI_SECONDARY_BUS];
> +    s->bus->sub_bus = d->config[PCI_SUBORDINATE_BUS];
>  }
>  
> -PCIBus *pci_find_bus(int bus_num)
> +PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
>  {
> -    PCIBus *bus = first_bus;
> +    PCIBus *sec;
>  
> -    while (bus && bus->bus_num != bus_num)
> -        bus = bus->next;
> +    if (!bus)
> +        return NULL;
>  
> -    return bus;
> +    if (bus->bus_num == bus_num) {
> +        return bus;
> +    }
> +
> +    /* try child bus */
> +    QLIST_FOREACH(sec, &bus->child, sibling) {
> +        if (sec->bus_num <= bus_num && bus_num <= sec->sub_bus) {
> +            return pci_find_bus(sec, bus_num);
> +        }
> +    }
> +
> +    return NULL;
>  }
>  
> -PCIDevice *pci_find_device(int bus_num, int slot, int function)
> +PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function)
>  {
> -    PCIBus *bus = pci_find_bus(bus_num);
> -
> +    bus = pci_find_bus(bus, bus_num);
>      if (!bus)
>          return NULL;
>  
> @@ -911,6 +965,7 @@ PCIDevice *pci_find_device(int bus_num, int slot, int function)
>  }
>  
>  PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
> +                        uint8_t sec_bus, uint8_t sub_bus,
>                          pci_map_irq_fn map_irq, const char *name)
>  {
>      PCIBridge *s;
> @@ -932,7 +987,11 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
>          PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE; // header_type
>      s->dev.config[0x1E] = 0xa0; // secondary status
>  
> -    s->bus = pci_register_secondary_bus(&s->dev, map_irq, name);
> +    assert(sec_bus <= sub_bus);
> +    s->dev.config[PCI_SECONDARY_BUS] = sec_bus;
> +    s->dev.config[PCI_SUBORDINATE_BUS] = sub_bus;

I think that this is wrong, config space is initialized by software.
And it is also wrong to bundle this into an unrelated patch.

> +
> +    s->bus = pci_register_secondary_bus(bus, &s->dev, map_irq, name);
>      return s->bus;
>  }
>  
> diff --git a/hw/pci.h b/hw/pci.h
> index b65ce03..00f2b78 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -160,6 +160,9 @@ typedef struct PCIIORegion {
>  
>  #define PCI_COMMAND_RESERVED_MASK_HI (PCI_COMMAND_RESERVED >> 8)
>  
> +/* Header type 1 (PCI-to-PCI bridges) */
> +#define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
> +
>  /* Size of the standard PCI config header */
>  #define PCI_CONFIG_HEADER_SIZE 0x40
>  /* Size of the standard PCI config space */
> @@ -268,15 +271,17 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
>  void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
>  uint32_t pci_data_read(void *opaque, uint32_t addr, int len);
>  int pci_bus_num(PCIBus *s);
> -void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d));
> -PCIBus *pci_find_bus(int bus_num);
> -PCIDevice *pci_find_device(int bus_num, int slot, int function);
> +void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDevice *d));
> +PCIBus *pci_find_host_bus(int domain);
> +PCIBus *pci_find_bus(PCIBus *bus, int bus_num);
> +PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function);
>  
>  int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
>                       unsigned *slotp);
>  
>  void pci_info(Monitor *mon);
>  PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
> +                        uint8_t sec_bus, uint8_t sub_bus,
>                          pci_map_irq_fn map_irq, const char *name);
>  
>  static inline void
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH 14/23] pci: factor out the logic to get pci device from address.
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 14/23] pci: factor out the logic to get pci device from address Isaku Yamahata
@ 2009-10-05 12:45   ` Michael S. Tsirkin
  2009-10-06  9:50     ` Isaku Yamahata
  0 siblings, 1 reply; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 12:45 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 07:06:54PM +0900, Isaku Yamahata wrote:
> factor out conversion logic from io port address into bus+dev+func
> with bit shift operation and conversion bus+dev+func into pci device.
> They will be used later by pcie support.
> This patch also eliminates the logic duplication.

Please split removing logic duplication into separate patch.
It might be applicable already, while express stuff needs more work IMO.

> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.c |   83 ++++++++++++++++++++++++++++++++++---------------------------
>  1 files changed, 46 insertions(+), 37 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 6ddd256..5f808ff 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -629,44 +629,25 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
>          pci_update_mappings(d);
>  }
>  
> -void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> +static void pci_data_write_common(PCIDevice *pci_dev,
> +                                  uint32_t config_addr, uint32_t val, int len)

So as I said in the previous comment, pci express should just be able to
use pci code directly, instead of reusing this low-level stuff.
All you need to do is range-check address and ignore extended registers.

>  {
> -    PCIBus *s = opaque;
> -    PCIDevice *pci_dev;
> -    int config_addr, bus_num;
> -
> -#if 0
> -    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
> -                addr, val, len);
> -#endif
> -    bus_num = (addr >> 16) & 0xff;
> -    s = pci_find_bus(s, bus_num);
> -    if (!s)
> -        return;
> -    pci_dev = s->devices[(addr >> 8) & 0xff];
> +    assert(len == 1 || len == 2 || len == 4);
>      if (!pci_dev)
>          return;
> -    config_addr = addr & 0xff;
> -    PCI_DPRINTF("pci_config_write: %s: "
> -                "addr=%02x val=%08"PRI32x" len=%d\n",
> -                pci_dev->name, config_addr, val, len);
> +
> +    PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRI32x" len=%d\n",
> +                __func__, pci_dev->name, config_addr, val, len);
>      pci_dev->config_write(pci_dev, config_addr, val, len);
>  }
>  
> -uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> +static uint32_t pci_data_read_common(PCIDevice *pci_dev,
> +                                     uint32_t config_addr, int len)
>  {
> -    PCIBus *s = opaque;
> -    PCIDevice *pci_dev;
> -    int config_addr, bus_num;
>      uint32_t val;
>  
> -    bus_num = (addr >> 16) & 0xff;
> -    s = pci_find_bus(s, bus_num);
> -    if (!s)
> -        goto fail;
> -    pci_dev = s->devices[(addr >> 8) & 0xff];
> +    assert(len == 1 || len == 2 || len == 4);
>      if (!pci_dev) {
> -    fail:
>          switch(len) {
>          case 1:
>              val = 0xff;
> @@ -679,21 +660,49 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
>              val = 0xffffffff;
>              break;
>          }
> -        goto the_end;
> +    } else {
> +        val = pci_dev->config_read(pci_dev, config_addr, len);
> +        PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
> +                    __func__, pci_dev->name, config_addr, val, len);
>      }
> -    config_addr = addr & 0xff;
> -    val = pci_dev->config_read(pci_dev, config_addr, len);
> -    PCI_DPRINTF("pci_config_read: %s: "
> -                "addr=%02x val=%08"PRIx32" len=%d\n",
> -                pci_dev->name, config_addr, val, len);
> - the_end:
> +
>  #if 0
> -    PCI_DPRINTF("pci_data_read: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
> -                addr, val, len);
> +    PCI_DPRINTF("%s: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
> +                __func__, addr, val, len);
>  #endif

move to real pci_data_read?

>      return val;
>  }
>  
> +static inline PCIDevice *pci_addr_to_dev(PCIBus *bus, uint32_t addr)
> +{
> +    uint8_t bus_num = (addr >> 16) & 0xff;
> +    uint8_t devfn = (addr >> 8) & 0xff;
> +    return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
> +}
> +
> +static inline uint32_t pci_addr_to_config(uint32_t addr)
> +{
> +    return addr & 0xff;
> +}
> +
> +void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> +{
> +    PCIBus *s = opaque;
> +#if 0
> +    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
> +                addr, val, len);
> +#endif
> +
> +    pci_data_write_common(pci_addr_to_dev(s, addr), pci_addr_to_config(addr),
> +                          val, len);

For pci express, there's extended register number in bits 11:8
so what we should do here IMO is check these bits and
ignore if they are not 0.

> +}
> +
> +uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> +{
> +    PCIBus *s = opaque;

For pci express, there's extended register number in bits 11:8
so what we should do here IMO is check these bits and
return 0 if not 0.

> +    return pci_data_read_common(pci_addr_to_dev(s, addr),
> +                                pci_addr_to_config(addr), len);
> +}
>  /***********************************************************/
>  /* generic PCI irq support */
>  
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH 12/23] pci: 64bit bar support.
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 12/23] pci: 64bit bar support Isaku Yamahata
  2009-10-05 12:06   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-05 12:47   ` Michael S. Tsirkin
  2009-10-06  9:42     ` Isaku Yamahata
  1 sibling, 1 reply; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 12:47 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 07:06:52PM +0900, Isaku Yamahata wrote:
> implemented pci 64bit bar support.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++--------
>  hw/pci.h |    2 ++
>  2 files changed, 48 insertions(+), 8 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 21565f5..09a6816 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -395,6 +395,13 @@ int pci_unregister_device(PCIDevice *pci_dev)
>      return 0;
>  }
>  
> +static inline int pci_bar_is_mem64(const PCIIORegion *r)
> +{
> +    return !(r->type & PCI_ADDRESS_SPACE_IO) &&
> +        (r->type & PCI_ADDRESS_SPACE_MEM_TYPE_MASK) ==
> +        PCI_ADDRESS_SPACE_MEM_TYPE_64;
> +}
> +
>  void pci_register_bar(PCIDevice *pci_dev, int region_num,
>                              pcibus_t size, int type,
>                              PCIMapIORegionFunc *map_func)
> @@ -427,8 +434,13 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
>          addr = 0x10 + region_num * 4;
>      }
>      pci_set_long(pci_dev->config + addr, type);
> -    pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
> -    pci_set_long(pci_dev->cmask + addr, 0xffffffff);
> +    if (pci_bar_is_mem64(r)) {
> +        pci_set_quad(pci_dev->wmask + addr, wmask);
> +        pci_set_quad(pci_dev->cmask + addr, ~0ULL);
> +    } else {
> +        pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
> +        pci_set_long(pci_dev->cmask + addr, 0xffffffff);
> +    }
>  }
>  
>  static void pci_update_mappings(PCIDevice *d)
> @@ -462,7 +474,11 @@ static void pci_update_mappings(PCIDevice *d)
>                  }
>              } else {
>                  if (cmd & PCI_COMMAND_MEMORY) {
> -                    new_addr = pci_get_long(d->config + config_ofs);
> +                    if (pci_bar_is_mem64(r)) {
> +                        new_addr = pci_get_quad(d->config + config_ofs);

>From previous patch, config_ofs is region_num * 4
This is incorrect for 64 bit regions.

> +                    } else {
> +                        new_addr = pci_get_long(d->config + config_ofs);
> +                    }
>                      /* the ROM slot has a specific enable bit */
>                      if (i == PCI_ROM_SLOT && !(new_addr & 1))
>                          goto no_mem_map;
> @@ -473,11 +489,24 @@ static void pci_update_mappings(PCIDevice *d)
>                         mappings, we handle specific values as invalid
>                         mappings. */
>                      if (last_addr <= new_addr || new_addr == 0 ||
> -                        last_addr == PCI_BAR_UNMAPPED ||
> +                        last_addr == PCI_BAR_UNMAPPED) {
> +                        new_addr = PCI_BAR_UNMAPPED;
> +                    }
>  
> -                        /* keep old behaviour
> -                         * without this, PC ide doesn't work well. */
> -                        last_addr >= UINT32_MAX) {
> +                    /*
> +                     * work around: without this, PC ide and other devices
> +                     * don't work well.
> +                     * OS writes all 1 bits to 32 BAR to find its size
> +                     * resulting in setting UINT32_MAX - alignemnt,
> +                     * and then OS sets the BAR to where they really want
> +                     * the BAR to sit.
> +                     * On the other hand, there are some important areas
> +                     * blow 4G on i386/x86_64. So setting BAR over those area
> +                     * below 4G causes troubles.
> +                     * We work around the issues by prohibitting BAR
> +                     * from sitting right blow 4G.
> +                     */
> +                    if (!pci_bar_is_mem64(r) && last_addr >= UINT32_MAX) {
>                          new_addr = PCI_BAR_UNMAPPED;
>                      }
>                  } else {
> @@ -736,7 +765,16 @@ static void pci_info_device(PCIDevice *d)
>                  monitor_printf(mon, "I/O at 0x%04"FMT_PCIBUS" [0x%04"FMT_PCIBUS"].\n",
>                                 r->addr, r->addr + r->size - 1);
>              } else {
> -                monitor_printf(mon, "32 bit memory at 0x%08"FMT_PCIBUS" [0x%08"FMT_PCIBUS"].\n",
> +                const char *type = pci_bar_is_mem64(r)? "64 bit": "32 bit";
> +                const char *prefetch = "";
> +
> +                if (r->type & PCI_ADDRESS_SPACE_MEM_PREFETCH) {
> +                    prefetch = " prefetchable";
> +                }
> +
> +                monitor_printf(mon, "%s%s memory at "
> +                               "0x%08"FMT_PCIBUS" [0x%08"FMT_PCIBUS"].\n",
> +                               type, prefetch,
>                                 r->addr, r->addr + r->size - 1);
>              }
>          }
> diff --git a/hw/pci.h b/hw/pci.h
> index cbf80c0..b65ce03 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -84,6 +84,8 @@ typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
>  
>  #define PCI_ADDRESS_SPACE_MEM		0x00
>  #define PCI_ADDRESS_SPACE_IO		0x01
> +#define PCI_ADDRESS_SPACE_MEM_TYPE_MASK 0x06
> +#define PCI_ADDRESS_SPACE_MEM_TYPE_64   0x04    /* 64 bit address */
>  #define PCI_ADDRESS_SPACE_MEM_PREFETCH	0x08
>  
>  typedef struct PCIIORegion {
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH v4 00/23] pci: various pci clean up and pci express support.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (23 preceding siblings ...)
  2009-10-05 10:14 ` [Qemu-devel] Re: [PATCH v4 00/23] pci: various pci clean up and pci express support Michael S. Tsirkin
@ 2009-10-05 13:34 ` Michael S. Tsirkin
  2009-10-07  2:30   ` Isaku Yamahata
  2009-10-06 14:40 ` Michael S. Tsirkin
  25 siblings, 1 reply; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 13:34 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

> Subject: Re: [PATCH v4 00/23] pci: various pci clean up

Could you please add version prefix to all patches?
As it is, once I'm deep in a thread, I don't really
know whether I'm looking at the latest patch version anymore.

-- 
MST

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

* [Qemu-devel] Re: [PATCH 10/23] pci: introduce FMT_PCIBUS for printf format for pcibus_t.
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 10/23] pci: introduce FMT_PCIBUS for printf format for pcibus_t Isaku Yamahata
@ 2009-10-05 13:41   ` Michael S. Tsirkin
  0 siblings, 0 replies; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 13:41 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 07:06:50PM +0900, Isaku Yamahata wrote:
> This patch is preliminary for 64bit BAR.
> Later pcibus_t will be changed from uint32_t to uint64_t.
> Introduce FMT_PCIBUS for printf format for pcibus_t.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/e1000.c        |    6 ++++--
>  hw/eepro100.c     |    6 ++++--
>  hw/pci.c          |   11 ++++++-----
>  hw/pci.h          |    1 +
>  hw/pcnet.c        |    5 +++--
>  hw/wdt_i6300esb.c |    3 ++-
>  6 files changed, 20 insertions(+), 12 deletions(-)
> 
> diff --git a/hw/e1000.c b/hw/e1000.c
> index c07eb42..8721e0e 100644
> --- a/hw/e1000.c
> +++ b/hw/e1000.c
> @@ -145,7 +145,8 @@ static void
>  ioport_map(PCIDevice *pci_dev, int region_num, pcibus_t addr,
>             pcibus_t size, int type)
>  {
> -    DBGOUT(IO, "e1000_ioport_map addr=0x%04x size=0x%08x\n", addr, size);
> +    DBGOUT(IO, "e1000_ioport_map addr=0x%04"FMT_PCIBUS" size=0x%08"FMT_PCIBUS"\n",

This line is now too long.

> +           addr, size);
>  }
>  
>  static void
> @@ -1040,7 +1041,8 @@ e1000_mmio_map(PCIDevice *pci_dev, int region_num,
>      };
>  
>  
> -    DBGOUT(MMIO, "e1000_mmio_map addr=0x%08x 0x%08x\n", addr, size);
> +    DBGOUT(MMIO, "e1000_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n",

same

> +           addr, size);
>  
>      cpu_register_physical_memory(addr, PNPMMIO_SIZE, d->mmio_index);
>      qemu_register_coalesced_mmio(addr, excluded_regs[0]);
> diff --git a/hw/eepro100.c b/hw/eepro100.c
> index 1a1a0da..52bfb1f 100644
> --- a/hw/eepro100.c
> +++ b/hw/eepro100.c
> @@ -1378,7 +1378,8 @@ static void pci_map(PCIDevice * pci_dev, int region_num,
>  {
>      EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
>  
> -    TRACE(OTHER, logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n",
> +    TRACE(OTHER, logout("region %d, addr=0x%08"FMT_PCIBUS", "
> +          "size=0x%08"FMT_PCIBUS", type=%d\n",
>            region_num, addr, size, type));
>  
>      assert(region_num == 1);
> @@ -1457,7 +1458,8 @@ static void pci_mmio_map(PCIDevice * pci_dev, int region_num,
>  {
>      EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
>  
> -    TRACE(OTHER, logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n",
> +    TRACE(OTHER, logout("region %d, addr=0x%08"FMT_PCIBUS", "
> +          "size=0x%08"FMT_PCIBUS", type=%d\n",
>            region_num, addr, size, type));
>  
>      if (region_num == 0) {
> diff --git a/hw/pci.c b/hw/pci.c
> index 674daba..8d6e8ea 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -408,7 +408,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
>  
>      if (size & (size-1)) {
>          fprintf(stderr, "ERROR: PCI region size must be pow2 "
> -                    "type=0x%x, size=0x%x\n", type, size);
> +                    "type=0x%x, size=0x%"FMT_PCIBUS"\n", type, size);
>          exit(1);
>      }
>  
> @@ -427,7 +427,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
>          addr = 0x10 + region_num * 4;
>      }
>      pci_set_long(pci_dev->config + addr, type);
> -    pci_set_long(pci_dev->wmask + addr, wmask);
> +    pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
>      pci_set_long(pci_dev->cmask + addr, 0xffffffff);
>  }
>  
> @@ -729,10 +729,10 @@ static void pci_info_device(PCIDevice *d)
>          if (r->size != 0) {
>              monitor_printf(mon, "      BAR%d: ", i);
>              if (r->type & PCI_ADDRESS_SPACE_IO) {
> -                monitor_printf(mon, "I/O at 0x%04x [0x%04x].\n",
> +                monitor_printf(mon, "I/O at 0x%04"FMT_PCIBUS" [0x%04"FMT_PCIBUS"].\n",
>                                 r->addr, r->addr + r->size - 1);
>              } else {
> -                monitor_printf(mon, "32 bit memory at 0x%08x [0x%08x].\n",
> +                monitor_printf(mon, "32 bit memory at 0x%08"FMT_PCIBUS" [0x%08"FMT_PCIBUS"].\n",

same

>                                 r->addr, r->addr + r->size - 1);
>              }
>          }
> @@ -1047,7 +1047,8 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
>          r = &d->io_regions[i];
>          if (!r->size)
>              continue;
> -        monitor_printf(mon, "%*sbar %d: %s at 0x%x [0x%x]\n", indent, "",
> +        monitor_printf(mon, "%*sbar %d: %s at 0x%"FMT_PCIBUS" [0x%"FMT_PCIBUS"]\n",

same

> +                       indent, "",
>                         i, r->type & PCI_ADDRESS_SPACE_IO ? "i/o" : "mem",
>                         r->addr, r->addr + r->size - 1);
>      }
> diff --git a/hw/pci.h b/hw/pci.h
> index 2796c1d..359fce1 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -72,6 +72,7 @@ extern target_phys_addr_t pci_mem_base;
>  #define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003
>  
>  typedef uint32_t pcibus_t;
> +#define FMT_PCIBUS                      PRIx32
>  
>  typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
>                                  uint32_t address, uint32_t data, int len);
> diff --git a/hw/pcnet.c b/hw/pcnet.c
> index 2789574..b4d85a5 100644
> --- a/hw/pcnet.c
> +++ b/hw/pcnet.c
> @@ -1766,7 +1766,8 @@ static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
>      PCNetState *d = &DO_UPCAST(PCIPCNetState, pci_dev, pci_dev)->state;
>  
>  #ifdef PCNET_DEBUG_IO
> -    printf("pcnet_ioport_map addr=0x%04x size=0x%04x\n", addr, size);
> +    printf("pcnet_ioport_map addr=0x%04"FMT_PCIBUS" size=0x%04"FMT_PCIBUS"\n",
> +           addr, size);
>  #endif
>  
>      register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
> @@ -1994,7 +1995,7 @@ static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
>      PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
>  
>  #ifdef PCNET_DEBUG_IO
> -    printf("pcnet_mmio_map addr=0x%08x 0x%08x\n", addr, size);
> +    printf("pcnet_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n", addr, size);

same

>  #endif
>  
>      cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->state.mmio_index);
> diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c
> index d3ab3c8..88450a8 100644
> --- a/hw/wdt_i6300esb.c
> +++ b/hw/wdt_i6300esb.c
> @@ -362,7 +362,8 @@ static void i6300esb_map(PCIDevice *dev, int region_num,
>      I6300State *d = DO_UPCAST(I6300State, dev, dev);
>      int io_mem;
>  
> -    i6300esb_debug("addr = %x, size = %x, type = %d\n", addr, size, type);
> +    i6300esb_debug("addr = %"FMT_PCIBUS", size = %"FMT_PCIBUS", type = %d\n",
> +                   addr, size, type);
>  
>      io_mem = cpu_register_io_memory(mem_read, mem_write, d);
>      cpu_register_physical_memory (addr, 0x10, io_mem);
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH 21/23] pci/brdige: qdevfy and initialize secondary bus and subordinate bus.
  2009-10-05 10:07 ` [Qemu-devel] [PATCH 21/23] pci/brdige: qdevfy and initialize secondary bus and subordinate bus Isaku Yamahata
@ 2009-10-05 13:49   ` Michael S. Tsirkin
  2009-10-05 14:58   ` Michael S. Tsirkin
  1 sibling, 0 replies; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 13:49 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 07:07:01PM +0900, Isaku Yamahata wrote:
> qdevfy pci bridge, and initialize secondary bus and subordinate bus
> in configuration space.

Why do you initialize these? Should not guest do this?

> And some clean up to use symbolic constant and to remove // comments.

You also apparently did some unrelated changes. Pls document.

> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.c |   85 +++++++++++++++++++++++++++++++++++++++++++-------------------
>  hw/pci.h |    9 ++++++
>  2 files changed, 68 insertions(+), 26 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index af864c6..fb93b99 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -174,6 +174,7 @@ static PCIBus *pci_register_secondary_bus(PCIBus *parent,
>      bus->sub_bus = dev->config[PCI_SUBORDINATE_BUS];
>      QLIST_INIT(&bus->child);
>      QLIST_INSERT_HEAD(&parent->child, bus, sibling);
> +    vmstate_register(-1, &vmstate_pcibus, bus);
>      return bus;
>  }
>  
> @@ -1140,7 +1141,7 @@ typedef struct {
>      PCIBus *bus;
>  } PCIBridge;
>  
> -static void pci_bridge_write_config(PCIDevice *d,
> +void pci_bridge_write_config(PCIDevice *d,
>                               uint32_t address, uint32_t val, int len)
>  {
>      PCIBridge *s = (PCIBridge *)d;
> @@ -1193,35 +1194,67 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function)
>      return bus->devices[PCI_DEVFN(slot, function)];
>  }
>  
> -PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
> -                        uint8_t sec_bus, uint8_t sub_bus,
> -                        pci_map_irq_fn map_irq, const char *name)
> +int pci_bridge_initfn(PCIDevice *pci_dev)
> +{
> +    uint8_t *pci_conf = pci_dev->config;

We don't need this variable IMO.

> +
> +    /* secondary bus, subordinate bus and vid/did will be set
> +       by pci_bridge_create_simple(), the caller of qdev_init() */
> +    pci_conf[PCI_COMMAND] = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
> +    pci_conf[PCI_STATUS] = PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK;

command and status are words, so it is better to use
pci_set_word here, even if specific values
happen to be in the 1'st byte.

> +    pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_PCI);
> +    pci_conf[PCI_LATENCY_TIMER] = 0x10;

Why 0x10?

> +    pci_conf[PCI_HEADER_TYPE] =
> +        PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE;

Any idea why it's multifunction?
Many (most?) bridges have a single function ...

> +    pci_conf[PCI_PRIMARY_BUS] = pci_dev->bus->bus_num;

I think this is 0 at reset, and assigned by BIOS.

> +    pci_conf[PCI_SEC_STATUS] = PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK;

pci_set_word.

> +
> +    return 0;
> +}
> +
> +#define PCI_BRIDGE_DEFAULT      "default PCI to PCI bridge"
> +static PCIDeviceInfo pci_bridge_info_default = {
> +    .qdev.name = PCI_BRIDGE_DEFAULT,
> +    .qdev.size = sizeof(PCIBridge),
> +    .config_write = pci_bridge_write_config,
> +    .init = pci_bridge_initfn,
> +    .pcie = 0,
> +};
> +
> +static void pci_bridge_register_device(void)
>  {
> -    PCIBridge *s;
> -    s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge),
> -                                         devfn, NULL, pci_bridge_write_config);
> -
> -    pci_config_set_vendor_id(s->dev.config, vid);
> -    pci_config_set_device_id(s->dev.config, did);
> -
> -    s->dev.config[0x04] = 0x06; // command = bus master, pci mem
> -    s->dev.config[0x05] = 0x00;
> -    s->dev.config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
> -    s->dev.config[0x07] = 0x00; // status = fast devsel
> -    s->dev.config[0x08] = 0x00; // revision
> -    s->dev.config[0x09] = 0x00; // programming i/f
> -    pci_config_set_class(s->dev.config, PCI_CLASS_BRIDGE_PCI);
> -    s->dev.config[0x0D] = 0x10; // latency_timer
> -    s->dev.config[PCI_HEADER_TYPE] =
> -        PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE; // header_type
> -    s->dev.config[0x1E] = 0xa0; // secondary status
> +    pci_qdev_register(&pci_bridge_info_default);
> +}
> +device_init(pci_bridge_register_device);
> +
> +PCIBus *pci_bridge_create_simple(PCIBus *bus, int devfn,
> +                                 uint16_t vid, uint16_t did,
> +                                 uint8_t sec_bus, uint8_t sub_bus,
> +                                 pci_map_irq_fn map_irq, const char *bus_name,
> +                                 const char *name)
> +{
> +    PCIDevice *d;
> +    PCIBridge *br;
> +
> +    d = pci_create_simple(bus, devfn, name);
>  
> +    pci_config_set_vendor_id(d->config, vid);
> +    pci_config_set_device_id(d->config, did);
>      assert(sec_bus <= sub_bus);
> -    s->dev.config[PCI_SECONDARY_BUS] = sec_bus;
> -    s->dev.config[PCI_SUBORDINATE_BUS] = sub_bus;
> +    d->config[PCI_SECONDARY_BUS] = sec_bus;
> +    d->config[PCI_SUBORDINATE_BUS] = sub_bus;
>  
> -    s->bus = pci_register_secondary_bus(bus, &s->dev, map_irq, name);
> -    return s->bus;
> +    br = DO_UPCAST(PCIBridge, dev, d);
> +    br->bus = pci_register_secondary_bus(bus, d, map_irq, name);
> +    return br->bus;
> +}
> +
> +PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid,
> +                        uint16_t did, uint8_t sec_bus, uint8_t sub_bus,
> +                        pci_map_irq_fn map_irq, const char *name)
> +{
> +    return pci_bridge_create_simple(bus, devfn, vid, did, sec_bus, sub_bus,
> +                                    map_irq, name, PCI_BRIDGE_DEFAULT);
>  }
>  
>  static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
> diff --git a/hw/pci.h b/hw/pci.h
> index 1d45437..5cf0b59 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -294,6 +294,15 @@ void pci_info(Monitor *mon);
>  PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
>                          uint8_t sec_bus, uint8_t sub_bus,
>                          pci_map_irq_fn map_irq, const char *name);
> +PCIBus *pci_bridge_create_simple(PCIBus *bus, int devfn,
> +                                 uint16_t vid, uint16_t did,
> +                                 uint8_t sec_bus, uint8_t sub_bus,
> +                                 pci_map_irq_fn map_irq, const char *bus_name,
> +                                 const char *name);
> +void pci_bridge_write_config(PCIDevice *d,
> +                             uint32_t address, uint32_t val, int len);
> +int pci_bridge_initfn(PCIDevice *pci_dev);
> +void pci_bridge_set_map_irq(PCIBus *bus, pci_map_irq_fn map_irq);
>  
>  static inline void
>  pci_set_byte(uint8_t *config, uint8_t val)
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH 22/23] pci: initialize wmask according to pci header type.
  2009-10-05 10:07 ` [Qemu-devel] [PATCH 22/23] pci: initialize wmask according to pci header type Isaku Yamahata
@ 2009-10-05 14:09   ` Michael S. Tsirkin
  0 siblings, 0 replies; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 14:09 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 07:07:02PM +0900, Isaku Yamahata wrote:
> - initialize wmask according to pci header type.
>   So far, header of type 01  was not correctly initialized.

I think it was correct. Which register has incorrect value?

It works because BAR for regular device is at the same location as
base/limit for bridge.  value at which offset was wrong.  Since no one
uses bridges and everyone uses regular devices, there's value in using
common code. So let's just add a comment explaing why code works, and be
done with it.

> - only sets default subsystem id for header type 00.
>   header type 01 doesn't have subsystem id, and uses the register
>   for other purpose. So setting default subsystem id doesn't make sense.

But then it's easier to reuse regular device code and override the value
to 0 in bridge after the fact than fork a ton of code.

> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/cirrus_vga.c |    2 +-
>  hw/pci.c        |   98 +++++++++++++++++++++++++++++++++++++++++++++++++-----
>  hw/pci.h        |   36 ++++++++++++++++++++
>  3 files changed, 126 insertions(+), 10 deletions(-)
> 
> diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
> index 2a6aba8..55ef4c1 100644
> --- a/hw/cirrus_vga.c
> +++ b/hw/cirrus_vga.c
> @@ -180,7 +180,7 @@
>  #define PCI_COMMAND_PALETTESNOOPING         0x0020
>  #define PCI_COMMAND_PARITYDETECTION         0x0040
>  #define PCI_COMMAND_ADDRESSDATASTEPPING     0x0080
> -#define PCI_COMMAND_SERR                    0x0100
> +// #define PCI_COMMAND_SERR                    0x0100 /* duplicated */

so remove it?

>  #define PCI_COMMAND_BACKTOBACKTRANS         0x0200
>  // PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev)
>  #define PCI_CLASS_BASE_DISPLAY        0x03
> diff --git a/hw/pci.c b/hw/pci.c
> index fb93b99..2694e83 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -381,16 +381,32 @@ static void pci_init_cmask(PCIDevice *dev)
>      dev->cmask[PCI_CAPABILITY_LIST] = 0xff;
>  }
>  
> -static void pci_init_wmask(PCIDevice *dev)
> +static void pci_conf_init_type00(PCIDevice *dev)

I think it was a good idea to split wmask init from conf init. Small
functions doing one thing and doing it well. Let's not merge them.

>  {
>      int i;
>      uint32_t config_size = pcie_config_size(dev);
>  
> +    pci_set_default_subsystem_id(dev);
> +
> +    pci_set_word(&dev->wmask[PCI_COMMAND],

dev->wmask + COMMAND

> +                 PCI_COMMAND_IO |
> +                 PCI_COMMAND_MEMORY |
> +                 PCI_COMMAND_MASTER |
> +                 PCI_COMMAND_SPECIAL |
> +                 PCI_COMMAND_INVALIDATE |
> +                 PCI_COMMAND_VGA_PALETTE |
> +                 PCI_COMMAND_PARITY |
> +                 PCI_COMMAND_WAIT |
> +                 PCI_COMMAND_SERR |
> +                 PCI_COMMAND_FAST_BACK |
> +                 PCI_COMMAND_INTX_DISABLE);
> +
>      dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
> +    dev->wmask[PCI_LATENCY_TIMER] = 0xff;
>      dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
> -    dev->wmask[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY
> -                              | PCI_COMMAND_MASTER;
> -    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
> +
> +    /* device dependent part */
> +    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; i++)
>          dev->wmask[i] = 0xff;
>  }
>  
> @@ -410,10 +426,12 @@ static void pci_config_alloc(PCIDevice *pci_dev)
>  }
>  
>  /* -1 for devfn means auto assign */
> +typedef void (*pci_conf_init_t)(PCIDevice *d);
>  static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
>                                           const char *name, int devfn,
>                                           PCIConfigReadFunc *config_read,
> -                                         PCIConfigWriteFunc *config_write)
> +                                         PCIConfigWriteFunc *config_write,
> +                                         pci_conf_init_t conf_init)
>  {
>      if (devfn < 0) {
>          for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) {
> @@ -430,9 +448,8 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
>      pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
>      memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
>      pci_config_alloc(pci_dev);
> -    pci_set_default_subsystem_id(pci_dev);
>      pci_init_cmask(pci_dev);
> -    pci_init_wmask(pci_dev);
> +    conf_init(pci_dev);

Oh no, not another callback.
Let users just customize it *after* device is registered.

>  
>      if (!config_read)
>          config_read = pci_default_read_config;
> @@ -455,9 +472,11 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
>  
>      pci_dev = qemu_mallocz(instance_size);
>      pci_dev = do_pci_register_device(pci_dev, bus, name, devfn,
> -                                     config_read, config_write);
> +                                     config_read, config_write,
> +                                     pci_conf_init_type00);
>      return pci_dev;
>  }
> +
>  static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
>  {
>      return addr + pci_mem_base;
> @@ -1194,6 +1213,59 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function)
>      return bus->devices[PCI_DEVFN(slot, function)];
>  }
>  
> +static void pci_conf_init_type01(PCIDevice *d)
> +{
> +    uint32_t addr;
> +    uint32_t config_size = pcie_config_size(d);
> +
> +    pci_set_word(&d->wmask[PCI_COMMAND],
> +                 PCI_COMMAND_IO |
> +                 PCI_COMMAND_MEMORY |
> +                 PCI_COMMAND_MASTER |
> +                 PCI_COMMAND_SPECIAL |
> +                 PCI_COMMAND_INVALIDATE |
> +                 PCI_COMMAND_VGA_PALETTE |
> +                 PCI_COMMAND_PARITY |
> +                 PCI_COMMAND_WAIT |
> +                 PCI_COMMAND_SERR |
> +                 PCI_COMMAND_FAST_BACK |
> +                 PCI_COMMAND_INTX_DISABLE);
> +
> +    d->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
> +    d->wmask[PCI_LATENCY_TIMER] = 0xff;
> +
> +    d->wmask[PCI_PRIMARY_BUS] = 0xff;
> +    d->wmask[PCI_SECONDARY_BUS] = 0xff;
> +    d->wmask[PCI_SUBORDINATE_BUS] = 0xff;
> +    d->wmask[PCI_SEC_LATENCY_TIMER] = 0xff;
> +    d->wmask[PCI_IO_BASE] = PCI_IO_RANGE_MASK & 0xff;
> +    d->wmask[PCI_IO_LIMIT] = PCI_IO_RANGE_MASK & 0xff;
> +
> +    /* sec status isn't emulated (yet) */
> +    d->wmask[PCI_SEC_STATUS] = 0;
> +
> +    pci_set_word(&d->wmask[PCI_MEMORY_BASE], PCI_MEMORY_RANGE_MASK & 0xffff);

d->wmask + PCI_MEMORY_BASE, same elsewhere.
Especially because you don't address a single byte with pci_set_word,
so you really pass it pointer into array, not pointer to specific field
which just happens to be inside array.

> +    pci_set_word(&d->wmask[PCI_MEMORY_LIMIT], PCI_MEMORY_RANGE_MASK & 0xffff);
> +    pci_set_word(&d->wmask[PCI_PREF_MEMORY_BASE], PCI_PREF_RANGE_MASK & 0xffff);
> +    pci_set_word(&d->wmask[PCI_PREF_MEMORY_LIMIT], PCI_PREF_RANGE_MASK & 0xffff);
> +    pci_set_long(&d->wmask[PCI_PREF_BASE_UPPER32], 0xffffffff);
> +    pci_set_long(&d->wmask[PCI_PREF_LIMIT_UPPER32], 0xffffffff);


This is a lot of code, but the result is that a ton of registers
are filled with all ones. Let's just memset a range to 0xff.
When you do it this way, you will see that code is basically
identical to regular devices.

> +
> +    d->wmask[PCI_INTERRUPT_LINE] = 0xff;
> +    pci_set_word(&d->wmask[PCI_BRIDGE_CONTROL], 0xffff);
> +
> +    /* device dependent part */
> +    for (addr = PCI_CONFIG_HEADER_SIZE; addr < config_size; addr++)
> +        d->wmask[addr] = 0xff;
> +}
> +
> +static void pci_conf_init_type02(PCIDevice *d)
> +{
> +    fprintf(stderr,
> +            "ERROR: pci header type 02(CARDBUS) isn't supported yet.\n");
> +    abort();
> +}
> +

so why write it? type 0x3 isn't supported either.

>  int pci_bridge_initfn(PCIDevice *pci_dev)
>  {
>      uint8_t *pci_conf = pci_dev->config;
> @@ -1263,11 +1335,19 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
>      PCIDeviceInfo *info = container_of(base, PCIDeviceInfo, qdev);
>      PCIBus *bus;
>      int devfn;
> +    const pci_conf_init_t conf_init[] = {
> +        pci_conf_init_type00,
> +        pci_conf_init_type01,
> +        pci_conf_init_type02,
> +    };
>  
>      bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
>      devfn = pci_dev->devfn;
> +    assert(0 <= info->header_type);

so make it unsigned?

> +    assert(info->header_type <= ARRAY_SIZE(conf_init));
>      pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn,
> -                                     info->config_read, info->config_write);
> +                                     info->config_read, info->config_write,
> +                                     conf_init[info->header_type]);

Overdoing table-driven here. Simple switch would catch
errors faster, e.g. with default: value.

>      assert(pci_dev);
>      return info->init(pci_dev);
>  }
> diff --git a/hw/pci.h b/hw/pci.h
> index 5cf0b59..aadd1a5 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -106,6 +106,14 @@ typedef struct PCIIORegion {
>  #define  PCI_COMMAND_IO		0x1	/* Enable response in I/O space */
>  #define  PCI_COMMAND_MEMORY	0x2	/* Enable response in Memory space */
>  #define  PCI_COMMAND_MASTER	0x4	/* Enable bus master */
> +#define  PCI_COMMAND_SPECIAL	0x8	/* Enable response to special cycles */
> +#define  PCI_COMMAND_INVALIDATE 0x10	/* Use memory write and invalidate */
> +#define  PCI_COMMAND_VGA_PALETTE 0x20	/* Enable palette snooping */
> +#define  PCI_COMMAND_PARITY	0x40	/* Enable parity checking */
> +#define  PCI_COMMAND_WAIT	0x80	/* Enable address/data stepping */
> +#define  PCI_COMMAND_SERR	0x100	/* Enable SERR */
> +#define  PCI_COMMAND_FAST_BACK	0x200	/* Enable back-to-back writes */
> +#define  PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
>  #define PCI_STATUS              0x06    /* 16 bits */
>  #define PCI_REVISION_ID         0x08    /* 8 bits  */
>  #define PCI_CLASS_PROG		0x09	/* Reg. Level Programming Interface */
> @@ -164,7 +172,32 @@ typedef struct PCIIORegion {
>  
>  /* Header type 1 (PCI-to-PCI bridges) */
>  #define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
> +#define PCI_SEC_LATENCY_TIMER   0x1b    /* Latency timer for secondary interface */
> +#define PCI_IO_BASE             0x1c    /* I/O range behind the bridge */
> +#define PCI_IO_LIMIT            0x1d
> +#define  PCI_IO_RANGE_TYPE_MASK 0x0fUL  /* I/O bridging type */
> +#define  PCI_IO_RANGE_TYPE_16   0x00
> +#define  PCI_IO_RANGE_TYPE_32   0x01
> +#define  PCI_IO_RANGE_MASK      (~0x0fUL)
> +#define PCI_MEMORY_BASE         0x20    /* Memory range behind */
> +#define PCI_MEMORY_LIMIT        0x22
> +#define  PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL
> +#define  PCI_MEMORY_RANGE_MASK  (~0x0fUL)
> +#define PCI_PREF_MEMORY_BASE    0x24    /* Prefetchable memory range behind */
> +#define PCI_PREF_MEMORY_LIMIT   0x26
> +#define  PCI_PREF_RANGE_TYPE_MASK 0x0fUL
> +#define  PCI_PREF_RANGE_TYPE_32 0x00
> +#define  PCI_PREF_RANGE_TYPE_64 0x01
> +#define  PCI_PREF_RANGE_MASK    (~0x0fUL)
> +#define PCI_PREF_BASE_UPPER32   0x28    /* Upper half of prefetchable memory range */
> +#define PCI_PREF_LIMIT_UPPER32  0x2c
> +#define PCI_IO_BASE_UPPER16     0x30    /* Upper half of I/O addresses */
> +#define PCI_IO_LIMIT_UPPER16    0x32
> +/* 0x34 same as for htype 0 */
> +/* 0x35-0x3b is reserved */
>  #define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
> +/* 0x3c-0x3d are same as for htype 0 */
> +#define PCI_BRIDGE_CONTROL      0x3e

There's a ton of registers here we do not really need, since you can
initialize a range to 0xff without looking at what is in the range.  And
frankly I prefer it this way rather than spend time checking each value.

>  /* Size of the standard PCI config header */
>  #define PCI_CONFIG_HEADER_SIZE 0x40
> @@ -377,6 +410,9 @@ typedef struct {
>      PCIConfigReadFunc *config_read;
>      PCIConfigWriteFunc *config_write;
>  
> +    /* pci config header type */
> +    uint8_t header_type;
> +

We don't need this in PCIDeviceInfo, this is part of
config space already.

>      /* pcie stuff */
>      int pcie;
>  } PCIDeviceInfo;
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH 23/23] pci/monitor: print out bridge's filtering values and so on.
  2009-10-05 10:07 ` [Qemu-devel] [PATCH 23/23] pci/monitor: print out bridge's filtering values and so on Isaku Yamahata
@ 2009-10-05 14:24   ` Michael S. Tsirkin
  0 siblings, 0 replies; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 14:24 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 07:07:03PM +0900, Isaku Yamahata wrote:
> make pci_info_device() print out bridge's filtering value like
> io base/limit, subbus and subordinate bus.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.c |   39 +++++++++++++++++++++++++++++++++++++++
>  1 files changed, 39 insertions(+), 0 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 2694e83..570531c 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -1032,7 +1032,46 @@ static void pci_info_device(PCIBus *bus, PCIDevice *d)
>                         d->config[PCI_INTERRUPT_LINE]);
>      }
>      if (class == 0x0604) {
> +        uint64_t base;
> +        uint64_t limit;
> +
>          monitor_printf(mon, "      BUS %d.\n", d->config[0x19]);
> +        monitor_printf(mon, "      secondary bus %d.\n",
> +                       d->config[PCI_SECONDARY_BUS]);
> +        monitor_printf(mon, "      subordinate bus %d.\n",
> +                       d->config[PCI_SUBORDINATE_BUS]);
> +
> +        base =
> +            ((uint32_t)d->config[PCI_IO_BASE] & ~PCI_IO_RANGE_TYPE_MASK) << 8;
> +        limit =
> +            ((uint32_t)d->config[PCI_IO_LIMIT] & ~PCI_IO_RANGE_TYPE_MASK) << 8;
> +        if (d->config[PCI_IO_BASE] & PCI_IO_RANGE_TYPE_32) {
> +            base |= pci_get_word(d->config + PCI_IO_BASE_UPPER16) << 16;

pci_get_word returns a 16 bit integer. Isn't shifting it
by 16 bit wrong?

> +            limit |= pci_get_word(d->config + PCI_IO_LIMIT_UPPER16) << 16;
> +        }
> +        limit |= 0xfff;
> +        monitor_printf(mon, "      IO range [0x%04"PRIx64", 0x%04"PRIx64"]\n",
> +                       base, limit);
> +
> +        base = (pci_get_word(d->config + PCI_MEMORY_BASE) &
> +                PCI_MEMORY_RANGE_MASK) << 16;
> +        limit = (pci_get_word(d->config + PCI_MEMORY_LIMIT) &
> +                 PCI_MEMORY_RANGE_MASK) << 16;
> +        limit |= 0xfffff;
> +        monitor_printf(mon,
> +                       "      memory range [0x%08"PRIx64", 0x%08"PRIx64"]\n",
> +                       base, limit);
> +        base = ((uint64_t)pci_get_word(d->config + PCI_PREF_MEMORY_BASE) &
> +                PCI_PREF_RANGE_MASK) << 16;
> +        limit = ((uint64_t)pci_get_word(d->config + PCI_PREF_MEMORY_LIMIT) &
> +                 PCI_PREF_RANGE_MASK) << 16;
> +        base |=
> +            (uint64_t)pci_get_long(d->config + PCI_PREF_BASE_UPPER32) << 32;
> +        limit |=
> +            (uint64_t)pci_get_long(d->config + PCI_PREF_LIMIT_UPPER32) << 32;
> +        limit |= 0xfffff;
> +        monitor_printf(mon, "      prefetchable memory range "
> +                       "[0x%08"PRIx64", 0x%08"PRIx64"]\n", base, limit);

Here, for once, is a chance to add a helper routine to good effect :)

>      }
>      for(i = 0;i < PCI_NUM_REGIONS; i++) {
>          r = &d->io_regions[i];
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH 15/23] pci_host.h: split non-inline static function in pci_host.h into pci_host.c
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 15/23] pci_host.h: split non-inline static function in pci_host.h into pci_host.c Isaku Yamahata
@ 2009-10-05 14:35   ` Michael S. Tsirkin
  2009-10-05 14:37     ` Michael S. Tsirkin
  0 siblings, 1 reply; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 14:35 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 07:06:55PM +0900, Isaku Yamahata wrote:
> Later a structures declared in pci_host.h, PCIHostState, will be used.
> However pci_host.h doesn't allow to include itself easily. This patches
> addresses it.
> 
> pci_host.h includes non-inline static functions which are instantiated
> in .c by including pci_host.h. That prevents from including pci_host.h
> to use PCIHostState.
> So split pci_host.h non-inline static functions into pci_host.c.
> Its purpose to include is to instantiate io function for mmio or ioio.
> To avoid including code, we always instantiate both version.

This is even worse than what we had, file including itself, oh my.
All I suggested was either
- get rid of macro hackery in some sane way
- make all function static inline

> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  Makefile.target               |    8 ++--
>  hw/apb_pci.c                  |   21 ++-------
>  hw/grackle_pci.c              |   24 ++--------
>  hw/gt64xxx.c                  |   11 +----
>  hw/{pci_host.h => pci_host.c} |   61 +++++++++++++++++++++-----
>  hw/pci_host.h                 |   96 ++++++-----------------------------------
>  hw/piix_pci.c                 |   16 +++----
>  hw/ppc4xx_pci.c               |   18 +-------
>  hw/ppce500_pci.c              |   17 +------
>  hw/prep_pci.c                 |   14 +++---
>  hw/unin_pci.c                 |   47 +++++---------------
>  11 files changed, 105 insertions(+), 228 deletions(-)
>  copy hw/{pci_host.h => pci_host.c} (69%)
> 
> diff --git a/Makefile.target b/Makefile.target
> index 1f4518c..2da39b7 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -186,11 +186,11 @@ obj-i386-y += fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
>  obj-i386-y += cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
>  obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
>  obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
> -obj-i386-y += ne2000-isa.o
> +obj-i386-y += ne2000-isa.o pci_host.o
>  
>  # shared objects
>  obj-ppc-y = ppc.o ide/core.o ide/qdev.o ide/isa.o ide/pci.o ide/macio.o
> -obj-ppc-y += vga.o vga-pci.o $(sound-obj-y) dma.o openpic.o
> +obj-ppc-y += vga.o vga-pci.o $(sound-obj-y) dma.o openpic.o pci_host.o
>  # PREP target
>  obj-ppc-y += pckbd.o serial.o i8259.o i8254.o fdc.o mc146818rtc.o
>  obj-ppc-y += prep_pci.o ppc_prep.o ne2000-isa.o
> @@ -217,7 +217,7 @@ obj-mips-y += gt64xxx.o pckbd.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o
>  obj-mips-y += piix4.o parallel.o cirrus_vga.o pcspk.o $(sound-obj-y)
>  obj-mips-y += mipsnet.o ne2000-isa.o
>  obj-mips-y += pflash_cfi01.o
> -obj-mips-y += vmware_vga.o
> +obj-mips-y += vmware_vga.o pci_host.o
>  
>  obj-microblaze-y = petalogix_s3adsp1800_mmu.o
>  
> @@ -244,7 +244,7 @@ obj-cris-y += etraxfs_ser.o
>  obj-cris-y += pflash_cfi02.o
>  
>  ifeq ($(TARGET_ARCH), sparc64)
> -obj-sparc-y = sun4u.o pckbd.o apb_pci.o
> +obj-sparc-y = sun4u.o pckbd.o apb_pci.o pci_host.o
>  obj-sparc-y += ide/core.o ide/qdev.o ide/pci.o
>  obj-sparc-y += vga.o vga-pci.o
>  obj-sparc-y += fdc.o mc146818rtc.o serial.o
> diff --git a/hw/apb_pci.c b/hw/apb_pci.c
> index 381b924..89413b1 100644
> --- a/hw/apb_pci.c
> +++ b/hw/apb_pci.c
> @@ -28,6 +28,7 @@
>  
>  #include "sysbus.h"
>  #include "pci.h"
> +#include "pci_host.h"
>  
>  /* debug APB */
>  //#define DEBUG_APB
> @@ -39,9 +40,6 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
>  #define APB_DPRINTF(fmt, ...)
>  #endif
>  
> -typedef target_phys_addr_t pci_addr_t;
> -#include "pci_host.h"
> -
>  typedef struct APBState {
>      SysBusDevice busdev;
>      PCIHostState host_state;
> @@ -136,18 +134,6 @@ static CPUReadMemoryFunc * const apb_config_read[] = {
>      &apb_config_readl,
>  };
>  
> -static CPUWriteMemoryFunc * const pci_apb_write[] = {
> -    &pci_host_data_writeb,
> -    &pci_host_data_writew,
> -    &pci_host_data_writel,
> -};
> -
> -static CPUReadMemoryFunc * const pci_apb_read[] = {
> -    &pci_host_data_readb,
> -    &pci_host_data_readw,
> -    &pci_host_data_readl,
> -};
> -
>  static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
>                                    uint32_t val)
>  {
> @@ -284,8 +270,9 @@ static int pci_pbm_init_device(SysBusDevice *dev)
>                                              pci_apb_config_write, s);
>      sysbus_init_mmio(dev, 0x10ULL, pci_mem_config);
>      /* mem_data */
> -    pci_mem_data = cpu_register_io_memory(pci_apb_read,
> -                                          pci_apb_write, &s->host_state);
> +    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
> +                                          pci_host_data_write_mmio,
> +                                          &s->host_state);
>      sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data);
>      return 0;
>  }
> diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
> index d878cf6..d29175b 100644
> --- a/hw/grackle_pci.c
> +++ b/hw/grackle_pci.c
> @@ -26,6 +26,7 @@
>  #include "sysbus.h"
>  #include "ppc_mac.h"
>  #include "pci.h"
> +#include "pci_host.h"
>  
>  /* debug Grackle */
>  //#define DEBUG_GRACKLE
> @@ -37,9 +38,6 @@
>  #define GRACKLE_DPRINTF(fmt, ...)
>  #endif
>  
> -typedef target_phys_addr_t pci_addr_t;
> -#include "pci_host.h"
> -
>  typedef struct GrackleState {
>      SysBusDevice busdev;
>      PCIHostState host_state;
> @@ -84,18 +82,6 @@ static CPUReadMemoryFunc * const pci_grackle_config_read[] = {
>      &pci_grackle_config_readl,
>  };
>  
> -static CPUWriteMemoryFunc * const pci_grackle_write[] = {
> -    &pci_host_data_writeb,
> -    &pci_host_data_writew,
> -    &pci_host_data_writel,
> -};
> -
> -static CPUReadMemoryFunc * const pci_grackle_read[] = {
> -    &pci_host_data_readb,
> -    &pci_host_data_readw,
> -    &pci_host_data_readl,
> -};
> -
>  /* Don't know if this matches real hardware, but it agrees with OHW.  */
>  static int pci_grackle_map_irq(PCIDevice *pci_dev, int irq_num)
>  {
> @@ -163,8 +149,8 @@ static int pci_grackle_init_device(SysBusDevice *dev)
>  
>      pci_mem_config = cpu_register_io_memory(pci_grackle_config_read,
>                                              pci_grackle_config_write, s);
> -    pci_mem_data = cpu_register_io_memory(pci_grackle_read,
> -                                          pci_grackle_write,
> +    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
> +                                          pci_host_data_write_mmio,
>                                            &s->host_state);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> @@ -185,8 +171,8 @@ static int pci_dec_21154_init_device(SysBusDevice *dev)
>  
>      pci_mem_config = cpu_register_io_memory(pci_grackle_config_read,
>                                              pci_grackle_config_write, s);
> -    pci_mem_data = cpu_register_io_memory(pci_grackle_read,
> -                                          pci_grackle_write,
> +    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
> +                                          pci_host_data_write_mmio,
>                                            &s->host_state);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
> index 8f9ae4a..fb7f5bd 100644
> --- a/hw/gt64xxx.c
> +++ b/hw/gt64xxx.c
> @@ -25,10 +25,8 @@
>  #include "hw.h"
>  #include "mips.h"
>  #include "pci.h"
> -#include "pc.h"
> -
> -typedef target_phys_addr_t pci_addr_t;
>  #include "pci_host.h"
> +#include "pc.h"
>  
>  //#define DEBUG
>  
> @@ -1119,13 +1117,6 @@ PCIBus *pci_gt64120_init(qemu_irq *pic)
>      GT64120State *s;
>      PCIDevice *d;
>  
> -    (void)&pci_host_data_writeb; /* avoid warning */
> -    (void)&pci_host_data_writew; /* avoid warning */
> -    (void)&pci_host_data_writel; /* avoid warning */
> -    (void)&pci_host_data_readb; /* avoid warning */
> -    (void)&pci_host_data_readw; /* avoid warning */
> -    (void)&pci_host_data_readl; /* avoid warning */
> -
>      s = qemu_mallocz(sizeof(GT64120State));
>      s->pci = qemu_mallocz(sizeof(GT64120PCIState));
>  
> diff --git a/hw/pci_host.h b/hw/pci_host.c
> similarity index 69%
> copy from hw/pci_host.h
> copy to hw/pci_host.c
> index 48862b5..5c06f03 100644
> --- a/hw/pci_host.h
> +++ b/hw/pci_host.c
> @@ -25,10 +25,13 @@
>  /* Worker routines for a PCI host controller that uses an {address,data}
>     register pair to access PCI configuration space.  */
>  
> +#ifndef PCI_HOST_C
> +
>  /* debug PCI */
>  //#define DEBUG_PCI
>  
> -#include "sysbus.h"
> +#include "pci.h"
> +#include "pci_host.h"
>  
>  #ifdef DEBUG_PCI
>  #define PCI_DPRINTF(fmt, ...) \
> @@ -37,13 +40,40 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
>  #define PCI_DPRINTF(fmt, ...)
>  #endif
>  
> -typedef struct {
> -    SysBusDevice busdev;
> -    uint32_t config_reg;
> -    PCIBus *bus;
> -} PCIHostState;
> +#define PCI_HOST_C
> +
> +#define PCI_ADDR_T      target_phys_addr_t
> +#define PCI_HOST_SUFFIX _mmio
> +#define PCI_HOST_STATIC static
> +
> +#include "pci_host.c"
> +
> +CPUWriteMemoryFunc * const pci_host_data_write_mmio[] = {
> +    &glue(pci_host_data_writeb, PCI_HOST_SUFFIX),
> +    &glue(pci_host_data_writew, PCI_HOST_SUFFIX),
> +    &glue(pci_host_data_writel, PCI_HOST_SUFFIX),
> +};
> +
> +CPUReadMemoryFunc * const pci_host_data_read_mmio[] = {
> +    &glue(pci_host_data_readb, PCI_HOST_SUFFIX),
> +    &glue(pci_host_data_readw, PCI_HOST_SUFFIX),
> +    &glue(pci_host_data_readl, PCI_HOST_SUFFIX),
> +};
> +
> +#undef PCI_ADDR_T
> +#undef PCI_HOST_SUFFIX
> +#undef PCI_HOST_STATIC
>  
> -static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
> +#define PCI_ADDR_T      uint32_t
> +#define PCI_HOST_SUFFIX _ioport
> +#define PCI_HOST_STATIC /* nothing. export this function */
> +
> +#include "pci_host.c"
> +
> +#else
> +
> +PCI_HOST_STATIC void glue(pci_host_data_writeb, PCI_HOST_SUFFIX)(
> +    void* opaque, PCI_ADDR_T addr, uint32_t val)
>  {
>      PCIHostState *s = opaque;
>  
> @@ -53,7 +83,8 @@ static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
>          pci_data_write(s->bus, s->config_reg | (addr & 3), val, 1);
>  }
>  
> -static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val)
> +PCI_HOST_STATIC void glue(pci_host_data_writew, PCI_HOST_SUFFIX)(
> +    void* opaque, PCI_ADDR_T addr, uint32_t val)
>  {
>      PCIHostState *s = opaque;
>  #ifdef TARGET_WORDS_BIGENDIAN
> @@ -65,7 +96,8 @@ static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val)
>          pci_data_write(s->bus, s->config_reg | (addr & 3), val, 2);
>  }
>  
> -static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
> +PCI_HOST_STATIC void glue(pci_host_data_writel, PCI_HOST_SUFFIX)(
> +    void* opaque, PCI_ADDR_T addr, uint32_t val)
>  {
>      PCIHostState *s = opaque;
>  #ifdef TARGET_WORDS_BIGENDIAN
> @@ -77,7 +109,8 @@ static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
>          pci_data_write(s->bus, s->config_reg, val, 4);
>  }
>  
> -static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr)
> +PCI_HOST_STATIC uint32_t glue(pci_host_data_readb, PCI_HOST_SUFFIX)(
> +    void* opaque, PCI_ADDR_T addr)
>  {
>      PCIHostState *s = opaque;
>      uint32_t val;
> @@ -90,7 +123,8 @@ static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr)
>      return val;
>  }
>  
> -static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
> +PCI_HOST_STATIC uint32_t glue(pci_host_data_readw, PCI_HOST_SUFFIX)(
> +    void* opaque, PCI_ADDR_T addr)
>  {
>      PCIHostState *s = opaque;
>      uint32_t val;
> @@ -105,7 +139,8 @@ static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
>      return val;
>  }
>  
> -static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr)
> +PCI_HOST_STATIC uint32_t glue(pci_host_data_readl, PCI_HOST_SUFFIX)(
> +    void* opaque, PCI_ADDR_T addr)
>  {
>      PCIHostState *s = opaque;
>      uint32_t val;
> @@ -119,3 +154,5 @@ static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr)
>  #endif
>      return val;
>  }
> +
> +#endif
> diff --git a/hw/pci_host.h b/hw/pci_host.h
> index 48862b5..ea98ed2 100644
> --- a/hw/pci_host.h
> +++ b/hw/pci_host.h
> @@ -25,97 +25,27 @@
>  /* Worker routines for a PCI host controller that uses an {address,data}
>     register pair to access PCI configuration space.  */
>  
> -/* debug PCI */
> -//#define DEBUG_PCI
> +#ifndef PCI_HOST_H
> +#define PCI_HOST_H
>  
>  #include "sysbus.h"
>  
> -#ifdef DEBUG_PCI
> -#define PCI_DPRINTF(fmt, ...) \
> -do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
> -#else
> -#define PCI_DPRINTF(fmt, ...)
> -#endif
> -
>  typedef struct {
>      SysBusDevice busdev;
>      uint32_t config_reg;
>      PCIBus *bus;
>  } PCIHostState;
>  
> -static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
> -{
> -    PCIHostState *s = opaque;
> -
> -    PCI_DPRINTF("writeb addr " TARGET_FMT_plx " val %x\n",
> -                (target_phys_addr_t)addr, val);
> -    if (s->config_reg & (1u << 31))
> -        pci_data_write(s->bus, s->config_reg | (addr & 3), val, 1);
> -}
> -
> -static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val)
> -{
> -    PCIHostState *s = opaque;
> -#ifdef TARGET_WORDS_BIGENDIAN
> -    val = bswap16(val);
> -#endif
> -    PCI_DPRINTF("writew addr " TARGET_FMT_plx " val %x\n",
> -                (target_phys_addr_t)addr, val);
> -    if (s->config_reg & (1u << 31))
> -        pci_data_write(s->bus, s->config_reg | (addr & 3), val, 2);
> -}
> -
> -static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
> -{
> -    PCIHostState *s = opaque;
> -#ifdef TARGET_WORDS_BIGENDIAN
> -    val = bswap32(val);
> -#endif
> -    PCI_DPRINTF("writel addr " TARGET_FMT_plx " val %x\n",
> -                (target_phys_addr_t)addr, val);
> -    if (s->config_reg & (1u << 31))
> -        pci_data_write(s->bus, s->config_reg, val, 4);
> -}
> -
> -static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr)
> -{
> -    PCIHostState *s = opaque;
> -    uint32_t val;
> -
> -    if (!(s->config_reg & (1 << 31)))
> -        return 0xff;
> -    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 1);
> -    PCI_DPRINTF("readb addr " TARGET_FMT_plx " val %x\n",
> -                (target_phys_addr_t)addr, val);
> -    return val;
> -}
> +/* for mmio */
> +extern CPUWriteMemoryFunc * const pci_host_data_write_mmio[];
> +extern CPUReadMemoryFunc * const pci_host_data_read_mmio[];
>  
> -static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
> -{
> -    PCIHostState *s = opaque;
> -    uint32_t val;
> -    if (!(s->config_reg & (1 << 31)))
> -        return 0xffff;
> -    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 2);
> -    PCI_DPRINTF("readw addr " TARGET_FMT_plx " val %x\n",
> -                (target_phys_addr_t)addr, val);
> -#ifdef TARGET_WORDS_BIGENDIAN
> -    val = bswap16(val);
> -#endif
> -    return val;
> -}
> +/* for ioio */
> +void pci_host_data_writeb_ioport(void* opaque, uint32_t addr, uint32_t val);
> +void pci_host_data_writew_ioport(void* opaque, uint32_t addr, uint32_t val);
> +void pci_host_data_writel_ioport(void* opaque, uint32_t addr, uint32_t val);
> +uint32_t pci_host_data_readb_ioport(void* opaque, uint32_t addr);
> +uint32_t pci_host_data_readw_ioport(void* opaque, uint32_t addr);
> +uint32_t pci_host_data_readl_ioport(void* opaque, uint32_t addr);
>  
> -static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr)
> -{
> -    PCIHostState *s = opaque;
> -    uint32_t val;
> -    if (!(s->config_reg & (1 << 31)))
> -        return 0xffffffff;
> -    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 4);
> -    PCI_DPRINTF("readl addr " TARGET_FMT_plx " val %x\n",
> -                (target_phys_addr_t)addr, val);
> -#ifdef TARGET_WORDS_BIGENDIAN
> -    val = bswap32(val);
> -#endif
> -    return val;
> -}
> +#endif /* PCI_HOST_H */
> diff --git a/hw/piix_pci.c b/hw/piix_pci.c
> index edd6df0..c8db791 100644
> --- a/hw/piix_pci.c
> +++ b/hw/piix_pci.c
> @@ -25,12 +25,10 @@
>  #include "hw.h"
>  #include "pc.h"
>  #include "pci.h"
> +#include "pci_host.h"
>  #include "isa.h"
>  #include "sysbus.h"
>  
> -typedef uint32_t pci_addr_t;
> -#include "pci_host.h"
> -
>  typedef PCIHostState I440FXState;
>  
>  typedef struct PIIX3State {
> @@ -201,12 +199,12 @@ static int i440fx_pcihost_initfn(SysBusDevice *dev)
>      register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
>      register_ioport_read(0xcf8, 4, 4, i440fx_addr_readl, s);
>  
> -    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb, s);
> -    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew, s);
> -    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel, s);
> -    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
> -    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
> -    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
> +    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb_ioport, s);
> +    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew_ioport, s);
> +    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel_ioport, s);
> +    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb_ioport, s);
> +    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw_ioport, s);
> +    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl_ioport, s);
>      return 0;
>  }
>  
> diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
> index 655fe86..953e6b6 100644
> --- a/hw/ppc4xx_pci.c
> +++ b/hw/ppc4xx_pci.c
> @@ -22,8 +22,6 @@
>  #include "hw.h"
>  #include "ppc.h"
>  #include "ppc4xx.h"
> -
> -typedef target_phys_addr_t pci_addr_t;
>  #include "pci.h"
>  #include "pci_host.h"
>  #include "bswap.h"
> @@ -117,18 +115,6 @@ static CPUWriteMemoryFunc * const pci4xx_cfgaddr_write[] = {
>      &pci4xx_cfgaddr_writel,
>  };
>  
> -static CPUReadMemoryFunc * const pci4xx_cfgdata_read[] = {
> -    &pci_host_data_readb,
> -    &pci_host_data_readw,
> -    &pci_host_data_readl,
> -};
> -
> -static CPUWriteMemoryFunc * const pci4xx_cfgdata_write[] = {
> -    &pci_host_data_writeb,
> -    &pci_host_data_writew,
> -    &pci_host_data_writel,
> -};
> -
>  static void ppc4xx_pci_reg_write4(void *opaque, target_phys_addr_t offset,
>                                    uint32_t value)
>  {
> @@ -392,8 +378,8 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
>      cpu_register_physical_memory(config_space + PCIC0_CFGADDR, 4, index);
>  
>      /* CFGDATA */
> -    index = cpu_register_io_memory(pci4xx_cfgdata_read,
> -                                   pci4xx_cfgdata_write,
> +    index = cpu_register_io_memory(pci_host_data_read_mmio,
> +                                   pci_host_data_write_mmio,
>                                     &controller->pci_state);
>      if (index < 0)
>          goto free;
> diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
> index 64fccfd..4920837 100644
> --- a/hw/ppce500_pci.c
> +++ b/hw/ppce500_pci.c
> @@ -17,7 +17,6 @@
>  #include "hw.h"
>  #include "ppc.h"
>  #include "ppce500.h"
> -typedef target_phys_addr_t pci_addr_t;
>  #include "pci.h"
>  #include "pci_host.h"
>  #include "bswap.h"
> @@ -116,18 +115,6 @@ static CPUWriteMemoryFunc * const pcie500_cfgaddr_write[] = {
>      &pcie500_cfgaddr_writel,
>  };
>  
> -static CPUReadMemoryFunc * const pcie500_cfgdata_read[] = {
> -    &pci_host_data_readb,
> -    &pci_host_data_readw,
> -    &pci_host_data_readl,
> -};
> -
> -static CPUWriteMemoryFunc * const pcie500_cfgdata_write[] = {
> -    &pci_host_data_writeb,
> -    &pci_host_data_writew,
> -    &pci_host_data_writel,
> -};
> -
>  static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
>  {
>      PPCE500PCIState *pci = opaque;
> @@ -344,8 +331,8 @@ PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
>      cpu_register_physical_memory(registers + PCIE500_CFGADDR, 4, index);
>  
>      /* CFGDATA */
> -    index = cpu_register_io_memory(pcie500_cfgdata_read,
> -                                   pcie500_cfgdata_write,
> +    index = cpu_register_io_memory(pci_host_data_read_mmio,
> +                                   pci_host_data_write_mmio,
>                                     &controller->pci_state);
>      if (index < 0)
>          goto free;
> diff --git a/hw/prep_pci.c b/hw/prep_pci.c
> index 2d8a0fa..943de90 100644
> --- a/hw/prep_pci.c
> +++ b/hw/prep_pci.c
> @@ -24,8 +24,6 @@
>  
>  #include "hw.h"
>  #include "pci.h"
> -
> -typedef uint32_t pci_addr_t;
>  #include "pci_host.h"
>  
>  typedef PCIHostState PREPPCIState;
> @@ -144,12 +142,12 @@ PCIBus *pci_prep_init(qemu_irq *pic)
>      register_ioport_write(0xcf8, 4, 4, pci_prep_addr_writel, s);
>      register_ioport_read(0xcf8, 4, 4, pci_prep_addr_readl, s);
>  
> -    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb, s);
> -    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew, s);
> -    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel, s);
> -    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
> -    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
> -    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
> +    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb_ioport, s);
> +    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew_ioport, s);
> +    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel_ioport, s);
> +    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb_ioport, s);
> +    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw_ioport, s);
> +    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl_ioport, s);
>  
>      PPC_io_memory = cpu_register_io_memory(PPC_PCIIO_read,
>                                             PPC_PCIIO_write, s);
> diff --git a/hw/unin_pci.c b/hw/unin_pci.c
> index a202153..1d11816 100644
> --- a/hw/unin_pci.c
> +++ b/hw/unin_pci.c
> @@ -24,6 +24,7 @@
>  #include "hw.h"
>  #include "ppc_mac.h"
>  #include "pci.h"
> +#include "pci_host.h"
>  
>  /* debug UniNorth */
>  //#define DEBUG_UNIN
> @@ -35,9 +36,6 @@
>  #define UNIN_DPRINTF(fmt, ...)
>  #endif
>  
> -typedef target_phys_addr_t pci_addr_t;
> -#include "pci_host.h"
> -
>  typedef struct UNINState {
>      SysBusDevice busdev;
>      PCIHostState host_state;
> @@ -83,18 +81,6 @@ static CPUReadMemoryFunc * const pci_unin_main_config_read[] = {
>      &pci_unin_main_config_readl,
>  };
>  
> -static CPUWriteMemoryFunc * const pci_unin_main_write[] = {
> -    &pci_host_data_writeb,
> -    &pci_host_data_writew,
> -    &pci_host_data_writel,
> -};
> -
> -static CPUReadMemoryFunc * const pci_unin_main_read[] = {
> -    &pci_host_data_readb,
> -    &pci_host_data_readw,
> -    &pci_host_data_readl,
> -};
> -
>  static void pci_unin_config_writel (void *opaque, target_phys_addr_t addr,
>                                      uint32_t val)
>  {
> @@ -123,18 +109,6 @@ static CPUReadMemoryFunc * const pci_unin_config_read[] = {
>      &pci_unin_config_readl,
>  };
>  
> -static CPUWriteMemoryFunc * const pci_unin_write[] = {
> -    &pci_host_data_writeb,
> -    &pci_host_data_writew,
> -    &pci_host_data_writel,
> -};
> -
> -static CPUReadMemoryFunc * const pci_unin_read[] = {
> -    &pci_host_data_readb,
> -    &pci_host_data_readw,
> -    &pci_host_data_readl,
> -};
> -
>  /* Don't know if this matches real hardware, but it agrees with OHW.  */
>  static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
>  {
> @@ -180,8 +154,9 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
>  
>      pci_mem_config = cpu_register_io_memory(pci_unin_main_config_read,
>                                              pci_unin_main_config_write, s);
> -    pci_mem_data = cpu_register_io_memory(pci_unin_main_read,
> -                                          pci_unin_main_write, &s->host_state);
> +    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
> +                                          pci_host_data_write_mmio,
> +                                          &s->host_state);
>  
>      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> @@ -203,8 +178,9 @@ static int pci_dec_21154_init_device(SysBusDevice *dev)
>      // XXX: s = &pci_bridge[2];
>      pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
>                                              pci_unin_config_write, s);
> -    pci_mem_data = cpu_register_io_memory(pci_unin_main_read,
> -                                          pci_unin_main_write, &s->host_state);
> +    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
> +                                          pci_host_data_write_mmio,
> +                                          &s->host_state);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
>      return 0;
> @@ -220,8 +196,9 @@ static int pci_unin_agp_init_device(SysBusDevice *dev)
>  
>      pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
>                                              pci_unin_config_write, s);
> -    pci_mem_data = cpu_register_io_memory(pci_unin_main_read,
> -                                          pci_unin_main_write, &s->host_state);
> +    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
> +                                          pci_host_data_write_mmio,
> +                                          &s->host_state);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
>      return 0;
> @@ -237,8 +214,8 @@ static int pci_unin_internal_init_device(SysBusDevice *dev)
>  
>      pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
>                                              pci_unin_config_write, s);
> -    pci_mem_data = cpu_register_io_memory(pci_unin_read,
> -                                          pci_unin_write, s);
> +    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
> +                                          pci_host_data_write_mmio, s);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
>      return 0;
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH 15/23] pci_host.h: split non-inline static function in pci_host.h into pci_host.c
  2009-10-05 14:35   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-05 14:37     ` Michael S. Tsirkin
  0 siblings, 0 replies; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 14:37 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 04:35:33PM +0200, Michael S. Tsirkin wrote:
> On Mon, Oct 05, 2009 at 07:06:55PM +0900, Isaku Yamahata wrote:
> > Later a structures declared in pci_host.h, PCIHostState, will be used.
> > However pci_host.h doesn't allow to include itself easily. This patches
> > addresses it.
> > 
> > pci_host.h includes non-inline static functions which are instantiated
> > in .c by including pci_host.h. That prevents from including pci_host.h
> > to use PCIHostState.
> > So split pci_host.h non-inline static functions into pci_host.c.
> > Its purpose to include is to instantiate io function for mmio or ioio.
> > To avoid including code, we always instantiate both version.
> 
> This is even worse than what we had, file including itself, oh my.
> All I suggested was either
> - get rid of macro hackery in some sane way

And by sane way I mean just let users write their own routines
which get proper types, and call pci host.

> - make all function static inline
> 
> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > ---
> >  Makefile.target               |    8 ++--
> >  hw/apb_pci.c                  |   21 ++-------
> >  hw/grackle_pci.c              |   24 ++--------
> >  hw/gt64xxx.c                  |   11 +----
> >  hw/{pci_host.h => pci_host.c} |   61 +++++++++++++++++++++-----
> >  hw/pci_host.h                 |   96 ++++++-----------------------------------
> >  hw/piix_pci.c                 |   16 +++----
> >  hw/ppc4xx_pci.c               |   18 +-------
> >  hw/ppce500_pci.c              |   17 +------
> >  hw/prep_pci.c                 |   14 +++---
> >  hw/unin_pci.c                 |   47 +++++---------------
> >  11 files changed, 105 insertions(+), 228 deletions(-)
> >  copy hw/{pci_host.h => pci_host.c} (69%)
> > 
> > diff --git a/Makefile.target b/Makefile.target
> > index 1f4518c..2da39b7 100644
> > --- a/Makefile.target
> > +++ b/Makefile.target
> > @@ -186,11 +186,11 @@ obj-i386-y += fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
> >  obj-i386-y += cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
> >  obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
> >  obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
> > -obj-i386-y += ne2000-isa.o
> > +obj-i386-y += ne2000-isa.o pci_host.o
> >  
> >  # shared objects
> >  obj-ppc-y = ppc.o ide/core.o ide/qdev.o ide/isa.o ide/pci.o ide/macio.o
> > -obj-ppc-y += vga.o vga-pci.o $(sound-obj-y) dma.o openpic.o
> > +obj-ppc-y += vga.o vga-pci.o $(sound-obj-y) dma.o openpic.o pci_host.o
> >  # PREP target
> >  obj-ppc-y += pckbd.o serial.o i8259.o i8254.o fdc.o mc146818rtc.o
> >  obj-ppc-y += prep_pci.o ppc_prep.o ne2000-isa.o
> > @@ -217,7 +217,7 @@ obj-mips-y += gt64xxx.o pckbd.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o
> >  obj-mips-y += piix4.o parallel.o cirrus_vga.o pcspk.o $(sound-obj-y)
> >  obj-mips-y += mipsnet.o ne2000-isa.o
> >  obj-mips-y += pflash_cfi01.o
> > -obj-mips-y += vmware_vga.o
> > +obj-mips-y += vmware_vga.o pci_host.o
> >  
> >  obj-microblaze-y = petalogix_s3adsp1800_mmu.o
> >  
> > @@ -244,7 +244,7 @@ obj-cris-y += etraxfs_ser.o
> >  obj-cris-y += pflash_cfi02.o
> >  
> >  ifeq ($(TARGET_ARCH), sparc64)
> > -obj-sparc-y = sun4u.o pckbd.o apb_pci.o
> > +obj-sparc-y = sun4u.o pckbd.o apb_pci.o pci_host.o
> >  obj-sparc-y += ide/core.o ide/qdev.o ide/pci.o
> >  obj-sparc-y += vga.o vga-pci.o
> >  obj-sparc-y += fdc.o mc146818rtc.o serial.o
> > diff --git a/hw/apb_pci.c b/hw/apb_pci.c
> > index 381b924..89413b1 100644
> > --- a/hw/apb_pci.c
> > +++ b/hw/apb_pci.c
> > @@ -28,6 +28,7 @@
> >  
> >  #include "sysbus.h"
> >  #include "pci.h"
> > +#include "pci_host.h"
> >  
> >  /* debug APB */
> >  //#define DEBUG_APB
> > @@ -39,9 +40,6 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
> >  #define APB_DPRINTF(fmt, ...)
> >  #endif
> >  
> > -typedef target_phys_addr_t pci_addr_t;
> > -#include "pci_host.h"
> > -
> >  typedef struct APBState {
> >      SysBusDevice busdev;
> >      PCIHostState host_state;
> > @@ -136,18 +134,6 @@ static CPUReadMemoryFunc * const apb_config_read[] = {
> >      &apb_config_readl,
> >  };
> >  
> > -static CPUWriteMemoryFunc * const pci_apb_write[] = {
> > -    &pci_host_data_writeb,
> > -    &pci_host_data_writew,
> > -    &pci_host_data_writel,
> > -};
> > -
> > -static CPUReadMemoryFunc * const pci_apb_read[] = {
> > -    &pci_host_data_readb,
> > -    &pci_host_data_readw,
> > -    &pci_host_data_readl,
> > -};
> > -
> >  static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
> >                                    uint32_t val)
> >  {
> > @@ -284,8 +270,9 @@ static int pci_pbm_init_device(SysBusDevice *dev)
> >                                              pci_apb_config_write, s);
> >      sysbus_init_mmio(dev, 0x10ULL, pci_mem_config);
> >      /* mem_data */
> > -    pci_mem_data = cpu_register_io_memory(pci_apb_read,
> > -                                          pci_apb_write, &s->host_state);
> > +    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
> > +                                          pci_host_data_write_mmio,
> > +                                          &s->host_state);
> >      sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data);
> >      return 0;
> >  }
> > diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
> > index d878cf6..d29175b 100644
> > --- a/hw/grackle_pci.c
> > +++ b/hw/grackle_pci.c
> > @@ -26,6 +26,7 @@
> >  #include "sysbus.h"
> >  #include "ppc_mac.h"
> >  #include "pci.h"
> > +#include "pci_host.h"
> >  
> >  /* debug Grackle */
> >  //#define DEBUG_GRACKLE
> > @@ -37,9 +38,6 @@
> >  #define GRACKLE_DPRINTF(fmt, ...)
> >  #endif
> >  
> > -typedef target_phys_addr_t pci_addr_t;
> > -#include "pci_host.h"
> > -
> >  typedef struct GrackleState {
> >      SysBusDevice busdev;
> >      PCIHostState host_state;
> > @@ -84,18 +82,6 @@ static CPUReadMemoryFunc * const pci_grackle_config_read[] = {
> >      &pci_grackle_config_readl,
> >  };
> >  
> > -static CPUWriteMemoryFunc * const pci_grackle_write[] = {
> > -    &pci_host_data_writeb,
> > -    &pci_host_data_writew,
> > -    &pci_host_data_writel,
> > -};
> > -
> > -static CPUReadMemoryFunc * const pci_grackle_read[] = {
> > -    &pci_host_data_readb,
> > -    &pci_host_data_readw,
> > -    &pci_host_data_readl,
> > -};
> > -
> >  /* Don't know if this matches real hardware, but it agrees with OHW.  */
> >  static int pci_grackle_map_irq(PCIDevice *pci_dev, int irq_num)
> >  {
> > @@ -163,8 +149,8 @@ static int pci_grackle_init_device(SysBusDevice *dev)
> >  
> >      pci_mem_config = cpu_register_io_memory(pci_grackle_config_read,
> >                                              pci_grackle_config_write, s);
> > -    pci_mem_data = cpu_register_io_memory(pci_grackle_read,
> > -                                          pci_grackle_write,
> > +    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
> > +                                          pci_host_data_write_mmio,
> >                                            &s->host_state);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> > @@ -185,8 +171,8 @@ static int pci_dec_21154_init_device(SysBusDevice *dev)
> >  
> >      pci_mem_config = cpu_register_io_memory(pci_grackle_config_read,
> >                                              pci_grackle_config_write, s);
> > -    pci_mem_data = cpu_register_io_memory(pci_grackle_read,
> > -                                          pci_grackle_write,
> > +    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
> > +                                          pci_host_data_write_mmio,
> >                                            &s->host_state);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> > diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
> > index 8f9ae4a..fb7f5bd 100644
> > --- a/hw/gt64xxx.c
> > +++ b/hw/gt64xxx.c
> > @@ -25,10 +25,8 @@
> >  #include "hw.h"
> >  #include "mips.h"
> >  #include "pci.h"
> > -#include "pc.h"
> > -
> > -typedef target_phys_addr_t pci_addr_t;
> >  #include "pci_host.h"
> > +#include "pc.h"
> >  
> >  //#define DEBUG
> >  
> > @@ -1119,13 +1117,6 @@ PCIBus *pci_gt64120_init(qemu_irq *pic)
> >      GT64120State *s;
> >      PCIDevice *d;
> >  
> > -    (void)&pci_host_data_writeb; /* avoid warning */
> > -    (void)&pci_host_data_writew; /* avoid warning */
> > -    (void)&pci_host_data_writel; /* avoid warning */
> > -    (void)&pci_host_data_readb; /* avoid warning */
> > -    (void)&pci_host_data_readw; /* avoid warning */
> > -    (void)&pci_host_data_readl; /* avoid warning */
> > -
> >      s = qemu_mallocz(sizeof(GT64120State));
> >      s->pci = qemu_mallocz(sizeof(GT64120PCIState));
> >  
> > diff --git a/hw/pci_host.h b/hw/pci_host.c
> > similarity index 69%
> > copy from hw/pci_host.h
> > copy to hw/pci_host.c
> > index 48862b5..5c06f03 100644
> > --- a/hw/pci_host.h
> > +++ b/hw/pci_host.c
> > @@ -25,10 +25,13 @@
> >  /* Worker routines for a PCI host controller that uses an {address,data}
> >     register pair to access PCI configuration space.  */
> >  
> > +#ifndef PCI_HOST_C
> > +
> >  /* debug PCI */
> >  //#define DEBUG_PCI
> >  
> > -#include "sysbus.h"
> > +#include "pci.h"
> > +#include "pci_host.h"
> >  
> >  #ifdef DEBUG_PCI
> >  #define PCI_DPRINTF(fmt, ...) \
> > @@ -37,13 +40,40 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
> >  #define PCI_DPRINTF(fmt, ...)
> >  #endif
> >  
> > -typedef struct {
> > -    SysBusDevice busdev;
> > -    uint32_t config_reg;
> > -    PCIBus *bus;
> > -} PCIHostState;
> > +#define PCI_HOST_C
> > +
> > +#define PCI_ADDR_T      target_phys_addr_t
> > +#define PCI_HOST_SUFFIX _mmio
> > +#define PCI_HOST_STATIC static
> > +
> > +#include "pci_host.c"
> > +
> > +CPUWriteMemoryFunc * const pci_host_data_write_mmio[] = {
> > +    &glue(pci_host_data_writeb, PCI_HOST_SUFFIX),
> > +    &glue(pci_host_data_writew, PCI_HOST_SUFFIX),
> > +    &glue(pci_host_data_writel, PCI_HOST_SUFFIX),
> > +};
> > +
> > +CPUReadMemoryFunc * const pci_host_data_read_mmio[] = {
> > +    &glue(pci_host_data_readb, PCI_HOST_SUFFIX),
> > +    &glue(pci_host_data_readw, PCI_HOST_SUFFIX),
> > +    &glue(pci_host_data_readl, PCI_HOST_SUFFIX),
> > +};
> > +
> > +#undef PCI_ADDR_T
> > +#undef PCI_HOST_SUFFIX
> > +#undef PCI_HOST_STATIC
> >  
> > -static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
> > +#define PCI_ADDR_T      uint32_t
> > +#define PCI_HOST_SUFFIX _ioport
> > +#define PCI_HOST_STATIC /* nothing. export this function */
> > +
> > +#include "pci_host.c"
> > +
> > +#else
> > +
> > +PCI_HOST_STATIC void glue(pci_host_data_writeb, PCI_HOST_SUFFIX)(
> > +    void* opaque, PCI_ADDR_T addr, uint32_t val)
> >  {
> >      PCIHostState *s = opaque;
> >  
> > @@ -53,7 +83,8 @@ static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
> >          pci_data_write(s->bus, s->config_reg | (addr & 3), val, 1);
> >  }
> >  
> > -static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val)
> > +PCI_HOST_STATIC void glue(pci_host_data_writew, PCI_HOST_SUFFIX)(
> > +    void* opaque, PCI_ADDR_T addr, uint32_t val)
> >  {
> >      PCIHostState *s = opaque;
> >  #ifdef TARGET_WORDS_BIGENDIAN
> > @@ -65,7 +96,8 @@ static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val)
> >          pci_data_write(s->bus, s->config_reg | (addr & 3), val, 2);
> >  }
> >  
> > -static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
> > +PCI_HOST_STATIC void glue(pci_host_data_writel, PCI_HOST_SUFFIX)(
> > +    void* opaque, PCI_ADDR_T addr, uint32_t val)
> >  {
> >      PCIHostState *s = opaque;
> >  #ifdef TARGET_WORDS_BIGENDIAN
> > @@ -77,7 +109,8 @@ static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
> >          pci_data_write(s->bus, s->config_reg, val, 4);
> >  }
> >  
> > -static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr)
> > +PCI_HOST_STATIC uint32_t glue(pci_host_data_readb, PCI_HOST_SUFFIX)(
> > +    void* opaque, PCI_ADDR_T addr)
> >  {
> >      PCIHostState *s = opaque;
> >      uint32_t val;
> > @@ -90,7 +123,8 @@ static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr)
> >      return val;
> >  }
> >  
> > -static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
> > +PCI_HOST_STATIC uint32_t glue(pci_host_data_readw, PCI_HOST_SUFFIX)(
> > +    void* opaque, PCI_ADDR_T addr)
> >  {
> >      PCIHostState *s = opaque;
> >      uint32_t val;
> > @@ -105,7 +139,8 @@ static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
> >      return val;
> >  }
> >  
> > -static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr)
> > +PCI_HOST_STATIC uint32_t glue(pci_host_data_readl, PCI_HOST_SUFFIX)(
> > +    void* opaque, PCI_ADDR_T addr)
> >  {
> >      PCIHostState *s = opaque;
> >      uint32_t val;
> > @@ -119,3 +154,5 @@ static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr)
> >  #endif
> >      return val;
> >  }
> > +
> > +#endif
> > diff --git a/hw/pci_host.h b/hw/pci_host.h
> > index 48862b5..ea98ed2 100644
> > --- a/hw/pci_host.h
> > +++ b/hw/pci_host.h
> > @@ -25,97 +25,27 @@
> >  /* Worker routines for a PCI host controller that uses an {address,data}
> >     register pair to access PCI configuration space.  */
> >  
> > -/* debug PCI */
> > -//#define DEBUG_PCI
> > +#ifndef PCI_HOST_H
> > +#define PCI_HOST_H
> >  
> >  #include "sysbus.h"
> >  
> > -#ifdef DEBUG_PCI
> > -#define PCI_DPRINTF(fmt, ...) \
> > -do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
> > -#else
> > -#define PCI_DPRINTF(fmt, ...)
> > -#endif
> > -
> >  typedef struct {
> >      SysBusDevice busdev;
> >      uint32_t config_reg;
> >      PCIBus *bus;
> >  } PCIHostState;
> >  
> > -static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
> > -{
> > -    PCIHostState *s = opaque;
> > -
> > -    PCI_DPRINTF("writeb addr " TARGET_FMT_plx " val %x\n",
> > -                (target_phys_addr_t)addr, val);
> > -    if (s->config_reg & (1u << 31))
> > -        pci_data_write(s->bus, s->config_reg | (addr & 3), val, 1);
> > -}
> > -
> > -static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val)
> > -{
> > -    PCIHostState *s = opaque;
> > -#ifdef TARGET_WORDS_BIGENDIAN
> > -    val = bswap16(val);
> > -#endif
> > -    PCI_DPRINTF("writew addr " TARGET_FMT_plx " val %x\n",
> > -                (target_phys_addr_t)addr, val);
> > -    if (s->config_reg & (1u << 31))
> > -        pci_data_write(s->bus, s->config_reg | (addr & 3), val, 2);
> > -}
> > -
> > -static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
> > -{
> > -    PCIHostState *s = opaque;
> > -#ifdef TARGET_WORDS_BIGENDIAN
> > -    val = bswap32(val);
> > -#endif
> > -    PCI_DPRINTF("writel addr " TARGET_FMT_plx " val %x\n",
> > -                (target_phys_addr_t)addr, val);
> > -    if (s->config_reg & (1u << 31))
> > -        pci_data_write(s->bus, s->config_reg, val, 4);
> > -}
> > -
> > -static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr)
> > -{
> > -    PCIHostState *s = opaque;
> > -    uint32_t val;
> > -
> > -    if (!(s->config_reg & (1 << 31)))
> > -        return 0xff;
> > -    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 1);
> > -    PCI_DPRINTF("readb addr " TARGET_FMT_plx " val %x\n",
> > -                (target_phys_addr_t)addr, val);
> > -    return val;
> > -}
> > +/* for mmio */
> > +extern CPUWriteMemoryFunc * const pci_host_data_write_mmio[];
> > +extern CPUReadMemoryFunc * const pci_host_data_read_mmio[];
> >  
> > -static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
> > -{
> > -    PCIHostState *s = opaque;
> > -    uint32_t val;
> > -    if (!(s->config_reg & (1 << 31)))
> > -        return 0xffff;
> > -    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 2);
> > -    PCI_DPRINTF("readw addr " TARGET_FMT_plx " val %x\n",
> > -                (target_phys_addr_t)addr, val);
> > -#ifdef TARGET_WORDS_BIGENDIAN
> > -    val = bswap16(val);
> > -#endif
> > -    return val;
> > -}
> > +/* for ioio */
> > +void pci_host_data_writeb_ioport(void* opaque, uint32_t addr, uint32_t val);
> > +void pci_host_data_writew_ioport(void* opaque, uint32_t addr, uint32_t val);
> > +void pci_host_data_writel_ioport(void* opaque, uint32_t addr, uint32_t val);
> > +uint32_t pci_host_data_readb_ioport(void* opaque, uint32_t addr);
> > +uint32_t pci_host_data_readw_ioport(void* opaque, uint32_t addr);
> > +uint32_t pci_host_data_readl_ioport(void* opaque, uint32_t addr);
> >  
> > -static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr)
> > -{
> > -    PCIHostState *s = opaque;
> > -    uint32_t val;
> > -    if (!(s->config_reg & (1 << 31)))
> > -        return 0xffffffff;
> > -    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 4);
> > -    PCI_DPRINTF("readl addr " TARGET_FMT_plx " val %x\n",
> > -                (target_phys_addr_t)addr, val);
> > -#ifdef TARGET_WORDS_BIGENDIAN
> > -    val = bswap32(val);
> > -#endif
> > -    return val;
> > -}
> > +#endif /* PCI_HOST_H */
> > diff --git a/hw/piix_pci.c b/hw/piix_pci.c
> > index edd6df0..c8db791 100644
> > --- a/hw/piix_pci.c
> > +++ b/hw/piix_pci.c
> > @@ -25,12 +25,10 @@
> >  #include "hw.h"
> >  #include "pc.h"
> >  #include "pci.h"
> > +#include "pci_host.h"
> >  #include "isa.h"
> >  #include "sysbus.h"
> >  
> > -typedef uint32_t pci_addr_t;
> > -#include "pci_host.h"
> > -
> >  typedef PCIHostState I440FXState;
> >  
> >  typedef struct PIIX3State {
> > @@ -201,12 +199,12 @@ static int i440fx_pcihost_initfn(SysBusDevice *dev)
> >      register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
> >      register_ioport_read(0xcf8, 4, 4, i440fx_addr_readl, s);
> >  
> > -    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb, s);
> > -    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew, s);
> > -    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel, s);
> > -    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
> > -    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
> > -    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
> > +    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb_ioport, s);
> > +    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew_ioport, s);
> > +    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel_ioport, s);
> > +    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb_ioport, s);
> > +    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw_ioport, s);
> > +    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl_ioport, s);
> >      return 0;
> >  }
> >  
> > diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
> > index 655fe86..953e6b6 100644
> > --- a/hw/ppc4xx_pci.c
> > +++ b/hw/ppc4xx_pci.c
> > @@ -22,8 +22,6 @@
> >  #include "hw.h"
> >  #include "ppc.h"
> >  #include "ppc4xx.h"
> > -
> > -typedef target_phys_addr_t pci_addr_t;
> >  #include "pci.h"
> >  #include "pci_host.h"
> >  #include "bswap.h"
> > @@ -117,18 +115,6 @@ static CPUWriteMemoryFunc * const pci4xx_cfgaddr_write[] = {
> >      &pci4xx_cfgaddr_writel,
> >  };
> >  
> > -static CPUReadMemoryFunc * const pci4xx_cfgdata_read[] = {
> > -    &pci_host_data_readb,
> > -    &pci_host_data_readw,
> > -    &pci_host_data_readl,
> > -};
> > -
> > -static CPUWriteMemoryFunc * const pci4xx_cfgdata_write[] = {
> > -    &pci_host_data_writeb,
> > -    &pci_host_data_writew,
> > -    &pci_host_data_writel,
> > -};
> > -
> >  static void ppc4xx_pci_reg_write4(void *opaque, target_phys_addr_t offset,
> >                                    uint32_t value)
> >  {
> > @@ -392,8 +378,8 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
> >      cpu_register_physical_memory(config_space + PCIC0_CFGADDR, 4, index);
> >  
> >      /* CFGDATA */
> > -    index = cpu_register_io_memory(pci4xx_cfgdata_read,
> > -                                   pci4xx_cfgdata_write,
> > +    index = cpu_register_io_memory(pci_host_data_read_mmio,
> > +                                   pci_host_data_write_mmio,
> >                                     &controller->pci_state);
> >      if (index < 0)
> >          goto free;
> > diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
> > index 64fccfd..4920837 100644
> > --- a/hw/ppce500_pci.c
> > +++ b/hw/ppce500_pci.c
> > @@ -17,7 +17,6 @@
> >  #include "hw.h"
> >  #include "ppc.h"
> >  #include "ppce500.h"
> > -typedef target_phys_addr_t pci_addr_t;
> >  #include "pci.h"
> >  #include "pci_host.h"
> >  #include "bswap.h"
> > @@ -116,18 +115,6 @@ static CPUWriteMemoryFunc * const pcie500_cfgaddr_write[] = {
> >      &pcie500_cfgaddr_writel,
> >  };
> >  
> > -static CPUReadMemoryFunc * const pcie500_cfgdata_read[] = {
> > -    &pci_host_data_readb,
> > -    &pci_host_data_readw,
> > -    &pci_host_data_readl,
> > -};
> > -
> > -static CPUWriteMemoryFunc * const pcie500_cfgdata_write[] = {
> > -    &pci_host_data_writeb,
> > -    &pci_host_data_writew,
> > -    &pci_host_data_writel,
> > -};
> > -
> >  static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
> >  {
> >      PPCE500PCIState *pci = opaque;
> > @@ -344,8 +331,8 @@ PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
> >      cpu_register_physical_memory(registers + PCIE500_CFGADDR, 4, index);
> >  
> >      /* CFGDATA */
> > -    index = cpu_register_io_memory(pcie500_cfgdata_read,
> > -                                   pcie500_cfgdata_write,
> > +    index = cpu_register_io_memory(pci_host_data_read_mmio,
> > +                                   pci_host_data_write_mmio,
> >                                     &controller->pci_state);
> >      if (index < 0)
> >          goto free;
> > diff --git a/hw/prep_pci.c b/hw/prep_pci.c
> > index 2d8a0fa..943de90 100644
> > --- a/hw/prep_pci.c
> > +++ b/hw/prep_pci.c
> > @@ -24,8 +24,6 @@
> >  
> >  #include "hw.h"
> >  #include "pci.h"
> > -
> > -typedef uint32_t pci_addr_t;
> >  #include "pci_host.h"
> >  
> >  typedef PCIHostState PREPPCIState;
> > @@ -144,12 +142,12 @@ PCIBus *pci_prep_init(qemu_irq *pic)
> >      register_ioport_write(0xcf8, 4, 4, pci_prep_addr_writel, s);
> >      register_ioport_read(0xcf8, 4, 4, pci_prep_addr_readl, s);
> >  
> > -    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb, s);
> > -    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew, s);
> > -    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel, s);
> > -    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
> > -    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
> > -    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
> > +    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb_ioport, s);
> > +    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew_ioport, s);
> > +    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel_ioport, s);
> > +    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb_ioport, s);
> > +    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw_ioport, s);
> > +    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl_ioport, s);
> >  
> >      PPC_io_memory = cpu_register_io_memory(PPC_PCIIO_read,
> >                                             PPC_PCIIO_write, s);
> > diff --git a/hw/unin_pci.c b/hw/unin_pci.c
> > index a202153..1d11816 100644
> > --- a/hw/unin_pci.c
> > +++ b/hw/unin_pci.c
> > @@ -24,6 +24,7 @@
> >  #include "hw.h"
> >  #include "ppc_mac.h"
> >  #include "pci.h"
> > +#include "pci_host.h"
> >  
> >  /* debug UniNorth */
> >  //#define DEBUG_UNIN
> > @@ -35,9 +36,6 @@
> >  #define UNIN_DPRINTF(fmt, ...)
> >  #endif
> >  
> > -typedef target_phys_addr_t pci_addr_t;
> > -#include "pci_host.h"
> > -
> >  typedef struct UNINState {
> >      SysBusDevice busdev;
> >      PCIHostState host_state;
> > @@ -83,18 +81,6 @@ static CPUReadMemoryFunc * const pci_unin_main_config_read[] = {
> >      &pci_unin_main_config_readl,
> >  };
> >  
> > -static CPUWriteMemoryFunc * const pci_unin_main_write[] = {
> > -    &pci_host_data_writeb,
> > -    &pci_host_data_writew,
> > -    &pci_host_data_writel,
> > -};
> > -
> > -static CPUReadMemoryFunc * const pci_unin_main_read[] = {
> > -    &pci_host_data_readb,
> > -    &pci_host_data_readw,
> > -    &pci_host_data_readl,
> > -};
> > -
> >  static void pci_unin_config_writel (void *opaque, target_phys_addr_t addr,
> >                                      uint32_t val)
> >  {
> > @@ -123,18 +109,6 @@ static CPUReadMemoryFunc * const pci_unin_config_read[] = {
> >      &pci_unin_config_readl,
> >  };
> >  
> > -static CPUWriteMemoryFunc * const pci_unin_write[] = {
> > -    &pci_host_data_writeb,
> > -    &pci_host_data_writew,
> > -    &pci_host_data_writel,
> > -};
> > -
> > -static CPUReadMemoryFunc * const pci_unin_read[] = {
> > -    &pci_host_data_readb,
> > -    &pci_host_data_readw,
> > -    &pci_host_data_readl,
> > -};
> > -
> >  /* Don't know if this matches real hardware, but it agrees with OHW.  */
> >  static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
> >  {
> > @@ -180,8 +154,9 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
> >  
> >      pci_mem_config = cpu_register_io_memory(pci_unin_main_config_read,
> >                                              pci_unin_main_config_write, s);
> > -    pci_mem_data = cpu_register_io_memory(pci_unin_main_read,
> > -                                          pci_unin_main_write, &s->host_state);
> > +    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
> > +                                          pci_host_data_write_mmio,
> > +                                          &s->host_state);
> >  
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> > @@ -203,8 +178,9 @@ static int pci_dec_21154_init_device(SysBusDevice *dev)
> >      // XXX: s = &pci_bridge[2];
> >      pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
> >                                              pci_unin_config_write, s);
> > -    pci_mem_data = cpu_register_io_memory(pci_unin_main_read,
> > -                                          pci_unin_main_write, &s->host_state);
> > +    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
> > +                                          pci_host_data_write_mmio,
> > +                                          &s->host_state);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> >      return 0;
> > @@ -220,8 +196,9 @@ static int pci_unin_agp_init_device(SysBusDevice *dev)
> >  
> >      pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
> >                                              pci_unin_config_write, s);
> > -    pci_mem_data = cpu_register_io_memory(pci_unin_main_read,
> > -                                          pci_unin_main_write, &s->host_state);
> > +    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
> > +                                          pci_host_data_write_mmio,
> > +                                          &s->host_state);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> >      return 0;
> > @@ -237,8 +214,8 @@ static int pci_unin_internal_init_device(SysBusDevice *dev)
> >  
> >      pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
> >                                              pci_unin_config_write, s);
> > -    pci_mem_data = cpu_register_io_memory(pci_unin_read,
> > -                                          pci_unin_write, s);
> > +    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
> > +                                          pci_host_data_write_mmio, s);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> >      return 0;
> > -- 
> > 1.6.0.2

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

* [Qemu-devel] Re: [PATCH 21/23] pci/brdige: qdevfy and initialize secondary bus and subordinate bus.
  2009-10-05 10:07 ` [Qemu-devel] [PATCH 21/23] pci/brdige: qdevfy and initialize secondary bus and subordinate bus Isaku Yamahata
  2009-10-05 13:49   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-05 14:58   ` Michael S. Tsirkin
  1 sibling, 0 replies; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 14:58 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 07:07:01PM +0900, Isaku Yamahata wrote:
> +    br = DO_UPCAST(PCIBridge, dev, d);

By the way, why do we use DO_UPCAST thing,
which requires that field is at the start of parent
structure, instead of container_of which does not?

-- 
MST

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

* [Qemu-devel] Re: [PATCH 11/23] pci: typedef pcibus_t as uint64_t instead of uint32_t.
  2009-10-05 10:06 ` [Qemu-devel] [PATCH 11/23] pci: typedef pcibus_t as uint64_t instead of uint32_t Isaku Yamahata
@ 2009-10-05 20:18   ` Michael S. Tsirkin
  0 siblings, 0 replies; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 20:18 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 07:06:51PM +0900, Isaku Yamahata wrote:
> This patch is preliminary for 64bit bar.
> For 64bit bar support, change pcibus_t which represents
> pci bus addr/size from uint32_t to uint64_t.
> And also change FMT_pcibus for printf.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.c |    6 +++++-
>  hw/pci.h |    4 ++--
>  2 files changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 8d6e8ea..21565f5 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -473,7 +473,11 @@ static void pci_update_mappings(PCIDevice *d)
>                         mappings, we handle specific values as invalid
>                         mappings. */
>                      if (last_addr <= new_addr || new_addr == 0 ||
> -                        last_addr == PCI_BAR_UNMAPPED) {
> +                        last_addr == PCI_BAR_UNMAPPED ||
> +
> +                        /* keep old behaviour
> +                         * without this, PC ide doesn't work well. */
> +                        last_addr >= UINT32_MAX) {
>                          new_addr = PCI_BAR_UNMAPPED;
>                      }
>                  } else {

This change does not seem to be related to either pcibus_t or
FMT_PCIBUS.

> diff --git a/hw/pci.h b/hw/pci.h
> index 359fce1..cbf80c0 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -71,8 +71,8 @@ extern target_phys_addr_t pci_mem_base;
>  #define PCI_DEVICE_ID_VIRTIO_BALLOON     0x1002
>  #define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003
>  
> -typedef uint32_t pcibus_t;
> -#define FMT_PCIBUS                      PRIx32
> +typedef uint64_t pcibus_t;
> +#define FMT_PCIBUS                      PRIx64
>  
>  typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
>                                  uint32_t address, uint32_t data, int len);
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH 16/23] pci: pcie host and mmcfg support.
  2009-10-05 11:01   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-06  8:48     ` Isaku Yamahata
  2009-10-06  9:30       ` Michael S. Tsirkin
  0 siblings, 1 reply; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-06  8:48 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 01:01:43PM +0200, Michael S. Tsirkin wrote:
> On Mon, Oct 05, 2009 at 07:06:56PM +0900, Isaku Yamahata wrote:
> > This patch adds common routines for pcie host bridge and pcie mmcfg.
> > This will be used by q35 based chipset emulation.
> > 
> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> 
> Looks like most my comments on this patch were ignored.
> I started repeating them here but then I grew tired,
> so only partially repeated them. Are you going to address this?

Which mail? Could you please care to resent the previous mail to me?
I'm willing to address your review, and I appreciated your review.

I'm afraid that your mail was lost somewhere in the net.
I tried the qemu.org ML archive, however I couldn't find it there.
And I also wasn't able to find it in gmane.org neither.
-- 
yamahata

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

* [Qemu-devel] Re: [PATCH 16/23] pci: pcie host and mmcfg support.
  2009-10-06  8:48     ` Isaku Yamahata
@ 2009-10-06  9:30       ` Michael S. Tsirkin
  0 siblings, 0 replies; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-06  9:30 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Tue, Oct 06, 2009 at 05:48:22PM +0900, Isaku Yamahata wrote:
> On Mon, Oct 05, 2009 at 01:01:43PM +0200, Michael S. Tsirkin wrote:
> > On Mon, Oct 05, 2009 at 07:06:56PM +0900, Isaku Yamahata wrote:
> > > This patch adds common routines for pcie host bridge and pcie mmcfg.
> > > This will be used by q35 based chipset emulation.
> > > 
> > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > 
> > Looks like most my comments on this patch were ignored.
> > I started repeating them here but then I grew tired,
> > so only partially repeated them. Are you going to address this?
> 
> Which mail? Could you please care to resent the previous mail to me?
> I'm willing to address your review, and I appreciated your review.
> 
> I'm afraid that your mail was lost somewhere in the net.

Ugh, looks like I never sent it.  No wonder comments weren't addressed
:) Sending out now, sorry about the noise.

-- 
MST

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

* [Qemu-devel] Re: [PATCH 12/23] pci: 64bit bar support.
  2009-10-05 12:06   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-06  9:38     ` Isaku Yamahata
  2009-10-06  9:43       ` Michael S. Tsirkin
  0 siblings, 1 reply; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-06  9:38 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 02:06:30PM +0200, Michael S. Tsirkin wrote:
> On Mon, Oct 05, 2009 at 07:06:52PM +0900, Isaku Yamahata wrote:
> > implemented pci 64bit bar support.
> > 
> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > ---
> >  hw/pci.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++--------
> >  hw/pci.h |    2 ++
> >  2 files changed, 48 insertions(+), 8 deletions(-)
> > 
> > diff --git a/hw/pci.c b/hw/pci.c
> > index 21565f5..09a6816 100644
> > --- a/hw/pci.c
> > +++ b/hw/pci.c
> > @@ -395,6 +395,13 @@ int pci_unregister_device(PCIDevice *pci_dev)
> >      return 0;
> >  }
> >  
> > +static inline int pci_bar_is_mem64(const PCIIORegion *r)
> > +{
> > +    return !(r->type & PCI_ADDRESS_SPACE_IO) &&
> > +        (r->type & PCI_ADDRESS_SPACE_MEM_TYPE_MASK) ==
> > +        PCI_ADDRESS_SPACE_MEM_TYPE_64;
> > +}
> > +
> 
> why are we checking PCI_ADDRESS_SPACE_IO? Let's not.

Because bar handling logic for io bar and 32bit memory bar is same.
For example, pci_register_bar() does.


> >  void pci_register_bar(PCIDevice *pci_dev, int region_num,
> >                              pcibus_t size, int type,
> >                              PCIMapIORegionFunc *map_func)
> > @@ -427,8 +434,13 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
> >          addr = 0x10 + region_num * 4;
> >      }
> >      pci_set_long(pci_dev->config + addr, type);
> > -    pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
> > -    pci_set_long(pci_dev->cmask + addr, 0xffffffff);
> > +    if (pci_bar_is_mem64(r)) {
> > +        pci_set_quad(pci_dev->wmask + addr, wmask);
> > +        pci_set_quad(pci_dev->cmask + addr, ~0ULL);
> > +    } else {
> > +        pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
> > +        pci_set_long(pci_dev->cmask + addr, 0xffffffff);
> > +    }
> >  }
> >  
> >  static void pci_update_mappings(PCIDevice *d)
> > @@ -462,7 +474,11 @@ static void pci_update_mappings(PCIDevice *d)
> >                  }
> >              } else {
> >                  if (cmd & PCI_COMMAND_MEMORY) {
> > -                    new_addr = pci_get_long(d->config + config_ofs);
> > +                    if (pci_bar_is_mem64(r)) {
> > +                        new_addr = pci_get_quad(d->config + config_ofs);
> > +                    } else {
> > +                        new_addr = pci_get_long(d->config + config_ofs);
> > +                    }
> >                      /* the ROM slot has a specific enable bit */
> >                      if (i == PCI_ROM_SLOT && !(new_addr & 1))
> >                          goto no_mem_map;
> > @@ -473,11 +489,24 @@ static void pci_update_mappings(PCIDevice *d)
> >                         mappings, we handle specific values as invalid
> >                         mappings. */
> >                      if (last_addr <= new_addr || new_addr == 0 ||
> > -                        last_addr == PCI_BAR_UNMAPPED ||
> > +                        last_addr == PCI_BAR_UNMAPPED) {
> > +                        new_addr = PCI_BAR_UNMAPPED;
> > +                    }
> >  
> > -                        /* keep old behaviour
> > -                         * without this, PC ide doesn't work well. */
> > -                        last_addr >= UINT32_MAX) {
> > +                    /*
> > +                     * work around: without this, PC ide and other devices
> > +                     * don't work well.
> > +                     * OS writes all 1 bits to 32 BAR to find its size
> 
> Isn't memory disabled then? PCI spec says it should be ...
> 
> > +                     * resulting in setting UINT32_MAX - alignemnt,
> 
> typo
> 
> > +                     * and then OS sets the BAR to where they really want
> > +                     * the BAR to sit.
> > +                     * On the other hand, there are some important areas
> > +                     * blow 4G on i386/x86_64. So setting BAR over those area
> 
> typo
> 
> > +                     * below 4G causes troubles.
> > +                     * We work around the issues by prohibitting BAR
> 
> typo.
> 
> > +                     * from sitting right blow 4G.
> 
> typo
> 
> > +                     */
> > +                    if (!pci_bar_is_mem64(r) && last_addr >= UINT32_MAX) {
> >                          new_addr = PCI_BAR_UNMAPPED;
> >                      }
> >                  } else {
> > @@ -736,7 +765,16 @@ static void pci_info_device(PCIDevice *d)
> >                  monitor_printf(mon, "I/O at 0x%04"FMT_PCIBUS" [0x%04"FMT_PCIBUS"].\n",
> >                                 r->addr, r->addr + r->size - 1);
> >              } else {
> > -                monitor_printf(mon, "32 bit memory at 0x%08"FMT_PCIBUS" [0x%08"FMT_PCIBUS"].\n",
> > +                const char *type = pci_bar_is_mem64(r)? "64 bit": "32 bit";
> > +                const char *prefetch = "";
> > +
> > +                if (r->type & PCI_ADDRESS_SPACE_MEM_PREFETCH) {
> > +                    prefetch = " prefetchable";
> > +                }
> > +
> > +                monitor_printf(mon, "%s%s memory at "
> > +                               "0x%08"FMT_PCIBUS" [0x%08"FMT_PCIBUS"].\n",
> > +                               type, prefetch,
> >                                 r->addr, r->addr + r->size - 1);
> >              }
> >          }
> > diff --git a/hw/pci.h b/hw/pci.h
> > index cbf80c0..b65ce03 100644
> > --- a/hw/pci.h
> > +++ b/hw/pci.h
> > @@ -84,6 +84,8 @@ typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
> >  
> >  #define PCI_ADDRESS_SPACE_MEM		0x00
> >  #define PCI_ADDRESS_SPACE_IO		0x01
> > +#define PCI_ADDRESS_SPACE_MEM_TYPE_MASK 0x06
> > +#define PCI_ADDRESS_SPACE_MEM_TYPE_64   0x04    /* 64 bit address */
> 
> something wrong with text alignment here. pls align with tabs as the
> rest of surrounding code does.
> 
> And I thought we were switching to names from pci_regs.h?
> 
> >  #define PCI_ADDRESS_SPACE_MEM_PREFETCH	0x08
> >  
> >  typedef struct PCIIORegion {
> 

-- 
yamahata

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

* [Qemu-devel] Re: [PATCH 12/23] pci: 64bit bar support.
  2009-10-05 12:47   ` Michael S. Tsirkin
@ 2009-10-06  9:42     ` Isaku Yamahata
  2009-10-06  9:47       ` Michael S. Tsirkin
  0 siblings, 1 reply; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-06  9:42 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 02:47:11PM +0200, Michael S. Tsirkin wrote:
> > @@ -462,7 +474,11 @@ static void pci_update_mappings(PCIDevice *d)
> >                  }
> >              } else {
> >                  if (cmd & PCI_COMMAND_MEMORY) {
> > -                    new_addr = pci_get_long(d->config + config_ofs);
> > +                    if (pci_bar_is_mem64(r)) {
> > +                        new_addr = pci_get_quad(d->config + config_ofs);
> 
> From previous patch, config_ofs is region_num * 4
> This is incorrect for 64 bit regions.

I don't see any problems. In the following example, 
0, 2 ... will be used for region_number and 1 is left unused.

BAR0 64bit memory
BAR1 used by BAR0 64bit
BAR2 ...
-- 
yamahata

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

* [Qemu-devel] Re: [PATCH 12/23] pci: 64bit bar support.
  2009-10-06  9:38     ` Isaku Yamahata
@ 2009-10-06  9:43       ` Michael S. Tsirkin
  0 siblings, 0 replies; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-06  9:43 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Tue, Oct 06, 2009 at 06:38:30PM +0900, Isaku Yamahata wrote:
> On Mon, Oct 05, 2009 at 02:06:30PM +0200, Michael S. Tsirkin wrote:
> > On Mon, Oct 05, 2009 at 07:06:52PM +0900, Isaku Yamahata wrote:
> > > implemented pci 64bit bar support.
> > > 
> > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > > ---
> > >  hw/pci.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++--------
> > >  hw/pci.h |    2 ++
> > >  2 files changed, 48 insertions(+), 8 deletions(-)
> > > 
> > > diff --git a/hw/pci.c b/hw/pci.c
> > > index 21565f5..09a6816 100644
> > > --- a/hw/pci.c
> > > +++ b/hw/pci.c
> > > @@ -395,6 +395,13 @@ int pci_unregister_device(PCIDevice *pci_dev)
> > >      return 0;
> > >  }
> > >  
> > > +static inline int pci_bar_is_mem64(const PCIIORegion *r)
> > > +{
> > > +    return !(r->type & PCI_ADDRESS_SPACE_IO) &&
> > > +        (r->type & PCI_ADDRESS_SPACE_MEM_TYPE_MASK) ==
> > > +        PCI_ADDRESS_SPACE_MEM_TYPE_64;
> > > +}
> > > +
> > 
> > why are we checking PCI_ADDRESS_SPACE_IO? Let's not.
> 
> Because bar handling logic for io bar and 32bit memory bar is same.
> For example, pci_register_bar() does.

Yes, but 64 bit handling does not care about this: if you see a 64 bit
bar, you can handle it as 64 bit.  No need to check the I/O bit.

> 
> > >  void pci_register_bar(PCIDevice *pci_dev, int region_num,
> > >                              pcibus_t size, int type,
> > >                              PCIMapIORegionFunc *map_func)
> > > @@ -427,8 +434,13 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
> > >          addr = 0x10 + region_num * 4;
> > >      }
> > >      pci_set_long(pci_dev->config + addr, type);
> > > -    pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
> > > -    pci_set_long(pci_dev->cmask + addr, 0xffffffff);
> > > +    if (pci_bar_is_mem64(r)) {
> > > +        pci_set_quad(pci_dev->wmask + addr, wmask);
> > > +        pci_set_quad(pci_dev->cmask + addr, ~0ULL);
> > > +    } else {
> > > +        pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
> > > +        pci_set_long(pci_dev->cmask + addr, 0xffffffff);
> > > +    }
> > >  }
> > >  
> > >  static void pci_update_mappings(PCIDevice *d)
> > > @@ -462,7 +474,11 @@ static void pci_update_mappings(PCIDevice *d)
> > >                  }
> > >              } else {
> > >                  if (cmd & PCI_COMMAND_MEMORY) {
> > > -                    new_addr = pci_get_long(d->config + config_ofs);
> > > +                    if (pci_bar_is_mem64(r)) {
> > > +                        new_addr = pci_get_quad(d->config + config_ofs);
> > > +                    } else {
> > > +                        new_addr = pci_get_long(d->config + config_ofs);
> > > +                    }
> > >                      /* the ROM slot has a specific enable bit */
> > >                      if (i == PCI_ROM_SLOT && !(new_addr & 1))
> > >                          goto no_mem_map;
> > > @@ -473,11 +489,24 @@ static void pci_update_mappings(PCIDevice *d)
> > >                         mappings, we handle specific values as invalid
> > >                         mappings. */
> > >                      if (last_addr <= new_addr || new_addr == 0 ||
> > > -                        last_addr == PCI_BAR_UNMAPPED ||
> > > +                        last_addr == PCI_BAR_UNMAPPED) {
> > > +                        new_addr = PCI_BAR_UNMAPPED;
> > > +                    }
> > >  
> > > -                        /* keep old behaviour
> > > -                         * without this, PC ide doesn't work well. */
> > > -                        last_addr >= UINT32_MAX) {
> > > +                    /*
> > > +                     * work around: without this, PC ide and other devices
> > > +                     * don't work well.
> > > +                     * OS writes all 1 bits to 32 BAR to find its size
> > 
> > Isn't memory disabled then? PCI spec says it should be ...
> > 
> > > +                     * resulting in setting UINT32_MAX - alignemnt,
> > 
> > typo
> > 
> > > +                     * and then OS sets the BAR to where they really want
> > > +                     * the BAR to sit.
> > > +                     * On the other hand, there are some important areas
> > > +                     * blow 4G on i386/x86_64. So setting BAR over those area
> > 
> > typo
> > 
> > > +                     * below 4G causes troubles.
> > > +                     * We work around the issues by prohibitting BAR
> > 
> > typo.
> > 
> > > +                     * from sitting right blow 4G.
> > 
> > typo
> > 
> > > +                     */
> > > +                    if (!pci_bar_is_mem64(r) && last_addr >= UINT32_MAX) {
> > >                          new_addr = PCI_BAR_UNMAPPED;
> > >                      }
> > >                  } else {
> > > @@ -736,7 +765,16 @@ static void pci_info_device(PCIDevice *d)
> > >                  monitor_printf(mon, "I/O at 0x%04"FMT_PCIBUS" [0x%04"FMT_PCIBUS"].\n",
> > >                                 r->addr, r->addr + r->size - 1);
> > >              } else {
> > > -                monitor_printf(mon, "32 bit memory at 0x%08"FMT_PCIBUS" [0x%08"FMT_PCIBUS"].\n",
> > > +                const char *type = pci_bar_is_mem64(r)? "64 bit": "32 bit";
> > > +                const char *prefetch = "";
> > > +
> > > +                if (r->type & PCI_ADDRESS_SPACE_MEM_PREFETCH) {
> > > +                    prefetch = " prefetchable";
> > > +                }
> > > +
> > > +                monitor_printf(mon, "%s%s memory at "
> > > +                               "0x%08"FMT_PCIBUS" [0x%08"FMT_PCIBUS"].\n",
> > > +                               type, prefetch,
> > >                                 r->addr, r->addr + r->size - 1);
> > >              }
> > >          }
> > > diff --git a/hw/pci.h b/hw/pci.h
> > > index cbf80c0..b65ce03 100644
> > > --- a/hw/pci.h
> > > +++ b/hw/pci.h
> > > @@ -84,6 +84,8 @@ typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
> > >  
> > >  #define PCI_ADDRESS_SPACE_MEM		0x00
> > >  #define PCI_ADDRESS_SPACE_IO		0x01
> > > +#define PCI_ADDRESS_SPACE_MEM_TYPE_MASK 0x06
> > > +#define PCI_ADDRESS_SPACE_MEM_TYPE_64   0x04    /* 64 bit address */
> > 
> > something wrong with text alignment here. pls align with tabs as the
> > rest of surrounding code does.
> > 
> > And I thought we were switching to names from pci_regs.h?
> > 
> > >  #define PCI_ADDRESS_SPACE_MEM_PREFETCH	0x08
> > >  
> > >  typedef struct PCIIORegion {
> > 
> 
> -- 
> yamahata

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

* [Qemu-devel] Re: [PATCH 12/23] pci: 64bit bar support.
  2009-10-06  9:42     ` Isaku Yamahata
@ 2009-10-06  9:47       ` Michael S. Tsirkin
  0 siblings, 0 replies; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-06  9:47 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Tue, Oct 06, 2009 at 06:42:02PM +0900, Isaku Yamahata wrote:
> On Mon, Oct 05, 2009 at 02:47:11PM +0200, Michael S. Tsirkin wrote:
> > > @@ -462,7 +474,11 @@ static void pci_update_mappings(PCIDevice *d)
> > >                  }
> > >              } else {
> > >                  if (cmd & PCI_COMMAND_MEMORY) {
> > > -                    new_addr = pci_get_long(d->config + config_ofs);
> > > +                    if (pci_bar_is_mem64(r)) {
> > > +                        new_addr = pci_get_quad(d->config + config_ofs);
> > 
> > From previous patch, config_ofs is region_num * 4
> > This is incorrect for 64 bit regions.
> 
> I don't see any problems. In the following example, 
> 0, 2 ... will be used for region_number and 1 is left unused.
> 
> BAR0 64bit memory
> BAR1 used by BAR0 64bit
> BAR2 ...

Oh, I see. It's up to the user of pci_register_bar to allocate sane
region numbers. Fine. Maybe add a comment before pci_register_bar about
legal values for region_num: not everyone knows about PCI internals.

> -- 
> yamahata

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

* [Qemu-devel] Re: [PATCH 14/23] pci: factor out the logic to get pci device from address.
  2009-10-05 12:45   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-06  9:50     ` Isaku Yamahata
  2009-10-06 10:23       ` Michael S. Tsirkin
  0 siblings, 1 reply; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-06  9:50 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 02:45:33PM +0200, Michael S. Tsirkin wrote:
> On Mon, Oct 05, 2009 at 07:06:54PM +0900, Isaku Yamahata wrote:
> > factor out conversion logic from io port address into bus+dev+func
> > with bit shift operation and conversion bus+dev+func into pci device.
> > They will be used later by pcie support.
> > This patch also eliminates the logic duplication.
> 
> Please split removing logic duplication into separate patch.
> It might be applicable already, while express stuff needs more work IMO.
> 
> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > ---
> >  hw/pci.c |   83 ++++++++++++++++++++++++++++++++++---------------------------
> >  1 files changed, 46 insertions(+), 37 deletions(-)
> > 
> > diff --git a/hw/pci.c b/hw/pci.c
> > index 6ddd256..5f808ff 100644
> > --- a/hw/pci.c
> > +++ b/hw/pci.c
> > @@ -629,44 +629,25 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
> >          pci_update_mappings(d);
> >  }
> >  
> > -void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> > +static void pci_data_write_common(PCIDevice *pci_dev,
> > +                                  uint32_t config_addr, uint32_t val, int len)
> 
> So as I said in the previous comment, pci express should just be able to
> use pci code directly, instead of reusing this low-level stuff.
> All you need to do is range-check address and ignore extended registers.

Maybe my patch description isn't good enough,
I'm afraid that you misunderstood the patch purpose.

PCI configuration and PCI express MMCONFIG uses different address scheme
as follows.
This patch purpose is to separate out its address parsing logic
from pci config space update logic.

PCI:
 0- 7 bit: offset in the configuration space (256bytes)
 7-15 bit: devfn
16-14 bit: bus

PCI express:
 0-11 bit: offset in the configuration space (4KBytes)
12-19 bit: devfn
20-28 bit: bus



> >  {
> > -    PCIBus *s = opaque;
> > -    PCIDevice *pci_dev;
> > -    int config_addr, bus_num;
> > -
> > -#if 0
> > -    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
> > -                addr, val, len);
> > -#endif
> > -    bus_num = (addr >> 16) & 0xff;
> > -    s = pci_find_bus(s, bus_num);
> > -    if (!s)
> > -        return;
> > -    pci_dev = s->devices[(addr >> 8) & 0xff];
> > +    assert(len == 1 || len == 2 || len == 4);
> >      if (!pci_dev)
> >          return;
> > -    config_addr = addr & 0xff;
> > -    PCI_DPRINTF("pci_config_write: %s: "
> > -                "addr=%02x val=%08"PRI32x" len=%d\n",
> > -                pci_dev->name, config_addr, val, len);
> > +
> > +    PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRI32x" len=%d\n",
> > +                __func__, pci_dev->name, config_addr, val, len);
> >      pci_dev->config_write(pci_dev, config_addr, val, len);
> >  }
> >  
> > -uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> > +static uint32_t pci_data_read_common(PCIDevice *pci_dev,
> > +                                     uint32_t config_addr, int len)
> >  {
> > -    PCIBus *s = opaque;
> > -    PCIDevice *pci_dev;
> > -    int config_addr, bus_num;
> >      uint32_t val;
> >  
> > -    bus_num = (addr >> 16) & 0xff;
> > -    s = pci_find_bus(s, bus_num);
> > -    if (!s)
> > -        goto fail;
> > -    pci_dev = s->devices[(addr >> 8) & 0xff];
> > +    assert(len == 1 || len == 2 || len == 4);
> >      if (!pci_dev) {
> > -    fail:
> >          switch(len) {
> >          case 1:
> >              val = 0xff;
> > @@ -679,21 +660,49 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> >              val = 0xffffffff;
> >              break;
> >          }
> > -        goto the_end;
> > +    } else {
> > +        val = pci_dev->config_read(pci_dev, config_addr, len);
> > +        PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
> > +                    __func__, pci_dev->name, config_addr, val, len);
> >      }
> > -    config_addr = addr & 0xff;
> > -    val = pci_dev->config_read(pci_dev, config_addr, len);
> > -    PCI_DPRINTF("pci_config_read: %s: "
> > -                "addr=%02x val=%08"PRIx32" len=%d\n",
> > -                pci_dev->name, config_addr, val, len);
> > - the_end:
> > +
> >  #if 0
> > -    PCI_DPRINTF("pci_data_read: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
> > -                addr, val, len);
> > +    PCI_DPRINTF("%s: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
> > +                __func__, addr, val, len);
> >  #endif
> 
> move to real pci_data_read?
> 
> >      return val;
> >  }
> >  
> > +static inline PCIDevice *pci_addr_to_dev(PCIBus *bus, uint32_t addr)
> > +{
> > +    uint8_t bus_num = (addr >> 16) & 0xff;
> > +    uint8_t devfn = (addr >> 8) & 0xff;
> > +    return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
> > +}
> > +
> > +static inline uint32_t pci_addr_to_config(uint32_t addr)
> > +{
> > +    return addr & 0xff;
> > +}
> > +
> > +void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> > +{
> > +    PCIBus *s = opaque;
> > +#if 0
> > +    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
> > +                addr, val, len);
> > +#endif
> > +
> > +    pci_data_write_common(pci_addr_to_dev(s, addr), pci_addr_to_config(addr),
> > +                          val, len);
> 
> For pci express, there's extended register number in bits 11:8
> so what we should do here IMO is check these bits and
> ignore if they are not 0.

I don't understand what you suggest.
pci_data_{write, read}() are glue for ioio or mmio to
access pci configuration space. And 'addr' parameter is used
to specify configuration space access.
It includes not only the offset in configuration space, but also
devfn and bus.


> > +}
> > +
> > +uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> > +{
> > +    PCIBus *s = opaque;
> 
> For pci express, there's extended register number in bits 11:8
> so what we should do here IMO is check these bits and
> return 0 if not 0.
> 
> > +    return pci_data_read_common(pci_addr_to_dev(s, addr),
> > +                                pci_addr_to_config(addr), len);
> > +}
> >  /***********************************************************/
> >  /* generic PCI irq support */
> >  
> 

-- 
yamahata

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

* [Qemu-devel] Re: [PATCH 16/23] pci: pcie host and mmcfg support.
  2009-10-05 11:41   ` Michael S. Tsirkin
@ 2009-10-06 10:02     ` Isaku Yamahata
  2009-10-06 10:57       ` Michael S. Tsirkin
  2009-10-07 11:30       ` Akio Takebe
  0 siblings, 2 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-06 10:02 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 01:41:21PM +0200, Michael S. Tsirkin wrote:
> On Mon, Oct 05, 2009 at 07:06:56PM +0900, Isaku Yamahata wrote:
> > @@ -1052,9 +1242,10 @@ PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
> >  
> >  static int pci_find_space(PCIDevice *pdev, uint8_t size)
> >  {
> > +    int config_size = pcie_config_size(pdev);
> >      int offset = PCI_CONFIG_HEADER_SIZE;
> >      int i;
> > -    for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i)
> > +    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
> >          if (pdev->used[i])
> >              offset = i + 1;
> >          else if (i - offset + 1 == size)
> > diff --git a/hw/pci.h b/hw/pci.h
> > index 00f2b78..1f402d2 100644
> > --- a/hw/pci.h
> > +++ b/hw/pci.h
> > @@ -175,20 +175,26 @@ enum {
> >      QEMU_PCI_CAP_MSIX = 0x1,
> >  };
> >  
> > +/* Size of the standart PCIe config space: 4KB */
> > +#define PCIE_CONFIG_SPACE_SIZE  0x1000
> > +#define PCIE_EXT_CONFIG_SPACE_SIZE                      \
> > +    (PCIE_CONFIG_SPACE_SIZE - PCI_CONFIG_SPACE_SIZE)
> > +
> >  struct PCIDevice {
> >      DeviceState qdev;
> > +
> >      /* PCI config space */
> > -    uint8_t config[PCI_CONFIG_SPACE_SIZE];
> > +    uint8_t *config;
> >  
> >      /* Used to enable config checks on load. Note that writeable bits are
> >       * never checked even if set in cmask. */
> > -    uint8_t cmask[PCI_CONFIG_SPACE_SIZE];
> > +    uint8_t *cmask;
> >  
> >      /* Used to implement R/W bytes */
> > -    uint8_t wmask[PCI_CONFIG_SPACE_SIZE];
> > +    uint8_t *wmask;
> >  
> >      /* Used to allocate config space for capabilities. */
> > -    uint8_t used[PCI_CONFIG_SPACE_SIZE];
> > +    uint8_t *used;
> >  
> >      /* the following fields are read only */
> >      PCIBus *bus;
> 
> 
> So I thought about this some more, and I think that this change
> in unnecessary. PCI Express adds support for extended 4K
> configuration space, but the only thing that must reside
> there is the optional advanced error reporting capability,
> which I don't think we'll need to implement, ever.
>
> Everything else can reside in the first 256 bytes, just as for regular
> PCI. And pci code already returns 0 for accesses outside the first 256
> bytes, so express specific code is necessary.

I agree with you for emulated PCI express device
(which doesn't exist for now). However I oppose it for other reason.

My purpose is to direct attach PCIe device to a guest including
AER emulation somehow.
When direct attaching PCIe native device to a guest,
we don't have any control on how its configuration space is used.
When an error is reported on host via AER, I'd like to pass 
the error to guest in some manner. So I want AER too in a sense.
-- 
yamahata

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

* [Qemu-devel] Re: [PATCH 14/23] pci: factor out the logic to get pci device from address.
  2009-10-06  9:50     ` Isaku Yamahata
@ 2009-10-06 10:23       ` Michael S. Tsirkin
  0 siblings, 0 replies; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-06 10:23 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Tue, Oct 06, 2009 at 06:50:05PM +0900, Isaku Yamahata wrote:
> On Mon, Oct 05, 2009 at 02:45:33PM +0200, Michael S. Tsirkin wrote:
> > On Mon, Oct 05, 2009 at 07:06:54PM +0900, Isaku Yamahata wrote:
> > > factor out conversion logic from io port address into bus+dev+func
> > > with bit shift operation and conversion bus+dev+func into pci device.
> > > They will be used later by pcie support.
> > > This patch also eliminates the logic duplication.
> > 
> > Please split removing logic duplication into separate patch.
> > It might be applicable already, while express stuff needs more work IMO.
> > 
> > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > > ---
> > >  hw/pci.c |   83 ++++++++++++++++++++++++++++++++++---------------------------
> > >  1 files changed, 46 insertions(+), 37 deletions(-)
> > > 
> > > diff --git a/hw/pci.c b/hw/pci.c
> > > index 6ddd256..5f808ff 100644
> > > --- a/hw/pci.c
> > > +++ b/hw/pci.c
> > > @@ -629,44 +629,25 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
> > >          pci_update_mappings(d);
> > >  }
> > >  
> > > -void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> > > +static void pci_data_write_common(PCIDevice *pci_dev,
> > > +                                  uint32_t config_addr, uint32_t val, int len)
> > 
> > So as I said in the previous comment, pci express should just be able to
> > use pci code directly, instead of reusing this low-level stuff.
> > All you need to do is range-check address and ignore extended registers.
> 
> Maybe my patch description isn't good enough,
> I'm afraid that you misunderstood the patch purpose.
> 
> PCI configuration and PCI express MMCONFIG uses different address scheme
> as follows.
> This patch purpose is to separate out its address parsing logic
> from pci config space update logic.
> 
> PCI:
>  0- 7 bit: offset in the configuration space (256bytes)
>  7-15 bit: devfn
> 16-14 bit: bus
> 
> PCI express:
>  0-11 bit: offset in the configuration space (4KBytes)
> 12-19 bit: devfn
> 20-28 bit: bus

The comment is basically that there's no common code:
you don't need len checks that you added for mmconfig (they are there
just for documentation purposes), and so all pci_data_write does is
address parsing.  So just call pci_dev->config_write for both mmconfig
and config.

> > >  {
> > > -    PCIBus *s = opaque;
> > > -    PCIDevice *pci_dev;
> > > -    int config_addr, bus_num;
> > > -
> > > -#if 0
> > > -    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
> > > -                addr, val, len);
> > > -#endif
> > > -    bus_num = (addr >> 16) & 0xff;
> > > -    s = pci_find_bus(s, bus_num);
> > > -    if (!s)
> > > -        return;
> > > -    pci_dev = s->devices[(addr >> 8) & 0xff];
> > > +    assert(len == 1 || len == 2 || len == 4);
> > >      if (!pci_dev)
> > >          return;
> > > -    config_addr = addr & 0xff;
> > > -    PCI_DPRINTF("pci_config_write: %s: "
> > > -                "addr=%02x val=%08"PRI32x" len=%d\n",
> > > -                pci_dev->name, config_addr, val, len);
> > > +
> > > +    PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRI32x" len=%d\n",
> > > +                __func__, pci_dev->name, config_addr, val, len);
> > >      pci_dev->config_write(pci_dev, config_addr, val, len);
> > >  }
> > >  
> > > -uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> > > +static uint32_t pci_data_read_common(PCIDevice *pci_dev,
> > > +                                     uint32_t config_addr, int len)
> > >  {
> > > -    PCIBus *s = opaque;
> > > -    PCIDevice *pci_dev;
> > > -    int config_addr, bus_num;
> > >      uint32_t val;
> > >  
> > > -    bus_num = (addr >> 16) & 0xff;
> > > -    s = pci_find_bus(s, bus_num);
> > > -    if (!s)
> > > -        goto fail;
> > > -    pci_dev = s->devices[(addr >> 8) & 0xff];
> > > +    assert(len == 1 || len == 2 || len == 4);
> > >      if (!pci_dev) {
> > > -    fail:
> > >          switch(len) {
> > >          case 1:
> > >              val = 0xff;
> > > @@ -679,21 +660,49 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> > >              val = 0xffffffff;
> > >              break;
> > >          }
> > > -        goto the_end;
> > > +    } else {
> > > +        val = pci_dev->config_read(pci_dev, config_addr, len);
> > > +        PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
> > > +                    __func__, pci_dev->name, config_addr, val, len);
> > >      }
> > > -    config_addr = addr & 0xff;
> > > -    val = pci_dev->config_read(pci_dev, config_addr, len);
> > > -    PCI_DPRINTF("pci_config_read: %s: "
> > > -                "addr=%02x val=%08"PRIx32" len=%d\n",
> > > -                pci_dev->name, config_addr, val, len);
> > > - the_end:
> > > +
> > >  #if 0
> > > -    PCI_DPRINTF("pci_data_read: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
> > > -                addr, val, len);
> > > +    PCI_DPRINTF("%s: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
> > > +                __func__, addr, val, len);
> > >  #endif
> > 
> > move to real pci_data_read?
> > 
> > >      return val;
> > >  }
> > >  
> > > +static inline PCIDevice *pci_addr_to_dev(PCIBus *bus, uint32_t addr)
> > > +{
> > > +    uint8_t bus_num = (addr >> 16) & 0xff;
> > > +    uint8_t devfn = (addr >> 8) & 0xff;
> > > +    return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
> > > +}
> > > +
> > > +static inline uint32_t pci_addr_to_config(uint32_t addr)
> > > +{
> > > +    return addr & 0xff;
> > > +}
> > > +
> > > +void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> > > +{
> > > +    PCIBus *s = opaque;
> > > +#if 0
> > > +    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
> > > +                addr, val, len);
> > > +#endif
> > > +
> > > +    pci_data_write_common(pci_addr_to_dev(s, addr), pci_addr_to_config(addr),
> > > +                          val, len);
> > 
> > For pci express, there's extended register number in bits 11:8
> > so what we should do here IMO is check these bits and
> > ignore if they are not 0.
> 
> I don't understand what you suggest.
> pci_data_{write, read}() are glue for ioio or mmio to
> access pci configuration space. And 'addr' parameter is used
> to specify configuration space access.
> It includes not only the offset in configuration space, but also
> devfn and bus.
> 

Okay. I was misled by naming.  What I am saying, here and elsewhere, is
that a large part of pain is because of 256 byte/4K byte difference.
Since in express you can hardware addresses > 256 to 0, I propose that
we simply make mmconfig code do this:

if (offset > 256)
	return 0;

And then basically nothing needs to be changed in pci.

> 
> > > +}
> > > +
> > > +uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> > > +{
> > > +    PCIBus *s = opaque;
> > 
> > For pci express, there's extended register number in bits 11:8
> > so what we should do here IMO is check these bits and
> > return 0 if not 0.
> > 
> > > +    return pci_data_read_common(pci_addr_to_dev(s, addr),
> > > +                                pci_addr_to_config(addr), len);
> > > +}
> > >  /***********************************************************/
> > >  /* generic PCI irq support */
> > >  
> > 
> 
> -- 
> yamahata

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

* [Qemu-devel] Re: [PATCH 16/23] pci: pcie host and mmcfg support.
  2009-10-06 10:02     ` Isaku Yamahata
@ 2009-10-06 10:57       ` Michael S. Tsirkin
  2009-10-06 13:21         ` Michael S. Tsirkin
  2009-10-07 11:30       ` Akio Takebe
  1 sibling, 1 reply; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-06 10:57 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Tue, Oct 06, 2009 at 07:02:59PM +0900, Isaku Yamahata wrote:
> On Mon, Oct 05, 2009 at 01:41:21PM +0200, Michael S. Tsirkin wrote:
> > On Mon, Oct 05, 2009 at 07:06:56PM +0900, Isaku Yamahata wrote:
> > > @@ -1052,9 +1242,10 @@ PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
> > >  
> > >  static int pci_find_space(PCIDevice *pdev, uint8_t size)
> > >  {
> > > +    int config_size = pcie_config_size(pdev);
> > >      int offset = PCI_CONFIG_HEADER_SIZE;
> > >      int i;
> > > -    for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i)
> > > +    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
> > >          if (pdev->used[i])
> > >              offset = i + 1;
> > >          else if (i - offset + 1 == size)
> > > diff --git a/hw/pci.h b/hw/pci.h
> > > index 00f2b78..1f402d2 100644
> > > --- a/hw/pci.h
> > > +++ b/hw/pci.h
> > > @@ -175,20 +175,26 @@ enum {
> > >      QEMU_PCI_CAP_MSIX = 0x1,
> > >  };
> > >  
> > > +/* Size of the standart PCIe config space: 4KB */
> > > +#define PCIE_CONFIG_SPACE_SIZE  0x1000
> > > +#define PCIE_EXT_CONFIG_SPACE_SIZE                      \
> > > +    (PCIE_CONFIG_SPACE_SIZE - PCI_CONFIG_SPACE_SIZE)
> > > +
> > >  struct PCIDevice {
> > >      DeviceState qdev;
> > > +
> > >      /* PCI config space */
> > > -    uint8_t config[PCI_CONFIG_SPACE_SIZE];
> > > +    uint8_t *config;
> > >  
> > >      /* Used to enable config checks on load. Note that writeable bits are
> > >       * never checked even if set in cmask. */
> > > -    uint8_t cmask[PCI_CONFIG_SPACE_SIZE];
> > > +    uint8_t *cmask;
> > >  
> > >      /* Used to implement R/W bytes */
> > > -    uint8_t wmask[PCI_CONFIG_SPACE_SIZE];
> > > +    uint8_t *wmask;
> > >  
> > >      /* Used to allocate config space for capabilities. */
> > > -    uint8_t used[PCI_CONFIG_SPACE_SIZE];
> > > +    uint8_t *used;
> > >  
> > >      /* the following fields are read only */
> > >      PCIBus *bus;
> > 
> > 
> > So I thought about this some more, and I think that this change
> > in unnecessary. PCI Express adds support for extended 4K
> > configuration space, but the only thing that must reside
> > there is the optional advanced error reporting capability,
> > which I don't think we'll need to implement, ever.
> >
> > Everything else can reside in the first 256 bytes, just as for regular
> > PCI. And pci code already returns 0 for accesses outside the first 256
> > bytes, so express specific code is necessary.
> 
> I agree with you for emulated PCI express device
> (which doesn't exist for now). However I oppose it for other reason.
> 
> My purpose is to direct attach PCIe device to a guest including
> AER emulation somehow.

For now, if I were you, I would just ignore AER.

> When direct attaching PCIe native device to a guest,
> we don't have any control on how its configuration space is used.
> When an error is reported on host via AER, I'd like to pass 
> the error to guest in some manner. So I want AER too in a sense.

Since what you will want to do is forward stuff to a physical device,
you likely won't need to keep anything in memory at all.
So express code might just do
	if (offset > 256)
		write_to_physical_device();
But, let's take these things one at a time.
For one, device assignment is not upstream at all.

By the way, a general question: how was this tested?  Did you manage to
make guest generate mmconfig transactions?  Which guests do this?

> -- 
> yamahata

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

* [Qemu-devel] Re: [PATCH 16/23] pci: pcie host and mmcfg support.
  2009-10-06 10:57       ` Michael S. Tsirkin
@ 2009-10-06 13:21         ` Michael S. Tsirkin
  2009-10-07  2:25           ` Isaku Yamahata
  0 siblings, 1 reply; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-06 13:21 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Tue, Oct 06, 2009 at 12:57:01PM +0200, Michael S. Tsirkin wrote:
> On Tue, Oct 06, 2009 at 07:02:59PM +0900, Isaku Yamahata wrote:
> > On Mon, Oct 05, 2009 at 01:41:21PM +0200, Michael S. Tsirkin wrote:
> > > On Mon, Oct 05, 2009 at 07:06:56PM +0900, Isaku Yamahata wrote:
> > > > @@ -1052,9 +1242,10 @@ PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
> > > >  
> > > >  static int pci_find_space(PCIDevice *pdev, uint8_t size)
> > > >  {
> > > > +    int config_size = pcie_config_size(pdev);
> > > >      int offset = PCI_CONFIG_HEADER_SIZE;
> > > >      int i;
> > > > -    for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i)
> > > > +    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
> > > >          if (pdev->used[i])
> > > >              offset = i + 1;
> > > >          else if (i - offset + 1 == size)
> > > > diff --git a/hw/pci.h b/hw/pci.h
> > > > index 00f2b78..1f402d2 100644
> > > > --- a/hw/pci.h
> > > > +++ b/hw/pci.h
> > > > @@ -175,20 +175,26 @@ enum {
> > > >      QEMU_PCI_CAP_MSIX = 0x1,
> > > >  };
> > > >  
> > > > +/* Size of the standart PCIe config space: 4KB */
> > > > +#define PCIE_CONFIG_SPACE_SIZE  0x1000
> > > > +#define PCIE_EXT_CONFIG_SPACE_SIZE                      \
> > > > +    (PCIE_CONFIG_SPACE_SIZE - PCI_CONFIG_SPACE_SIZE)
> > > > +
> > > >  struct PCIDevice {
> > > >      DeviceState qdev;
> > > > +
> > > >      /* PCI config space */
> > > > -    uint8_t config[PCI_CONFIG_SPACE_SIZE];
> > > > +    uint8_t *config;
> > > >  
> > > >      /* Used to enable config checks on load. Note that writeable bits are
> > > >       * never checked even if set in cmask. */
> > > > -    uint8_t cmask[PCI_CONFIG_SPACE_SIZE];
> > > > +    uint8_t *cmask;
> > > >  
> > > >      /* Used to implement R/W bytes */
> > > > -    uint8_t wmask[PCI_CONFIG_SPACE_SIZE];
> > > > +    uint8_t *wmask;
> > > >  
> > > >      /* Used to allocate config space for capabilities. */
> > > > -    uint8_t used[PCI_CONFIG_SPACE_SIZE];
> > > > +    uint8_t *used;
> > > >  
> > > >      /* the following fields are read only */
> > > >      PCIBus *bus;
> > > 
> > > 
> > > So I thought about this some more, and I think that this change
> > > in unnecessary. PCI Express adds support for extended 4K
> > > configuration space, but the only thing that must reside
> > > there is the optional advanced error reporting capability,
> > > which I don't think we'll need to implement, ever.
> > >
> > > Everything else can reside in the first 256 bytes, just as for regular
> > > PCI. And pci code already returns 0 for accesses outside the first 256
> > > bytes, so express specific code is necessary.
> > 
> > I agree with you for emulated PCI express device
> > (which doesn't exist for now). However I oppose it for other reason.
> > 
> > My purpose is to direct attach PCIe device to a guest including
> > AER emulation somehow.
> 
> For now, if I were you, I would just ignore AER.
> 
> > When direct attaching PCIe native device to a guest,
> > we don't have any control on how its configuration space is used.
> > When an error is reported on host via AER, I'd like to pass 
> > the error to guest in some manner. So I want AER too in a sense.
> 
> Since what you will want to do is forward stuff to a physical device,
> you likely won't need to keep anything in memory at all.
> So express code might just do
> 	if (offset > 256)
> 		write_to_physical_device();
> But, let's take these things one at a time.
> For one, device assignment is not upstream at all.

The point being, we'll know what's the best way to implement
extended memory space when we see some code using it.


> By the way, a general question: how was this tested?  Did you manage to
> make guest generate mmconfig transactions?  Which guests do this?
> 
> > -- 
> > yamahata

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

* [Qemu-devel] Re: [PATCH v4 00/23] pci: various pci clean up and pci express support.
  2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (24 preceding siblings ...)
  2009-10-05 13:34 ` Michael S. Tsirkin
@ 2009-10-06 14:40 ` Michael S. Tsirkin
  2009-10-07  2:29   ` Isaku Yamahata
  25 siblings, 1 reply; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-06 14:40 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 07:06:40PM +0900, Isaku Yamahata wrote:
> Thanks to Michael's review, patches have been much improved
> and became much readable.

So I think the following are definitely ready to be merged.  I'll stick them on
my pci tree, this way we won't get conflicts.  OK?

pci: use helper functions to access config space
pci: helper functions to access PCIDevice::config
pci: define a constant to represent a unmapped bar and use it.
pci: use PCI_SLOT() and PCI_FUNC().
pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4.
pci: fix PCI_DPRINTF() wrt variadic macro.

-- 
MST

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

* [Qemu-devel] Re: [PATCH 16/23] pci: pcie host and mmcfg support.
  2009-10-06 13:21         ` Michael S. Tsirkin
@ 2009-10-07  2:25           ` Isaku Yamahata
  2009-10-07 12:17             ` Michael S. Tsirkin
  0 siblings, 1 reply; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-07  2:25 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Tue, Oct 06, 2009 at 03:21:38PM +0200, Michael S. Tsirkin wrote:
> On Tue, Oct 06, 2009 at 12:57:01PM +0200, Michael S. Tsirkin wrote:
> > On Tue, Oct 06, 2009 at 07:02:59PM +0900, Isaku Yamahata wrote:
> > > On Mon, Oct 05, 2009 at 01:41:21PM +0200, Michael S. Tsirkin wrote:
> > > > On Mon, Oct 05, 2009 at 07:06:56PM +0900, Isaku Yamahata wrote:
> > > > > @@ -1052,9 +1242,10 @@ PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
> > > > >  
> > > > >  static int pci_find_space(PCIDevice *pdev, uint8_t size)
> > > > >  {
> > > > > +    int config_size = pcie_config_size(pdev);
> > > > >      int offset = PCI_CONFIG_HEADER_SIZE;
> > > > >      int i;
> > > > > -    for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i)
> > > > > +    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
> > > > >          if (pdev->used[i])
> > > > >              offset = i + 1;
> > > > >          else if (i - offset + 1 == size)
> > > > > diff --git a/hw/pci.h b/hw/pci.h
> > > > > index 00f2b78..1f402d2 100644
> > > > > --- a/hw/pci.h
> > > > > +++ b/hw/pci.h
> > > > > @@ -175,20 +175,26 @@ enum {
> > > > >      QEMU_PCI_CAP_MSIX = 0x1,
> > > > >  };
> > > > >  
> > > > > +/* Size of the standart PCIe config space: 4KB */
> > > > > +#define PCIE_CONFIG_SPACE_SIZE  0x1000
> > > > > +#define PCIE_EXT_CONFIG_SPACE_SIZE                      \
> > > > > +    (PCIE_CONFIG_SPACE_SIZE - PCI_CONFIG_SPACE_SIZE)
> > > > > +
> > > > >  struct PCIDevice {
> > > > >      DeviceState qdev;
> > > > > +
> > > > >      /* PCI config space */
> > > > > -    uint8_t config[PCI_CONFIG_SPACE_SIZE];
> > > > > +    uint8_t *config;
> > > > >  
> > > > >      /* Used to enable config checks on load. Note that writeable bits are
> > > > >       * never checked even if set in cmask. */
> > > > > -    uint8_t cmask[PCI_CONFIG_SPACE_SIZE];
> > > > > +    uint8_t *cmask;
> > > > >  
> > > > >      /* Used to implement R/W bytes */
> > > > > -    uint8_t wmask[PCI_CONFIG_SPACE_SIZE];
> > > > > +    uint8_t *wmask;
> > > > >  
> > > > >      /* Used to allocate config space for capabilities. */
> > > > > -    uint8_t used[PCI_CONFIG_SPACE_SIZE];
> > > > > +    uint8_t *used;
> > > > >  
> > > > >      /* the following fields are read only */
> > > > >      PCIBus *bus;
> > > > 
> > > > 
> > > > So I thought about this some more, and I think that this change
> > > > in unnecessary. PCI Express adds support for extended 4K
> > > > configuration space, but the only thing that must reside
> > > > there is the optional advanced error reporting capability,
> > > > which I don't think we'll need to implement, ever.
> > > >
> > > > Everything else can reside in the first 256 bytes, just as for regular
> > > > PCI. And pci code already returns 0 for accesses outside the first 256
> > > > bytes, so express specific code is necessary.
> > > 
> > > I agree with you for emulated PCI express device
> > > (which doesn't exist for now). However I oppose it for other reason.
> > > 
> > > My purpose is to direct attach PCIe device to a guest including
> > > AER emulation somehow.
> > 
> > For now, if I were you, I would just ignore AER.
>
> > > When direct attaching PCIe native device to a guest,
> > > we don't have any control on how its configuration space is used.
> > > When an error is reported on host via AER, I'd like to pass 
> > > the error to guest in some manner. So I want AER too in a sense.
> > 
> > Since what you will want to do is forward stuff to a physical device,
> > you likely won't need to keep anything in memory at all.
> > So express code might just do
> > 	if (offset > 256)
> > 		write_to_physical_device();
> > But, let's take these things one at a time.
> > For one, device assignment is not upstream at all.
> 
> The point being, we'll know what's the best way to implement
> extended memory space when we see some code using it.

The above code doesn't work.
Some bits in configuration space must be virtualized, it means that
virtualized value must be stored in memory.
Limiting 256 bytes would just make unnecessary complication.
We have to add many hooks like if (offset > 256) call_express_code()
and the express code would be almost same as pci one.
We've already had direct attached code. The difference for pci express 
direct attach from pci direct attach is just that the code receives offset
in configuration space which might be greater than 255.


> > By the way, a general question: how was this tested?  Did you manage to
> > make guest generate mmconfig transactions?  Which guests do this?

Yes, I've tested MMCONFIG access by patching linux kernel as stated in
patch description in PATCH 0.
-- 
yamahata

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

* [Qemu-devel] Re: [PATCH v4 00/23] pci: various pci clean up and pci express support.
  2009-10-06 14:40 ` Michael S. Tsirkin
@ 2009-10-07  2:29   ` Isaku Yamahata
  0 siblings, 0 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-07  2:29 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Tue, Oct 06, 2009 at 04:40:43PM +0200, Michael S. Tsirkin wrote:
> On Mon, Oct 05, 2009 at 07:06:40PM +0900, Isaku Yamahata wrote:
> > Thanks to Michael's review, patches have been much improved
> > and became much readable.
> 
> So I think the following are definitely ready to be merged.  I'll stick them on
> my pci tree, this way we won't get conflicts.  OK?

Okay.
I'll reorder the patches such that they are the first part as [1-6]/N.

> pci: use helper functions to access config space
> pci: helper functions to access PCIDevice::config
> pci: define a constant to represent a unmapped bar and use it.
> pci: use PCI_SLOT() and PCI_FUNC().
> pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4.
> pci: fix PCI_DPRINTF() wrt variadic macro.
> 

-- 
yamahata

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

* [Qemu-devel] Re: [PATCH v4 00/23] pci: various pci clean up and pci express support.
  2009-10-05 13:34 ` Michael S. Tsirkin
@ 2009-10-07  2:30   ` Isaku Yamahata
  0 siblings, 0 replies; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-07  2:30 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 03:34:46PM +0200, Michael S. Tsirkin wrote:
> > Subject: Re: [PATCH v4 00/23] pci: various pci clean up
> 
> Could you please add version prefix to all patches?
> As it is, once I'm deep in a thread, I don't really
> know whether I'm looking at the latest patch version anymore.

Yes, I'll use git format-patch --subject-prefix="PATCH vN".

-- 
yamahata

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

* Re: [Qemu-devel] Re: [PATCH 16/23] pci: pcie host and mmcfg support.
  2009-10-06 10:02     ` Isaku Yamahata
  2009-10-06 10:57       ` Michael S. Tsirkin
@ 2009-10-07 11:30       ` Akio Takebe
  1 sibling, 0 replies; 62+ messages in thread
From: Akio Takebe @ 2009-10-07 11:30 UTC (permalink / raw)
  To: Isaku Yamahata, Michael S. Tsirkin; +Cc: qemu-devel

>> So I thought about this some more, and I think that this change
>> in unnecessary. PCI Express adds support for extended 4K
>> configuration space, but the only thing that must reside
>> there is the optional advanced error reporting capability,
>> which I don't think we'll need to implement, ever.
>>
>> Everything else can reside in the first 256 bytes, just as for regular
>> PCI. And pci code already returns 0 for accesses outside the first 256
>> bytes, so express specific code is necessary.
>
>I agree with you for emulated PCI express device
>(which doesn't exist for now). However I oppose it for other reason.
>
>My purpose is to direct attach PCIe device to a guest including
>AER emulation somehow.
>When direct attaching PCIe native device to a guest,
>we don't have any control on how its configuration space is used.
>When an error is reported on host via AER, I'd like to pass 
>the error to guest in some manner. So I want AER too in a sense.
I also want AER feature. In this PCIe emulator codes,
PCIe features like AER is highlight.
If we can use AER, this pcie emulator is very worthwhile, I think.

Best Regards,

Akio Takebe

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

* [Qemu-devel] Re: [PATCH 16/23] pci: pcie host and mmcfg support.
  2009-10-07  2:25           ` Isaku Yamahata
@ 2009-10-07 12:17             ` Michael S. Tsirkin
  0 siblings, 0 replies; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-07 12:17 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Wed, Oct 07, 2009 at 11:25:46AM +0900, Isaku Yamahata wrote:
> The above code doesn't work.
> Some bits in configuration space must be virtualized, it means that
> virtualized value must be stored in memory.
> Limiting 256 bytes would just make unnecessary complication.
> We have to add many hooks like if (offset > 256) call_express_code()
> and the express code would be almost same as pci one.
> We've already had direct attached code. The difference for pci express 
> direct attach from pci direct attach is just that the code receives offset
> in configuration space which might be greater than 255.

Okay. What I mainly disliked is the complex update routines.  But I
found a way to get rid of them without limiting ourselves to 256 bytes
size: in fact, we only need to save the first 64 bytes for default
config callback, whatever the full config space size is.

Since this is a single cache line, it won't get any more efficient,
and we can use simple memcmp to check for bar changes etc.

Patch soon, please review and let me know.

-- 
MST

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

* [Qemu-devel] Re: [PATCH 20/23] pci: make bar update function aware of pci bridge.
  2009-10-05 11:59   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-09  3:27     ` Isaku Yamahata
  2009-10-10 20:20       ` Michael S. Tsirkin
  0 siblings, 1 reply; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-09  3:27 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Mon, Oct 05, 2009 at 01:59:51PM +0200, Michael S. Tsirkin wrote:
> On Mon, Oct 05, 2009 at 07:07:00PM +0900, Isaku Yamahata wrote:
> > header type of 01 has differenct BAR to type 00.
> > It has only BAR0,1 and expantion rom whose offset address
> > is different from type 00 one.
> > 
> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> 
> The existing code is actually correct, and I think this breaks it.  I
> think it's a good idea to add pci_bar_config_offset, though.
> Split this up to a separate patch?
> 
> > ---
> >  hw/pci.c |   56 +++++++++++++++++++++++++++++++++++++++++++++-----------
> >  hw/pci.h |    2 ++
> >  2 files changed, 47 insertions(+), 11 deletions(-)
> > 
> > diff --git a/hw/pci.c b/hw/pci.c
> > index b8d2f8f..af864c6 100644
> > --- a/hw/pci.c
> > +++ b/hw/pci.c
> > @@ -505,6 +505,33 @@ static inline int pci_bar_is_mem64(const PCIIORegion *r)
> >          PCI_ADDRESS_SPACE_MEM_TYPE_64;
> >  }
> >  
> > +/*
> > + * return offset in pci configuration space for a given BAR of region_num.
> > + * header type
> > + * normal  = 0: bar 0-5 and rom
> > + * bridge  = 1: bar 0,1 and rom
> > + * cardbus = 2: bar 0
> > + */
> > +static uint32_t pci_bar_config_offset(PCIDevice *d, int region_num)
> > +{
> > +    uint8_t header_type =
> > +        d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
> > +
> > +    assert((header_type == PCI_HEADER_TYPE_NORMAL &&
> > +            ((0 <= region_num && region_num < 6) ||
> > +             region_num == PCI_ROM_SLOT)) ||
> 
> && already binds stronger than ||, so don't put () around &&

gcc wants parens like
hw/pci.c:531: error: suggest parentheses around && within ||
note:qemu configure script enables -Werror by defaults.


> > +           (header_type == PCI_HEADER_TYPE_BRIDGE &&
> > +            ((0 <= region_num && region_num < 2) ||
> > +             region_num == PCI_ROM_SLOT)) ||
> > +           (header_type == PCI_HEADER_TYPE_CARDBUS && region_num == 0));
> 
> This is not the best place to put assertions.
> If you really need them, pci_register_bar is a better place.
> 
> > +
> > +    if (region_num != PCI_ROM_ADDRESS)
> > +        return PCI_BASE_ADDRESS_0 + region_num * 4;
> 
> BTW, how does it work for 64 bit regions?
> 
> > +
> > +    return header_type == PCI_HEADER_TYPE_BRIDGE?
> > +        PCI_ROM_ADDRESS1: PCI_ROM_ADDRESS;
> 
> space before :
> 
> > +}
> > +
> >  void pci_register_bar(PCIDevice *pci_dev, int region_num,
> >                              pcibus_t size, int type,
> >                              PCIMapIORegionFunc *map_func)
> > @@ -528,13 +555,11 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
> >      r->type = type;
> >      r->map_func = map_func;
> >  
> > +    addr = pci_bar_config_offset(pci_dev, region_num);
> >      wmask = ~(size - 1);
> >      if (region_num == PCI_ROM_SLOT) {
> > -        addr = 0x30;
> >          /* ROM enable bit is writeable */
> >          wmask |= PCI_ROM_ADDRESS_ENABLE;
> > -    } else {
> > -        addr = 0x10 + region_num * 4;
> >      }
> >      pci_set_long(pci_dev->config + addr, type);
> >      if (pci_bar_is_mem64(r)) {
> > @@ -556,11 +581,7 @@ static void pci_update_mappings(PCIDevice *d)
> >      cmd = pci_get_word(d->config + PCI_COMMAND);
> >      for(i = 0; i < PCI_NUM_REGIONS; i++) {
> >          r = &d->io_regions[i];
> > -        if (i == PCI_ROM_SLOT) {
> > -            config_ofs = 0x30;
> > -        } else {
> > -            config_ofs = 0x10 + i * 4;
> > -        }
> > +        config_ofs = pci_bar_config_offset(d, i);
> >          if (r->size != 0) {
> >              if (r->type & PCI_ADDRESS_SPACE_IO) {
> >                  if (cmd & PCI_COMMAND_IO) {
> > @@ -1123,10 +1144,23 @@ static void pci_bridge_write_config(PCIDevice *d,
> >                               uint32_t address, uint32_t val, int len)
> >  {
> >      PCIBridge *s = (PCIBridge *)d;
> > +    PCIBus *bus = s->bus;
> > +    struct pci_config_update update;
> >  
> > -    pci_default_write_config(d, address, val, len);
> > -    s->bus->bus_num = d->config[PCI_SECONDARY_BUS];
> > -    s->bus->sub_bus = d->config[PCI_SUBORDINATE_BUS];
> > +    pci_write_config_init(&update, d, address, val, len);
> > +    pci_write_config_update(&update);
> > +    if (pci_config_changed(&update,
> > +                           PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_2 + 4) ||
> > +        pci_config_changed_with_size(&update, PCI_ROM_ADDRESS1, 4) ||
> > +        pci_config_changed_with_size(&update, PCI_COMMAND, 1)) {
> > +        pci_update_mappings(d);
> > +    }
> 
> This is wrong I think. You must also take into account memory
> base/limit registers, and redo mapping when these change.
> If you do, you should note several things:
> - BARs for devices placed behind a bridge who's memory
>   is outside the bridge base/limit are effectively disabled.

I deliberately didn't implemented bridge io/memory filtering
because linux doesn't depend on it. I'll add some comment on this.
Linux boots happily without filtering emulation.
However Linux was confused without correct emulation of
reading/writing to/from base/limit. so wmask needs to be initialized.

If other OS needs filtering emulation, it will be implemented.
I don't know other OSes. Especially windows.
I suppose Solaris doesn't because apb_pci.c uses bridge.


> - Base addresses for pci devices overlap base/limit for
>   bridge. For this reason, default_write_config
>   was already doing the right thing, doing update
>   when the bridge base/limit are changed.

I don't understand "the right thing" that the old code is doing
and don't understand why the patch is wrong.

BAR0 or BAR1 case:
Okay. pci_default_write_config() properly update BAR0/1 mappings.

BAR2-5 case = memory/io base/limit case,:
pci_default_write_config() calls pci_update_mapping(),
but pci_update_mapping() does nothing because bar 2 - 5 must not registered.
It's just overhead to do nothing.

PCI_ROM_ADDRESS = IO base/limit upper 16 case:
If the bug is fixed, pci_default_write_config() calls pci_update_mapping().
but it does nothing.

PCI_ROM_ADDRESS1 case
And when PCI_ROM_ADDRESS1 (!= PCI_ROM_ADDRESS) is changed,
pci_update_mapping() should be called. but pci_default_write_config() doesn't.




> > +    if (pci_config_changed_with_size(&update, PCI_SECONDARY_BUS, 1)) {
> > +        bus->bus_num = d->config[PCI_SECONDARY_BUS];
> > +    }
> > +    if (pci_config_changed_with_size(&update, PCI_SUBORDINATE_BUS, 1)) {
> > +        bus->sub_bus = d->config[PCI_SUBORDINATE_BUS];
> > +    }
> >  }
> >  
> >  PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
> > diff --git a/hw/pci.h b/hw/pci.h
> > index 37c2c23..1d45437 100644
> > --- a/hw/pci.h
> > +++ b/hw/pci.h
> > @@ -118,6 +118,7 @@ typedef struct PCIIORegion {
> >  #define  PCI_HEADER_TYPE_CARDBUS	2
> >  #define  PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
> >  #define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
> > +#define PCI_BASE_ADDRESS_2	0x18	/* 32 bits */
> >  #define PCI_BASE_ADDRESS_5	0x24	/* 32 bits */
> >  #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
> >  #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
> > @@ -163,6 +164,7 @@ typedef struct PCIIORegion {
> >  
> >  /* Header type 1 (PCI-to-PCI bridges) */
> >  #define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
> > +#define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
> >  
> >  /* Size of the standard PCI config header */
> >  #define PCI_CONFIG_HEADER_SIZE 0x40
> 

-- 
yamahata

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

* [Qemu-devel] Re: [PATCH 20/23] pci: make bar update function aware of pci bridge.
  2009-10-09  3:27     ` Isaku Yamahata
@ 2009-10-10 20:20       ` Michael S. Tsirkin
  2009-10-13 15:14         ` Isaku Yamahata
  0 siblings, 1 reply; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-10 20:20 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 12:27:35PM +0900, Isaku Yamahata wrote:
> On Mon, Oct 05, 2009 at 01:59:51PM +0200, Michael S. Tsirkin wrote:
> > On Mon, Oct 05, 2009 at 07:07:00PM +0900, Isaku Yamahata wrote:
> > > header type of 01 has differenct BAR to type 00.
> > > It has only BAR0,1 and expantion rom whose offset address
> > > is different from type 00 one.
> > > 
> > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > 
> > The existing code is actually correct, and I think this breaks it.  I
> > think it's a good idea to add pci_bar_config_offset, though.
> > Split this up to a separate patch?
> > 
> > > ---
> > >  hw/pci.c |   56 +++++++++++++++++++++++++++++++++++++++++++++-----------
> > >  hw/pci.h |    2 ++
> > >  2 files changed, 47 insertions(+), 11 deletions(-)
> > > 
> > > diff --git a/hw/pci.c b/hw/pci.c
> > > index b8d2f8f..af864c6 100644
> > > --- a/hw/pci.c
> > > +++ b/hw/pci.c
> > > @@ -505,6 +505,33 @@ static inline int pci_bar_is_mem64(const PCIIORegion *r)
> > >          PCI_ADDRESS_SPACE_MEM_TYPE_64;
> > >  }
> > >  
> > > +/*
> > > + * return offset in pci configuration space for a given BAR of region_num.
> > > + * header type
> > > + * normal  = 0: bar 0-5 and rom
> > > + * bridge  = 1: bar 0,1 and rom
> > > + * cardbus = 2: bar 0
> > > + */
> > > +static uint32_t pci_bar_config_offset(PCIDevice *d, int region_num)
> > > +{
> > > +    uint8_t header_type =
> > > +        d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
> > > +
> > > +    assert((header_type == PCI_HEADER_TYPE_NORMAL &&
> > > +            ((0 <= region_num && region_num < 6) ||
> > > +             region_num == PCI_ROM_SLOT)) ||
> > 
> > && already binds stronger than ||, so don't put () around &&
> 
> gcc wants parens like
> hw/pci.c:531: error: suggest parentheses around && within ||
> note:qemu configure script enables -Werror by defaults.

I see.

> 
> > > +           (header_type == PCI_HEADER_TYPE_BRIDGE &&
> > > +            ((0 <= region_num && region_num < 2) ||
> > > +             region_num == PCI_ROM_SLOT)) ||
> > > +           (header_type == PCI_HEADER_TYPE_CARDBUS && region_num == 0));
> > 
> > This is not the best place to put assertions.
> > If you really need them, pci_register_bar is a better place.
> > 
> > > +
> > > +    if (region_num != PCI_ROM_ADDRESS)
> > > +        return PCI_BASE_ADDRESS_0 + region_num * 4;
> > 
> > BTW, how does it work for 64 bit regions?
> > 
> > > +
> > > +    return header_type == PCI_HEADER_TYPE_BRIDGE?
> > > +        PCI_ROM_ADDRESS1: PCI_ROM_ADDRESS;
> > 
> > space before :
> > 
> > > +}
> > > +
> > >  void pci_register_bar(PCIDevice *pci_dev, int region_num,
> > >                              pcibus_t size, int type,
> > >                              PCIMapIORegionFunc *map_func)
> > > @@ -528,13 +555,11 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
> > >      r->type = type;
> > >      r->map_func = map_func;
> > >  
> > > +    addr = pci_bar_config_offset(pci_dev, region_num);
> > >      wmask = ~(size - 1);
> > >      if (region_num == PCI_ROM_SLOT) {
> > > -        addr = 0x30;
> > >          /* ROM enable bit is writeable */
> > >          wmask |= PCI_ROM_ADDRESS_ENABLE;
> > > -    } else {
> > > -        addr = 0x10 + region_num * 4;
> > >      }
> > >      pci_set_long(pci_dev->config + addr, type);
> > >      if (pci_bar_is_mem64(r)) {
> > > @@ -556,11 +581,7 @@ static void pci_update_mappings(PCIDevice *d)
> > >      cmd = pci_get_word(d->config + PCI_COMMAND);
> > >      for(i = 0; i < PCI_NUM_REGIONS; i++) {
> > >          r = &d->io_regions[i];
> > > -        if (i == PCI_ROM_SLOT) {
> > > -            config_ofs = 0x30;
> > > -        } else {
> > > -            config_ofs = 0x10 + i * 4;
> > > -        }
> > > +        config_ofs = pci_bar_config_offset(d, i);
> > >          if (r->size != 0) {
> > >              if (r->type & PCI_ADDRESS_SPACE_IO) {
> > >                  if (cmd & PCI_COMMAND_IO) {
> > > @@ -1123,10 +1144,23 @@ static void pci_bridge_write_config(PCIDevice *d,
> > >                               uint32_t address, uint32_t val, int len)
> > >  {
> > >      PCIBridge *s = (PCIBridge *)d;
> > > +    PCIBus *bus = s->bus;
> > > +    struct pci_config_update update;
> > >  
> > > -    pci_default_write_config(d, address, val, len);
> > > -    s->bus->bus_num = d->config[PCI_SECONDARY_BUS];
> > > -    s->bus->sub_bus = d->config[PCI_SUBORDINATE_BUS];
> > > +    pci_write_config_init(&update, d, address, val, len);
> > > +    pci_write_config_update(&update);
> > > +    if (pci_config_changed(&update,
> > > +                           PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_2 + 4) ||
> > > +        pci_config_changed_with_size(&update, PCI_ROM_ADDRESS1, 4) ||
> > > +        pci_config_changed_with_size(&update, PCI_COMMAND, 1)) {
> > > +        pci_update_mappings(d);
> > > +    }
> > 
> > This is wrong I think. You must also take into account memory
> > base/limit registers, and redo mapping when these change.
> > If you do, you should note several things:
> > - BARs for devices placed behind a bridge who's memory
> >   is outside the bridge base/limit are effectively disabled.
> 
> I deliberately didn't implemented bridge io/memory filtering
> because linux doesn't depend on it. I'll add some comment on this.
> Linux boots happily without filtering emulation.
> However Linux was confused without correct emulation of
> reading/writing to/from base/limit. so wmask needs to be initialized.
> 
> If other OS needs filtering emulation, it will be implemented.
> I don't know other OSes. Especially windows.
> I suppose Solaris doesn't because apb_pci.c uses bridge.

Filtering is the only way to disable e.g. prefetchable memory in a
bridge accoring to PCI spec, and I know that some BIOSes take advantage
of this. Frankly, I think we should just try and stick to spec.
It's not hard at all.

> > - Base addresses for pci devices overlap base/limit for
> >   bridge. For this reason, default_write_config
> >   was already doing the right thing, doing update
> >   when the bridge base/limit are changed.
> 
> I don't understand "the right thing" that the old code is doing
> and don't understand why the patch is wrong.

The patch is wrong in that it does not implement filtering.
As you show below, handling for PCI_ROM_ADDRESS1 is missing,
let's fix that, it's a single line change.

> BAR0 or BAR1 case:
> Okay. pci_default_write_config() properly update BAR0/1 mappings.
> 
> BAR2-5 case = memory/io base/limit case,:
> pci_default_write_config() calls pci_update_mapping(),
> but pci_update_mapping() does nothing because bar 2 - 5 must not registered.
> It's just overhead to do nothing.
> 
> PCI_ROM_ADDRESS = IO base/limit upper 16 case:
> If the bug is fixed, pci_default_write_config() calls pci_update_mapping().
> but it does nothing.
> 
> PCI_ROM_ADDRESS1 case
> And when PCI_ROM_ADDRESS1 (!= PCI_ROM_ADDRESS) is changed,
> pci_update_mapping() should be called. but pci_default_write_config() doesn't.
> 

Ah, I see. Let's just teach default_config_write to
call pci_update_mapping when PCI_ROM_ADDRESS1 is changed.
For regular devices this does no harm.

> 
> 
> > > +    if (pci_config_changed_with_size(&update, PCI_SECONDARY_BUS, 1)) {
> > > +        bus->bus_num = d->config[PCI_SECONDARY_BUS];
> > > +    }
> > > +    if (pci_config_changed_with_size(&update, PCI_SUBORDINATE_BUS, 1)) {
> > > +        bus->sub_bus = d->config[PCI_SUBORDINATE_BUS];
> > > +    }
> > >  }
> > >  
> > >  PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
> > > diff --git a/hw/pci.h b/hw/pci.h
> > > index 37c2c23..1d45437 100644
> > > --- a/hw/pci.h
> > > +++ b/hw/pci.h
> > > @@ -118,6 +118,7 @@ typedef struct PCIIORegion {
> > >  #define  PCI_HEADER_TYPE_CARDBUS	2
> > >  #define  PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
> > >  #define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
> > > +#define PCI_BASE_ADDRESS_2	0x18	/* 32 bits */
> > >  #define PCI_BASE_ADDRESS_5	0x24	/* 32 bits */
> > >  #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
> > >  #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
> > > @@ -163,6 +164,7 @@ typedef struct PCIIORegion {
> > >  
> > >  /* Header type 1 (PCI-to-PCI bridges) */
> > >  #define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
> > > +#define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
> > >  
> > >  /* Size of the standard PCI config header */
> > >  #define PCI_CONFIG_HEADER_SIZE 0x40
> > 
> 
> -- 
> yamahata

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

* [Qemu-devel] Re: [PATCH 20/23] pci: make bar update function aware of pci bridge.
  2009-10-10 20:20       ` Michael S. Tsirkin
@ 2009-10-13 15:14         ` Isaku Yamahata
  2009-10-13 15:22           ` Michael S. Tsirkin
  0 siblings, 1 reply; 62+ messages in thread
From: Isaku Yamahata @ 2009-10-13 15:14 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Sat, Oct 10, 2009 at 10:20:36PM +0200, Michael S. Tsirkin wrote:
> > > > @@ -1123,10 +1144,23 @@ static void pci_bridge_write_config(PCIDevice *d,
> > > >                               uint32_t address, uint32_t val, int len)
> > > >  {
> > > >      PCIBridge *s = (PCIBridge *)d;
> > > > +    PCIBus *bus = s->bus;
> > > > +    struct pci_config_update update;
> > > >  
> > > > -    pci_default_write_config(d, address, val, len);
> > > > -    s->bus->bus_num = d->config[PCI_SECONDARY_BUS];
> > > > -    s->bus->sub_bus = d->config[PCI_SUBORDINATE_BUS];
> > > > +    pci_write_config_init(&update, d, address, val, len);
> > > > +    pci_write_config_update(&update);
> > > > +    if (pci_config_changed(&update,
> > > > +                           PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_2 + 4) ||
> > > > +        pci_config_changed_with_size(&update, PCI_ROM_ADDRESS1, 4) ||
> > > > +        pci_config_changed_with_size(&update, PCI_COMMAND, 1)) {
> > > > +        pci_update_mappings(d);
> > > > +    }
> > > 
> > > This is wrong I think. You must also take into account memory
> > > base/limit registers, and redo mapping when these change.
> > > If you do, you should note several things:
> > > - BARs for devices placed behind a bridge who's memory
> > >   is outside the bridge base/limit are effectively disabled.
> > 
> > I deliberately didn't implemented bridge io/memory filtering
> > because linux doesn't depend on it. I'll add some comment on this.
> > Linux boots happily without filtering emulation.
> > However Linux was confused without correct emulation of
> > reading/writing to/from base/limit. so wmask needs to be initialized.
> > 
> > If other OS needs filtering emulation, it will be implemented.
> > I don't know other OSes. Especially windows.
> > I suppose Solaris doesn't because apb_pci.c uses bridge.
> 
> Filtering is the only way to disable e.g. prefetchable memory in a
> bridge accoring to PCI spec, and I know that some BIOSes take advantage
> of this. Frankly, I think we should just try and stick to spec.
> It's not hard at all.

BIOS for real hardware? 
At least pcbios and seabios doesn't, so the above doesn't make sense.
Implementing filtering would be another story.
-- 
yamahata

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

* [Qemu-devel] Re: [PATCH 20/23] pci: make bar update function aware of pci bridge.
  2009-10-13 15:14         ` Isaku Yamahata
@ 2009-10-13 15:22           ` Michael S. Tsirkin
  0 siblings, 0 replies; 62+ messages in thread
From: Michael S. Tsirkin @ 2009-10-13 15:22 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Wed, Oct 14, 2009 at 12:14:17AM +0900, Isaku Yamahata wrote:
> On Sat, Oct 10, 2009 at 10:20:36PM +0200, Michael S. Tsirkin wrote:
> > > > > @@ -1123,10 +1144,23 @@ static void pci_bridge_write_config(PCIDevice *d,
> > > > >                               uint32_t address, uint32_t val, int len)
> > > > >  {
> > > > >      PCIBridge *s = (PCIBridge *)d;
> > > > > +    PCIBus *bus = s->bus;
> > > > > +    struct pci_config_update update;
> > > > >  
> > > > > -    pci_default_write_config(d, address, val, len);
> > > > > -    s->bus->bus_num = d->config[PCI_SECONDARY_BUS];
> > > > > -    s->bus->sub_bus = d->config[PCI_SUBORDINATE_BUS];
> > > > > +    pci_write_config_init(&update, d, address, val, len);
> > > > > +    pci_write_config_update(&update);
> > > > > +    if (pci_config_changed(&update,
> > > > > +                           PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_2 + 4) ||
> > > > > +        pci_config_changed_with_size(&update, PCI_ROM_ADDRESS1, 4) ||
> > > > > +        pci_config_changed_with_size(&update, PCI_COMMAND, 1)) {
> > > > > +        pci_update_mappings(d);
> > > > > +    }
> > > > 
> > > > This is wrong I think. You must also take into account memory
> > > > base/limit registers, and redo mapping when these change.
> > > > If you do, you should note several things:
> > > > - BARs for devices placed behind a bridge who's memory
> > > >   is outside the bridge base/limit are effectively disabled.
> > > 
> > > I deliberately didn't implemented bridge io/memory filtering
> > > because linux doesn't depend on it. I'll add some comment on this.
> > > Linux boots happily without filtering emulation.
> > > However Linux was confused without correct emulation of
> > > reading/writing to/from base/limit. so wmask needs to be initialized.
> > > 
> > > If other OS needs filtering emulation, it will be implemented.
> > > I don't know other OSes. Especially windows.
> > > I suppose Solaris doesn't because apb_pci.c uses bridge.
> > 
> > Filtering is the only way to disable e.g. prefetchable memory in a
> > bridge accoring to PCI spec, and I know that some BIOSes take advantage
> > of this. Frankly, I think we should just try and stick to spec.
> > It's not hard at all.
> 
> BIOS for real hardware? 
> At least pcbios and seabios doesn't,

At the moment. But why assume things?

> so the above doesn't make sense.
> Implementing filtering would be another story.

What do you call filtering?
I think that all you have to do is
1. scan all child devices on bridge header write,
	and call update
2. when updating regions, check parent bus base/limit registers,
   scanning all bars upwards, and unmap registers that move
   outside the range, map registers that move inside the range.

Where's the difficulty?

> -- 
> yamahata

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

end of thread, other threads:[~2009-10-13 15:24 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-10-05 10:06 [Qemu-devel] [PATCH v4 00/23] pci: various pci clean up and pci express support Isaku Yamahata
2009-10-05 10:06 ` [Qemu-devel] [PATCH 01/23] pci: fix PCI_DPRINTF() wrt variadic macro Isaku Yamahata
2009-10-05 10:06 ` [Qemu-devel] [PATCH 02/23] pci: use appropriate PRIs in PCI_DPRINTF() for portability Isaku Yamahata
2009-10-05 10:06 ` [Qemu-devel] [PATCH 03/23] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4 Isaku Yamahata
2009-10-05 10:06 ` [Qemu-devel] [PATCH 04/23] pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1 Isaku Yamahata
2009-10-05 10:06 ` [Qemu-devel] [PATCH 05/23] pci: use PCI_SLOT() and PCI_FUNC() Isaku Yamahata
2009-10-05 10:06 ` [Qemu-devel] [PATCH 06/23] pci: define a constant to represent a unmapped bar and use it Isaku Yamahata
2009-10-05 10:06 ` [Qemu-devel] [PATCH 07/23] pci: helper functions to access PCIDevice::config Isaku Yamahata
2009-10-05 10:06 ` [Qemu-devel] [PATCH 08/23] pci: use helper functions to access pci config space Isaku Yamahata
2009-10-05 10:06 ` [Qemu-devel] [PATCH 09/23] pci: introduce pcibus_t to represent pci bus address/size instead of uint32_t Isaku Yamahata
2009-10-05 10:06 ` [Qemu-devel] [PATCH 10/23] pci: introduce FMT_PCIBUS for printf format for pcibus_t Isaku Yamahata
2009-10-05 13:41   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-05 10:06 ` [Qemu-devel] [PATCH 11/23] pci: typedef pcibus_t as uint64_t instead of uint32_t Isaku Yamahata
2009-10-05 20:18   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-05 10:06 ` [Qemu-devel] [PATCH 12/23] pci: 64bit bar support Isaku Yamahata
2009-10-05 12:06   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-06  9:38     ` Isaku Yamahata
2009-10-06  9:43       ` Michael S. Tsirkin
2009-10-05 12:47   ` Michael S. Tsirkin
2009-10-06  9:42     ` Isaku Yamahata
2009-10-06  9:47       ` Michael S. Tsirkin
2009-10-05 10:06 ` [Qemu-devel] [PATCH 13/23] pci: make pci configuration transaction more accurate Isaku Yamahata
2009-10-05 12:26   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-05 10:06 ` [Qemu-devel] [PATCH 14/23] pci: factor out the logic to get pci device from address Isaku Yamahata
2009-10-05 12:45   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-06  9:50     ` Isaku Yamahata
2009-10-06 10:23       ` Michael S. Tsirkin
2009-10-05 10:06 ` [Qemu-devel] [PATCH 15/23] pci_host.h: split non-inline static function in pci_host.h into pci_host.c Isaku Yamahata
2009-10-05 14:35   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-05 14:37     ` Michael S. Tsirkin
2009-10-05 10:06 ` [Qemu-devel] [PATCH 16/23] pci: pcie host and mmcfg support Isaku Yamahata
2009-10-05 11:01   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-06  8:48     ` Isaku Yamahata
2009-10-06  9:30       ` Michael S. Tsirkin
2009-10-05 11:41   ` Michael S. Tsirkin
2009-10-06 10:02     ` Isaku Yamahata
2009-10-06 10:57       ` Michael S. Tsirkin
2009-10-06 13:21         ` Michael S. Tsirkin
2009-10-07  2:25           ` Isaku Yamahata
2009-10-07 12:17             ` Michael S. Tsirkin
2009-10-07 11:30       ` Akio Takebe
2009-10-05 10:06 ` [Qemu-devel] [PATCH 17/23] pci: fix pci_default_write_config() Isaku Yamahata
2009-10-05 10:06 ` [Qemu-devel] [PATCH 18/23] pci: add helper functions for pci config write function Isaku Yamahata
2009-10-05 10:06 ` [Qemu-devel] [PATCH 19/23] pci: use helper function in pci_default_write_config() Isaku Yamahata
2009-10-05 10:07 ` [Qemu-devel] [PATCH 20/23] pci: make bar update function aware of pci bridge Isaku Yamahata
2009-10-05 11:59   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-09  3:27     ` Isaku Yamahata
2009-10-10 20:20       ` Michael S. Tsirkin
2009-10-13 15:14         ` Isaku Yamahata
2009-10-13 15:22           ` Michael S. Tsirkin
2009-10-05 10:07 ` [Qemu-devel] [PATCH 21/23] pci/brdige: qdevfy and initialize secondary bus and subordinate bus Isaku Yamahata
2009-10-05 13:49   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-05 14:58   ` Michael S. Tsirkin
2009-10-05 10:07 ` [Qemu-devel] [PATCH 22/23] pci: initialize wmask according to pci header type Isaku Yamahata
2009-10-05 14:09   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-05 10:07 ` [Qemu-devel] [PATCH 23/23] pci/monitor: print out bridge's filtering values and so on Isaku Yamahata
2009-10-05 14:24   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-05 10:14 ` [Qemu-devel] Re: [PATCH v4 00/23] pci: various pci clean up and pci express support Michael S. Tsirkin
2009-10-05 13:34 ` Michael S. Tsirkin
2009-10-07  2:30   ` Isaku Yamahata
2009-10-06 14:40 ` Michael S. Tsirkin
2009-10-07  2:29   ` Isaku Yamahata

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.