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

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.


Now I updated the patches following Michael's comment and implemented
PCI bridge filtering.
Windows xp 32bit installs and boots. I don't see any boot
delay with windows and Linux. Anyway their boot are slow under qemu
so that some increase of code path is noise.

some random comments:
- The patches status is as follows.
  Anthony, is there any way to merge first 11 patches?
  If you want, I'm willing to send patch series which contains only
  first 11 ones. Michael also want it, I suppose.

  1-7,9-11,14,15,22: no change, acked-by Michael.
  13, 16: no change
  12, 17, 19-21, 24, 28,23: changed
  8, 18, 23, 25-27, 29-31: new

- Although I implemented bridge filtering, I don't think of
  how BIOS utilize bridge filtering. 
  Michael, could you please elaborate how BIOS utilses it?
  What usage do you have in your mind?

- & 0xffff is necessary otherwise gcc comains. So I didn't remove it.

thanks,

changes from V5:
- rebased to f7cbc08ff0d712b0febcf84ce8458c3ae30db4fa
- introduced range check helper functions
- removed unnecessary member of PCIBus
- implemented bridge flitering

changes from V4:
- rebased to ad323081aa0e20d3d573ea64e88a893d576c05e0
- reordered patches.
- many clean up
- more consolidation of pci host stuff into pci_host.c
- move pci host stuff to pci_host.c
- move pcie host stuff to pcie_host.c
- introduced QEMU_PCI_CAP_EXPRESS

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 (32):
  pci: fix PCI_DPRINTF() wrt variadic macro.
  pci: introduce constant PCI_NUM_PINS for the number of interrupt
    pins, 4.
  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/bridge: clean up of pci_bridge_initfn()
  pci: clean up pci_init_wmask()
  pci: s/PCI_ADDRESS_SPACE_/PCI_BASE_ADDRESS_SPACE_/ to match
    pci_regs.h
  pci: clean up of pci_default_read_config.
  pci: make pci_bar() aware of header type 1.
  pci_host.h: move functions in pci_host.h into .c file.
  pci_host: consolidate pci config address access.
  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: remove bus_num member from struct PCIBus.
  pci: make pci configuration transaction more accurate.
  pci: factor out the conversion logic from io port address into pci
    device.
  pci: move pci host stuff from pci.c to pci_host.c
  pci_host: change the signature of pci_data_{read, write}.
  vmstate: introduce VMSTATE_BUFFER_UNSAFE_INFO.
  pci: pcie host and mmcfg support.
  pci: add helper functions to check ranges overlap.
  pci: use range helper functions.
  pci: teach pci_default_config_write() ROM bar for normal/bridge
    device .
  pci: initialize pci config headers depending it pci header type.
  pci: cosmetic on pci_upadte_mappings()
  pci: factor out pci_for_each_device().
  pci: implement pci bridge filtering.
  pci/monitor: print out bridge's filtering values and so on.

 Makefile.target                        |    2 +-
 hw/ac97.c                              |    7 +-
 hw/apb_pci.c                           |   72 +---
 hw/cirrus_vga.c                        |   11 +-
 hw/e1000.c                             |   16 +-
 hw/eepro100.c                          |   28 +-
 hw/es1370.c                            |    4 +-
 hw/grackle_pci.c                       |   69 +---
 hw/gt64xxx.c                           |   11 +-
 hw/hw.h                                |   18 +-
 hw/ide/cmd646.c                        |   14 +-
 hw/ide/piix.c                          |    4 +-
 hw/lsi53c895a.c                        |   12 +-
 hw/macio.c                             |    4 +-
 hw/msix.c                              |    2 +-
 hw/msix.h                              |    3 +-
 hw/ne2000.c                            |    4 +-
 hw/openpic.c                           |    4 +-
 hw/pci-hotplug.c                       |    4 +-
 hw/pci.c                               |  805 ++++++++++++++++++++++----------
 hw/pci.h                               |  137 +++++-
 hw/pci_host.c                          |  244 ++++++++++
 hw/pci_host.h                          |   93 +----
 hw/{pci_host.h => pci_host_template.h} |   36 +-
 hw/pcie_host.c                         |  192 ++++++++
 hw/pcie_host.h                         |   50 ++
 hw/pcnet.c                             |   14 +-
 hw/piix_pci.c                          |   26 +-
 hw/ppc4xx_pci.c                        |   18 +-
 hw/ppce500_pci.c                       |   51 +--
 hw/prep_pci.c                          |   24 +-
 hw/rtl8139.c                           |    8 +-
 hw/sun4u.c                             |    6 +-
 hw/unin_pci.c                          |  121 +-----
 hw/usb-ohci.c                          |    4 +-
 hw/usb-uhci.c                          |    4 +-
 hw/vga-pci.c                           |    6 +-
 hw/virtio-pci.c                        |    6 +-
 hw/vmware_vga.c                        |    8 +-
 hw/wdt_i6300esb.c                      |    7 +-
 40 files changed, 1331 insertions(+), 818 deletions(-)
 create mode 100644 hw/pci_host.c
 copy hw/{pci_host.h => pci_host_template.h} (80%)
 create mode 100644 hw/pcie_host.c
 create mode 100644 hw/pcie_host.h

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

* [Qemu-devel] [PATCH V6 01/32] pci: fix PCI_DPRINTF() wrt variadic macro.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
@ 2009-10-30 12:20 ` Isaku Yamahata
  2009-10-30 12:20 ` [Qemu-devel] [PATCH V6 02/32] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4 Isaku Yamahata
                   ` (30 subsequent siblings)
  31 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:20 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 ef134f7..1c95f88 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] 75+ messages in thread

* [Qemu-devel] [PATCH V6 02/32] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
  2009-10-30 12:20 ` [Qemu-devel] [PATCH V6 01/32] pci: fix PCI_DPRINTF() wrt variadic macro Isaku Yamahata
@ 2009-10-30 12:20 ` Isaku Yamahata
  2009-10-30 12:20 ` [Qemu-devel] [PATCH V6 03/32] pci: use PCI_SLOT() and PCI_FUNC() Isaku Yamahata
                   ` (29 subsequent siblings)
  31 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:20 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 1c95f88..e21098b 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -229,7 +229,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()
     }
 };
@@ -389,7 +389,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 93f93fb..476ff59 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -158,6 +158,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,
@@ -192,7 +194,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] 75+ messages in thread

* [Qemu-devel] [PATCH V6 03/32] pci: use PCI_SLOT() and PCI_FUNC().
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
  2009-10-30 12:20 ` [Qemu-devel] [PATCH V6 01/32] pci: fix PCI_DPRINTF() wrt variadic macro Isaku Yamahata
  2009-10-30 12:20 ` [Qemu-devel] [PATCH V6 02/32] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4 Isaku Yamahata
@ 2009-10-30 12:20 ` Isaku Yamahata
  2009-10-30 12:20 ` [Qemu-devel] [PATCH V6 04/32] pci: define a constant to represent a unmapped bar and use it Isaku Yamahata
                   ` (28 subsequent siblings)
  31 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:20 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 43be7ce..1ea3e0d 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -261,11 +261,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 e21098b..ce3329b 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -745,7 +745,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;
@@ -1111,7 +1111,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] 75+ messages in thread

* [Qemu-devel] [PATCH V6 04/32] pci: define a constant to represent a unmapped bar and use it.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (2 preceding siblings ...)
  2009-10-30 12:20 ` [Qemu-devel] [PATCH V6 03/32] pci: use PCI_SLOT() and PCI_FUNC() Isaku Yamahata
@ 2009-10-30 12:20 ` Isaku Yamahata
  2009-10-30 12:20 ` [Qemu-devel] [PATCH V6 05/32] pci: helper functions to access PCIDevice::config Isaku Yamahata
                   ` (27 subsequent siblings)
  31 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:20 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 9dfe76a..04ba68d 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3208,7 +3208,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 ce3329b..00d407d 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -418,7 +418,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);
@@ -466,7 +466,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;
@@ -500,10 +500,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) {
@@ -518,17 +518,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:
@@ -547,7 +547,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 476ff59..bab9cab 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] 75+ messages in thread

* [Qemu-devel] [PATCH V6 05/32] pci: helper functions to access PCIDevice::config
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (3 preceding siblings ...)
  2009-10-30 12:20 ` [Qemu-devel] [PATCH V6 04/32] pci: define a constant to represent a unmapped bar and use it Isaku Yamahata
@ 2009-10-30 12:20 ` Isaku Yamahata
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 06/32] pci: use helper functions to access pci config space Isaku Yamahata
                   ` (26 subsequent siblings)
  31 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:20 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 bab9cab..157995c 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -312,6 +312,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] 75+ messages in thread

* [Qemu-devel] [PATCH V6 06/32] pci: use helper functions to access pci config space.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (4 preceding siblings ...)
  2009-10-30 12:20 ` [Qemu-devel] [PATCH V6 05/32] pci: helper functions to access PCIDevice::config Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 07/32] pci/bridge: clean up of pci_bridge_initfn() Isaku Yamahata
                   ` (25 subsequent siblings)
  31 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 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 |   30 +++++++++++++++---------------
 1 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 00d407d..ab5eff8 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -477,9 +477,9 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
         /* ROM enable bit is writeable */
         wmask |= PCI_ROM_ADDRESS_ENABLE;
     }
-    *(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)
@@ -488,7 +488,7 @@ static void pci_update_mappings(PCIDevice *d)
     int cmd, i;
     uint32_t last_addr, new_addr;
 
-    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 (r->size != 0) {
@@ -564,18 +564,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;
@@ -746,7 +746,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)
@@ -757,8 +757,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",
@@ -1098,7 +1098,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++;
@@ -1112,10 +1112,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] 75+ messages in thread

* [Qemu-devel] [PATCH V6 07/32] pci/bridge: clean up of pci_bridge_initfn()
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (5 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 06/32] pci: use helper functions to access pci config space Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 08/32] pci: clean up pci_init_wmask() Isaku Yamahata
                   ` (24 subsequent siblings)
  31 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

- use symbolic constant
- use helper function pci_set_xxx()
- removed lines which initializes to 0.
  It is unnecessary because it is already zeroed.
- add some comments on command registers.

Some initial values are suspicious because they seems to
be specific to apb_pci.c which is the only user of pci bridge right now.
For now don't touch those values to avoid breakage.

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

diff --git a/hw/pci.c b/hw/pci.c
index ab5eff8..6abb0e2 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -922,17 +922,31 @@ static int pci_bridge_initfn(PCIDevice *dev)
     pci_config_set_vendor_id(s->dev.config, s->vid);
     pci_config_set_device_id(s->dev.config, s->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
+    /* TODO: intial value
+     * command register:
+     * According to PCI bridge spec, after reset
+     *   bus master bit is off
+     *   memory space enable bit is off
+     * According to manual (805-1251.pdf).(See abp_pbi.c for its links.)
+     *   the reset value should be zero unless the boot pin is tied high
+     *   (which is tru) and thus it should be PCI_COMMAND_MEMORY.
+     *
+     * For now, don't touch the value.
+     * Later command register will be set to zero and apb_pci.c will
+     * override the value.
+     * Same for latency timer, and multi function bit of header type.
+     */
+    pci_set_word(dev->config + PCI_COMMAND,
+                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+
+    pci_set_word(dev->config + PCI_STATUS,
+                 PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
+    pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_PCI);
+    dev->config[PCI_LATENCY_TIMER] = 0x10;
+    dev->config[PCI_HEADER_TYPE] =
+        PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE;
+    pci_set_word(dev->config + PCI_SEC_STATUS,
+                 PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
     return 0;
 }
 
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 08/32] pci: clean up pci_init_wmask()
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (6 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 07/32] pci/bridge: clean up of pci_bridge_initfn() Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-11-03 13:22   ` [Qemu-devel] " Michael S. Tsirkin
  2009-11-10 15:26   ` Michael S. Tsirkin
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 09/32] pci: s/PCI_ADDRESS_SPACE_/PCI_BASE_ADDRESS_SPACE_/ to match pci_regs.h Isaku Yamahata
                   ` (23 subsequent siblings)
  31 siblings, 2 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

use pci_set_word() for pci command register.

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

diff --git a/hw/pci.c b/hw/pci.c
index 6abb0e2..84c7611 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -352,8 +352,8 @@ static void pci_init_wmask(PCIDevice *dev)
     int i;
     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;
+    pci_set_word(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)
         dev->wmask[i] = 0xff;
 }
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 09/32] pci: s/PCI_ADDRESS_SPACE_/PCI_BASE_ADDRESS_SPACE_/ to match pci_regs.h
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (7 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 08/32] pci: clean up pci_init_wmask() Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 10/32] pci: clean up of pci_default_read_config Isaku Yamahata
                   ` (22 subsequent siblings)
  31 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

make constants for pci base address match pci_regs.h by
renaming PCI_ADDRESS_SPACE_xxx to PCI_BASE_ADDRESS_SPACE_xxx.

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

diff --git a/hw/ac97.c b/hw/ac97.c
index 610ca60..534f899 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -1331,8 +1331,9 @@ static int ac97_initfn (PCIDevice *dev)
     c[0x3c] = 0x00;      /* intr_ln interrupt line rw */
     c[0x3d] = 0x01;      /* intr_pn interrupt pin ro */
 
-    pci_register_bar (&s->dev, 0, 256 * 4, PCI_ADDRESS_SPACE_IO, ac97_map);
-    pci_register_bar (&s->dev, 1, 64 * 4, PCI_ADDRESS_SPACE_IO, ac97_map);
+    pci_register_bar (&s->dev, 0, 256 * 4, PCI_BASE_ADDRESS_SPACE_IO,
+                      ac97_map);
+    pci_register_bar (&s->dev, 1, 64 * 4, PCI_BASE_ADDRESS_SPACE_IO, ac97_map);
     register_savevm ("ac97", 0, 2, ac97_save, ac97_load, s);
     qemu_register_reset (ac97_on_reset, s);
     AUD_register_card ("ac97", &s->card);
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 04ba68d..0eb058d 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3239,10 +3239,10 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
      /* memory #1 memory-mapped I/O */
      /* XXX: s->vga.vram_size must be a power of two */
      pci_register_bar((PCIDevice *)d, 0, 0x2000000,
-                      PCI_ADDRESS_SPACE_MEM_PREFETCH, cirrus_pci_lfb_map);
+                      PCI_BASE_ADDRESS_MEM_PREFETCH, cirrus_pci_lfb_map);
      if (device_id == CIRRUS_ID_CLGD5446) {
          pci_register_bar((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE,
-                          PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map);
+                          PCI_BASE_ADDRESS_SPACE_MEMORY, cirrus_pci_mmio_map);
      }
      vmstate_register(0, &vmstate_pci_cirrus_vga, d);
      /* XXX: ROM BIOS */
diff --git a/hw/e1000.c b/hw/e1000.c
index 07e663c..ebaadc9 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1086,10 +1086,10 @@ static int pci_e1000_init(PCIDevice *pci_dev)
             e1000_mmio_write, d);
 
     pci_register_bar((PCIDevice *)d, 0, PNPMMIO_SIZE,
-                           PCI_ADDRESS_SPACE_MEM, e1000_mmio_map);
+                           PCI_BASE_ADDRESS_SPACE_MEMORY, e1000_mmio_map);
 
     pci_register_bar((PCIDevice *)d, 1, IOPORT_SIZE,
-                           PCI_ADDRESS_SPACE_IO, ioport_map);
+                           PCI_BASE_ADDRESS_SPACE_IO, ioport_map);
 
     memmove(d->eeprom_data, e1000_eeprom_template,
         sizeof e1000_eeprom_template);
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 0842d48..829731e 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -412,18 +412,20 @@ static void pci_reset(EEPRO100State * s)
     /* BIST (built-in self test) */
 #if defined(TARGET_I386)
 // !!! workaround for buggy bios
-//~ #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0
+//~ #define PCI_BASE_ADDRESS_MEM_PREFETCH 0
 #endif
 #if 0
     /* PCI Base Address Registers */
     /* CSR Memory Mapped Base Address */
     PCI_CONFIG_32(PCI_BASE_ADDRESS_0,
-                  PCI_ADDRESS_SPACE_MEM | PCI_ADDRESS_SPACE_MEM_PREFETCH);
+                  PCI_BASE_ADDRESS_SPACE_MEMORY |
+                  PCI_BASE_ADDRESS_MEM_PREFETCH);
     /* CSR I/O Mapped Base Address */
-    PCI_CONFIG_32(PCI_BASE_ADDRESS_1, PCI_ADDRESS_SPACE_IO);
+    PCI_CONFIG_32(PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_SPACE_IO);
 #if 0
     /* Flash Memory Mapped Base Address */
-    PCI_CONFIG_32(PCI_BASE_ADDRESS_2, 0xfffe0000 | PCI_ADDRESS_SPACE_MEM);
+    PCI_CONFIG_32(PCI_BASE_ADDRESS_2,
+                  0xfffe0000 | PCI_BASE_ADDRESS_SPACE_MEMORY);
 #endif
 #endif
     /* Expansion ROM Base Address (depends on boot disable!!!) */
@@ -1693,11 +1695,11 @@ static int nic_init(PCIDevice *pci_dev, uint32_t device)
         cpu_register_io_memory(pci_mmio_read, pci_mmio_write, s);
 
     pci_register_bar(&s->dev, 0, PCI_MEM_SIZE,
-                           PCI_ADDRESS_SPACE_MEM |
-                           PCI_ADDRESS_SPACE_MEM_PREFETCH, pci_mmio_map);
-    pci_register_bar(&s->dev, 1, PCI_IO_SIZE, PCI_ADDRESS_SPACE_IO,
+                           PCI_BASE_ADDRESS_SPACE_MEMORY |
+                           PCI_BASE_ADDRESS_MEM_PREFETCH, pci_mmio_map);
+    pci_register_bar(&s->dev, 1, PCI_IO_SIZE, PCI_BASE_ADDRESS_SPACE_IO,
                            pci_map);
-    pci_register_bar(&s->dev, 2, PCI_FLASH_SIZE, PCI_ADDRESS_SPACE_MEM,
+    pci_register_bar(&s->dev, 2, PCI_FLASH_SIZE, PCI_BASE_ADDRESS_SPACE_MEMORY,
                            pci_mmio_map);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
diff --git a/hw/es1370.c b/hw/es1370.c
index 9071a48..f048951 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -1027,7 +1027,7 @@ static int es1370_initfn (PCIDevice *dev)
     c[0x3e] = 0x0c;
     c[0x3f] = 0x80;
 
-    pci_register_bar (&s->dev, 0, 256, PCI_ADDRESS_SPACE_IO, es1370_map);
+    pci_register_bar (&s->dev, 0, 256, PCI_BASE_ADDRESS_SPACE_IO, es1370_map);
     register_savevm ("es1370", 0, 2, es1370_save, es1370_load, s);
     qemu_register_reset (es1370_on_reset, s);
 
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index ea116fc..b6e7866 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -219,11 +219,11 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
         pci_conf[0x51] |= 0x08; /* enable IDE1 */
     }
 
-    pci_register_bar(dev, 0, 0x8, PCI_ADDRESS_SPACE_IO, ide_map);
-    pci_register_bar(dev, 1, 0x4, PCI_ADDRESS_SPACE_IO, ide_map);
-    pci_register_bar(dev, 2, 0x8, PCI_ADDRESS_SPACE_IO, ide_map);
-    pci_register_bar(dev, 3, 0x4, PCI_ADDRESS_SPACE_IO, ide_map);
-    pci_register_bar(dev, 4, 0x10, PCI_ADDRESS_SPACE_IO, bmdma_map);
+    pci_register_bar(dev, 0, 0x8, PCI_BASE_ADDRESS_SPACE_IO, ide_map);
+    pci_register_bar(dev, 1, 0x4, PCI_BASE_ADDRESS_SPACE_IO, ide_map);
+    pci_register_bar(dev, 2, 0x8, PCI_BASE_ADDRESS_SPACE_IO, ide_map);
+    pci_register_bar(dev, 3, 0x4, PCI_BASE_ADDRESS_SPACE_IO, ide_map);
+    pci_register_bar(dev, 4, 0x10, PCI_BASE_ADDRESS_SPACE_IO, bmdma_map);
 
     pci_conf[0x3d] = 0x01; // interrupt on pin 1
 
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index a17bf59..5652c99 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -122,7 +122,7 @@ static int pci_piix_ide_initfn(PCIIDEState *d)
     qemu_register_reset(piix3_reset, d);
     piix3_reset(d);
 
-    pci_register_bar(&d->dev, 4, 0x10, PCI_ADDRESS_SPACE_IO, bmdma_map);
+    pci_register_bar(&d->dev, 4, 0x10, PCI_BASE_ADDRESS_SPACE_IO, bmdma_map);
 
     vmstate_register(0, &vmstate_ide_pci, d);
 
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 3966f2f..74f9bbf 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -2090,11 +2090,11 @@ static int lsi_scsi_init(PCIDevice *dev)
                                             lsi_ram_writefn, s);
 
     pci_register_bar((struct PCIDevice *)s, 0, 256,
-                           PCI_ADDRESS_SPACE_IO, lsi_io_mapfunc);
+                           PCI_BASE_ADDRESS_SPACE_IO, lsi_io_mapfunc);
     pci_register_bar((struct PCIDevice *)s, 1, 0x400,
-                           PCI_ADDRESS_SPACE_MEM, lsi_mmio_mapfunc);
+                           PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_mmio_mapfunc);
     pci_register_bar((struct PCIDevice *)s, 2, 0x2000,
-                           PCI_ADDRESS_SPACE_MEM, lsi_ram_mapfunc);
+                           PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_ram_mapfunc);
     s->queue = qemu_malloc(sizeof(lsi_queue));
     s->queue_len = 1;
     s->active_commands = 0;
diff --git a/hw/macio.c b/hw/macio.c
index 8cfadfc..0703abc 100644
--- a/hw/macio.c
+++ b/hw/macio.c
@@ -115,5 +115,5 @@ void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index,
     d->config[0x3d] = 0x01; // interrupt on pin 1
 
     pci_register_bar(d, 0, 0x80000,
-                           PCI_ADDRESS_SPACE_MEM, macio_map);
+                           PCI_BASE_ADDRESS_SPACE_MEMORY, macio_map);
 }
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 97204e8..5fe3883 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -719,7 +719,7 @@ static int pci_ne2000_init(PCIDevice *pci_dev)
     pci_conf[0x3d] = 1; // interrupt pin 0
 
     pci_register_bar(&d->dev, 0, 0x100,
-                           PCI_ADDRESS_SPACE_IO, ne2000_map);
+                           PCI_BASE_ADDRESS_SPACE_IO, ne2000_map);
     s = &d->ne2000;
     s->irq = d->dev.irq[0];
 
diff --git a/hw/openpic.c b/hw/openpic.c
index 74dde6d..5de44a3 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -1213,7 +1213,7 @@ qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
 
         /* Register I/O spaces */
         pci_register_bar((PCIDevice *)opp, 0, 0x40000,
-                               PCI_ADDRESS_SPACE_MEM, &openpic_map);
+                               PCI_BASE_ADDRESS_SPACE_MEMORY, &openpic_map);
     } else {
         opp = qemu_mallocz(sizeof(openpic_t));
     }
diff --git a/hw/pci.c b/hw/pci.c
index 84c7611..91acb85 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -420,7 +420,7 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
         r = &pci_dev->io_regions[i];
         if (!r->size || r->addr == PCI_BAR_UNMAPPED)
             continue;
-        if (r->type == PCI_ADDRESS_SPACE_IO) {
+        if (r->type == PCI_BASE_ADDRESS_SPACE_IO) {
             isa_unassign_ioport(r->addr, r->size);
         } else {
             cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
@@ -492,7 +492,7 @@ static void pci_update_mappings(PCIDevice *d)
     for(i = 0; i < PCI_NUM_REGIONS; i++) {
         r = &d->io_regions[i];
         if (r->size != 0) {
-            if (r->type & PCI_ADDRESS_SPACE_IO) {
+            if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
                 if (cmd & PCI_COMMAND_IO) {
                     new_addr = pci_get_long(d->config + pci_bar(i));
                     new_addr = new_addr & ~(r->size - 1);
@@ -529,7 +529,7 @@ static void pci_update_mappings(PCIDevice *d)
             /* now do the real mapping */
             if (new_addr != r->addr) {
                 if (r->addr != PCI_BAR_UNMAPPED) {
-                    if (r->type & PCI_ADDRESS_SPACE_IO) {
+                    if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
                         int class;
                         /* NOTE: specific hack for IDE in PC case:
                            only one byte must be mapped. */
@@ -771,7 +771,7 @@ static void pci_info_device(PCIDevice *d)
         r = &d->io_regions[i];
         if (r->size != 0) {
             monitor_printf(mon, "      BAR%d: ", i);
-            if (r->type & PCI_ADDRESS_SPACE_IO) {
+            if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
                 monitor_printf(mon, "I/O at 0x%04x [0x%04x].\n",
                                r->addr, r->addr + r->size - 1);
             } else {
@@ -1135,7 +1135,7 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
         if (!r->size)
             continue;
         monitor_printf(mon, "%*sbar %d: %s at 0x%x [0x%x]\n", indent, "",
-                       i, r->type & PCI_ADDRESS_SPACE_IO ? "i/o" : "mem",
+                       i, r->type & PCI_BASE_ADDRESS_SPACE_IO ? "i/o" : "mem",
                        r->addr, r->addr + r->size - 1);
     }
 }
diff --git a/hw/pci.h b/hw/pci.h
index 157995c..bbce56b 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -79,10 +79,6 @@ typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
                                 uint32_t addr, uint32_t size, int type);
 typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
 
-#define PCI_ADDRESS_SPACE_MEM		0x00
-#define PCI_ADDRESS_SPACE_IO		0x01
-#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)
@@ -113,6 +109,9 @@ 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_SPACE_IO	0x01
+#define  PCI_BASE_ADDRESS_SPACE_MEMORY	0x00
+#define  PCI_BASE_ADDRESS_MEM_PREFETCH	0x08	/* prefetchable? */
 #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 */
diff --git a/hw/pcnet.c b/hw/pcnet.c
index a1f9d82..77e59ca 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -1997,10 +1997,10 @@ static int pci_pcnet_init(PCIDevice *pci_dev)
       cpu_register_io_memory(pcnet_mmio_read, pcnet_mmio_write, &d->state);
 
     pci_register_bar((PCIDevice *)d, 0, PCNET_IOPORT_SIZE,
-                           PCI_ADDRESS_SPACE_IO, pcnet_ioport_map);
+                           PCI_BASE_ADDRESS_SPACE_IO, pcnet_ioport_map);
 
     pci_register_bar((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE,
-                           PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map);
+                           PCI_BASE_ADDRESS_SPACE_MEMORY, pcnet_mmio_map);
 
     s->irq = pci_dev->irq[0];
     s->phys_mem_read = pci_physical_memory_read;
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index d26df48..becfca8 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3325,10 +3325,10 @@ static int pci_rtl8139_init(PCIDevice *dev)
     cpu_register_io_memory(rtl8139_mmio_read, rtl8139_mmio_write, s);
 
     pci_register_bar(&s->dev, 0, 0x100,
-                           PCI_ADDRESS_SPACE_IO,  rtl8139_ioport_map);
+                           PCI_BASE_ADDRESS_SPACE_IO,  rtl8139_ioport_map);
 
     pci_register_bar(&s->dev, 1, 0x100,
-                           PCI_ADDRESS_SPACE_MEM, rtl8139_mmio_map);
+                           PCI_BASE_ADDRESS_SPACE_MEMORY, rtl8139_mmio_map);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     rtl8139_reset(&s->dev.qdev);
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 0c7cea6..6a7c698 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -383,9 +383,9 @@ pci_ebus_init1(PCIDevice *s)
     s->config[0x0D] = 0x0a; // latency_timer
     s->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
 
-    pci_register_bar(s, 0, 0x1000000, PCI_ADDRESS_SPACE_MEM,
+    pci_register_bar(s, 0, 0x1000000, PCI_BASE_ADDRESS_SPACE_MEMORY,
                            ebus_mmio_mapfunc);
-    pci_register_bar(s, 1, 0x800000,  PCI_ADDRESS_SPACE_MEM,
+    pci_register_bar(s, 1, 0x800000,  PCI_BASE_ADDRESS_SPACE_MEMORY,
                            ebus_mmio_mapfunc);
     return 0;
 }
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 48ccd49..d498401 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1730,7 +1730,7 @@ static int usb_ohci_initfn_pci(struct PCIDevice *dev)
                   OHCI_TYPE_PCI, ohci->pci_dev.name, 0);
 
     pci_register_bar((struct PCIDevice *)ohci, 0, 256,
-                           PCI_ADDRESS_SPACE_MEM, ohci_mapfunc);
+                           PCI_BASE_ADDRESS_SPACE_MEMORY, ohci_mapfunc);
     return 0;
 }
 
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 67a9a23..a32e409 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1084,7 +1084,7 @@ static int usb_uhci_common_initfn(UHCIState *s)
     /* Use region 4 for consistency with real hardware.  BSD guests seem
        to rely on this.  */
     pci_register_bar(&s->dev, 4, 0x20,
-                           PCI_ADDRESS_SPACE_IO, uhci_map);
+                           PCI_BASE_ADDRESS_SPACE_IO, uhci_map);
 
     vmstate_register(0, &vmstate_uhci, s);
     return 0;
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index 1edfdee..91449e0 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -94,7 +94,7 @@ static int pci_vga_initfn(PCIDevice *dev)
 
      /* XXX: VGA_RAM_SIZE must be a power of two */
      pci_register_bar(&d->dev, 0, VGA_RAM_SIZE,
-                      PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
+                      PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map);
 
      if (s->bios_size) {
         unsigned int bios_total_size;
@@ -103,7 +103,7 @@ static int pci_vga_initfn(PCIDevice *dev)
         while (bios_total_size < s->bios_size)
             bios_total_size <<= 1;
         pci_register_bar(&d->dev, PCI_ROM_SLOT, bios_total_size,
-                         PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
+                         PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map);
      }
      return 0;
 }
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 1665b59..1b0702a 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -415,7 +415,7 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
     if (vdev->nvectors && !msix_init(&proxy->pci_dev, vdev->nvectors, 1, 0)) {
         pci_register_bar(&proxy->pci_dev, 1,
                          msix_bar_size(&proxy->pci_dev),
-                         PCI_ADDRESS_SPACE_MEM,
+                         PCI_BASE_ADDRESS_SPACE_MEMORY,
                          msix_mmio_map);
     } else
         vdev->nvectors = 0;
@@ -426,7 +426,7 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
     if (size & (size-1))
         size = 1 << qemu_fls(size);
 
-    pci_register_bar(&proxy->pci_dev, 0, size, PCI_ADDRESS_SPACE_IO,
+    pci_register_bar(&proxy->pci_dev, 0, size, PCI_BASE_ADDRESS_SPACE_IO,
                            virtio_map);
 
     virtio_bind_device(vdev, &virtio_pci_bindings, proxy);
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 77d7669..baafedd 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1182,9 +1182,9 @@ static int pci_vmsvga_initfn(PCIDevice *dev)
     s->card.config[0x3c]		= 0xff;		/* End */
 
     pci_register_bar(&s->card, 0, 0x10,
-                    PCI_ADDRESS_SPACE_IO, pci_vmsvga_map_ioport);
+                    PCI_BASE_ADDRESS_SPACE_IO, pci_vmsvga_map_ioport);
     pci_register_bar(&s->card, 1, VGA_RAM_SIZE,
-                    PCI_ADDRESS_SPACE_MEM_PREFETCH, pci_vmsvga_map_mem);
+                    PCI_BASE_ADDRESS_MEM_PREFETCH, pci_vmsvga_map_mem);
 
     vmsvga_init(&s->chip, VGA_RAM_SIZE);
 
diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c
index 40081ca..75f1fc6 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -413,7 +413,7 @@ static int i6300esb_init(PCIDevice *dev)
     pci_conf[0x0e] = 0x00;
 
     pci_register_bar(&d->dev, 0, 0x10,
-                            PCI_ADDRESS_SPACE_MEM, i6300esb_map);
+                            PCI_BASE_ADDRESS_SPACE_MEMORY, i6300esb_map);
 
     vmstate_register(-1, &vmstate_i6300esb, d);
 
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 10/32] pci: clean up of pci_default_read_config.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (8 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 09/32] pci: s/PCI_ADDRESS_SPACE_/PCI_BASE_ADDRESS_SPACE_/ to match pci_regs.h Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 11/32] pci: make pci_bar() aware of header type 1 Isaku Yamahata
                   ` (21 subsequent siblings)
  31 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

This patch cleans up pci_default_read_config() removing
ugly length and range check.

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

diff --git a/hw/pci.c b/hw/pci.c
index 91acb85..6b89177 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -558,27 +558,11 @@ static void pci_update_mappings(PCIDevice *d)
 uint32_t pci_default_read_config(PCIDevice *d,
                                  uint32_t address, int len)
 {
-    uint32_t val;
-
-    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;
+    uint32_t val = 0;
+    assert(len == 1 || len == 2 || len == 4);
+    len = MIN(len, PCI_CONFIG_SPACE_SIZE - address);
+    memcpy(&val, d->config + address, len);
+    return le32_to_cpu(val);
 }
 
 void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 11/32] pci: make pci_bar() aware of header type 1.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (9 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 10/32] pci: clean up of pci_default_read_config Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 12/32] pci_host.h: move functions in pci_host.h into .c file Isaku Yamahata
                   ` (20 subsequent siblings)
  31 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

make pci_bar() aware of header type 1. When PCI_ROM_SLOT
it should return PCI_ROM_ADDRESS1 (!= PCI_ROM_ADDRESS)

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

diff --git a/hw/pci.c b/hw/pci.c
index 6b89177..3315820 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -84,9 +84,15 @@ static const VMStateDescription vmstate_pcibus = {
     }
 };
 
-static inline int pci_bar(int reg)
+static int pci_bar(PCIDevice *d, int reg)
 {
-    return reg == PCI_ROM_SLOT ? PCI_ROM_ADDRESS : PCI_BASE_ADDRESS_0 + reg * 4;
+    uint8_t type;
+
+    if (reg != PCI_ROM_SLOT)
+        return PCI_BASE_ADDRESS_0 + reg * 4;
+
+    type = d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
+    return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS;
 }
 
 static void pci_device_reset(PCIDevice *dev)
@@ -102,7 +108,7 @@ static void pci_device_reset(PCIDevice *dev)
         if (!dev->io_regions[r].size) {
             continue;
         }
-        pci_set_long(dev->config + pci_bar(r), dev->io_regions[r].type);
+        pci_set_long(dev->config + pci_bar(dev, r), dev->io_regions[r].type);
     }
     pci_update_mappings(dev);
 }
@@ -472,7 +478,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     r->map_func = map_func;
 
     wmask = ~(size - 1);
-    addr = pci_bar(region_num);
+    addr = pci_bar(pci_dev, region_num);
     if (region_num == PCI_ROM_SLOT) {
         /* ROM enable bit is writeable */
         wmask |= PCI_ROM_ADDRESS_ENABLE;
@@ -494,7 +500,7 @@ static void pci_update_mappings(PCIDevice *d)
         if (r->size != 0) {
             if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
                 if (cmd & PCI_COMMAND_IO) {
-                    new_addr = pci_get_long(d->config + pci_bar(i));
+                    new_addr = pci_get_long(d->config + pci_bar(d, i));
                     new_addr = new_addr & ~(r->size - 1);
                     last_addr = new_addr + r->size - 1;
                     /* NOTE: we have only 64K ioports on PC */
@@ -507,7 +513,7 @@ static void pci_update_mappings(PCIDevice *d)
                 }
             } else {
                 if (cmd & PCI_COMMAND_MEMORY) {
-                    new_addr = pci_get_long(d->config + pci_bar(i));
+                    new_addr = pci_get_long(d->config + pci_bar(d, i));
                     /* the ROM slot has a specific enable bit */
                     if (i == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE))
                         goto no_mem_map;
diff --git a/hw/pci.h b/hw/pci.h
index bbce56b..e9ba6d3 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -120,6 +120,7 @@ typedef struct PCIIORegion {
 #define PCI_ROM_ADDRESS		0x30	/* Bits 31..11 are address, 10..1 reserved */
 #define  PCI_ROM_ADDRESS_ENABLE	0x01
 #define PCI_CAPABILITY_LIST	0x34	/* Offset of first capability list entry */
+#define PCI_ROM_ADDRESS1	0x38	/* Same as PCI_ROM_ADDRESS, but for htype 1 */
 #define PCI_INTERRUPT_LINE	0x3c	/* 8 bits */
 #define PCI_INTERRUPT_PIN	0x3d	/* 8 bits */
 #define PCI_MIN_GNT		0x3e	/* 8 bits */
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 12/32] pci_host.h: move functions in pci_host.h into .c file.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (10 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 11/32] pci: make pci_bar() aware of header type 1 Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-11-03 13:31   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 13/32] pci_host: consolidate pci config address access Isaku Yamahata
                   ` (19 subsequent siblings)
  31 siblings, 1 reply; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

split static functions in pci_host.h into pci_host.c and
pci_host_template.h.
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 functions which are instantiated in .c by including
pci_host.h with typedefing pci_addr_t.
pci_addr_t is per pci host bridge and is typedef'ed to uint32_t for ioio
or target_phys_addr_t for mmio in .c file.
That prevents from including pci_host.h to use PCIHostState because of
requiring type, pci_addr_t.

Its purpose to include is to instantiate io function for mmio or ioio
depending on which pci host bridge requires ioio or mmio.
To avoid including code, we always instantiate both version.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 Makefile.target                        |    2 +-
 hw/apb_pci.c                           |   19 +------
 hw/grackle_pci.c                       |   24 +-------
 hw/gt64xxx.c                           |   11 +----
 hw/pci_host.c                          |   75 ++++++++++++++++++++++++++
 hw/pci_host.h                          |   90 +++-----------------------------
 hw/{pci_host.h => pci_host_template.h} |   36 ++++---------
 hw/piix_pci.c                          |   11 +---
 hw/ppc4xx_pci.c                        |   18 +------
 hw/ppce500_pci.c                       |   17 +------
 hw/prep_pci.c                          |    9 +---
 hw/unin_pci.c                          |   40 ++------------
 12 files changed, 111 insertions(+), 241 deletions(-)
 create mode 100644 hw/pci_host.c
 copy hw/{pci_host.h => pci_host_template.h} (80%)

diff --git a/Makefile.target b/Makefile.target
index fefd7ac..db0d0ab 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -154,7 +154,7 @@ endif #CONFIG_BSD_USER
 # System emulator target
 ifdef CONFIG_SOFTMMU
 
-obj-y = vl.o async.o monitor.o pci.o machine.o gdbstub.o
+obj-y = vl.o async.o monitor.o pci.o pci_host.o machine.o gdbstub.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
 obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o virtio-pci.o
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 1ea3e0d..560617a 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
@@ -48,9 +49,6 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
  * http://www.sun.com/processors/manuals/805-1251.pdf
  */
 
-typedef target_phys_addr_t pci_addr_t;
-#include "pci_host.h"
-
 typedef struct APBState {
     SysBusDevice busdev;
     PCIHostState host_state;
@@ -145,18 +143,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)
 {
@@ -293,8 +279,7 @@ 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 = pci_host_data_register_io_memory(&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 b49cf1e..8407cd2 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,9 +149,7 @@ 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,
-                                          &s->host_state);
+    pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
 
@@ -185,9 +169,7 @@ 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,
-                                          &s->host_state);
+    pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
     return 0;
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.c b/hw/pci_host.c
new file mode 100644
index 0000000..45da1e7
--- /dev/null
+++ b/hw/pci_host.c
@@ -0,0 +1,75 @@
+/*
+ * pci_host.c
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "pci.h"
+#include "pci_host.h"
+
+/* debug PCI */
+//#define DEBUG_PCI
+
+#ifdef DEBUG_PCI
+#define PCI_DPRINTF(fmt, ...) \
+do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define PCI_DPRINTF(fmt, ...)
+#endif
+
+#define PCI_ADDR_T      target_phys_addr_t
+#define PCI_HOST_SUFFIX _mmio
+
+#include "pci_host_template.h"
+
+static CPUWriteMemoryFunc * const pci_host_data_write_mmio[] = {
+    pci_host_data_writeb_mmio,
+    pci_host_data_writew_mmio,
+    pci_host_data_writel_mmio,
+};
+
+static CPUReadMemoryFunc * const pci_host_data_read_mmio[] = {
+    pci_host_data_readb_mmio,
+    pci_host_data_readw_mmio,
+    pci_host_data_readl_mmio,
+};
+
+int pci_host_data_register_io_memory(PCIHostState *s)
+{
+    return cpu_register_io_memory(pci_host_data_read_mmio,
+                                  pci_host_data_write_mmio,
+                                  s);
+}
+
+#undef PCI_ADDR_T
+#undef PCI_HOST_SUFFIX
+
+#define PCI_ADDR_T      uint32_t
+#define PCI_HOST_SUFFIX _ioport
+
+#include "pci_host_template.h"
+
+void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s)
+{
+    register_ioport_write(ioport, 4, 1, pci_host_data_writeb_ioport, s);
+    register_ioport_write(ioport, 4, 2, pci_host_data_writew_ioport, s);
+    register_ioport_write(ioport, 4, 4, pci_host_data_writel_ioport, s);
+    register_ioport_read(ioport, 4, 1, pci_host_data_readb_ioport, s);
+    register_ioport_read(ioport, 4, 2, pci_host_data_readw_ioport, s);
+    register_ioport_read(ioport, 4, 4, pci_host_data_readl_ioport, s);
+}
diff --git a/hw/pci_host.h b/hw/pci_host.h
index 48862b5..92a35f9 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -25,97 +25,21 @@
 /* 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 */
+int pci_host_data_register_io_memory(PCIHostState *s);
 
-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_register_ioport(pio_addr_t ioport, PCIHostState *s);
 
-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/pci_host.h b/hw/pci_host_template.h
similarity index 80%
copy from hw/pci_host.h
copy to hw/pci_host_template.h
index 48862b5..11e6c88 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host_template.h
@@ -25,25 +25,8 @@
 /* Worker routines for a PCI host controller that uses an {address,data}
    register pair to access PCI configuration space.  */
 
-/* debug PCI */
-//#define DEBUG_PCI
-
-#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)
+static void glue(pci_host_data_writeb, PCI_HOST_SUFFIX)(
+    void* opaque, PCI_ADDR_T addr, uint32_t val)
 {
     PCIHostState *s = opaque;
 
@@ -53,7 +36,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)
+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 +49,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)
+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 +62,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)
+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 +76,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)
+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 +92,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)
+static uint32_t glue(pci_host_data_readl, PCI_HOST_SUFFIX)(
+    void* opaque, PCI_ADDR_T addr)
 {
     PCIHostState *s = opaque;
     uint32_t val;
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index ed036fe..866348d 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 {
@@ -197,12 +195,7 @@ 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);
+    pci_host_data_register_ioport(0xcfc, s);
     return 0;
 }
 
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index 655fe86..3aa7489 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,9 +378,7 @@ 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,
-                                   &controller->pci_state);
+    index = pci_host_data_register_io_memory(&controller->pci_state);
     if (index < 0)
         goto free;
     cpu_register_physical_memory(config_space + PCIC0_CFGDATA, 4, index);
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 64fccfd..7c8cdad 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,9 +331,7 @@ 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,
-                                   &controller->pci_state);
+    index = pci_host_data_register_io_memory(&controller->pci_state);
     if (index < 0)
         goto free;
     cpu_register_physical_memory(registers + PCIE500_CFGDATA, 4, index);
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index 2d8a0fa..5a5b3da 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,7 @@ 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);
+    pci_host_data_register_ioport(0xcfc, 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 4abb5c8..6b8f98b 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,7 @@ 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 = pci_host_data_register_io_memory(&s->host_state);
 
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
@@ -203,8 +176,7 @@ 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 = pci_host_data_register_io_memory(&s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
     return 0;
@@ -220,8 +192,7 @@ 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 = pci_host_data_register_io_memory(&s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
     return 0;
@@ -237,8 +208,7 @@ 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 = pci_host_data_register_io_memory(&s->host_state);
     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] 75+ messages in thread

* [Qemu-devel] [PATCH V6 13/32] pci_host: consolidate pci config address access.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (11 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 12/32] pci_host.h: move functions in pci_host.h into .c file Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-11-03 13:45   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 14/32] pci: introduce pcibus_t to represent pci bus address/size instead of uint32_t Isaku Yamahata
                   ` (18 subsequent siblings)
  31 siblings, 1 reply; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

consolidate pci_config address access into pci_host.c

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/apb_pci.c     |   43 +---------------------
 hw/grackle_pci.c |   45 +---------------------
 hw/pci_host.c    |  108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/pci_host.h    |    3 +
 hw/piix_pci.c    |   15 +-------
 hw/ppce500_pci.c |   34 +----------------
 hw/prep_pci.c    |   15 +-------
 hw/unin_pci.c    |   81 ++--------------------------------------
 8 files changed, 121 insertions(+), 223 deletions(-)

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 560617a..3999879 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -54,46 +54,6 @@ typedef struct APBState {
     PCIHostState host_state;
 } APBState;
 
-static void pci_apb_config_writel (void *opaque, target_phys_addr_t addr,
-                                         uint32_t val)
-{
-    APBState *s = opaque;
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    APB_DPRINTF("config_writel addr " TARGET_FMT_plx " val %x\n", addr,
-                val);
-    s->host_state.config_reg = val;
-}
-
-static uint32_t pci_apb_config_readl (void *opaque,
-                                            target_phys_addr_t addr)
-{
-    APBState *s = opaque;
-    uint32_t val;
-
-    val = s->host_state.config_reg;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    APB_DPRINTF("config_readl addr " TARGET_FMT_plx " val %x\n", addr,
-                val);
-    return val;
-}
-
-static CPUWriteMemoryFunc * const pci_apb_config_write[] = {
-    &pci_apb_config_writel,
-    &pci_apb_config_writel,
-    &pci_apb_config_writel,
-};
-
-static CPUReadMemoryFunc * const pci_apb_config_read[] = {
-    &pci_apb_config_readl,
-    &pci_apb_config_readl,
-    &pci_apb_config_readl,
-};
-
 static void apb_config_writel (void *opaque, target_phys_addr_t addr,
                                uint32_t val)
 {
@@ -275,8 +235,7 @@ static int pci_pbm_init_device(SysBusDevice *dev)
                                           pci_apb_iowrite, s);
     sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
     /* mem_config  */
-    pci_mem_config = cpu_register_io_memory(pci_apb_config_read,
-                                            pci_apb_config_write, s);
+    pci_mem_config = pci_host_config_register_io_memory(&s->host_state);
     sysbus_init_mmio(dev, 0x10ULL, pci_mem_config);
     /* mem_data */
     pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index 8407cd2..58dcd11 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -43,45 +43,6 @@ typedef struct GrackleState {
     PCIHostState host_state;
 } GrackleState;
 
-static void pci_grackle_config_writel (void *opaque, target_phys_addr_t addr,
-                                       uint32_t val)
-{
-    GrackleState *s = opaque;
-
-    GRACKLE_DPRINTF("config_writel addr " TARGET_FMT_plx " val %x\n", addr,
-                    val);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    s->host_state.config_reg = val;
-}
-
-static uint32_t pci_grackle_config_readl (void *opaque, target_phys_addr_t addr)
-{
-    GrackleState *s = opaque;
-    uint32_t val;
-
-    val = s->host_state.config_reg;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    GRACKLE_DPRINTF("config_readl addr " TARGET_FMT_plx " val %x\n", addr,
-                    val);
-    return val;
-}
-
-static CPUWriteMemoryFunc * const pci_grackle_config_write[] = {
-    &pci_grackle_config_writel,
-    &pci_grackle_config_writel,
-    &pci_grackle_config_writel,
-};
-
-static CPUReadMemoryFunc * const pci_grackle_config_read[] = {
-    &pci_grackle_config_readl,
-    &pci_grackle_config_readl,
-    &pci_grackle_config_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)
 {
@@ -147,8 +108,7 @@ static int pci_grackle_init_device(SysBusDevice *dev)
 
     s = FROM_SYSBUS(GrackleState, dev);
 
-    pci_mem_config = cpu_register_io_memory(pci_grackle_config_read,
-                                            pci_grackle_config_write, s);
+    pci_mem_config = pci_host_config_register_io_memory(&s->host_state);
     pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
@@ -167,8 +127,7 @@ static int pci_dec_21154_init_device(SysBusDevice *dev)
 
     s = FROM_SYSBUS(GrackleState, dev);
 
-    pci_mem_config = cpu_register_io_memory(pci_grackle_config_read,
-                                            pci_grackle_config_write, s);
+    pci_mem_config = pci_host_config_register_io_memory(&s->host_state);
     pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
diff --git a/hw/pci_host.c b/hw/pci_host.c
index 45da1e7..6009e37 100644
--- a/hw/pci_host.c
+++ b/hw/pci_host.c
@@ -32,6 +32,114 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
 #define PCI_DPRINTF(fmt, ...)
 #endif
 
+static void pci_host_config_writel(void *opaque, target_phys_addr_t addr,
+                                   uint32_t val)
+{
+    PCIHostState *s = opaque;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
+                __func__, addr, val);
+    s->config_reg = val;
+}
+
+static uint32_t pci_host_config_readl(void *opaque, target_phys_addr_t addr)
+{
+    PCIHostState *s = opaque;
+    uint32_t val = s->config_reg;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
+                __func__, addr, val);
+    return val;
+}
+
+static CPUWriteMemoryFunc * const pci_host_config_write[] = {
+    &pci_host_config_writel,
+    &pci_host_config_writel,
+    &pci_host_config_writel,
+};
+
+static CPUReadMemoryFunc * const pci_host_config_read[] = {
+    &pci_host_config_readl,
+    &pci_host_config_readl,
+    &pci_host_config_readl,
+};
+
+int pci_host_config_register_io_memory(PCIHostState *s)
+{
+    return cpu_register_io_memory(pci_host_config_read,
+                                  pci_host_config_write, s);
+}
+
+static void pci_host_config_writel_noswap(void *opaque,
+                                          target_phys_addr_t addr,
+                                          uint32_t val)
+{
+    PCIHostState *s = opaque;
+
+    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
+                __func__, addr, val);
+    s->config_reg = val;
+}
+
+static uint32_t pci_host_config_readl_noswap(void *opaque,
+                                             target_phys_addr_t addr)
+{
+    PCIHostState *s = opaque;
+    uint32_t val = s->config_reg;
+
+    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
+                __func__, addr, val);
+    return val;
+}
+
+static CPUWriteMemoryFunc * const pci_host_config_write_noswap[] = {
+    &pci_host_config_writel_noswap,
+    &pci_host_config_writel_noswap,
+    &pci_host_config_writel_noswap,
+};
+
+static CPUReadMemoryFunc * const pci_host_config_read_noswap[] = {
+    &pci_host_config_readl_noswap,
+    &pci_host_config_readl_noswap,
+    &pci_host_config_readl_noswap,
+};
+
+int pci_host_config_register_io_memory_noswap(PCIHostState *s)
+{
+    return cpu_register_io_memory(pci_host_config_read_noswap,
+                                  pci_host_config_write_noswap, s);
+}
+
+static void pci_host_config_writel_ioport(void *opaque,
+                                          uint32_t addr, uint32_t val)
+{
+    PCIHostState *s = opaque;
+
+    PCI_DPRINTF("%s addr %"PRIx32 " val %"PRIx32"\n", __func__, addr, val);
+    s->config_reg = val;
+}
+
+static uint32_t pci_host_config_readl_ioport(void *opaque, uint32_t addr)
+{
+    PCIHostState *s = opaque;
+    uint32_t val = s->config_reg;
+
+    PCI_DPRINTF("%s addr %"PRIx32" val %"PRIx32"\n", __func__, addr, val);
+    return val;
+}
+
+void pci_host_config_register_ioport(pio_addr_t ioport, PCIHostState *s)
+{
+    register_ioport_write(ioport, 4, 4, pci_host_config_writel_ioport, s);
+    register_ioport_read(ioport, 4, 4, pci_host_config_readl_ioport, s);
+}
+
 #define PCI_ADDR_T      target_phys_addr_t
 #define PCI_HOST_SUFFIX _mmio
 
diff --git a/hw/pci_host.h b/hw/pci_host.h
index 92a35f9..e5e877f 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -37,9 +37,12 @@ typedef struct {
 } PCIHostState;
 
 /* for mmio */
+int pci_host_config_register_io_memory(PCIHostState *s);
+int pci_host_config_register_io_memory_noswap(PCIHostState *s);
 int pci_host_data_register_io_memory(PCIHostState *s);
 
 /* for ioio */
+void pci_host_config_register_ioport(pio_addr_t ioport, PCIHostState *s);
 void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s);
 
 #endif /* PCI_HOST_H */
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 866348d..bf0005e 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -44,18 +44,6 @@ struct PCII440FXState {
     PIIX3State *piix3;
 };
 
-static void i440fx_addr_writel(void* opaque, uint32_t addr, uint32_t val)
-{
-    I440FXState *s = opaque;
-    s->config_reg = val;
-}
-
-static uint32_t i440fx_addr_readl(void* opaque, uint32_t addr)
-{
-    I440FXState *s = opaque;
-    return s->config_reg;
-}
-
 static void piix3_set_irq(void *opaque, int irq_num, int level);
 
 /* return the global irq number corresponding to a given device irq
@@ -192,8 +180,7 @@ static int i440fx_pcihost_initfn(SysBusDevice *dev)
 {
     I440FXState *s = FROM_SYSBUS(I440FXState, dev);
 
-    register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
-    register_ioport_read(0xcf8, 4, 4, i440fx_addr_readl, s);
+    pci_host_config_register_ioport(0xcf8, s);
 
     pci_host_data_register_ioport(0xcfc, s);
     return 0;
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 7c8cdad..223de3a 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -84,37 +84,6 @@ struct PPCE500PCIState {
 
 typedef struct PPCE500PCIState PPCE500PCIState;
 
-static uint32_t pcie500_cfgaddr_readl(void *opaque, target_phys_addr_t addr)
-{
-    PPCE500PCIState *pci = opaque;
-
-    pci_debug("%s: (addr:" TARGET_FMT_plx ") -> value:%x\n", __func__, addr,
-              pci->pci_state.config_reg);
-    return pci->pci_state.config_reg;
-}
-
-static CPUReadMemoryFunc * const pcie500_cfgaddr_read[] = {
-    &pcie500_cfgaddr_readl,
-    &pcie500_cfgaddr_readl,
-    &pcie500_cfgaddr_readl,
-};
-
-static void pcie500_cfgaddr_writel(void *opaque, target_phys_addr_t addr,
-                                  uint32_t value)
-{
-    PPCE500PCIState *controller = opaque;
-
-    pci_debug("%s: value:%x -> (addr:" TARGET_FMT_plx ")\n", __func__, value,
-              addr);
-    controller->pci_state.config_reg = value & ~0x3;
-}
-
-static CPUWriteMemoryFunc * const pcie500_cfgaddr_write[] = {
-    &pcie500_cfgaddr_writel,
-    &pcie500_cfgaddr_writel,
-    &pcie500_cfgaddr_writel,
-};
-
 static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
 {
     PPCE500PCIState *pci = opaque;
@@ -324,8 +293,7 @@ PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
     controller->pci_dev = d;
 
     /* CFGADDR */
-    index = cpu_register_io_memory(pcie500_cfgaddr_read,
-                                   pcie500_cfgaddr_write, controller);
+    index = pci_host_config_register_io_memory_noswap(&controller->pci_state);
     if (index < 0)
         goto free;
     cpu_register_physical_memory(registers + PCIE500_CFGADDR, 4, index);
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index 5a5b3da..a338f81 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -28,18 +28,6 @@
 
 typedef PCIHostState PREPPCIState;
 
-static void pci_prep_addr_writel(void* opaque, uint32_t addr, uint32_t val)
-{
-    PREPPCIState *s = opaque;
-    s->config_reg = val;
-}
-
-static uint32_t pci_prep_addr_readl(void* opaque, uint32_t addr)
-{
-    PREPPCIState *s = opaque;
-    return s->config_reg;
-}
-
 static inline uint32_t PPC_PCIIO_config(target_phys_addr_t addr)
 {
     int i;
@@ -139,8 +127,7 @@ PCIBus *pci_prep_init(qemu_irq *pic)
     s->bus = pci_register_bus(NULL, "pci",
                               prep_set_irq, prep_map_irq, pic, 0, 4);
 
-    register_ioport_write(0xcf8, 4, 4, pci_prep_addr_writel, s);
-    register_ioport_read(0xcf8, 4, 4, pci_prep_addr_readl, s);
+    pci_host_config_register_ioport(0xcf8, s);
 
     pci_host_data_register_ioport(0xcfc, s);
 
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index 6b8f98b..a9a62fd 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -41,74 +41,6 @@ typedef struct UNINState {
     PCIHostState host_state;
 } UNINState;
 
-static void pci_unin_main_config_writel (void *opaque, target_phys_addr_t addr,
-                                         uint32_t val)
-{
-    UNINState *s = opaque;
-
-    UNIN_DPRINTF("config_writel addr " TARGET_FMT_plx " val %x\n", addr, val);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-
-    s->host_state.config_reg = val;
-}
-
-static uint32_t pci_unin_main_config_readl (void *opaque,
-                                            target_phys_addr_t addr)
-{
-    UNINState *s = opaque;
-    uint32_t val;
-
-    val = s->host_state.config_reg;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    UNIN_DPRINTF("config_readl addr " TARGET_FMT_plx " val %x\n", addr, val);
-
-    return val;
-}
-
-static CPUWriteMemoryFunc * const pci_unin_main_config_write[] = {
-    &pci_unin_main_config_writel,
-    &pci_unin_main_config_writel,
-    &pci_unin_main_config_writel,
-};
-
-static CPUReadMemoryFunc * const pci_unin_main_config_read[] = {
-    &pci_unin_main_config_readl,
-    &pci_unin_main_config_readl,
-    &pci_unin_main_config_readl,
-};
-
-static void pci_unin_config_writel (void *opaque, target_phys_addr_t addr,
-                                    uint32_t val)
-{
-    UNINState *s = opaque;
-
-    s->host_state.config_reg = val;
-}
-
-static uint32_t pci_unin_config_readl (void *opaque,
-                                       target_phys_addr_t addr)
-{
-    UNINState *s = opaque;
-
-    return s->host_state.config_reg;
-}
-
-static CPUWriteMemoryFunc * const pci_unin_config_write[] = {
-    &pci_unin_config_writel,
-    &pci_unin_config_writel,
-    &pci_unin_config_writel,
-};
-
-static CPUReadMemoryFunc * const pci_unin_config_read[] = {
-    &pci_unin_config_readl,
-    &pci_unin_config_readl,
-    &pci_unin_config_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)
 {
@@ -152,10 +84,8 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
     /* Uninorth main bus */
     s = FROM_SYSBUS(UNINState, dev);
 
-    pci_mem_config = cpu_register_io_memory(pci_unin_main_config_read,
-                                            pci_unin_main_config_write, s);
+    pci_mem_config = pci_host_config_register_io_memory(&s->host_state);
     pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
-
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
 
@@ -174,8 +104,7 @@ static int pci_dec_21154_init_device(SysBusDevice *dev)
     s = FROM_SYSBUS(UNINState, dev);
 
     // XXX: s = &pci_bridge[2];
-    pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
-                                            pci_unin_config_write, s);
+    pci_mem_config = pci_host_config_register_io_memory_noswap(&s->host_state);
     pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
@@ -190,8 +119,7 @@ static int pci_unin_agp_init_device(SysBusDevice *dev)
     /* Uninorth AGP bus */
     s = FROM_SYSBUS(UNINState, dev);
 
-    pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
-                                            pci_unin_config_write, s);
+    pci_mem_config = pci_host_config_register_io_memory_noswap(&s->host_state);
     pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
@@ -206,8 +134,7 @@ static int pci_unin_internal_init_device(SysBusDevice *dev)
     /* Uninorth internal bus */
     s = FROM_SYSBUS(UNINState, dev);
 
-    pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
-                                            pci_unin_config_write, s);
+    pci_mem_config = pci_host_config_register_io_memory_noswap(&s->host_state);
     pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 14/32] pci: introduce pcibus_t to represent pci bus address/size instead of uint32_t
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (12 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 13/32] pci_host: consolidate pci config address access Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 15/32] pci: introduce FMT_PCIBUS for printf format for pcibus_t Isaku Yamahata
                   ` (17 subsequent siblings)
  31 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 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/cmd646.c   |    4 ++--
 hw/ide/piix.c     |    2 +-
 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          |    6 +++---
 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 +-
 24 files changed, 43 insertions(+), 40 deletions(-)

diff --git a/hw/ac97.c b/hw/ac97.c
index 534f899..f72c46d 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 0eb058d..ef72c62 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3172,7 +3172,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;
 
@@ -3193,7 +3193,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 ebaadc9..9ae1e87 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -144,8 +144,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);
 }
@@ -1010,7 +1010,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 829731e..55e7717 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1384,7 +1384,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);
 
@@ -1463,7 +1463,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 f048951..10da250 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/cmd646.c b/hw/ide/cmd646.c
index b6e7866..b1907a7 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -45,7 +45,7 @@
 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 = DO_UPCAST(PCIIDEState, dev, pci_dev);
     IDEBus *bus;
@@ -136,7 +136,7 @@ static void bmdma_writeb(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 = DO_UPCAST(PCIIDEState, dev, pci_dev);
     int i;
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 5652c99..17910dc 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -69,7 +69,7 @@ static void bmdma_writeb(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 = DO_UPCAST(PCIIDEState, dev, pci_dev);
     int i;
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 74f9bbf..a1e48ca 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 0703abc..e92e82a 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 b0dea91..ee565bc 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -203,7 +203,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 3427778..39fa568 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(PCIDevice *pdev, unsigned short nentries,
               unsigned bar_nr, unsigned bar_size);
@@ -10,7 +11,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 5fe3883..63efc3a 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -679,7 +679,7 @@ const VMStateDescription vmstate_pci_ne2000 = {
 /* 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 5de44a3..f2d2937 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 3315820..5114ed3 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -455,12 +455,12 @@ static int pci_unregister_device(DeviceState *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;
@@ -492,7 +492,7 @@ static void pci_update_mappings(PCIDevice *d)
 {
     PCIIORegion *r;
     int cmd, i;
-    uint32_t last_addr, new_addr;
+    pcibus_t last_addr, new_addr;
 
     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 e9ba6d3..9509a6b 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -71,18 +71,20 @@ 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);
 
 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;
@@ -224,7 +226,7 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
                                PCIConfigWriteFunc *config_write);
 
 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 77e59ca..2716f5f 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -1727,7 +1727,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;
 
@@ -1921,7 +1921,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 becfca8..8b6c714 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3192,7 +3192,7 @@ static const VMStateDescription vmstate_rtl8139 = {
 /* 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);
 
@@ -3200,7 +3200,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 6a7c698..e93393e 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -338,7 +338,7 @@ void cpu_tick_set_limit(void *opaque, uint64_t limit)
 }
 
 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 d498401..567fb17 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 a32e409..86f12ce 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1047,7 +1047,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 91449e0..2de8d8f 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -47,7 +47,7 @@ static const VMStateDescription vmstate_vga_pci = {
 };
 
 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 1b0702a..aebcf9d 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -344,7 +344,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 baafedd..33e876e 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1126,7 +1126,7 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
 }
 
 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;
@@ -1146,7 +1146,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 75f1fc6..6da396a 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -343,7 +343,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] 75+ messages in thread

* [Qemu-devel] [PATCH V6 15/32] pci: introduce FMT_PCIBUS for printf format for pcibus_t.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (13 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 14/32] pci: introduce pcibus_t to represent pci bus address/size instead of uint32_t Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 16/32] pci: typedef pcibus_t as uint64_t instead of uint32_t Isaku Yamahata
                   ` (16 subsequent siblings)
  31 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 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>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/e1000.c        |    6 ++++--
 hw/eepro100.c     |    6 ++++--
 hw/pci.c          |   14 +++++++++-----
 hw/pci.h          |    1 +
 hw/pcnet.c        |    6 ++++--
 hw/wdt_i6300esb.c |    3 ++-
 6 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/hw/e1000.c b/hw/e1000.c
index 9ae1e87..7e3ab80 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -147,7 +147,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
@@ -1020,7 +1021,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 55e7717..ba8cdf6 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1388,7 +1388,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);
@@ -1467,7 +1468,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 5114ed3..5cf50e0 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -467,7 +467,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);
     }
 
@@ -484,7 +484,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
         wmask |= PCI_ROM_ADDRESS_ENABLE;
     }
     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);
 }
 
@@ -762,10 +762,12 @@ static void pci_info_device(PCIDevice *d)
         if (r->size != 0) {
             monitor_printf(mon, "      BAR%d: ", i);
             if (r->type & PCI_BASE_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);
             }
         }
@@ -1124,7 +1126,9 @@ 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_BASE_ADDRESS_SPACE_IO ? "i/o" : "mem",
                        r->addr, r->addr + r->size - 1);
     }
diff --git a/hw/pci.h b/hw/pci.h
index 9509a6b..fa2077d 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 2716f5f..43ca415 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -1732,7 +1732,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);
@@ -1926,7 +1927,8 @@ 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 6da396a..27fa09e 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -358,7 +358,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] 75+ messages in thread

* [Qemu-devel] [PATCH V6 16/32] pci: typedef pcibus_t as uint64_t instead of uint32_t.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (14 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 15/32] pci: introduce FMT_PCIBUS for printf format for pcibus_t Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 17/32] pci: 64bit bar support Isaku Yamahata
                   ` (15 subsequent siblings)
  31 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 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.

In pci_update_mapping() checks 32bit overflow.
So the check must be updated too.

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

diff --git a/hw/pci.c b/hw/pci.c
index 5cf50e0..b462bd6 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -524,7 +524,14 @@ 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 ||
+
+                        /* Now pcibus_t is 64bit.
+                         * Check if 32 bit BAR wrap around explicitly.
+                         * Without this, PC ide doesn't work well.
+                         * TODO: remove this work around.
+                         */
+                        last_addr >= UINT32_MAX) {
                         new_addr = PCI_BAR_UNMAPPED;
                     }
                 } else {
diff --git a/hw/pci.h b/hw/pci.h
index fa2077d..305c030 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] 75+ messages in thread

* [Qemu-devel] [PATCH V6 17/32] pci: 64bit bar support.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (15 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 16/32] pci: typedef pcibus_t as uint64_t instead of uint32_t Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-11-01 16:07   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 18/32] pci: remove bus_num member from struct PCIBus Isaku Yamahata
                   ` (14 subsequent siblings)
  31 siblings, 1 reply; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

implemented pci 64bit bar support.
The tricky bit is pci_update_mapping().
An OS is allowed to set the BAR such that OS can't address the area
pointed by BAR. It doesn't make sense, though.
In that case, don't map the BAR.

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

diff --git a/hw/pci.c b/hw/pci.c
index b462bd6..7da3db9 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -484,8 +484,14 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
         wmask |= PCI_ROM_ADDRESS_ENABLE;
     }
     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 (!(r->type & PCI_BASE_ADDRESS_SPACE_IO) &&
+        r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+        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)
@@ -513,7 +519,11 @@ static void pci_update_mappings(PCIDevice *d)
                 }
             } else {
                 if (cmd & PCI_COMMAND_MEMORY) {
-                    new_addr = pci_get_long(d->config + pci_bar(d, i));
+                    if (r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+                        new_addr = pci_get_quad(d->config + pci_bar(d, i));
+                    } else {
+                        new_addr = pci_get_long(d->config + pci_bar(d, i));
+                    }
                     /* the ROM slot has a specific enable bit */
                     if (i == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE))
                         goto no_mem_map;
@@ -531,7 +541,15 @@ static void pci_update_mappings(PCIDevice *d)
                          * Without this, PC ide doesn't work well.
                          * TODO: remove this work around.
                          */
-                        last_addr >= UINT32_MAX) {
+                        (!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) &&
+                         last_addr >= UINT32_MAX) ||
+
+                        /*
+                         * OS is allowed to set BAR beyond its addressable
+                         * bits. For example, 32 bit OS can set 64bit bar
+                         * to >4G. Check it.
+                         */
+                        last_addr >= TARGET_PHYS_ADDR_MAX) {
                         new_addr = PCI_BAR_UNMAPPED;
                     }
                 } else {
@@ -773,8 +791,15 @@ static void pci_info_device(PCIDevice *d)
                                " [0x%04"FMT_PCIBUS"].\n",
                                r->addr, r->addr + r->size - 1);
             } else {
-                monitor_printf(mon, "32 bit memory at 0x%08"FMT_PCIBUS
+                const char *type = r->type & PCI_BASE_ADDRESS_MEM_TYPE_64 ?
+                    "64 bit" : "32 bit";
+                const char *prefetch =
+                    r->type & PCI_BASE_ADDRESS_MEM_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 305c030..e83faf5 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -114,6 +114,7 @@ typedef struct PCIIORegion {
 #define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
 #define  PCI_BASE_ADDRESS_SPACE_IO	0x01
 #define  PCI_BASE_ADDRESS_SPACE_MEMORY	0x00
+#define  PCI_BASE_ADDRESS_MEM_TYPE_64	0x04	/* 64 bit address */
 #define  PCI_BASE_ADDRESS_MEM_PREFETCH	0x08	/* prefetchable? */
 #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
 #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 18/32] pci: remove bus_num member from struct PCIBus.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (16 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 17/32] pci: 64bit bar support Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-11-03 13:47   ` [Qemu-devel] " Michael S. Tsirkin
  2009-11-10 15:33   ` Michael S. Tsirkin
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 19/32] pci: make pci configuration transaction more accurate Isaku Yamahata
                   ` (13 subsequent siblings)
  31 siblings, 2 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

Since It can be retrieved from pci configuration space,
the member is unnecessary.

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

diff --git a/hw/pci.c b/hw/pci.c
index 7da3db9..a75d981 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -36,7 +36,6 @@
 
 struct PCIBus {
     BusState qbus;
-    int bus_num;
     int devfn_min;
     pci_set_irq_fn set_irq;
     pci_map_irq_fn map_irq;
@@ -192,7 +191,9 @@ static void pci_register_secondary_bus(PCIBus *bus,
 
 int pci_bus_num(PCIBus *s)
 {
-    return s->bus_num;
+    if (!s->parent_dev)
+        return 0;       /* pci host bridge */
+    return s->parent_dev->config[PCI_SECONDARY_BUS];
 }
 
 static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
@@ -624,7 +625,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)
+    while (s && pci_bus_num(s) != bus_num)
         s = s->next;
     if (!s)
         return;
@@ -645,7 +646,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)
+    while (s && pci_bus_num(s) != bus_num)
         s= s->next;
     if (!s)
         goto fail;
@@ -760,7 +761,8 @@ 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, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
+                   pci_bus_num(d->bus),
+                   PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
     class = pci_get_word(d->config + PCI_CLASS_DEVICE);
     monitor_printf(mon, "    ");
     desc = pci_class_descriptions;
@@ -816,7 +818,7 @@ void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
     PCIDevice *d;
     int devfn;
 
-    while (bus && bus->bus_num != bus_num)
+    while (bus && pci_bus_num(bus) != bus_num)
         bus = bus->next;
     if (bus) {
         for(devfn = 0; devfn < 256; devfn++) {
@@ -913,17 +915,14 @@ typedef struct {
 static void pci_bridge_write_config(PCIDevice *d,
                              uint32_t address, uint32_t val, int len)
 {
-    PCIBridge *s = (PCIBridge *)d;
-
     pci_default_write_config(d, address, val, len);
-    s->bus.bus_num = d->config[PCI_SECONDARY_BUS];
 }
 
 PCIBus *pci_find_bus(int bus_num)
 {
     PCIBus *bus = first_bus;
 
-    while (bus && bus->bus_num != bus_num)
+    while (bus && pci_bus_num(bus) != bus_num)
         bus = bus->next;
 
     return bus;
@@ -1149,7 +1148,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, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
+                   pci_bus_num(d->bus), PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
                    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),
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 19/32] pci: make pci configuration transaction more accurate.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (17 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 18/32] pci: remove bus_num member from struct PCIBus Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-11-10 15:49   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 20/32] pci: factor out the conversion logic from io port address into pci device Isaku Yamahata
                   ` (12 subsequent siblings)
  31 siblings, 1 reply; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

This patch sorts out/enhances pci code to track pci bus topology
more accurately.
- Track host bus bridge with pci domain number. Although the
  current qemu implementation supports 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/pci-hotplug.c |    4 +-
 hw/pci.c         |  132 +++++++++++++++++++++++++++++++++++++++++-------------
 hw/pci.h         |    8 ++-
 3 files changed, 108 insertions(+), 36 deletions(-)

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 15a2dfb..48a641b 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -113,7 +113,7 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
         if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
             goto err;
         }
-        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);
             goto err;
@@ -257,7 +257,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;
diff --git a/hw/pci.c b/hw/pci.c
index a75d981..3e5780a 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -44,7 +44,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 +72,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",
@@ -127,6 +136,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;
+}
+
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name, int devfn_min)
 {
@@ -134,8 +165,11 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
 
     qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name);
     bus->devfn_min = devfn_min;
-    bus->next = first_bus;
-    first_bus = bus;
+
+    /* host bridge */
+    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);
 }
@@ -177,7 +211,8 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
     return bus;
 }
 
-static void pci_register_secondary_bus(PCIBus *bus,
+static void pci_register_secondary_bus(PCIBus *parent,
+                                       PCIBus *bus,
                                        PCIDevice *dev,
                                        pci_map_irq_fn map_irq,
                                        const char *name)
@@ -185,8 +220,15 @@ static void pci_register_secondary_bus(PCIBus *bus,
     qbus_create_inplace(&bus->qbus, &pci_bus_info, &dev->qdev, name);
     bus->map_irq = map_irq;
     bus->parent_dev = dev;
-    bus->next = dev->bus->next;
-    dev->bus->next = bus;
+
+    QLIST_INIT(&bus->child);
+    QLIST_INSERT_HEAD(&parent->child, bus, sibling);
+}
+
+static void pci_unregister_secondary_bus(PCIBus *bus)
+{
+    assert(QLIST_EMPTY(&bus->child));
+    QLIST_REMOVE(bus, sibling);
 }
 
 int pci_bus_num(PCIBus *s)
@@ -196,6 +238,13 @@ int pci_bus_num(PCIBus *s)
     return s->parent_dev->config[PCI_SECONDARY_BUS];
 }
 
+static uint8_t pci_sub_bus(PCIBus *s)
+{
+    if (!s->parent_dev)
+        return 255;     /* pci host bridge */
+    return s->parent_dev->config[PCI_SUBORDINATE_BUS];
+}
+
 static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
 {
     PCIDevice *s = container_of(pv, PCIDevice, config);
@@ -301,7 +350,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 (!pci_find_bus(pci_find_host_bus(dom), bus))
 	return -1;
 
     *domp = dom;
@@ -331,7 +380,7 @@ 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) {
@@ -339,7 +388,7 @@ 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)
@@ -625,8 +674,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 && pci_bus_num(s) != bus_num)
-        s = s->next;
+    s = pci_find_bus(s, bus_num);
     if (!s)
         return;
     pci_dev = s->devices[(addr >> 8) & 0xff];
@@ -646,8 +694,7 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
     uint32_t val;
 
     bus_num = (addr >> 16) & 0xff;
-    while (s && pci_bus_num(s) != bus_num)
-        s= s->next;
+    s = pci_find_bus(s, bus_num);
     if (!s)
         goto fail;
     pci_dev = s->devices[(addr >> 8) & 0xff];
@@ -753,7 +800,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;
@@ -808,30 +855,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 && pci_bus_num(bus) != 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);
+    }
 }
 
 static const char * const pci_nic_models[] = {
@@ -918,19 +967,30 @@ static void pci_bridge_write_config(PCIDevice *d,
     pci_default_write_config(d, address, val, len);
 }
 
-PCIBus *pci_find_bus(int bus_num)
+PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
 {
-    PCIBus *bus = first_bus;
+    PCIBus *sec;
 
-    while (bus && pci_bus_num(bus) != bus_num)
-        bus = bus->next;
+    if (!bus)
+        return NULL;
 
-    return bus;
+    if (pci_bus_num(bus) == bus_num) {
+        return bus;
+    }
+
+    /* try child bus */
+    QLIST_FOREACH(sec, &bus->child, sibling) {
+        if (pci_bus_num(sec) <= bus_num && bus_num <= pci_sub_bus(sec)) {
+            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;
@@ -973,6 +1033,14 @@ static int pci_bridge_initfn(PCIDevice *dev)
     return 0;
 }
 
+static int pci_bridge_exitfn(PCIDevice *pci_dev)
+{
+    PCIBridge *s = DO_UPCAST(PCIBridge, dev, pci_dev);
+    PCIBus *bus = &s->bus;
+    pci_unregister_secondary_bus(bus);
+    return 0;
+}
+
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
                         pci_map_irq_fn map_irq, const char *name)
 {
@@ -985,7 +1053,7 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
     qdev_init_nofail(&dev->qdev);
 
     s = DO_UPCAST(PCIBridge, dev, dev);
-    pci_register_secondary_bus(&s->bus, &s->dev, map_irq, name);
+    pci_register_secondary_bus(bus, &s->bus, &s->dev, map_irq, name);
     return &s->bus;
 }
 
@@ -1148,7 +1216,8 @@ 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,
-                   pci_bus_num(d->bus), PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
+                   d->config[PCI_SECONDARY_BUS],
+                   PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
                    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),
@@ -1169,6 +1238,7 @@ static PCIDeviceInfo bridge_info = {
     .qdev.name    = "pci-bridge",
     .qdev.size    = sizeof(PCIBridge),
     .init         = pci_bridge_initfn,
+    .exit         = pci_bridge_exitfn,
     .config_write = pci_bridge_write_config,
     .qdev.props   = (Property[]) {
         DEFINE_PROP_HEX32("vendorid", PCIBridge, vid, 0),
diff --git a/hw/pci.h b/hw/pci.h
index e83faf5..b16f8f8 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -118,6 +118,7 @@ typedef struct PCIIORegion {
 #define  PCI_BASE_ADDRESS_MEM_PREFETCH	0x08	/* prefetchable? */
 #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
 #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
+#define PCI_SUBORDINATE_BUS	0x1a	/* Highest bus number behind the bridge */
 #define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
 #define PCI_SUBSYSTEM_VENDOR_ID 0x2c    /* 16 bits */
 #define PCI_SUBSYSTEM_ID        0x2e    /* 16 bits */
@@ -267,9 +268,10 @@ PCIDevice *pci_nic_init_nofail(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);
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
 
 int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 20/32] pci: factor out the conversion logic from io port address into pci device.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (18 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 19/32] pci: make pci configuration transaction more accurate Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-11-03 13:52   ` [Qemu-devel] " Michael S. Tsirkin
  2009-11-10 15:56   ` Michael S. Tsirkin
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 21/32] pci: move pci host stuff from pci.c to pci_host.c Isaku Yamahata
                   ` (11 subsequent siblings)
  31 siblings, 2 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

factor out the logic which converts io port address into pci device
and offset in PCI configuration space.

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

diff --git a/hw/pci.c b/hw/pci.c
index 3e5780a..d0a96c6 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -663,24 +663,33 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
         pci_update_mappings(d);
 }
 
+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 int pci_addr_to_config(uint32_t addr)
+{
+    return addr & (PCI_CONFIG_SPACE_SIZE - 1);
+}
+
 void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
 {
     PCIBus *s = opaque;
     PCIDevice *pci_dev;
-    int config_addr, bus_num;
+    int config_addr;
 
 #if 0
     PCI_DPRINTF("pci_data_write: addr=%08x val=%08x 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];
+    pci_dev = pci_addr_to_dev(s, addr);
     if (!pci_dev)
         return;
     config_addr = addr & 0xff;
+    config_addr = pci_addr_to_config(addr);
     PCI_DPRINTF("pci_config_write: %s: addr=%02x val=%08x len=%d\n",
                 pci_dev->name, config_addr, val, len);
     pci_dev->config_write(pci_dev, config_addr, val, len);
@@ -690,16 +699,11 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
 {
     PCIBus *s = opaque;
     PCIDevice *pci_dev;
-    int config_addr, bus_num;
+    int config_addr;
     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];
+    pci_dev = pci_addr_to_dev(s, addr);
     if (!pci_dev) {
-    fail:
         switch(len) {
         case 1:
             val = 0xff;
@@ -714,7 +718,7 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
         }
         goto the_end;
     }
-    config_addr = addr & 0xff;
+    config_addr = pci_addr_to_config(addr);
     val = pci_dev->config_read(pci_dev, config_addr, len);
     PCI_DPRINTF("pci_config_read: %s: addr=%02x val=%08x len=%d\n",
                 pci_dev->name, config_addr, val, len);
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 21/32] pci: move pci host stuff from pci.c to pci_host.c
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (19 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 20/32] pci: factor out the conversion logic from io port address into pci device Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-11-03 14:04   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 22/32] pci_host: change the signature of pci_data_{read, write} Isaku Yamahata
                   ` (10 subsequent siblings)
  31 siblings, 1 reply; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

Move pci host stuff from pci.c to pci_host.c.
And add some comments.
Later pcie host bridge functions will be defined in pcie_host.c
not to bloat pci.c.

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

diff --git a/hw/pci.c b/hw/pci.c
index d0a96c6..a599996 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -663,73 +663,6 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
         pci_update_mappings(d);
 }
 
-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 int pci_addr_to_config(uint32_t addr)
-{
-    return addr & (PCI_CONFIG_SPACE_SIZE - 1);
-}
-
-void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
-{
-    PCIBus *s = opaque;
-    PCIDevice *pci_dev;
-    int config_addr;
-
-#if 0
-    PCI_DPRINTF("pci_data_write: addr=%08x val=%08x len=%d\n",
-                addr, val, len);
-#endif
-    pci_dev = pci_addr_to_dev(s, addr);
-    if (!pci_dev)
-        return;
-    config_addr = addr & 0xff;
-    config_addr = pci_addr_to_config(addr);
-    PCI_DPRINTF("pci_config_write: %s: addr=%02x val=%08x len=%d\n",
-                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)
-{
-    PCIBus *s = opaque;
-    PCIDevice *pci_dev;
-    int config_addr;
-    uint32_t val;
-
-    pci_dev = pci_addr_to_dev(s, addr);
-    if (!pci_dev) {
-        switch(len) {
-        case 1:
-            val = 0xff;
-            break;
-        case 2:
-            val = 0xffff;
-            break;
-        default:
-        case 4:
-            val = 0xffffffff;
-            break;
-        }
-        goto the_end;
-    }
-    config_addr = pci_addr_to_config(addr);
-    val = pci_dev->config_read(pci_dev, config_addr, len);
-    PCI_DPRINTF("pci_config_read: %s: addr=%02x val=%08x 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",
-                addr, val, len);
-#endif
-    return val;
-}
-
 /***********************************************************/
 /* generic PCI irq support */
 
diff --git a/hw/pci_host.c b/hw/pci_host.c
index 6009e37..351ade4 100644
--- a/hw/pci_host.c
+++ b/hw/pci_host.c
@@ -32,6 +32,69 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
 #define PCI_DPRINTF(fmt, ...)
 #endif
 
+/*
+ * PCI address
+ * bit 16 - 24: bus number
+ * bit  8 - 15: devfun number
+ * bit  0 -  7: offset in configuration space of a given pci device
+ */
+
+/* the helper functio to get a PCIDeice* for a given pci address */
+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 & (PCI_CONFIG_SPACE_SIZE - 1);
+}
+
+void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
+{
+    PCIBus *s = opaque;
+    PCIDevice *pci_dev = pci_addr_to_dev(s, addr);
+    uint32_t config_addr = pci_addr_to_config(addr);
+
+    if (!pci_dev)
+        return;
+
+    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)
+{
+    PCIBus *s = opaque;
+    PCIDevice *pci_dev = pci_addr_to_dev(s, addr);
+    uint32_t config_addr = pci_addr_to_config(addr);
+    uint32_t val;
+
+    if (!pci_dev) {
+        switch(len) {
+        case 1:
+            val = 0xff;
+            break;
+        case 2:
+            val = 0xffff;
+            break;
+        default:
+        case 4:
+            val = 0xffffffff;
+            break;
+        }
+    } 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);
+    }
+
+    return val;
+}
+
 static void pci_host_config_writel(void *opaque, target_phys_addr_t addr,
                                    uint32_t val)
 {
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 22/32] pci_host: change the signature of pci_data_{read, write}.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (20 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 21/32] pci: move pci host stuff from pci.c to pci_host.c Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-11-10 15:57   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 23/32] vmstate: introduce VMSTATE_BUFFER_UNSAFE_INFO Isaku Yamahata
                   ` (9 subsequent siblings)
  31 siblings, 1 reply; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

change the first argument, void *opaque to PCIBus *s
of the pci_data_{read, write}.
They aren't used as direct callback so the argument type
don't have to be void*. So change it to the right type.

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

diff --git a/hw/pci.h b/hw/pci.h
index b16f8f8..4f4266d 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -265,8 +265,8 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
                         const char *default_devaddr);
 PCIDevice *pci_nic_init_nofail(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 pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len);
+uint32_t pci_data_read(PCIBus *s, 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);
diff --git a/hw/pci_host.c b/hw/pci_host.c
index 351ade4..f4518dc 100644
--- a/hw/pci_host.c
+++ b/hw/pci_host.c
@@ -52,9 +52,8 @@ static inline uint32_t pci_addr_to_config(uint32_t addr)
     return addr & (PCI_CONFIG_SPACE_SIZE - 1);
 }
 
-void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
+void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
 {
-    PCIBus *s = opaque;
     PCIDevice *pci_dev = pci_addr_to_dev(s, addr);
     uint32_t config_addr = pci_addr_to_config(addr);
 
@@ -66,9 +65,8 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
     pci_dev->config_write(pci_dev, config_addr, val, len);
 }
 
-uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
+uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
 {
-    PCIBus *s = opaque;
     PCIDevice *pci_dev = pci_addr_to_dev(s, addr);
     uint32_t config_addr = pci_addr_to_config(addr);
     uint32_t val;
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 23/32] vmstate: introduce VMSTATE_BUFFER_UNSAFE_INFO.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (21 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 22/32] pci_host: change the signature of pci_data_{read, write} Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 24/32] pci: pcie host and mmcfg support Isaku Yamahata
                   ` (8 subsequent siblings)
  31 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

VMSTATE_BUFFER_UNSAFE_INFO for as a buffer with specified VMStateInfo.
It will be used later.

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

diff --git a/hw/hw.h b/hw/hw.h
index eb5c639..cf8c304 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -485,11 +485,11 @@ extern const VMStateInfo vmstate_info_unused_buffer;
     .offset       = vmstate_offset_buffer(_state, _field) + _start,  \
 }
 
-#define VMSTATE_BUFFER_UNSAFE(_field, _state, _version, _size) {     \
+#define VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, _info, _size) { \
     .name       = (stringify(_field)),                               \
     .version_id = (_version),                                        \
     .size       = (_size),                                           \
-    .info       = &vmstate_info_buffer,                              \
+    .info       = &(_info),                                          \
     .flags      = VMS_BUFFER,                                        \
     .offset     = offsetof(_state, _field),                          \
 }
@@ -670,6 +670,9 @@ extern const VMStateDescription vmstate_i2c_slave;
 #define VMSTATE_BUFFER_TEST(_f, _s, _test)                            \
     VMSTATE_STATIC_BUFFER(_f, _s, 0, _test, 0, sizeof(typeof_field(_s, _f)))
 
+#define VMSTATE_BUFFER_UNSAFE(_field, _state, _version, _size)        \
+    VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, vmstate_info_buffer, _size)
+
 #define VMSTATE_UNUSED_V(_v, _size)                                   \
     VMSTATE_UNUSED_BUFFER(NULL, _v, _size)
 
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 24/32] pci: pcie host and mmcfg support.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (22 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 23/32] vmstate: introduce VMSTATE_BUFFER_UNSAFE_INFO Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-11-03 14:50   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 25/32] pci: add helper functions to check ranges overlap Isaku Yamahata
                   ` (7 subsequent siblings)
  31 siblings, 1 reply; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 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>
---
 Makefile.target |    2 +-
 hw/hw.h         |   11 +++
 hw/pci.c        |   86 +++++++++++++++++++++----
 hw/pci.h        |   27 +++++++-
 hw/pcie_host.c  |  192 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/pcie_host.h  |   50 ++++++++++++++
 6 files changed, 349 insertions(+), 19 deletions(-)
 create mode 100644 hw/pcie_host.c
 create mode 100644 hw/pcie_host.h

diff --git a/Makefile.target b/Makefile.target
index db0d0ab..bc3c375 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -154,7 +154,7 @@ endif #CONFIG_BSD_USER
 # System emulator target
 ifdef CONFIG_SOFTMMU
 
-obj-y = vl.o async.o monitor.o pci.o pci_host.o machine.o gdbstub.o
+obj-y = vl.o async.o monitor.o pci.o pci_host.o pcie_host.o machine.o gdbstub.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
 obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o virtio-pci.o
diff --git a/hw/hw.h b/hw/hw.h
index cf8c304..1d4af2a 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -512,6 +512,17 @@ extern const VMStateDescription vmstate_pci_device;
     .offset     = vmstate_offset_value(_state, _field, PCIDevice),   \
 }
 
+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     = vmstate_offset_value(_state, _field, PCIDevice),   \
+}
+
 extern const VMStateDescription vmstate_i2c_slave;
 
 #define VMSTATE_I2C_SLAVE(_field, _state) {                          \
diff --git a/hw/pci.c b/hw/pci.c
index a599996..67133b6 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"
@@ -248,18 +249,24 @@ static uint8_t pci_sub_bus(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[PCI_CONFIG_SPACE_SIZE];
+    uint8_t *config;
     int i;
 
-    assert(size == sizeof config);
-    qemu_get_buffer(f, config, sizeof config);
-    for (i = 0; i < sizeof config; ++i)
-        if ((config[i] ^ s->config[i]) & s->cmask[i] & ~s->wmask[i])
+    assert(size == pci_config_size(s));
+    config = qemu_malloc(size);
+
+    qemu_get_buffer(f, config, size);
+    for (i = 0; i < size; ++i) {
+        if ((config[i] ^ s->config[i]) & s->cmask[i] & ~s->wmask[i]) {
+            qemu_free(config);
             return -EINVAL;
-    memcpy(s->config, config, sizeof config);
+        }
+    }
+    memcpy(s->config, config, size);
 
     pci_update_mappings(s);
 
+    qemu_free(config);
     return 0;
 }
 
@@ -267,6 +274,7 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
 static void put_pci_config_device(QEMUFile *f, void *pv, size_t size)
 {
     const uint8_t *v = pv;
+    assert(size == pci_config_size(container_of(pv, PCIDevice, config)));
     qemu_put_buffer(f, v, size);
 }
 
@@ -283,21 +291,42 @@ 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_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
+                                   vmstate_info_pci_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_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
+                                   vmstate_info_pci_config,
+                                   PCIE_CONFIG_SPACE_SIZE),
         VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
         VMSTATE_END_OF_LIST()
     }
 };
 
+static inline const VMStateDescription *pci_get_vmstate(PCIDevice *s)
+{
+    return pci_is_express(s) ? &vmstate_pcie_device : &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)
@@ -406,14 +435,34 @@ static void pci_init_cmask(PCIDevice *dev)
 static void pci_init_wmask(PCIDevice *dev)
 {
     int i;
+    int config_size = pci_config_size(dev);
+
     dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
     dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
     pci_set_word(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 = pci_config_size(pci_dev);
+
+    pci_dev->config = qemu_mallocz(config_size);
+    pci_dev->cmask = qemu_mallocz(config_size);
+    pci_dev->wmask = qemu_mallocz(config_size);
+    pci_dev->used = qemu_mallocz(config_size);
+}
+
+static void pci_config_free(PCIDevice *pci_dev)
+{
+    qemu_free(pci_dev->config);
+    qemu_free(pci_dev->cmask);
+    qemu_free(pci_dev->wmask);
+    qemu_free(pci_dev->used);
+}
+
 /* -1 for devfn means auto assign */
 static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
                                          const char *name, int devfn,
@@ -434,6 +483,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);
@@ -501,6 +551,7 @@ static int pci_unregister_device(DeviceState *dev)
 
     qemu_free_irqs(pci_dev->irq);
     pci_dev->bus->devices[pci_dev->devfn] = NULL;
+    pci_config_free(pci_dev);
     return 0;
 }
 
@@ -641,7 +692,7 @@ uint32_t pci_default_read_config(PCIDevice *d,
 {
     uint32_t val = 0;
     assert(len == 1 || len == 2 || len == 4);
-    len = MIN(len, PCI_CONFIG_SPACE_SIZE - address);
+    len = MIN(len, pci_config_size(d) - address);
     memcpy(&val, d->config + address, len);
     return le32_to_cpu(val);
 }
@@ -650,10 +701,11 @@ 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 = pci_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);
     }
@@ -1001,6 +1053,11 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
     PCIBus *bus;
     int devfn, rc;
 
+    /* initialize cap_present for pci_is_express() and pci_config_size() */
+    if (info->is_express) {
+        pci_dev->cap_present |= QEMU_PCI_CAP_EXPRESS;
+    }
+
     bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
     devfn = pci_dev->devfn;
     pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn,
@@ -1057,9 +1114,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 = pci_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 4f4266d..8e5d64a 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -163,28 +163,31 @@ typedef struct PCIIORegion {
 #define PCI_CONFIG_HEADER_SIZE 0x40
 /* Size of the standard PCI config space */
 #define PCI_CONFIG_SPACE_SIZE 0x100
+/* Size of the standart PCIe config space: 4KB */
+#define PCIE_CONFIG_SPACE_SIZE  0x1000
 
 #define PCI_NUM_PINS 4 /* A-D */
 
 /* Bits in cap_present field. */
 enum {
     QEMU_PCI_CAP_MSIX = 0x1,
+    QEMU_PCI_CAP_EXPRESS = 0x2,
 };
 
 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;
@@ -354,6 +357,12 @@ typedef struct {
     PCIUnregisterFunc *exit;
     PCIConfigReadFunc *config_read;
     PCIConfigWriteFunc *config_write;
+
+    /* pcie stuff */
+    int is_express;   /* is this device pci express?
+                       * initialization code needs to know this before
+                       * each specific device initialization.
+                       */
 } PCIDeviceInfo;
 
 void pci_qdev_register(PCIDeviceInfo *info);
@@ -362,6 +371,16 @@ void pci_qdev_register_many(PCIDeviceInfo *info);
 PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name);
 PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
 
+static inline int pci_is_express(PCIDevice *d)
+{
+    return d->cap_present & QEMU_PCI_CAP_EXPRESS;
+}
+
+static inline uint32_t pci_config_size(PCIDevice *d)
+{
+    return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE;
+}
+
 /* lsi53c895a.c */
 #define LSI_MAX_DEVS 7
 
diff --git a/hw/pcie_host.c b/hw/pcie_host.c
new file mode 100644
index 0000000..b52fec6
--- /dev/null
+++ b/hw/pcie_host.c
@@ -0,0 +1,192 @@
+/*
+ * pcie_host.c
+ * utility functions for pci express host bridge.
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "hw.h"
+#include "pci.h"
+#include "pcie_host.h"
+
+/*
+ * PCI express mmcfig address
+ * bit 20 - 28: bus number
+ * bit 15 - 19: device number
+ * bit 12 - 14: function number
+ * bit  0 - 11: offset in configuration space of a given device
+ */
+#define PCIE_MMCFG_SIZE_MAX             (1ULL << 28)
+#define PCIE_MMCFG_SIZE_MIN             (1ULL << 20)
+#define PCIE_MMCFG_BUS_BIT              20
+#define PCIE_MMCFG_BUS_MASK             0x1ff
+#define PCIE_MMCFG_DEVFN_BIT            12
+#define PCIE_MMCFG_DEVFN_MASK           0xff
+#define PCIE_MMCFG_CONFOFFSET_MASK      0xfff
+#define PCIE_MMCFG_BUS(addr)            (((addr) >> PCIE_MMCFG_BUS_BIT) & \
+                                         PCIE_MMCFG_BUS_MASK)
+#define PCIE_MMCFG_DEVFN(addr)          (((addr) >> PCIE_MMCFG_DEVFN_BIT) & \
+                                         PCIE_MMCFG_DEVFN_MASK)
+#define PCIE_MMCFG_CONFOFFSET(addr)     ((addr) & PCIE_MMCFG_CONFOFFSET_MASK)
+
+
+/* a helper function to get a PCIDevice for a given mmconfig address */
+static inline PCIDevice *pcie_mmcfg_addr_to_dev(PCIBus *s, uint32_t mmcfg_addr)
+{
+    return pci_find_device(s, PCIE_MMCFG_BUS(mmcfg_addr),
+                           PCI_SLOT(PCIE_MMCFG_DEVFN(mmcfg_addr)),
+                           PCI_FUNC(PCIE_MMCFG_DEVFN(mmcfg_addr)));
+}
+
+static void pcie_mmcfg_data_write(PCIBus *s,
+                                  uint32_t mmcfg_addr, uint32_t val, int len)
+{
+    PCIDevice *pci_dev = pcie_mmcfg_addr_to_dev(s, mmcfg_addr);
+
+    if (!pci_dev)
+        return;
+
+    pci_dev->config_write(pci_dev,
+                          PCIE_MMCFG_CONFOFFSET(mmcfg_addr), val, len);
+}
+
+static uint32_t pcie_mmcfg_data_read(PCIBus *s,
+                                     uint32_t mmcfg_addr, int len)
+{
+    PCIDevice *pci_dev = pcie_mmcfg_addr_to_dev(s, mmcfg_addr);
+    uint32_t val;
+
+    if (!pci_dev) {
+        switch(len) {
+        case 1:
+            val = 0xff;
+            break;
+        case 2:
+            val = 0xffff;
+            break;
+        default:
+        case 4:
+            val = 0xffffffff;
+            break;
+        }
+    } else {
+        val = pci_dev->config_read(pci_dev,
+                                   PCIE_MMCFG_CONFOFFSET(mmcfg_addr), len);
+    }
+
+    return val;
+}
+
+static void pcie_mmcfg_data_writeb(void *opaque,
+                                   target_phys_addr_t addr, uint32_t value)
+{
+    PCIExpressHost *e = opaque;
+    pcie_mmcfg_data_write(e->pci.bus, addr - e->base_addr, value, 1);
+}
+
+static void pcie_mmcfg_data_writew(void *opaque,
+                                   target_phys_addr_t addr, uint32_t value)
+{
+    PCIExpressHost *e = opaque;
+    pcie_mmcfg_data_write(e->pci.bus, addr - e->base_addr, value, 2);
+}
+
+static void pcie_mmcfg_data_writel(void *opaque,
+                                   target_phys_addr_t addr, uint32_t value)
+{
+    PCIExpressHost *e = opaque;
+    pcie_mmcfg_data_write(e->pci.bus, addr - e->base_addr, value, 4);
+}
+
+static uint32_t pcie_mmcfg_data_readb(void *opaque, target_phys_addr_t addr)
+{
+    PCIExpressHost *e = opaque;
+    return pcie_mmcfg_data_read(e->pci.bus, addr - e->base_addr, 1);
+}
+
+static uint32_t pcie_mmcfg_data_readw(void *opaque, target_phys_addr_t addr)
+{
+    PCIExpressHost *e = opaque;
+    return pcie_mmcfg_data_read(e->pci.bus, addr - e->base_addr, 2);
+}
+
+static uint32_t pcie_mmcfg_data_readl(void *opaque, target_phys_addr_t addr)
+{
+    PCIExpressHost *e = opaque;
+    return pcie_mmcfg_data_read(e->pci.bus, addr - e->base_addr, 4);
+}
+
+
+static CPUWriteMemoryFunc * const pcie_mmcfg_write[] =
+{
+    pcie_mmcfg_data_writeb,
+    pcie_mmcfg_data_writew,
+    pcie_mmcfg_data_writel,
+};
+
+static CPUReadMemoryFunc * const pcie_mmcfg_read[] =
+{
+    pcie_mmcfg_data_readb,
+    pcie_mmcfg_data_readw,
+    pcie_mmcfg_data_readl,
+};
+
+/* pcie_host::base_addr == PCIE_BASE_ADDR_UNMAPPED when it isn't mapped. */
+#define PCIE_BASE_ADDR_UNMAPPED  ((target_phys_addr_t)-1ULL)
+
+int pcie_host_init(PCIExpressHost *e)
+{
+    e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
+    e->mmio_index =
+        cpu_register_io_memory(pcie_mmcfg_read, pcie_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_UNMAPPED) {
+        cpu_register_physical_memory(e->base_addr, e->size, IO_MEM_UNASSIGNED);
+        e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
+    }
+}
+
+void pcie_host_mmcfg_map(PCIExpressHost *e,
+                         target_phys_addr_t addr, uint32_t size)
+{
+    assert(!(size & (size - 1)));       /* power of 2 */
+    assert(size >= PCIE_MMCFG_SIZE_MIN);
+    assert(size <= PCIE_MMCFG_SIZE_MAX);
+
+    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);
+    }
+}
diff --git a/hw/pcie_host.h b/hw/pcie_host.h
new file mode 100644
index 0000000..a7771c9
--- /dev/null
+++ b/hw/pcie_host.h
@@ -0,0 +1,50 @@
+/*
+ * pcie_host.h
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PCIE_HOST_H
+#define PCIE_HOST_H
+
+#include "pci_host.h"
+
+typedef struct {
+    PCIHostState pci;
+
+    /* express part */
+
+    /* base address where MMCONFIG area is mapped. */
+    target_phys_addr_t  base_addr;
+
+    /* the size of MMCONFIG area. It's host bridge dependent */
+    target_phys_addr_t  size;
+
+    /* result of cpu_register_io_memory() to map MMCONFIG area */
+    int mmio_index;
+} PCIExpressHost;
+
+int pcie_host_init(PCIExpressHost *e);
+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 /* PCIE_HOST_H */
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 25/32] pci: add helper functions to check ranges overlap.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (23 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 24/32] pci: pcie host and mmcfg support Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-11-03 14:18   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 26/32] pci: use range helper functions Isaku Yamahata
                   ` (6 subsequent siblings)
  31 siblings, 1 reply; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

add helper function to check ranges overlap suggested by
Michael S. Tsirkin <mst@redhat.com>.
His original suggestion was to use [first, last], however I chosen
to use offset, length pair, i.e. [offset, offset + length)
because pci configuration space related functions all uses offset and length
pair, so it helps to avoid to type constant twice.

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

diff --git a/hw/pci.h b/hw/pci.h
index 8e5d64a..7991bfd 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -406,4 +406,33 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
 PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                             void *pic, int devfn_min, int nirq);
 
+/* These are not pci specific. Should move into a separate header.
+ * Only pci.c uses them, so keep them here for now.
+ */
+
+/* Get last byte of a range from offset + length.
+ * Undefined for ranges that wrap around 0. */
+static inline uint64_t range_get_last(uint64_t offset, uint64_t len)
+{
+    return offset + len - 1;
+}
+
+/* Check whether a given range covers a given byte. */
+static inline int range_covers_byte(uint64_t offset, uint64_t len,
+                                    uint64_t byte)
+{
+    return offset <= byte && byte <= range_get_last(offset, len);
+}
+
+/* Check whether 2 given ranges overlap.
+ * Undefined if ranges that wrap around 0. */
+static inline int ranges_overlap(uint64_t first1, uint64_t len1,
+                                 uint64_t first2, uint64_t len2)
+{
+    uint64_t last1 = range_get_last(first1, len1);
+    uint64_t last2 = range_get_last(first2, len2);
+
+    return !(last2 < first1 || last1 < first2);
+}
+
 #endif
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 26/32] pci: use range helper functions.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (24 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 25/32] pci: add helper functions to check ranges overlap Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-11-03 14:19   ` [Qemu-devel] " Michael S. Tsirkin
  2009-11-10 15:59   ` Michael S. Tsirkin
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 27/32] pci: teach pci_default_config_write() ROM bar for normal/bridge device Isaku Yamahata
                   ` (5 subsequent siblings)
  31 siblings, 2 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

clean up pci_default_write_config() by the range helper functions.

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

diff --git a/hw/pci.c b/hw/pci.c
index 67133b6..d9fd564 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -699,19 +699,15 @@ 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 = pci_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)
-        || ((orig[PCI_COMMAND] ^ d->config[PCI_COMMAND])
-            & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)))
+    if (ranges_overlap(addr, l, PCI_BASE_ADDRESS_0, 24) ||
+        range_covers_byte(addr, l, PCI_COMMAND))
         pci_update_mappings(d);
 }
 
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 27/32] pci: teach pci_default_config_write() ROM bar for normal/bridge device .
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (25 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 26/32] pci: use range helper functions Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-11-03 14:20   ` [Qemu-devel] " Michael S. Tsirkin
  2009-11-10 16:01   ` Michael S. Tsirkin
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 28/32] pci: initialize pci config headers depending it pci header type Isaku Yamahata
                   ` (4 subsequent siblings)
  31 siblings, 2 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 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()
Also update pci mapping when PCI_ROM_ADDRESS1 is written for header type 1.

pci_update_mapping() path isn't performance critical,
so call it even independent of header type.

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

diff --git a/hw/pci.c b/hw/pci.c
index d9fd564..46b22ec 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -707,6 +707,8 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
         d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
     }
     if (ranges_overlap(addr, l, PCI_BASE_ADDRESS_0, 24) ||
+        ranges_overlap(addr, l, PCI_ROM_ADDRESS, 4) ||
+        ranges_overlap(addr, l, PCI_ROM_ADDRESS1, 4) ||
         range_covers_byte(addr, l, PCI_COMMAND))
         pci_update_mappings(d);
 }
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 28/32] pci: initialize pci config headers depending it pci header type.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (26 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 27/32] pci: teach pci_default_config_write() ROM bar for normal/bridge device Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-11-03 14:27   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 29/32] pci: cosmetic on pci_upadte_mappings() Isaku Yamahata
                   ` (3 subsequent siblings)
  31 siblings, 1 reply; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

- Only sets default subsystem id for header type 00.(normal header type)
  because header type 01 doesn't have subsystem id, and uses the register
  for other purpose. So setting default subsystem id doesn't make sense.

- initialize wmask more for header type 01.(bridge header type)
  Without those wmasks, linux was confused not boot,
  and lspci was confused not to print out expected IO/memory range.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/cirrus_vga.c |    1 -
 hw/pci.c        |   42 ++++++++++++++++++++++++++++++++++++++----
 hw/pci.h        |   29 +++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+), 5 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index ef72c62..c1bafd3 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -180,7 +180,6 @@
 #define PCI_COMMAND_PALETTESNOOPING         0x0020
 #define PCI_COMMAND_PARITYDETECTION         0x0040
 #define PCI_COMMAND_ADDRESSDATASTEPPING     0x0080
-#define PCI_COMMAND_SERR                    0x0100
 #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 46b22ec..beefae3 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -445,6 +445,30 @@ static void pci_init_wmask(PCIDevice *dev)
         dev->wmask[i] = 0xff;
 }
 
+static void pci_init_wmask_bridge(PCIDevice *d)
+{
+    /* PCI_PRIMARY_BUS, PCI_SECONDARY_BUS, PCI_SUBORDINATE_BUS and
+       PCI_SEC_LETENCY_TIMER */
+    memset(d->wmask + PCI_PRIMARY_BUS, 0xff, 4);
+
+    /* base and limit */
+    d->wmask[PCI_IO_BASE] = PCI_IO_RANGE_MASK & 0xff;
+    d->wmask[PCI_IO_LIMIT] = PCI_IO_RANGE_MASK & 0xff;
+    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_PREF_BASE_UPPER32 and PCI_PREF_LIMIT_UPPER32 */
+    memset(d->wmask + PCI_PREF_BASE_UPPER32, 0xff, 8);
+
+    pci_set_word(d->wmask + PCI_BRIDGE_CONTROL, 0xffff);
+}
+
 static void pci_config_alloc(PCIDevice *pci_dev)
 {
     int config_size = pci_config_size(pci_dev);
@@ -467,7 +491,8 @@ static void pci_config_free(PCIDevice *pci_dev)
 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,
+                                         uint8_t header_type)
 {
     if (devfn < 0) {
         for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) {
@@ -484,9 +509,16 @@ 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);
+
+    header_type &= ~PCI_HEADER_TYPE_MULTI_FUNCTION;
+    if (header_type == PCI_HEADER_TYPE_NORMAL) {
+        pci_set_default_subsystem_id(pci_dev);
+    }
     pci_init_cmask(pci_dev);
     pci_init_wmask(pci_dev);
+    if (header_type == PCI_HEADER_TYPE_BRIDGE) {
+        pci_init_wmask_bridge(pci_dev);
+    }
 
     if (!config_read)
         config_read = pci_default_read_config;
@@ -509,7 +541,8 @@ 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_HEADER_TYPE_NORMAL);
     return pci_dev;
 }
 static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
@@ -1059,7 +1092,8 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
     bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
     devfn = pci_dev->devfn;
     pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn,
-                                     info->config_read, info->config_write);
+                                     info->config_read, info->config_write,
+                                     info->header_type);
     assert(pci_dev);
     rc = info->init(pci_dev);
     if (rc != 0)
diff --git a/hw/pci.h b/hw/pci.h
index 7991bfd..3f50294 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -100,6 +100,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 */
@@ -119,16 +127,30 @@ typedef struct PCIIORegion {
 #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
 #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
 #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_MASK      (~0x0fUL)
 #define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
+#define PCI_MEMORY_BASE         0x20    /* Memory range behind */
+#define PCI_MEMORY_LIMIT        0x22
+#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_MASK    (~0x0fUL)
+#define PCI_PREF_BASE_UPPER32   0x28    /* Upper half of prefetchable memory range */
 #define PCI_SUBSYSTEM_VENDOR_ID 0x2c    /* 16 bits */
 #define PCI_SUBSYSTEM_ID        0x2e    /* 16 bits */
 #define PCI_ROM_ADDRESS		0x30	/* Bits 31..11 are address, 10..1 reserved */
 #define  PCI_ROM_ADDRESS_ENABLE	0x01
+#define PCI_IO_BASE_UPPER16     0x30    /* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16    0x32
 #define PCI_CAPABILITY_LIST	0x34	/* Offset of first capability list entry */
 #define PCI_ROM_ADDRESS1	0x38	/* Same as PCI_ROM_ADDRESS, but for htype 1 */
 #define PCI_INTERRUPT_LINE	0x3c	/* 8 bits */
 #define PCI_INTERRUPT_PIN	0x3d	/* 8 bits */
 #define PCI_MIN_GNT		0x3e	/* 8 bits */
+#define PCI_BRIDGE_CONTROL      0x3e
 #define PCI_MAX_LAT		0x3f	/* 8 bits */
 
 /* Capability lists */
@@ -358,6 +380,13 @@ typedef struct {
     PCIConfigReadFunc *config_read;
     PCIConfigWriteFunc *config_write;
 
+    /* pci config header type */
+    uint8_t header_type;        /* this is necessary for initialization
+                                 * code to know its header type before
+                                 * device specific code can initialize
+                                 * configuration space.
+                                 */
+
     /* pcie stuff */
     int is_express;   /* is this device pci express?
                        * initialization code needs to know this before
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 29/32] pci: cosmetic on pci_upadte_mappings()
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (27 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 28/32] pci: initialize pci config headers depending it pci header type Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-11-03 14:17   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 30/32] pci: factor out pci_for_each_device() Isaku Yamahata
                   ` (2 subsequent siblings)
  31 siblings, 1 reply; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

Remove one indentation of pci_update_mappings.
Just for cosmetics, no logic change.

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

diff --git a/hw/pci.c b/hw/pci.c
index beefae3..b43f6c6 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -637,86 +637,92 @@ 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 (r->size != 0) {
-            if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
-                if (cmd & PCI_COMMAND_IO) {
-                    new_addr = pci_get_long(d->config + pci_bar(d, i));
-                    new_addr = new_addr & ~(r->size - 1);
-                    last_addr = new_addr + r->size - 1;
-                    /* NOTE: we have only 64K ioports on PC */
-                    if (last_addr <= new_addr || new_addr == 0 ||
-                        last_addr >= 0x10000) {
-                        new_addr = PCI_BAR_UNMAPPED;
-                    }
-                } else {
+
+        /* this region isn't registered */
+        if (r->size == 0)
+            continue;
+
+        if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
+            if (cmd & PCI_COMMAND_IO) {
+                new_addr = pci_get_long(d->config + pci_bar(d, i));
+                new_addr = new_addr & ~(r->size - 1);
+                last_addr = new_addr + r->size - 1;
+                /* NOTE: we have only 64K ioports on PC */
+                if (last_addr <= new_addr || new_addr == 0 ||
+                    last_addr >= 0x10000) {
                     new_addr = PCI_BAR_UNMAPPED;
                 }
             } else {
-                if (cmd & PCI_COMMAND_MEMORY) {
-                    if (r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-                        new_addr = pci_get_quad(d->config + pci_bar(d, i));
-                    } else {
-                        new_addr = pci_get_long(d->config + pci_bar(d, i));
-                    }
-                    /* the ROM slot has a specific enable bit */
-                    if (i == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE))
-                        goto no_mem_map;
-                    new_addr = new_addr & ~(r->size - 1);
-                    last_addr = new_addr + r->size - 1;
-                    /* NOTE: we do not support wrapping */
-                    /* XXX: as we cannot support really dynamic
-                       mappings, we handle specific values as invalid
-                       mappings. */
-                    if (last_addr <= new_addr || new_addr == 0 ||
-                        last_addr == PCI_BAR_UNMAPPED ||
-
-                        /* Now pcibus_t is 64bit.
-                         * Check if 32 bit BAR wrap around explicitly.
-                         * Without this, PC ide doesn't work well.
-                         * TODO: remove this work around.
-                         */
-                        (!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) &&
-                         last_addr >= UINT32_MAX) ||
-
-                        /*
-                         * OS is allowed to set BAR beyond its addressable
-                         * bits. For example, 32 bit OS can set 64bit bar
-                         * to >4G. Check it.
-                         */
-                        last_addr >= TARGET_PHYS_ADDR_MAX) {
-                        new_addr = PCI_BAR_UNMAPPED;
-                    }
+                new_addr = PCI_BAR_UNMAPPED;
+            }
+        } else {
+            if (cmd & PCI_COMMAND_MEMORY) {
+                if (r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+                    new_addr = pci_get_quad(d->config + pci_bar(d, i));
                 } else {
-                no_mem_map:
+                    new_addr = pci_get_long(d->config + pci_bar(d, i));
+                }
+                /* the ROM slot has a specific enable bit */
+                if (i == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE))
+                    goto no_mem_map;
+                new_addr = new_addr & ~(r->size - 1);
+                last_addr = new_addr + r->size - 1;
+                /* NOTE: we do not support wrapping */
+                /* XXX: as we cannot support really dynamic
+                   mappings, we handle specific values as invalid
+                   mappings. */
+                if (last_addr <= new_addr || new_addr == 0 ||
+                    last_addr == PCI_BAR_UNMAPPED ||
+
+                    /* Now pcibus_t is 64bit.
+                     * Check if 32 bit BAR wrap around explicitly.
+                     * Without this, PC ide doesn't work well.
+                     * TODO: remove this work around.
+                     */
+                    (!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) &&
+                     last_addr >= UINT32_MAX) ||
+
+                    /*
+                     * OS is allowed to set BAR beyond its addressable
+                     * bits. For example, 32 bit OS can set 64bit bar
+                     * to >4G. Check it.
+                     */
+                    last_addr >= TARGET_PHYS_ADDR_MAX) {
                     new_addr = PCI_BAR_UNMAPPED;
                 }
+            } else {
+            no_mem_map:
+                new_addr = PCI_BAR_UNMAPPED;
             }
-            /* now do the real mapping */
-            if (new_addr != r->addr) {
-                if (r->addr != PCI_BAR_UNMAPPED) {
-                    if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
-                        int class;
-                        /* NOTE: specific hack for IDE in PC case:
-                           only one byte must be mapped. */
-                        class = pci_get_word(d->config + PCI_CLASS_DEVICE);
-                        if (class == 0x0101 && r->size == 4) {
-                            isa_unassign_ioport(r->addr + 2, 1);
-                        } else {
-                            isa_unassign_ioport(r->addr, r->size);
-                        }
-                    } else {
-                        cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
-                                                     r->size,
-                                                     IO_MEM_UNASSIGNED);
-                        qemu_unregister_coalesced_mmio(r->addr, r->size);
-                    }
-                }
-                r->addr = new_addr;
-                if (r->addr != PCI_BAR_UNMAPPED) {
-                    r->map_func(d, i, r->addr, r->size, r->type);
+        }
+
+        /* This bar isn't changed */
+        if (new_addr == r->addr)
+            continue;
+
+        /* now do the real mapping */
+        if (r->addr != PCI_BAR_UNMAPPED) {
+            if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
+                int class;
+                /* NOTE: specific hack for IDE in PC case:
+                   only one byte must be mapped. */
+                class = pci_get_word(d->config + PCI_CLASS_DEVICE);
+                if (class == 0x0101 && r->size == 4) {
+                    isa_unassign_ioport(r->addr + 2, 1);
+                } else {
+                    isa_unassign_ioport(r->addr, r->size);
                 }
+            } else {
+                cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
+                                             r->size,
+                                             IO_MEM_UNASSIGNED);
+                qemu_unregister_coalesced_mmio(r->addr, r->size);
             }
         }
+        r->addr = new_addr;
+        if (r->addr != PCI_BAR_UNMAPPED) {
+            r->map_func(d, i, r->addr, r->size, r->type);
+        }
     }
 }
 
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 30/32] pci: factor out pci_for_each_device().
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (28 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 29/32] pci: cosmetic on pci_upadte_mappings() Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-11-03 14:29   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 31/32] pci: implement pci bridge filtering Isaku Yamahata
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 32/32] pci/monitor: print out bridge's filtering values and so on Isaku Yamahata
  31 siblings, 1 reply; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

split out device iteration logic from pci_for_each_device().
factored out function, pci_for_each_device_under_bus() will be used later.

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

diff --git a/hw/pci.c b/hw/pci.c
index b43f6c6..d565f6e 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -885,19 +885,26 @@ static void pci_info_device(PCIBus *bus, PCIDevice *d)
     }
 }
 
-void pci_for_each_device(PCIBus *bus, int bus_num,
-                         void (*fn)(PCIBus *b, PCIDevice *d))
+static void pci_for_each_device_under_bus(PCIBus *bus,
+                                          void (*fn)(PCIBus *b, PCIDevice *d))
 {
     PCIDevice *d;
     int devfn;
 
+    for(devfn = 0; devfn < 256; devfn++) {
+        d = bus->devices[devfn];
+        if (d)
+            fn(bus, d);
+    }
+}
+
+void pci_for_each_device(PCIBus *bus, int bus_num,
+                         void (*fn)(PCIBus *b, PCIDevice *d))
+{
     bus = pci_find_bus(bus, bus_num);
+
     if (bus) {
-        for(devfn = 0; devfn < 256; devfn++) {
-            d = bus->devices[devfn];
-            if (d)
-                fn(bus, d);
-        }
+        pci_for_each_device_under_bus(bus, fn);
     }
 }
 
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 31/32] pci: implement pci bridge filtering.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (29 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 30/32] pci: factor out pci_for_each_device() Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  2009-11-03 15:01   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 32/32] pci/monitor: print out bridge's filtering values and so on Isaku Yamahata
  31 siblings, 1 reply; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

This patch implements pci bridge filtering.

TODO: currently almost all the map funcions assumes
filtered_size == size and addr & ~(size - 1) == addr.
However with bridge filtering, they aren't always true.
Teach them such cases, such that filtered_size < size and
addr & (size - 1) != 0.

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

diff --git a/hw/pci.c b/hw/pci.c
index d565f6e..336c1a3 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -560,10 +560,10 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
         if (!r->size || r->addr == PCI_BAR_UNMAPPED)
             continue;
         if (r->type == PCI_BASE_ADDRESS_SPACE_IO) {
-            isa_unassign_ioport(r->addr, r->size);
+            isa_unassign_ioport(r->addr, r->filtered_size);
         } else {
             cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
-                                                     r->size,
+                                                     r->filtered_size,
                                                      IO_MEM_UNASSIGNED);
         }
     }
@@ -608,6 +608,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     r = &pci_dev->io_regions[region_num];
     r->addr = PCI_BAR_UNMAPPED;
     r->size = size;
+    r->filtered_size = size;
     r->type = type;
     r->map_func = map_func;
 
@@ -628,11 +629,111 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     }
 }
 
+static uint32_t pci_config_get_io_base(PCIDevice *d,
+                                       uint32_t base, uint32_t base_upper16)
+{
+    uint32_t val;
+
+    val = ((uint32_t)d->config[base] & PCI_IO_RANGE_MASK) << 8;
+    if (d->config[base] & PCI_IO_RANGE_TYPE_32) {
+        val |= (uint32_t)pci_get_word(d->config + PCI_IO_BASE_UPPER16) << 16;
+    }
+    return val;
+}
+
+static uint64_t pci_config_get_memory_base(PCIDevice *d, uint32_t base)
+{
+    return ((uint64_t)pci_get_word(d->config + base) & PCI_MEMORY_RANGE_MASK)
+        << 16;
+}
+
+static uint64_t pci_config_get_pref_base(PCIDevice *d,
+                                         uint32_t base, uint32_t upper)
+{
+    uint64_t val;
+    val = ((uint64_t)pci_get_word(d->config + base) &
+           PCI_PREF_RANGE_MASK) << 16;
+    val |= (uint64_t)pci_get_long(d->config + upper) << 32;
+    return val;
+}
+
+static pcibus_t pci_bridge_get_base(PCIDevice *bridge, uint8_t type)
+{
+    pcibus_t base;
+    if (type & PCI_BASE_ADDRESS_SPACE_IO) {
+        base = pci_config_get_io_base(bridge,
+                                      PCI_IO_BASE, PCI_IO_BASE_UPPER16);
+    } else {
+        if (type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+            base = pci_config_get_pref_base(
+                bridge, PCI_PREF_MEMORY_BASE, PCI_PREF_BASE_UPPER32);
+        } else {
+            base = pci_config_get_memory_base(bridge, PCI_MEMORY_BASE);
+        }
+    }
+
+    return base;
+}
+
+static pcibus_t pci_bridge_get_limit(PCIDevice *bridge, uint8_t type)
+{
+    pcibus_t limit;
+    if (type & PCI_BASE_ADDRESS_SPACE_IO) {
+        limit = pci_config_get_io_base(bridge,
+                                      PCI_IO_LIMIT, PCI_IO_LIMIT_UPPER16);
+        limit |= 0xfff;         /* PCI bridge spec 3.2.5.6. */
+    } else {
+        if (type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+            limit = pci_config_get_pref_base(
+                bridge, PCI_PREF_MEMORY_LIMIT, PCI_PREF_LIMIT_UPPER32);
+        } else {
+            limit = pci_config_get_memory_base(bridge, PCI_MEMORY_LIMIT);
+        }
+        limit |= 0xfffff;       /* PCI bridge spec 3.2.5.{1, 8}. */
+    }
+    return limit;
+}
+
+static void pci_bridge_filter(PCIDevice *d, pcibus_t *addr, pcibus_t *size,
+                              uint8_t type)
+{
+    pcibus_t base = *addr;
+    pcibus_t limit = *addr + *size - 1;
+    PCIDevice *br;
+
+    for (br = d->bus->parent_dev; br; br = br->bus->parent_dev) {
+        uint16_t cmd = pci_get_word(d->config + PCI_COMMAND);
+
+        if (type & PCI_BASE_ADDRESS_SPACE_IO) {
+            if (!(cmd & PCI_COMMAND_IO)) {
+                goto no_map;
+            }
+        } else {
+            if (!(cmd & PCI_COMMAND_MEMORY)) {
+                goto no_map;
+            }
+        }
+
+        base = MAX(base, pci_bridge_get_base(br, type));
+        limit = MIN(limit, pci_bridge_get_limit(br, type));
+    }
+
+    if (base > limit) {
+    no_map:
+        *addr = PCI_BAR_UNMAPPED;
+        *size = 0;
+    } else {
+        *addr = base;
+        *size = limit - base + 1;
+    }
+}
+
 static void pci_update_mappings(PCIDevice *d)
 {
     PCIIORegion *r;
     int cmd, i;
     pcibus_t last_addr, new_addr;
+    pcibus_t filtered_size;
 
     cmd = pci_get_word(d->config + PCI_COMMAND);
     for(i = 0; i < PCI_NUM_REGIONS; i++) {
@@ -696,8 +797,14 @@ static void pci_update_mappings(PCIDevice *d)
             }
         }
 
+        /* bridge filtering */
+        filtered_size = r->size;
+        if (new_addr != PCI_BAR_UNMAPPED) {
+            pci_bridge_filter(d, &new_addr, &filtered_size, r->type);
+        }
+
         /* This bar isn't changed */
-        if (new_addr == r->addr)
+        if (new_addr == r->addr && filtered_size == r->filtered_size)
             continue;
 
         /* now do the real mapping */
@@ -710,18 +817,26 @@ static void pci_update_mappings(PCIDevice *d)
                 if (class == 0x0101 && r->size == 4) {
                     isa_unassign_ioport(r->addr + 2, 1);
                 } else {
-                    isa_unassign_ioport(r->addr, r->size);
+                    isa_unassign_ioport(r->addr, r->filtered_size);
                 }
             } else {
                 cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
-                                             r->size,
+                                             r->filtered_size,
                                              IO_MEM_UNASSIGNED);
-                qemu_unregister_coalesced_mmio(r->addr, r->size);
+                qemu_unregister_coalesced_mmio(r->addr, r->filtered_size);
             }
         }
         r->addr = new_addr;
+        r->filtered_size = filtered_size;
         if (r->addr != PCI_BAR_UNMAPPED) {
-            r->map_func(d, i, r->addr, r->size, r->type);
+            /*
+             * TODO: currently almost all the map funcions assumes
+             * filtered_size == size and addr & ~(size - 1) == addr.
+             * However with bridge filtering, they aren't always true.
+             * Teach them such cases, such that filtered_size < size and
+             * addr & (size - 1) != 0.
+             */
+            r->map_func(d, i, r->addr, r->filtered_size, r->type);
         }
     }
 }
@@ -994,10 +1109,36 @@ typedef struct {
     uint32_t did;
 } PCIBridge;
 
+
+static void pci_bridge_update_mappings_fn(PCIBus *b, PCIDevice *d)
+{
+    pci_update_mappings(d);
+}
+
+static void pci_bridge_update_mappings(PCIBus *b)
+{
+    PCIBus *child;
+
+    pci_for_each_device_under_bus(b, pci_bridge_update_mappings_fn);
+
+    QLIST_FOREACH(child, &b->child, sibling) {
+        pci_bridge_update_mappings(child);
+    }
+}
+
 static void pci_bridge_write_config(PCIDevice *d,
                              uint32_t address, uint32_t val, int len)
 {
     pci_default_write_config(d, address, val, len);
+
+    if (/* io base/limit */
+        ranges_overlap(address, len, PCI_IO_BASE, 2) ||
+
+        /* memory base/limit, prefetchable base/limit and
+           io base/limit upper 16 */
+        ranges_overlap(address, len, PCI_MEMORY_BASE, 20)) {
+        pci_bridge_update_mappings(d->bus);
+    }
 }
 
 PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
diff --git a/hw/pci.h b/hw/pci.h
index 3f50294..9a56d0d 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -86,6 +86,7 @@ typedef struct PCIIORegion {
     pcibus_t addr; /* current PCI mapping address. -1 means not mapped */
 #define PCI_BAR_UNMAPPED (~(pcibus_t)0)
     pcibus_t size;
+    pcibus_t filtered_size;
     uint8_t type;
     PCIMapIORegionFunc *map_func;
 } PCIIORegion;
@@ -130,6 +131,7 @@ typedef struct PCIIORegion {
 #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_32	0x01
 #define  PCI_IO_RANGE_MASK      (~0x0fUL)
 #define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
 #define PCI_MEMORY_BASE         0x20    /* Memory range behind */
@@ -139,6 +141,7 @@ typedef struct PCIIORegion {
 #define PCI_PREF_MEMORY_LIMIT   0x26
 #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_SUBSYSTEM_VENDOR_ID 0x2c    /* 16 bits */
 #define PCI_SUBSYSTEM_ID        0x2e    /* 16 bits */
 #define PCI_ROM_ADDRESS		0x30	/* Bits 31..11 are address, 10..1 reserved */
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V6 32/32] pci/monitor: print out bridge's filtering values and so on.
  2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (30 preceding siblings ...)
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 31/32] pci: implement pci bridge filtering Isaku Yamahata
@ 2009-10-30 12:21 ` Isaku Yamahata
  31 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-10-30 12:21 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>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/pci.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 336c1a3..2ab1117 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -970,7 +970,32 @@ 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 = pci_bridge_get_base(d, PCI_BASE_ADDRESS_SPACE_IO);
+        limit = pci_bridge_get_limit(d, PCI_BASE_ADDRESS_SPACE_IO);
+        monitor_printf(mon, "      IO range [0x%04"PRIx64", 0x%04"PRIx64"]\n",
+                       base, limit);
+
+        base = pci_bridge_get_base(d, PCI_BASE_ADDRESS_SPACE_MEMORY);
+        limit= pci_config_get_memory_base(d, PCI_BASE_ADDRESS_SPACE_MEMORY);
+        monitor_printf(mon,
+                       "      memory range [0x%08"PRIx64", 0x%08"PRIx64"]\n",
+                       base, limit);
+
+        base = pci_bridge_get_base(d, PCI_BASE_ADDRESS_SPACE_MEMORY |
+                                   PCI_BASE_ADDRESS_MEM_PREFETCH);
+        limit = pci_bridge_get_limit(d, PCI_BASE_ADDRESS_SPACE_MEMORY |
+                                     PCI_BASE_ADDRESS_MEM_PREFETCH);
+        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] 75+ messages in thread

* [Qemu-devel] Re: [PATCH V6 17/32] pci: 64bit bar support.
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 17/32] pci: 64bit bar support Isaku Yamahata
@ 2009-11-01 16:07   ` Michael S. Tsirkin
  2009-11-03  3:52     ` Isaku Yamahata
  0 siblings, 1 reply; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-01 16:07 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:11PM +0900, Isaku Yamahata wrote:
> implemented pci 64bit bar support.
> The tricky bit is pci_update_mapping().
> An OS is allowed to set the BAR such that OS can't address the area
> pointed by BAR. It doesn't make sense, though.

It might make sense. 32 bit guest can address more than 4G of
physical RAM, e.g. using PAE.
Since I think qemu can not support this if target phys address is 32
bit, we should declare lack of support for 64 bit addressing on these
platforms, by forcing BAR into 32 bit mode, rather than silently failing
to map it.

> In that case, don't map the BAR.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.c |   35 ++++++++++++++++++++++++++++++-----
>  hw/pci.h |    1 +
>  2 files changed, 31 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index b462bd6..7da3db9 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -484,8 +484,14 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
>          wmask |= PCI_ROM_ADDRESS_ENABLE;
>      }
>      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 (!(r->type & PCI_BASE_ADDRESS_SPACE_IO) &&
> +        r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
> +        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)
> @@ -513,7 +519,11 @@ static void pci_update_mappings(PCIDevice *d)
>                  }
>              } else {
>                  if (cmd & PCI_COMMAND_MEMORY) {
> -                    new_addr = pci_get_long(d->config + pci_bar(d, i));
> +                    if (r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
> +                        new_addr = pci_get_quad(d->config + pci_bar(d, i));
> +                    } else {
> +                        new_addr = pci_get_long(d->config + pci_bar(d, i));
> +                    }
>                      /* the ROM slot has a specific enable bit */
>                      if (i == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE))
>                          goto no_mem_map;
> @@ -531,7 +541,15 @@ static void pci_update_mappings(PCIDevice *d)
>                           * Without this, PC ide doesn't work well.
>                           * TODO: remove this work around.
>                           */
> -                        last_addr >= UINT32_MAX) {
> +                        (!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) &&
> +                         last_addr >= UINT32_MAX) ||
> +
> +                        /*
> +                         * OS is allowed to set BAR beyond its addressable
> +                         * bits. For example, 32 bit OS can set 64bit bar
> +                         * to >4G. Check it.
> +                         */
> +                        last_addr >= TARGET_PHYS_ADDR_MAX) {
>                          new_addr = PCI_BAR_UNMAPPED;
>                      }
>                  } else {
> @@ -773,8 +791,15 @@ static void pci_info_device(PCIDevice *d)
>                                 " [0x%04"FMT_PCIBUS"].\n",
>                                 r->addr, r->addr + r->size - 1);
>              } else {
> -                monitor_printf(mon, "32 bit memory at 0x%08"FMT_PCIBUS
> +                const char *type = r->type & PCI_BASE_ADDRESS_MEM_TYPE_64 ?
> +                    "64 bit" : "32 bit";
> +                const char *prefetch =
> +                    r->type & PCI_BASE_ADDRESS_MEM_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 305c030..e83faf5 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -114,6 +114,7 @@ typedef struct PCIIORegion {
>  #define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
>  #define  PCI_BASE_ADDRESS_SPACE_IO	0x01
>  #define  PCI_BASE_ADDRESS_SPACE_MEMORY	0x00
> +#define  PCI_BASE_ADDRESS_MEM_TYPE_64	0x04	/* 64 bit address */
>  #define  PCI_BASE_ADDRESS_MEM_PREFETCH	0x08	/* prefetchable? */
>  #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
>  #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
> -- 
> 1.6.0.2
> 
> 

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

* [Qemu-devel] Re: [PATCH V6 17/32] pci: 64bit bar support.
  2009-11-01 16:07   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-11-03  3:52     ` Isaku Yamahata
  2009-11-03 11:47       ` Michael S. Tsirkin
  0 siblings, 1 reply; 75+ messages in thread
From: Isaku Yamahata @ 2009-11-03  3:52 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Sun, Nov 01, 2009 at 06:07:30PM +0200, Michael S. Tsirkin wrote:
> On Fri, Oct 30, 2009 at 09:21:11PM +0900, Isaku Yamahata wrote:
> > implemented pci 64bit bar support.
> > The tricky bit is pci_update_mapping().
> > An OS is allowed to set the BAR such that OS can't address the area
> > pointed by BAR. It doesn't make sense, though.
> 
> It might make sense. 32 bit guest can address more than 4G of
> physical RAM, e.g. using PAE.

Yes, in that case, guest OS will set bar to be under 36 bit.
If PAE were supported, target phys address would be 64 bit.


> Since I think qemu can not support this if target phys address is 32
> bit, we should declare lack of support for 64 bit addressing on these
> platforms, by forcing BAR into 32 bit mode, rather than silently failing
> to map it.

I don't get your point. And I don't understand the benefit of focing
BAR into 32 bit mode.
Real hardware silently maps BAR to address beyond CPU addressable
area.
Let's stick to PCI spec as you said before.

32 bit guest OS will set 64 bit BAR to be smaller 32bit
(or 36bit if PAE). That's it.
Even if 64 bit CPU case, architectally addressable address bit is smaller
than 64 bit. It's CPU implementation dependent.
And guest OS sets BAR according to it.

-- 
yamahata

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

* [Qemu-devel] Re: [PATCH V6 17/32] pci: 64bit bar support.
  2009-11-03  3:52     ` Isaku Yamahata
@ 2009-11-03 11:47       ` Michael S. Tsirkin
  2009-11-03 12:22         ` Avi Kivity
  0 siblings, 1 reply; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 11:47 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Tue, Nov 03, 2009 at 12:52:10PM +0900, Isaku Yamahata wrote:
> On Sun, Nov 01, 2009 at 06:07:30PM +0200, Michael S. Tsirkin wrote:
> > On Fri, Oct 30, 2009 at 09:21:11PM +0900, Isaku Yamahata wrote:
> > > implemented pci 64bit bar support.
> > > The tricky bit is pci_update_mapping().
> > > An OS is allowed to set the BAR such that OS can't address the area
> > > pointed by BAR. It doesn't make sense, though.
> > 
> > It might make sense. 32 bit guest can address more than 4G of
> > physical RAM, e.g. using PAE.
> 
> Yes, in that case, guest OS will set bar to be under 36 bit.
> If PAE were supported, target phys address would be 64 bit.
> 
> 
> > Since I think qemu can not support this if target phys address is 32
> > bit, we should declare lack of support for 64 bit addressing on these
> > platforms, by forcing BAR into 32 bit mode, rather than silently failing
> > to map it.
> 
> I don't get your point. And I don't understand the benefit of focing
> BAR into 32 bit mode.
> Real hardware silently maps BAR to address beyond CPU addressable
> area.
> Let's stick to PCI spec as you said before.
> 
> 32 bit guest OS will set 64 bit BAR to be smaller 32bit
> (or 36bit if PAE). That's it.
> Even if 64 bit CPU case, architectally addressable address bit is smaller
> than 64 bit. It's CPU implementation dependent.
> And guest OS sets BAR according to it.
> -- 
> yamahata

IMO, this is not a question of what guest does or does not do.

If qemu is compiled with target phys address size 32 bit, emulated
devices can not support a 64 bit BAR.  Therefore, according to PCI spec,
such devices should declare all BARs as 32 bit.

I think you are right that guests on such systems really do not have a
way to address PCI devices if BAR is set beyond 4G. But pci emulation is
better off not relying on this, IMO. Makes sense?

-- 
MST

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

* Re: [Qemu-devel] Re: [PATCH V6 17/32] pci: 64bit bar support.
  2009-11-03 11:47       ` Michael S. Tsirkin
@ 2009-11-03 12:22         ` Avi Kivity
  2009-11-03 12:39           ` Michael S. Tsirkin
  0 siblings, 1 reply; 75+ messages in thread
From: Avi Kivity @ 2009-11-03 12:22 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Isaku Yamahata, qemu-devel

On 11/03/2009 01:47 PM, Michael S. Tsirkin wrote:
>
> If qemu is compiled with target phys address size 32 bit, emulated
> devices can not support a 64 bit BAR.  Therefore, according to PCI spec,
> such devices should declare all BARs as 32 bit.
>
>    

What happens if you take a PCI card that supports 64-bit BARs and stick 
it into a machine that has a 32-bit physical address space?

The firmware/OS will configure the BARs to below 4G.

> I think you are right that guests on such systems really do not have a
> way to address PCI devices if BAR is set beyond 4G. But pci emulation is
> better off not relying on this, IMO. Makes sense?
>    

No.  Device emulation shouldn't change with the machine type.

-- 
error compiling committee.c: too many arguments to function

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

* Re: [Qemu-devel] Re: [PATCH V6 17/32] pci: 64bit bar support.
  2009-11-03 12:22         ` Avi Kivity
@ 2009-11-03 12:39           ` Michael S. Tsirkin
  2009-11-03 13:21             ` Michael S. Tsirkin
  2009-11-03 14:01             ` Isaku Yamahata
  0 siblings, 2 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 12:39 UTC (permalink / raw)
  To: Avi Kivity; +Cc: Isaku Yamahata, qemu-devel

On Tue, Nov 03, 2009 at 02:22:07PM +0200, Avi Kivity wrote:
> On 11/03/2009 01:47 PM, Michael S. Tsirkin wrote:
>>
>> If qemu is compiled with target phys address size 32 bit, emulated
>> devices can not support a 64 bit BAR.  Therefore, according to PCI spec,
>> such devices should declare all BARs as 32 bit.
>>
>>    
>
> What happens if you take a PCI card that supports 64-bit BARs and stick  
> it into a machine that has a 32-bit physical address space?
> The firmware/OS will configure the BARs to below 4G.
> 
>> I think you are right that guests on such systems really do not have a
>> way to address PCI devices if BAR is set beyond 4G. But pci emulation is
>> better off not relying on this, IMO. Makes sense?
>>    
>
> No.  Device emulation shouldn't change with the machine type.

I agree. Issue is, we recompile the *devices* as well.
It's the device emulation that is broken when compiled
with target phys addr set to 32 bit, because all devices
take pcibus_t and cast it to target_phys_addr_t
and then do stuff with it.

So such emulation should not claim to support 64 bit.

Long term, we should fix all devices and *then* they can claim 64 bit
support always.  As a nice side effect, we'll be able to avoid
rebuilding devices.

> -- 
> error compiling committee.c: too many arguments to function

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

* Re: [Qemu-devel] Re: [PATCH V6 17/32] pci: 64bit bar support.
  2009-11-03 12:39           ` Michael S. Tsirkin
@ 2009-11-03 13:21             ` Michael S. Tsirkin
  2009-11-03 14:01             ` Isaku Yamahata
  1 sibling, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 13:21 UTC (permalink / raw)
  To: Avi Kivity; +Cc: Isaku Yamahata, qemu-devel

On Tue, Nov 03, 2009 at 02:39:06PM +0200, Michael S. Tsirkin wrote:
> On Tue, Nov 03, 2009 at 02:22:07PM +0200, Avi Kivity wrote:
> > On 11/03/2009 01:47 PM, Michael S. Tsirkin wrote:
> >>
> >> If qemu is compiled with target phys address size 32 bit, emulated
> >> devices can not support a 64 bit BAR.  Therefore, according to PCI spec,
> >> such devices should declare all BARs as 32 bit.
> >>
> >>    
> >
> > What happens if you take a PCI card that supports 64-bit BARs and stick  
> > it into a machine that has a 32-bit physical address space?
> > The firmware/OS will configure the BARs to below 4G.
> > 
> >> I think you are right that guests on such systems really do not have a
> >> way to address PCI devices if BAR is set beyond 4G. But pci emulation is
> >> better off not relying on this, IMO. Makes sense?
> >>    
> >
> > No.  Device emulation shouldn't change with the machine type.
> 
> I agree. Issue is, we recompile the *devices* as well.
> It's the device emulation that is broken when compiled
> with target phys addr set to 32 bit, because all devices
> take pcibus_t and cast it to target_phys_addr_t
> and then do stuff with it.
> 
> So such emulation should not claim to support 64 bit.
> 
> Long term, we should fix all devices and *then* they can claim 64 bit
> support always.  As a nice side effect, we'll be able to avoid
> rebuilding devices.

BTW, the right way to do this is probably to move mapping device memory
out of devices proper and into pci.


> > -- 
> > error compiling committee.c: too many arguments to function

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

* [Qemu-devel] Re: [PATCH V6 08/32] pci: clean up pci_init_wmask()
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 08/32] pci: clean up pci_init_wmask() Isaku Yamahata
@ 2009-11-03 13:22   ` Michael S. Tsirkin
  2009-11-10 15:26   ` Michael S. Tsirkin
  1 sibling, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 13:22 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:02PM +0900, Isaku Yamahata wrote:
> use pci_set_word() for pci command register.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Acked-by: Michael S. Tsirkin <mst@redhat.com>

> ---
>  hw/pci.c |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 6abb0e2..84c7611 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -352,8 +352,8 @@ static void pci_init_wmask(PCIDevice *dev)
>      int i;
>      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;
> +    pci_set_word(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)
>          dev->wmask[i] = 0xff;
>  }
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V6 12/32] pci_host.h: move functions in pci_host.h into .c file.
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 12/32] pci_host.h: move functions in pci_host.h into .c file Isaku Yamahata
@ 2009-11-03 13:31   ` Michael S. Tsirkin
  2009-11-03 13:35     ` Michael S. Tsirkin
  0 siblings, 1 reply; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 13:31 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:06PM +0900, Isaku Yamahata wrote:
> split static functions in pci_host.h into pci_host.c and
> pci_host_template.h.
> 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 functions which are instantiated in .c by including
> pci_host.h with typedefing pci_addr_t.
> pci_addr_t is per pci host bridge and is typedef'ed to uint32_t for ioio
> or target_phys_addr_t for mmio in .c file.
> That prevents from including pci_host.h to use PCIHostState because of
> requiring type, pci_addr_t.
> 
> Its purpose to include is to instantiate io function for mmio or ioio
> depending on which pci host bridge requires ioio or mmio.
> To avoid including code, we always instantiate both version.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

I think this is good cleanup.  Maybe names can be shorter:
pci_host_data_register_io_memory -> pci_host_register_io_memory
pci_host_data_register_ioport -> pci_host_register_ioport

What do you think?

Acked-by: Michael S. Tsirkin <mst@redhat.com>

> ---
>  Makefile.target                        |    2 +-
>  hw/apb_pci.c                           |   19 +------
>  hw/grackle_pci.c                       |   24 +-------
>  hw/gt64xxx.c                           |   11 +----
>  hw/pci_host.c                          |   75 ++++++++++++++++++++++++++
>  hw/pci_host.h                          |   90 +++-----------------------------
>  hw/{pci_host.h => pci_host_template.h} |   36 ++++---------
>  hw/piix_pci.c                          |   11 +---
>  hw/ppc4xx_pci.c                        |   18 +------
>  hw/ppce500_pci.c                       |   17 +------
>  hw/prep_pci.c                          |    9 +---
>  hw/unin_pci.c                          |   40 ++------------
>  12 files changed, 111 insertions(+), 241 deletions(-)
>  create mode 100644 hw/pci_host.c
>  copy hw/{pci_host.h => pci_host_template.h} (80%)
> 
> diff --git a/Makefile.target b/Makefile.target
> index fefd7ac..db0d0ab 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -154,7 +154,7 @@ endif #CONFIG_BSD_USER
>  # System emulator target
>  ifdef CONFIG_SOFTMMU
>  
> -obj-y = vl.o async.o monitor.o pci.o machine.o gdbstub.o
> +obj-y = vl.o async.o monitor.o pci.o pci_host.o machine.o gdbstub.o
>  # virtio has to be here due to weird dependency between PCI and virtio-net.
>  # need to fix this properly
>  obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o virtio-pci.o
> diff --git a/hw/apb_pci.c b/hw/apb_pci.c
> index 1ea3e0d..560617a 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
> @@ -48,9 +49,6 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
>   * http://www.sun.com/processors/manuals/805-1251.pdf
>   */
>  
> -typedef target_phys_addr_t pci_addr_t;
> -#include "pci_host.h"
> -
>  typedef struct APBState {
>      SysBusDevice busdev;
>      PCIHostState host_state;
> @@ -145,18 +143,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)
>  {
> @@ -293,8 +279,7 @@ 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 = pci_host_data_register_io_memory(&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 b49cf1e..8407cd2 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,9 +149,7 @@ 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,
> -                                          &s->host_state);
> +    pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
>  
> @@ -185,9 +169,7 @@ 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,
> -                                          &s->host_state);
> +    pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
>      return 0;
> 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.c b/hw/pci_host.c
> new file mode 100644
> index 0000000..45da1e7
> --- /dev/null
> +++ b/hw/pci_host.c
> @@ -0,0 +1,75 @@
> +/*
> + * pci_host.c
> + *
> + * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
> + *                    VA Linux Systems Japan K.K.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> +
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> +
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#include "pci.h"
> +#include "pci_host.h"
> +
> +/* debug PCI */
> +//#define DEBUG_PCI
> +
> +#ifdef DEBUG_PCI
> +#define PCI_DPRINTF(fmt, ...) \
> +do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
> +#else
> +#define PCI_DPRINTF(fmt, ...)
> +#endif
> +
> +#define PCI_ADDR_T      target_phys_addr_t
> +#define PCI_HOST_SUFFIX _mmio
> +
> +#include "pci_host_template.h"
> +
> +static CPUWriteMemoryFunc * const pci_host_data_write_mmio[] = {
> +    pci_host_data_writeb_mmio,
> +    pci_host_data_writew_mmio,
> +    pci_host_data_writel_mmio,
> +};
> +
> +static CPUReadMemoryFunc * const pci_host_data_read_mmio[] = {
> +    pci_host_data_readb_mmio,
> +    pci_host_data_readw_mmio,
> +    pci_host_data_readl_mmio,
> +};
> +
> +int pci_host_data_register_io_memory(PCIHostState *s)
> +{
> +    return cpu_register_io_memory(pci_host_data_read_mmio,
> +                                  pci_host_data_write_mmio,
> +                                  s);
> +}
> +
> +#undef PCI_ADDR_T
> +#undef PCI_HOST_SUFFIX
> +
> +#define PCI_ADDR_T      uint32_t
> +#define PCI_HOST_SUFFIX _ioport
> +
> +#include "pci_host_template.h"
> +
> +void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s)
> +{
> +    register_ioport_write(ioport, 4, 1, pci_host_data_writeb_ioport, s);
> +    register_ioport_write(ioport, 4, 2, pci_host_data_writew_ioport, s);
> +    register_ioport_write(ioport, 4, 4, pci_host_data_writel_ioport, s);
> +    register_ioport_read(ioport, 4, 1, pci_host_data_readb_ioport, s);
> +    register_ioport_read(ioport, 4, 2, pci_host_data_readw_ioport, s);
> +    register_ioport_read(ioport, 4, 4, pci_host_data_readl_ioport, s);
> +}
> diff --git a/hw/pci_host.h b/hw/pci_host.h
> index 48862b5..92a35f9 100644
> --- a/hw/pci_host.h
> +++ b/hw/pci_host.h
> @@ -25,97 +25,21 @@
>  /* 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 */
> +int pci_host_data_register_io_memory(PCIHostState *s);
>  
> -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_register_ioport(pio_addr_t ioport, PCIHostState *s);
>  
> -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/pci_host.h b/hw/pci_host_template.h
> similarity index 80%
> copy from hw/pci_host.h
> copy to hw/pci_host_template.h
> index 48862b5..11e6c88 100644
> --- a/hw/pci_host.h
> +++ b/hw/pci_host_template.h
> @@ -25,25 +25,8 @@
>  /* Worker routines for a PCI host controller that uses an {address,data}
>     register pair to access PCI configuration space.  */
>  
> -/* debug PCI */
> -//#define DEBUG_PCI
> -
> -#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)
> +static void glue(pci_host_data_writeb, PCI_HOST_SUFFIX)(
> +    void* opaque, PCI_ADDR_T addr, uint32_t val)
>  {
>      PCIHostState *s = opaque;
>  
> @@ -53,7 +36,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)
> +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 +49,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)
> +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 +62,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)
> +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 +76,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)
> +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 +92,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)
> +static uint32_t glue(pci_host_data_readl, PCI_HOST_SUFFIX)(
> +    void* opaque, PCI_ADDR_T addr)
>  {
>      PCIHostState *s = opaque;
>      uint32_t val;
> diff --git a/hw/piix_pci.c b/hw/piix_pci.c
> index ed036fe..866348d 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 {
> @@ -197,12 +195,7 @@ 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);
> +    pci_host_data_register_ioport(0xcfc, s);
>      return 0;
>  }
>  
> diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
> index 655fe86..3aa7489 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,9 +378,7 @@ 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,
> -                                   &controller->pci_state);
> +    index = pci_host_data_register_io_memory(&controller->pci_state);
>      if (index < 0)
>          goto free;
>      cpu_register_physical_memory(config_space + PCIC0_CFGDATA, 4, index);
> diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
> index 64fccfd..7c8cdad 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,9 +331,7 @@ 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,
> -                                   &controller->pci_state);
> +    index = pci_host_data_register_io_memory(&controller->pci_state);
>      if (index < 0)
>          goto free;
>      cpu_register_physical_memory(registers + PCIE500_CFGDATA, 4, index);
> diff --git a/hw/prep_pci.c b/hw/prep_pci.c
> index 2d8a0fa..5a5b3da 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,7 @@ 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);
> +    pci_host_data_register_ioport(0xcfc, 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 4abb5c8..6b8f98b 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,7 @@ 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 = pci_host_data_register_io_memory(&s->host_state);
>  
>      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> @@ -203,8 +176,7 @@ 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 = pci_host_data_register_io_memory(&s->host_state);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
>      return 0;
> @@ -220,8 +192,7 @@ 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 = pci_host_data_register_io_memory(&s->host_state);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
>      return 0;
> @@ -237,8 +208,7 @@ 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 = pci_host_data_register_io_memory(&s->host_state);
>      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] 75+ messages in thread

* [Qemu-devel] Re: [PATCH V6 12/32] pci_host.h: move functions in pci_host.h into .c file.
  2009-11-03 13:31   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-11-03 13:35     ` Michael S. Tsirkin
  2009-11-04  4:09       ` Isaku Yamahata
  0 siblings, 1 reply; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 13:35 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Tue, Nov 03, 2009 at 03:31:51PM +0200, Michael S. Tsirkin wrote:
> On Fri, Oct 30, 2009 at 09:21:06PM +0900, Isaku Yamahata wrote:
> > split static functions in pci_host.h into pci_host.c and
> > pci_host_template.h.
> > 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 functions which are instantiated in .c by including
> > pci_host.h with typedefing pci_addr_t.
> > pci_addr_t is per pci host bridge and is typedef'ed to uint32_t for ioio
> > or target_phys_addr_t for mmio in .c file.
> > That prevents from including pci_host.h to use PCIHostState because of
> > requiring type, pci_addr_t.
> > 
> > Its purpose to include is to instantiate io function for mmio or ioio
> > depending on which pci host bridge requires ioio or mmio.
> > To avoid including code, we always instantiate both version.
> > 
> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> 
> I think this is good cleanup.  Maybe names can be shorter:
> pci_host_data_register_io_memory -> pci_host_register_io_memory
> pci_host_data_register_ioport -> pci_host_register_ioport
> 
> What do you think?

Or maybe not - we have to avoid confusing this with config...


> Acked-by: Michael S. Tsirkin <mst@redhat.com>
> 
> > ---
> >  Makefile.target                        |    2 +-
> >  hw/apb_pci.c                           |   19 +------
> >  hw/grackle_pci.c                       |   24 +-------
> >  hw/gt64xxx.c                           |   11 +----
> >  hw/pci_host.c                          |   75 ++++++++++++++++++++++++++
> >  hw/pci_host.h                          |   90 +++-----------------------------
> >  hw/{pci_host.h => pci_host_template.h} |   36 ++++---------
> >  hw/piix_pci.c                          |   11 +---
> >  hw/ppc4xx_pci.c                        |   18 +------
> >  hw/ppce500_pci.c                       |   17 +------
> >  hw/prep_pci.c                          |    9 +---
> >  hw/unin_pci.c                          |   40 ++------------
> >  12 files changed, 111 insertions(+), 241 deletions(-)
> >  create mode 100644 hw/pci_host.c
> >  copy hw/{pci_host.h => pci_host_template.h} (80%)
> > 
> > diff --git a/Makefile.target b/Makefile.target
> > index fefd7ac..db0d0ab 100644
> > --- a/Makefile.target
> > +++ b/Makefile.target
> > @@ -154,7 +154,7 @@ endif #CONFIG_BSD_USER
> >  # System emulator target
> >  ifdef CONFIG_SOFTMMU
> >  
> > -obj-y = vl.o async.o monitor.o pci.o machine.o gdbstub.o
> > +obj-y = vl.o async.o monitor.o pci.o pci_host.o machine.o gdbstub.o
> >  # virtio has to be here due to weird dependency between PCI and virtio-net.
> >  # need to fix this properly
> >  obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o virtio-pci.o
> > diff --git a/hw/apb_pci.c b/hw/apb_pci.c
> > index 1ea3e0d..560617a 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
> > @@ -48,9 +49,6 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
> >   * http://www.sun.com/processors/manuals/805-1251.pdf
> >   */
> >  
> > -typedef target_phys_addr_t pci_addr_t;
> > -#include "pci_host.h"
> > -
> >  typedef struct APBState {
> >      SysBusDevice busdev;
> >      PCIHostState host_state;
> > @@ -145,18 +143,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)
> >  {
> > @@ -293,8 +279,7 @@ 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 = pci_host_data_register_io_memory(&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 b49cf1e..8407cd2 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,9 +149,7 @@ 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,
> > -                                          &s->host_state);
> > +    pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> >  
> > @@ -185,9 +169,7 @@ 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,
> > -                                          &s->host_state);
> > +    pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> >      return 0;
> > 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.c b/hw/pci_host.c
> > new file mode 100644
> > index 0000000..45da1e7
> > --- /dev/null
> > +++ b/hw/pci_host.c
> > @@ -0,0 +1,75 @@
> > +/*
> > + * pci_host.c
> > + *
> > + * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
> > + *                    VA Linux Systems Japan K.K.
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License as published by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > +
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > +
> > + * You should have received a copy of the GNU General Public License along
> > + * with this program; if not, write to the Free Software Foundation, Inc.,
> > + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> > + */
> > +
> > +#include "pci.h"
> > +#include "pci_host.h"
> > +
> > +/* debug PCI */
> > +//#define DEBUG_PCI
> > +
> > +#ifdef DEBUG_PCI
> > +#define PCI_DPRINTF(fmt, ...) \
> > +do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
> > +#else
> > +#define PCI_DPRINTF(fmt, ...)
> > +#endif
> > +
> > +#define PCI_ADDR_T      target_phys_addr_t
> > +#define PCI_HOST_SUFFIX _mmio
> > +
> > +#include "pci_host_template.h"
> > +
> > +static CPUWriteMemoryFunc * const pci_host_data_write_mmio[] = {
> > +    pci_host_data_writeb_mmio,
> > +    pci_host_data_writew_mmio,
> > +    pci_host_data_writel_mmio,
> > +};
> > +
> > +static CPUReadMemoryFunc * const pci_host_data_read_mmio[] = {
> > +    pci_host_data_readb_mmio,
> > +    pci_host_data_readw_mmio,
> > +    pci_host_data_readl_mmio,
> > +};
> > +
> > +int pci_host_data_register_io_memory(PCIHostState *s)
> > +{
> > +    return cpu_register_io_memory(pci_host_data_read_mmio,
> > +                                  pci_host_data_write_mmio,
> > +                                  s);
> > +}
> > +
> > +#undef PCI_ADDR_T
> > +#undef PCI_HOST_SUFFIX
> > +
> > +#define PCI_ADDR_T      uint32_t
> > +#define PCI_HOST_SUFFIX _ioport
> > +
> > +#include "pci_host_template.h"
> > +
> > +void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s)
> > +{
> > +    register_ioport_write(ioport, 4, 1, pci_host_data_writeb_ioport, s);
> > +    register_ioport_write(ioport, 4, 2, pci_host_data_writew_ioport, s);
> > +    register_ioport_write(ioport, 4, 4, pci_host_data_writel_ioport, s);
> > +    register_ioport_read(ioport, 4, 1, pci_host_data_readb_ioport, s);
> > +    register_ioport_read(ioport, 4, 2, pci_host_data_readw_ioport, s);
> > +    register_ioport_read(ioport, 4, 4, pci_host_data_readl_ioport, s);
> > +}
> > diff --git a/hw/pci_host.h b/hw/pci_host.h
> > index 48862b5..92a35f9 100644
> > --- a/hw/pci_host.h
> > +++ b/hw/pci_host.h
> > @@ -25,97 +25,21 @@
> >  /* 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 */
> > +int pci_host_data_register_io_memory(PCIHostState *s);
> >  
> > -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_register_ioport(pio_addr_t ioport, PCIHostState *s);
> >  
> > -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/pci_host.h b/hw/pci_host_template.h
> > similarity index 80%
> > copy from hw/pci_host.h
> > copy to hw/pci_host_template.h
> > index 48862b5..11e6c88 100644
> > --- a/hw/pci_host.h
> > +++ b/hw/pci_host_template.h
> > @@ -25,25 +25,8 @@
> >  /* Worker routines for a PCI host controller that uses an {address,data}
> >     register pair to access PCI configuration space.  */
> >  
> > -/* debug PCI */
> > -//#define DEBUG_PCI
> > -
> > -#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)
> > +static void glue(pci_host_data_writeb, PCI_HOST_SUFFIX)(
> > +    void* opaque, PCI_ADDR_T addr, uint32_t val)
> >  {
> >      PCIHostState *s = opaque;
> >  
> > @@ -53,7 +36,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)
> > +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 +49,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)
> > +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 +62,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)
> > +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 +76,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)
> > +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 +92,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)
> > +static uint32_t glue(pci_host_data_readl, PCI_HOST_SUFFIX)(
> > +    void* opaque, PCI_ADDR_T addr)
> >  {
> >      PCIHostState *s = opaque;
> >      uint32_t val;
> > diff --git a/hw/piix_pci.c b/hw/piix_pci.c
> > index ed036fe..866348d 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 {
> > @@ -197,12 +195,7 @@ 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);
> > +    pci_host_data_register_ioport(0xcfc, s);
> >      return 0;
> >  }
> >  
> > diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
> > index 655fe86..3aa7489 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,9 +378,7 @@ 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,
> > -                                   &controller->pci_state);
> > +    index = pci_host_data_register_io_memory(&controller->pci_state);
> >      if (index < 0)
> >          goto free;
> >      cpu_register_physical_memory(config_space + PCIC0_CFGDATA, 4, index);
> > diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
> > index 64fccfd..7c8cdad 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,9 +331,7 @@ 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,
> > -                                   &controller->pci_state);
> > +    index = pci_host_data_register_io_memory(&controller->pci_state);
> >      if (index < 0)
> >          goto free;
> >      cpu_register_physical_memory(registers + PCIE500_CFGDATA, 4, index);
> > diff --git a/hw/prep_pci.c b/hw/prep_pci.c
> > index 2d8a0fa..5a5b3da 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,7 @@ 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);
> > +    pci_host_data_register_ioport(0xcfc, 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 4abb5c8..6b8f98b 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,7 @@ 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 = pci_host_data_register_io_memory(&s->host_state);
> >  
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> > @@ -203,8 +176,7 @@ 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 = pci_host_data_register_io_memory(&s->host_state);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> >      return 0;
> > @@ -220,8 +192,7 @@ 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 = pci_host_data_register_io_memory(&s->host_state);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
> >      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> >      return 0;
> > @@ -237,8 +208,7 @@ 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 = pci_host_data_register_io_memory(&s->host_state);
> >      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] 75+ messages in thread

* [Qemu-devel] Re: [PATCH V6 13/32] pci_host: consolidate pci config address access.
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 13/32] pci_host: consolidate pci config address access Isaku Yamahata
@ 2009-11-03 13:45   ` Michael S. Tsirkin
  2009-11-04  6:14     ` Isaku Yamahata
  0 siblings, 1 reply; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 13:45 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:07PM +0900, Isaku Yamahata wrote:
> consolidate pci_config address access into pci_host.c
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/apb_pci.c     |   43 +---------------------
>  hw/grackle_pci.c |   45 +---------------------
>  hw/pci_host.c    |  108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/pci_host.h    |    3 +
>  hw/piix_pci.c    |   15 +-------
>  hw/ppce500_pci.c |   34 +----------------
>  hw/prep_pci.c    |   15 +-------
>  hw/unin_pci.c    |   81 ++--------------------------------------
>  8 files changed, 121 insertions(+), 223 deletions(-)
> 
> diff --git a/hw/apb_pci.c b/hw/apb_pci.c
> index 560617a..3999879 100644
> --- a/hw/apb_pci.c
> +++ b/hw/apb_pci.c
> @@ -54,46 +54,6 @@ typedef struct APBState {
>      PCIHostState host_state;
>  } APBState;
>  
> -static void pci_apb_config_writel (void *opaque, target_phys_addr_t addr,
> -                                         uint32_t val)
> -{
> -    APBState *s = opaque;
> -
> -#ifdef TARGET_WORDS_BIGENDIAN
> -    val = bswap32(val);
> -#endif
> -    APB_DPRINTF("config_writel addr " TARGET_FMT_plx " val %x\n", addr,
> -                val);
> -    s->host_state.config_reg = val;
> -}
> -
> -static uint32_t pci_apb_config_readl (void *opaque,
> -                                            target_phys_addr_t addr)
> -{
> -    APBState *s = opaque;
> -    uint32_t val;
> -
> -    val = s->host_state.config_reg;
> -#ifdef TARGET_WORDS_BIGENDIAN
> -    val = bswap32(val);
> -#endif
> -    APB_DPRINTF("config_readl addr " TARGET_FMT_plx " val %x\n", addr,
> -                val);
> -    return val;
> -}
> -
> -static CPUWriteMemoryFunc * const pci_apb_config_write[] = {
> -    &pci_apb_config_writel,
> -    &pci_apb_config_writel,
> -    &pci_apb_config_writel,
> -};
> -
> -static CPUReadMemoryFunc * const pci_apb_config_read[] = {
> -    &pci_apb_config_readl,
> -    &pci_apb_config_readl,
> -    &pci_apb_config_readl,
> -};
> -
>  static void apb_config_writel (void *opaque, target_phys_addr_t addr,
>                                 uint32_t val)
>  {
> @@ -275,8 +235,7 @@ static int pci_pbm_init_device(SysBusDevice *dev)
>                                            pci_apb_iowrite, s);
>      sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
>      /* mem_config  */
> -    pci_mem_config = cpu_register_io_memory(pci_apb_config_read,
> -                                            pci_apb_config_write, s);
> +    pci_mem_config = pci_host_config_register_io_memory(&s->host_state);
>      sysbus_init_mmio(dev, 0x10ULL, pci_mem_config);
>      /* mem_data */
>      pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
> diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
> index 8407cd2..58dcd11 100644
> --- a/hw/grackle_pci.c
> +++ b/hw/grackle_pci.c
> @@ -43,45 +43,6 @@ typedef struct GrackleState {
>      PCIHostState host_state;
>  } GrackleState;
>  
> -static void pci_grackle_config_writel (void *opaque, target_phys_addr_t addr,
> -                                       uint32_t val)
> -{
> -    GrackleState *s = opaque;
> -
> -    GRACKLE_DPRINTF("config_writel addr " TARGET_FMT_plx " val %x\n", addr,
> -                    val);
> -#ifdef TARGET_WORDS_BIGENDIAN
> -    val = bswap32(val);
> -#endif
> -    s->host_state.config_reg = val;
> -}
> -
> -static uint32_t pci_grackle_config_readl (void *opaque, target_phys_addr_t addr)
> -{
> -    GrackleState *s = opaque;
> -    uint32_t val;
> -
> -    val = s->host_state.config_reg;
> -#ifdef TARGET_WORDS_BIGENDIAN
> -    val = bswap32(val);
> -#endif
> -    GRACKLE_DPRINTF("config_readl addr " TARGET_FMT_plx " val %x\n", addr,
> -                    val);
> -    return val;
> -}
> -
> -static CPUWriteMemoryFunc * const pci_grackle_config_write[] = {
> -    &pci_grackle_config_writel,
> -    &pci_grackle_config_writel,
> -    &pci_grackle_config_writel,
> -};
> -
> -static CPUReadMemoryFunc * const pci_grackle_config_read[] = {
> -    &pci_grackle_config_readl,
> -    &pci_grackle_config_readl,
> -    &pci_grackle_config_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)
>  {
> @@ -147,8 +108,7 @@ static int pci_grackle_init_device(SysBusDevice *dev)
>  
>      s = FROM_SYSBUS(GrackleState, dev);
>  
> -    pci_mem_config = cpu_register_io_memory(pci_grackle_config_read,
> -                                            pci_grackle_config_write, s);
> +    pci_mem_config = pci_host_config_register_io_memory(&s->host_state);
>      pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> @@ -167,8 +127,7 @@ static int pci_dec_21154_init_device(SysBusDevice *dev)
>  
>      s = FROM_SYSBUS(GrackleState, dev);
>  
> -    pci_mem_config = cpu_register_io_memory(pci_grackle_config_read,
> -                                            pci_grackle_config_write, s);
> +    pci_mem_config = pci_host_config_register_io_memory(&s->host_state);
>      pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> diff --git a/hw/pci_host.c b/hw/pci_host.c
> index 45da1e7..6009e37 100644
> --- a/hw/pci_host.c
> +++ b/hw/pci_host.c
> @@ -32,6 +32,114 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
>  #define PCI_DPRINTF(fmt, ...)
>  #endif
>  
> +static void pci_host_config_writel(void *opaque, target_phys_addr_t addr,
> +                                   uint32_t val)
> +{
> +    PCIHostState *s = opaque;
> +
> +#ifdef TARGET_WORDS_BIGENDIAN
> +    val = bswap32(val);
> +#endif

I know you just copied it, but isn't this just
	val = le32_to_cpu(val);

?

> +    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
> +                __func__, addr, val);
> +    s->config_reg = val;
> +}
> +
> +static uint32_t pci_host_config_readl(void *opaque, target_phys_addr_t addr)
> +{
> +    PCIHostState *s = opaque;
> +    uint32_t val = s->config_reg;
> +
> +#ifdef TARGET_WORDS_BIGENDIAN
> +    val = bswap32(val);
> +#endif

same here.

> +    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
> +                __func__, addr, val);
> +    return val;
> +}
> +
> +static CPUWriteMemoryFunc * const pci_host_config_write[] = {
> +    &pci_host_config_writel,
> +    &pci_host_config_writel,
> +    &pci_host_config_writel,
> +};
> +
> +static CPUReadMemoryFunc * const pci_host_config_read[] = {
> +    &pci_host_config_readl,
> +    &pci_host_config_readl,
> +    &pci_host_config_readl,
> +};
> +
> +int pci_host_config_register_io_memory(PCIHostState *s)
> +{
> +    return cpu_register_io_memory(pci_host_config_read,
> +                                  pci_host_config_write, s);
> +}
> +
> +static void pci_host_config_writel_noswap(void *opaque,
> +                                          target_phys_addr_t addr,
> +                                          uint32_t val)
> +{
> +    PCIHostState *s = opaque;
> +
> +    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
> +                __func__, addr, val);
> +    s->config_reg = val;
> +}
> +
> +static uint32_t pci_host_config_readl_noswap(void *opaque,
> +                                             target_phys_addr_t addr)
> +{
> +    PCIHostState *s = opaque;
> +    uint32_t val = s->config_reg;
> +
> +    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
> +                __func__, addr, val);
> +    return val;
> +}
> +
> +static CPUWriteMemoryFunc * const pci_host_config_write_noswap[] = {
> +    &pci_host_config_writel_noswap,
> +    &pci_host_config_writel_noswap,
> +    &pci_host_config_writel_noswap,
> +};
> +
> +static CPUReadMemoryFunc * const pci_host_config_read_noswap[] = {
> +    &pci_host_config_readl_noswap,
> +    &pci_host_config_readl_noswap,
> +    &pci_host_config_readl_noswap,
> +};
> +
> +int pci_host_config_register_io_memory_noswap(PCIHostState *s)

This name is clearly too long,
as a result when you use it you run over the 80 character
limit. Let's not fix it, let's make name shorter.
io_memory -> memory?

> +{
> +    return cpu_register_io_memory(pci_host_config_read_noswap,
> +                                  pci_host_config_write_noswap, s);
> +}

Do you happen to know whether no swap is really needed?  I suspect some
of these places really only happen to work because everyone uses intel,
so they simply would not work on ppc host.

> +
> +static void pci_host_config_writel_ioport(void *opaque,
> +                                          uint32_t addr, uint32_t val)
> +{
> +    PCIHostState *s = opaque;
> +
> +    PCI_DPRINTF("%s addr %"PRIx32 " val %"PRIx32"\n", __func__, addr, val);
> +    s->config_reg = val;
> +}
> +
> +static uint32_t pci_host_config_readl_ioport(void *opaque, uint32_t addr)
> +{
> +    PCIHostState *s = opaque;
> +    uint32_t val = s->config_reg;
> +
> +    PCI_DPRINTF("%s addr %"PRIx32" val %"PRIx32"\n", __func__, addr, val);
> +    return val;
> +}
> +
> +void pci_host_config_register_ioport(pio_addr_t ioport, PCIHostState *s)
> +{
> +    register_ioport_write(ioport, 4, 4, pci_host_config_writel_ioport, s);
> +    register_ioport_read(ioport, 4, 4, pci_host_config_readl_ioport, s);
> +}
> +
>  #define PCI_ADDR_T      target_phys_addr_t
>  #define PCI_HOST_SUFFIX _mmio
>  
> diff --git a/hw/pci_host.h b/hw/pci_host.h
> index 92a35f9..e5e877f 100644
> --- a/hw/pci_host.h
> +++ b/hw/pci_host.h
> @@ -37,9 +37,12 @@ typedef struct {
>  } PCIHostState;
>  
>  /* for mmio */
> +int pci_host_config_register_io_memory(PCIHostState *s);
> +int pci_host_config_register_io_memory_noswap(PCIHostState *s);
>  int pci_host_data_register_io_memory(PCIHostState *s);
>  
>  /* for ioio */
> +void pci_host_config_register_ioport(pio_addr_t ioport, PCIHostState *s);
>  void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s);
>  
>  #endif /* PCI_HOST_H */
> diff --git a/hw/piix_pci.c b/hw/piix_pci.c
> index 866348d..bf0005e 100644
> --- a/hw/piix_pci.c
> +++ b/hw/piix_pci.c
> @@ -44,18 +44,6 @@ struct PCII440FXState {
>      PIIX3State *piix3;
>  };
>  
> -static void i440fx_addr_writel(void* opaque, uint32_t addr, uint32_t val)
> -{
> -    I440FXState *s = opaque;
> -    s->config_reg = val;
> -}
> -
> -static uint32_t i440fx_addr_readl(void* opaque, uint32_t addr)
> -{
> -    I440FXState *s = opaque;
> -    return s->config_reg;
> -}
> -
>  static void piix3_set_irq(void *opaque, int irq_num, int level);
>  
>  /* return the global irq number corresponding to a given device irq
> @@ -192,8 +180,7 @@ static int i440fx_pcihost_initfn(SysBusDevice *dev)
>  {
>      I440FXState *s = FROM_SYSBUS(I440FXState, dev);
>  
> -    register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
> -    register_ioport_read(0xcf8, 4, 4, i440fx_addr_readl, s);
> +    pci_host_config_register_ioport(0xcf8, s);
>  
>      pci_host_data_register_ioport(0xcfc, s);
>      return 0;
> diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
> index 7c8cdad..223de3a 100644
> --- a/hw/ppce500_pci.c
> +++ b/hw/ppce500_pci.c
> @@ -84,37 +84,6 @@ struct PPCE500PCIState {
>  
>  typedef struct PPCE500PCIState PPCE500PCIState;
>  
> -static uint32_t pcie500_cfgaddr_readl(void *opaque, target_phys_addr_t addr)
> -{
> -    PPCE500PCIState *pci = opaque;
> -
> -    pci_debug("%s: (addr:" TARGET_FMT_plx ") -> value:%x\n", __func__, addr,
> -              pci->pci_state.config_reg);
> -    return pci->pci_state.config_reg;
> -}
> -
> -static CPUReadMemoryFunc * const pcie500_cfgaddr_read[] = {
> -    &pcie500_cfgaddr_readl,
> -    &pcie500_cfgaddr_readl,
> -    &pcie500_cfgaddr_readl,
> -};
> -
> -static void pcie500_cfgaddr_writel(void *opaque, target_phys_addr_t addr,
> -                                  uint32_t value)
> -{
> -    PPCE500PCIState *controller = opaque;
> -
> -    pci_debug("%s: value:%x -> (addr:" TARGET_FMT_plx ")\n", __func__, value,
> -              addr);
> -    controller->pci_state.config_reg = value & ~0x3;
> -}
> -
> -static CPUWriteMemoryFunc * const pcie500_cfgaddr_write[] = {
> -    &pcie500_cfgaddr_writel,
> -    &pcie500_cfgaddr_writel,
> -    &pcie500_cfgaddr_writel,
> -};
> -
>  static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
>  {
>      PPCE500PCIState *pci = opaque;
> @@ -324,8 +293,7 @@ PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
>      controller->pci_dev = d;
>  
>      /* CFGADDR */
> -    index = cpu_register_io_memory(pcie500_cfgaddr_read,
> -                                   pcie500_cfgaddr_write, controller);
> +    index = pci_host_config_register_io_memory_noswap(&controller->pci_state);
>      if (index < 0)
>          goto free;
>      cpu_register_physical_memory(registers + PCIE500_CFGADDR, 4, index);
> diff --git a/hw/prep_pci.c b/hw/prep_pci.c
> index 5a5b3da..a338f81 100644
> --- a/hw/prep_pci.c
> +++ b/hw/prep_pci.c
> @@ -28,18 +28,6 @@
>  
>  typedef PCIHostState PREPPCIState;
>  
> -static void pci_prep_addr_writel(void* opaque, uint32_t addr, uint32_t val)
> -{
> -    PREPPCIState *s = opaque;
> -    s->config_reg = val;
> -}
> -
> -static uint32_t pci_prep_addr_readl(void* opaque, uint32_t addr)
> -{
> -    PREPPCIState *s = opaque;
> -    return s->config_reg;
> -}
> -
>  static inline uint32_t PPC_PCIIO_config(target_phys_addr_t addr)
>  {
>      int i;
> @@ -139,8 +127,7 @@ PCIBus *pci_prep_init(qemu_irq *pic)
>      s->bus = pci_register_bus(NULL, "pci",
>                                prep_set_irq, prep_map_irq, pic, 0, 4);
>  
> -    register_ioport_write(0xcf8, 4, 4, pci_prep_addr_writel, s);
> -    register_ioport_read(0xcf8, 4, 4, pci_prep_addr_readl, s);
> +    pci_host_config_register_ioport(0xcf8, s);
>  
>      pci_host_data_register_ioport(0xcfc, s);
>  
> diff --git a/hw/unin_pci.c b/hw/unin_pci.c
> index 6b8f98b..a9a62fd 100644
> --- a/hw/unin_pci.c
> +++ b/hw/unin_pci.c
> @@ -41,74 +41,6 @@ typedef struct UNINState {
>      PCIHostState host_state;
>  } UNINState;
>  
> -static void pci_unin_main_config_writel (void *opaque, target_phys_addr_t addr,
> -                                         uint32_t val)
> -{
> -    UNINState *s = opaque;
> -
> -    UNIN_DPRINTF("config_writel addr " TARGET_FMT_plx " val %x\n", addr, val);
> -#ifdef TARGET_WORDS_BIGENDIAN
> -    val = bswap32(val);
> -#endif
> -
> -    s->host_state.config_reg = val;
> -}
> -
> -static uint32_t pci_unin_main_config_readl (void *opaque,
> -                                            target_phys_addr_t addr)
> -{
> -    UNINState *s = opaque;
> -    uint32_t val;
> -
> -    val = s->host_state.config_reg;
> -#ifdef TARGET_WORDS_BIGENDIAN
> -    val = bswap32(val);
> -#endif
> -    UNIN_DPRINTF("config_readl addr " TARGET_FMT_plx " val %x\n", addr, val);
> -
> -    return val;
> -}
> -
> -static CPUWriteMemoryFunc * const pci_unin_main_config_write[] = {
> -    &pci_unin_main_config_writel,
> -    &pci_unin_main_config_writel,
> -    &pci_unin_main_config_writel,
> -};
> -
> -static CPUReadMemoryFunc * const pci_unin_main_config_read[] = {
> -    &pci_unin_main_config_readl,
> -    &pci_unin_main_config_readl,
> -    &pci_unin_main_config_readl,
> -};
> -
> -static void pci_unin_config_writel (void *opaque, target_phys_addr_t addr,
> -                                    uint32_t val)
> -{
> -    UNINState *s = opaque;
> -
> -    s->host_state.config_reg = val;
> -}
> -
> -static uint32_t pci_unin_config_readl (void *opaque,
> -                                       target_phys_addr_t addr)
> -{
> -    UNINState *s = opaque;
> -
> -    return s->host_state.config_reg;
> -}
> -
> -static CPUWriteMemoryFunc * const pci_unin_config_write[] = {
> -    &pci_unin_config_writel,
> -    &pci_unin_config_writel,
> -    &pci_unin_config_writel,
> -};
> -
> -static CPUReadMemoryFunc * const pci_unin_config_read[] = {
> -    &pci_unin_config_readl,
> -    &pci_unin_config_readl,
> -    &pci_unin_config_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)
>  {
> @@ -152,10 +84,8 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
>      /* Uninorth main bus */
>      s = FROM_SYSBUS(UNINState, dev);
>  
> -    pci_mem_config = cpu_register_io_memory(pci_unin_main_config_read,
> -                                            pci_unin_main_config_write, s);
> +    pci_mem_config = pci_host_config_register_io_memory(&s->host_state);
>      pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
> -
>      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
>  
> @@ -174,8 +104,7 @@ static int pci_dec_21154_init_device(SysBusDevice *dev)
>      s = FROM_SYSBUS(UNINState, dev);
>  
>      // XXX: s = &pci_bridge[2];
> -    pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
> -                                            pci_unin_config_write, s);
> +    pci_mem_config = pci_host_config_register_io_memory_noswap(&s->host_state);
>      pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> @@ -190,8 +119,7 @@ static int pci_unin_agp_init_device(SysBusDevice *dev)
>      /* Uninorth AGP bus */
>      s = FROM_SYSBUS(UNINState, dev);
>  
> -    pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
> -                                            pci_unin_config_write, s);
> +    pci_mem_config = pci_host_config_register_io_memory_noswap(&s->host_state);
>      pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> @@ -206,8 +134,7 @@ static int pci_unin_internal_init_device(SysBusDevice *dev)
>      /* Uninorth internal bus */
>      s = FROM_SYSBUS(UNINState, dev);
>  
> -    pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
> -                                            pci_unin_config_write, s);
> +    pci_mem_config = pci_host_config_register_io_memory_noswap(&s->host_state);
>      pci_mem_data = pci_host_data_register_io_memory(&s->host_state);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_config);
>      sysbus_init_mmio(dev, 0x1000, pci_mem_data);
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V6 18/32] pci: remove bus_num member from struct PCIBus.
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 18/32] pci: remove bus_num member from struct PCIBus Isaku Yamahata
@ 2009-11-03 13:47   ` Michael S. Tsirkin
  2009-11-10 15:33   ` Michael S. Tsirkin
  1 sibling, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 13:47 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:12PM +0900, Isaku Yamahata wrote:
> Since It can be retrieved from pci configuration space,
> the member is unnecessary.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Acked-by: Michael S. Tsirkin <mst@redhat.com>

> ---
>  hw/pci.c |   21 ++++++++++-----------
>  1 files changed, 10 insertions(+), 11 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 7da3db9..a75d981 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -36,7 +36,6 @@
>  
>  struct PCIBus {
>      BusState qbus;
> -    int bus_num;
>      int devfn_min;
>      pci_set_irq_fn set_irq;
>      pci_map_irq_fn map_irq;
> @@ -192,7 +191,9 @@ static void pci_register_secondary_bus(PCIBus *bus,
>  
>  int pci_bus_num(PCIBus *s)
>  {
> -    return s->bus_num;
> +    if (!s->parent_dev)
> +        return 0;       /* pci host bridge */
> +    return s->parent_dev->config[PCI_SECONDARY_BUS];
>  }
>  
>  static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
> @@ -624,7 +625,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)
> +    while (s && pci_bus_num(s) != bus_num)
>          s = s->next;
>      if (!s)
>          return;
> @@ -645,7 +646,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)
> +    while (s && pci_bus_num(s) != bus_num)
>          s= s->next;
>      if (!s)
>          goto fail;
> @@ -760,7 +761,8 @@ 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, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
> +                   pci_bus_num(d->bus),
> +                   PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
>      class = pci_get_word(d->config + PCI_CLASS_DEVICE);
>      monitor_printf(mon, "    ");
>      desc = pci_class_descriptions;
> @@ -816,7 +818,7 @@ void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
>      PCIDevice *d;
>      int devfn;
>  
> -    while (bus && bus->bus_num != bus_num)
> +    while (bus && pci_bus_num(bus) != bus_num)
>          bus = bus->next;
>      if (bus) {
>          for(devfn = 0; devfn < 256; devfn++) {
> @@ -913,17 +915,14 @@ typedef struct {
>  static void pci_bridge_write_config(PCIDevice *d,
>                               uint32_t address, uint32_t val, int len)
>  {
> -    PCIBridge *s = (PCIBridge *)d;
> -
>      pci_default_write_config(d, address, val, len);
> -    s->bus.bus_num = d->config[PCI_SECONDARY_BUS];
>  }
>  
>  PCIBus *pci_find_bus(int bus_num)
>  {
>      PCIBus *bus = first_bus;
>  
> -    while (bus && bus->bus_num != bus_num)
> +    while (bus && pci_bus_num(bus) != bus_num)
>          bus = bus->next;
>  
>      return bus;
> @@ -1149,7 +1148,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, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
> +                   pci_bus_num(d->bus), PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
>                     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),
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V6 20/32] pci: factor out the conversion logic from io port address into pci device.
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 20/32] pci: factor out the conversion logic from io port address into pci device Isaku Yamahata
@ 2009-11-03 13:52   ` Michael S. Tsirkin
  2009-11-10 15:56   ` Michael S. Tsirkin
  1 sibling, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 13:52 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:14PM +0900, Isaku Yamahata wrote:
> factor out the logic which converts io port address into pci device
> and offset in PCI configuration space.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.c |   32 ++++++++++++++++++--------------
>  1 files changed, 18 insertions(+), 14 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 3e5780a..d0a96c6 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -663,24 +663,33 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
>          pci_update_mappings(d);
>  }
>  
> +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));
> +}
> +

To me XXX_to_XXX says "type conversion". Since this is really lookup
(that even can fail) pci_dev_find_by_addr() would be a better name IMO.

> +static inline int pci_addr_to_config(uint32_t addr)
> +{
> +    return addr & (PCI_CONFIG_SPACE_SIZE - 1);
> +}
> +

The name is pretty confusing. This is probably clearer open-coded.

>  void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
>  {
>      PCIBus *s = opaque;
>      PCIDevice *pci_dev;
> -    int config_addr, bus_num;
> +    int config_addr;
>  
>  #if 0
>      PCI_DPRINTF("pci_data_write: addr=%08x val=%08x 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];
> +    pci_dev = pci_addr_to_dev(s, addr);
>      if (!pci_dev)
>          return;
>      config_addr = addr & 0xff;
> +    config_addr = pci_addr_to_config(addr);

Did you mean to assign it twice?

>      PCI_DPRINTF("pci_config_write: %s: addr=%02x val=%08x len=%d\n",
>                  pci_dev->name, config_addr, val, len);
>      pci_dev->config_write(pci_dev, config_addr, val, len);
> @@ -690,16 +699,11 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
>  {
>      PCIBus *s = opaque;
>      PCIDevice *pci_dev;
> -    int config_addr, bus_num;
> +    int config_addr;
>      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];
> +    pci_dev = pci_addr_to_dev(s, addr);
>      if (!pci_dev) {
> -    fail:
>          switch(len) {
>          case 1:
>              val = 0xff;
> @@ -714,7 +718,7 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
>          }
>          goto the_end;
>      }
> -    config_addr = addr & 0xff;
> +    config_addr = pci_addr_to_config(addr);
>      val = pci_dev->config_read(pci_dev, config_addr, len);
>      PCI_DPRINTF("pci_config_read: %s: addr=%02x val=%08x len=%d\n",
>                  pci_dev->name, config_addr, val, len);
> -- 
> 1.6.0.2

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

* Re: [Qemu-devel] Re: [PATCH V6 17/32] pci: 64bit bar support.
  2009-11-03 12:39           ` Michael S. Tsirkin
  2009-11-03 13:21             ` Michael S. Tsirkin
@ 2009-11-03 14:01             ` Isaku Yamahata
  2009-11-03 14:09               ` Michael S. Tsirkin
  1 sibling, 1 reply; 75+ messages in thread
From: Isaku Yamahata @ 2009-11-03 14:01 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Avi Kivity, qemu-devel

On Tue, Nov 03, 2009 at 02:39:06PM +0200, Michael S. Tsirkin wrote:
> On Tue, Nov 03, 2009 at 02:22:07PM +0200, Avi Kivity wrote:
> > On 11/03/2009 01:47 PM, Michael S. Tsirkin wrote:
> >>
> >> If qemu is compiled with target phys address size 32 bit, emulated
> >> devices can not support a 64 bit BAR.  Therefore, according to PCI spec,
> >> such devices should declare all BARs as 32 bit.

Here is the point.
  > "emulated devices can not support a 64 bit BAR"
If target_phy_addr_t = uint32_t, the emulation of 64 bit BAR which
is set to >4GB is cpu can't access it. So just not-mapping it
is correct behavior.


> > What happens if you take a PCI card that supports 64-bit BARs and stick  
> > it into a machine that has a 32-bit physical address space?
> > The firmware/OS will configure the BARs to below 4G.
> > 
> >> I think you are right that guests on such systems really do not have a
> >> way to address PCI devices if BAR is set beyond 4G. But pci emulation is
> >> better off not relying on this, IMO. Makes sense?
> >>    
> >
> > No.  Device emulation shouldn't change with the machine type.
> 
> I agree. Issue is, we recompile the *devices* as well.
> It's the device emulation that is broken when compiled
> with target phys addr set to 32 bit, because all devices
> take pcibus_t and cast it to target_phys_addr_t
> and then do stuff with it.
> So such emulation should not claim to support 64 bit.

Such case is checked by "last_addr >= TARGET_PHYS_ADDR_MAX",
so the device emulation works well.

Generally device drivers know their devices. For example they know
that BAR0 is 64bit memory and so on. So if BAR type were changed
by forcing 64 bit BAR into 32 bit BAR, the device driver wouldn't be
confused.


> Long term, we should fix all devices and *then* they can claim 64 bit
> support always.  As a nice side effect, we'll be able to avoid
> rebuilding devices.

Are you claiming that (PCI) devices emulation shouldn't depend on
target_phys_addr_t? That sounds a good idea.

However I don't agree on "*then*".
The conversions would take place step by step as it's long term object.
I don't see any reason to penalize correct device emulations just
because there are incomplete device emulations left.

thanks,
-- 
yamahata

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

* [Qemu-devel] Re: [PATCH V6 21/32] pci: move pci host stuff from pci.c to pci_host.c
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 21/32] pci: move pci host stuff from pci.c to pci_host.c Isaku Yamahata
@ 2009-11-03 14:04   ` Michael S. Tsirkin
  0 siblings, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 14:04 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:15PM +0900, Isaku Yamahata wrote:
> Move pci host stuff from pci.c to pci_host.c.
> And add some comments.
> Later pcie host bridge functions will be defined in pcie_host.c
> not to bloat pci.c.

For consistency, should we also move declaration to appropriate header,
and rename it as well?

> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.c      |   67 ---------------------------------------------------------
>  hw/pci_host.c |   63 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 63 insertions(+), 67 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index d0a96c6..a599996 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -663,73 +663,6 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
>          pci_update_mappings(d);
>  }
>  
> -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 int pci_addr_to_config(uint32_t addr)
> -{
> -    return addr & (PCI_CONFIG_SPACE_SIZE - 1);
> -}
> -
> -void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> -{
> -    PCIBus *s = opaque;
> -    PCIDevice *pci_dev;
> -    int config_addr;
> -
> -#if 0
> -    PCI_DPRINTF("pci_data_write: addr=%08x val=%08x len=%d\n",
> -                addr, val, len);
> -#endif
> -    pci_dev = pci_addr_to_dev(s, addr);
> -    if (!pci_dev)
> -        return;
> -    config_addr = addr & 0xff;
> -    config_addr = pci_addr_to_config(addr);
> -    PCI_DPRINTF("pci_config_write: %s: addr=%02x val=%08x len=%d\n",
> -                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)
> -{
> -    PCIBus *s = opaque;
> -    PCIDevice *pci_dev;
> -    int config_addr;
> -    uint32_t val;
> -
> -    pci_dev = pci_addr_to_dev(s, addr);
> -    if (!pci_dev) {
> -        switch(len) {
> -        case 1:
> -            val = 0xff;
> -            break;
> -        case 2:
> -            val = 0xffff;
> -            break;
> -        default:
> -        case 4:
> -            val = 0xffffffff;
> -            break;
> -        }
> -        goto the_end;
> -    }
> -    config_addr = pci_addr_to_config(addr);
> -    val = pci_dev->config_read(pci_dev, config_addr, len);
> -    PCI_DPRINTF("pci_config_read: %s: addr=%02x val=%08x 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",
> -                addr, val, len);
> -#endif
> -    return val;
> -}
> -
>  /***********************************************************/
>  /* generic PCI irq support */
>  
> diff --git a/hw/pci_host.c b/hw/pci_host.c
> index 6009e37..351ade4 100644
> --- a/hw/pci_host.c
> +++ b/hw/pci_host.c
> @@ -32,6 +32,69 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
>  #define PCI_DPRINTF(fmt, ...)
>  #endif
>  
> +/*
> + * PCI address
> + * bit 16 - 24: bus number
> + * bit  8 - 15: devfun number
> + * bit  0 -  7: offset in configuration space of a given pci device
> + */
> +
> +/* the helper functio to get a PCIDeice* for a given pci address */
> +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 & (PCI_CONFIG_SPACE_SIZE - 1);
> +}
> +
> +void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> +{
> +    PCIBus *s = opaque;
> +    PCIDevice *pci_dev = pci_addr_to_dev(s, addr);
> +    uint32_t config_addr = pci_addr_to_config(addr);
> +
> +    if (!pci_dev)
> +        return;
> +
> +    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)
> +{
> +    PCIBus *s = opaque;
> +    PCIDevice *pci_dev = pci_addr_to_dev(s, addr);
> +    uint32_t config_addr = pci_addr_to_config(addr);
> +    uint32_t val;
> +
> +    if (!pci_dev) {
> +        switch(len) {
> +        case 1:
> +            val = 0xff;
> +            break;
> +        case 2:
> +            val = 0xffff;
> +            break;
> +        default:
> +        case 4:
> +            val = 0xffffffff;
> +            break;
> +        }

We can do the memcpy trick here as well I think.

> +    } 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);
> +    }
> +
> +    return val;
> +}
> +
>  static void pci_host_config_writel(void *opaque, target_phys_addr_t addr,
>                                     uint32_t val)
>  {
> -- 
> 1.6.0.2

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

* Re: [Qemu-devel] Re: [PATCH V6 17/32] pci: 64bit bar support.
  2009-11-03 14:01             ` Isaku Yamahata
@ 2009-11-03 14:09               ` Michael S. Tsirkin
  2009-11-04  6:20                 ` Isaku Yamahata
  0 siblings, 1 reply; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 14:09 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: Avi Kivity, qemu-devel

On Tue, Nov 03, 2009 at 11:01:00PM +0900, Isaku Yamahata wrote:
> On Tue, Nov 03, 2009 at 02:39:06PM +0200, Michael S. Tsirkin wrote:
> > On Tue, Nov 03, 2009 at 02:22:07PM +0200, Avi Kivity wrote:
> > > On 11/03/2009 01:47 PM, Michael S. Tsirkin wrote:
> > >>
> > >> If qemu is compiled with target phys address size 32 bit, emulated
> > >> devices can not support a 64 bit BAR.  Therefore, according to PCI spec,
> > >> such devices should declare all BARs as 32 bit.
> 
> Here is the point.
>   > "emulated devices can not support a 64 bit BAR"
> If target_phy_addr_t = uint32_t, the emulation of 64 bit BAR which
> is set to >4GB is cpu can't access it. So just not-mapping it
> is correct behavior.
> 
> 
> > > What happens if you take a PCI card that supports 64-bit BARs and stick  
> > > it into a machine that has a 32-bit physical address space?
> > > The firmware/OS will configure the BARs to below 4G.
> > > 
> > >> I think you are right that guests on such systems really do not have a
> > >> way to address PCI devices if BAR is set beyond 4G. But pci emulation is
> > >> better off not relying on this, IMO. Makes sense?
> > >>    
> > >
> > > No.  Device emulation shouldn't change with the machine type.
> > 
> > I agree. Issue is, we recompile the *devices* as well.
> > It's the device emulation that is broken when compiled
> > with target phys addr set to 32 bit, because all devices
> > take pcibus_t and cast it to target_phys_addr_t
> > and then do stuff with it.
> > So such emulation should not claim to support 64 bit.
> 
> Such case is checked by "last_addr >= TARGET_PHYS_ADDR_MAX",
> so the device emulation works well.
> 
> Generally device drivers know their devices. For example they know
> that BAR0 is 64bit memory and so on. So if BAR type were changed
> by forcing 64 bit BAR into 32 bit BAR, the device driver wouldn't be
> confused.
> 
> > Long term, we should fix all devices and *then* they can claim 64 bit
> > support always.  As a nice side effect, we'll be able to avoid
> > rebuilding devices.
> 
> Are you claiming that (PCI) devices emulation shouldn't depend on
> target_phys_addr_t? That sounds a good idea.

Yes. Maybe we can stop devices from mapping memory, have pci
core do it for them.

> However I don't agree on "*then*".
> The conversions would take place step by step as it's long term object.
> I don't see any reason to penalize correct device emulations just
> because there are incomplete device emulations left.

Hmm. Okay ... but which device emulations are correct?
It seems that none of them are.
I don't see the rush .

> thanks,
> -- 
> yamahata

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

* [Qemu-devel] Re: [PATCH V6 29/32] pci: cosmetic on pci_upadte_mappings()
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 29/32] pci: cosmetic on pci_upadte_mappings() Isaku Yamahata
@ 2009-11-03 14:17   ` Michael S. Tsirkin
  0 siblings, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 14:17 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:23PM +0900, Isaku Yamahata wrote:
> Remove one indentation of pci_update_mappings.
> Just for cosmetics, no logic change.

Good stuff. But since you are not afraid of churn for
cosmetics, let's fix a couple more nits?

> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.c |  146 ++++++++++++++++++++++++++++++++------------------------------
>  1 files changed, 76 insertions(+), 70 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index beefae3..b43f6c6 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -637,86 +637,92 @@ 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 (r->size != 0) {
> -            if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
> -                if (cmd & PCI_COMMAND_IO) {
> -                    new_addr = pci_get_long(d->config + pci_bar(d, i));
> -                    new_addr = new_addr & ~(r->size - 1);
> -                    last_addr = new_addr + r->size - 1;
> -                    /* NOTE: we have only 64K ioports on PC */
> -                    if (last_addr <= new_addr || new_addr == 0 ||
> -                        last_addr >= 0x10000) {
> -                        new_addr = PCI_BAR_UNMAPPED;
> -                    }
> -                } else {
> +
> +        /* this region isn't registered */
> +        if (r->size == 0)

Let's replace by !r->size?

> +            continue;
> +
> +        if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
> +            if (cmd & PCI_COMMAND_IO) {
> +                new_addr = pci_get_long(d->config + pci_bar(d, i));
> +                new_addr = new_addr & ~(r->size - 1);
> +                last_addr = new_addr + r->size - 1;
> +                /* NOTE: we have only 64K ioports on PC */
> +                if (last_addr <= new_addr || new_addr == 0 ||
> +                    last_addr >= 0x10000) {
>                      new_addr = PCI_BAR_UNMAPPED;
>                  }
>              } else {
> -                if (cmd & PCI_COMMAND_MEMORY) {
> -                    if (r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
> -                        new_addr = pci_get_quad(d->config + pci_bar(d, i));
> -                    } else {
> -                        new_addr = pci_get_long(d->config + pci_bar(d, i));
> -                    }
> -                    /* the ROM slot has a specific enable bit */
> -                    if (i == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE))
> -                        goto no_mem_map;
> -                    new_addr = new_addr & ~(r->size - 1);
> -                    last_addr = new_addr + r->size - 1;
> -                    /* NOTE: we do not support wrapping */
> -                    /* XXX: as we cannot support really dynamic
> -                       mappings, we handle specific values as invalid
> -                       mappings. */
> -                    if (last_addr <= new_addr || new_addr == 0 ||
> -                        last_addr == PCI_BAR_UNMAPPED ||
> -
> -                        /* Now pcibus_t is 64bit.
> -                         * Check if 32 bit BAR wrap around explicitly.
> -                         * Without this, PC ide doesn't work well.
> -                         * TODO: remove this work around.
> -                         */
> -                        (!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) &&
> -                         last_addr >= UINT32_MAX) ||
> -
> -                        /*
> -                         * OS is allowed to set BAR beyond its addressable
> -                         * bits. For example, 32 bit OS can set 64bit bar
> -                         * to >4G. Check it.
> -                         */
> -                        last_addr >= TARGET_PHYS_ADDR_MAX) {
> -                        new_addr = PCI_BAR_UNMAPPED;
> -                    }
> +                new_addr = PCI_BAR_UNMAPPED;
> +            }
> +        } else {
> +            if (cmd & PCI_COMMAND_MEMORY) {
> +                if (r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
> +                    new_addr = pci_get_quad(d->config + pci_bar(d, i));
>                  } else {
> -                no_mem_map:
> +                    new_addr = pci_get_long(d->config + pci_bar(d, i));
> +                }
> +                /* the ROM slot has a specific enable bit */
> +                if (i == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE))
> +                    goto no_mem_map;
> +                new_addr = new_addr & ~(r->size - 1);
> +                last_addr = new_addr + r->size - 1;
> +                /* NOTE: we do not support wrapping */
> +                /* XXX: as we cannot support really dynamic
> +                   mappings, we handle specific values as invalid
> +                   mappings. */
> +                if (last_addr <= new_addr || new_addr == 0 ||
> +                    last_addr == PCI_BAR_UNMAPPED ||
> +
> +                    /* Now pcibus_t is 64bit.
> +                     * Check if 32 bit BAR wrap around explicitly.
> +                     * Without this, PC ide doesn't work well.
> +                     * TODO: remove this work around.
> +                     */
> +                    (!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) &&
> +                     last_addr >= UINT32_MAX) ||
> +
> +                    /*
> +                     * OS is allowed to set BAR beyond its addressable
> +                     * bits. For example, 32 bit OS can set 64bit bar
> +                     * to >4G. Check it.
> +                     */
> +                    last_addr >= TARGET_PHYS_ADDR_MAX) {
>                      new_addr = PCI_BAR_UNMAPPED;
>                  }
> +            } else {
> +            no_mem_map:
> +                new_addr = PCI_BAR_UNMAPPED;

Grr goto into scope ...
Can't we get rid of this as well?
Let's just move the whole if() statement to a subfunction,
then we can return PCI_BAR_UNMAPPED instead of goto.



>              }
> -            /* now do the real mapping */
> -            if (new_addr != r->addr) {
> -                if (r->addr != PCI_BAR_UNMAPPED) {
> -                    if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
> -                        int class;
> -                        /* NOTE: specific hack for IDE in PC case:
> -                           only one byte must be mapped. */
> -                        class = pci_get_word(d->config + PCI_CLASS_DEVICE);
> -                        if (class == 0x0101 && r->size == 4) {
> -                            isa_unassign_ioport(r->addr + 2, 1);
> -                        } else {
> -                            isa_unassign_ioport(r->addr, r->size);
> -                        }
> -                    } else {
> -                        cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
> -                                                     r->size,
> -                                                     IO_MEM_UNASSIGNED);
> -                        qemu_unregister_coalesced_mmio(r->addr, r->size);
> -                    }
> -                }
> -                r->addr = new_addr;
> -                if (r->addr != PCI_BAR_UNMAPPED) {
> -                    r->map_func(d, i, r->addr, r->size, r->type);
> +        }
> +
> +        /* This bar isn't changed */
> +        if (new_addr == r->addr)
> +            continue;
> +
> +        /* now do the real mapping */
> +        if (r->addr != PCI_BAR_UNMAPPED) {
> +            if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
> +                int class;
> +                /* NOTE: specific hack for IDE in PC case:
> +                   only one byte must be mapped. */
> +                class = pci_get_word(d->config + PCI_CLASS_DEVICE);
> +                if (class == 0x0101 && r->size == 4) {
> +                    isa_unassign_ioport(r->addr + 2, 1);
> +                } else {
> +                    isa_unassign_ioport(r->addr, r->size);
>                  }
> +            } else {
> +                cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
> +                                             r->size,
> +                                             IO_MEM_UNASSIGNED);
> +                qemu_unregister_coalesced_mmio(r->addr, r->size);
>              }
>          }
> +        r->addr = new_addr;
> +        if (r->addr != PCI_BAR_UNMAPPED) {
> +            r->map_func(d, i, r->addr, r->size, r->type);
> +        }
>      }
>  }
>  
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V6 25/32] pci: add helper functions to check ranges overlap.
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 25/32] pci: add helper functions to check ranges overlap Isaku Yamahata
@ 2009-11-03 14:18   ` Michael S. Tsirkin
  0 siblings, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 14:18 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:19PM +0900, Isaku Yamahata wrote:
> add helper function to check ranges overlap suggested by
> Michael S. Tsirkin <mst@redhat.com>.
> His original suggestion was to use [first, last], however I chosen
> to use offset, length pair, i.e. [offset, offset + length)
> because pci configuration space related functions all uses offset and length
> pair, so it helps to avoid to type constant twice.
> 
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Acked-by: Michael S. Tsirkin <mst@redhat.com>

> ---
>  hw/pci.h |   29 +++++++++++++++++++++++++++++
>  1 files changed, 29 insertions(+), 0 deletions(-)
> 
> diff --git a/hw/pci.h b/hw/pci.h
> index 8e5d64a..7991bfd 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -406,4 +406,33 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
>  PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
>                              void *pic, int devfn_min, int nirq);
>  
> +/* These are not pci specific. Should move into a separate header.
> + * Only pci.c uses them, so keep them here for now.
> + */
> +
> +/* Get last byte of a range from offset + length.
> + * Undefined for ranges that wrap around 0. */
> +static inline uint64_t range_get_last(uint64_t offset, uint64_t len)
> +{
> +    return offset + len - 1;
> +}
> +
> +/* Check whether a given range covers a given byte. */
> +static inline int range_covers_byte(uint64_t offset, uint64_t len,
> +                                    uint64_t byte)
> +{
> +    return offset <= byte && byte <= range_get_last(offset, len);
> +}
> +
> +/* Check whether 2 given ranges overlap.
> + * Undefined if ranges that wrap around 0. */
> +static inline int ranges_overlap(uint64_t first1, uint64_t len1,
> +                                 uint64_t first2, uint64_t len2)
> +{
> +    uint64_t last1 = range_get_last(first1, len1);
> +    uint64_t last2 = range_get_last(first2, len2);
> +
> +    return !(last2 < first1 || last1 < first2);
> +}
> +
>  #endif
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V6 26/32] pci: use range helper functions.
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 26/32] pci: use range helper functions Isaku Yamahata
@ 2009-11-03 14:19   ` Michael S. Tsirkin
  2009-11-10 15:59   ` Michael S. Tsirkin
  1 sibling, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 14:19 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:20PM +0900, Isaku Yamahata wrote:
> clean up pci_default_write_config() by the range helper functions.
> 
> Suggested by Michael S. Tsirkin <mst@redhat.com>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Acked-by: Michael S. Tsirkin <mst@redhat.com>

> ---
>  hw/pci.c |    8 ++------
>  1 files changed, 2 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 67133b6..d9fd564 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -699,19 +699,15 @@ 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 = pci_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)
> -        || ((orig[PCI_COMMAND] ^ d->config[PCI_COMMAND])
> -            & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)))
> +    if (ranges_overlap(addr, l, PCI_BASE_ADDRESS_0, 24) ||
> +        range_covers_byte(addr, l, PCI_COMMAND))
>          pci_update_mappings(d);
>  }
>  
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V6 27/32] pci: teach pci_default_config_write() ROM bar for normal/bridge device .
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 27/32] pci: teach pci_default_config_write() ROM bar for normal/bridge device Isaku Yamahata
@ 2009-11-03 14:20   ` Michael S. Tsirkin
  2009-11-10 16:01   ` Michael S. Tsirkin
  1 sibling, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 14:20 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:21PM +0900, Isaku Yamahata wrote:
> 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()
> Also update pci mapping when PCI_ROM_ADDRESS1 is written for header type 1.
> 
> pci_update_mapping() path isn't performance critical,
> so call it even independent of header type.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Acked-by: Michael S. Tsirkin <mst@redhat.com>

> ---
>  hw/pci.c |    2 ++
>  1 files changed, 2 insertions(+), 0 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index d9fd564..46b22ec 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -707,6 +707,8 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
>          d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
>      }
>      if (ranges_overlap(addr, l, PCI_BASE_ADDRESS_0, 24) ||
> +        ranges_overlap(addr, l, PCI_ROM_ADDRESS, 4) ||
> +        ranges_overlap(addr, l, PCI_ROM_ADDRESS1, 4) ||
>          range_covers_byte(addr, l, PCI_COMMAND))
>          pci_update_mappings(d);
>  }
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V6 28/32] pci: initialize pci config headers depending it pci header type.
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 28/32] pci: initialize pci config headers depending it pci header type Isaku Yamahata
@ 2009-11-03 14:27   ` Michael S. Tsirkin
  2009-11-12  5:23     ` Isaku Yamahata
  0 siblings, 1 reply; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 14:27 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:22PM +0900, Isaku Yamahata wrote:
> - Only sets default subsystem id for header type 00.(normal header type)
>   because header type 01 doesn't have subsystem id, and uses the register
>   for other purpose. So setting default subsystem id doesn't make sense.
> 
> - initialize wmask more for header type 01.(bridge header type)
>   Without those wmasks, linux was confused not boot,
>   and lspci was confused not to print out expected IO/memory range.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/cirrus_vga.c |    1 -
>  hw/pci.c        |   42 ++++++++++++++++++++++++++++++++++++++----
>  hw/pci.h        |   29 +++++++++++++++++++++++++++++
>  3 files changed, 67 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
> index ef72c62..c1bafd3 100644
> --- a/hw/cirrus_vga.c
> +++ b/hw/cirrus_vga.c
> @@ -180,7 +180,6 @@
>  #define PCI_COMMAND_PALETTESNOOPING         0x0020
>  #define PCI_COMMAND_PARITYDETECTION         0x0040
>  #define PCI_COMMAND_ADDRESSDATASTEPPING     0x0080
> -#define PCI_COMMAND_SERR                    0x0100
>  #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 46b22ec..beefae3 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -445,6 +445,30 @@ static void pci_init_wmask(PCIDevice *dev)
>          dev->wmask[i] = 0xff;
>  }
>  
> +static void pci_init_wmask_bridge(PCIDevice *d)
> +{
> +    /* PCI_PRIMARY_BUS, PCI_SECONDARY_BUS, PCI_SUBORDINATE_BUS and
> +       PCI_SEC_LETENCY_TIMER */
> +    memset(d->wmask + PCI_PRIMARY_BUS, 0xff, 4);
> +
> +    /* base and limit */
> +    d->wmask[PCI_IO_BASE] = PCI_IO_RANGE_MASK & 0xff;
> +    d->wmask[PCI_IO_LIMIT] = PCI_IO_RANGE_MASK & 0xff;
> +    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_PREF_BASE_UPPER32 and PCI_PREF_LIMIT_UPPER32 */
> +    memset(d->wmask + PCI_PREF_BASE_UPPER32, 0xff, 8);
> +
> +    pci_set_word(d->wmask + PCI_BRIDGE_CONTROL, 0xffff);
> +}
> +
>  static void pci_config_alloc(PCIDevice *pci_dev)
>  {
>      int config_size = pci_config_size(pci_dev);
> @@ -467,7 +491,8 @@ static void pci_config_free(PCIDevice *pci_dev)
>  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,
> +                                         uint8_t header_type)
>  {
>      if (devfn < 0) {
>          for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) {
> @@ -484,9 +509,16 @@ 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);
> +
> +    header_type &= ~PCI_HEADER_TYPE_MULTI_FUNCTION;
> +    if (header_type == PCI_HEADER_TYPE_NORMAL) {
> +        pci_set_default_subsystem_id(pci_dev);
> +    }
>      pci_init_cmask(pci_dev);
>      pci_init_wmask(pci_dev);
> +    if (header_type == PCI_HEADER_TYPE_BRIDGE) {
> +        pci_init_wmask_bridge(pci_dev);
> +    }
>  
>      if (!config_read)
>          config_read = pci_default_read_config;

Instead of this, can we have pci_init_bridge that will simply
be called after device has been initialized?
Down the road we will be able to move it to pci_bridge.c


> @@ -509,7 +541,8 @@ 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_HEADER_TYPE_NORMAL);
>      return pci_dev;
>  }
>  static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
> @@ -1059,7 +1092,8 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
>      bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
>      devfn = pci_dev->devfn;
>      pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn,
> -                                     info->config_read, info->config_write);
> +                                     info->config_read, info->config_write,
> +                                     info->header_type);
>      assert(pci_dev);
>      rc = info->init(pci_dev);
>      if (rc != 0)
> diff --git a/hw/pci.h b/hw/pci.h
> index 7991bfd..3f50294 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -100,6 +100,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 */
> @@ -119,16 +127,30 @@ typedef struct PCIIORegion {
>  #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
>  #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
>  #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_MASK      (~0x0fUL)
>  #define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
> +#define PCI_MEMORY_BASE         0x20    /* Memory range behind */
> +#define PCI_MEMORY_LIMIT        0x22
> +#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_MASK    (~0x0fUL)
> +#define PCI_PREF_BASE_UPPER32   0x28    /* Upper half of prefetchable memory range */
>  #define PCI_SUBSYSTEM_VENDOR_ID 0x2c    /* 16 bits */
>  #define PCI_SUBSYSTEM_ID        0x2e    /* 16 bits */
>  #define PCI_ROM_ADDRESS		0x30	/* Bits 31..11 are address, 10..1 reserved */
>  #define  PCI_ROM_ADDRESS_ENABLE	0x01
> +#define PCI_IO_BASE_UPPER16     0x30    /* Upper half of I/O addresses */
> +#define PCI_IO_LIMIT_UPPER16    0x32
>  #define PCI_CAPABILITY_LIST	0x34	/* Offset of first capability list entry */
>  #define PCI_ROM_ADDRESS1	0x38	/* Same as PCI_ROM_ADDRESS, but for htype 1 */
>  #define PCI_INTERRUPT_LINE	0x3c	/* 8 bits */
>  #define PCI_INTERRUPT_PIN	0x3d	/* 8 bits */
>  #define PCI_MIN_GNT		0x3e	/* 8 bits */
> +#define PCI_BRIDGE_CONTROL      0x3e
>  #define PCI_MAX_LAT		0x3f	/* 8 bits */
>  
>  /* Capability lists */


Many of these are unused. I'd rather we only defined what we use.

> @@ -358,6 +380,13 @@ typedef struct {
>      PCIConfigReadFunc *config_read;
>      PCIConfigWriteFunc *config_write;
>  
> +    /* pci config header type */
> +    uint8_t header_type;        /* this is necessary for initialization
> +                                 * code to know its header type before
> +                                 * device specific code can initialize
> +                                 * configuration space.
> +                                 */


The text probably belongs in commit comment.
Comments that tell how field is used quickly get out of date.
Say *what* it is is enough.

> +
>      /* pcie stuff */
>      int is_express;   /* is this device pci express?
>                         * initialization code needs to know this before
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V6 30/32] pci: factor out pci_for_each_device().
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 30/32] pci: factor out pci_for_each_device() Isaku Yamahata
@ 2009-11-03 14:29   ` Michael S. Tsirkin
  0 siblings, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 14:29 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:24PM +0900, Isaku Yamahata wrote:
> split out device iteration logic from pci_for_each_device().
> factored out function, pci_for_each_device_under_bus() will be used later.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.c |   21 ++++++++++++++-------
>  1 files changed, 14 insertions(+), 7 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index b43f6c6..d565f6e 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -885,19 +885,26 @@ static void pci_info_device(PCIBus *bus, PCIDevice *d)
>      }
>  }
>  
> -void pci_for_each_device(PCIBus *bus, int bus_num,
> -                         void (*fn)(PCIBus *b, PCIDevice *d))
> +static void pci_for_each_device_under_bus(PCIBus *bus,
> +                                          void (*fn)(PCIBus *b, PCIDevice *d))
>  {
>      PCIDevice *d;
>      int devfn;
>  
> +    for(devfn = 0; devfn < 256; devfn++) {

256 -> ARRAY_SIZE(bus->devices)

> +        d = bus->devices[devfn];
> +        if (d)
> +            fn(bus, d);
> +    }
> +}
> +
> +void pci_for_each_device(PCIBus *bus, int bus_num,
> +                         void (*fn)(PCIBus *b, PCIDevice *d))
> +{
>      bus = pci_find_bus(bus, bus_num);
> +
>      if (bus) {
> -        for(devfn = 0; devfn < 256; devfn++) {
> -            d = bus->devices[devfn];
> -            if (d)
> -                fn(bus, d);
> -        }
> +        pci_for_each_device_under_bus(bus, fn);
>      }
>  }
>  
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V6 24/32] pci: pcie host and mmcfg support.
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 24/32] pci: pcie host and mmcfg support Isaku Yamahata
@ 2009-11-03 14:50   ` Michael S. Tsirkin
  0 siblings, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 14:50 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:18PM +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>
> ---
>  Makefile.target |    2 +-
>  hw/hw.h         |   11 +++
>  hw/pci.c        |   86 +++++++++++++++++++++----
>  hw/pci.h        |   27 +++++++-
>  hw/pcie_host.c  |  192 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/pcie_host.h  |   50 ++++++++++++++
>  6 files changed, 349 insertions(+), 19 deletions(-)
>  create mode 100644 hw/pcie_host.c
>  create mode 100644 hw/pcie_host.h
> 
> diff --git a/Makefile.target b/Makefile.target
> index db0d0ab..bc3c375 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -154,7 +154,7 @@ endif #CONFIG_BSD_USER
>  # System emulator target
>  ifdef CONFIG_SOFTMMU
>  
> -obj-y = vl.o async.o monitor.o pci.o pci_host.o machine.o gdbstub.o
> +obj-y = vl.o async.o monitor.o pci.o pci_host.o pcie_host.o machine.o gdbstub.o
>  # virtio has to be here due to weird dependency between PCI and virtio-net.
>  # need to fix this properly
>  obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o virtio-pci.o
> diff --git a/hw/hw.h b/hw/hw.h
> index cf8c304..1d4af2a 100644
> --- a/hw/hw.h
> +++ b/hw/hw.h
> @@ -512,6 +512,17 @@ extern const VMStateDescription vmstate_pci_device;
>      .offset     = vmstate_offset_value(_state, _field, PCIDevice),   \
>  }
>  
> +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     = vmstate_offset_value(_state, _field, PCIDevice),   \
> +}
> +
>  extern const VMStateDescription vmstate_i2c_slave;
>  
>  #define VMSTATE_I2C_SLAVE(_field, _state) {                          \
> diff --git a/hw/pci.c b/hw/pci.c
> index a599996..67133b6 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"

Why do we need this include?
Would be nicer not to have the dependency.

> @@ -248,18 +249,24 @@ static uint8_t pci_sub_bus(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[PCI_CONFIG_SPACE_SIZE];
> +    uint8_t *config;
>      int i;
>  
> -    assert(size == sizeof config);
> -    qemu_get_buffer(f, config, sizeof config);
> -    for (i = 0; i < sizeof config; ++i)
> -        if ((config[i] ^ s->config[i]) & s->cmask[i] & ~s->wmask[i])
> +    assert(size == pci_config_size(s));
> +    config = qemu_malloc(size);
> +
> +    qemu_get_buffer(f, config, size);
> +    for (i = 0; i < size; ++i) {
> +        if ((config[i] ^ s->config[i]) & s->cmask[i] & ~s->wmask[i]) {
> +            qemu_free(config);
>              return -EINVAL;
> -    memcpy(s->config, config, sizeof config);
> +        }
> +    }
> +    memcpy(s->config, config, size);
>  
>      pci_update_mappings(s);
>  
> +    qemu_free(config);
>      return 0;
>  }
>  
> @@ -267,6 +274,7 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
>  static void put_pci_config_device(QEMUFile *f, void *pv, size_t size)
>  {
>      const uint8_t *v = pv;
> +    assert(size == pci_config_size(container_of(pv, PCIDevice, config)));
>      qemu_put_buffer(f, v, size);
>  }
>  
> @@ -283,21 +291,42 @@ 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_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
> +                                   vmstate_info_pci_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_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
> +                                   vmstate_info_pci_config,
> +                                   PCIE_CONFIG_SPACE_SIZE),
>          VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
>          VMSTATE_END_OF_LIST()
>      }
>  };
>  
> +static inline const VMStateDescription *pci_get_vmstate(PCIDevice *s)
> +{
> +    return pci_is_express(s) ? &vmstate_pcie_device : &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)
> @@ -406,14 +435,34 @@ static void pci_init_cmask(PCIDevice *dev)
>  static void pci_init_wmask(PCIDevice *dev)
>  {
>      int i;
> +    int config_size = pci_config_size(dev);
> +
>      dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
>      dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
>      pci_set_word(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;

By the way, no idea why didn't I just memset it instead of a loop.
Let's fix?

>  }
>  
> +static void pci_config_alloc(PCIDevice *pci_dev)
> +{
> +    int config_size = pci_config_size(pci_dev);
> +
> +    pci_dev->config = qemu_mallocz(config_size);
> +    pci_dev->cmask = qemu_mallocz(config_size);
> +    pci_dev->wmask = qemu_mallocz(config_size);
> +    pci_dev->used = qemu_mallocz(config_size);
> +}
> +
> +static void pci_config_free(PCIDevice *pci_dev)
> +{
> +    qemu_free(pci_dev->config);
> +    qemu_free(pci_dev->cmask);
> +    qemu_free(pci_dev->wmask);
> +    qemu_free(pci_dev->used);
> +}
> +
>  /* -1 for devfn means auto assign */
>  static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
>                                           const char *name, int devfn,
> @@ -434,6 +483,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);
> @@ -501,6 +551,7 @@ static int pci_unregister_device(DeviceState *dev)
>  
>      qemu_free_irqs(pci_dev->irq);
>      pci_dev->bus->devices[pci_dev->devfn] = NULL;
> +    pci_config_free(pci_dev);
>      return 0;
>  }
>  
> @@ -641,7 +692,7 @@ uint32_t pci_default_read_config(PCIDevice *d,
>  {
>      uint32_t val = 0;
>      assert(len == 1 || len == 2 || len == 4);
> -    len = MIN(len, PCI_CONFIG_SPACE_SIZE - address);
> +    len = MIN(len, pci_config_size(d) - address);
>      memcpy(&val, d->config + address, len);
>      return le32_to_cpu(val);
>  }
> @@ -650,10 +701,11 @@ 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 = pci_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);
>      }
> @@ -1001,6 +1053,11 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
>      PCIBus *bus;
>      int devfn, rc;
>  
> +    /* initialize cap_present for pci_is_express() and pci_config_size() */
> +    if (info->is_express) {
> +        pci_dev->cap_present |= QEMU_PCI_CAP_EXPRESS;
> +    }
> +
>      bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
>      devfn = pci_dev->devfn;
>      pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn,

It would be better if we could have a separate pcie_init.
But no idea how to make it so. Ideas?

> @@ -1057,9 +1114,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 = pci_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 4f4266d..8e5d64a 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -163,28 +163,31 @@ typedef struct PCIIORegion {
>  #define PCI_CONFIG_HEADER_SIZE 0x40
>  /* Size of the standard PCI config space */
>  #define PCI_CONFIG_SPACE_SIZE 0x100
> +/* Size of the standart PCIe config space: 4KB */
> +#define PCIE_CONFIG_SPACE_SIZE  0x1000
>  
>  #define PCI_NUM_PINS 4 /* A-D */
>  
>  /* Bits in cap_present field. */
>  enum {
>      QEMU_PCI_CAP_MSIX = 0x1,
> +    QEMU_PCI_CAP_EXPRESS = 0x2,
>  };
>  
>  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;
> @@ -354,6 +357,12 @@ typedef struct {
>      PCIUnregisterFunc *exit;
>      PCIConfigReadFunc *config_read;
>      PCIConfigWriteFunc *config_write;
> +
> +    /* pcie stuff */
> +    int is_express;   /* is this device pci express?
> +                       * initialization code needs to know this before
> +                       * each specific device initialization.
> +                       */

kill two last lines.

>  } PCIDeviceInfo;
>  
>  void pci_qdev_register(PCIDeviceInfo *info);
> @@ -362,6 +371,16 @@ void pci_qdev_register_many(PCIDeviceInfo *info);
>  PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name);
>  PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
>  
> +static inline int pci_is_express(PCIDevice *d)
> +{
> +    return d->cap_present & QEMU_PCI_CAP_EXPRESS;
> +}
> +
> +static inline uint32_t pci_config_size(PCIDevice *d)
> +{
> +    return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE;
> +}
> +
>  /* lsi53c895a.c */
>  #define LSI_MAX_DEVS 7
>  
> diff --git a/hw/pcie_host.c b/hw/pcie_host.c
> new file mode 100644
> index 0000000..b52fec6
> --- /dev/null
> +++ b/hw/pcie_host.c
> @@ -0,0 +1,192 @@
> +/*
> + * pcie_host.c
> + * utility functions for pci express host bridge.
> + *
> + * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
> + *                    VA Linux Systems Japan K.K.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> +
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> +
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#include "hw.h"
> +#include "pci.h"
> +#include "pcie_host.h"
> +
> +/*
> + * PCI express mmcfig address
> + * bit 20 - 28: bus number
> + * bit 15 - 19: device number
> + * bit 12 - 14: function number
> + * bit  0 - 11: offset in configuration space of a given device
> + */
> +#define PCIE_MMCFG_SIZE_MAX             (1ULL << 28)
> +#define PCIE_MMCFG_SIZE_MIN             (1ULL << 20)
> +#define PCIE_MMCFG_BUS_BIT              20
> +#define PCIE_MMCFG_BUS_MASK             0x1ff
> +#define PCIE_MMCFG_DEVFN_BIT            12
> +#define PCIE_MMCFG_DEVFN_MASK           0xff
> +#define PCIE_MMCFG_CONFOFFSET_MASK      0xfff
> +#define PCIE_MMCFG_BUS(addr)            (((addr) >> PCIE_MMCFG_BUS_BIT) & \
> +                                         PCIE_MMCFG_BUS_MASK)
> +#define PCIE_MMCFG_DEVFN(addr)          (((addr) >> PCIE_MMCFG_DEVFN_BIT) & \
> +                                         PCIE_MMCFG_DEVFN_MASK)
> +#define PCIE_MMCFG_CONFOFFSET(addr)     ((addr) & PCIE_MMCFG_CONFOFFSET_MASK)
> +
> +
> +/* a helper function to get a PCIDevice for a given mmconfig address */
> +static inline PCIDevice *pcie_mmcfg_addr_to_dev(PCIBus *s, uint32_t mmcfg_addr)
> +{
> +    return pci_find_device(s, PCIE_MMCFG_BUS(mmcfg_addr),
> +                           PCI_SLOT(PCIE_MMCFG_DEVFN(mmcfg_addr)),
> +                           PCI_FUNC(PCIE_MMCFG_DEVFN(mmcfg_addr)));
> +}
> +
> +static void pcie_mmcfg_data_write(PCIBus *s,
> +                                  uint32_t mmcfg_addr, uint32_t val, int len)
> +{
> +    PCIDevice *pci_dev = pcie_mmcfg_addr_to_dev(s, mmcfg_addr);
> +
> +    if (!pci_dev)
> +        return;
> +
> +    pci_dev->config_write(pci_dev,
> +                          PCIE_MMCFG_CONFOFFSET(mmcfg_addr), val, len);
> +}
> +
> +static uint32_t pcie_mmcfg_data_read(PCIBus *s,
> +                                     uint32_t mmcfg_addr, int len)
> +{
> +    PCIDevice *pci_dev = pcie_mmcfg_addr_to_dev(s, mmcfg_addr);
> +    uint32_t val;
> +
> +    if (!pci_dev) {
> +        switch(len) {
> +        case 1:
> +            val = 0xff;
> +            break;
> +        case 2:
> +            val = 0xffff;
> +            break;
> +        default:
> +        case 4:
> +            val = 0xffffffff;
> +            break;
> +        }

use the memcpy hack?

> +    } else {
> +        val = pci_dev->config_read(pci_dev,
> +                                   PCIE_MMCFG_CONFOFFSET(mmcfg_addr), len);
> +    }
> +
> +    return val;
> +}
> +
> +static void pcie_mmcfg_data_writeb(void *opaque,
> +                                   target_phys_addr_t addr, uint32_t value)
> +{
> +    PCIExpressHost *e = opaque;
> +    pcie_mmcfg_data_write(e->pci.bus, addr - e->base_addr, value, 1);
> +}
> +
> +static void pcie_mmcfg_data_writew(void *opaque,
> +                                   target_phys_addr_t addr, uint32_t value)
> +{
> +    PCIExpressHost *e = opaque;
> +    pcie_mmcfg_data_write(e->pci.bus, addr - e->base_addr, value, 2);
> +}
> +
> +static void pcie_mmcfg_data_writel(void *opaque,
> +                                   target_phys_addr_t addr, uint32_t value)
> +{
> +    PCIExpressHost *e = opaque;
> +    pcie_mmcfg_data_write(e->pci.bus, addr - e->base_addr, value, 4);
> +}
> +
> +static uint32_t pcie_mmcfg_data_readb(void *opaque, target_phys_addr_t addr)
> +{
> +    PCIExpressHost *e = opaque;
> +    return pcie_mmcfg_data_read(e->pci.bus, addr - e->base_addr, 1);
> +}
> +
> +static uint32_t pcie_mmcfg_data_readw(void *opaque, target_phys_addr_t addr)
> +{
> +    PCIExpressHost *e = opaque;
> +    return pcie_mmcfg_data_read(e->pci.bus, addr - e->base_addr, 2);
> +}
> +
> +static uint32_t pcie_mmcfg_data_readl(void *opaque, target_phys_addr_t addr)
> +{
> +    PCIExpressHost *e = opaque;
> +    return pcie_mmcfg_data_read(e->pci.bus, addr - e->base_addr, 4);
> +}
> +
> +
> +static CPUWriteMemoryFunc * const pcie_mmcfg_write[] =
> +{
> +    pcie_mmcfg_data_writeb,
> +    pcie_mmcfg_data_writew,
> +    pcie_mmcfg_data_writel,
> +};
> +
> +static CPUReadMemoryFunc * const pcie_mmcfg_read[] =
> +{
> +    pcie_mmcfg_data_readb,
> +    pcie_mmcfg_data_readw,
> +    pcie_mmcfg_data_readl,
> +};
> +
> +/* pcie_host::base_addr == PCIE_BASE_ADDR_UNMAPPED when it isn't mapped. */
> +#define PCIE_BASE_ADDR_UNMAPPED  ((target_phys_addr_t)-1ULL)
> +
> +int pcie_host_init(PCIExpressHost *e)
> +{
> +    e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
> +    e->mmio_index =
> +        cpu_register_io_memory(pcie_mmcfg_read, pcie_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_UNMAPPED) {
> +        cpu_register_physical_memory(e->base_addr, e->size, IO_MEM_UNASSIGNED);
> +        e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
> +    }
> +}
> +
> +void pcie_host_mmcfg_map(PCIExpressHost *e,
> +                         target_phys_addr_t addr, uint32_t size)
> +{
> +    assert(!(size & (size - 1)));       /* power of 2 */
> +    assert(size >= PCIE_MMCFG_SIZE_MIN);
> +    assert(size <= PCIE_MMCFG_SIZE_MAX);
> +
> +    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);
> +    }
> +}
> diff --git a/hw/pcie_host.h b/hw/pcie_host.h
> new file mode 100644
> index 0000000..a7771c9
> --- /dev/null
> +++ b/hw/pcie_host.h
> @@ -0,0 +1,50 @@
> +/*
> + * pcie_host.h
> + *
> + * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
> + *                    VA Linux Systems Japan K.K.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> +
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> +
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#ifndef PCIE_HOST_H
> +#define PCIE_HOST_H
> +
> +#include "pci_host.h"
> +
> +typedef struct {

struct -> struct PCIExpressHost.
typedef can move to common.h then.

> +    PCIHostState pci;
> +
> +    /* express part */
> +
> +    /* base address where MMCONFIG area is mapped. */
> +    target_phys_addr_t  base_addr;
> +
> +    /* the size of MMCONFIG area. It's host bridge dependent */
> +    target_phys_addr_t  size;
> +
> +    /* result of cpu_register_io_memory() to map MMCONFIG area */
> +    int mmio_index;
> +} PCIExpressHost;
> +
> +int pcie_host_init(PCIExpressHost *e);
> +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 /* PCIE_HOST_H */
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V6 31/32] pci: implement pci bridge filtering.
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 31/32] pci: implement pci bridge filtering Isaku Yamahata
@ 2009-11-03 15:01   ` Michael S. Tsirkin
  0 siblings, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-03 15:01 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:25PM +0900, Isaku Yamahata wrote:
> This patch implements pci bridge filtering.
> 
> TODO: currently almost all the map funcions assumes
> filtered_size == size and addr & ~(size - 1) == addr.
> However with bridge filtering, they aren't always true.
> Teach them such cases, such that filtered_size < size and
> addr & (size - 1) != 0.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Thanks for looking into this, good stuff.
A couple of minor nits.

> ---
>  hw/pci.c |  155 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
>  hw/pci.h |    3 +
>  2 files changed, 151 insertions(+), 7 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index d565f6e..336c1a3 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -560,10 +560,10 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
>          if (!r->size || r->addr == PCI_BAR_UNMAPPED)
>              continue;
>          if (r->type == PCI_BASE_ADDRESS_SPACE_IO) {
> -            isa_unassign_ioport(r->addr, r->size);
> +            isa_unassign_ioport(r->addr, r->filtered_size);
>          } else {
>              cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
> -                                                     r->size,
> +                                                     r->filtered_size,
>                                                       IO_MEM_UNASSIGNED);
>          }
>      }
> @@ -608,6 +608,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
>      r = &pci_dev->io_regions[region_num];
>      r->addr = PCI_BAR_UNMAPPED;
>      r->size = size;
> +    r->filtered_size = size;
>      r->type = type;
>      r->map_func = map_func;
>  
> @@ -628,11 +629,111 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
>      }
>  }
>  
> +static uint32_t pci_config_get_io_base(PCIDevice *d,
> +                                       uint32_t base, uint32_t base_upper16)
> +{

base_upper16 unused?

> +    uint32_t val;
> +
> +    val = ((uint32_t)d->config[base] & PCI_IO_RANGE_MASK) << 8;
> +    if (d->config[base] & PCI_IO_RANGE_TYPE_32) {
> +        val |= (uint32_t)pci_get_word(d->config + PCI_IO_BASE_UPPER16) << 16;
> +    }
> +    return val;
> +}
> +
> +static uint64_t pci_config_get_memory_base(PCIDevice *d, uint32_t base)
> +{
> +    return ((uint64_t)pci_get_word(d->config + base) & PCI_MEMORY_RANGE_MASK)
> +        << 16;
> +}
> +
> +static uint64_t pci_config_get_pref_base(PCIDevice *d,
> +                                         uint32_t base, uint32_t upper)
> +{
> +    uint64_t val;
> +    val = ((uint64_t)pci_get_word(d->config + base) &
> +           PCI_PREF_RANGE_MASK) << 16;
> +    val |= (uint64_t)pci_get_long(d->config + upper) << 32;
> +    return val;
> +}

When is it 64 bit and when pcibus_t?
Also, bus might not support 64 bit addressing: need to check?


> +
> +static pcibus_t pci_bridge_get_base(PCIDevice *bridge, uint8_t type)
> +{
> +    pcibus_t base;
> +    if (type & PCI_BASE_ADDRESS_SPACE_IO) {
> +        base = pci_config_get_io_base(bridge,
> +                                      PCI_IO_BASE, PCI_IO_BASE_UPPER16);
> +    } else {
> +        if (type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
> +            base = pci_config_get_pref_base(
> +                bridge, PCI_PREF_MEMORY_BASE, PCI_PREF_BASE_UPPER32);
> +        } else {
> +            base = pci_config_get_memory_base(bridge, PCI_MEMORY_BASE);
> +        }
> +    }
> +
> +    return base;
> +}
> +
> +static pcibus_t pci_bridge_get_limit(PCIDevice *bridge, uint8_t type)
> +{
> +    pcibus_t limit;
> +    if (type & PCI_BASE_ADDRESS_SPACE_IO) {
> +        limit = pci_config_get_io_base(bridge,
> +                                      PCI_IO_LIMIT, PCI_IO_LIMIT_UPPER16);
> +        limit |= 0xfff;         /* PCI bridge spec 3.2.5.6. */
> +    } else {
> +        if (type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
> +            limit = pci_config_get_pref_base(
> +                bridge, PCI_PREF_MEMORY_LIMIT, PCI_PREF_LIMIT_UPPER32);
> +        } else {
> +            limit = pci_config_get_memory_base(bridge, PCI_MEMORY_LIMIT);
> +        }
> +        limit |= 0xfffff;       /* PCI bridge spec 3.2.5.{1, 8}. */
> +    }
> +    return limit;
> +}
> +
> +static void pci_bridge_filter(PCIDevice *d, pcibus_t *addr, pcibus_t *size,
> +                              uint8_t type)
> +{
> +    pcibus_t base = *addr;
> +    pcibus_t limit = *addr + *size - 1;
> +    PCIDevice *br;
> +
> +    for (br = d->bus->parent_dev; br; br = br->bus->parent_dev) {
> +        uint16_t cmd = pci_get_word(d->config + PCI_COMMAND);
> +
> +        if (type & PCI_BASE_ADDRESS_SPACE_IO) {
> +            if (!(cmd & PCI_COMMAND_IO)) {
> +                goto no_map;
> +            }
> +        } else {
> +            if (!(cmd & PCI_COMMAND_MEMORY)) {
> +                goto no_map;
> +            }
> +        }
> +
> +        base = MAX(base, pci_bridge_get_base(br, type));
> +        limit = MIN(limit, pci_bridge_get_limit(br, type));
> +    }
> +
> +    if (base > limit) {
> +    no_map:

Could you code this without goto into scope please?
Using subfunctions usually helps.

> +        *addr = PCI_BAR_UNMAPPED;
> +        *size = 0;
> +    } else {
> +        *addr = base;
> +        *size = limit - base + 1;
> +    }
> +}
> +
>  static void pci_update_mappings(PCIDevice *d)
>  {
>      PCIIORegion *r;
>      int cmd, i;
>      pcibus_t last_addr, new_addr;
> +    pcibus_t filtered_size;
>  
>      cmd = pci_get_word(d->config + PCI_COMMAND);
>      for(i = 0; i < PCI_NUM_REGIONS; i++) {
> @@ -696,8 +797,14 @@ static void pci_update_mappings(PCIDevice *d)
>              }
>          }
>  
> +        /* bridge filtering */
> +        filtered_size = r->size;
> +        if (new_addr != PCI_BAR_UNMAPPED) {
> +            pci_bridge_filter(d, &new_addr, &filtered_size, r->type);
> +        }
> +
>          /* This bar isn't changed */
> -        if (new_addr == r->addr)
> +        if (new_addr == r->addr && filtered_size == r->filtered_size)
>              continue;
>  
>          /* now do the real mapping */
> @@ -710,18 +817,26 @@ static void pci_update_mappings(PCIDevice *d)
>                  if (class == 0x0101 && r->size == 4) {
>                      isa_unassign_ioport(r->addr + 2, 1);
>                  } else {
> -                    isa_unassign_ioport(r->addr, r->size);
> +                    isa_unassign_ioport(r->addr, r->filtered_size);
>                  }
>              } else {
>                  cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
> -                                             r->size,
> +                                             r->filtered_size,
>                                               IO_MEM_UNASSIGNED);
> -                qemu_unregister_coalesced_mmio(r->addr, r->size);
> +                qemu_unregister_coalesced_mmio(r->addr, r->filtered_size);
>              }
>          }
>          r->addr = new_addr;
> +        r->filtered_size = filtered_size;
>          if (r->addr != PCI_BAR_UNMAPPED) {
> -            r->map_func(d, i, r->addr, r->size, r->type);
> +            /*
> +             * TODO: currently almost all the map funcions assumes
> +             * filtered_size == size and addr & ~(size - 1) == addr.
> +             * However with bridge filtering, they aren't always true.
> +             * Teach them such cases, such that filtered_size < size and
> +             * addr & (size - 1) != 0.
> +             */
> +            r->map_func(d, i, r->addr, r->filtered_size, r->type);
>          }
>      }
>  }
> @@ -994,10 +1109,36 @@ typedef struct {
>      uint32_t did;
>  } PCIBridge;
>  
> +
> +static void pci_bridge_update_mappings_fn(PCIBus *b, PCIDevice *d)
> +{
> +    pci_update_mappings(d);
> +}
> +
> +static void pci_bridge_update_mappings(PCIBus *b)
> +{
> +    PCIBus *child;
> +
> +    pci_for_each_device_under_bus(b, pci_bridge_update_mappings_fn);
> +
> +    QLIST_FOREACH(child, &b->child, sibling) {
> +        pci_bridge_update_mappings(child);
> +    }
> +}
> +
>  static void pci_bridge_write_config(PCIDevice *d,
>                               uint32_t address, uint32_t val, int len)
>  {
>      pci_default_write_config(d, address, val, len);
> +
> +    if (/* io base/limit */
> +        ranges_overlap(address, len, PCI_IO_BASE, 2) ||
> +
> +        /* memory base/limit, prefetchable base/limit and
> +           io base/limit upper 16 */
> +        ranges_overlap(address, len, PCI_MEMORY_BASE, 20)) {
> +        pci_bridge_update_mappings(d->bus);
> +    }
>  }
>  
>  PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
> diff --git a/hw/pci.h b/hw/pci.h
> index 3f50294..9a56d0d 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -86,6 +86,7 @@ typedef struct PCIIORegion {
>      pcibus_t addr; /* current PCI mapping address. -1 means not mapped */
>  #define PCI_BAR_UNMAPPED (~(pcibus_t)0)
>      pcibus_t size;
> +    pcibus_t filtered_size;
>      uint8_t type;
>      PCIMapIORegionFunc *map_func;
>  } PCIIORegion;
> @@ -130,6 +131,7 @@ typedef struct PCIIORegion {
>  #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_32	0x01
>  #define  PCI_IO_RANGE_MASK      (~0x0fUL)
>  #define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
>  #define PCI_MEMORY_BASE         0x20    /* Memory range behind */
> @@ -139,6 +141,7 @@ typedef struct PCIIORegion {
>  #define PCI_PREF_MEMORY_LIMIT   0x26
>  #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_SUBSYSTEM_VENDOR_ID 0x2c    /* 16 bits */
>  #define PCI_SUBSYSTEM_ID        0x2e    /* 16 bits */
>  #define PCI_ROM_ADDRESS		0x30	/* Bits 31..11 are address, 10..1 reserved */
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V6 12/32] pci_host.h: move functions in pci_host.h into .c file.
  2009-11-03 13:35     ` Michael S. Tsirkin
@ 2009-11-04  4:09       ` Isaku Yamahata
  0 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-11-04  4:09 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Tue, Nov 03, 2009 at 03:35:12PM +0200, Michael S. Tsirkin wrote:
> On Tue, Nov 03, 2009 at 03:31:51PM +0200, Michael S. Tsirkin wrote:
> > On Fri, Oct 30, 2009 at 09:21:06PM +0900, Isaku Yamahata wrote:
> > > split static functions in pci_host.h into pci_host.c and
> > > pci_host_template.h.
> > > 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 functions which are instantiated in .c by including
> > > pci_host.h with typedefing pci_addr_t.
> > > pci_addr_t is per pci host bridge and is typedef'ed to uint32_t for ioio
> > > or target_phys_addr_t for mmio in .c file.
> > > That prevents from including pci_host.h to use PCIHostState because of
> > > requiring type, pci_addr_t.
> > > 
> > > Its purpose to include is to instantiate io function for mmio or ioio
> > > depending on which pci host bridge requires ioio or mmio.
> > > To avoid including code, we always instantiate both version.
> > > 
> > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > 
> > I think this is good cleanup.  Maybe names can be shorter:
> > pci_host_data_register_io_memory -> pci_host_register_io_memory
> > pci_host_data_register_ioport -> pci_host_register_ioport
> > 
> > What do you think?
> 
> Or maybe not - we have to avoid confusing this with config...

How about the followings?
pci_host_{conf, data}_register_{mmio, mmio_noswap, ioport}()

-- 
yamahata

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

* [Qemu-devel] Re: [PATCH V6 13/32] pci_host: consolidate pci config address access.
  2009-11-03 13:45   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-11-04  6:14     ` Isaku Yamahata
  2009-11-04 11:50       ` Alexander Graf
  2009-11-04 15:17       ` Aurelien Jarno
  0 siblings, 2 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-11-04  6:14 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: alex, yu.liu, qemu-devel, aurelien

On Tue, Nov 03, 2009 at 03:45:12PM +0200, Michael S. Tsirkin wrote:
> > --- a/hw/pci_host.c
> > +++ b/hw/pci_host.c
> > @@ -32,6 +32,114 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
> >  #define PCI_DPRINTF(fmt, ...)
> >  #endif
> >  
> > +static void pci_host_config_writel(void *opaque, target_phys_addr_t addr,
> > +                                   uint32_t val)
> > +{
> > +    PCIHostState *s = opaque;
> > +
> > +#ifdef TARGET_WORDS_BIGENDIAN
> > +    val = bswap32(val);
> > +#endif
> 
> I know you just copied it, but isn't this just
> 	val = le32_to_cpu(val);
> 
> ?

Makes sense.


> > +static void pci_host_config_writel_noswap(void *opaque,
> > +                                          target_phys_addr_t addr,
> > +                                          uint32_t val)
> > +{
> > +    PCIHostState *s = opaque;
> > +
> > +    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
> > +                __func__, addr, val);
> > +    s->config_reg = val;
> > +}
> > +
> > +static uint32_t pci_host_config_readl_noswap(void *opaque,
> > +                                             target_phys_addr_t addr)
> > +{
> > +    PCIHostState *s = opaque;
> > +    uint32_t val = s->config_reg;
> > +
> > +    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
> > +                __func__, addr, val);
> > +    return val;
> > +}
> > +
> > +static CPUWriteMemoryFunc * const pci_host_config_write_noswap[] = {
> > +    &pci_host_config_writel_noswap,
> > +    &pci_host_config_writel_noswap,
> > +    &pci_host_config_writel_noswap,
> > +};
> > +
> > +static CPUReadMemoryFunc * const pci_host_config_read_noswap[] = {
> > +    &pci_host_config_readl_noswap,
> > +    &pci_host_config_readl_noswap,
> > +    &pci_host_config_readl_noswap,
> > +};
> > +
> > +int pci_host_config_register_io_memory_noswap(PCIHostState *s)
> 
> This name is clearly too long,
> as a result when you use it you run over the 80 character
> limit. Let's not fix it, let's make name shorter.
> io_memory -> memory?
> 
> > +{
> > +    return cpu_register_io_memory(pci_host_config_read_noswap,
> > +                                  pci_host_config_write_noswap, s);
> > +}
> 
> Do you happen to know whether no swap is really needed?  I suspect some
> of these places really only happen to work because everyone uses intel,
> so they simply would not work on ppc host.

I just followed the original code not to break it.
I dug into the commit logs a bit.
Liu, Aurelian and Alexander, could you give me a comment on
whether those functions needs byte swap (le32_to_cpu()) or not.
  - ppcie500_cfgaddr_{write, read}l() in ppce500_pci.c
  - pci_unin_config_{write, read}l() in unin_pci.c

ppce500_pci.c case:
The related commit is 74c62ba88902575be9ac3badf95d773470884b1c.
The comment on the top in the file says that it is derived from ppc4xx_pci.c.
ppc4xx_pci.c has byte swap, on the other hand ppce500_pci.c doesn't.
So I'm inclined to suspect that the byte swap was dropped accidently.
However I don't know its pci host bridge spec.


unin_pci.c case:
I don't know its spec neither.
The following changeset seems to remove the byte swap deliberately.
Alexander, could you please give us comment on it?

commit 783a20dcb51f7197c56f77c8012fa4abe8a23391
Author: blueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>
Date:   Sat Mar 7 20:53:18 2009 +0000

    Activate uninorth AGP bridge
    
    Linux tries to poke the AGP bridge port and is pretty sad when it can't,
    so let's activate the old code again and throw out the bit modifications,
    as we don't really do anything with the values anyways.
    
    Signed-off-by: Alexander Graf <alex@csgraf.de>
    
    
    git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6750 c046a42c-6fe2-441c-8c8c-71466251a162

-- 
yamahata

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

* Re: [Qemu-devel] Re: [PATCH V6 17/32] pci: 64bit bar support.
  2009-11-03 14:09               ` Michael S. Tsirkin
@ 2009-11-04  6:20                 ` Isaku Yamahata
  2009-11-04 12:19                   ` Michael S. Tsirkin
  0 siblings, 1 reply; 75+ messages in thread
From: Isaku Yamahata @ 2009-11-04  6:20 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Avi Kivity, qemu-devel

On Tue, Nov 03, 2009 at 04:09:16PM +0200, Michael S. Tsirkin wrote:
> > > Long term, we should fix all devices and *then* they can claim 64 bit
> > > support always.  As a nice side effect, we'll be able to avoid
> > > rebuilding devices.
> > 
> > Are you claiming that (PCI) devices emulation shouldn't depend on
> > target_phys_addr_t? That sounds a good idea.
> 
> Yes. Maybe we can stop devices from mapping memory, have pci
> core do it for them.

IIRC Avi proposed such a patch, but it didn't get merged.

-- 
yamahata

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

* [Qemu-devel] Re: [PATCH V6 13/32] pci_host: consolidate pci config address access.
  2009-11-04  6:14     ` Isaku Yamahata
@ 2009-11-04 11:50       ` Alexander Graf
  2009-11-04 15:17       ` Aurelien Jarno
  1 sibling, 0 replies; 75+ messages in thread
From: Alexander Graf @ 2009-11-04 11:50 UTC (permalink / raw)
  To: Isaku Yamahata
  Cc: Hollis Blanchard, Liu Yu-B13201, qemu-devel, Aurelien Jarno,
	Michael S. Tsirkin


On 04.11.2009, at 07:14, Isaku Yamahata wrote:

> On Tue, Nov 03, 2009 at 03:45:12PM +0200, Michael S. Tsirkin wrote:
>>> --- a/hw/pci_host.c
>>> +++ b/hw/pci_host.c
>>> @@ -32,6 +32,114 @@ do { printf("pci_host_data: " fmt , ##  
>>> __VA_ARGS__); } while (0)
>>> #define PCI_DPRINTF(fmt, ...)
>>> #endif
>>>
>>> +static void pci_host_config_writel(void *opaque,  
>>> target_phys_addr_t addr,
>>> +                                   uint32_t val)
>>> +{
>>> +    PCIHostState *s = opaque;
>>> +
>>> +#ifdef TARGET_WORDS_BIGENDIAN
>>> +    val = bswap32(val);
>>> +#endif
>>
>> I know you just copied it, but isn't this just
>> 	val = le32_to_cpu(val);
>>
>> ?
>
> Makes sense.
>
>
>>> +static void pci_host_config_writel_noswap(void *opaque,
>>> +                                          target_phys_addr_t addr,
>>> +                                          uint32_t val)
>>> +{
>>> +    PCIHostState *s = opaque;
>>> +
>>> +    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
>>> +                __func__, addr, val);
>>> +    s->config_reg = val;
>>> +}
>>> +
>>> +static uint32_t pci_host_config_readl_noswap(void *opaque,
>>> +                                             target_phys_addr_t  
>>> addr)
>>> +{
>>> +    PCIHostState *s = opaque;
>>> +    uint32_t val = s->config_reg;
>>> +
>>> +    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
>>> +                __func__, addr, val);
>>> +    return val;
>>> +}
>>> +
>>> +static CPUWriteMemoryFunc * const pci_host_config_write_noswap[]  
>>> = {
>>> +    &pci_host_config_writel_noswap,
>>> +    &pci_host_config_writel_noswap,
>>> +    &pci_host_config_writel_noswap,
>>> +};
>>> +
>>> +static CPUReadMemoryFunc * const pci_host_config_read_noswap[] = {
>>> +    &pci_host_config_readl_noswap,
>>> +    &pci_host_config_readl_noswap,
>>> +    &pci_host_config_readl_noswap,
>>> +};
>>> +
>>> +int pci_host_config_register_io_memory_noswap(PCIHostState *s)
>>
>> This name is clearly too long,
>> as a result when you use it you run over the 80 character
>> limit. Let's not fix it, let's make name shorter.
>> io_memory -> memory?
>>
>>> +{
>>> +    return cpu_register_io_memory(pci_host_config_read_noswap,
>>> +                                  pci_host_config_write_noswap, s);
>>> +}
>>
>> Do you happen to know whether no swap is really needed?  I suspect  
>> some
>> of these places really only happen to work because everyone uses  
>> intel,
>> so they simply would not work on ppc host.
>
> I just followed the original code not to break it.
> I dug into the commit logs a bit.
> Liu, Aurelian and Alexander, could you give me a comment on
> whether those functions needs byte swap (le32_to_cpu()) or not.
>  - ppcie500_cfgaddr_{write, read}l() in ppce500_pci.c
>  - pci_unin_config_{write, read}l() in unin_pci.c
>
> ppce500_pci.c case:
> The related commit is 74c62ba88902575be9ac3badf95d773470884b1c.
> The comment on the top in the file says that it is derived from  
> ppc4xx_pci.c.
> ppc4xx_pci.c has byte swap, on the other hand ppce500_pci.c doesn't.
> So I'm inclined to suspect that the byte swap was dropped accidently.
> However I don't know its pci host bridge spec.
>
>
> unin_pci.c case:
> I don't know its spec neither.
> The following changeset seems to remove the byte swap deliberately.
> Alexander, could you please give us comment on it?

Phew - I frankly don't remember. Something broke because some bits  
were strangely mangled and the way it's not it worked more than it did  
before :-). The whole Uninorth thing is still utterly broken, so  
please don't take anything from there as example.

I do know that Hollis was working a lot about LE/BE issues on PPC in  
Qemu, so he's probably the best person to CC and ask here.


Alex

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

* Re: [Qemu-devel] Re: [PATCH V6 17/32] pci: 64bit bar support.
  2009-11-04  6:20                 ` Isaku Yamahata
@ 2009-11-04 12:19                   ` Michael S. Tsirkin
  0 siblings, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-04 12:19 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: Avi Kivity, qemu-devel

On Wed, Nov 04, 2009 at 03:20:02PM +0900, Isaku Yamahata wrote:
> On Tue, Nov 03, 2009 at 04:09:16PM +0200, Michael S. Tsirkin wrote:
> > > > Long term, we should fix all devices and *then* they can claim 64 bit
> > > > support always.  As a nice side effect, we'll be able to avoid
> > > > rebuilding devices.
> > > 
> > > Are you claiming that (PCI) devices emulation shouldn't depend on
> > > target_phys_addr_t? That sounds a good idea.
> > 
> > Yes. Maybe we can stop devices from mapping memory, have pci
> > core do it for them.
> 
> IIRC Avi proposed such a patch,

link?

> but it didn't get merged.

I wonder why - currently mapping is done by devices but unmapping is
done by pci core. That's been always bothering me.


> -- 
> yamahata

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

* [Qemu-devel] Re: [PATCH V6 13/32] pci_host: consolidate pci config address access.
  2009-11-04  6:14     ` Isaku Yamahata
  2009-11-04 11:50       ` Alexander Graf
@ 2009-11-04 15:17       ` Aurelien Jarno
  2009-11-04 15:37         ` Michael S. Tsirkin
  1 sibling, 1 reply; 75+ messages in thread
From: Aurelien Jarno @ 2009-11-04 15:17 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: alex, yu.liu, qemu-devel, Michael S. Tsirkin

On Wed, Nov 04, 2009 at 03:14:26PM +0900, Isaku Yamahata wrote:
> On Tue, Nov 03, 2009 at 03:45:12PM +0200, Michael S. Tsirkin wrote:
> > > --- a/hw/pci_host.c
> > > +++ b/hw/pci_host.c
> > > @@ -32,6 +32,114 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
> > >  #define PCI_DPRINTF(fmt, ...)
> > >  #endif
> > >  
> > > +static void pci_host_config_writel(void *opaque, target_phys_addr_t addr,
> > > +                                   uint32_t val)
> > > +{
> > > +    PCIHostState *s = opaque;
> > > +
> > > +#ifdef TARGET_WORDS_BIGENDIAN
> > > +    val = bswap32(val);
> > > +#endif
> > 
> > I know you just copied it, but isn't this just
> > 	val = le32_to_cpu(val);
> > 
> > ?
> 
> Makes sense.
 
The original code is actually wrong, but le32_to_cpu(val), will break on
big endian hosts.

The fact is that QEMU doesn't emulate byteswap on buses. Hopefully on all
big endian machines we emulate, the PCI bus is always connected backward,
so we can simply do the byteswap depending on TARGET_WORDS_BIGENDIAN.

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* [Qemu-devel] Re: [PATCH V6 13/32] pci_host: consolidate pci config address access.
  2009-11-04 15:17       ` Aurelien Jarno
@ 2009-11-04 15:37         ` Michael S. Tsirkin
  2009-11-04 17:34           ` Aurelien Jarno
  0 siblings, 1 reply; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-04 15:37 UTC (permalink / raw)
  To: Aurelien Jarno; +Cc: Isaku Yamahata, yu.liu, qemu-devel, alex

On Wed, Nov 04, 2009 at 04:17:46PM +0100, Aurelien Jarno wrote:
> On Wed, Nov 04, 2009 at 03:14:26PM +0900, Isaku Yamahata wrote:
> > On Tue, Nov 03, 2009 at 03:45:12PM +0200, Michael S. Tsirkin wrote:
> > > > --- a/hw/pci_host.c
> > > > +++ b/hw/pci_host.c
> > > > @@ -32,6 +32,114 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
> > > >  #define PCI_DPRINTF(fmt, ...)
> > > >  #endif
> > > >  
> > > > +static void pci_host_config_writel(void *opaque, target_phys_addr_t addr,
> > > > +                                   uint32_t val)
> > > > +{
> > > > +    PCIHostState *s = opaque;
> > > > +
> > > > +#ifdef TARGET_WORDS_BIGENDIAN
> > > > +    val = bswap32(val);
> > > > +#endif
> > > 
> > > I know you just copied it, but isn't this just
> > > 	val = le32_to_cpu(val);
> > > 
> > > ?
> > 
> > Makes sense.
>  
> The original code is actually wrong, but le32_to_cpu(val), will break on
> big endian hosts.
> 
> The fact is that QEMU doesn't emulate byteswap on buses. Hopefully on all
> big endian machines we emulate, the PCI bus is always connected backward,
> so we can simply do the byteswap depending on TARGET_WORDS_BIGENDIAN.
> 
> -- 
> Aurelien Jarno	                        GPG: 1024D/F1BCDB73
> aurelien@aurel32.net                 http://www.aurel32.net

Are you speaking about bit endian hosts with little endian guests?
Ugh ... my head hurts. bswap32 is evil because there's no way to
figure out what is converted to what. big to little? guest to host?


-- 
MST

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

* [Qemu-devel] Re: [PATCH V6 13/32] pci_host: consolidate pci config address access.
  2009-11-04 15:37         ` Michael S. Tsirkin
@ 2009-11-04 17:34           ` Aurelien Jarno
  0 siblings, 0 replies; 75+ messages in thread
From: Aurelien Jarno @ 2009-11-04 17:34 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Isaku Yamahata, yu.liu, qemu-devel, alex

On Wed, Nov 04, 2009 at 05:37:13PM +0200, Michael S. Tsirkin wrote:
> On Wed, Nov 04, 2009 at 04:17:46PM +0100, Aurelien Jarno wrote:
> > On Wed, Nov 04, 2009 at 03:14:26PM +0900, Isaku Yamahata wrote:
> > > On Tue, Nov 03, 2009 at 03:45:12PM +0200, Michael S. Tsirkin wrote:
> > > > > --- a/hw/pci_host.c
> > > > > +++ b/hw/pci_host.c
> > > > > @@ -32,6 +32,114 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
> > > > >  #define PCI_DPRINTF(fmt, ...)
> > > > >  #endif
> > > > >  
> > > > > +static void pci_host_config_writel(void *opaque, target_phys_addr_t addr,
> > > > > +                                   uint32_t val)
> > > > > +{
> > > > > +    PCIHostState *s = opaque;
> > > > > +
> > > > > +#ifdef TARGET_WORDS_BIGENDIAN
> > > > > +    val = bswap32(val);
> > > > > +#endif
> > > > 
> > > > I know you just copied it, but isn't this just
> > > > 	val = le32_to_cpu(val);
> > > > 
> > > > ?
> > > 
> > > Makes sense.
> >  
> > The original code is actually wrong, but le32_to_cpu(val), will break on
> > big endian hosts.
> > 
> > The fact is that QEMU doesn't emulate byteswap on buses. Hopefully on all
> > big endian machines we emulate, the PCI bus is always connected backward,
> > so we can simply do the byteswap depending on TARGET_WORDS_BIGENDIAN.
> > 
> > -- 
> > Aurelien Jarno	                        GPG: 1024D/F1BCDB73
> > aurelien@aurel32.net                 http://www.aurel32.net
> 
> Are you speaking about bit endian hosts with little endian guests?
> Ugh ... my head hurts. bswap32 is evil because there's no way to
> figure out what is converted to what. big to little? guest to host?
> 

This is not related to the host and guest endianess, but just of the
way the PCI bus is connected to the CPU on all the big endian guest we 
emulate.

On theses machine, a byteswap is needed when transferring a word between
the PCI bus and the CPU.

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* [Qemu-devel] Re: [PATCH V6 08/32] pci: clean up pci_init_wmask()
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 08/32] pci: clean up pci_init_wmask() Isaku Yamahata
  2009-11-03 13:22   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-11-10 15:26   ` Michael S. Tsirkin
  1 sibling, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-10 15:26 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:02PM +0900, Isaku Yamahata wrote:
> use pci_set_word() for pci command register.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Acked-by: Michael S. Tsirkin <mst@redhat.com>

I thought I acked this already. It's an obvious one.

> ---
>  hw/pci.c |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 6abb0e2..84c7611 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -352,8 +352,8 @@ static void pci_init_wmask(PCIDevice *dev)
>      int i;
>      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;
> +    pci_set_word(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)
>          dev->wmask[i] = 0xff;
>  }
> -- 
> 1.6.0.2
> 
> 

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

* [Qemu-devel] Re: [PATCH V6 18/32] pci: remove bus_num member from struct PCIBus.
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 18/32] pci: remove bus_num member from struct PCIBus Isaku Yamahata
  2009-11-03 13:47   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-11-10 15:33   ` Michael S. Tsirkin
  2009-11-10 15:46     ` Michael S. Tsirkin
  1 sibling, 1 reply; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-10 15:33 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:12PM +0900, Isaku Yamahata wrote:
> Since It can be retrieved from pci configuration space,
> the member is unnecessary.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Acked-by: Michael S. Tsirkin <mst@redhat.com>

> ---
>  hw/pci.c |   21 ++++++++++-----------
>  1 files changed, 10 insertions(+), 11 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 7da3db9..a75d981 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -36,7 +36,6 @@
>  
>  struct PCIBus {
>      BusState qbus;
> -    int bus_num;
>      int devfn_min;
>      pci_set_irq_fn set_irq;
>      pci_map_irq_fn map_irq;
> @@ -192,7 +191,9 @@ static void pci_register_secondary_bus(PCIBus *bus,
>  
>  int pci_bus_num(PCIBus *s)
>  {
> -    return s->bus_num;
> +    if (!s->parent_dev)
> +        return 0;       /* pci host bridge */
> +    return s->parent_dev->config[PCI_SECONDARY_BUS];
>  }
>  
>  static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
> @@ -624,7 +625,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)
> +    while (s && pci_bus_num(s) != bus_num)
>          s = s->next;
>      if (!s)
>          return;
> @@ -645,7 +646,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)
> +    while (s && pci_bus_num(s) != bus_num)
>          s= s->next;
>      if (!s)
>          goto fail;
> @@ -760,7 +761,8 @@ 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, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
> +                   pci_bus_num(d->bus),
> +                   PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
>      class = pci_get_word(d->config + PCI_CLASS_DEVICE);
>      monitor_printf(mon, "    ");
>      desc = pci_class_descriptions;
> @@ -816,7 +818,7 @@ void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
>      PCIDevice *d;
>      int devfn;
>  
> -    while (bus && bus->bus_num != bus_num)
> +    while (bus && pci_bus_num(bus) != bus_num)
>          bus = bus->next;
>      if (bus) {
>          for(devfn = 0; devfn < 256; devfn++) {
> @@ -913,17 +915,14 @@ typedef struct {
>  static void pci_bridge_write_config(PCIDevice *d,
>                               uint32_t address, uint32_t val, int len)
>  {
> -    PCIBridge *s = (PCIBridge *)d;
> -
>      pci_default_write_config(d, address, val, len);
> -    s->bus.bus_num = d->config[PCI_SECONDARY_BUS];
>  }
>  
>  PCIBus *pci_find_bus(int bus_num)
>  {
>      PCIBus *bus = first_bus;
>  
> -    while (bus && bus->bus_num != bus_num)
> +    while (bus && pci_bus_num(bus) != bus_num)
>          bus = bus->next;
>  
>      return bus;
> @@ -1149,7 +1148,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, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
> +                   pci_bus_num(d->bus), PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
>                     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),
> -- 
> 1.6.0.2
> 
> 

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

* [Qemu-devel] Re: [PATCH V6 18/32] pci: remove bus_num member from struct PCIBus.
  2009-11-10 15:33   ` Michael S. Tsirkin
@ 2009-11-10 15:46     ` Michael S. Tsirkin
  2009-11-12  3:12       ` Isaku Yamahata
  0 siblings, 1 reply; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-10 15:46 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Tue, Nov 10, 2009 at 05:33:22PM +0200, Michael S. Tsirkin wrote:
> On Fri, Oct 30, 2009 at 09:21:12PM +0900, Isaku Yamahata wrote:
> > Since It can be retrieved from pci configuration space,
> > the member is unnecessary.
> > 
> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> 
> Acked-by: Michael S. Tsirkin <mst@redhat.com>

Sorry, wait a second please:

> > ---
> >  hw/pci.c |   21 ++++++++++-----------
> >  1 files changed, 10 insertions(+), 11 deletions(-)
> > 
> > diff --git a/hw/pci.c b/hw/pci.c
> > index 7da3db9..a75d981 100644
> > --- a/hw/pci.c
> > +++ b/hw/pci.c
> > @@ -36,7 +36,6 @@
> >  
> >  struct PCIBus {
> >      BusState qbus;
> > -    int bus_num;
> >      int devfn_min;
> >      pci_set_irq_fn set_irq;
> >      pci_map_irq_fn map_irq;
> > @@ -192,7 +191,9 @@ static void pci_register_secondary_bus(PCIBus *bus,
> >  
> >  int pci_bus_num(PCIBus *s)
> >  {
> > -    return s->bus_num;
> > +    if (!s->parent_dev)
> > +        return 0;       /* pci host bridge */
> > +    return s->parent_dev->config[PCI_SECONDARY_BUS];

Why are you using the value from the *parent*?
Because originally ...

> >  }
> >  
> >  static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
> > @@ -624,7 +625,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)
> > +    while (s && pci_bus_num(s) != bus_num)
> >          s = s->next;
> >      if (!s)
> >          return;
> > @@ -645,7 +646,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)
> > +    while (s && pci_bus_num(s) != bus_num)
> >          s= s->next;
> >      if (!s)
> >          goto fail;
> > @@ -760,7 +761,8 @@ 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, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
> > +                   pci_bus_num(d->bus),
> > +                   PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
> >      class = pci_get_word(d->config + PCI_CLASS_DEVICE);
> >      monitor_printf(mon, "    ");
> >      desc = pci_class_descriptions;
> > @@ -816,7 +818,7 @@ void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
> >      PCIDevice *d;
> >      int devfn;
> >  
> > -    while (bus && bus->bus_num != bus_num)
> > +    while (bus && pci_bus_num(bus) != bus_num)
> >          bus = bus->next;
> >      if (bus) {
> >          for(devfn = 0; devfn < 256; devfn++) {
> > @@ -913,17 +915,14 @@ typedef struct {
> >  static void pci_bridge_write_config(PCIDevice *d,
> >                               uint32_t address, uint32_t val, int len)
> >  {
> > -    PCIBridge *s = (PCIBridge *)d;
> > -
> >      pci_default_write_config(d, address, val, len);
> > -    s->bus.bus_num = d->config[PCI_SECONDARY_BUS];

... bus number used to equal PCI_SECONDARY_BUS for the *same* device.

> >  }
> >  
> >  PCIBus *pci_find_bus(int bus_num)
> >  {
> >      PCIBus *bus = first_bus;
> >  
> > -    while (bus && bus->bus_num != bus_num)
> > +    while (bus && pci_bus_num(bus) != bus_num)
> >          bus = bus->next;
> >  
> >      return bus;
> > @@ -1149,7 +1148,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, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
> > +                   pci_bus_num(d->bus), PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
> >                     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),
> > -- 
> > 1.6.0.2
> > 
> > 

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

* [Qemu-devel] Re: [PATCH V6 19/32] pci: make pci configuration transaction more accurate.
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 19/32] pci: make pci configuration transaction more accurate Isaku Yamahata
@ 2009-11-10 15:49   ` Michael S. Tsirkin
  2009-11-12  3:27     ` Isaku Yamahata
  0 siblings, 1 reply; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-10 15:49 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:13PM +0900, Isaku Yamahata wrote:
> This patch sorts out/enhances pci code to track pci bus topology
> more accurately.
> - Track host bus bridge with pci domain number. Although the
>   current qemu implementation supports 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>

I agree with what you are doing here, overall. Some comments:

> ---
>  hw/pci-hotplug.c |    4 +-
>  hw/pci.c         |  132 +++++++++++++++++++++++++++++++++++++++++-------------
>  hw/pci.h         |    8 ++-
>  3 files changed, 108 insertions(+), 36 deletions(-)
> 
> diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
> index 15a2dfb..48a641b 100644
> --- a/hw/pci-hotplug.c
> +++ b/hw/pci-hotplug.c
> @@ -113,7 +113,7 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
>          if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
>              goto err;
>          }
> -        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);
>              goto err;
> @@ -257,7 +257,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;
> diff --git a/hw/pci.c b/hw/pci.c
> index a75d981..3e5780a 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -44,7 +44,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 +72,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",
> @@ -127,6 +136,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;
> +}
> +
>  void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
>                           const char *name, int devfn_min)
>  {
> @@ -134,8 +165,11 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
>  
>      qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name);
>      bus->devfn_min = devfn_min;
> -    bus->next = first_bus;
> -    first_bus = bus;
> +
> +    /* host bridge */
> +    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);
>  }
> @@ -177,7 +211,8 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
>      return bus;
>  }
>  
> -static void pci_register_secondary_bus(PCIBus *bus,
> +static void pci_register_secondary_bus(PCIBus *parent,
> +                                       PCIBus *bus,
>                                         PCIDevice *dev,
>                                         pci_map_irq_fn map_irq,
>                                         const char *name)
> @@ -185,8 +220,15 @@ static void pci_register_secondary_bus(PCIBus *bus,
>      qbus_create_inplace(&bus->qbus, &pci_bus_info, &dev->qdev, name);
>      bus->map_irq = map_irq;
>      bus->parent_dev = dev;
> -    bus->next = dev->bus->next;
> -    dev->bus->next = bus;
> +
> +    QLIST_INIT(&bus->child);
> +    QLIST_INSERT_HEAD(&parent->child, bus, sibling);
> +}
> +
> +static void pci_unregister_secondary_bus(PCIBus *bus)
> +{
> +    assert(QLIST_EMPTY(&bus->child));
> +    QLIST_REMOVE(bus, sibling);
>  }
>  
>  int pci_bus_num(PCIBus *s)
> @@ -196,6 +238,13 @@ int pci_bus_num(PCIBus *s)
>      return s->parent_dev->config[PCI_SECONDARY_BUS];
>  }
>  
> +static uint8_t pci_sub_bus(PCIBus *s)

This seems to be only used in one place,
and it's not obvious what this does.
Please open-code.

> +{
> +    if (!s->parent_dev)
> +        return 255;     /* pci host bridge */

Please use a symbolic constant.
Is this one UINT8_MAX or ARRAY_SIZE() or some array?

> +    return s->parent_dev->config[PCI_SUBORDINATE_BUS];
> +}
> +
>  static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
>  {
>      PCIDevice *s = container_of(pv, PCIDevice, config);
> @@ -301,7 +350,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 (!pci_find_bus(pci_find_host_bus(dom), bus))
>  	return -1;
>  
>      *domp = dom;
> @@ -331,7 +380,7 @@ 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) {
> @@ -339,7 +388,7 @@ 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)
> @@ -625,8 +674,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 && pci_bus_num(s) != bus_num)
> -        s = s->next;
> +    s = pci_find_bus(s, bus_num);
>      if (!s)
>          return;
>      pci_dev = s->devices[(addr >> 8) & 0xff];
> @@ -646,8 +694,7 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
>      uint32_t val;
>  
>      bus_num = (addr >> 16) & 0xff;
> -    while (s && pci_bus_num(s) != bus_num)
> -        s= s->next;
> +    s = pci_find_bus(s, bus_num);
>      if (!s)
>          goto fail;
>      pci_dev = s->devices[(addr >> 8) & 0xff];
> @@ -753,7 +800,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;
> @@ -808,30 +855,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 && pci_bus_num(bus) != 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);
> +    }
>  }
>  
>  static const char * const pci_nic_models[] = {
> @@ -918,19 +967,30 @@ static void pci_bridge_write_config(PCIDevice *d,
>      pci_default_write_config(d, address, val, len);
>  }
>  
> -PCIBus *pci_find_bus(int bus_num)
> +PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
>  {
> -    PCIBus *bus = first_bus;
> +    PCIBus *sec;
>  
> -    while (bus && pci_bus_num(bus) != bus_num)
> -        bus = bus->next;
> +    if (!bus)
> +        return NULL;
>  
> -    return bus;
> +    if (pci_bus_num(bus) == bus_num) {
> +        return bus;
> +    }
> +
> +    /* try child bus */
> +    QLIST_FOREACH(sec, &bus->child, sibling) {
> +        if (pci_bus_num(sec) <= bus_num && bus_num <= pci_sub_bus(sec)) {

I find this confusing.
Can we just look at each bridge and decide whether to propage
down from it, instead of lookup up at the parent bridge?

> +            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;
> @@ -973,6 +1033,14 @@ static int pci_bridge_initfn(PCIDevice *dev)
>      return 0;
>  }
>  
> +static int pci_bridge_exitfn(PCIDevice *pci_dev)
> +{
> +    PCIBridge *s = DO_UPCAST(PCIBridge, dev, pci_dev);
> +    PCIBus *bus = &s->bus;
> +    pci_unregister_secondary_bus(bus);
> +    return 0;
> +}
> +
>  PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
>                          pci_map_irq_fn map_irq, const char *name)
>  {
> @@ -985,7 +1053,7 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
>      qdev_init_nofail(&dev->qdev);
>  
>      s = DO_UPCAST(PCIBridge, dev, dev);
> -    pci_register_secondary_bus(&s->bus, &s->dev, map_irq, name);
> +    pci_register_secondary_bus(bus, &s->bus, &s->dev, map_irq, name);
>      return &s->bus;
>  }
>  
> @@ -1148,7 +1216,8 @@ 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,
> -                   pci_bus_num(d->bus), PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
> +                   d->config[PCI_SECONDARY_BUS],
> +                   PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
>                     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),
> @@ -1169,6 +1238,7 @@ static PCIDeviceInfo bridge_info = {
>      .qdev.name    = "pci-bridge",
>      .qdev.size    = sizeof(PCIBridge),
>      .init         = pci_bridge_initfn,
> +    .exit         = pci_bridge_exitfn,
>      .config_write = pci_bridge_write_config,
>      .qdev.props   = (Property[]) {
>          DEFINE_PROP_HEX32("vendorid", PCIBridge, vid, 0),
> diff --git a/hw/pci.h b/hw/pci.h
> index e83faf5..b16f8f8 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -118,6 +118,7 @@ typedef struct PCIIORegion {
>  #define  PCI_BASE_ADDRESS_MEM_PREFETCH	0x08	/* prefetchable? */
>  #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
>  #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
> +#define PCI_SUBORDINATE_BUS	0x1a	/* Highest bus number behind the bridge */
>  #define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
>  #define PCI_SUBSYSTEM_VENDOR_ID 0x2c    /* 16 bits */
>  #define PCI_SUBSYSTEM_ID        0x2e    /* 16 bits */
> @@ -267,9 +268,10 @@ PCIDevice *pci_nic_init_nofail(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);

pci_find_root_bus would be more descriptive IMO.

> +PCIBus *pci_find_bus(PCIBus *bus, int bus_num);
> +PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function);
>  PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
>  
>  int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
> -- 
> 1.6.0.2
> 
> 

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

* [Qemu-devel] Re: [PATCH V6 20/32] pci: factor out the conversion logic from io port address into pci device.
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 20/32] pci: factor out the conversion logic from io port address into pci device Isaku Yamahata
  2009-11-03 13:52   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-11-10 15:56   ` Michael S. Tsirkin
  1 sibling, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-10 15:56 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:14PM +0900, Isaku Yamahata wrote:
> factor out the logic which converts io port address into pci device
> and offset in PCI configuration space.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.c |   32 ++++++++++++++++++--------------
>  1 files changed, 18 insertions(+), 14 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 3e5780a..d0a96c6 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -663,24 +663,33 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
>          pci_update_mappings(d);
>  }
>  
> +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;

& 0xff is not necessary here, is it?

> +    return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
> +}
> +
> +static inline int pci_addr_to_config(uint32_t addr)
> +{
> +    return addr & (PCI_CONFIG_SPACE_SIZE - 1);
> +}
> +

This one is more clear opencoded, IMO.
It also seems that the fact that it is 0xff == PCI_CONFIG_SPACE_SIZE - 1 here is
just a coinsidence: it depends on pci host. Right?
Maybe 0xff is more appropriate here.

>  void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
>  {
>      PCIBus *s = opaque;
>      PCIDevice *pci_dev;
> -    int config_addr, bus_num;
> +    int config_addr;
>  
>  #if 0
>      PCI_DPRINTF("pci_data_write: addr=%08x val=%08x 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];
> +    pci_dev = pci_addr_to_dev(s, addr);
>      if (!pci_dev)
>          return;
>      config_addr = addr & 0xff;
> +    config_addr = pci_addr_to_config(addr);
>      PCI_DPRINTF("pci_config_write: %s: addr=%02x val=%08x len=%d\n",
>                  pci_dev->name, config_addr, val, len);
>      pci_dev->config_write(pci_dev, config_addr, val, len);
> @@ -690,16 +699,11 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
>  {
>      PCIBus *s = opaque;
>      PCIDevice *pci_dev;
> -    int config_addr, bus_num;
> +    int config_addr;
>      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];
> +    pci_dev = pci_addr_to_dev(s, addr);
>      if (!pci_dev) {
> -    fail:
>          switch(len) {
>          case 1:
>              val = 0xff;
> @@ -714,7 +718,7 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
>          }
>          goto the_end;
>      }
> -    config_addr = addr & 0xff;
> +    config_addr = pci_addr_to_config(addr);
>      val = pci_dev->config_read(pci_dev, config_addr, len);
>      PCI_DPRINTF("pci_config_read: %s: addr=%02x val=%08x len=%d\n",
>                  pci_dev->name, config_addr, val, len);
> -- 
> 1.6.0.2
> 
> 

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

* [Qemu-devel] Re: [PATCH V6 22/32] pci_host: change the signature of pci_data_{read, write}.
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 22/32] pci_host: change the signature of pci_data_{read, write} Isaku Yamahata
@ 2009-11-10 15:57   ` Michael S. Tsirkin
  0 siblings, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-10 15:57 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:16PM +0900, Isaku Yamahata wrote:
> change the first argument, void *opaque to PCIBus *s
> of the pci_data_{read, write}.
> They aren't used as direct callback so the argument type
> don't have to be void*. So change it to the right type.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> Acked-by: Michael S. Tsirkin <mst@redhat.com>

Maybe you can float this patch up so I can apply it to pci tree.

> ---
>  hw/pci.h      |    4 ++--
>  hw/pci_host.c |    6 ++----
>  2 files changed, 4 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/pci.h b/hw/pci.h
> index b16f8f8..4f4266d 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -265,8 +265,8 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
>                          const char *default_devaddr);
>  PCIDevice *pci_nic_init_nofail(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 pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len);
> +uint32_t pci_data_read(PCIBus *s, 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);
> diff --git a/hw/pci_host.c b/hw/pci_host.c
> index 351ade4..f4518dc 100644
> --- a/hw/pci_host.c
> +++ b/hw/pci_host.c
> @@ -52,9 +52,8 @@ static inline uint32_t pci_addr_to_config(uint32_t addr)
>      return addr & (PCI_CONFIG_SPACE_SIZE - 1);
>  }
>  
> -void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> +void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
>  {
> -    PCIBus *s = opaque;
>      PCIDevice *pci_dev = pci_addr_to_dev(s, addr);
>      uint32_t config_addr = pci_addr_to_config(addr);
>  
> @@ -66,9 +65,8 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
>      pci_dev->config_write(pci_dev, config_addr, val, len);
>  }
>  
> -uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> +uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
>  {
> -    PCIBus *s = opaque;
>      PCIDevice *pci_dev = pci_addr_to_dev(s, addr);
>      uint32_t config_addr = pci_addr_to_config(addr);
>      uint32_t val;
> -- 
> 1.6.0.2
> 
> 

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

* [Qemu-devel] Re: [PATCH V6 26/32] pci: use range helper functions.
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 26/32] pci: use range helper functions Isaku Yamahata
  2009-11-03 14:19   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-11-10 15:59   ` Michael S. Tsirkin
  1 sibling, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-10 15:59 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:20PM +0900, Isaku Yamahata wrote:
> clean up pci_default_write_config() by the range helper functions.
> 
> Suggested by Michael S. Tsirkin <mst@redhat.com>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Mabe you can float this patch up so I can put it on pci tree.

> ---
>  hw/pci.c |    8 ++------
>  1 files changed, 2 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 67133b6..d9fd564 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -699,19 +699,15 @@ 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 = pci_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)
> -        || ((orig[PCI_COMMAND] ^ d->config[PCI_COMMAND])
> -            & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)))
> +    if (ranges_overlap(addr, l, PCI_BASE_ADDRESS_0, 24) ||
> +        range_covers_byte(addr, l, PCI_COMMAND))
>          pci_update_mappings(d);
>  }
>  
> -- 
> 1.6.0.2
> 
> 

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

* [Qemu-devel] Re: [PATCH V6 27/32] pci: teach pci_default_config_write() ROM bar for normal/bridge device .
  2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 27/32] pci: teach pci_default_config_write() ROM bar for normal/bridge device Isaku Yamahata
  2009-11-03 14:20   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-11-10 16:01   ` Michael S. Tsirkin
  1 sibling, 0 replies; 75+ messages in thread
From: Michael S. Tsirkin @ 2009-11-10 16:01 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 30, 2009 at 09:21:21PM +0900, Isaku Yamahata wrote:
> 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()
> Also update pci mapping when PCI_ROM_ADDRESS1 is written for header type 1.
> 
> pci_update_mapping() path isn't performance critical,
> so call it even independent of header type.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

If possible please float this to start of series to I can
put on pci tree.

> ---
>  hw/pci.c |    2 ++
>  1 files changed, 2 insertions(+), 0 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index d9fd564..46b22ec 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -707,6 +707,8 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
>          d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
>      }
>      if (ranges_overlap(addr, l, PCI_BASE_ADDRESS_0, 24) ||
> +        ranges_overlap(addr, l, PCI_ROM_ADDRESS, 4) ||
> +        ranges_overlap(addr, l, PCI_ROM_ADDRESS1, 4) ||
>          range_covers_byte(addr, l, PCI_COMMAND))
>          pci_update_mappings(d);
>  }
> -- 
> 1.6.0.2
> 
> 

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

* [Qemu-devel] Re: [PATCH V6 18/32] pci: remove bus_num member from struct PCIBus.
  2009-11-10 15:46     ` Michael S. Tsirkin
@ 2009-11-12  3:12       ` Isaku Yamahata
  0 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-11-12  3:12 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Tue, Nov 10, 2009 at 05:46:40PM +0200, Michael S. Tsirkin wrote:
> On Tue, Nov 10, 2009 at 05:33:22PM +0200, Michael S. Tsirkin wrote:
> > On Fri, Oct 30, 2009 at 09:21:12PM +0900, Isaku Yamahata wrote:
> > > Since It can be retrieved from pci configuration space,
> > > the member is unnecessary.
> > > 
> > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > 
> > Acked-by: Michael S. Tsirkin <mst@redhat.com>
> 
> Sorry, wait a second please:
> 
> > > ---
> > >  hw/pci.c |   21 ++++++++++-----------
> > >  1 files changed, 10 insertions(+), 11 deletions(-)
> > > 
> > > diff --git a/hw/pci.c b/hw/pci.c
> > > index 7da3db9..a75d981 100644
> > > --- a/hw/pci.c
> > > +++ b/hw/pci.c
> > > @@ -36,7 +36,6 @@
> > >  
> > >  struct PCIBus {
> > >      BusState qbus;
> > > -    int bus_num;
> > >      int devfn_min;
> > >      pci_set_irq_fn set_irq;
> > >      pci_map_irq_fn map_irq;
> > > @@ -192,7 +191,9 @@ static void pci_register_secondary_bus(PCIBus *bus,
> > >  
> > >  int pci_bus_num(PCIBus *s)
> > >  {
> > > -    return s->bus_num;
> > > +    if (!s->parent_dev)
> > > +        return 0;       /* pci host bridge */
> > > +    return s->parent_dev->config[PCI_SECONDARY_BUS];
> 
> Why are you using the value from the *parent*?
> Because originally ...

You seem to be confuging PCIBus with PCIBridge.
"s" here is PCIBus. "s" in pci_brdige_write_config() is PCIBrdige.
And both PCIBridge and PCIDevice have bus member,
so it's more confusing.

              NULL
               ^
               | PCIBus::parent_dev
               |
            PCIBus (pci host bridge)
                includes
                devices[256]
               ^
               | PCIDevice::bus
               |
            PCIBridge
               includes PCIDevice
              | ^
PCIBridge::bus| | PCIBus::parent_dev
              v |
            PCIBus


thanks,

 > >  }
> > >  
> > >  static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
> > > @@ -624,7 +625,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)
> > > +    while (s && pci_bus_num(s) != bus_num)
> > >          s = s->next;
> > >      if (!s)
> > >          return;
> > > @@ -645,7 +646,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)
> > > +    while (s && pci_bus_num(s) != bus_num)
> > >          s= s->next;
> > >      if (!s)
> > >          goto fail;
> > > @@ -760,7 +761,8 @@ 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, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
> > > +                   pci_bus_num(d->bus),
> > > +                   PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
> > >      class = pci_get_word(d->config + PCI_CLASS_DEVICE);
> > >      monitor_printf(mon, "    ");
> > >      desc = pci_class_descriptions;
> > > @@ -816,7 +818,7 @@ void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
> > >      PCIDevice *d;
> > >      int devfn;
> > >  
> > > -    while (bus && bus->bus_num != bus_num)
> > > +    while (bus && pci_bus_num(bus) != bus_num)
> > >          bus = bus->next;
> > >      if (bus) {
> > >          for(devfn = 0; devfn < 256; devfn++) {
> > > @@ -913,17 +915,14 @@ typedef struct {
> > >  static void pci_bridge_write_config(PCIDevice *d,
> > >                               uint32_t address, uint32_t val, int len)
> > >  {
> > > -    PCIBridge *s = (PCIBridge *)d;
> > > -
> > >      pci_default_write_config(d, address, val, len);
> > > -    s->bus.bus_num = d->config[PCI_SECONDARY_BUS];
> 
> ... bus number used to equal PCI_SECONDARY_BUS for the *same* device.
> 
> > >  }
> > >  
> > >  PCIBus *pci_find_bus(int bus_num)
> > >  {
> > >      PCIBus *bus = first_bus;
> > >  
> > > -    while (bus && bus->bus_num != bus_num)
> > > +    while (bus && pci_bus_num(bus) != bus_num)
> > >          bus = bus->next;
> > >  
> > >      return bus;
> > > @@ -1149,7 +1148,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, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
> > > +                   pci_bus_num(d->bus), PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
> > >                     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),
> 

-- 
yamahata

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

* [Qemu-devel] Re: [PATCH V6 19/32] pci: make pci configuration transaction more accurate.
  2009-11-10 15:49   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-11-12  3:27     ` Isaku Yamahata
  0 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-11-12  3:27 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Tue, Nov 10, 2009 at 05:49:55PM +0200, Michael S. Tsirkin wrote:
> On Fri, Oct 30, 2009 at 09:21:13PM +0900, Isaku Yamahata wrote:
> > This patch sorts out/enhances pci code to track pci bus topology
> > more accurately.
> > - Track host bus bridge with pci domain number. Although the
> >   current qemu implementation supports 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>
> 
> I agree with what you are doing here, overall. Some comments:
> 
> > ---
> >  hw/pci-hotplug.c |    4 +-
> >  hw/pci.c         |  132 +++++++++++++++++++++++++++++++++++++++++-------------
> >  hw/pci.h         |    8 ++-
> >  3 files changed, 108 insertions(+), 36 deletions(-)
> > 
> > diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
> > index 15a2dfb..48a641b 100644
> > --- a/hw/pci-hotplug.c
> > +++ b/hw/pci-hotplug.c
> > @@ -113,7 +113,7 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
> >          if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
> >              goto err;
> >          }
> > -        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);
> >              goto err;
> > @@ -257,7 +257,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;
> > diff --git a/hw/pci.c b/hw/pci.c
> > index a75d981..3e5780a 100644
> > --- a/hw/pci.c
> > +++ b/hw/pci.c
> > @@ -44,7 +44,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 +72,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",
> > @@ -127,6 +136,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;
> > +}
> > +
> >  void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
> >                           const char *name, int devfn_min)
> >  {
> > @@ -134,8 +165,11 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
> >  
> >      qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name);
> >      bus->devfn_min = devfn_min;
> > -    bus->next = first_bus;
> > -    first_bus = bus;
> > +
> > +    /* host bridge */
> > +    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);
> >  }
> > @@ -177,7 +211,8 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
> >      return bus;
> >  }
> >  
> > -static void pci_register_secondary_bus(PCIBus *bus,
> > +static void pci_register_secondary_bus(PCIBus *parent,
> > +                                       PCIBus *bus,
> >                                         PCIDevice *dev,
> >                                         pci_map_irq_fn map_irq,
> >                                         const char *name)
> > @@ -185,8 +220,15 @@ static void pci_register_secondary_bus(PCIBus *bus,
> >      qbus_create_inplace(&bus->qbus, &pci_bus_info, &dev->qdev, name);
> >      bus->map_irq = map_irq;
> >      bus->parent_dev = dev;
> > -    bus->next = dev->bus->next;
> > -    dev->bus->next = bus;
> > +
> > +    QLIST_INIT(&bus->child);
> > +    QLIST_INSERT_HEAD(&parent->child, bus, sibling);
> > +}
> > +
> > +static void pci_unregister_secondary_bus(PCIBus *bus)
> > +{
> > +    assert(QLIST_EMPTY(&bus->child));
> > +    QLIST_REMOVE(bus, sibling);
> >  }
> >  
> >  int pci_bus_num(PCIBus *s)
> > @@ -196,6 +238,13 @@ int pci_bus_num(PCIBus *s)
> >      return s->parent_dev->config[PCI_SECONDARY_BUS];
> >  }
> >  
> > +static uint8_t pci_sub_bus(PCIBus *s)
> 
> This seems to be only used in one place,
> and it's not obvious what this does.
> Please open-code.

OK.

> > +{
> > +    if (!s->parent_dev)
> > +        return 255;     /* pci host bridge */
> 
> Please use a symbolic constant.
> Is this one UINT8_MAX or ARRAY_SIZE() or some array?
> 
> > +    return s->parent_dev->config[PCI_SUBORDINATE_BUS];
> > +}
> > +
> >  static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
> >  {
> >      PCIDevice *s = container_of(pv, PCIDevice, config);
> > @@ -301,7 +350,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 (!pci_find_bus(pci_find_host_bus(dom), bus))
> >  	return -1;
> >  
> >      *domp = dom;
> > @@ -331,7 +380,7 @@ 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) {
> > @@ -339,7 +388,7 @@ 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)
> > @@ -625,8 +674,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 && pci_bus_num(s) != bus_num)
> > -        s = s->next;
> > +    s = pci_find_bus(s, bus_num);
> >      if (!s)
> >          return;
> >      pci_dev = s->devices[(addr >> 8) & 0xff];
> > @@ -646,8 +694,7 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> >      uint32_t val;
> >  
> >      bus_num = (addr >> 16) & 0xff;
> > -    while (s && pci_bus_num(s) != bus_num)
> > -        s= s->next;
> > +    s = pci_find_bus(s, bus_num);
> >      if (!s)
> >          goto fail;
> >      pci_dev = s->devices[(addr >> 8) & 0xff];
> > @@ -753,7 +800,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;
> > @@ -808,30 +855,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 && pci_bus_num(bus) != 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);
> > +    }
> >  }
> >  
> >  static const char * const pci_nic_models[] = {
> > @@ -918,19 +967,30 @@ static void pci_bridge_write_config(PCIDevice *d,
> >      pci_default_write_config(d, address, val, len);
> >  }
> >  
> > -PCIBus *pci_find_bus(int bus_num)
> > +PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
> >  {
> > -    PCIBus *bus = first_bus;
> > +    PCIBus *sec;
> >  
> > -    while (bus && pci_bus_num(bus) != bus_num)
> > -        bus = bus->next;
> > +    if (!bus)
> > +        return NULL;
> >  
> > -    return bus;
> > +    if (pci_bus_num(bus) == bus_num) {
> > +        return bus;
> > +    }
> > +
> > +    /* try child bus */
> > +    QLIST_FOREACH(sec, &bus->child, sibling) {
> > +        if (pci_bus_num(sec) <= bus_num && bus_num <= pci_sub_bus(sec)) {
> 
> I find this confusing.
> Can we just look at each bridge and decide whether to propage
> down from it, instead of lookup up at the parent bridge?

Do you mean something like the blow?
	for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
		if (bus->devices[i] is PCIBridge)
			recursive lookup;
	}

Unfortunately there is no reliable way to determine
whether a given PCIDevice is PCIBridge.
So I had to resort to introduce PCIBus::child member.
One possible way is to check pci config header type,
but if the header type were wrongly set due to a bug,
it would be very nasty which is very difficult to track down.
So I avoided it.

> 
> > +            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;
> > @@ -973,6 +1033,14 @@ static int pci_bridge_initfn(PCIDevice *dev)
> >      return 0;
> >  }
> >  
> > +static int pci_bridge_exitfn(PCIDevice *pci_dev)
> > +{
> > +    PCIBridge *s = DO_UPCAST(PCIBridge, dev, pci_dev);
> > +    PCIBus *bus = &s->bus;
> > +    pci_unregister_secondary_bus(bus);
> > +    return 0;
> > +}
> > +
> >  PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
> >                          pci_map_irq_fn map_irq, const char *name)
> >  {
> > @@ -985,7 +1053,7 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
> >      qdev_init_nofail(&dev->qdev);
> >  
> >      s = DO_UPCAST(PCIBridge, dev, dev);
> > -    pci_register_secondary_bus(&s->bus, &s->dev, map_irq, name);
> > +    pci_register_secondary_bus(bus, &s->bus, &s->dev, map_irq, name);
> >      return &s->bus;
> >  }
> >  
> > @@ -1148,7 +1216,8 @@ 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,
> > -                   pci_bus_num(d->bus), PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
> > +                   d->config[PCI_SECONDARY_BUS],
> > +                   PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
> >                     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),
> > @@ -1169,6 +1238,7 @@ static PCIDeviceInfo bridge_info = {
> >      .qdev.name    = "pci-bridge",
> >      .qdev.size    = sizeof(PCIBridge),
> >      .init         = pci_bridge_initfn,
> > +    .exit         = pci_bridge_exitfn,
> >      .config_write = pci_bridge_write_config,
> >      .qdev.props   = (Property[]) {
> >          DEFINE_PROP_HEX32("vendorid", PCIBridge, vid, 0),
> > diff --git a/hw/pci.h b/hw/pci.h
> > index e83faf5..b16f8f8 100644
> > --- a/hw/pci.h
> > +++ b/hw/pci.h
> > @@ -118,6 +118,7 @@ typedef struct PCIIORegion {
> >  #define  PCI_BASE_ADDRESS_MEM_PREFETCH	0x08	/* prefetchable? */
> >  #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
> >  #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
> > +#define PCI_SUBORDINATE_BUS	0x1a	/* Highest bus number behind the bridge */
> >  #define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
> >  #define PCI_SUBSYSTEM_VENDOR_ID 0x2c    /* 16 bits */
> >  #define PCI_SUBSYSTEM_ID        0x2e    /* 16 bits */
> > @@ -267,9 +268,10 @@ PCIDevice *pci_nic_init_nofail(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);
> 
> pci_find_root_bus would be more descriptive IMO.
> 
> > +PCIBus *pci_find_bus(PCIBus *bus, int bus_num);
> > +PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function);
> >  PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
> >  
> >  int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
> 

-- 
yamahata

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

* [Qemu-devel] Re: [PATCH V6 28/32] pci: initialize pci config headers depending it pci header type.
  2009-11-03 14:27   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-11-12  5:23     ` Isaku Yamahata
  0 siblings, 0 replies; 75+ messages in thread
From: Isaku Yamahata @ 2009-11-12  5:23 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Tue, Nov 03, 2009 at 04:27:18PM +0200, Michael S. Tsirkin wrote:
> On Fri, Oct 30, 2009 at 09:21:22PM +0900, Isaku Yamahata wrote:
> > - Only sets default subsystem id for header type 00.(normal header type)
> >   because header type 01 doesn't have subsystem id, and uses the register
> >   for other purpose. So setting default subsystem id doesn't make sense.
> > 
> > - initialize wmask more for header type 01.(bridge header type)
> >   Without those wmasks, linux was confused not boot,
> >   and lspci was confused not to print out expected IO/memory range.
> > 
> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > ---
> >  hw/cirrus_vga.c |    1 -
> >  hw/pci.c        |   42 ++++++++++++++++++++++++++++++++++++++----
> >  hw/pci.h        |   29 +++++++++++++++++++++++++++++
> >  3 files changed, 67 insertions(+), 5 deletions(-)
> > 
> > diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
> > index ef72c62..c1bafd3 100644
> > --- a/hw/cirrus_vga.c
> > +++ b/hw/cirrus_vga.c
> > @@ -180,7 +180,6 @@
> >  #define PCI_COMMAND_PALETTESNOOPING         0x0020
> >  #define PCI_COMMAND_PARITYDETECTION         0x0040
> >  #define PCI_COMMAND_ADDRESSDATASTEPPING     0x0080
> > -#define PCI_COMMAND_SERR                    0x0100
> >  #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 46b22ec..beefae3 100644
> > --- a/hw/pci.c
> > +++ b/hw/pci.c
> > @@ -445,6 +445,30 @@ static void pci_init_wmask(PCIDevice *dev)
> >          dev->wmask[i] = 0xff;
> >  }
> >  
> > +static void pci_init_wmask_bridge(PCIDevice *d)
> > +{
> > +    /* PCI_PRIMARY_BUS, PCI_SECONDARY_BUS, PCI_SUBORDINATE_BUS and
> > +       PCI_SEC_LETENCY_TIMER */
> > +    memset(d->wmask + PCI_PRIMARY_BUS, 0xff, 4);
> > +
> > +    /* base and limit */
> > +    d->wmask[PCI_IO_BASE] = PCI_IO_RANGE_MASK & 0xff;
> > +    d->wmask[PCI_IO_LIMIT] = PCI_IO_RANGE_MASK & 0xff;
> > +    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_PREF_BASE_UPPER32 and PCI_PREF_LIMIT_UPPER32 */
> > +    memset(d->wmask + PCI_PREF_BASE_UPPER32, 0xff, 8);
> > +
> > +    pci_set_word(d->wmask + PCI_BRIDGE_CONTROL, 0xffff);
> > +}
> > +
> >  static void pci_config_alloc(PCIDevice *pci_dev)
> >  {
> >      int config_size = pci_config_size(pci_dev);
> > @@ -467,7 +491,8 @@ static void pci_config_free(PCIDevice *pci_dev)
> >  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,
> > +                                         uint8_t header_type)
> >  {
> >      if (devfn < 0) {
> >          for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) {
> > @@ -484,9 +509,16 @@ 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);
> > +
> > +    header_type &= ~PCI_HEADER_TYPE_MULTI_FUNCTION;
> > +    if (header_type == PCI_HEADER_TYPE_NORMAL) {
> > +        pci_set_default_subsystem_id(pci_dev);
> > +    }
> >      pci_init_cmask(pci_dev);
> >      pci_init_wmask(pci_dev);
> > +    if (header_type == PCI_HEADER_TYPE_BRIDGE) {
> > +        pci_init_wmask_bridge(pci_dev);
> > +    }
> >  
> >      if (!config_read)
> >          config_read = pci_default_read_config;
> 
> Instead of this, can we have pci_init_bridge that will simply
> be called after device has been initialized?
> Down the road we will be able to move it to pci_bridge.c

Makes sense.
I will address it when I implement pci hot plug which requires
pcie port emulator.


> 
> 
> > @@ -509,7 +541,8 @@ 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_HEADER_TYPE_NORMAL);
> >      return pci_dev;
> >  }
> >  static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
> > @@ -1059,7 +1092,8 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
> >      bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
> >      devfn = pci_dev->devfn;
> >      pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn,
> > -                                     info->config_read, info->config_write);
> > +                                     info->config_read, info->config_write,
> > +                                     info->header_type);
> >      assert(pci_dev);
> >      rc = info->init(pci_dev);
> >      if (rc != 0)
> > diff --git a/hw/pci.h b/hw/pci.h
> > index 7991bfd..3f50294 100644
> > --- a/hw/pci.h
> > +++ b/hw/pci.h
> > @@ -100,6 +100,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 */
> > @@ -119,16 +127,30 @@ typedef struct PCIIORegion {
> >  #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
> >  #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
> >  #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_MASK      (~0x0fUL)
> >  #define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
> > +#define PCI_MEMORY_BASE         0x20    /* Memory range behind */
> > +#define PCI_MEMORY_LIMIT        0x22
> > +#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_MASK    (~0x0fUL)
> > +#define PCI_PREF_BASE_UPPER32   0x28    /* Upper half of prefetchable memory range */
> >  #define PCI_SUBSYSTEM_VENDOR_ID 0x2c    /* 16 bits */
> >  #define PCI_SUBSYSTEM_ID        0x2e    /* 16 bits */
> >  #define PCI_ROM_ADDRESS		0x30	/* Bits 31..11 are address, 10..1 reserved */
> >  #define  PCI_ROM_ADDRESS_ENABLE	0x01
> > +#define PCI_IO_BASE_UPPER16     0x30    /* Upper half of I/O addresses */
> > +#define PCI_IO_LIMIT_UPPER16    0x32
> >  #define PCI_CAPABILITY_LIST	0x34	/* Offset of first capability list entry */
> >  #define PCI_ROM_ADDRESS1	0x38	/* Same as PCI_ROM_ADDRESS, but for htype 1 */
> >  #define PCI_INTERRUPT_LINE	0x3c	/* 8 bits */
> >  #define PCI_INTERRUPT_PIN	0x3d	/* 8 bits */
> >  #define PCI_MIN_GNT		0x3e	/* 8 bits */
> > +#define PCI_BRIDGE_CONTROL      0x3e
> >  #define PCI_MAX_LAT		0x3f	/* 8 bits */
> >  
> >  /* Capability lists */
> 
> 
> Many of these are unused. I'd rather we only defined what we use.
> 
> > @@ -358,6 +380,13 @@ typedef struct {
> >      PCIConfigReadFunc *config_read;
> >      PCIConfigWriteFunc *config_write;
> >  
> > +    /* pci config header type */
> > +    uint8_t header_type;        /* this is necessary for initialization
> > +                                 * code to know its header type before
> > +                                 * device specific code can initialize
> > +                                 * configuration space.
> > +                                 */
> 
> 
> The text probably belongs in commit comment.
> Comments that tell how field is used quickly get out of date.
> Say *what* it is is enough.
> 
> > +
> >      /* pcie stuff */
> >      int is_express;   /* is this device pci express?
> >                         * initialization code needs to know this before
> 

-- 
yamahata

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

end of thread, other threads:[~2009-11-12  5:23 UTC | newest]

Thread overview: 75+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-10-30 12:20 [Qemu-devel] [PATCH V6 00/32] pci: various pci clean up and pci express support Isaku Yamahata
2009-10-30 12:20 ` [Qemu-devel] [PATCH V6 01/32] pci: fix PCI_DPRINTF() wrt variadic macro Isaku Yamahata
2009-10-30 12:20 ` [Qemu-devel] [PATCH V6 02/32] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4 Isaku Yamahata
2009-10-30 12:20 ` [Qemu-devel] [PATCH V6 03/32] pci: use PCI_SLOT() and PCI_FUNC() Isaku Yamahata
2009-10-30 12:20 ` [Qemu-devel] [PATCH V6 04/32] pci: define a constant to represent a unmapped bar and use it Isaku Yamahata
2009-10-30 12:20 ` [Qemu-devel] [PATCH V6 05/32] pci: helper functions to access PCIDevice::config Isaku Yamahata
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 06/32] pci: use helper functions to access pci config space Isaku Yamahata
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 07/32] pci/bridge: clean up of pci_bridge_initfn() Isaku Yamahata
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 08/32] pci: clean up pci_init_wmask() Isaku Yamahata
2009-11-03 13:22   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-10 15:26   ` Michael S. Tsirkin
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 09/32] pci: s/PCI_ADDRESS_SPACE_/PCI_BASE_ADDRESS_SPACE_/ to match pci_regs.h Isaku Yamahata
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 10/32] pci: clean up of pci_default_read_config Isaku Yamahata
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 11/32] pci: make pci_bar() aware of header type 1 Isaku Yamahata
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 12/32] pci_host.h: move functions in pci_host.h into .c file Isaku Yamahata
2009-11-03 13:31   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-03 13:35     ` Michael S. Tsirkin
2009-11-04  4:09       ` Isaku Yamahata
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 13/32] pci_host: consolidate pci config address access Isaku Yamahata
2009-11-03 13:45   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-04  6:14     ` Isaku Yamahata
2009-11-04 11:50       ` Alexander Graf
2009-11-04 15:17       ` Aurelien Jarno
2009-11-04 15:37         ` Michael S. Tsirkin
2009-11-04 17:34           ` Aurelien Jarno
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 14/32] pci: introduce pcibus_t to represent pci bus address/size instead of uint32_t Isaku Yamahata
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 15/32] pci: introduce FMT_PCIBUS for printf format for pcibus_t Isaku Yamahata
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 16/32] pci: typedef pcibus_t as uint64_t instead of uint32_t Isaku Yamahata
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 17/32] pci: 64bit bar support Isaku Yamahata
2009-11-01 16:07   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-03  3:52     ` Isaku Yamahata
2009-11-03 11:47       ` Michael S. Tsirkin
2009-11-03 12:22         ` Avi Kivity
2009-11-03 12:39           ` Michael S. Tsirkin
2009-11-03 13:21             ` Michael S. Tsirkin
2009-11-03 14:01             ` Isaku Yamahata
2009-11-03 14:09               ` Michael S. Tsirkin
2009-11-04  6:20                 ` Isaku Yamahata
2009-11-04 12:19                   ` Michael S. Tsirkin
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 18/32] pci: remove bus_num member from struct PCIBus Isaku Yamahata
2009-11-03 13:47   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-10 15:33   ` Michael S. Tsirkin
2009-11-10 15:46     ` Michael S. Tsirkin
2009-11-12  3:12       ` Isaku Yamahata
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 19/32] pci: make pci configuration transaction more accurate Isaku Yamahata
2009-11-10 15:49   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12  3:27     ` Isaku Yamahata
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 20/32] pci: factor out the conversion logic from io port address into pci device Isaku Yamahata
2009-11-03 13:52   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-10 15:56   ` Michael S. Tsirkin
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 21/32] pci: move pci host stuff from pci.c to pci_host.c Isaku Yamahata
2009-11-03 14:04   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 22/32] pci_host: change the signature of pci_data_{read, write} Isaku Yamahata
2009-11-10 15:57   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 23/32] vmstate: introduce VMSTATE_BUFFER_UNSAFE_INFO Isaku Yamahata
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 24/32] pci: pcie host and mmcfg support Isaku Yamahata
2009-11-03 14:50   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 25/32] pci: add helper functions to check ranges overlap Isaku Yamahata
2009-11-03 14:18   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 26/32] pci: use range helper functions Isaku Yamahata
2009-11-03 14:19   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-10 15:59   ` Michael S. Tsirkin
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 27/32] pci: teach pci_default_config_write() ROM bar for normal/bridge device Isaku Yamahata
2009-11-03 14:20   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-10 16:01   ` Michael S. Tsirkin
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 28/32] pci: initialize pci config headers depending it pci header type Isaku Yamahata
2009-11-03 14:27   ` [Qemu-devel] " Michael S. Tsirkin
2009-11-12  5:23     ` Isaku Yamahata
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 29/32] pci: cosmetic on pci_upadte_mappings() Isaku Yamahata
2009-11-03 14:17   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 30/32] pci: factor out pci_for_each_device() Isaku Yamahata
2009-11-03 14:29   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 31/32] pci: implement pci bridge filtering Isaku Yamahata
2009-11-03 15:01   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-30 12:21 ` [Qemu-devel] [PATCH V6 32/32] pci/monitor: print out bridge's filtering values and so on 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.