qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Marcel Apfelbaum <marcel@redhat.com>
To: qemu-devel@nongnu.org
Cc: kraxel@redhat.com, mst@redhat.com, quintela@redhat.com,
	agraf@suse.de, marcel@redhat.com, alex.williamson@redhat.com,
	kevin@koconnor.net, hare@suse.de, imammedo@redhat.com,
	amit.shah@redhat.com, pbonzini@redhat.com, leon.alrae@imgtec.com,
	aurelien@aurel32.net, rth@twiddle.net
Subject: [Qemu-devel] [PATCH V6 for-2.3 14/26] hw/pci-host/piix: implement TYPE_PCI_HOST_BRIDGE_SNOOPED interface
Date: Thu, 19 Mar 2015 20:52:49 +0200	[thread overview]
Message-ID: <1426791181-23831-15-git-send-email-marcel@redhat.com> (raw)
In-Reply-To: <1426791181-23831-1-git-send-email-marcel@redhat.com>

The PIIX holds a list of snooping host bridges that is populated
by a registration function that shall be used by any host bridge
that needs to use PIIX configuration space to complete their
configuration cycles.

PIIX monitors acceses to configuration registers and passes them
to the corresponding host bridge if the input bus number is
in its bus range.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
---
 hw/pci-host/piix.c        | 118 +++++++++++++++++++++++++++++++++++++++++++++-
 hw/pci/pci_host.c         |  28 +++++++++++
 include/hw/i386/pc.h      |   6 +++
 include/hw/pci/pci_host.h |   3 ++
 4 files changed, 154 insertions(+), 1 deletion(-)

diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index 0033ab4..f512765 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -50,6 +50,12 @@ typedef struct I440FXState {
     PcPciInfo pci_info;
     uint64_t pci_hole64_size;
     uint32_t short_root_bus;
+
+    /*
+     * List of PCI host bridges listening to
+     * the same configuration registers.
+     */
+    GPtrArray *snooping_hosts;
 } I440FXState;
 
 #define PIIX_NUM_PIC_IRQS       16      /* i8259 * 2 */
@@ -255,14 +261,80 @@ static void i440fx_pcihost_get_pci_hole64_end(Object *obj, Visitor *v,
     visit_type_uint64(v, &w64.end, name, errp);
 }
 
+static PCIBus *i440fx_find_target_bus(I440FXState *i440fx, uint8_t bus_num)
+{
+    PCIHostState *host = PCI_HOST_BRIDGE(i440fx);
+    PCIBus *target_bus = NULL;
+
+    if (bus_num == pci_bus_num(host->bus)) {
+        target_bus = host->bus;
+    } else {
+        int i;
+
+        for (i = 0; i < i440fx->snooping_hosts->len; i++) {
+            PCIHostState *s_host = g_ptr_array_index(i440fx->snooping_hosts, i);
+            Range r = pci_host_get_buses_range(s_host);
+
+            if (r.begin <= bus_num && r.end >= bus_num) {
+                target_bus = s_host->bus;
+            }
+
+        }
+    }
+
+    return target_bus;
+}
+
+static void i440fx_pcihost_data_write(void *opaque, hwaddr addr,
+                                      uint64_t val, unsigned len)
+{
+    uint32_t config_reg = PCI_HOST_BRIDGE(opaque)->config_reg;
+
+    if (config_reg & (1u << 31)) {
+        uint8_t bus_num = (config_reg >> 16) & 0xFF;
+        I440FXState *i440fx = I440FX_PCI_HOST_BRIDGE(opaque);
+        PCIBus *target_bus = i440fx_find_target_bus(i440fx, bus_num);
+
+        if (target_bus) {
+            pci_data_write(target_bus, config_reg | (addr & 3), val, len);
+        }
+    }
+}
+
+static uint64_t i440fx_pcihost_data_read(void *opaque,
+                                         hwaddr addr, unsigned len)
+{
+    uint32_t config_reg = PCI_HOST_BRIDGE(opaque)->config_reg;
+
+    if (config_reg & (1U << 31)) {
+        int bus_num = (config_reg >> 16) & 0xFF;
+        I440FXState *i440fx = I440FX_PCI_HOST_BRIDGE(opaque);
+        PCIBus *target_bus = i440fx_find_target_bus(i440fx, bus_num);
+
+        if (target_bus) {
+            return pci_data_read(target_bus, config_reg | (addr & 3), len);
+        }
+    }
+
+    return 0xffffffff;
+}
+
+const MemoryRegionOps i440fx_pcihost_data_le_ops = {
+    .read = i440fx_pcihost_data_read,
+    .write = i440fx_pcihost_data_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 static void i440fx_pcihost_initfn(Object *obj)
 {
     PCIHostState *s = PCI_HOST_BRIDGE(obj);
     I440FXState *d = I440FX_PCI_HOST_BRIDGE(obj);
 
+    d->snooping_hosts = g_ptr_array_new();
+
     memory_region_init_io(&s->conf_mem, obj, &pci_host_conf_le_ops, s,
                           "pci-conf-idx", 4);
-    memory_region_init_io(&s->data_mem, obj, &pci_host_data_le_ops, s,
+    memory_region_init_io(&s->data_mem, obj, &i440fx_pcihost_data_le_ops, s,
                           "pci-conf-data", 4);
 
     object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "int",
@@ -400,6 +472,40 @@ PCIBus *find_i440fx(void)
     return s ? s->bus : NULL;
 }
 
+/*
+ * Returns 0 on successs, -1 if i440fx host was not
+ * found or the bus number is already in use.
+ */
+int i440fx_register_snooping_host(PCIHostState *host)
+{
+    I440FXState *s = OBJECT_CHECK(I440FXState,
+                                  object_resolve_path("/machine/i440fx", NULL),
+                                  TYPE_I440FX_PCI_HOST_BRIDGE);
+    uint8_t bus_num = pci_bus_num(host->bus);
+    int i;
+
+    /* i440fx host not found */
+    if (!s) {
+        return -1;
+    }
+
+    /* 0 is reserved for i440fx host bridge */
+    if (bus_num == 0) {
+        return -1;
+    }
+
+    /* check if the bus number is unique */
+    for (i = 0; i < s->snooping_hosts->len; i++) {
+        PCIHostState *s_host = g_ptr_array_index(s->snooping_hosts, i);
+        if (bus_num == pci_bus_num(s_host->bus)) {
+            return -1;
+        }
+    }
+
+    g_ptr_array_add(s->snooping_hosts, host);
+    return 0;
+}
+
 /* PIIX3 PCI to ISA bridge */
 static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
 {
@@ -742,6 +848,13 @@ static const char *i440fx_pcihost_root_bus_path(PCIHostState *host_bridge,
     return "0000:00";
 }
 
+static GPtrArray *i440fx_snooping_hosts(PCIHostState *host_bridge)
+{
+    I440FXState *s = I440FX_PCI_HOST_BRIDGE(host_bridge);
+
+    return s->snooping_hosts;
+}
+
 static Property i440fx_props[] = {
     DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, I440FXState,
                      pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE),
@@ -753,11 +866,13 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
+    PCIHostBridgeSnoopedClass *sc = TYPE_PCI_HOST_BRIDGE_SNOOPED_CLASS(klass);
 
     hc->root_bus_path = i440fx_pcihost_root_bus_path;
     dc->realize = i440fx_pcihost_realize;
     dc->fw_name = "pci";
     dc->props = i440fx_props;
+    sc->snooping_hosts = i440fx_snooping_hosts;
 }
 
 static const TypeInfo i440fx_pcihost_info = {
@@ -768,6 +883,7 @@ static const TypeInfo i440fx_pcihost_info = {
     .class_init    = i440fx_pcihost_class_init,
     .interfaces    = (InterfaceInfo[]) {
         { TYPE_PCI_MAIN_HOST_BRIDGE },
+        { TYPE_PCI_HOST_BRIDGE_SNOOPED },
         { }
     }
 
diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c
index 288e74c..35e462b 100644
--- a/hw/pci/pci_host.c
+++ b/hw/pci/pci_host.c
@@ -20,6 +20,8 @@
 
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_host.h"
+#include "hw/pci/pci_bus.h"
+#include "qemu/range.h"
 #include "trace.h"
 
 /* debug PCI */
@@ -32,6 +34,32 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
 #define PCI_DPRINTF(fmt, ...)
 #endif
 
+Range pci_host_get_buses_range(PCIHostState *host)
+{
+    uint8_t root_bus_num = pci_bus_num(host->bus);
+    Range r = {root_bus_num, root_bus_num};
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(host->bus->devices); ++i) {
+        PCIDevice *dev = host->bus->devices[i];
+        PCIDeviceClass *pc;
+
+        if (!dev) {
+            continue;
+        }
+
+        pc = PCI_DEVICE_GET_CLASS(dev);
+
+        if (pc->is_bridge) {
+            uint8_t subordinate = dev->config[PCI_SUBORDINATE_BUS];
+            if (subordinate > r.end) {
+                r.end = subordinate;
+            }
+        }
+    }
+
+    return r;
+}
 /*
  * PCI address
  * bit 16 - 24: bus number
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 1b35168..a918a61 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -241,6 +241,12 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn,
                     MemoryRegion *ram_memory);
 
 PCIBus *find_i440fx(void);
+/*
+ * Register hosts without their own configuration registers
+ * to i440fx main PCI host bridge
+ */
+int i440fx_register_snooping_host(PCIHostState *host);
+
 /* piix4.c */
 extern PCIDevice *piix4_dev;
 int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn);
diff --git a/include/hw/pci/pci_host.h b/include/hw/pci/pci_host.h
index a041919..dc7ccb2 100644
--- a/include/hw/pci/pci_host.h
+++ b/include/hw/pci/pci_host.h
@@ -87,6 +87,9 @@ typedef struct PCIHostBridgeSnoopedClass {
     GPtrArray *(*snooping_hosts)(PCIHostState *);
 } PCIHostBridgeSnoopedClass;
 
+/* Returns the buses interval owned by the input host */
+Range pci_host_get_buses_range(PCIHostState *host);
+
 /* common internal helpers for PCI/PCIe hosts, cut off overflows */
 void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
                                   uint32_t limit, uint32_t val, uint32_t len);
-- 
2.1.0

  parent reply	other threads:[~2015-03-19 18:54 UTC|newest]

Thread overview: 61+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-19 18:52 [Qemu-devel] [PATCH V6 for-2.3 00/26] hw/pc: implement multiple primary busses for pc machines Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 01/26] acpi: add aml_or() term Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 02/26] acpi: add aml_add() term Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 03/26] acpi: add aml_lless() term Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 04/26] acpi: add aml_index() term Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 05/26] acpi: add aml_shiftleft() term Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 06/26] acpi: add aml_shiftright() term Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 07/26] acpi: add aml_increment() term Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 08/26] acpi: add aml_while() term Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 09/26] hw/pci: move pci bus related code to separate files Marcel Apfelbaum
2015-04-27 11:14   ` Michael S. Tsirkin
2015-04-27 11:35     ` Paolo Bonzini
2015-04-27 11:49       ` Marcel Apfelbaum
2015-04-27 12:24         ` Michael S. Tsirkin
2015-04-28  7:31       ` Markus Armbruster
2015-04-28  8:25         ` Marcel Apfelbaum
2015-04-27 12:26     ` Marcel Apfelbaum
2015-04-28  8:30       ` Michael S. Tsirkin
2015-04-28  8:30         ` Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 10/26] hw/pci: made pci_bus_is_root a PCIBusClass method Marcel Apfelbaum
2015-04-27 11:37   ` Michael S. Tsirkin
2015-04-27 11:49     ` Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 11/26] hw/pci: made pci_bus_num " Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 12/26] hw/pci: introduce TYPE_PCI_MAIN_HOST_BRIDGE interface Marcel Apfelbaum
2015-04-27 11:24   ` Michael S. Tsirkin
2015-04-27 12:30     ` Marcel Apfelbaum
2015-04-27 12:48       ` Michael S. Tsirkin
2015-04-27 13:04         ` Marcel Apfelbaum
2015-04-27 20:54           ` Michael S. Tsirkin
2015-04-28  8:33             ` Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 13/26] hw/pci-host: introduce TYPE_PCI_HOST_BRIDGE_SNOOPED interface Marcel Apfelbaum
2015-04-27 12:14   ` Michael S. Tsirkin
2015-04-27 13:01     ` Marcel Apfelbaum
2015-04-27 14:45       ` Michael S. Tsirkin
2015-04-28  8:39         ` Marcel Apfelbaum
2015-04-28  8:43           ` Michael S. Tsirkin
2015-04-28 10:21             ` Marcel Apfelbaum
2015-04-28 10:44               ` Michael S. Tsirkin
2015-03-19 18:52 ` Marcel Apfelbaum [this message]
2015-04-27 12:23   ` [Qemu-devel] [PATCH V6 for-2.3 14/26] hw/pci-host/piix: implement " Michael S. Tsirkin
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 15/26] hw/acpi: add support for i440fx 'snooping' root busses Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 16/26] hw/apci: add _PRT method for extra PCI " Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 17/26] hw/acpi: add _CRS method for extra " Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 18/26] hw/acpi: remove from root bus 0 the crs resources used by other busses Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 19/26] hw/pci: removed 'rootbus nr is 0' assumption from qmp_pci_query Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 20/26] hw/pci: introduce PCI Expander Bridge (PXB) Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 21/26] hw/pci: inform bios if the system has extra pci root buses Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 22/26] hw/pxb: add map_irq func Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 23/26] hw/pci_bus: add support for NUMA nodes Marcel Apfelbaum
2015-03-19 18:52 ` [Qemu-devel] [PATCH V6 for-2.3 24/26] hw/pxb: add numa_node parameter Marcel Apfelbaum
2015-03-19 18:53 ` [Qemu-devel] [PATCH V6 for-2.3 25/26] apci: fix PXB behaviour if used with unsupported BIOS Marcel Apfelbaum
2015-04-27 11:19   ` Michael S. Tsirkin
2015-04-27 11:51     ` Gerd Hoffmann
2015-03-19 18:53 ` [Qemu-devel] [PATCH V6 for-2.3 26/26] docs: Add PXB documentation Marcel Apfelbaum
2015-03-19 21:45 ` [Qemu-devel] [PATCH V6 for-2.3 00/26] hw/pc: implement multiple primary busses for pc machines Paolo Bonzini
2015-03-20  8:37   ` Marcel Apfelbaum
2015-03-20 17:56     ` Paolo Bonzini
2015-03-20 18:07       ` Peter Maydell
2015-03-20  7:44 ` Gerd Hoffmann
2015-03-20  8:25   ` Marcel Apfelbaum
2015-03-21 18:49 ` Michael S. Tsirkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1426791181-23831-15-git-send-email-marcel@redhat.com \
    --to=marcel@redhat.com \
    --cc=agraf@suse.de \
    --cc=alex.williamson@redhat.com \
    --cc=amit.shah@redhat.com \
    --cc=aurelien@aurel32.net \
    --cc=hare@suse.de \
    --cc=imammedo@redhat.com \
    --cc=kevin@koconnor.net \
    --cc=kraxel@redhat.com \
    --cc=leon.alrae@imgtec.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=quintela@redhat.com \
    --cc=rth@twiddle.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).