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

Again thanks to Michael's review, patches have been much cleaned up.
And I suppose sparc64 issue is also fixed.
The qemu repository has many commits and I rebased to it.


- pci: add helper functions for pci config write function.
I'd like to sent out patches as soon as possible after big commit,
so I didn't have time to fully addressed the following patch fully. 
This patch would need more spin.

- pci_host.h: move functions in pci_host.h into .c file.
This uses some macro trick. Or should I duplicate function
instead of tricky macro?


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

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

thanks,

changes from 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 (29):
  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: 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: make pci configuration transaction more accurate.
  pci: factor out the conversion logic from io port address into pci
    device.
  pci: split out ioport address parsing from pci configuration access
    logic.
  pci: move pci host stuff from pci.c to pci_host.c
  pci_host: change the signature of pci_data_{read, write}.
  vmstate: add VMSTATE_ARRAY_POINTER for pointer to array.
  pci: pcie host and mmcfg support.
  pci: fix pci_default_write_config()
  pci: add helper functions for pci config write function.
  pci: use helper function in pci_default_write_config()
  pci/bridge: don't update bar mapping when bar2-5 is changed.
  pci: initialize pci config headers depending it pci header type.
  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                                |   22 ++
 hw/ide/pci.c                           |   16 +-
 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                               |  582 ++++++++++++++++++++++----------
 hw/pci.h                               |  169 +++++++++-
 hw/pci_host.c                          |  215 ++++++++++++
 hw/pci_host.h                          |   93 +-----
 hw/{pci_host.h => pci_host_template.h} |   36 +--
 hw/pcie_host.c                         |  166 +++++++++
 hw/pcie_host.h                         |   53 +++
 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 +-
 39 files changed, 1165 insertions(+), 743 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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 01/29] pci: fix PCI_DPRINTF() wrt variadic macro.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 02/29] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4 Isaku Yamahata
                   ` (27 subsequent siblings)
  28 siblings, 0 replies; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 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 49651d0..9fd2c38 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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 02/29] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 01/29] pci: fix PCI_DPRINTF() wrt variadic macro Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 03/29] pci: use PCI_SLOT() and PCI_FUNC() Isaku Yamahata
                   ` (26 subsequent siblings)
  28 siblings, 0 replies; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 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 9fd2c38..9b145ee 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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 03/29] pci: use PCI_SLOT() and PCI_FUNC().
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 01/29] pci: fix PCI_DPRINTF() wrt variadic macro Isaku Yamahata
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 02/29] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4 Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 04/29] pci: define a constant to represent a unmapped bar and use it Isaku Yamahata
                   ` (25 subsequent siblings)
  28 siblings, 0 replies; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 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 72f15af..920b647 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -252,11 +252,13 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
                                          0, 32);
     pci_create_simple(d->host_state.bus, 0, "pbm");
     /* APB secondary busses */
-    *bus2 = pci_bridge_init(d->host_state.bus, 8, PCI_VENDOR_ID_SUN,
-                            PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
+    *bus2 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 0),
+                            PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
+                            pci_apb_map_irq,
                             "Advanced PCI Bus secondary bridge 1");
-    *bus3 = pci_bridge_init(d->host_state.bus, 9, PCI_VENDOR_ID_SUN,
-                            PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
+    *bus3 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 1),
+                            PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
+                            pci_apb_map_irq,
                             "Advanced PCI Bus secondary bridge 2");
 
     return d->host_state.bus;
diff --git a/hw/pci.c b/hw/pci.c
index 9b145ee..5d1a68f 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;
@@ -1112,7 +1112,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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 04/29] pci: define a constant to represent a unmapped bar and use it.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (2 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 03/29] pci: use PCI_SLOT() and PCI_FUNC() Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 05/29] pci: helper functions to access PCIDevice::config Isaku Yamahata
                   ` (24 subsequent siblings)
  28 siblings, 0 replies; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 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 5d1a68f..a906a0a 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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 05/29] pci: helper functions to access PCIDevice::config
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (3 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 04/29] pci: define a constant to represent a unmapped bar and use it Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 06/29] pci: use helper functions to access pci config space Isaku Yamahata
                   ` (23 subsequent siblings)
  28 siblings, 0 replies; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 06/29] pci: use helper functions to access pci config space.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (4 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 05/29] pci: helper functions to access PCIDevice::config Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 07/29] pci/bridge: clean up of pci_bridge_initfn() Isaku Yamahata
                   ` (22 subsequent siblings)
  28 siblings, 0 replies; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 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 a906a0a..a66e3de 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",
@@ -1099,7 +1099,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++;
@@ -1113,10 +1113,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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 07/29] pci/bridge: clean up of pci_bridge_initfn()
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (5 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 06/29] pci: use helper functions to access pci config space Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-09  6:53   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-09  6:54   ` Michael S. Tsirkin
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 08/29] pci: s/PCI_ADDRESS_SPACE_/PCI_BASE_ADDRESS_SPACE_/ to match pci_regs.h Isaku Yamahata
                   ` (21 subsequent siblings)
  28 siblings, 2 replies; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

- use symbolic constant
- use helper function pci_set_xxx()

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

diff --git a/hw/pci.c b/hw/pci.c
index a66e3de..eaf471a 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -923,17 +923,18 @@ 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
+    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);
+    dev->config[PCI_REVISION_ID] = 0x00;
+    dev->config[PCI_CLASS_PROG] = 0x00;
+    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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 08/29] pci: s/PCI_ADDRESS_SPACE_/PCI_BASE_ADDRESS_SPACE_/ to match pci_regs.h
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (6 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 07/29] pci/bridge: clean up of pci_bridge_initfn() Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-09  6:57   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 09/29] pci: clean up of pci_default_read_config Isaku Yamahata
                   ` (20 subsequent siblings)
  28 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 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>
---
 hw/ac97.c         |    5 +++--
 hw/cirrus_vga.c   |    4 ++--
 hw/e1000.c        |    4 ++--
 hw/eepro100.c     |   18 ++++++++++--------
 hw/es1370.c       |    2 +-
 hw/ide/pci.c      |   12 ++++++------
 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 +-
 21 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 f123bda..ffa337b 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1106,10 +1106,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 445d46c..4691028 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -428,18 +428,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!!!) */
@@ -1818,11 +1820,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);
 
     qdev_get_macaddr(&s->dev.qdev, s->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/pci.c b/hw/ide/pci.c
index 9504e44..be5b1dc 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -414,15 +414,15 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
     }
 
     pci_register_bar((PCIDevice *)d, 0, 0x8,
-                     PCI_ADDRESS_SPACE_IO, ide_map);
+                     PCI_BASE_ADDRESS_SPACE_IO, ide_map);
     pci_register_bar((PCIDevice *)d, 1, 0x4,
-                     PCI_ADDRESS_SPACE_IO, ide_map);
+                     PCI_BASE_ADDRESS_SPACE_IO, ide_map);
     pci_register_bar((PCIDevice *)d, 2, 0x8,
-                     PCI_ADDRESS_SPACE_IO, ide_map);
+                     PCI_BASE_ADDRESS_SPACE_IO, ide_map);
     pci_register_bar((PCIDevice *)d, 3, 0x4,
-                     PCI_ADDRESS_SPACE_IO, ide_map);
+                     PCI_BASE_ADDRESS_SPACE_IO, ide_map);
     pci_register_bar((PCIDevice *)d, 4, 0x10,
-                     PCI_ADDRESS_SPACE_IO, bmdma_map);
+                     PCI_BASE_ADDRESS_SPACE_IO, bmdma_map);
 
     pci_conf[0x3d] = 0x01; // interrupt on pin 1
 
@@ -478,7 +478,7 @@ static int pci_piix_ide_initfn(PCIIDEState *d)
     piix3_reset(d);
 
     pci_register_bar((PCIDevice *)d, 4, 0x10,
-                     PCI_ADDRESS_SPACE_IO, bmdma_map);
+                     PCI_BASE_ADDRESS_SPACE_IO, bmdma_map);
 
     register_savevm("ide", 0, 3, pci_ide_save, pci_ide_load, d);
 
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index a4d3a57..2c5232c 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -2166,11 +2166,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 87f1e59..a9a4577 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -755,7 +755,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];
     qdev_get_macaddr(&d->dev.qdev, s->macaddr);
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 eaf471a..634899a 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 {
@@ -1123,7 +1123,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 afeaca7..1097445 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -2058,10 +2058,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 10daeb2..608085f 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3458,10 +3458,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);
 
     qdev_get_macaddr(&dev->qdev, s->macaddr);
     rtl8139_reset(&s->dev.qdev);
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 276b17b..314dea6 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -386,9 +386,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 a3ed9b2..e54fff0 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1095,7 +1095,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);
 
     register_savevm("uhci", 0, 1, uhci_save, uhci_load, s);
     return 0;
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index 5e75938..0a2982a 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -106,7 +106,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;
@@ -115,7 +115,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 e07a2a7..86766f4 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -413,7 +413,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;
@@ -424,7 +424,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 a273f35..eb1f2f5 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1230,9 +1230,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 3abaa87..32e4ef3 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -437,7 +437,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);
 
     register_savevm("i6300esb_wdt", -1, sizeof(I6300State),
                      i6300esb_save, i6300esb_load, d);
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V5 09/29] pci: clean up of pci_default_read_config.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (7 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 08/29] pci: s/PCI_ADDRESS_SPACE_/PCI_BASE_ADDRESS_SPACE_/ to match pci_regs.h Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-09  6:50   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-09  6:58   ` Michael S. Tsirkin
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 10/29] pci: make pci_bar() aware of header type 1 Isaku Yamahata
                   ` (19 subsequent siblings)
  28 siblings, 2 replies; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

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

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

diff --git a/hw/pci.c b/hw/pci.c
index 634899a..755ebad 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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 10/29] pci: make pci_bar() aware of header type 1.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (8 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 09/29] pci: clean up of pci_default_read_config Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-09  7:06   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-10 19:29   ` Michael S. Tsirkin
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 11/29] pci_host.h: move functions in pci_host.h into .c file Isaku Yamahata
                   ` (18 subsequent siblings)
  28 siblings, 2 replies; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 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>
---
 hw/pci.c |   18 ++++++++++++------
 hw/pci.h |    3 +++
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 755ebad..82c1c3c 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;
+    if (reg == PCI_ROM_SLOT) {
+        return (d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION)
+            == PCI_HEADER_TYPE_BRIDGE ?
+            PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS;
+    }
+
+    return PCI_BASE_ADDRESS_0 + reg * 4;
 }
 
 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..bd63534 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -153,6 +153,9 @@ typedef struct PCIIORegion {
 
 #define PCI_COMMAND_RESERVED_MASK_HI (PCI_COMMAND_RESERVED >> 8)
 
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+
 /* Size of the standard PCI config header */
 #define PCI_CONFIG_HEADER_SIZE 0x40
 /* Size of the standard PCI config space */
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V5 11/29] pci_host.h: move functions in pci_host.h into .c file.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (9 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 10/29] pci: make pci_bar() aware of header type 1 Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 12/29] pci_host: consolidate pci config address access Isaku Yamahata
                   ` (17 subsequent siblings)
  28 siblings, 0 replies; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 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 94bc03b..cc555cb 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 monitor.o pci.o machine.o gdbstub.o
+obj-y = vl.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 920b647..8c38d41 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -28,6 +28,7 @@
 
 #include "sysbus.h"
 #include "pci.h"
+#include "pci_host.h"
 
 /* debug APB */
 //#define DEBUG_APB
@@ -39,9 +40,6 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
 #define APB_DPRINTF(fmt, ...)
 #endif
 
-typedef target_phys_addr_t pci_addr_t;
-#include "pci_host.h"
-
 typedef struct APBState {
     SysBusDevice busdev;
     PCIHostState host_state;
@@ -136,18 +134,6 @@ static CPUReadMemoryFunc * const apb_config_read[] = {
     &apb_config_readl,
 };
 
-static CPUWriteMemoryFunc * const pci_apb_write[] = {
-    &pci_host_data_writeb,
-    &pci_host_data_writew,
-    &pci_host_data_writel,
-};
-
-static CPUReadMemoryFunc * const pci_apb_read[] = {
-    &pci_host_data_readb,
-    &pci_host_data_readw,
-    &pci_host_data_readl,
-};
-
 static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
                                   uint32_t val)
 {
@@ -284,8 +270,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..29d19f9
--- /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 start, PCIHostState *s)
+{
+    register_ioport_write(start, 4, 1, pci_host_data_writeb_ioport, s);
+    register_ioport_write(start, 4, 2, pci_host_data_writew_ioport, s);
+    register_ioport_write(start, 4, 4, pci_host_data_writel_ioport, s);
+    register_ioport_read(start, 4, 1, pci_host_data_readb_ioport, s);
+    register_ioport_read(start, 4, 2, pci_host_data_readw_ioport, s);
+    register_ioport_read(start, 4, 4, pci_host_data_readl_ioport, s);
+}
diff --git a/hw/pci_host.h b/hw/pci_host.h
index 48862b5..4c723ee 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 start, 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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 12/29] pci_host: consolidate pci config address access.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (10 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 11/29] pci_host.h: move functions in pci_host.h into .c file Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 13/29] pci: introduce pcibus_t to represent pci bus address/size instead of uint32_t Isaku Yamahata
                   ` (16 subsequent siblings)
  28 siblings, 0 replies; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 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 8c38d41..db18f45 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -45,46 +45,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)
 {
@@ -266,8 +226,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 29d19f9..99416c8 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(uint32_t start, PCIHostState *s)
+{
+    register_ioport_write(start, 4, 4, pci_host_config_writel_ioport, s);
+    register_ioport_read(start, 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 4c723ee..ae71d7f 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(uint32_t start, PCIHostState *s);
 void pci_host_data_register_ioport(pio_addr_t start, 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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 13/29] pci: introduce pcibus_t to represent pci bus address/size instead of uint32_t
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (11 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 12/29] pci_host: consolidate pci config address access Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 14/29] pci: introduce FMT_PCIBUS for printf format for pcibus_t Isaku Yamahata
                   ` (15 subsequent siblings)
  28 siblings, 0 replies; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

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

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/ac97.c         |    2 +-
 hw/cirrus_vga.c   |    4 ++--
 hw/e1000.c        |    6 +++---
 hw/eepro100.c     |    4 ++--
 hw/es1370.c       |    2 +-
 hw/ide/pci.c      |    4 ++--
 hw/lsi53c895a.c   |    6 +++---
 hw/macio.c        |    2 +-
 hw/msix.c         |    2 +-
 hw/msix.h         |    3 ++-
 hw/ne2000.c       |    2 +-
 hw/openpic.c      |    2 +-
 hw/pci.c          |    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 +-
 23 files changed, 42 insertions(+), 39 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 ffa337b..aa84f31 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -142,8 +142,8 @@ static const char phy_regcap[0x20] = {
 };
 
 static void
-ioport_map(PCIDevice *pci_dev, int region_num, uint32_t addr,
-           uint32_t size, int type)
+ioport_map(PCIDevice *pci_dev, int region_num, pcibus_t addr,
+           pcibus_t size, int type)
 {
     DBGOUT(IO, "e1000_ioport_map addr=0x%04x size=0x%08x\n", addr, size);
 }
@@ -1030,7 +1030,7 @@ static CPUReadMemoryFunc * const e1000_mmio_read[] = {
 
 static void
 e1000_mmio_map(PCIDevice *pci_dev, int region_num,
-                uint32_t addr, uint32_t size, int type)
+                pcibus_t addr, pcibus_t size, int type)
 {
     E1000State *d = DO_UPCAST(E1000State, dev, pci_dev);
     int i;
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 4691028..1a9e96e 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1394,7 +1394,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);
 
@@ -1473,7 +1473,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/pci.c b/hw/ide/pci.c
index be5b1dc..7e63f7e 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -60,7 +60,7 @@ typedef struct PCIIDEState {
 static void cmd646_update_irq(PCIIDEState *d);
 
 static void ide_map(PCIDevice *pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    pcibus_t addr, pcibus_t size, int type)
 {
     PCIIDEState *d = (PCIIDEState *)pci_dev;
     IDEBus *bus;
@@ -245,7 +245,7 @@ static void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val)
 }
 
 static void bmdma_map(PCIDevice *pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    pcibus_t addr, pcibus_t size, int type)
 {
     PCIIDEState *d = (PCIIDEState *)pci_dev;
     int i;
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 2c5232c..df27d23 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 a9a4577..40e2227 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -715,7 +715,7 @@ static int pci_ne2000_load(QEMUFile* f, void* opaque, int version_id)
 /* PCI NE2000 definitions */
 
 static void ne2000_map(PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       pcibus_t addr, pcibus_t size, int type)
 {
     PCINE2000State *d = DO_UPCAST(PCINE2000State, dev, pci_dev);
     NE2000State *s = &d->ne2000;
diff --git a/hw/openpic.c b/hw/openpic.c
index 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 82c1c3c..6d46e5b 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 bd63534..7d3911d 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;
@@ -226,7 +228,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 1097445..e9d2d73 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -1759,7 +1759,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;
 
@@ -1985,7 +1985,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 608085f..f180010 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3324,7 +3324,7 @@ static int rtl8139_load(QEMUFile* f,void* opaque,int version_id)
 /* PCI RTL8139 definitions */
 
 static void rtl8139_mmio_map(PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       pcibus_t addr, pcibus_t size, int type)
 {
     RTL8139State *s = DO_UPCAST(RTL8139State, dev, pci_dev);
 
@@ -3332,7 +3332,7 @@ static void rtl8139_mmio_map(PCIDevice *pci_dev, int region_num,
 }
 
 static void rtl8139_ioport_map(PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       pcibus_t addr, pcibus_t size, int type)
 {
     RTL8139State *s = DO_UPCAST(RTL8139State, dev, pci_dev);
 
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 314dea6..29fae80 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -341,7 +341,7 @@ static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
 static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 
 static void ebus_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
-                              uint32_t addr, uint32_t size, int type)
+                              pcibus_t addr, pcibus_t size, int type)
 {
     DPRINTF("Mapping region %d registers at %08x\n", region_num, addr);
     switch (region_num) {
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 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 e54fff0..7787171 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1059,7 +1059,7 @@ static void uhci_frame_timer(void *opaque)
 }
 
 static void uhci_map(PCIDevice *pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    pcibus_t addr, pcibus_t size, int type)
 {
     UHCIState *s = (UHCIState *)pci_dev;
 
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index 0a2982a..93e5f3c 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -59,7 +59,7 @@ static int pci_vga_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 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 86766f4..a1e8a0b 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -342,7 +342,7 @@ static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
 }
 
 static void virtio_map(PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       pcibus_t addr, pcibus_t size, int type)
 {
     VirtIOPCIProxy *proxy = container_of(pci_dev, VirtIOPCIProxy, pci_dev);
     VirtIODevice *vdev = proxy->vdev;
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index eb1f2f5..6dfdf46 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1174,7 +1174,7 @@ static int pci_vmsvga_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
-                uint32_t addr, uint32_t size, int type)
+                pcibus_t addr, pcibus_t size, int type)
 {
     struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
     struct vmsvga_state_s *s = &d->chip;
@@ -1194,7 +1194,7 @@ static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
 }
 
 static void pci_vmsvga_map_mem(PCIDevice *pci_dev, int region_num,
-                uint32_t addr, uint32_t size, int type)
+                pcibus_t addr, pcibus_t size, int type)
 {
     struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
     struct vmsvga_state_s *s = &d->chip;
diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c
index 32e4ef3..76f5dd9 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -347,7 +347,7 @@ static void i6300esb_mem_writel(void *vp, target_phys_addr_t addr, uint32_t val)
 }
 
 static void i6300esb_map(PCIDevice *dev, int region_num,
-                         uint32_t addr, uint32_t size, int type)
+                         pcibus_t addr, pcibus_t size, int type)
 {
     static CPUReadMemoryFunc * const mem_read[3] = {
         i6300esb_mem_readb,
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V5 14/29] pci: introduce FMT_PCIBUS for printf format for pcibus_t.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (12 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 13/29] pci: introduce pcibus_t to represent pci bus address/size instead of uint32_t Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-10 19:32   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 15/29] pci: typedef pcibus_t as uint64_t instead of uint32_t Isaku Yamahata
                   ` (14 subsequent siblings)
  28 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

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

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/e1000.c        |    6 ++++--
 hw/eepro100.c     |    6 ++++--
 hw/pci.c          |   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 aa84f31..9056e2f 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -145,7 +145,8 @@ static void
 ioport_map(PCIDevice *pci_dev, int region_num, pcibus_t addr,
            pcibus_t size, int type)
 {
-    DBGOUT(IO, "e1000_ioport_map addr=0x%04x size=0x%08x\n", addr, size);
+    DBGOUT(IO, "e1000_ioport_map addr=0x%04"FMT_PCIBUS
+           " size=0x%08"FMT_PCIBUS"\n", addr, size);
 }
 
 static void
@@ -1040,7 +1041,8 @@ e1000_mmio_map(PCIDevice *pci_dev, int region_num,
     };
 
 
-    DBGOUT(MMIO, "e1000_mmio_map addr=0x%08x 0x%08x\n", addr, size);
+    DBGOUT(MMIO, "e1000_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n",
+           addr, size);
 
     cpu_register_physical_memory(addr, PNPMMIO_SIZE, d->mmio_index);
     qemu_register_coalesced_mmio(addr, excluded_regs[0]);
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 1a9e96e..da41b73 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1398,7 +1398,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);
@@ -1477,7 +1478,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 6d46e5b..c0ae66a 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);
             }
         }
@@ -1112,7 +1114,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 7d3911d..8a187c2 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 e9d2d73..6102e1a 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -1764,7 +1764,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);
@@ -1990,7 +1991,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 76f5dd9..9621035 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -362,7 +362,8 @@ static void i6300esb_map(PCIDevice *dev, int region_num,
     I6300State *d = DO_UPCAST(I6300State, dev, dev);
     int io_mem;
 
-    i6300esb_debug("addr = %x, size = %x, type = %d\n", addr, size, type);
+    i6300esb_debug("addr = %"FMT_PCIBUS", size = %"FMT_PCIBUS", type = %d\n",
+                   addr, size, type);
 
     io_mem = cpu_register_io_memory(mem_read, mem_write, d);
     cpu_register_physical_memory (addr, 0x10, io_mem);
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V5 15/29] pci: typedef pcibus_t as uint64_t instead of uint32_t.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (13 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 14/29] pci: introduce FMT_PCIBUS for printf format for pcibus_t Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-11 10:43   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 16/29] pci: 64bit bar support Isaku Yamahata
                   ` (13 subsequent siblings)
  28 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 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 c0ae66a..e7f8fb4 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 8a187c2..8fbd45e 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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 16/29] pci: 64bit bar support.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (14 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 15/29] pci: typedef pcibus_t as uint64_t instead of uint32_t Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-10 19:39   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 17/29] pci: make pci configuration transaction more accurate Isaku Yamahata
                   ` (12 subsequent siblings)
  28 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

implemented pci 64bit bar support.

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

diff --git a/hw/pci.c b/hw/pci.c
index e7f8fb4..ee3ab05 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -454,6 +454,13 @@ static int pci_unregister_device(DeviceState *dev)
     return 0;
 }
 
+static inline int pci_bar_is_mem64(const PCIIORegion *r)
+{
+    return !(r->type & PCI_BASE_ADDRESS_SPACE_IO) &&
+        (r->type & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+        PCI_BASE_ADDRESS_MEM_TYPE_64;
+}
+
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
                             pcibus_t size, int type,
                             PCIMapIORegionFunc *map_func)
@@ -484,8 +491,13 @@ 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 (pci_bar_is_mem64(r)) {
+        pci_set_quad(pci_dev->wmask + addr, wmask);
+        pci_set_quad(pci_dev->cmask + addr, ~0ULL);
+    } else {
+        pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
+        pci_set_long(pci_dev->cmask + addr, 0xffffffff);
+    }
 }
 
 static void pci_update_mappings(PCIDevice *d)
@@ -513,7 +525,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 (pci_bar_is_mem64(r)) {
+                        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 +547,7 @@ static void pci_update_mappings(PCIDevice *d)
                          * Without this, PC ide doesn't work well.
                          * TODO: remove this work around.
                          */
-                        last_addr >= UINT32_MAX) {
+                        (!pci_bar_is_mem64(r) && last_addr >= UINT32_MAX)) {
                         new_addr = PCI_BAR_UNMAPPED;
                     }
                 } else {
@@ -773,8 +789,16 @@ 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 = pci_bar_is_mem64(r)? "64 bit": "32 bit";
+                const char *prefetch = "";
+
+                if (r->type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+                    prefetch = " prefetchable";
+                }
+
+                monitor_printf(mon, "%s%s memory at 0x%08"FMT_PCIBUS
                                " [0x%08"FMT_PCIBUS"].\n",
+                               type, prefetch,
                                r->addr, r->addr + r->size - 1);
             }
         }
diff --git a/hw/pci.h b/hw/pci.h
index 8fbd45e..269981a 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -114,6 +114,8 @@ 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_MASK	0x06
+#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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 17/29] pci: make pci configuration transaction more accurate.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (15 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 16/29] pci: 64bit bar support Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-09 12:52   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 18/29] pci: factor out the conversion logic from io port address into pci device Isaku Yamahata
                   ` (11 subsequent siblings)
  28 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 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         |  115 ++++++++++++++++++++++++++++++++++++++++--------------
 hw/pci.h         |    8 ++-
 3 files changed, 92 insertions(+), 35 deletions(-)

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index ccd2cf3..d50919b 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -87,7 +87,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;
@@ -222,7 +222,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 ee3ab05..33cc476 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -34,9 +34,12 @@
 # define PCI_DPRINTF(format, ...)       do { } while (0)
 #endif
 
+#define PCI_BUS_NUM_MAX 255
 struct PCIBus {
     BusState qbus;
     int bus_num;
+    int sub_bus;
+
     int devfn_min;
     pci_set_irq_fn set_irq;
     pci_map_irq_fn map_irq;
@@ -45,7 +48,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;
@@ -70,7 +76,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",
@@ -128,6 +140,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)
 {
@@ -135,8 +169,13 @@ 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 */
+    bus->bus_num = 0;
+    bus->sub_bus = PCI_BUS_NUM_MAX;
+    QLIST_INIT(&bus->child);
+    pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */
+
     vmstate_register(nbus++, &vmstate_pcibus, bus);
     qemu_register_reset(pci_bus_reset, bus);
 }
@@ -178,7 +217,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)
@@ -186,8 +226,11 @@ 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;
+
+    bus->bus_num = dev->config[PCI_SECONDARY_BUS];
+    bus->sub_bus = dev->config[PCI_SUBORDINATE_BUS];
+    QLIST_INIT(&bus->child);
+    QLIST_INSERT_HEAD(&parent->child, bus, sibling);
 }
 
 int pci_bus_num(PCIBus *s)
@@ -300,7 +343,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) == NULL)
 	return -1;
 
     *domp = dom;
@@ -330,7 +373,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) {
@@ -338,7 +381,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)
@@ -622,8 +665,7 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
                 addr, val, len);
 #endif
     bus_num = (addr >> 16) & 0xff;
-    while (s && s->bus_num != bus_num)
-        s = s->next;
+    s = pci_find_bus(s, bus_num);
     if (!s)
         return;
     pci_dev = s->devices[(addr >> 8) & 0xff];
@@ -643,8 +685,7 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
     uint32_t val;
 
     bus_num = (addr >> 16) & 0xff;
-    while (s && s->bus_num != bus_num)
-        s= s->next;
+    s = pci_find_bus(s, bus_num);
     if (!s)
         goto fail;
     pci_dev = s->devices[(addr >> 8) & 0xff];
@@ -750,7 +791,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;
@@ -805,30 +846,32 @@ static void pci_info_device(PCIDevice *d)
     }
     monitor_printf(mon, "      id \"%s\"\n", d->qdev.id ? d->qdev.id : "");
     if (class == 0x0604 && d->config[0x19] != 0) {
-        pci_for_each_device(d->config[0x19], pci_info_device);
+        pci_for_each_device(bus, d->config[0x19], pci_info_device);
     }
 }
 
-void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
+void pci_for_each_device(PCIBus *bus, int bus_num,
+                         void (*fn)(PCIBus *b, PCIDevice *d))
 {
-    PCIBus *bus = first_bus;
     PCIDevice *d;
     int devfn;
 
-    while (bus && bus->bus_num != bus_num)
-        bus = bus->next;
+    bus = pci_find_bus(bus, bus_num);
     if (bus) {
         for(devfn = 0; devfn < 256; devfn++) {
             d = bus->devices[devfn];
             if (d)
-                fn(d);
+                fn(bus, d);
         }
     }
 }
 
 void pci_info(Monitor *mon)
 {
-    pci_for_each_device(0, pci_info_device);
+    struct PCIHostBus *host;
+    QLIST_FOREACH(host, &host_buses, next) {
+        pci_for_each_device(host->bus, 0, pci_info_device);
+    }
 }
 
 static const char * const pci_nic_models[] = {
@@ -917,21 +960,33 @@ static void pci_bridge_write_config(PCIDevice *d,
 
     pci_default_write_config(d, address, val, len);
     s->bus.bus_num = d->config[PCI_SECONDARY_BUS];
+    s->bus.sub_bus = d->config[PCI_SUBORDINATE_BUS];
 }
 
-PCIBus *pci_find_bus(int bus_num)
+PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
 {
-    PCIBus *bus = first_bus;
+    PCIBus *sec;
 
-    while (bus && bus->bus_num != bus_num)
-        bus = bus->next;
+    if (!bus)
+        return NULL;
 
-    return bus;
+    if (bus->bus_num == bus_num) {
+        return bus;
+    }
+
+    /* try child bus */
+    QLIST_FOREACH(sec, &bus->child, sibling) {
+        if (sec->bus_num <= bus_num && bus_num <= sec->sub_bus) {
+            return pci_find_bus(sec, bus_num);
+        }
+    }
+
+    return NULL;
 }
 
-PCIDevice *pci_find_device(int bus_num, int slot, int function)
+PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function)
 {
-    PCIBus *bus = pci_find_bus(bus_num);
+    bus = pci_find_bus(bus, bus_num);
 
     if (!bus)
         return NULL;
@@ -973,7 +1028,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;
 }
 
diff --git a/hw/pci.h b/hw/pci.h
index 269981a..3a3838d 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -159,6 +159,7 @@ typedef struct PCIIORegion {
 #define PCI_COMMAND_RESERVED_MASK_HI (PCI_COMMAND_RESERVED >> 8)
 
 /* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
 #define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
 
 /* Size of the standard PCI config header */
@@ -270,9 +271,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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 18/29] pci: factor out the conversion logic from io port address into pci device.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (16 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 17/29] pci: make pci configuration transaction more accurate Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-10 19:41   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 19/29] pci: split out ioport address parsing from pci configuration access logic Isaku Yamahata
                   ` (10 subsequent siblings)
  28 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 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 33cc476..0021c96 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -654,24 +654,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 & 0xff;
+}
+
 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);
@@ -681,16 +690,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;
@@ -705,7 +709,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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 19/29] pci: split out ioport address parsing from pci configuration access logic.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (17 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 18/29] pci: factor out the conversion logic from io port address into pci device Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-10 19:45   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 20/29] pci: move pci host stuff from pci.c to pci_host.c Isaku Yamahata
                   ` (9 subsequent siblings)
  28 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

Split out pci_data_{write, read} into two part, one is the code which
convert ioport address into pci device and the other is the code
which access PCI configuration space.

Later PCI express code will use the access code.
PCI express addressing scheme is different so that the address
must be parsed differently.

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

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

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

diff --git a/hw/pci.c b/hw/pci.c
index 0021c96..d472b58 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -654,46 +654,24 @@ 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 & 0xff;
-}
-
-void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
+static void pci_dev_write_config(PCIDevice *pci_dev,
+                                 uint32_t config_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);
+    assert(len == 1 || len == 2 || len == 4);
     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_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRI32x" len=%d\n",
+                __func__, pci_dev->name, config_addr, val, len);
     pci_dev->config_write(pci_dev, config_addr, val, len);
 }
 
-uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
+static uint32_t pci_dev_read_config(PCIDevice *pci_dev,
+                                    uint32_t config_addr, int len)
 {
-    PCIBus *s = opaque;
-    PCIDevice *pci_dev;
-    int config_addr;
     uint32_t val;
 
-    pci_dev = pci_addr_to_dev(s, addr);
+    assert(len == 1 || len == 2 || len == 4);
     if (!pci_dev) {
         switch(len) {
         case 1:
@@ -707,20 +685,40 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
             val = 0xffffffff;
             break;
         }
-        goto the_end;
+    } else {
+        val = pci_dev->config_read(pci_dev, config_addr, len);
+        PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
+                    __func__, pci_dev->name, config_addr, val, len);
     }
-    config_addr = 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;
 }
 
+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 & 0xff;
+}
+
+void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
+{
+    PCIBus *s = opaque;
+    pci_dev_write_config(pci_addr_to_dev(s, addr), pci_addr_to_config(addr),
+                         val, len);
+}
+
+uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
+{
+    PCIBus *s = opaque;
+    return pci_dev_read_config(pci_addr_to_dev(s, addr),
+                               pci_addr_to_config(addr), len);
+}
+
 /***********************************************************/
 /* generic PCI irq support */
 
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V5 20/29] pci: move pci host stuff from pci.c to pci_host.c
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (18 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 19/29] pci: split out ioport address parsing from pci configuration access logic Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-10 19:46   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 21/29] pci_host: change the signature of pci_data_{read, write} Isaku Yamahata
                   ` (8 subsequent siblings)
  28 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 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      |   34 ++++------------------------------
 hw/pci.h      |    4 ++++
 hw/pci_host.c |   34 ++++++++++++++++++++++++++++++++++
 3 files changed, 42 insertions(+), 30 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index d472b58..99b420f 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -654,8 +654,8 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
         pci_update_mappings(d);
 }
 
-static void pci_dev_write_config(PCIDevice *pci_dev,
-                                 uint32_t config_addr, uint32_t val, int len)
+void pci_dev_write_config(PCIDevice *pci_dev,
+                          uint32_t config_addr, uint32_t val, int len)
 {
     assert(len == 1 || len == 2 || len == 4);
     if (!pci_dev)
@@ -666,8 +666,8 @@ static void pci_dev_write_config(PCIDevice *pci_dev,
     pci_dev->config_write(pci_dev, config_addr, val, len);
 }
 
-static uint32_t pci_dev_read_config(PCIDevice *pci_dev,
-                                    uint32_t config_addr, int len)
+uint32_t pci_dev_read_config(PCIDevice *pci_dev,
+                             uint32_t config_addr, int len)
 {
     uint32_t val;
 
@@ -693,32 +693,6 @@ static uint32_t pci_dev_read_config(PCIDevice *pci_dev,
     return val;
 }
 
-static inline PCIDevice *pci_addr_to_dev(PCIBus *bus, uint32_t addr)
-{
-    uint8_t bus_num = (addr >> 16) & 0xff;
-    uint8_t devfn = (addr >> 8) & 0xff;
-    return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
-}
-
-static inline int pci_addr_to_config(uint32_t addr)
-{
-    return addr & 0xff;
-}
-
-void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
-{
-    PCIBus *s = opaque;
-    pci_dev_write_config(pci_addr_to_dev(s, addr), pci_addr_to_config(addr),
-                         val, len);
-}
-
-uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
-{
-    PCIBus *s = opaque;
-    return pci_dev_read_config(pci_addr_to_dev(s, addr),
-                               pci_addr_to_config(addr), len);
-}
-
 /***********************************************************/
 /* generic PCI irq support */
 
diff --git a/hw/pci.h b/hw/pci.h
index 3a3838d..7711ed4 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -268,6 +268,10 @@ 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_dev_write_config(PCIDevice *pci_dev,
+                          uint32_t config_addr, uint32_t val, int len);
+uint32_t pci_dev_read_config(PCIDevice *pci_dev,
+                             uint32_t config_addr, int len);
 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);
diff --git a/hw/pci_host.c b/hw/pci_host.c
index 99416c8..d827b06 100644
--- a/hw/pci_host.c
+++ b/hw/pci_host.c
@@ -32,6 +32,40 @@ 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 & 0xff;
+}
+
+void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
+{
+    PCIBus *s = opaque;
+    pci_dev_write_config(pci_addr_to_dev(s, addr), pci_addr_to_config(addr),
+                         val, len);
+}
+
+uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
+{
+    PCIBus *s = opaque;
+    return pci_dev_read_config(pci_addr_to_dev(s, addr),
+                               pci_addr_to_config(addr), len);
+}
+
 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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 21/29] pci_host: change the signature of pci_data_{read, write}.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (19 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 20/29] pci: move pci host stuff from pci.c to pci_host.c Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-09 12:02   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 22/29] vmstate: add VMSTATE_ARRAY_POINTER for pointer to array Isaku Yamahata
                   ` (7 subsequent siblings)
  28 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 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>
---
 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 7711ed4..5b8f5cf 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -272,8 +272,8 @@ void pci_dev_write_config(PCIDevice *pci_dev,
                           uint32_t config_addr, uint32_t val, int len);
 uint32_t pci_dev_read_config(PCIDevice *pci_dev,
                              uint32_t config_addr, int len);
-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 d827b06..87933d9 100644
--- a/hw/pci_host.c
+++ b/hw/pci_host.c
@@ -52,16 +52,14 @@ static inline uint32_t pci_addr_to_config(uint32_t addr)
     return addr & 0xff;
 }
 
-void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
+void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
 {
-    PCIBus *s = opaque;
     pci_dev_write_config(pci_addr_to_dev(s, addr), pci_addr_to_config(addr),
                          val, len);
 }
 
-uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
+uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
 {
-    PCIBus *s = opaque;
     return pci_dev_read_config(pci_addr_to_dev(s, addr),
                                pci_addr_to_config(addr), len);
 }
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V5 22/29] vmstate: add VMSTATE_ARRAY_POINTER for pointer to array.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (20 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 21/29] pci_host: change the signature of pci_data_{read, write} Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-11 10:37   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 23/29] pci: pcie host and mmcfg support Isaku Yamahata
                   ` (6 subsequent siblings)
  28 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

add VMSTATE_ARRAY_POINTER for pointer to array.
This will be used later.

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

diff --git a/hw/hw.h b/hw/hw.h
index 8c223f8..e867af4 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -389,6 +389,16 @@ extern const VMStateInfo vmstate_info_buffer;
         + type_check_array(_type,typeof_field(_state, _field),_num)  \
 }
 
+#define VMSTATE_ARRAY_POINTER(_field, _state, _version, _info, _type, _size) { \
+    .name       = (stringify(_field)),                               \
+    .version_id = (_version),                                        \
+    .size       = (_size),                                           \
+    .info       = &(_info),                                          \
+    .flags      = VMS_SINGLE | VMS_POINTER,                          \
+    .offset     = offsetof(_state, _field)                           \
+            + type_check(_type,typeof_field(_state, _field))         \
+}
+
 #define VMSTATE_VARRAY(_field, _state, _field_num, _version, _info, _type) {\
     .name       = (stringify(_field)),                               \
     .version_id = (_version),                                        \
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V5 23/29] pci: pcie host and mmcfg support.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (21 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 22/29] vmstate: add VMSTATE_ARRAY_POINTER for pointer to array Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-11 10:26   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 24/29] pci: fix pci_default_write_config() Isaku Yamahata
                   ` (5 subsequent siblings)
  28 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 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         |   12 ++++
 hw/pci.c        |   86 ++++++++++++++++++++++++-----
 hw/pci.h        |   27 ++++++++-
 hw/pcie_host.c  |  166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/pcie_host.h  |   53 ++++++++++++++++++
 6 files changed, 327 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 cc555cb..ced7f65 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 monitor.o pci.o pci_host.o machine.o gdbstub.o
+obj-y = vl.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 e867af4..fba3167 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -494,6 +494,18 @@ extern const VMStateDescription vmstate_pci_device;
             + type_check(PCIDevice,typeof_field(_state, _field))     \
 }
 
+extern const VMStateDescription vmstate_pcie_device;
+
+#define VMSTATE_PCIE_DEVICE(_field, _state) {                        \
+    .name       = (stringify(_field)),                               \
+    .version_id = 2,                                                 \
+    .size       = sizeof(PCIDevice),                                 \
+    .vmsd       = &vmstate_pcie_device,                              \
+    .flags      = VMS_STRUCT,                                        \
+    .offset     = offsetof(_state, _field)                           \
+            + type_check(PCIDevice,typeof_field(_state, _field))     \
+}
+
 extern const VMStateDescription vmstate_i2c_slave;
 
 #define VMSTATE_I2C_SLAVE(_field, _state) {                          \
diff --git a/hw/pci.c b/hw/pci.c
index 99b420f..4436e12 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"
@@ -241,18 +242,24 @@ int pci_bus_num(PCIBus *s)
 static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
 {
     PCIDevice *s = container_of(pv, PCIDevice, config);
-    uint8_t config[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;
 }
 
@@ -260,6 +267,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);
 }
 
@@ -276,21 +284,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_ARRAY_POINTER(config, PCIDevice, 0, vmstate_info_pci_config,
+                              typeof_field(PCIDevice, config),
+                              PCI_CONFIG_SPACE_SIZE),
+        VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+const VMStateDescription vmstate_pcie_device = {
+    .name = "PCIDevice",
+    .version_id = 2,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_INT32_LE(version_id, PCIDevice),
+        VMSTATE_ARRAY_POINTER(config, PCIDevice, 0, vmstate_info_pci_config,
+                              typeof_field(PCIDevice, config),
+                              PCIE_CONFIG_SPACE_SIZE),
         VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
         VMSTATE_END_OF_LIST()
     }
 };
 
+static 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)
@@ -399,14 +428,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;
     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,
@@ -427,6 +476,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);
@@ -494,6 +544,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;
 }
 
@@ -632,7 +683,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);
 }
@@ -641,10 +692,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);
     }
@@ -1015,6 +1067,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,
@@ -1071,9 +1128,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 5b8f5cf..bfa29c8 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -166,28 +166,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;
@@ -361,6 +364,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);
@@ -369,6 +378,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..134d348
--- /dev/null
+++ b/hw/pcie_host.c
@@ -0,0 +1,166 @@
+/*
+ * 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)
+{
+    pci_dev_write_config(pcie_mmcfg_addr_to_dev(s, mmcfg_addr),
+                         PCIE_MMCFG_CONFOFFSET(mmcfg_addr),
+                         val, len);
+}
+
+static uint32_t pcie_mmcfg_data_read(PCIBus *s,
+                                     uint32_t mmcfg_addr, int len)
+{
+    return pci_dev_read_config(pcie_mmcfg_addr_to_dev(s, mmcfg_addr),
+                               PCIE_MMCFG_CONFOFFSET(mmcfg_addr),
+                               len);
+}
+
+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,
+};
+
+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..f4116b3
--- /dev/null
+++ b/hw/pcie_host.h
@@ -0,0 +1,53 @@
+/*
+ * 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 of MMCONFIG area is mapped.
+     * PCIE_BASE_ADDR_UNMAPPED when it isn't mapped.
+     */
+    target_phys_addr_t  base_addr;
+#define PCIE_BASE_ADDR_UNMAPPED  ((target_phys_addr_t)-1ULL)
+
+    /* the size of MMCONFIG area. It's host bridge dependent */
+    target_phys_addr_t  size;
+
+    /* result of cpu_resiger_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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 24/29] pci: fix pci_default_write_config()
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (22 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 23/29] pci: pcie host and mmcfg support Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 25/29] pci: add helper functions for pci config write function Isaku Yamahata
                   ` (4 subsequent siblings)
  28 siblings, 0 replies; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

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

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

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

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

* [Qemu-devel] [PATCH V5 25/29] pci: add helper functions for pci config write function.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (23 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 24/29] pci: fix pci_default_write_config() Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-10 19:58   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 26/29] pci: use helper function in pci_default_write_config() Isaku Yamahata
                   ` (3 subsequent siblings)
  28 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

add helper functions for pci config write function to check
if its configuration space is changed.
To detect the change in configuration space, memcpy the original
value and memcmp with updated value.
The original value is allocated in PCIDevice because its length
might be 4K for pci express which is a bit too large for stack.

Those functions will be used later and generic enough for specific
pci device to use.

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

diff --git a/hw/pci.c b/hw/pci.c
index 8e396b6..ece429f 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -446,6 +446,7 @@ static void pci_config_alloc(PCIDevice *pci_dev)
     pci_dev->cmask = qemu_mallocz(config_size);
     pci_dev->wmask = qemu_mallocz(config_size);
     pci_dev->used = qemu_mallocz(config_size);
+    pci_dev->orig = qemu_mallocz(config_size);
 }
 
 static void pci_config_free(PCIDevice *pci_dev)
@@ -454,6 +455,7 @@ static void pci_config_free(PCIDevice *pci_dev)
     qemu_free(pci_dev->cmask);
     qemu_free(pci_dev->wmask);
     qemu_free(pci_dev->used);
+    qemu_free(pci_dev->orig);
 }
 
 /* -1 for devfn means auto assign */
diff --git a/hw/pci.h b/hw/pci.h
index bfa29c8..2896b0e 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -192,6 +192,9 @@ struct PCIDevice {
     /* Used to allocate config space for capabilities. */
     uint8_t *used;
 
+    /* Used to implement configuration space change */
+    uint8_t *orig;
+
     /* the following fields are read only */
     PCIBus *bus;
     uint32_t devfn;
@@ -388,6 +391,53 @@ static inline uint32_t pci_config_size(PCIDevice *d)
     return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE;
 }
 
+struct pci_config_update {
+    PCIDevice *d;
+    uint32_t addr;
+    uint32_t val;
+    int len;
+};
+
+static inline void pci_write_config_init(struct pci_config_update *update,
+                                         PCIDevice *d,
+                                         uint32_t addr, uint32_t val, int len)
+{
+    update->d = d;
+    update->addr = addr;
+    update->val = val;
+    update->len = len;
+    memcpy(d->orig, d->config, pci_config_size(d));
+}
+
+static inline void pci_write_config_update(struct pci_config_update *update)
+{
+    PCIDevice *d = update->d;
+    uint32_t addr = update->addr;
+    uint32_t val = update->val;
+    uint32_t config_size = pci_config_size(d);
+    int i;
+
+    for(i = 0; i < update->len && addr < config_size; val >>= 8, ++i, ++addr) {
+        uint8_t wmask = d->wmask[addr];
+        d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
+    }
+}
+
+/* check if [base, end) in configuration space is changed */
+static inline int pci_config_changed(const struct pci_config_update *update,
+                                     uint32_t base, uint32_t end)
+{
+    return memcmp(update->d->orig + base, update->d->config + base,
+                  end - base);
+}
+
+/* for convinience not to type symbol constant twice */
+static inline int pci_config_changed_with_size(
+    const struct pci_config_update *update, uint32_t base, uint32_t size)
+{
+    return pci_config_changed(update, base, base + size);
+}
+
 /* lsi53c895a.c */
 #define LSI_MAX_DEVS 7
 
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V5 26/29] pci: use helper function in pci_default_write_config()
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (24 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 25/29] pci: add helper functions for pci config write function Isaku Yamahata
@ 2009-10-09  6:28 ` Isaku Yamahata
  2009-10-09  6:29 ` [Qemu-devel] [PATCH V5 27/29] pci/bridge: don't update bar mapping when bar2-5 is changed Isaku Yamahata
                   ` (2 subsequent siblings)
  28 siblings, 0 replies; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:28 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

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

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

diff --git a/hw/pci.c b/hw/pci.c
index ece429f..37c2eed 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -692,21 +692,16 @@ uint32_t pci_default_read_config(PCIDevice *d,
 
 void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
 {
-    uint8_t orig[PCI_CONFIG_SPACE_SIZE];
-    int i;
-    uint32_t config_size = 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) ||
-         memcmp(orig + PCI_ROM_ADDRESS, d->config + PCI_ROM_ADDRESS, 4))
-        || ((orig[PCI_COMMAND] ^ d->config[PCI_COMMAND])
-            & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)))
+    struct pci_config_update update;
+
+    pci_write_config_init(&update, d, addr, val, l);
+    pci_write_config_update(&update);
+    if (pci_config_changed(&update,
+                           PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_5 + 4) ||
+        pci_config_changed_with_size(&update, PCI_ROM_ADDRESS, 4) ||
+        pci_config_changed_with_size(&update, PCI_COMMAND, 1)) {
         pci_update_mappings(d);
+    }
 }
 
 void pci_dev_write_config(PCIDevice *pci_dev,
diff --git a/hw/pci.h b/hw/pci.h
index 2896b0e..59c65fc 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -112,6 +112,7 @@ typedef struct PCIIORegion {
 #define  PCI_HEADER_TYPE_CARDBUS	2
 #define  PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
 #define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
+#define PCI_BASE_ADDRESS_5	0x24	/* 32 bits */
 #define  PCI_BASE_ADDRESS_SPACE_IO	0x01
 #define  PCI_BASE_ADDRESS_SPACE_MEMORY	0x00
 #define  PCI_BASE_ADDRESS_MEM_TYPE_MASK	0x06
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V5 27/29] pci/bridge: don't update bar mapping when bar2-5 is changed.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (25 preceding siblings ...)
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 26/29] pci: use helper function in pci_default_write_config() Isaku Yamahata
@ 2009-10-09  6:29 ` Isaku Yamahata
  2009-10-09 10:35   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-09  6:29 ` [Qemu-devel] [PATCH V5 28/29] pci: initialize pci config headers depending it pci header type Isaku Yamahata
  2009-10-09  6:29 ` [Qemu-devel] [PATCH V5 29/29] pci/monitor: print out bridge's filtering values and so on Isaku Yamahata
  28 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:29 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

header type of 01 has only BAR 0, 1 and ROM.
So when bar2-5 of bridge is updated (In fact, they are used for
different purpose), it isn't necessary to call pci_update_mappings().

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

diff --git a/hw/pci.c b/hw/pci.c
index 37c2eed..3a17cd8 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -983,10 +983,30 @@ static void pci_bridge_write_config(PCIDevice *d,
                              uint32_t address, uint32_t val, int len)
 {
     PCIBridge *s = (PCIBridge *)d;
+    struct pci_config_update update;
 
-    pci_default_write_config(d, address, val, len);
+    pci_write_config_init(&update, d, address, val, len);
+    pci_write_config_update(&update);
+    if (pci_config_changed(&update,
+                           PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_2 + 4) ||
+        pci_config_changed_with_size(&update, PCI_ROM_ADDRESS1, 4) ||
+        pci_config_changed_with_size(&update, PCI_COMMAND, 1)) {
+        pci_update_mappings(d);
+    }
     s->bus.bus_num = d->config[PCI_SECONDARY_BUS];
     s->bus.sub_bus = d->config[PCI_SUBORDINATE_BUS];
+
+    /*
+     * TODO:
+     * Bridge IO/memory filter isn't emulated. (yet)
+     * At least Linux doesn't depend on bridge filter at the moment,
+     * so it boots happily without bridge filter emulation.
+     * On the other hand, it needs to read/wrote to base/limit registers
+     * accurately.
+     *
+     * If OS depending on bridge filter is found,
+     * filtering will be implemented.
+     */
 }
 
 PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
diff --git a/hw/pci.h b/hw/pci.h
index 59c65fc..3cd93e9 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -112,6 +112,7 @@ typedef struct PCIIORegion {
 #define  PCI_HEADER_TYPE_CARDBUS	2
 #define  PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
 #define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
+#define PCI_BASE_ADDRESS_2	0x18	/* 32 bits */
 #define PCI_BASE_ADDRESS_5	0x24	/* 32 bits */
 #define  PCI_BASE_ADDRESS_SPACE_IO	0x01
 #define  PCI_BASE_ADDRESS_SPACE_MEMORY	0x00
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH V5 28/29] pci: initialize pci config headers depending it pci header type.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (26 preceding siblings ...)
  2009-10-09  6:29 ` [Qemu-devel] [PATCH V5 27/29] pci/bridge: don't update bar mapping when bar2-5 is changed Isaku Yamahata
@ 2009-10-09  6:29 ` Isaku Yamahata
  2009-10-09 10:42   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-09  6:29 ` [Qemu-devel] [PATCH V5 29/29] pci/monitor: print out bridge's filtering values and so on Isaku Yamahata
  28 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:29 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.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/cirrus_vga.c |    1 -
 hw/pci.c        |   62 ++++++++++++++++++++++++++++++++++++++++++++++++------
 hw/pci.h        |   33 +++++++++++++++++++++++++++++
 3 files changed, 88 insertions(+), 8 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 3a17cd8..6b51bba 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -430,14 +430,52 @@ static void pci_init_wmask(PCIDevice *dev)
     int i;
     int config_size = pci_config_size(dev);
 
+    pci_set_word(dev->wmask + PCI_COMMAND,
+                 PCI_COMMAND_IO |
+                 PCI_COMMAND_MEMORY |
+                 PCI_COMMAND_MASTER |
+                 PCI_COMMAND_SPECIAL |
+                 PCI_COMMAND_INVALIDATE |
+                 PCI_COMMAND_VGA_PALETTE |
+                 PCI_COMMAND_PARITY |
+                 PCI_COMMAND_WAIT |
+                 PCI_COMMAND_SERR |
+                 PCI_COMMAND_FAST_BACK |
+                 PCI_COMMAND_INTX_DISABLE);
+
     dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
     dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
-    dev->wmask[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY
-                              | PCI_COMMAND_MASTER;
-    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
+
+    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; i++)
         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);
+
+    /* sec status isn't emulated (yet) */
+    d->wmask[PCI_SEC_STATUS] = 0;
+
+    /* 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_set_long(d->wmask + PCI_PREF_BASE_UPPER32, 0xffffffff);
+    pci_set_long(d->wmask + PCI_PREF_LIMIT_UPPER32, 0xffffffff);
+
+    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);
@@ -462,7 +500,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) {
@@ -479,9 +518,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;
@@ -504,7 +550,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)
@@ -1093,7 +1140,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 3cd93e9..a933ef1 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 */
@@ -162,7 +170,25 @@ typedef struct PCIIORegion {
 
 /* Header type 1 (PCI-to-PCI bridges) */
 #define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER   0x1b    /* Latency timer for secondary interface */
+#define PCI_IO_BASE             0x1c    /* I/O range behind the bridge */
+#define PCI_IO_LIMIT            0x1d
+#define  PCI_IO_RANGE_MASK      (~0x0fUL)
+#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_PREF_LIMIT_UPPER32  0x2c
+#define PCI_IO_BASE_UPPER16     0x30    /* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16    0x32
+/* 0x34 same as for htype 0 */
+/* 0x35-0x3b is reserved */
 #define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL      0x3e
 
 /* Size of the standard PCI config header */
 #define PCI_CONFIG_HEADER_SIZE 0x40
@@ -370,6 +396,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] 68+ messages in thread

* [Qemu-devel] [PATCH V5 29/29] pci/monitor: print out bridge's filtering values and so on.
  2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
                   ` (27 preceding siblings ...)
  2009-10-09  6:29 ` [Qemu-devel] [PATCH V5 28/29] pci: initialize pci config headers depending it pci header type Isaku Yamahata
@ 2009-10-09  6:29 ` Isaku Yamahata
  2009-10-10 20:05   ` [Qemu-devel] " Michael S. Tsirkin
  28 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-09  6:29 UTC (permalink / raw)
  To: qemu-devel, mst; +Cc: yamahata

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

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

diff --git a/hw/pci.c b/hw/pci.c
index 6b51bba..6ce7a40 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -864,6 +864,33 @@ static const pci_class_desc pci_class_descriptions[] =
     { 0, NULL}
 };
 
+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 (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 void pci_info_device(PCIBus *bus, PCIDevice *d)
 {
     Monitor *mon = cur_mon;
@@ -892,7 +919,35 @@ 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_config_get_io_base(d, PCI_IO_BASE, PCI_IO_BASE_UPPER16);
+        limit = pci_config_get_io_base(d, PCI_IO_LIMIT, PCI_IO_LIMIT_UPPER16);
+        limit |= 0xfff; /* PCI bridge spec 3.2.5.6. */
+        monitor_printf(mon, "      IO range [0x%04"PRIx64", 0x%04"PRIx64"]\n",
+                       base, limit);
+
+        base = pci_config_get_memory_base(d, PCI_MEMORY_BASE);
+        limit= pci_config_get_memory_base(d, PCI_MEMORY_LIMIT);
+        limit |= 0xfffff;       /* PCI bridge spec 3.2.5.1. */
+        monitor_printf(mon,
+                       "      memory range [0x%08"PRIx64", 0x%08"PRIx64"]\n",
+                       base, limit);
+
+        base = pci_config_get_pref_base(d, PCI_PREF_MEMORY_BASE,
+                                        PCI_PREF_BASE_UPPER32);
+        limit = pci_config_get_pref_base(d, PCI_PREF_MEMORY_LIMIT,
+                                         PCI_PREF_LIMIT_UPPER32);
+        limit |= 0xfffff;       /* PCI bridge spec 3.2.5.8 */
+        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];
diff --git a/hw/pci.h b/hw/pci.h
index a933ef1..80efbf9 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -173,6 +173,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_MEMORY_BASE         0x20    /* Memory range behind */
 #define PCI_MEMORY_LIMIT        0x22
-- 
1.6.0.2

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

* [Qemu-devel] Re: [PATCH V5 09/29] pci: clean up of pci_default_read_config.
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 09/29] pci: clean up of pci_default_read_config Isaku Yamahata
@ 2009-10-09  6:50   ` Michael S. Tsirkin
  2009-10-09  6:58   ` Michael S. Tsirkin
  1 sibling, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-09  6:50 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:42PM +0900, Isaku Yamahata wrote:
> This patch cleans up pci_default_read_config() removing
> ugly length and range check.
> 
> Suggesed by "Michael S. Tsirkin" <mst@redhat.com>

Nit: suggested.

> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.c |   26 +++++---------------------
>  1 files changed, 5 insertions(+), 21 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 634899a..755ebad 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	[flat|nested] 68+ messages in thread

* [Qemu-devel] Re: [PATCH V5 07/29] pci/bridge: clean up of pci_bridge_initfn()
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 07/29] pci/bridge: clean up of pci_bridge_initfn() Isaku Yamahata
@ 2009-10-09  6:53   ` Michael S. Tsirkin
  2009-10-13 13:20     ` Isaku Yamahata
  2009-10-09  6:54   ` Michael S. Tsirkin
  1 sibling, 1 reply; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-09  6:53 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:40PM +0900, Isaku Yamahata wrote:
> - use symbolic constant
> - use helper function pci_set_xxx()
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.c |   23 ++++++++++++-----------
>  1 files changed, 12 insertions(+), 11 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index a66e3de..eaf471a 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -923,17 +923,18 @@ 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
> +    pci_set_word(dev->config + PCI_COMMAND,
> +                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);

BTW, I think this is a wrong reset value: should be disabled
by default. Fixing this needs some testing though, so
I am not suggesting we do it in this patch. Have some time
to fix this?

> +    pci_set_word(dev->config + PCI_STATUS,
> +                 PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
> +    dev->config[PCI_REVISION_ID] = 0x00;
> +    dev->config[PCI_CLASS_PROG] = 0x00;

I think we can remove these two: this is the default already.

> +    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	[flat|nested] 68+ messages in thread

* [Qemu-devel] Re: [PATCH V5 07/29] pci/bridge: clean up of pci_bridge_initfn()
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 07/29] pci/bridge: clean up of pci_bridge_initfn() Isaku Yamahata
  2009-10-09  6:53   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-09  6:54   ` Michael S. Tsirkin
  1 sibling, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-09  6:54 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:40PM +0900, Isaku Yamahata wrote:
> - use symbolic constant
> - use helper function pci_set_xxx()
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Posted some minor comments previously, but anyway, this is
much better than what we now have.

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

> ---
>  hw/pci.c |   23 ++++++++++++-----------
>  1 files changed, 12 insertions(+), 11 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index a66e3de..eaf471a 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -923,17 +923,18 @@ 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
> +    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);
> +    dev->config[PCI_REVISION_ID] = 0x00;
> +    dev->config[PCI_CLASS_PROG] = 0x00;
> +    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	[flat|nested] 68+ messages in thread

* [Qemu-devel] Re: [PATCH V5 08/29] pci: s/PCI_ADDRESS_SPACE_/PCI_BASE_ADDRESS_SPACE_/ to match pci_regs.h
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 08/29] pci: s/PCI_ADDRESS_SPACE_/PCI_BASE_ADDRESS_SPACE_/ to match pci_regs.h Isaku Yamahata
@ 2009-10-09  6:57   ` Michael S. Tsirkin
  2009-10-13 13:21     ` Isaku Yamahata
  0 siblings, 1 reply; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-09  6:57 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:41PM +0900, Isaku Yamahata wrote:
> make constants for pci base address match pci_regs.h by
> renaming PCI_ADDRESS_SPACE_xxx to PCI_BASE_ADDRESS_SPACE_xxx.

The less macros we have to maintain by our own, the better.
BTW, long term, do we want to split these into pci_regs.h, which can
then be just exported from linux? Anthony?

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


> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/ac97.c         |    5 +++--
>  hw/cirrus_vga.c   |    4 ++--
>  hw/e1000.c        |    4 ++--
>  hw/eepro100.c     |   18 ++++++++++--------
>  hw/es1370.c       |    2 +-
>  hw/ide/pci.c      |   12 ++++++------
>  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 +-
>  21 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 f123bda..ffa337b 100644
> --- a/hw/e1000.c
> +++ b/hw/e1000.c
> @@ -1106,10 +1106,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 445d46c..4691028 100644
> --- a/hw/eepro100.c
> +++ b/hw/eepro100.c
> @@ -428,18 +428,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!!!) */
> @@ -1818,11 +1820,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);
>  
>      qdev_get_macaddr(&s->dev.qdev, s->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/pci.c b/hw/ide/pci.c
> index 9504e44..be5b1dc 100644
> --- a/hw/ide/pci.c
> +++ b/hw/ide/pci.c
> @@ -414,15 +414,15 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
>      }
>  
>      pci_register_bar((PCIDevice *)d, 0, 0x8,
> -                     PCI_ADDRESS_SPACE_IO, ide_map);
> +                     PCI_BASE_ADDRESS_SPACE_IO, ide_map);
>      pci_register_bar((PCIDevice *)d, 1, 0x4,
> -                     PCI_ADDRESS_SPACE_IO, ide_map);
> +                     PCI_BASE_ADDRESS_SPACE_IO, ide_map);
>      pci_register_bar((PCIDevice *)d, 2, 0x8,
> -                     PCI_ADDRESS_SPACE_IO, ide_map);
> +                     PCI_BASE_ADDRESS_SPACE_IO, ide_map);
>      pci_register_bar((PCIDevice *)d, 3, 0x4,
> -                     PCI_ADDRESS_SPACE_IO, ide_map);
> +                     PCI_BASE_ADDRESS_SPACE_IO, ide_map);
>      pci_register_bar((PCIDevice *)d, 4, 0x10,
> -                     PCI_ADDRESS_SPACE_IO, bmdma_map);
> +                     PCI_BASE_ADDRESS_SPACE_IO, bmdma_map);
>  
>      pci_conf[0x3d] = 0x01; // interrupt on pin 1
>  
> @@ -478,7 +478,7 @@ static int pci_piix_ide_initfn(PCIIDEState *d)
>      piix3_reset(d);
>  
>      pci_register_bar((PCIDevice *)d, 4, 0x10,
> -                     PCI_ADDRESS_SPACE_IO, bmdma_map);
> +                     PCI_BASE_ADDRESS_SPACE_IO, bmdma_map);
>  
>      register_savevm("ide", 0, 3, pci_ide_save, pci_ide_load, d);
>  
> diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
> index a4d3a57..2c5232c 100644
> --- a/hw/lsi53c895a.c
> +++ b/hw/lsi53c895a.c
> @@ -2166,11 +2166,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 87f1e59..a9a4577 100644
> --- a/hw/ne2000.c
> +++ b/hw/ne2000.c
> @@ -755,7 +755,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];
>      qdev_get_macaddr(&d->dev.qdev, s->macaddr);
> 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 eaf471a..634899a 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 {
> @@ -1123,7 +1123,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 afeaca7..1097445 100644
> --- a/hw/pcnet.c
> +++ b/hw/pcnet.c
> @@ -2058,10 +2058,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 10daeb2..608085f 100644
> --- a/hw/rtl8139.c
> +++ b/hw/rtl8139.c
> @@ -3458,10 +3458,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);
>  
>      qdev_get_macaddr(&dev->qdev, s->macaddr);
>      rtl8139_reset(&s->dev.qdev);
> diff --git a/hw/sun4u.c b/hw/sun4u.c
> index 276b17b..314dea6 100644
> --- a/hw/sun4u.c
> +++ b/hw/sun4u.c
> @@ -386,9 +386,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 a3ed9b2..e54fff0 100644
> --- a/hw/usb-uhci.c
> +++ b/hw/usb-uhci.c
> @@ -1095,7 +1095,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);
>  
>      register_savevm("uhci", 0, 1, uhci_save, uhci_load, s);
>      return 0;
> diff --git a/hw/vga-pci.c b/hw/vga-pci.c
> index 5e75938..0a2982a 100644
> --- a/hw/vga-pci.c
> +++ b/hw/vga-pci.c
> @@ -106,7 +106,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;
> @@ -115,7 +115,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 e07a2a7..86766f4 100644
> --- a/hw/virtio-pci.c
> +++ b/hw/virtio-pci.c
> @@ -413,7 +413,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;
> @@ -424,7 +424,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 a273f35..eb1f2f5 100644
> --- a/hw/vmware_vga.c
> +++ b/hw/vmware_vga.c
> @@ -1230,9 +1230,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 3abaa87..32e4ef3 100644
> --- a/hw/wdt_i6300esb.c
> +++ b/hw/wdt_i6300esb.c
> @@ -437,7 +437,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);
>  
>      register_savevm("i6300esb_wdt", -1, sizeof(I6300State),
>                       i6300esb_save, i6300esb_load, d);
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V5 09/29] pci: clean up of pci_default_read_config.
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 09/29] pci: clean up of pci_default_read_config Isaku Yamahata
  2009-10-09  6:50   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-09  6:58   ` Michael S. Tsirkin
  1 sibling, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-09  6:58 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:42PM +0900, Isaku Yamahata wrote:
> This patch cleans up pci_default_read_config() removing
> ugly length and range check.
> 
> Suggesed 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 634899a..755ebad 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	[flat|nested] 68+ messages in thread

* [Qemu-devel] Re: [PATCH V5 10/29] pci: make pci_bar() aware of header type 1.
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 10/29] pci: make pci_bar() aware of header type 1 Isaku Yamahata
@ 2009-10-09  7:06   ` Michael S. Tsirkin
  2009-10-10 19:29   ` Michael S. Tsirkin
  1 sibling, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-09  7:06 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:43PM +0900, Isaku Yamahata wrote:
> 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>

Some minor comments below.
Acked-by: Michael S. Tsirkin <mst@redhat.com>

> ---
>  hw/pci.c |   18 ++++++++++++------
>  hw/pci.h |    3 +++
>  2 files changed, 15 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 755ebad..82c1c3c 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;
> +    if (reg == PCI_ROM_SLOT) {
> +        return (d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION)
> +            == PCI_HEADER_TYPE_BRIDGE ?
> +            PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS;
> +    }
> +
> +    return PCI_BASE_ADDRESS_0 + reg * 4;
>  }

Nit: it would be nice to write it in a way that does not lead to such
wrapping. How about:

static int pci_bar(PCIDevice *d, int reg)
{
    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;
}

Neater, isn't it?

>  
>  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..bd63534 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -153,6 +153,9 @@ typedef struct PCIIORegion {
>  
>  #define PCI_COMMAND_RESERVED_MASK_HI (PCI_COMMAND_RESERVED >> 8)
>  
> +/* Header type 1 (PCI-to-PCI bridges) */
> +#define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
> +

PCI_COMMAND_RESERVED_MASK_HI is our own macro, PCI_ROM_ADDRESS1 comes
from pci_regs.h, it should come in the same block with macros copied
from there. Also please try to keep macros there in the same order, so
one can diff to easily fine errors.

>  /* Size of the standard PCI config header */
>  #define PCI_CONFIG_HEADER_SIZE 0x40
>  /* Size of the standard PCI config space */
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V5 27/29] pci/bridge: don't update bar mapping when bar2-5 is changed.
  2009-10-09  6:29 ` [Qemu-devel] [PATCH V5 27/29] pci/bridge: don't update bar mapping when bar2-5 is changed Isaku Yamahata
@ 2009-10-09 10:35   ` Michael S. Tsirkin
  0 siblings, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-09 10:35 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:29:00PM +0900, Isaku Yamahata wrote:
> header type of 01 has only BAR 0, 1 and ROM.
> So when bar2-5 of bridge is updated (In fact, they are used for
> different purpose), it isn't necessary to call pci_update_mappings().
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

What is the motivation for all these changes?

Is there a good reason to optimize config writes into bridge?  I think
we might want to go in another direction and remove the orig mask in
default write config as well, just update mappings on any write in the
range 0x04 to 0x40.

I also think just calling pci_default_write_config from bridge
is a cleaner API than what is proposed with this
and previous patches.


> ---
>  hw/pci.c |   22 +++++++++++++++++++++-
>  hw/pci.h |    1 +
>  2 files changed, 22 insertions(+), 1 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 37c2eed..3a17cd8 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -983,10 +983,30 @@ static void pci_bridge_write_config(PCIDevice *d,
>                               uint32_t address, uint32_t val, int len)
>  {
>      PCIBridge *s = (PCIBridge *)d;
> +    struct pci_config_update update;
>  
> -    pci_default_write_config(d, address, val, len);
> +    pci_write_config_init(&update, d, address, val, len);
> +    pci_write_config_update(&update);
> +    if (pci_config_changed(&update,
> +                           PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_2 + 4) ||
> +        pci_config_changed_with_size(&update, PCI_ROM_ADDRESS1, 4) ||
> +        pci_config_changed_with_size(&update, PCI_COMMAND, 1)) {
> +        pci_update_mappings(d);
> +    }
>      s->bus.bus_num = d->config[PCI_SECONDARY_BUS];
>      s->bus.sub_bus = d->config[PCI_SUBORDINATE_BUS];
> +
> +    /*
> +     * TODO:
> +     * Bridge IO/memory filter isn't emulated. (yet)
> +     * At least Linux doesn't depend on bridge filter at the moment,
> +     * so it boots happily without bridge filter emulation.
> +     * On the other hand, it needs to read/wrote to base/limit registers
> +     * accurately.
> +     *
> +     * If OS depending on bridge filter is found,
> +     * filtering will be implemented.
> +     */
>  }
>  
>  PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
> diff --git a/hw/pci.h b/hw/pci.h
> index 59c65fc..3cd93e9 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -112,6 +112,7 @@ typedef struct PCIIORegion {
>  #define  PCI_HEADER_TYPE_CARDBUS	2
>  #define  PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
>  #define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
> +#define PCI_BASE_ADDRESS_2	0x18	/* 32 bits */
>  #define PCI_BASE_ADDRESS_5	0x24	/* 32 bits */
>  #define  PCI_BASE_ADDRESS_SPACE_IO	0x01
>  #define  PCI_BASE_ADDRESS_SPACE_MEMORY	0x00
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V5 28/29] pci: initialize pci config headers depending it pci header type.
  2009-10-09  6:29 ` [Qemu-devel] [PATCH V5 28/29] pci: initialize pci config headers depending it pci header type Isaku Yamahata
@ 2009-10-09 10:42   ` Michael S. Tsirkin
  2009-10-13 14:31     ` Isaku Yamahata
  0 siblings, 1 reply; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-09 10:42 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:29:01PM +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.

It was? Can you investigate please?
Spec says most of these are optional.

> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/cirrus_vga.c |    1 -
>  hw/pci.c        |   62 ++++++++++++++++++++++++++++++++++++++++++++++++------
>  hw/pci.h        |   33 +++++++++++++++++++++++++++++
>  3 files changed, 88 insertions(+), 8 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 3a17cd8..6b51bba 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -430,14 +430,52 @@ static void pci_init_wmask(PCIDevice *dev)
>      int i;
>      int config_size = pci_config_size(dev);
>  
> +    pci_set_word(dev->wmask + PCI_COMMAND,
> +                 PCI_COMMAND_IO |
> +                 PCI_COMMAND_MEMORY |
> +                 PCI_COMMAND_MASTER |
> +                 PCI_COMMAND_SPECIAL |
> +                 PCI_COMMAND_INVALIDATE |
> +                 PCI_COMMAND_VGA_PALETTE |
> +                 PCI_COMMAND_PARITY |
> +                 PCI_COMMAND_WAIT |
> +                 PCI_COMMAND_SERR |
> +                 PCI_COMMAND_FAST_BACK |
> +                 PCI_COMMAND_INTX_DISABLE);

At least INTX disable must not be writeable unless
we implement the masking functionality, and we don't

> +
>      dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
>      dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
> -    dev->wmask[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY
> -                              | PCI_COMMAND_MASTER;
> -    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
> +
> +    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; i++)

I dislike this change. We don't use the old value so ++i
is cleaner.

>          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);
> +
> +    /* sec status isn't emulated (yet) */
> +    d->wmask[PCI_SEC_STATUS] = 0;

0 is default value. Replace with /* TODO: emulate PCI_SEC_STATUS */
 (which bits do we have to emulate there?)

> +    /* base and limit */
> +    d->wmask[PCI_IO_BASE] = PCI_IO_RANGE_MASK & 0xff;
> +    d->wmask[PCI_IO_LIMIT] = PCI_IO_RANGE_MASK & 0xff;


& 0xff not necessary.

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

Can we just memset(xxx, 0xff, yyy) the whole range,
and just clear a single byte that is 0?

> +}
> +
>  static void pci_config_alloc(PCIDevice *pci_dev)
>  {
>      int config_size = pci_config_size(pci_dev);
> @@ -462,7 +500,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) {
> @@ -479,9 +518,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;
> @@ -504,7 +550,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)
> @@ -1093,7 +1140,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 3cd93e9..a933ef1 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 */
> @@ -162,7 +170,25 @@ typedef struct PCIIORegion {
>  
>  /* Header type 1 (PCI-to-PCI bridges) */
>  #define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
> +#define PCI_SEC_LATENCY_TIMER   0x1b    /* Latency timer for secondary interface */
> +#define PCI_IO_BASE             0x1c    /* I/O range behind the bridge */
> +#define PCI_IO_LIMIT            0x1d
> +#define  PCI_IO_RANGE_MASK      (~0x0fUL)
> +#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_PREF_LIMIT_UPPER32  0x2c
> +#define PCI_IO_BASE_UPPER16     0x30    /* Upper half of I/O addresses */
> +#define PCI_IO_LIMIT_UPPER16    0x32
> +/* 0x34 same as for htype 0 */
> +/* 0x35-0x3b is reserved */
>  #define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
> +/* 0x3c-0x3d are same as for htype 0 */
> +#define PCI_BRIDGE_CONTROL      0x3e
>  
>  /* Size of the standard PCI config header */
>  #define PCI_CONFIG_HEADER_SIZE 0x40
> @@ -370,6 +396,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	[flat|nested] 68+ messages in thread

* [Qemu-devel] Re: [PATCH V5 21/29] pci_host: change the signature of pci_data_{read, write}.
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 21/29] pci_host: change the signature of pci_data_{read, write} Isaku Yamahata
@ 2009-10-09 12:02   ` Michael S. Tsirkin
  0 siblings, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-09 12:02 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:54PM +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>

> ---
>  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 7711ed4..5b8f5cf 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -272,8 +272,8 @@ void pci_dev_write_config(PCIDevice *pci_dev,
>                            uint32_t config_addr, uint32_t val, int len);
>  uint32_t pci_dev_read_config(PCIDevice *pci_dev,
>                               uint32_t config_addr, int len);
> -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 d827b06..87933d9 100644
> --- a/hw/pci_host.c
> +++ b/hw/pci_host.c
> @@ -52,16 +52,14 @@ static inline uint32_t pci_addr_to_config(uint32_t addr)
>      return addr & 0xff;
>  }
>  
> -void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> +void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
>  {
> -    PCIBus *s = opaque;
>      pci_dev_write_config(pci_addr_to_dev(s, addr), pci_addr_to_config(addr),
>                           val, len);
>  }
>  
> -uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> +uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
>  {
> -    PCIBus *s = opaque;
>      return pci_dev_read_config(pci_addr_to_dev(s, addr),
>                                 pci_addr_to_config(addr), len);
>  }
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V5 17/29] pci: make pci configuration transaction more accurate.
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 17/29] pci: make pci configuration transaction more accurate Isaku Yamahata
@ 2009-10-09 12:52   ` Michael S. Tsirkin
  0 siblings, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-09 12:52 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:50PM +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.

Overall I think this is a good idea.

> 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.

Another point: why store these separately at all?
Can't we just use the pci config registers directly?

> 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>

Some comments below. Could you please test something like windows
boot and verify that using a more complex structure does not
affect boot times?

> ---
>  hw/pci-hotplug.c |    4 +-
>  hw/pci.c         |  115 ++++++++++++++++++++++++++++++++++++++++--------------
>  hw/pci.h         |    8 ++-
>  3 files changed, 92 insertions(+), 35 deletions(-)
> 
> diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
> index ccd2cf3..d50919b 100644
> --- a/hw/pci-hotplug.c
> +++ b/hw/pci-hotplug.c
> @@ -87,7 +87,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;
> @@ -222,7 +222,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 ee3ab05..33cc476 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -34,9 +34,12 @@
>  # define PCI_DPRINTF(format, ...)       do { } while (0)
>  #endif
>  
> +#define PCI_BUS_NUM_MAX 255
>  struct PCIBus {
>      BusState qbus;
>      int bus_num;
> +    int sub_bus;
> +
>      int devfn_min;
>      pci_set_irq_fn set_irq;
>      pci_map_irq_fn map_irq;
> @@ -45,7 +48,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;
> @@ -70,7 +76,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",
> @@ -128,6 +140,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)
>  {
> @@ -135,8 +169,13 @@ 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 */
> +    bus->bus_num = 0;
> +    bus->sub_bus = PCI_BUS_NUM_MAX;
> +    QLIST_INIT(&bus->child);
> +    pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */
> +
>      vmstate_register(nbus++, &vmstate_pcibus, bus);
>      qemu_register_reset(pci_bus_reset, bus);
>  }
> @@ -178,7 +217,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)
> @@ -186,8 +226,11 @@ static void pci_register_secondary_bus(PCIBus *bus,

BTW, should not it be possible to remove buses?
I don't see code removing bus from the tree, anywhere.

>      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;
> +
> +    bus->bus_num = dev->config[PCI_SECONDARY_BUS];
> +    bus->sub_bus = dev->config[PCI_SUBORDINATE_BUS];

These seem unnecessary: init value is 0 anyway.
But you need to update these at reset, I don't see where you do this.

> +    QLIST_INIT(&bus->child);
> +    QLIST_INSERT_HEAD(&parent->child, bus, sibling);
>  }
>  
>  int pci_bus_num(PCIBus *s)
> @@ -300,7 +343,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) == NULL)

Replace == NULL with ! please.

>  	return -1;
>  
>      *domp = dom;
> @@ -330,7 +373,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) {
> @@ -338,7 +381,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)
> @@ -622,8 +665,7 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
>                  addr, val, len);
>  #endif
>      bus_num = (addr >> 16) & 0xff;
> -    while (s && s->bus_num != bus_num)
> -        s = s->next;
> +    s = pci_find_bus(s, bus_num);
>      if (!s)
>          return;
>      pci_dev = s->devices[(addr >> 8) & 0xff];
> @@ -643,8 +685,7 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
>      uint32_t val;
>  
>      bus_num = (addr >> 16) & 0xff;
> -    while (s && s->bus_num != bus_num)
> -        s= s->next;
> +    s = pci_find_bus(s, bus_num);
>      if (!s)
>          goto fail;
>      pci_dev = s->devices[(addr >> 8) & 0xff];
> @@ -750,7 +791,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;
> @@ -805,30 +846,32 @@ static void pci_info_device(PCIDevice *d)
>      }
>      monitor_printf(mon, "      id \"%s\"\n", d->qdev.id ? d->qdev.id : "");
>      if (class == 0x0604 && d->config[0x19] != 0) {
> -        pci_for_each_device(d->config[0x19], pci_info_device);
> +        pci_for_each_device(bus, d->config[0x19], pci_info_device);
>      }
>  }
>  
> -void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
> +void pci_for_each_device(PCIBus *bus, int bus_num,
> +                         void (*fn)(PCIBus *b, PCIDevice *d))
>  {
> -    PCIBus *bus = first_bus;
>      PCIDevice *d;
>      int devfn;
>  
> -    while (bus && bus->bus_num != bus_num)
> -        bus = bus->next;
> +    bus = pci_find_bus(bus, bus_num);
>      if (bus) {
>          for(devfn = 0; devfn < 256; devfn++) {
>              d = bus->devices[devfn];
>              if (d)
> -                fn(d);
> +                fn(bus, d);
>          }
>      }
>  }
>  
>  void pci_info(Monitor *mon)
>  {
> -    pci_for_each_device(0, pci_info_device);
> +    struct PCIHostBus *host;
> +    QLIST_FOREACH(host, &host_buses, next) {
> +        pci_for_each_device(host->bus, 0, pci_info_device);
> +    }
>  }
>  
>  static const char * const pci_nic_models[] = {
> @@ -917,21 +960,33 @@ static void pci_bridge_write_config(PCIDevice *d,
>  
>      pci_default_write_config(d, address, val, len);
>      s->bus.bus_num = d->config[PCI_SECONDARY_BUS];
> +    s->bus.sub_bus = d->config[PCI_SUBORDINATE_BUS];
>  }
>  
> -PCIBus *pci_find_bus(int bus_num)
> +PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
>  {
> -    PCIBus *bus = first_bus;
> +    PCIBus *sec;
>  
> -    while (bus && bus->bus_num != bus_num)
> -        bus = bus->next;
> +    if (!bus)
> +        return NULL;
>  
> -    return bus;
> +    if (bus->bus_num == bus_num) {
> +        return bus;
> +    }
> +
> +    /* try child bus */
> +    QLIST_FOREACH(sec, &bus->child, sibling) {
> +        if (sec->bus_num <= bus_num && bus_num <= sec->sub_bus) {
> +            return pci_find_bus(sec, bus_num);
> +        }
> +    }
> +
> +    return NULL;
>  }
>  
> -PCIDevice *pci_find_device(int bus_num, int slot, int function)
> +PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function)
>  {
> -    PCIBus *bus = pci_find_bus(bus_num);
> +    bus = pci_find_bus(bus, bus_num);
>  
>      if (!bus)
>          return NULL;
> @@ -973,7 +1028,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;
>  }
>  
> diff --git a/hw/pci.h b/hw/pci.h
> index 269981a..3a3838d 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -159,6 +159,7 @@ typedef struct PCIIORegion {
>  #define PCI_COMMAND_RESERVED_MASK_HI (PCI_COMMAND_RESERVED >> 8)
>  
>  /* Header type 1 (PCI-to-PCI bridges) */
> +#define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
>  #define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
>  
>  /* Size of the standard PCI config header */
> @@ -270,9 +271,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	[flat|nested] 68+ messages in thread

* [Qemu-devel] Re: [PATCH V5 10/29] pci: make pci_bar() aware of header type 1.
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 10/29] pci: make pci_bar() aware of header type 1 Isaku Yamahata
  2009-10-09  7:06   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-10 19:29   ` Michael S. Tsirkin
  1 sibling, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-10 19:29 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:43PM +0900, Isaku Yamahata wrote:
> 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>
> ---
>  hw/pci.c |   18 ++++++++++++------
>  hw/pci.h |    3 +++
>  2 files changed, 15 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 755ebad..82c1c3c 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;
> +    if (reg == PCI_ROM_SLOT) {
> +        return (d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION)
> +            == PCI_HEADER_TYPE_BRIDGE ?
> +            PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS;
> +    }
> +
> +    return PCI_BASE_ADDRESS_0 + reg * 4;
>  }
>  

While not critical, I proposed a slightly neater version of
this function. Don't like it?

>  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..bd63534 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -153,6 +153,9 @@ typedef struct PCIIORegion {
>  
>  #define PCI_COMMAND_RESERVED_MASK_HI (PCI_COMMAND_RESERVED >> 8)
>  
> +/* Header type 1 (PCI-to-PCI bridges) */
> +#define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
> +
>  /* Size of the standard PCI config header */
>  #define PCI_CONFIG_HEADER_SIZE 0x40
>  /* Size of the standard PCI config space */
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V5 14/29] pci: introduce FMT_PCIBUS for printf format for pcibus_t.
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 14/29] pci: introduce FMT_PCIBUS for printf format for pcibus_t Isaku Yamahata
@ 2009-10-10 19:32   ` Michael S. Tsirkin
  0 siblings, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-10 19:32 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:47PM +0900, Isaku Yamahata wrote:
> This patch is preliminary for 64bit BAR.
> Later pcibus_t will be changed from uint32_t to uint64_t.
> Introduce FMT_PCIBUS for printf format for pcibus_t.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

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 aa84f31..9056e2f 100644
> --- a/hw/e1000.c
> +++ b/hw/e1000.c
> @@ -145,7 +145,8 @@ static void
>  ioport_map(PCIDevice *pci_dev, int region_num, pcibus_t addr,
>             pcibus_t size, int type)
>  {
> -    DBGOUT(IO, "e1000_ioport_map addr=0x%04x size=0x%08x\n", addr, size);
> +    DBGOUT(IO, "e1000_ioport_map addr=0x%04"FMT_PCIBUS
> +           " size=0x%08"FMT_PCIBUS"\n", addr, size);
>  }
>  
>  static void
> @@ -1040,7 +1041,8 @@ e1000_mmio_map(PCIDevice *pci_dev, int region_num,
>      };
>  
>  
> -    DBGOUT(MMIO, "e1000_mmio_map addr=0x%08x 0x%08x\n", addr, size);
> +    DBGOUT(MMIO, "e1000_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n",
> +           addr, size);
>  
>      cpu_register_physical_memory(addr, PNPMMIO_SIZE, d->mmio_index);
>      qemu_register_coalesced_mmio(addr, excluded_regs[0]);
> diff --git a/hw/eepro100.c b/hw/eepro100.c
> index 1a9e96e..da41b73 100644
> --- a/hw/eepro100.c
> +++ b/hw/eepro100.c
> @@ -1398,7 +1398,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);
> @@ -1477,7 +1478,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 6d46e5b..c0ae66a 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);
>              }
>          }
> @@ -1112,7 +1114,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 7d3911d..8a187c2 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 e9d2d73..6102e1a 100644
> --- a/hw/pcnet.c
> +++ b/hw/pcnet.c
> @@ -1764,7 +1764,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);
> @@ -1990,7 +1991,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 76f5dd9..9621035 100644
> --- a/hw/wdt_i6300esb.c
> +++ b/hw/wdt_i6300esb.c
> @@ -362,7 +362,8 @@ static void i6300esb_map(PCIDevice *dev, int region_num,
>      I6300State *d = DO_UPCAST(I6300State, dev, dev);
>      int io_mem;
>  
> -    i6300esb_debug("addr = %x, size = %x, type = %d\n", addr, size, type);
> +    i6300esb_debug("addr = %"FMT_PCIBUS", size = %"FMT_PCIBUS", type = %d\n",
> +                   addr, size, type);
>  
>      io_mem = cpu_register_io_memory(mem_read, mem_write, d);
>      cpu_register_physical_memory (addr, 0x10, io_mem);
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V5 16/29] pci: 64bit bar support.
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 16/29] pci: 64bit bar support Isaku Yamahata
@ 2009-10-10 19:39   ` Michael S. Tsirkin
  2009-10-13 13:52     ` Isaku Yamahata
  0 siblings, 1 reply; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-10 19:39 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:49PM +0900, Isaku Yamahata wrote:
> implemented pci 64bit bar support.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.c |   34 +++++++++++++++++++++++++++++-----
>  hw/pci.h |    2 ++
>  2 files changed, 31 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index e7f8fb4..ee3ab05 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -454,6 +454,13 @@ static int pci_unregister_device(DeviceState *dev)
>      return 0;
>  }
>  
> +static inline int pci_bar_is_mem64(const PCIIORegion *r)
> +{
> +    return !(r->type & PCI_BASE_ADDRESS_SPACE_IO) &&
> +        (r->type & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
> +        PCI_BASE_ADDRESS_MEM_TYPE_64;
> +}
> +

This should be just 
return r->type & PCI_BASE_ADDRESS_MEM_TYPE_64
and then this can be open-coded.
PCI_BASE_ADDRESS_MEM_TYPE_MASK will also not be needed.

I have a feeling I said this already, and the spec is pretty
clear: there is exactly 1 bit that means 64 bit memory.
No reason to check anything else.

>  void pci_register_bar(PCIDevice *pci_dev, int region_num,
>                              pcibus_t size, int type,
>                              PCIMapIORegionFunc *map_func)
> @@ -484,8 +491,13 @@ 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 (pci_bar_is_mem64(r)) {
> +        pci_set_quad(pci_dev->wmask + addr, wmask);
> +        pci_set_quad(pci_dev->cmask + addr, ~0ULL);
> +    } else {
> +        pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
> +        pci_set_long(pci_dev->cmask + addr, 0xffffffff);
> +    }
>  }
>  
>  static void pci_update_mappings(PCIDevice *d)
> @@ -513,7 +525,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 (pci_bar_is_mem64(r)) {
> +                        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 +547,7 @@ static void pci_update_mappings(PCIDevice *d)
>                           * Without this, PC ide doesn't work well.
>                           * TODO: remove this work around.
>                           */
> -                        last_addr >= UINT32_MAX) {
> +                        (!pci_bar_is_mem64(r) && last_addr >= UINT32_MAX)) {
>                          new_addr = PCI_BAR_UNMAPPED;
>                      }
>                  } else {
> @@ -773,8 +789,16 @@ 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 = pci_bar_is_mem64(r)? "64 bit": "32 bit";
> +                const char *prefetch = "";
> +
> +                if (r->type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
> +                    prefetch = " prefetchable";
> +                }
> +
> +                monitor_printf(mon, "%s%s memory at 0x%08"FMT_PCIBUS
>                                 " [0x%08"FMT_PCIBUS"].\n",
> +                               type, prefetch,
>                                 r->addr, r->addr + r->size - 1);
>              }
>          }
> diff --git a/hw/pci.h b/hw/pci.h
> index 8fbd45e..269981a 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -114,6 +114,8 @@ 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_MASK	0x06
> +#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] 68+ messages in thread

* [Qemu-devel] Re: [PATCH V5 18/29] pci: factor out the conversion logic from io port address into pci device.
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 18/29] pci: factor out the conversion logic from io port address into pci device Isaku Yamahata
@ 2009-10-10 19:41   ` Michael S. Tsirkin
  0 siblings, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-10 19:41 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:51PM +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 33cc476..0021c96 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -654,24 +654,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 & 0xff;
> +}

Replace 0xff with (PCI_CONFIG_SPACE - 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);
> @@ -681,16 +690,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;
> @@ -705,7 +709,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] 68+ messages in thread

* [Qemu-devel] Re: [PATCH V5 19/29] pci: split out ioport address parsing from pci configuration access logic.
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 19/29] pci: split out ioport address parsing from pci configuration access logic Isaku Yamahata
@ 2009-10-10 19:45   ` Michael S. Tsirkin
  2009-10-13 14:14     ` Isaku Yamahata
  0 siblings, 1 reply; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-10 19:45 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:52PM +0900, Isaku Yamahata wrote:
> Split out pci_data_{write, read} into two part, one is the code which
> convert ioport address into pci device and the other is the code
> which access PCI configuration space.
> 
> Later PCI express code will use the access code.
> PCI express addressing scheme is different so that the address
> must be parsed differently.
> 
> PCI:
>  0- 7 bit: offset in the configuration space (256bytes)
>  7-15 bit: devfn
> 16-24 bit: bus
> 
> PCI express:
>  0-11 bit: offset in the configuration space (4KBytes)
> 12-19 bit: devfn
> 20-28 bit: bus
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

So I think I said this already: the only useful thing that
pci_data_read/write does is address conversion which is different for
express.  PCI Express should do its own thing and then call
pci_dev->config_read / pci_dev->config_write directly.

I think this will even make it possible to put express code in a
separate file from pci.c.

> ---
>  hw/pci.c |   80 ++++++++++++++++++++++++++++++-------------------------------
>  1 files changed, 39 insertions(+), 41 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 0021c96..d472b58 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -654,46 +654,24 @@ 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 & 0xff;
> -}
> -
> -void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> +static void pci_dev_write_config(PCIDevice *pci_dev,
> +                                 uint32_t config_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);
> +    assert(len == 1 || len == 2 || len == 4);
>      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_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRI32x" len=%d\n",
> +                __func__, pci_dev->name, config_addr, val, len);
>      pci_dev->config_write(pci_dev, config_addr, val, len);
>  }
>  
> -uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> +static uint32_t pci_dev_read_config(PCIDevice *pci_dev,
> +                                    uint32_t config_addr, int len)
>  {
> -    PCIBus *s = opaque;
> -    PCIDevice *pci_dev;
> -    int config_addr;
>      uint32_t val;
>  
> -    pci_dev = pci_addr_to_dev(s, addr);
> +    assert(len == 1 || len == 2 || len == 4);
>      if (!pci_dev) {
>          switch(len) {
>          case 1:
> @@ -707,20 +685,40 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
>              val = 0xffffffff;
>              break;
>          }
> -        goto the_end;
> +    } else {
> +        val = pci_dev->config_read(pci_dev, config_addr, len);
> +        PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
> +                    __func__, pci_dev->name, config_addr, val, len);
>      }
> -    config_addr = 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;
>  }
>  
> +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 & 0xff;
> +}
> +
> +void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> +{
> +    PCIBus *s = opaque;
> +    pci_dev_write_config(pci_addr_to_dev(s, addr), pci_addr_to_config(addr),
> +                         val, len);
> +}
> +
> +uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> +{
> +    PCIBus *s = opaque;
> +    return pci_dev_read_config(pci_addr_to_dev(s, addr),
> +                               pci_addr_to_config(addr), len);
> +}
> +
>  /***********************************************************/
>  /* generic PCI irq support */
>  
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V5 20/29] pci: move pci host stuff from pci.c to pci_host.c
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 20/29] pci: move pci host stuff from pci.c to pci_host.c Isaku Yamahata
@ 2009-10-10 19:46   ` Michael S. Tsirkin
  0 siblings, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-10 19:46 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:53PM +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.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

So this is good stuff except we do not need
pci_dev_write_config/pci_dev_read_config.

> ---
>  hw/pci.c      |   34 ++++------------------------------
>  hw/pci.h      |    4 ++++
>  hw/pci_host.c |   34 ++++++++++++++++++++++++++++++++++
>  3 files changed, 42 insertions(+), 30 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index d472b58..99b420f 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -654,8 +654,8 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
>          pci_update_mappings(d);
>  }
>  
> -static void pci_dev_write_config(PCIDevice *pci_dev,
> -                                 uint32_t config_addr, uint32_t val, int len)
> +void pci_dev_write_config(PCIDevice *pci_dev,
> +                          uint32_t config_addr, uint32_t val, int len)
>  {
>      assert(len == 1 || len == 2 || len == 4);
>      if (!pci_dev)
> @@ -666,8 +666,8 @@ static void pci_dev_write_config(PCIDevice *pci_dev,
>      pci_dev->config_write(pci_dev, config_addr, val, len);
>  }
>  
> -static uint32_t pci_dev_read_config(PCIDevice *pci_dev,
> -                                    uint32_t config_addr, int len)
> +uint32_t pci_dev_read_config(PCIDevice *pci_dev,
> +                             uint32_t config_addr, int len)
>  {
>      uint32_t val;
>  
> @@ -693,32 +693,6 @@ static uint32_t pci_dev_read_config(PCIDevice *pci_dev,
>      return val;
>  }
>  
> -static inline PCIDevice *pci_addr_to_dev(PCIBus *bus, uint32_t addr)
> -{
> -    uint8_t bus_num = (addr >> 16) & 0xff;
> -    uint8_t devfn = (addr >> 8) & 0xff;
> -    return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
> -}
> -
> -static inline int pci_addr_to_config(uint32_t addr)
> -{
> -    return addr & 0xff;
> -}
> -
> -void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> -{
> -    PCIBus *s = opaque;
> -    pci_dev_write_config(pci_addr_to_dev(s, addr), pci_addr_to_config(addr),
> -                         val, len);
> -}
> -
> -uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> -{
> -    PCIBus *s = opaque;
> -    return pci_dev_read_config(pci_addr_to_dev(s, addr),
> -                               pci_addr_to_config(addr), len);
> -}
> -
>  /***********************************************************/
>  /* generic PCI irq support */
>  
> diff --git a/hw/pci.h b/hw/pci.h
> index 3a3838d..7711ed4 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -268,6 +268,10 @@ 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_dev_write_config(PCIDevice *pci_dev,
> +                          uint32_t config_addr, uint32_t val, int len);
> +uint32_t pci_dev_read_config(PCIDevice *pci_dev,
> +                             uint32_t config_addr, int len);
>  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);
> diff --git a/hw/pci_host.c b/hw/pci_host.c
> index 99416c8..d827b06 100644
> --- a/hw/pci_host.c
> +++ b/hw/pci_host.c
> @@ -32,6 +32,40 @@ 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 & 0xff;
> +}
> +
> +void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> +{
> +    PCIBus *s = opaque;
> +    pci_dev_write_config(pci_addr_to_dev(s, addr), pci_addr_to_config(addr),
> +                         val, len);
> +}
> +
> +uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> +{
> +    PCIBus *s = opaque;
> +    return pci_dev_read_config(pci_addr_to_dev(s, addr),
> +                               pci_addr_to_config(addr), len);
> +}
> +
>  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] 68+ messages in thread

* [Qemu-devel] Re: [PATCH V5 25/29] pci: add helper functions for pci config write function.
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 25/29] pci: add helper functions for pci config write function Isaku Yamahata
@ 2009-10-10 19:58   ` Michael S. Tsirkin
  0 siblings, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-10 19:58 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:58PM +0900, Isaku Yamahata wrote:
> add helper functions for pci config write function to check
> if its configuration space is changed.
> To detect the change in configuration space, memcpy the original
> value and memcmp with updated value.
> The original value is allocated in PCIDevice because its length
> might be 4K for pci express which is a bit too large for stack.
> 
> Those functions will be used later and generic enough for specific
> pci device to use.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.c |    2 ++
>  hw/pci.h |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 52 insertions(+), 0 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 8e396b6..ece429f 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -446,6 +446,7 @@ static void pci_config_alloc(PCIDevice *pci_dev)
>      pci_dev->cmask = qemu_mallocz(config_size);
>      pci_dev->wmask = qemu_mallocz(config_size);
>      pci_dev->used = qemu_mallocz(config_size);
> +    pci_dev->orig = qemu_mallocz(config_size);
>  }
>  
>  static void pci_config_free(PCIDevice *pci_dev)
> @@ -454,6 +455,7 @@ static void pci_config_free(PCIDevice *pci_dev)
>      qemu_free(pci_dev->cmask);
>      qemu_free(pci_dev->wmask);
>      qemu_free(pci_dev->used);
> +    qemu_free(pci_dev->orig);
>  }
>  
>  /* -1 for devfn means auto assign */
> diff --git a/hw/pci.h b/hw/pci.h
> index bfa29c8..2896b0e 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -192,6 +192,9 @@ struct PCIDevice {
>      /* Used to allocate config space for capabilities. */
>      uint8_t *used;
>  
> +    /* Used to implement configuration space change */
> +    uint8_t *orig;
> +
>      /* the following fields are read only */
>      PCIBus *bus;
>      uint32_t devfn;
> @@ -388,6 +391,53 @@ static inline uint32_t pci_config_size(PCIDevice *d)
>      return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE;
>  }
>  
> +struct pci_config_update {
> +    PCIDevice *d;
> +    uint32_t addr;
> +    uint32_t val;
> +    int len;
> +};
> +
> +static inline void pci_write_config_init(struct pci_config_update *update,
> +                                         PCIDevice *d,
> +                                         uint32_t addr, uint32_t val, int len)
> +{
> +    update->d = d;
> +    update->addr = addr;
> +    update->val = val;
> +    update->len = len;
> +    memcpy(d->orig, d->config, pci_config_size(d));
> +}
> +

I think this is a bad API, because it is not re-entrant:
If someone calls pci_write_config_init and then default_write_config
which calls pci_write_config_init internally, everything breaks.

What happens if default write onfig will just update regions
on each write into PCI header? That would simplify code very much.

> +static inline void pci_write_config_update(struct pci_config_update *update)
> +{
> +    PCIDevice *d = update->d;
> +    uint32_t addr = update->addr;
> +    uint32_t val = update->val;
> +    uint32_t config_size = pci_config_size(d);
> +    int i;
> +
> +    for(i = 0; i < update->len && addr < config_size; val >>= 8, ++i, ++addr) {
> +        uint8_t wmask = d->wmask[addr];
> +        d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
> +    }
> +}
> +
> +/* check if [base, end) in configuration space is changed */
> +static inline int pci_config_changed(const struct pci_config_update *update,
> +                                     uint32_t base, uint32_t end)
> +{
> +    return memcmp(update->d->orig + base, update->d->config + base,
> +                  end - base);
> +}
> +
> +/* for convinience not to type symbol constant twice */
> +static inline int pci_config_changed_with_size(
> +    const struct pci_config_update *update, uint32_t base, uint32_t size)
> +{
> +    return pci_config_changed(update, base, base + size);
> +}
> +
>  /* lsi53c895a.c */
>  #define LSI_MAX_DEVS 7
>  
> -- 
> 1.6.0.2

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

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

On Fri, Oct 09, 2009 at 03:29:02PM +0900, Isaku Yamahata wrote:
> make pci_info_device() print out bridge's filtering value like
> io base/limit, subbus and subordinate bus.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

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

Minor comment below.

> ---
>  hw/pci.c |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/pci.h |    1 +
>  2 files changed, 56 insertions(+), 0 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 6b51bba..6ce7a40 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -864,6 +864,33 @@ static const pci_class_desc pci_class_descriptions[] =
>      { 0, NULL}
>  };
>  
> +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;

I note that here you decided to cast a value to uint32_t before & ...

> +    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 (pci_get_word(d->config + base) & PCI_MEMORY_RANGE_MASK) << 16;

But not here. Let's be consistent: both or none.

> +}
> +
> +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 void pci_info_device(PCIBus *bus, PCIDevice *d)
>  {
>      Monitor *mon = cur_mon;
> @@ -892,7 +919,35 @@ 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_config_get_io_base(d, PCI_IO_BASE, PCI_IO_BASE_UPPER16);
> +        limit = pci_config_get_io_base(d, PCI_IO_LIMIT, PCI_IO_LIMIT_UPPER16);
> +        limit |= 0xfff; /* PCI bridge spec 3.2.5.6. */
> +        monitor_printf(mon, "      IO range [0x%04"PRIx64", 0x%04"PRIx64"]\n",
> +                       base, limit);
> +
> +        base = pci_config_get_memory_base(d, PCI_MEMORY_BASE);
> +        limit= pci_config_get_memory_base(d, PCI_MEMORY_LIMIT);
> +        limit |= 0xfffff;       /* PCI bridge spec 3.2.5.1. */
> +        monitor_printf(mon,
> +                       "      memory range [0x%08"PRIx64", 0x%08"PRIx64"]\n",
> +                       base, limit);
> +
> +        base = pci_config_get_pref_base(d, PCI_PREF_MEMORY_BASE,
> +                                        PCI_PREF_BASE_UPPER32);
> +        limit = pci_config_get_pref_base(d, PCI_PREF_MEMORY_LIMIT,
> +                                         PCI_PREF_LIMIT_UPPER32);
> +        limit |= 0xfffff;       /* PCI bridge spec 3.2.5.8 */
> +        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];
> diff --git a/hw/pci.h b/hw/pci.h
> index a933ef1..80efbf9 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -173,6 +173,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_MEMORY_BASE         0x20    /* Memory range behind */
>  #define PCI_MEMORY_LIMIT        0x22
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V5 23/29] pci: pcie host and mmcfg support.
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 23/29] pci: pcie host and mmcfg support Isaku Yamahata
@ 2009-10-11 10:26   ` Michael S. Tsirkin
  0 siblings, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-11 10:26 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:56PM +0900, Isaku Yamahata wrote:
> This patch adds common routines for pcie host bridge and pcie mmcfg.
> This will be used by q35 based chipset emulation.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  Makefile.target |    2 +-
>  hw/hw.h         |   12 ++++
>  hw/pci.c        |   86 ++++++++++++++++++++++++-----
>  hw/pci.h        |   27 ++++++++-
>  hw/pcie_host.c  |  166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/pcie_host.h  |   53 ++++++++++++++++++
>  6 files changed, 327 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 cc555cb..ced7f65 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 monitor.o pci.o pci_host.o machine.o gdbstub.o
> +obj-y = vl.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 e867af4..fba3167 100644
> --- a/hw/hw.h
> +++ b/hw/hw.h
> @@ -494,6 +494,18 @@ extern const VMStateDescription vmstate_pci_device;
>              + type_check(PCIDevice,typeof_field(_state, _field))     \
>  }
>  
> +extern const VMStateDescription vmstate_pcie_device;
> +
> +#define VMSTATE_PCIE_DEVICE(_field, _state) {                        \
> +    .name       = (stringify(_field)),                               \
> +    .version_id = 2,                                                 \
> +    .size       = sizeof(PCIDevice),                                 \
> +    .vmsd       = &vmstate_pcie_device,                              \
> +    .flags      = VMS_STRUCT,                                        \
> +    .offset     = offsetof(_state, _field)                           \
> +            + type_check(PCIDevice,typeof_field(_state, _field))     \
> +}
> +
>  extern const VMStateDescription vmstate_i2c_slave;
>  
>  #define VMSTATE_I2C_SLAVE(_field, _state) {                          \
> diff --git a/hw/pci.c b/hw/pci.c
> index 99b420f..4436e12 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"
> @@ -241,18 +242,24 @@ int pci_bus_num(PCIBus *s)
>  static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
>  {
>      PCIDevice *s = container_of(pv, PCIDevice, config);
> -    uint8_t config[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;
>  }
>  
> @@ -260,6 +267,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);
>  }
>  
> @@ -276,21 +284,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_ARRAY_POINTER(config, PCIDevice, 0, vmstate_info_pci_config,
> +                              typeof_field(PCIDevice, config),
> +                              PCI_CONFIG_SPACE_SIZE),
> +        VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +const VMStateDescription vmstate_pcie_device = {
> +    .name = "PCIDevice",
> +    .version_id = 2,
> +    .minimum_version_id = 1,
> +    .minimum_version_id_old = 1,
> +    .fields      = (VMStateField []) {
> +        VMSTATE_INT32_LE(version_id, PCIDevice),
> +        VMSTATE_ARRAY_POINTER(config, PCIDevice, 0, vmstate_info_pci_config,
> +                              typeof_field(PCIDevice, config),
> +                              PCIE_CONFIG_SPACE_SIZE),
>          VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
>          VMSTATE_END_OF_LIST()
>      }
>  };
>  
> +static 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)
> @@ -399,14 +428,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;
>      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,
> @@ -427,6 +476,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);
> @@ -494,6 +544,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;
>  }
>  
> @@ -632,7 +683,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);
>  }
> @@ -641,10 +692,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);
>      }
> @@ -1015,6 +1067,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,
> @@ -1071,9 +1128,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 5b8f5cf..bfa29c8 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -166,28 +166,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;
> @@ -361,6 +364,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);
> @@ -369,6 +378,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..134d348
> --- /dev/null
> +++ b/hw/pcie_host.c
> @@ -0,0 +1,166 @@
> +/*
> + * 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)
> +{
> +    pci_dev_write_config(pcie_mmcfg_addr_to_dev(s, mmcfg_addr),
> +                         PCIE_MMCFG_CONFOFFSET(mmcfg_addr),
> +                         val, len);
> +}
> +
> +static uint32_t pcie_mmcfg_data_read(PCIBus *s,
> +                                     uint32_t mmcfg_addr, int len)
> +{
> +    return pci_dev_read_config(pcie_mmcfg_addr_to_dev(s, mmcfg_addr),
> +                               PCIE_MMCFG_CONFOFFSET(mmcfg_addr),
> +                               len);
> +}
> +
> +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,
> +};
> +
> +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..f4116b3
> --- /dev/null
> +++ b/hw/pcie_host.h
> @@ -0,0 +1,53 @@
> +/*
> + * 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 of MMCONFIG area is mapped.
> +     * PCIE_BASE_ADDR_UNMAPPED when it isn't mapped.
> +     */
> +    target_phys_addr_t  base_addr;
> +#define PCIE_BASE_ADDR_UNMAPPED  ((target_phys_addr_t)-1ULL)

can we use the PCI macro? Or is that only in .c (if the later, it's
not worth it to put it in .h).

> +
> +    /* the size of MMCONFIG area. It's host bridge dependent */
> +    target_phys_addr_t  size;
> +
> +    /* result of cpu_resiger_io_memory() to map MMCONFIG area */


typo

> +    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] 68+ messages in thread

* [Qemu-devel] Re: [PATCH V5 22/29] vmstate: add VMSTATE_ARRAY_POINTER for pointer to array.
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 22/29] vmstate: add VMSTATE_ARRAY_POINTER for pointer to array Isaku Yamahata
@ 2009-10-11 10:37   ` Michael S. Tsirkin
  0 siblings, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-11 10:37 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:55PM +0900, Isaku Yamahata wrote:
> add VMSTATE_ARRAY_POINTER for pointer to array.
> This will be used later.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/hw.h |   10 ++++++++++
>  1 files changed, 10 insertions(+), 0 deletions(-)
> 
> diff --git a/hw/hw.h b/hw/hw.h
> index 8c223f8..e867af4 100644
> --- a/hw/hw.h
> +++ b/hw/hw.h
> @@ -389,6 +389,16 @@ extern const VMStateInfo vmstate_info_buffer;
>          + type_check_array(_type,typeof_field(_state, _field),_num)  \
>  }
>  
> +#define VMSTATE_ARRAY_POINTER(_field, _state, _version, _info, _type, _size) { \
> +    .name       = (stringify(_field)),                               \
> +    .version_id = (_version),                                        \
> +    .size       = (_size),                                           \
> +    .info       = &(_info),                                          \
> +    .flags      = VMS_SINGLE | VMS_POINTER,                          \
> +    .offset     = offsetof(_state, _field)                           \
> +            + type_check(_type,typeof_field(_state, _field))         \
> +}
> +

This is really just VMSTATE_POINTER, array pointer implies char** IMO.
Also please use a wrapper so that users don't
have to repeat typeof_field(_state, _field).


>  #define VMSTATE_VARRAY(_field, _state, _field_num, _version, _info, _type) {\
>      .name       = (stringify(_field)),                               \
>      .version_id = (_version),                                        \
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V5 15/29] pci: typedef pcibus_t as uint64_t instead of uint32_t.
  2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 15/29] pci: typedef pcibus_t as uint64_t instead of uint32_t Isaku Yamahata
@ 2009-10-11 10:43   ` Michael S. Tsirkin
  2009-10-13 13:31     ` Isaku Yamahata
  0 siblings, 1 reply; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-11 10:43 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 03:28:48PM +0900, Isaku Yamahata wrote:
> This patch is preliminary for 64bit bar.
> For 64bit bar support, change pcibus_t which represents
> pci bus addr/size from uint32_t to uint64_t.
> And also change FMT_pcibus for printf.
> 
> In pci_update_mapping() checks 32bit overflow.
> So the check must be updated too.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

That's all fine, but if you look at users implementing
map io, they do: cpu_register_physical_memory()
on the address they are given.  And if target_phys_addr_t is 32 bit,
this will silently truncate the address.

So I would like to understand how this will all
work on 32 bit systems.

> ---
>  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 c0ae66a..e7f8fb4 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 8a187c2..8fbd45e 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -71,8 +71,8 @@ extern target_phys_addr_t pci_mem_base;
>  #define PCI_DEVICE_ID_VIRTIO_BALLOON     0x1002
>  #define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003
>  
> -typedef uint32_t pcibus_t;
> -#define FMT_PCIBUS                      PRIx32
> +typedef uint64_t pcibus_t;
> +#define FMT_PCIBUS                      PRIx64
>  
>  typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
>                                  uint32_t address, uint32_t data, int len);
> -- 
> 1.6.0.2

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

* [Qemu-devel] Re: [PATCH V5 07/29] pci/bridge: clean up of pci_bridge_initfn()
  2009-10-09  6:53   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-13 13:20     ` Isaku Yamahata
  2009-10-13 14:17       ` Michael S. Tsirkin
  2009-10-13 15:12       ` Blue Swirl
  0 siblings, 2 replies; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-13 13:20 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 08:53:10AM +0200, Michael S. Tsirkin wrote:
> On Fri, Oct 09, 2009 at 03:28:40PM +0900, Isaku Yamahata wrote:
> > - use symbolic constant
> > - use helper function pci_set_xxx()
> > 
> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > ---
> >  hw/pci.c |   23 ++++++++++++-----------
> >  1 files changed, 12 insertions(+), 11 deletions(-)
> > 
> > diff --git a/hw/pci.c b/hw/pci.c
> > index a66e3de..eaf471a 100644
> > --- a/hw/pci.c
> > +++ b/hw/pci.c
> > @@ -923,17 +923,18 @@ 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
> > +    pci_set_word(dev->config + PCI_COMMAND,
> > +                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
> 
> BTW, I think this is a wrong reset value: should be disabled
> by default. Fixing this needs some testing though, so
> I am not suggesting we do it in this patch. Have some time
> to fix this?

Hmm, the user of it is only apb_pci.c
I guess other magic values came from the real machine.
So one possible fix is to create apb_pci specific initialization function
and to move those initialization code into apb_pci.c leaving to
sparc guys. So we can avoid breakage.
What do you think of it?



> > +    pci_set_word(dev->config + PCI_STATUS,
> > +                 PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
> > +    dev->config[PCI_REVISION_ID] = 0x00;
> > +    dev->config[PCI_CLASS_PROG] = 0x00;
> 
> I think we can remove these two: this is the default already.

Okay.


> > +    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;
> >  }
> >  
> 

-- 
yamahata

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

* [Qemu-devel] Re: [PATCH V5 08/29] pci: s/PCI_ADDRESS_SPACE_/PCI_BASE_ADDRESS_SPACE_/ to match pci_regs.h
  2009-10-09  6:57   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-13 13:21     ` Isaku Yamahata
  0 siblings, 0 replies; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-13 13:21 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 08:57:40AM +0200, Michael S. Tsirkin wrote:
> On Fri, Oct 09, 2009 at 03:28:41PM +0900, Isaku Yamahata wrote:
> > make constants for pci base address match pci_regs.h by
> > renaming PCI_ADDRESS_SPACE_xxx to PCI_BASE_ADDRESS_SPACE_xxx.
> 
> The less macros we have to maintain by our own, the better.
> BTW, long term, do we want to split these into pci_regs.h, which can
> then be just exported from linux? Anthony?

+1.

-- 
yamahata

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

* [Qemu-devel] Re: [PATCH V5 15/29] pci: typedef pcibus_t as uint64_t instead of uint32_t.
  2009-10-11 10:43   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-13 13:31     ` Isaku Yamahata
  2009-10-13 14:39       ` Michael S. Tsirkin
  0 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-13 13:31 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Sun, Oct 11, 2009 at 12:43:12PM +0200, Michael S. Tsirkin wrote:
> On Fri, Oct 09, 2009 at 03:28:48PM +0900, Isaku Yamahata wrote:
> > This patch is preliminary for 64bit bar.
> > For 64bit bar support, change pcibus_t which represents
> > pci bus addr/size from uint32_t to uint64_t.
> > And also change FMT_pcibus for printf.
> > 
> > In pci_update_mapping() checks 32bit overflow.
> > So the check must be updated too.
> > 
> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> 
> That's all fine, but if you look at users implementing
> map io, they do: cpu_register_physical_memory()
> on the address they are given.  And if target_phys_addr_t is 32 bit,
> this will silently truncate the address.
> 
> So I would like to understand how this will all
> work on 32 bit systems.

The case is
  . BAR is memory 64bit and
  . target_phys_addr_t is 32bit and
  . bar is set to >4G.
Hmm, the case isn't checked.

It would be checked by
-	last_addr <= new_addr
+	(target_phys_addr_t)last_addr <= new_addr

I'll fix it with comments added. Nice catch.


> 
> > ---
> >  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 c0ae66a..e7f8fb4 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 8a187c2..8fbd45e 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);
> 

-- 
yamahata

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

* [Qemu-devel] Re: [PATCH V5 16/29] pci: 64bit bar support.
  2009-10-10 19:39   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-13 13:52     ` Isaku Yamahata
  2009-10-13 15:00       ` Michael S. Tsirkin
  0 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-13 13:52 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Sat, Oct 10, 2009 at 09:39:29PM +0200, Michael S. Tsirkin wrote:
> On Fri, Oct 09, 2009 at 03:28:49PM +0900, Isaku Yamahata wrote:
> > implemented pci 64bit bar support.
> > 
> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > ---
> >  hw/pci.c |   34 +++++++++++++++++++++++++++++-----
> >  hw/pci.h |    2 ++
> >  2 files changed, 31 insertions(+), 5 deletions(-)
> > 
> > diff --git a/hw/pci.c b/hw/pci.c
> > index e7f8fb4..ee3ab05 100644
> > --- a/hw/pci.c
> > +++ b/hw/pci.c
> > @@ -454,6 +454,13 @@ static int pci_unregister_device(DeviceState *dev)
> >      return 0;
> >  }
> >  
> > +static inline int pci_bar_is_mem64(const PCIIORegion *r)
> > +{
> > +    return !(r->type & PCI_BASE_ADDRESS_SPACE_IO) &&
> > +        (r->type & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
> > +        PCI_BASE_ADDRESS_MEM_TYPE_64;
> > +}
> > +
> 
> This should be just 
> return r->type & PCI_BASE_ADDRESS_MEM_TYPE_64
> and then this can be open-coded.
> PCI_BASE_ADDRESS_MEM_TYPE_MASK will also not be needed.

r->type & PCI_BASE_ADDRESS_MEM_TYPE_64 can be true for IO space.
For example, bar of IO space base with size 4 is 0x5. 
Thus PCI_BASE_ADDRESS_SPACE_IO check is necessary.


> I have a feeling I said this already, and the spec is pretty
> clear: there is exactly 1 bit that means 64 bit memory.
> No reason to check anything else.

It isn't to me because the spec says that (Table 6-4 page 226)
bit[2:3]
    00          32bit
    01          reserved(obsolete below 1M)
    10          64bit
    11          reserved

Although 11 isn't likely to be used in the future, it is safe to use mask.


> >  void pci_register_bar(PCIDevice *pci_dev, int region_num,
> >                              pcibus_t size, int type,
> >                              PCIMapIORegionFunc *map_func)
> > @@ -484,8 +491,13 @@ 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 (pci_bar_is_mem64(r)) {
> > +        pci_set_quad(pci_dev->wmask + addr, wmask);
> > +        pci_set_quad(pci_dev->cmask + addr, ~0ULL);
> > +    } else {
> > +        pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
> > +        pci_set_long(pci_dev->cmask + addr, 0xffffffff);
> > +    }
> >  }
> >  
> >  static void pci_update_mappings(PCIDevice *d)
> > @@ -513,7 +525,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 (pci_bar_is_mem64(r)) {
> > +                        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 +547,7 @@ static void pci_update_mappings(PCIDevice *d)
> >                           * Without this, PC ide doesn't work well.
> >                           * TODO: remove this work around.
> >                           */
> > -                        last_addr >= UINT32_MAX) {
> > +                        (!pci_bar_is_mem64(r) && last_addr >= UINT32_MAX)) {
> >                          new_addr = PCI_BAR_UNMAPPED;
> >                      }
> >                  } else {
> > @@ -773,8 +789,16 @@ 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 = pci_bar_is_mem64(r)? "64 bit": "32 bit";
> > +                const char *prefetch = "";
> > +
> > +                if (r->type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
> > +                    prefetch = " prefetchable";
> > +                }
> > +
> > +                monitor_printf(mon, "%s%s memory at 0x%08"FMT_PCIBUS
> >                                 " [0x%08"FMT_PCIBUS"].\n",
> > +                               type, prefetch,
> >                                 r->addr, r->addr + r->size - 1);
> >              }
> >          }
> > diff --git a/hw/pci.h b/hw/pci.h
> > index 8fbd45e..269981a 100644
> > --- a/hw/pci.h
> > +++ b/hw/pci.h
> > @@ -114,6 +114,8 @@ 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_MASK	0x06
> > +#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 */
> 

-- 
yamahata

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

* [Qemu-devel] Re: [PATCH V5 19/29] pci: split out ioport address parsing from pci configuration access logic.
  2009-10-10 19:45   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-13 14:14     ` Isaku Yamahata
  2009-10-13 14:49       ` Michael S. Tsirkin
  0 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-13 14:14 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Sat, Oct 10, 2009 at 09:45:00PM +0200, Michael S. Tsirkin wrote:
> On Fri, Oct 09, 2009 at 03:28:52PM +0900, Isaku Yamahata wrote:
> > Split out pci_data_{write, read} into two part, one is the code which
> > convert ioport address into pci device and the other is the code
> > which access PCI configuration space.
> > 
> > Later PCI express code will use the access code.
> > PCI express addressing scheme is different so that the address
> > must be parsed differently.
> > 
> > PCI:
> >  0- 7 bit: offset in the configuration space (256bytes)
> >  7-15 bit: devfn
> > 16-24 bit: bus
> > 
> > PCI express:
> >  0-11 bit: offset in the configuration space (4KBytes)
> > 12-19 bit: devfn
> > 20-28 bit: bus
> > 
> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> 
> So I think I said this already: the only useful thing that
> pci_data_read/write does is address conversion which is different for
> express.  PCI Express should do its own thing and then call
> pci_dev->config_read / pci_dev->config_write directly.
> 
> I think this will even make it possible to put express code in a
> separate file from pci.c.

Yes, I did it. And with the next patch, they will moved to pci_host.c
too as you noticed it.
Hmm, you seem to be saying that pci_dev_{write, read}_config() aren't
needed, however they are used by both pci_host.c and pcie_host.c
as follows. So introducing pci_dev_{write, read}_config() makes sense.


void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
{
    pci_dev_write_config(pci_addr_to_dev(s, addr), pci_addr_to_config(addr),
                         val, len);
}
It parses pci address and pass it to lower function.


With the patch of "pci: pcie host and mmcfg support.",
pcie counter part is as follows.
static void pcie_mmcfg_data_write(PCIBus *s,
                                  uint32_t mmcfg_addr, uint32_t val, int len)
{
    pci_dev_write_config(pcie_mmcfg_addr_to_dev(s, mmcfg_addr),
                         PCIE_MMCFG_CONFOFFSET(mmcfg_addr),
                         val, len);
}
It parses pcie mmconfig address and pass it to lower function.


> 
> > ---
> >  hw/pci.c |   80 ++++++++++++++++++++++++++++++-------------------------------
> >  1 files changed, 39 insertions(+), 41 deletions(-)
> > 
> > diff --git a/hw/pci.c b/hw/pci.c
> > index 0021c96..d472b58 100644
> > --- a/hw/pci.c
> > +++ b/hw/pci.c
> > @@ -654,46 +654,24 @@ 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 & 0xff;
> > -}
> > -
> > -void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> > +static void pci_dev_write_config(PCIDevice *pci_dev,
> > +                                 uint32_t config_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);
> > +    assert(len == 1 || len == 2 || len == 4);
> >      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_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRI32x" len=%d\n",
> > +                __func__, pci_dev->name, config_addr, val, len);
> >      pci_dev->config_write(pci_dev, config_addr, val, len);
> >  }
> >  
> > -uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> > +static uint32_t pci_dev_read_config(PCIDevice *pci_dev,
> > +                                    uint32_t config_addr, int len)
> >  {
> > -    PCIBus *s = opaque;
> > -    PCIDevice *pci_dev;
> > -    int config_addr;
> >      uint32_t val;
> >  
> > -    pci_dev = pci_addr_to_dev(s, addr);
> > +    assert(len == 1 || len == 2 || len == 4);
> >      if (!pci_dev) {
> >          switch(len) {
> >          case 1:
> > @@ -707,20 +685,40 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> >              val = 0xffffffff;
> >              break;
> >          }
> > -        goto the_end;
> > +    } else {
> > +        val = pci_dev->config_read(pci_dev, config_addr, len);
> > +        PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
> > +                    __func__, pci_dev->name, config_addr, val, len);
> >      }
> > -    config_addr = 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;
> >  }
> >  
> > +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 & 0xff;
> > +}
> > +
> > +void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> > +{
> > +    PCIBus *s = opaque;
> > +    pci_dev_write_config(pci_addr_to_dev(s, addr), pci_addr_to_config(addr),
> > +                         val, len);
> > +}
> > +
> > +uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> > +{
> > +    PCIBus *s = opaque;
> > +    return pci_dev_read_config(pci_addr_to_dev(s, addr),
> > +                               pci_addr_to_config(addr), len);
> > +}
> > +
> >  /***********************************************************/
> >  /* generic PCI irq support */
> >  
> 

-- 
yamahata

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

* [Qemu-devel] Re: [PATCH V5 07/29] pci/bridge: clean up of pci_bridge_initfn()
  2009-10-13 13:20     ` Isaku Yamahata
@ 2009-10-13 14:17       ` Michael S. Tsirkin
  2009-10-13 15:12       ` Blue Swirl
  1 sibling, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-13 14:17 UTC (permalink / raw)
  To: Isaku Yamahata, blauwirbel; +Cc: qemu-devel

On Tue, Oct 13, 2009 at 10:20:07PM +0900, Isaku Yamahata wrote:
> On Fri, Oct 09, 2009 at 08:53:10AM +0200, Michael S. Tsirkin wrote:
> > On Fri, Oct 09, 2009 at 03:28:40PM +0900, Isaku Yamahata wrote:
> > > - use symbolic constant
> > > - use helper function pci_set_xxx()
> > > 
> > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > > ---
> > >  hw/pci.c |   23 ++++++++++++-----------
> > >  1 files changed, 12 insertions(+), 11 deletions(-)
> > > 
> > > diff --git a/hw/pci.c b/hw/pci.c
> > > index a66e3de..eaf471a 100644
> > > --- a/hw/pci.c
> > > +++ b/hw/pci.c
> > > @@ -923,17 +923,18 @@ 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
> > > +    pci_set_word(dev->config + PCI_COMMAND,
> > > +                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
> > 
> > BTW, I think this is a wrong reset value: should be disabled
> > by default. Fixing this needs some testing though, so
> > I am not suggesting we do it in this patch. Have some time
> > to fix this?
> 
> Hmm, the user of it is only apb_pci.c
> I guess other magic values came from the real machine.
> So one possible fix is to create apb_pci specific initialization function
> and to move those initialization code into apb_pci.c leaving to
> sparc guys. So we can avoid breakage.
> What do you think of it?

That'll work, but let's start with Cc relevant people.  The issue here is
that the bridge is inited with memory enabled which is out of spec, but
we are concerned what fixing this will do - in the past such fixes
sometimes triggered BIOS bugs.  Anyone can test a fix for this?

> 
> 
> > > +    pci_set_word(dev->config + PCI_STATUS,
> > > +                 PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
> > > +    dev->config[PCI_REVISION_ID] = 0x00;
> > > +    dev->config[PCI_CLASS_PROG] = 0x00;
> > 
> > I think we can remove these two: this is the default already.
> 
> Okay.
> 
> 
> > > +    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;
> > >  }
> > >  
> > 
> 
> -- 
> yamahata

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

* [Qemu-devel] Re: [PATCH V5 28/29] pci: initialize pci config headers depending it pci header type.
  2009-10-09 10:42   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-13 14:31     ` Isaku Yamahata
  2009-10-13 14:52       ` Michael S. Tsirkin
  2009-10-13 15:06       ` Michael S. Tsirkin
  0 siblings, 2 replies; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-13 14:31 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 12:42:32PM +0200, Michael S. Tsirkin wrote:
> On Fri, Oct 09, 2009 at 03:29:01PM +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.
> 
> It was? Can you investigate please?
> Spec says most of these are optional.

Linux kernel thinks the bridge doesn't support to forwarding
bus command disabling devices behind the bridge.
If pci-ide is behind the bridge, kernel panics failing to find
root file system.


> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > ---
> >  hw/cirrus_vga.c |    1 -
> >  hw/pci.c        |   62 ++++++++++++++++++++++++++++++++++++++++++++++++------
> >  hw/pci.h        |   33 +++++++++++++++++++++++++++++
> >  3 files changed, 88 insertions(+), 8 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 3a17cd8..6b51bba 100644
> > --- a/hw/pci.c
> > +++ b/hw/pci.c
> > @@ -430,14 +430,52 @@ static void pci_init_wmask(PCIDevice *dev)
> >      int i;
> >      int config_size = pci_config_size(dev);
> >  
> > +    pci_set_word(dev->wmask + PCI_COMMAND,
> > +                 PCI_COMMAND_IO |
> > +                 PCI_COMMAND_MEMORY |
> > +                 PCI_COMMAND_MASTER |
> > +                 PCI_COMMAND_SPECIAL |
> > +                 PCI_COMMAND_INVALIDATE |
> > +                 PCI_COMMAND_VGA_PALETTE |
> > +                 PCI_COMMAND_PARITY |
> > +                 PCI_COMMAND_WAIT |
> > +                 PCI_COMMAND_SERR |
> > +                 PCI_COMMAND_FAST_BACK |
> > +                 PCI_COMMAND_INTX_DISABLE);
> 
> At least INTX disable must not be writeable unless
> we implement the masking functionality, and we don't

OK.

> > +
> >      dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
> >      dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
> > -    dev->wmask[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY
> > -                              | PCI_COMMAND_MASTER;
> > -    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
> > +
> > +    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; i++)
> 
> I dislike this change. We don't use the old value so ++i
> is cleaner.

Ok. It was an accidental one change I didn't meant.


> >          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);
> > +
> > +    /* sec status isn't emulated (yet) */
> > +    d->wmask[PCI_SEC_STATUS] = 0;
> 
> 0 is default value. Replace with /* TODO: emulate PCI_SEC_STATUS */
>  (which bits do we have to emulate there?)

Ok.


> > +    /* base and limit */
> > +    d->wmask[PCI_IO_BASE] = PCI_IO_RANGE_MASK & 0xff;
> > +    d->wmask[PCI_IO_LIMIT] = PCI_IO_RANGE_MASK & 0xff;
> 
> 
> & 0xff not necessary.

OK.

> > +    pci_set_word(d->wmask + PCI_MEMORY_BASE,
> > +                 PCI_MEMORY_RANGE_MASK & 0xffff);
> > +    pci_set_word(d->wmask + PCI_MEMORY_LIMIT,
> > +                 PCI_MEMORY_RANGE_MASK & 0xffff);
> > +    pci_set_word(d->wmask + PCI_PREF_MEMORY_BASE,
> > +                 PCI_PREF_RANGE_MASK & 0xffff);
> > +    pci_set_word(d->wmask + PCI_PREF_MEMORY_LIMIT,
> > +                 PCI_PREF_RANGE_MASK & 0xffff);
> > +    pci_set_long(d->wmask + PCI_PREF_BASE_UPPER32, 0xffffffff);
> > +    pci_set_long(d->wmask + PCI_PREF_LIMIT_UPPER32, 0xffffffff);
> > +
> > +    pci_set_word(d->wmask + PCI_BRIDGE_CONTROL, 0xffff);
> 
> Can we just memset(xxx, 0xff, yyy) the whole range,
> and just clear a single byte that is 0?

It can be done for PCI_RREF_{BASE, LIMIT}_UPPER32 with length 4.
However all base/limit needs to be 0xfff0 or 0xfffffff0.
(not 0, but 0xf0) So it doesn't make code cleaner much.



> > +}
> > +
> >  static void pci_config_alloc(PCIDevice *pci_dev)
> >  {
> >      int config_size = pci_config_size(pci_dev);
> > @@ -462,7 +500,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) {
> > @@ -479,9 +518,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;
> > @@ -504,7 +550,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)
> > @@ -1093,7 +1140,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 3cd93e9..a933ef1 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 */
> > @@ -162,7 +170,25 @@ typedef struct PCIIORegion {
> >  
> >  /* Header type 1 (PCI-to-PCI bridges) */
> >  #define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
> > +#define PCI_SEC_LATENCY_TIMER   0x1b    /* Latency timer for secondary interface */
> > +#define PCI_IO_BASE             0x1c    /* I/O range behind the bridge */
> > +#define PCI_IO_LIMIT            0x1d
> > +#define  PCI_IO_RANGE_MASK      (~0x0fUL)
> > +#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_PREF_LIMIT_UPPER32  0x2c
> > +#define PCI_IO_BASE_UPPER16     0x30    /* Upper half of I/O addresses */
> > +#define PCI_IO_LIMIT_UPPER16    0x32
> > +/* 0x34 same as for htype 0 */
> > +/* 0x35-0x3b is reserved */
> >  #define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
> > +/* 0x3c-0x3d are same as for htype 0 */
> > +#define PCI_BRIDGE_CONTROL      0x3e
> >  
> >  /* Size of the standard PCI config header */
> >  #define PCI_CONFIG_HEADER_SIZE 0x40
> > @@ -370,6 +396,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
> 

-- 
yamahata

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

* [Qemu-devel] Re: [PATCH V5 15/29] pci: typedef pcibus_t as uint64_t instead of uint32_t.
  2009-10-13 13:31     ` Isaku Yamahata
@ 2009-10-13 14:39       ` Michael S. Tsirkin
  2009-10-14  4:35         ` Isaku Yamahata
  0 siblings, 1 reply; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-13 14:39 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Tue, Oct 13, 2009 at 10:31:33PM +0900, Isaku Yamahata wrote:
> On Sun, Oct 11, 2009 at 12:43:12PM +0200, Michael S. Tsirkin wrote:
> > On Fri, Oct 09, 2009 at 03:28:48PM +0900, Isaku Yamahata wrote:
> > > This patch is preliminary for 64bit bar.
> > > For 64bit bar support, change pcibus_t which represents
> > > pci bus addr/size from uint32_t to uint64_t.
> > > And also change FMT_pcibus for printf.
> > > 
> > > In pci_update_mapping() checks 32bit overflow.
> > > So the check must be updated too.
> > > 
> > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > 
> > That's all fine, but if you look at users implementing
> > map io, they do: cpu_register_physical_memory()
> > on the address they are given.  And if target_phys_addr_t is 32 bit,
> > this will silently truncate the address.
> > 
> > So I would like to understand how this will all
> > work on 32 bit systems.
> 
> The case is
>   . BAR is memory 64bit and
>   . target_phys_addr_t is 32bit and
>   . bar is set to >4G.
> Hmm, the case isn't checked.
> 
> It would be checked by
> -	last_addr <= new_addr
> +	(target_phys_addr_t)last_addr <= new_addr

That's pretty tricky. Can we just convert everything into
64 bit unconditionally and just do simple range checks?

> 
> I'll fix it with comments added. Nice catch.

Is this the right thing to do though?
I think 32 bit CPU might address something like 64G
memory of highmem support, so a 64 bit value might
actually be valid.

Let's step back and understand what the motivation is?
Maybe declaring all bars as 32 bit for 32 bit targets is enough?

> 
> > 
> > > ---
> > >  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 c0ae66a..e7f8fb4 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 8a187c2..8fbd45e 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);
> > 
> 
> -- 
> yamahata

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

* [Qemu-devel] Re: [PATCH V5 19/29] pci: split out ioport address parsing from pci configuration access logic.
  2009-10-13 14:14     ` Isaku Yamahata
@ 2009-10-13 14:49       ` Michael S. Tsirkin
  0 siblings, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-13 14:49 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Tue, Oct 13, 2009 at 11:14:11PM +0900, Isaku Yamahata wrote:
> On Sat, Oct 10, 2009 at 09:45:00PM +0200, Michael S. Tsirkin wrote:
> > On Fri, Oct 09, 2009 at 03:28:52PM +0900, Isaku Yamahata wrote:
> > > Split out pci_data_{write, read} into two part, one is the code which
> > > convert ioport address into pci device and the other is the code
> > > which access PCI configuration space.
> > > 
> > > Later PCI express code will use the access code.
> > > PCI express addressing scheme is different so that the address
> > > must be parsed differently.
> > > 
> > > PCI:
> > >  0- 7 bit: offset in the configuration space (256bytes)
> > >  7-15 bit: devfn
> > > 16-24 bit: bus
> > > 
> > > PCI express:
> > >  0-11 bit: offset in the configuration space (4KBytes)
> > > 12-19 bit: devfn
> > > 20-28 bit: bus
> > > 
> > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > 
> > So I think I said this already: the only useful thing that
> > pci_data_read/write does is address conversion which is different for
> > express.  PCI Express should do its own thing and then call
> > pci_dev->config_read / pci_dev->config_write directly.
> > 
> > I think this will even make it possible to put express code in a
> > separate file from pci.c.
> 
> Yes, I did it. And with the next patch, they will moved to pci_host.c
> too as you noticed it.
> Hmm, you seem to be saying that pci_dev_{write, read}_config() aren't
> needed, however they are used by both pci_host.c and pcie_host.c
> as follows.

Yes, but if you look at them they do not do antyhing useful,
just call dev->config_write. So open-code and be done with it.

> So introducing pci_dev_{write, read}_config() makes sense.
> 
> 
> void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
> {
>     pci_dev_write_config(pci_addr_to_dev(s, addr), pci_addr_to_config(addr),
>                          val, len);
> }
> It parses pci address and pass it to lower function.
> 
> 
> With the patch of "pci: pcie host and mmcfg support.",
> pcie counter part is as follows.
> static void pcie_mmcfg_data_write(PCIBus *s,
>                                   uint32_t mmcfg_addr, uint32_t val, int len)
> {
>     pci_dev_write_config(pcie_mmcfg_addr_to_dev(s, mmcfg_addr),
>                          PCIE_MMCFG_CONFOFFSET(mmcfg_addr),
>                          val, len);
> }
> It parses pcie mmconfig address and pass it to lower function.

Yes but the lower function does nothing, so just opencode it.

So that will be
void pci_data_write(PCIBus *s,
		    uint32_t addr, uint32_t val, int len)
{
	PCIDevice *dev = pci_addr_to_dev(s, addr);
	if (!dev)
		return;
	dev->config_write(dev, pci_addr_to_config(addr), val, len);
}

and separately
static void pcie_mmcfg_data_write(PCIBus *s,
                                  uint32_t mmcfg_addr, uint32_t val, int len)
{
	PCIDevice *dev = pcie_mmcfg_addr_to_dev(s, mmcfg_addr);
	if (!dev)
		return;
	dev->config_write(dev, PCIE_MMCFG_CONFOFFSET(mmcfg_addr), val, len);
}

> > 
> > > ---
> > >  hw/pci.c |   80 ++++++++++++++++++++++++++++++-------------------------------
> > >  1 files changed, 39 insertions(+), 41 deletions(-)
> > > 
> > > diff --git a/hw/pci.c b/hw/pci.c
> > > index 0021c96..d472b58 100644
> > > --- a/hw/pci.c
> > > +++ b/hw/pci.c
> > > @@ -654,46 +654,24 @@ 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 & 0xff;
> > > -}
> > > -
> > > -void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> > > +static void pci_dev_write_config(PCIDevice *pci_dev,
> > > +                                 uint32_t config_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);
> > > +    assert(len == 1 || len == 2 || len == 4);
> > >      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_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRI32x" len=%d\n",
> > > +                __func__, pci_dev->name, config_addr, val, len);
> > >      pci_dev->config_write(pci_dev, config_addr, val, len);
> > >  }
> > >  
> > > -uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> > > +static uint32_t pci_dev_read_config(PCIDevice *pci_dev,
> > > +                                    uint32_t config_addr, int len)
> > >  {
> > > -    PCIBus *s = opaque;
> > > -    PCIDevice *pci_dev;
> > > -    int config_addr;
> > >      uint32_t val;
> > >  
> > > -    pci_dev = pci_addr_to_dev(s, addr);
> > > +    assert(len == 1 || len == 2 || len == 4);
> > >      if (!pci_dev) {
> > >          switch(len) {
> > >          case 1:
> > > @@ -707,20 +685,40 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> > >              val = 0xffffffff;
> > >              break;
> > >          }
> > > -        goto the_end;
> > > +    } else {
> > > +        val = pci_dev->config_read(pci_dev, config_addr, len);
> > > +        PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
> > > +                    __func__, pci_dev->name, config_addr, val, len);
> > >      }
> > > -    config_addr = 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;
> > >  }
> > >  
> > > +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 & 0xff;
> > > +}
> > > +
> > > +void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> > > +{
> > > +    PCIBus *s = opaque;
> > > +    pci_dev_write_config(pci_addr_to_dev(s, addr), pci_addr_to_config(addr),
> > > +                         val, len);
> > > +}
> > > +
> > > +uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> > > +{
> > > +    PCIBus *s = opaque;
> > > +    return pci_dev_read_config(pci_addr_to_dev(s, addr),
> > > +                               pci_addr_to_config(addr), len);
> > > +}
> > > +
> > >  /***********************************************************/
> > >  /* generic PCI irq support */
> > >  
> > 
> 
> -- 
> yamahata

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

* [Qemu-devel] Re: [PATCH V5 28/29] pci: initialize pci config headers depending it pci header type.
  2009-10-13 14:31     ` Isaku Yamahata
@ 2009-10-13 14:52       ` Michael S. Tsirkin
  2009-10-13 15:06       ` Michael S. Tsirkin
  1 sibling, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-13 14:52 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Tue, Oct 13, 2009 at 11:31:23PM +0900, Isaku Yamahata wrote:
> On Fri, Oct 09, 2009 at 12:42:32PM +0200, Michael S. Tsirkin wrote:
> > On Fri, Oct 09, 2009 at 03:29:01PM +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.
> > 
> > It was? Can you investigate please?
> > Spec says most of these are optional.
> 
> Linux kernel thinks the bridge doesn't support to forwarding
> bus command disabling devices behind the bridge.

Sorry, had trouble parsing this sentence.


> If pci-ide is behind the bridge, kernel panics failing to find
> root file system.
> 

Yes, but why does it help to make bus master enable writeable
when we never initiate pci transactions from bridge itself?

> > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > > ---
> > >  hw/cirrus_vga.c |    1 -
> > >  hw/pci.c        |   62 ++++++++++++++++++++++++++++++++++++++++++++++++------
> > >  hw/pci.h        |   33 +++++++++++++++++++++++++++++
> > >  3 files changed, 88 insertions(+), 8 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 3a17cd8..6b51bba 100644
> > > --- a/hw/pci.c
> > > +++ b/hw/pci.c
> > > @@ -430,14 +430,52 @@ static void pci_init_wmask(PCIDevice *dev)
> > >      int i;
> > >      int config_size = pci_config_size(dev);
> > >  
> > > +    pci_set_word(dev->wmask + PCI_COMMAND,
> > > +                 PCI_COMMAND_IO |
> > > +                 PCI_COMMAND_MEMORY |
> > > +                 PCI_COMMAND_MASTER |
> > > +                 PCI_COMMAND_SPECIAL |
> > > +                 PCI_COMMAND_INVALIDATE |
> > > +                 PCI_COMMAND_VGA_PALETTE |
> > > +                 PCI_COMMAND_PARITY |
> > > +                 PCI_COMMAND_WAIT |
> > > +                 PCI_COMMAND_SERR |
> > > +                 PCI_COMMAND_FAST_BACK |
> > > +                 PCI_COMMAND_INTX_DISABLE);
> > 
> > At least INTX disable must not be writeable unless
> > we implement the masking functionality, and we don't
> 
> OK.
> 
> > > +
> > >      dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
> > >      dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
> > > -    dev->wmask[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY
> > > -                              | PCI_COMMAND_MASTER;
> > > -    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
> > > +
> > > +    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; i++)
> > 
> > I dislike this change. We don't use the old value so ++i
> > is cleaner.
> 
> Ok. It was an accidental one change I didn't meant.
> 
> 
> > >          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);
> > > +
> > > +    /* sec status isn't emulated (yet) */
> > > +    d->wmask[PCI_SEC_STATUS] = 0;
> > 
> > 0 is default value. Replace with /* TODO: emulate PCI_SEC_STATUS */
> >  (which bits do we have to emulate there?)
> 
> Ok.
> 
> 
> > > +    /* base and limit */
> > > +    d->wmask[PCI_IO_BASE] = PCI_IO_RANGE_MASK & 0xff;
> > > +    d->wmask[PCI_IO_LIMIT] = PCI_IO_RANGE_MASK & 0xff;
> > 
> > 
> > & 0xff not necessary.
> 
> OK.
> 
> > > +    pci_set_word(d->wmask + PCI_MEMORY_BASE,
> > > +                 PCI_MEMORY_RANGE_MASK & 0xffff);
> > > +    pci_set_word(d->wmask + PCI_MEMORY_LIMIT,
> > > +                 PCI_MEMORY_RANGE_MASK & 0xffff);
> > > +    pci_set_word(d->wmask + PCI_PREF_MEMORY_BASE,
> > > +                 PCI_PREF_RANGE_MASK & 0xffff);
> > > +    pci_set_word(d->wmask + PCI_PREF_MEMORY_LIMIT,
> > > +                 PCI_PREF_RANGE_MASK & 0xffff);
> > > +    pci_set_long(d->wmask + PCI_PREF_BASE_UPPER32, 0xffffffff);
> > > +    pci_set_long(d->wmask + PCI_PREF_LIMIT_UPPER32, 0xffffffff);
> > > +
> > > +    pci_set_word(d->wmask + PCI_BRIDGE_CONTROL, 0xffff);
> > 
> > Can we just memset(xxx, 0xff, yyy) the whole range,
> > and just clear a single byte that is 0?
> 
> It can be done for PCI_RREF_{BASE, LIMIT}_UPPER32 with length 4.
> However all base/limit needs to be 0xfff0 or 0xfffffff0.
> (not 0, but 0xf0) So it doesn't make code cleaner much.
> 
> 
> 
> > > +}
> > > +
> > >  static void pci_config_alloc(PCIDevice *pci_dev)
> > >  {
> > >      int config_size = pci_config_size(pci_dev);
> > > @@ -462,7 +500,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) {
> > > @@ -479,9 +518,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;
> > > @@ -504,7 +550,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)
> > > @@ -1093,7 +1140,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 3cd93e9..a933ef1 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 */
> > > @@ -162,7 +170,25 @@ typedef struct PCIIORegion {
> > >  
> > >  /* Header type 1 (PCI-to-PCI bridges) */
> > >  #define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
> > > +#define PCI_SEC_LATENCY_TIMER   0x1b    /* Latency timer for secondary interface */
> > > +#define PCI_IO_BASE             0x1c    /* I/O range behind the bridge */
> > > +#define PCI_IO_LIMIT            0x1d
> > > +#define  PCI_IO_RANGE_MASK      (~0x0fUL)
> > > +#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_PREF_LIMIT_UPPER32  0x2c
> > > +#define PCI_IO_BASE_UPPER16     0x30    /* Upper half of I/O addresses */
> > > +#define PCI_IO_LIMIT_UPPER16    0x32
> > > +/* 0x34 same as for htype 0 */
> > > +/* 0x35-0x3b is reserved */
> > >  #define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
> > > +/* 0x3c-0x3d are same as for htype 0 */
> > > +#define PCI_BRIDGE_CONTROL      0x3e
> > >  
> > >  /* Size of the standard PCI config header */
> > >  #define PCI_CONFIG_HEADER_SIZE 0x40
> > > @@ -370,6 +396,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
> > 
> 
> -- 
> yamahata

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

* [Qemu-devel] Re: [PATCH V5 16/29] pci: 64bit bar support.
  2009-10-13 13:52     ` Isaku Yamahata
@ 2009-10-13 15:00       ` Michael S. Tsirkin
  0 siblings, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-13 15:00 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Tue, Oct 13, 2009 at 10:52:54PM +0900, Isaku Yamahata wrote:
> On Sat, Oct 10, 2009 at 09:39:29PM +0200, Michael S. Tsirkin wrote:
> > On Fri, Oct 09, 2009 at 03:28:49PM +0900, Isaku Yamahata wrote:
> > > implemented pci 64bit bar support.
> > > 
> > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > > ---
> > >  hw/pci.c |   34 +++++++++++++++++++++++++++++-----
> > >  hw/pci.h |    2 ++
> > >  2 files changed, 31 insertions(+), 5 deletions(-)
> > > 
> > > diff --git a/hw/pci.c b/hw/pci.c
> > > index e7f8fb4..ee3ab05 100644
> > > --- a/hw/pci.c
> > > +++ b/hw/pci.c
> > > @@ -454,6 +454,13 @@ static int pci_unregister_device(DeviceState *dev)
> > >      return 0;
> > >  }
> > >  
> > > +static inline int pci_bar_is_mem64(const PCIIORegion *r)
> > > +{
> > > +    return !(r->type & PCI_BASE_ADDRESS_SPACE_IO) &&
> > > +        (r->type & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
> > > +        PCI_BASE_ADDRESS_MEM_TYPE_64;
> > > +}
> > > +
> > 
> > This should be just 
> > return r->type & PCI_BASE_ADDRESS_MEM_TYPE_64

Or r->type == PCI_BASE_ADDRESS_MEM_TYPE_64
if you like that more.

> > and then this can be open-coded.

which is the important bit :)

> > PCI_BASE_ADDRESS_MEM_TYPE_MASK will also not be needed.
> 
> r->type & PCI_BASE_ADDRESS_MEM_TYPE_64 can be true for IO space.
> For example, bar of IO space base with size 4 is 0x5. 

I don't think we ever leak bits from BAR into r->type in this way.
Do we?

> Thus PCI_BASE_ADDRESS_SPACE_IO check is necessary.
> 
> 
> > I have a feeling I said this already, and the spec is pretty
> > clear: there is exactly 1 bit that means 64 bit memory.
> > No reason to check anything else.
> 
> It isn't to me because the spec says that (Table 6-4 page 226)
> bit[2:3]
>     00          32bit
>     01          reserved(obsolete below 1M)
>     10          64bit
>     11          reserved
> 
> Although 11 isn't likely to be used in the future, it is safe to use mask.

Well, if you care about this, I would say the right place to check for
unknown region types is when registering them, not at a random time when
we use them later.

> > >  void pci_register_bar(PCIDevice *pci_dev, int region_num,
> > >                              pcibus_t size, int type,
> > >                              PCIMapIORegionFunc *map_func)
> > > @@ -484,8 +491,13 @@ 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 (pci_bar_is_mem64(r)) {
> > > +        pci_set_quad(pci_dev->wmask + addr, wmask);
> > > +        pci_set_quad(pci_dev->cmask + addr, ~0ULL);
> > > +    } else {
> > > +        pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
> > > +        pci_set_long(pci_dev->cmask + addr, 0xffffffff);
> > > +    }
> > >  }
> > >  
> > >  static void pci_update_mappings(PCIDevice *d)
> > > @@ -513,7 +525,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 (pci_bar_is_mem64(r)) {
> > > +                        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 +547,7 @@ static void pci_update_mappings(PCIDevice *d)
> > >                           * Without this, PC ide doesn't work well.
> > >                           * TODO: remove this work around.
> > >                           */
> > > -                        last_addr >= UINT32_MAX) {
> > > +                        (!pci_bar_is_mem64(r) && last_addr >= UINT32_MAX)) {
> > >                          new_addr = PCI_BAR_UNMAPPED;
> > >                      }
> > >                  } else {
> > > @@ -773,8 +789,16 @@ 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 = pci_bar_is_mem64(r)? "64 bit": "32 bit";
> > > +                const char *prefetch = "";
> > > +
> > > +                if (r->type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
> > > +                    prefetch = " prefetchable";
> > > +                }
> > > +
> > > +                monitor_printf(mon, "%s%s memory at 0x%08"FMT_PCIBUS
> > >                                 " [0x%08"FMT_PCIBUS"].\n",
> > > +                               type, prefetch,
> > >                                 r->addr, r->addr + r->size - 1);
> > >              }
> > >          }
> > > diff --git a/hw/pci.h b/hw/pci.h
> > > index 8fbd45e..269981a 100644
> > > --- a/hw/pci.h
> > > +++ b/hw/pci.h
> > > @@ -114,6 +114,8 @@ 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_MASK	0x06
> > > +#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 */
> > 
> 
> -- 
> yamahata

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

* [Qemu-devel] Re: [PATCH V5 28/29] pci: initialize pci config headers depending it pci header type.
  2009-10-13 14:31     ` Isaku Yamahata
  2009-10-13 14:52       ` Michael S. Tsirkin
@ 2009-10-13 15:06       ` Michael S. Tsirkin
  1 sibling, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-13 15:06 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Tue, Oct 13, 2009 at 11:31:23PM +0900, Isaku Yamahata wrote:
> On Fri, Oct 09, 2009 at 12:42:32PM +0200, Michael S. Tsirkin wrote:
> > On Fri, Oct 09, 2009 at 03:29:01PM +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.
> > 
> > It was? Can you investigate please?
> > Spec says most of these are optional.
> 
> Linux kernel thinks the bridge doesn't support to forwarding
> bus command disabling devices behind the bridge.
> If pci-ide is behind the bridge, kernel panics failing to find
> root file system.
> 
> 
> > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > > ---
> > >  hw/cirrus_vga.c |    1 -
> > >  hw/pci.c        |   62 ++++++++++++++++++++++++++++++++++++++++++++++++------
> > >  hw/pci.h        |   33 +++++++++++++++++++++++++++++
> > >  3 files changed, 88 insertions(+), 8 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 3a17cd8..6b51bba 100644
> > > --- a/hw/pci.c
> > > +++ b/hw/pci.c
> > > @@ -430,14 +430,52 @@ static void pci_init_wmask(PCIDevice *dev)
> > >      int i;
> > >      int config_size = pci_config_size(dev);
> > >  
> > > +    pci_set_word(dev->wmask + PCI_COMMAND,
> > > +                 PCI_COMMAND_IO |
> > > +                 PCI_COMMAND_MEMORY |
> > > +                 PCI_COMMAND_MASTER |
> > > +                 PCI_COMMAND_SPECIAL |
> > > +                 PCI_COMMAND_INVALIDATE |
> > > +                 PCI_COMMAND_VGA_PALETTE |
> > > +                 PCI_COMMAND_PARITY |
> > > +                 PCI_COMMAND_WAIT |
> > > +                 PCI_COMMAND_SERR |
> > > +                 PCI_COMMAND_FAST_BACK |
> > > +                 PCI_COMMAND_INTX_DISABLE);
> > 
> > At least INTX disable must not be writeable unless
> > we implement the masking functionality, and we don't
> 
> OK.
> 
> > > +
> > >      dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
> > >      dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
> > > -    dev->wmask[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY
> > > -                              | PCI_COMMAND_MASTER;
> > > -    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
> > > +
> > > +    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; i++)
> > 
> > I dislike this change. We don't use the old value so ++i
> > is cleaner.
> 
> Ok. It was an accidental one change I didn't meant.
> 
> 
> > >          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);
> > > +
> > > +    /* sec status isn't emulated (yet) */
> > > +    d->wmask[PCI_SEC_STATUS] = 0;
> > 
> > 0 is default value. Replace with /* TODO: emulate PCI_SEC_STATUS */
> >  (which bits do we have to emulate there?)
> 
> Ok.
> 
> 
> > > +    /* base and limit */
> > > +    d->wmask[PCI_IO_BASE] = PCI_IO_RANGE_MASK & 0xff;
> > > +    d->wmask[PCI_IO_LIMIT] = PCI_IO_RANGE_MASK & 0xff;
> > 
> > 
> > & 0xff not necessary.
> 
> OK.
> 
> > > +    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);

& 0xffff is not necessary.

> > > +    pci_set_long(d->wmask + PCI_PREF_BASE_UPPER32, 0xffffffff);
> > > +    pci_set_long(d->wmask + PCI_PREF_LIMIT_UPPER32, 0xffffffff);
> > > +
> > > +    pci_set_word(d->wmask + PCI_BRIDGE_CONTROL, 0xffff);
> > 
> > Can we just memset(xxx, 0xff, yyy) the whole range,
> > and just clear a single byte that is 0?
> 
> It can be done for PCI_RREF_{BASE, LIMIT}_UPPER32 with length 4.

Length 8 actually (they sit together).

> However all base/limit needs to be 0xfff0 or 0xfffffff0.

That's true, I forgot.

> (not 0, but 0xf0) So it doesn't make code cleaner much.



> 
> 
> > > +}
> > > +
> > >  static void pci_config_alloc(PCIDevice *pci_dev)
> > >  {
> > >      int config_size = pci_config_size(pci_dev);
> > > @@ -462,7 +500,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) {
> > > @@ -479,9 +518,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;
> > > @@ -504,7 +550,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)
> > > @@ -1093,7 +1140,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 3cd93e9..a933ef1 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 */
> > > @@ -162,7 +170,25 @@ typedef struct PCIIORegion {
> > >  
> > >  /* Header type 1 (PCI-to-PCI bridges) */
> > >  #define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
> > > +#define PCI_SEC_LATENCY_TIMER   0x1b    /* Latency timer for secondary interface */
> > > +#define PCI_IO_BASE             0x1c    /* I/O range behind the bridge */
> > > +#define PCI_IO_LIMIT            0x1d
> > > +#define  PCI_IO_RANGE_MASK      (~0x0fUL)
> > > +#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_PREF_LIMIT_UPPER32  0x2c
> > > +#define PCI_IO_BASE_UPPER16     0x30    /* Upper half of I/O addresses */
> > > +#define PCI_IO_LIMIT_UPPER16    0x32
> > > +/* 0x34 same as for htype 0 */
> > > +/* 0x35-0x3b is reserved */
> > >  #define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
> > > +/* 0x3c-0x3d are same as for htype 0 */
> > > +#define PCI_BRIDGE_CONTROL      0x3e
> > >  
> > >  /* Size of the standard PCI config header */
> > >  #define PCI_CONFIG_HEADER_SIZE 0x40
> > > @@ -370,6 +396,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
> > 
> 
> -- 
> yamahata

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

* Re: [Qemu-devel] Re: [PATCH V5 07/29] pci/bridge: clean up of pci_bridge_initfn()
  2009-10-13 13:20     ` Isaku Yamahata
  2009-10-13 14:17       ` Michael S. Tsirkin
@ 2009-10-13 15:12       ` Blue Swirl
  2009-10-13 15:26         ` Michael S. Tsirkin
  1 sibling, 1 reply; 68+ messages in thread
From: Blue Swirl @ 2009-10-13 15:12 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel, Michael S. Tsirkin

On Tue, Oct 13, 2009 at 4:20 PM, Isaku Yamahata <yamahata@valinux.co.jp> wrote:
> On Fri, Oct 09, 2009 at 08:53:10AM +0200, Michael S. Tsirkin wrote:
>> On Fri, Oct 09, 2009 at 03:28:40PM +0900, Isaku Yamahata wrote:
>> > - use symbolic constant
>> > - use helper function pci_set_xxx()
>> >
>> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
>> > ---
>> >  hw/pci.c |   23 ++++++++++++-----------
>> >  1 files changed, 12 insertions(+), 11 deletions(-)
>> >
>> > diff --git a/hw/pci.c b/hw/pci.c
>> > index a66e3de..eaf471a 100644
>> > --- a/hw/pci.c
>> > +++ b/hw/pci.c
>> > @@ -923,17 +923,18 @@ 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
>> > +    pci_set_word(dev->config + PCI_COMMAND,
>> > +                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
>>
>> BTW, I think this is a wrong reset value: should be disabled
>> by default. Fixing this needs some testing though, so
>> I am not suggesting we do it in this patch. Have some time
>> to fix this?
>
> Hmm, the user of it is only apb_pci.c
> I guess other magic values came from the real machine.
> So one possible fix is to create apb_pci specific initialization function
> and to move those initialization code into apb_pci.c leaving to
> sparc guys. So we can avoid breakage.
> What do you think of it?

Current code is buggy. According to manual (805-1251) the reset value
should be zero, unless the boot pin is tied high (which is true) and
thus it should be PCI_COMMAND_MEMORY.

I think the default value should be zero and this should be overridden
later in apb_pci.c.

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

* Re: [Qemu-devel] Re: [PATCH V5 07/29] pci/bridge: clean up of pci_bridge_initfn()
  2009-10-13 15:12       ` Blue Swirl
@ 2009-10-13 15:26         ` Michael S. Tsirkin
  2009-10-13 16:32           ` Blue Swirl
  0 siblings, 1 reply; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-13 15:26 UTC (permalink / raw)
  To: Blue Swirl; +Cc: Isaku Yamahata, qemu-devel

On Tue, Oct 13, 2009 at 06:12:17PM +0300, Blue Swirl wrote:
> On Tue, Oct 13, 2009 at 4:20 PM, Isaku Yamahata <yamahata@valinux.co.jp> wrote:
> > On Fri, Oct 09, 2009 at 08:53:10AM +0200, Michael S. Tsirkin wrote:
> >> On Fri, Oct 09, 2009 at 03:28:40PM +0900, Isaku Yamahata wrote:
> >> > - use symbolic constant
> >> > - use helper function pci_set_xxx()
> >> >
> >> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> >> > ---
> >> >  hw/pci.c |   23 ++++++++++++-----------
> >> >  1 files changed, 12 insertions(+), 11 deletions(-)
> >> >
> >> > diff --git a/hw/pci.c b/hw/pci.c
> >> > index a66e3de..eaf471a 100644
> >> > --- a/hw/pci.c
> >> > +++ b/hw/pci.c
> >> > @@ -923,17 +923,18 @@ 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
> >> > +    pci_set_word(dev->config + PCI_COMMAND,
> >> > +                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
> >>
> >> BTW, I think this is a wrong reset value: should be disabled
> >> by default. Fixing this needs some testing though, so
> >> I am not suggesting we do it in this patch. Have some time
> >> to fix this?
> >
> > Hmm, the user of it is only apb_pci.c
> > I guess other magic values came from the real machine.
> > So one possible fix is to create apb_pci specific initialization function
> > and to move those initialization code into apb_pci.c leaving to
> > sparc guys. So we can avoid breakage.
> > What do you think of it?
> 
> Current code is buggy. According to manual (805-1251)

Link? Maybe we should put spec links in comments
in relevant code ...

> the reset value
> should be zero, unless the boot pin is tied high (which is true) and
> thus it should be PCI_COMMAND_MEMORY.
> 
> I think the default value should be zero and this should be overridden
> later in apb_pci.c.

Makes sense.

-- 
MST

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

* Re: [Qemu-devel] Re: [PATCH V5 07/29] pci/bridge: clean up of pci_bridge_initfn()
  2009-10-13 15:26         ` Michael S. Tsirkin
@ 2009-10-13 16:32           ` Blue Swirl
  0 siblings, 0 replies; 68+ messages in thread
From: Blue Swirl @ 2009-10-13 16:32 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Isaku Yamahata, qemu-devel

On Tue, Oct 13, 2009 at 6:26 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> On Tue, Oct 13, 2009 at 06:12:17PM +0300, Blue Swirl wrote:
>> On Tue, Oct 13, 2009 at 4:20 PM, Isaku Yamahata <yamahata@valinux.co.jp> wrote:
>> > On Fri, Oct 09, 2009 at 08:53:10AM +0200, Michael S. Tsirkin wrote:
>> >> On Fri, Oct 09, 2009 at 03:28:40PM +0900, Isaku Yamahata wrote:
>> >> > - use symbolic constant
>> >> > - use helper function pci_set_xxx()
>> >> >
>> >> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
>> >> > ---
>> >> >  hw/pci.c |   23 ++++++++++++-----------
>> >> >  1 files changed, 12 insertions(+), 11 deletions(-)
>> >> >
>> >> > diff --git a/hw/pci.c b/hw/pci.c
>> >> > index a66e3de..eaf471a 100644
>> >> > --- a/hw/pci.c
>> >> > +++ b/hw/pci.c
>> >> > @@ -923,17 +923,18 @@ 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
>> >> > +    pci_set_word(dev->config + PCI_COMMAND,
>> >> > +                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
>> >>
>> >> BTW, I think this is a wrong reset value: should be disabled
>> >> by default. Fixing this needs some testing though, so
>> >> I am not suggesting we do it in this patch. Have some time
>> >> to fix this?
>> >
>> > Hmm, the user of it is only apb_pci.c
>> > I guess other magic values came from the real machine.
>> > So one possible fix is to create apb_pci specific initialization function
>> > and to move those initialization code into apb_pci.c leaving to
>> > sparc guys. So we can avoid breakage.
>> > What do you think of it?
>>
>> Current code is buggy. According to manual (805-1251)
>
> Link?

http://www.sun.com/processors/manuals/805-1251.pdf

> Maybe we should put spec links in comments
> in relevant code ...

Yes. Maybe that should be mandatory for new code.

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

* [Qemu-devel] Re: [PATCH V5 15/29] pci: typedef pcibus_t as uint64_t instead of uint32_t.
  2009-10-13 14:39       ` Michael S. Tsirkin
@ 2009-10-14  4:35         ` Isaku Yamahata
  2009-10-14  8:55           ` Michael S. Tsirkin
  0 siblings, 1 reply; 68+ messages in thread
From: Isaku Yamahata @ 2009-10-14  4:35 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Tue, Oct 13, 2009 at 04:39:15PM +0200, Michael S. Tsirkin wrote:
> On Tue, Oct 13, 2009 at 10:31:33PM +0900, Isaku Yamahata wrote:
> > On Sun, Oct 11, 2009 at 12:43:12PM +0200, Michael S. Tsirkin wrote:
> > > On Fri, Oct 09, 2009 at 03:28:48PM +0900, Isaku Yamahata wrote:
> > > > This patch is preliminary for 64bit bar.
> > > > For 64bit bar support, change pcibus_t which represents
> > > > pci bus addr/size from uint32_t to uint64_t.
> > > > And also change FMT_pcibus for printf.
> > > > 
> > > > In pci_update_mapping() checks 32bit overflow.
> > > > So the check must be updated too.
> > > > 
> > > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > > 
> > > That's all fine, but if you look at users implementing
> > > map io, they do: cpu_register_physical_memory()
> > > on the address they are given.  And if target_phys_addr_t is 32 bit,
> > > this will silently truncate the address.
> > > 
> > > So I would like to understand how this will all
> > > work on 32 bit systems.
> > 
> > The case is
> >   . BAR is memory 64bit and
> >   . target_phys_addr_t is 32bit and
> >   . bar is set to >4G.
> > Hmm, the case isn't checked.
> > 
> > It would be checked by
> > -	last_addr <= new_addr
> > +	(target_phys_addr_t)last_addr <= new_addr
> 
> That's pretty tricky. Can we just convert everything into
> 64 bit unconditionally and just do simple range checks?
> 
> > 
> > I'll fix it with comments added. Nice catch.
> 
> Is this the right thing to do though?
> I think 32 bit CPU might address something like 64G
> memory of highmem support, so a 64 bit value might
> actually be valid.
> 
> Let's step back and understand what the motivation is?
> Maybe declaring all bars as 32 bit for 32 bit targets is enough?

It is independent of guest OS for PCI device to have 64 bit BAR.
It is valid to use PCI card with 64bit bar on 32 bit OS. In that case
the OS will set the 64 bit bar within addressable region.
And it is allowed for 32 bit OS to set 64bit BAR to >4GB.
(which doesn't make sense, though.)

How about adding the following check?
last_addr >= TARGET_PHYS_ADDR_MAX

-- 
yamahata

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

* [Qemu-devel] Re: [PATCH V5 15/29] pci: typedef pcibus_t as uint64_t instead of uint32_t.
  2009-10-14  4:35         ` Isaku Yamahata
@ 2009-10-14  8:55           ` Michael S. Tsirkin
  0 siblings, 0 replies; 68+ messages in thread
From: Michael S. Tsirkin @ 2009-10-14  8:55 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Wed, Oct 14, 2009 at 01:35:49PM +0900, Isaku Yamahata wrote:
> On Tue, Oct 13, 2009 at 04:39:15PM +0200, Michael S. Tsirkin wrote:
> > On Tue, Oct 13, 2009 at 10:31:33PM +0900, Isaku Yamahata wrote:
> > > On Sun, Oct 11, 2009 at 12:43:12PM +0200, Michael S. Tsirkin wrote:
> > > > On Fri, Oct 09, 2009 at 03:28:48PM +0900, Isaku Yamahata wrote:
> > > > > This patch is preliminary for 64bit bar.
> > > > > For 64bit bar support, change pcibus_t which represents
> > > > > pci bus addr/size from uint32_t to uint64_t.
> > > > > And also change FMT_pcibus for printf.
> > > > > 
> > > > > In pci_update_mapping() checks 32bit overflow.
> > > > > So the check must be updated too.
> > > > > 
> > > > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > > > 
> > > > That's all fine, but if you look at users implementing
> > > > map io, they do: cpu_register_physical_memory()
> > > > on the address they are given.  And if target_phys_addr_t is 32 bit,
> > > > this will silently truncate the address.
> > > > 
> > > > So I would like to understand how this will all
> > > > work on 32 bit systems.
> > > 
> > > The case is
> > >   . BAR is memory 64bit and
> > >   . target_phys_addr_t is 32bit and
> > >   . bar is set to >4G.
> > > Hmm, the case isn't checked.
> > > 
> > > It would be checked by
> > > -	last_addr <= new_addr
> > > +	(target_phys_addr_t)last_addr <= new_addr
> > 
> > That's pretty tricky. Can we just convert everything into
> > 64 bit unconditionally and just do simple range checks?
> > 
> > > 
> > > I'll fix it with comments added. Nice catch.
> > 
> > Is this the right thing to do though?
> > I think 32 bit CPU might address something like 64G
> > memory of highmem support, so a 64 bit value might
> > actually be valid.
> > 
> > Let's step back and understand what the motivation is?
> > Maybe declaring all bars as 32 bit for 32 bit targets is enough?
> 
> It is independent of guest OS for PCI device to have 64 bit BAR.
> It is valid to use PCI card with 64bit bar on 32 bit OS.

Yes, but qemu does not support this yet.

> In that case
> the OS will set the 64 bit bar within addressable region.
> And it is allowed for 32 bit OS to set 64bit BAR to >4GB.
> (which doesn't make sense, though.)

Yes, it does. E.g. with high memory, a 32 bit OS can address
more than 4G RAM.

> 
> How about adding the following check?
> last_addr >= TARGET_PHYS_ADDR_MAX

And then what?

> -- 
> yamahata

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

end of thread, other threads:[~2009-10-14  8:58 UTC | newest]

Thread overview: 68+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-10-09  6:28 [Qemu-devel] [PATCH V5 00/29] pci: various pci clean up and pci express support Isaku Yamahata
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 01/29] pci: fix PCI_DPRINTF() wrt variadic macro Isaku Yamahata
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 02/29] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4 Isaku Yamahata
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 03/29] pci: use PCI_SLOT() and PCI_FUNC() Isaku Yamahata
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 04/29] pci: define a constant to represent a unmapped bar and use it Isaku Yamahata
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 05/29] pci: helper functions to access PCIDevice::config Isaku Yamahata
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 06/29] pci: use helper functions to access pci config space Isaku Yamahata
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 07/29] pci/bridge: clean up of pci_bridge_initfn() Isaku Yamahata
2009-10-09  6:53   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-13 13:20     ` Isaku Yamahata
2009-10-13 14:17       ` Michael S. Tsirkin
2009-10-13 15:12       ` Blue Swirl
2009-10-13 15:26         ` Michael S. Tsirkin
2009-10-13 16:32           ` Blue Swirl
2009-10-09  6:54   ` Michael S. Tsirkin
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 08/29] pci: s/PCI_ADDRESS_SPACE_/PCI_BASE_ADDRESS_SPACE_/ to match pci_regs.h Isaku Yamahata
2009-10-09  6:57   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-13 13:21     ` Isaku Yamahata
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 09/29] pci: clean up of pci_default_read_config Isaku Yamahata
2009-10-09  6:50   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-09  6:58   ` Michael S. Tsirkin
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 10/29] pci: make pci_bar() aware of header type 1 Isaku Yamahata
2009-10-09  7:06   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-10 19:29   ` Michael S. Tsirkin
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 11/29] pci_host.h: move functions in pci_host.h into .c file Isaku Yamahata
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 12/29] pci_host: consolidate pci config address access Isaku Yamahata
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 13/29] pci: introduce pcibus_t to represent pci bus address/size instead of uint32_t Isaku Yamahata
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 14/29] pci: introduce FMT_PCIBUS for printf format for pcibus_t Isaku Yamahata
2009-10-10 19:32   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 15/29] pci: typedef pcibus_t as uint64_t instead of uint32_t Isaku Yamahata
2009-10-11 10:43   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-13 13:31     ` Isaku Yamahata
2009-10-13 14:39       ` Michael S. Tsirkin
2009-10-14  4:35         ` Isaku Yamahata
2009-10-14  8:55           ` Michael S. Tsirkin
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 16/29] pci: 64bit bar support Isaku Yamahata
2009-10-10 19:39   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-13 13:52     ` Isaku Yamahata
2009-10-13 15:00       ` Michael S. Tsirkin
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 17/29] pci: make pci configuration transaction more accurate Isaku Yamahata
2009-10-09 12:52   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 18/29] pci: factor out the conversion logic from io port address into pci device Isaku Yamahata
2009-10-10 19:41   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 19/29] pci: split out ioport address parsing from pci configuration access logic Isaku Yamahata
2009-10-10 19:45   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-13 14:14     ` Isaku Yamahata
2009-10-13 14:49       ` Michael S. Tsirkin
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 20/29] pci: move pci host stuff from pci.c to pci_host.c Isaku Yamahata
2009-10-10 19:46   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 21/29] pci_host: change the signature of pci_data_{read, write} Isaku Yamahata
2009-10-09 12:02   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 22/29] vmstate: add VMSTATE_ARRAY_POINTER for pointer to array Isaku Yamahata
2009-10-11 10:37   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 23/29] pci: pcie host and mmcfg support Isaku Yamahata
2009-10-11 10:26   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 24/29] pci: fix pci_default_write_config() Isaku Yamahata
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 25/29] pci: add helper functions for pci config write function Isaku Yamahata
2009-10-10 19:58   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-09  6:28 ` [Qemu-devel] [PATCH V5 26/29] pci: use helper function in pci_default_write_config() Isaku Yamahata
2009-10-09  6:29 ` [Qemu-devel] [PATCH V5 27/29] pci/bridge: don't update bar mapping when bar2-5 is changed Isaku Yamahata
2009-10-09 10:35   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-09  6:29 ` [Qemu-devel] [PATCH V5 28/29] pci: initialize pci config headers depending it pci header type Isaku Yamahata
2009-10-09 10:42   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-13 14:31     ` Isaku Yamahata
2009-10-13 14:52       ` Michael S. Tsirkin
2009-10-13 15:06       ` Michael S. Tsirkin
2009-10-09  6:29 ` [Qemu-devel] [PATCH V5 29/29] pci/monitor: print out bridge's filtering values and so on Isaku Yamahata
2009-10-10 20:05   ` [Qemu-devel] " Michael S. Tsirkin

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.