qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v11 0/5] *** SUBJECT HERE ***
@ 2010-12-24  3:14 Isaku Yamahata
  2010-12-24  3:14 ` [Qemu-devel] [PATCH v11 1/5] qdev: export qdev_find_recursive() for later use Isaku Yamahata
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Isaku Yamahata @ 2010-12-24  3:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: yamahata, mst

*** BLURB HERE ***

Isaku Yamahata (5):
  qdev: export qdev_find_recursive() for later use
  pci: introduce a helper function to convert qdev id to PCIDevice
  pcie/aer: glue aer error injection into qemu monitor
  pci: introduce a parser for fw device path to pci device
  pcie/aer: use fw device path as fallback for aer injection command

 hmp-commands.hx |   30 +++++++
 hw/pci-stub.c   |   13 +++
 hw/pci.c        |  164 +++++++++++++++++++++++++++++++++++++++
 hw/pci.h        |    3 +
 hw/pcie_aer.c   |  227 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.c       |    2 +-
 hw/qdev.h       |    2 +
 sysemu.h        |    5 +
 8 files changed, 445 insertions(+), 1 deletions(-)

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

* [Qemu-devel] [PATCH v11 1/5] qdev: export qdev_find_recursive() for later use
  2010-12-24  3:14 [Qemu-devel] [PATCH v11 0/5] *** SUBJECT HERE *** Isaku Yamahata
@ 2010-12-24  3:14 ` Isaku Yamahata
  2010-12-24  3:14 ` [Qemu-devel] [PATCH v11 2/5] pci: introduce a helper function to convert qdev id to PCIDevice Isaku Yamahata
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Isaku Yamahata @ 2010-12-24  3:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: yamahata, mst

This patch exports qdev_find_recursive() for later use.

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

diff --git a/hw/qdev.c b/hw/qdev.c
index 4747c67..31eb464 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -548,7 +548,7 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name,
     return NULL;
 }
 
-static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
+DeviceState *qdev_find_recursive(BusState *bus, const char *id)
 {
     DeviceState *dev, *ret;
     BusState *child;
diff --git a/hw/qdev.h b/hw/qdev.h
index 5f5a319..2be775f 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -183,6 +183,8 @@ BusState *qdev_get_parent_bus(DeviceState *dev);
 
 /*** BUS API. ***/
 
+DeviceState *qdev_find_recursive(BusState *bus, const char *id);
+
 /* Returns 0 to walk children, > 0 to skip walk, < 0 to terminate walk. */
 typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
 typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
-- 
1.7.1.1

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

* [Qemu-devel] [PATCH v11 2/5] pci: introduce a helper function to convert qdev id to PCIDevice
  2010-12-24  3:14 [Qemu-devel] [PATCH v11 0/5] *** SUBJECT HERE *** Isaku Yamahata
  2010-12-24  3:14 ` [Qemu-devel] [PATCH v11 1/5] qdev: export qdev_find_recursive() for later use Isaku Yamahata
@ 2010-12-24  3:14 ` Isaku Yamahata
  2010-12-24  3:14 ` [Qemu-devel] [PATCH v11 3/5] pcie/aer: glue aer error injection into qemu monitor Isaku Yamahata
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Isaku Yamahata @ 2010-12-24  3:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: yamahata, mst

This patch introduce a helper function to get PCIDevice from qdev id.
This function will be used later.

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

diff --git a/hw/pci.c b/hw/pci.c
index eb21848..44bb3b9 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -2027,3 +2027,38 @@ static char *pcibus_get_dev_path(DeviceState *dev)
     return strdup(path);
 }
 
+static int pci_qdev_find_recursive(PCIBus *bus,
+                                   const char *id, PCIDevice **pdev)
+{
+    DeviceState *qdev = qdev_find_recursive(&bus->qbus, id);
+    if (!qdev) {
+        return -ENODEV;
+    }
+
+    /* roughly check if given qdev is pci device */
+    if (qdev->info->init == &pci_qdev_init &&
+        qdev->parent_bus->info == &pci_bus_info) {
+        *pdev = DO_UPCAST(PCIDevice, qdev, qdev);
+        return 0;
+    }
+    return -EINVAL;
+}
+
+int pci_qdev_find_device(const char *id, PCIDevice **pdev)
+{
+    struct PCIHostBus *host;
+    int rc = -ENODEV;
+
+    QLIST_FOREACH(host, &host_buses, next) {
+        int tmp = pci_qdev_find_recursive(host->bus, id, pdev);
+        if (!tmp) {
+            rc = 0;
+            break;
+        }
+        if (tmp != -ENODEV) {
+            rc = tmp;
+        }
+    }
+
+    return rc;
+}
diff --git a/hw/pci.h b/hw/pci.h
index 6e80b08..052960e 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -252,6 +252,7 @@ PCIBus *pci_find_root_bus(int domain);
 int pci_find_domain(const PCIBus *bus);
 PCIBus *pci_find_bus(PCIBus *bus, int bus_num);
 PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function);
+int pci_qdev_find_device(const char *id, PCIDevice **pdev);
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
 
 int pci_parse_devaddr(const char *addr, int *domp, int *busp,
-- 
1.7.1.1

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

* [Qemu-devel] [PATCH v11 3/5] pcie/aer: glue aer error injection into qemu monitor
  2010-12-24  3:14 [Qemu-devel] [PATCH v11 0/5] *** SUBJECT HERE *** Isaku Yamahata
  2010-12-24  3:14 ` [Qemu-devel] [PATCH v11 1/5] qdev: export qdev_find_recursive() for later use Isaku Yamahata
  2010-12-24  3:14 ` [Qemu-devel] [PATCH v11 2/5] pci: introduce a helper function to convert qdev id to PCIDevice Isaku Yamahata
@ 2010-12-24  3:14 ` Isaku Yamahata
  2010-12-24  3:14 ` [Qemu-devel] [PATCH v11 4/5] pci: introduce a parser for fw device path to pci device Isaku Yamahata
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Isaku Yamahata @ 2010-12-24  3:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: yamahata, mst

introduce pcie_aer_inject_error command.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
Change v10 -> v11:
- use qdev id

Changes v9 -> v10:
- use fw device path
- error path
- pci-stub.c for CONFIG_PCI=n

Changes v8 -> v9:
- revise error code

Changes v7 -> v8:
- use domain:slot.func:slot.func...:slot.func instead of domain:bus:slot.func
- allow symbolic aer error name in addition to 32bit value

Changes v6 -> v7:
- check return value.

Changes v3 -> v4:
- s/PCIE_AER/PCIEAER/g for structure names.
- compilation adjustment.

Changes v2 -> v3:
- compilation adjustment.
---
 hmp-commands.hx |   25 ++++++
 hw/pci-stub.c   |   13 +++
 hw/pcie_aer.c   |  223 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 sysemu.h        |    5 +
 4 files changed, 266 insertions(+), 0 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index dd3db36..8d84ddc 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -873,6 +873,31 @@ Hot remove PCI device.
 ETEXI
 
     {
+        .name       = "pcie_aer_inject_error",
+        .args_type  = "advisory_non_fatal:-a,correctable:-c,"
+	              "id:s,error_status:s,"
+	              "header0:i?,header1:i?,header2:i?,header3:i?,"
+	              "prefix0:i?,prefix1:i?,prefix2:i?,prefix3:i?",
+        .params     = "[-a] [-c] id "
+                      "<error_status> [<tlp header> [<tlp header prefix>]]",
+        .help       = "inject pcie aer error\n\t\t\t"
+	              " -a for advisory non fatal error\n\t\t\t"
+	              " -c for correctable error\n\t\t\t"
+                      "<id> = qdev device id\n\t\t\t"
+                      "<error_status> = error string or 32bit\n\t\t\t"
+                      "<tlb header> = 32bit x 4\n\t\t\t"
+                      "<tlb header prefix> = 32bit x 4",
+        .user_print  = pcie_aer_inject_error_print,
+        .mhandler.cmd_new = do_pcie_aer_inejct_error,
+    },
+
+STEXI
+@item pcie_aer_inject_error
+@findex pcie_aer_inject_error
+Inject PCIe AER error
+ETEXI
+
+    {
         .name       = "host_net_add",
         .args_type  = "device:s,opts:s?",
         .params     = "tap|user|socket|vde|dump [options]",
diff --git a/hw/pci-stub.c b/hw/pci-stub.c
index 674591d..c5a0aa8 100644
--- a/hw/pci-stub.c
+++ b/hw/pci-stub.c
@@ -18,6 +18,7 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "sysemu.h"
 #include "monitor.h"
 #include "pci.h"
 
@@ -35,3 +36,15 @@ void do_pci_info_print(Monitor *mon, const QObject *data)
 {
     pci_error_message(mon);
 }
+
+int do_pcie_aer_inejct_error(Monitor *mon,
+                             const QDict *qdict, QObject **ret_data)
+{
+    pci_error_message(mon);
+    return -ENOSYS;
+}
+
+void pcie_aer_inject_error_print(Monitor *mon, const QObject *data)
+{
+    pci_error_message(mon);
+}
diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c
index cb97a95..6e653dd 100644
--- a/hw/pcie_aer.c
+++ b/hw/pcie_aer.c
@@ -19,6 +19,8 @@
  */
 
 #include "sysemu.h"
+#include "qemu-objects.h"
+#include "monitor.h"
 #include "pci_bridge.h"
 #include "pcie.h"
 #include "msix.h"
@@ -806,3 +808,224 @@ const VMStateDescription vmstate_pcie_aer_log = {
         VMSTATE_END_OF_LIST()
     }
 };
+
+void pcie_aer_inject_error_print(Monitor *mon, const QObject *data)
+{
+    QDict *qdict;
+    int devfn;
+    assert(qobject_type(data) == QTYPE_QDICT);
+    qdict = qobject_to_qdict(data);
+
+    devfn = (int)qdict_get_int(qdict, "devfn");
+    monitor_printf(mon, "OK id: %s domain: %x, bus: %x devfn: %x.%x\n",
+                   qdict_get_str(qdict, "id"),
+                   (int) qdict_get_int(qdict, "domain"),
+                   (int) qdict_get_int(qdict, "bus"),
+                   PCI_SLOT(devfn), PCI_FUNC(devfn));
+}
+
+typedef struct PCIEAERErrorName {
+    const char *name;
+    uint32_t val;
+    bool correctable;
+} PCIEAERErrorName;
+
+/*
+ * AER error name -> value convertion table
+ * This naming scheme is same to linux aer-injection tool.
+ */
+static const struct PCIEAERErrorName pcie_aer_error_list[] = {
+    {
+        .name = "TRAIN",
+        .val = PCI_ERR_UNC_TRAIN,
+        .correctable = false,
+    }, {
+        .name = "DLP",
+        .val = PCI_ERR_UNC_DLP,
+        .correctable = false,
+    }, {
+        .name = "SDN",
+        .val = PCI_ERR_UNC_SDN,
+        .correctable = false,
+    }, {
+        .name = "POISON_TLP",
+        .val = PCI_ERR_UNC_POISON_TLP,
+        .correctable = false,
+    }, {
+        .name = "FCP",
+        .val = PCI_ERR_UNC_FCP,
+        .correctable = false,
+    }, {
+        .name = "COMP_TIME",
+        .val = PCI_ERR_UNC_COMP_TIME,
+        .correctable = false,
+    }, {
+        .name = "COMP_ABORT",
+        .val = PCI_ERR_UNC_COMP_ABORT,
+        .correctable = false,
+    }, {
+        .name = "UNX_COMP",
+        .val = PCI_ERR_UNC_UNX_COMP,
+        .correctable = false,
+    }, {
+        .name = "RX_OVER",
+        .val = PCI_ERR_UNC_RX_OVER,
+        .correctable = false,
+    }, {
+        .name = "MALF_TLP",
+        .val = PCI_ERR_UNC_MALF_TLP,
+        .correctable = false,
+    }, {
+        .name = "ECRC",
+        .val = PCI_ERR_UNC_ECRC,
+        .correctable = false,
+    }, {
+        .name = "UNSUP",
+        .val = PCI_ERR_UNC_UNSUP,
+        .correctable = false,
+    }, {
+        .name = "ACSV",
+        .val = PCI_ERR_UNC_ACSV,
+        .correctable = false,
+    }, {
+        .name = "INTN",
+        .val = PCI_ERR_UNC_INTN,
+        .correctable = false,
+    }, {
+        .name = "MCBTLP",
+        .val = PCI_ERR_UNC_MCBTLP,
+        .correctable = false,
+    }, {
+        .name = "ATOP_EBLOCKED",
+        .val = PCI_ERR_UNC_ATOP_EBLOCKED,
+        .correctable = false,
+    }, {
+        .name = "TLP_PRF_BLOCKED",
+        .val = PCI_ERR_UNC_TLP_PRF_BLOCKED,
+        .correctable = false,
+    }, {
+        .name = "RCVR",
+        .val = PCI_ERR_COR_RCVR,
+        .correctable = true,
+    }, {
+        .name = "BAD_TLP",
+        .val = PCI_ERR_COR_BAD_TLP,
+        .correctable = true,
+    }, {
+        .name = "BAD_DLLP",
+        .val = PCI_ERR_COR_BAD_DLLP,
+        .correctable = true,
+    }, {
+        .name = "REP_ROLL",
+        .val = PCI_ERR_COR_REP_ROLL,
+        .correctable = true,
+    }, {
+        .name = "REP_TIMER",
+        .val = PCI_ERR_COR_REP_TIMER,
+        .correctable = true,
+    }, {
+        .name = "ADV_NONFATAL",
+        .val = PCI_ERR_COR_ADV_NONFATAL,
+        .correctable = true,
+    }, {
+        .name = "INTERNAL",
+        .val = PCI_ERR_COR_INTERNAL,
+        .correctable = true,
+    }, {
+        .name = "HL_OVERFLOW",
+        .val = PCI_ERR_COR_HL_OVERFLOW,
+        .correctable = true,
+    },
+};
+
+static int pcie_aer_parse_error_string(const char *error_name,
+                                       uint32_t *status, bool *correctable)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(pcie_aer_error_list); i++) {
+        const  PCIEAERErrorName *e = &pcie_aer_error_list[i];
+        if (strcmp(error_name, e->name)) {
+            continue;
+        }
+
+        *status = e->val;
+        *correctable = e->correctable;
+        return 0;
+    }
+    return -EINVAL;
+}
+
+int do_pcie_aer_inejct_error(Monitor *mon,
+                             const QDict *qdict, QObject **ret_data)
+{
+    const char *id = qdict_get_str(qdict, "id");
+    const char *error_name;
+    uint32_t error_status;
+    bool correctable;
+    PCIDevice *dev;
+    PCIEAERErr err;
+    int ret;
+
+    ret = pci_qdev_find_device(id, &dev);
+    if (ret < 0) {
+        monitor_printf(mon,
+                       "id or pci device path is invalid or device not "
+                       "found. %s\n", id);
+        return ret;
+    }
+    if (!pci_is_express(dev)) {
+        monitor_printf(mon, "the device doesn't support pci express. %s\n",
+                       id);
+        return -ENOSYS;
+    }
+
+    error_name = qdict_get_str(qdict, "error_status");
+    if (pcie_aer_parse_error_string(error_name, &error_status, &correctable)) {
+        char *e = NULL;
+        error_status = strtoul(error_name, &e, 0);
+        correctable = !!qdict_get_int(qdict, "correctable");
+        if (!e || *e != '\0') {
+            monitor_printf(mon, "invalid error status value. \"%s\"",
+                           error_name);
+            return -EINVAL;
+        }
+    }
+    err.source_id = (pci_bus_num(dev->bus) << 8) | dev->devfn;
+
+    err.flags = 0;
+    if (correctable) {
+        err.flags |= PCIE_AER_ERR_IS_CORRECTABLE;
+    }
+    if (qdict_get_int(qdict, "advisory_non_fatal")) {
+        err.flags |= PCIE_AER_ERR_MAYBE_ADVISORY;
+    }
+    if (qdict_haskey(qdict, "header0")) {
+        err.flags |= PCIE_AER_ERR_HEADER_VALID;
+    }
+    if (qdict_haskey(qdict, "prefix0")) {
+        err.flags |= PCIE_AER_ERR_TLP_PREFIX_PRESENT;
+    }
+
+    err.header[0] = qdict_get_try_int(qdict, "header0", 0);
+    err.header[1] = qdict_get_try_int(qdict, "header1", 0);
+    err.header[2] = qdict_get_try_int(qdict, "header2", 0);
+    err.header[3] = qdict_get_try_int(qdict, "header3", 0);
+
+    err.prefix[0] = qdict_get_try_int(qdict, "prefix0", 0);
+    err.prefix[1] = qdict_get_try_int(qdict, "prefix1", 0);
+    err.prefix[2] = qdict_get_try_int(qdict, "prefix2", 0);
+    err.prefix[3] = qdict_get_try_int(qdict, "prefix3", 0);
+
+    ret = pcie_aer_inject_error(dev, &err);
+    *ret_data = qobject_from_jsonf("{'id': %s, "
+                                   "'domain': %d, 'bus': %d, 'devfn': %d, "
+                                   "'ret': %d}",
+                                   id,
+                                   pci_find_domain(dev->bus),
+                                   pci_bus_num(dev->bus), dev->devfn,
+                                   ret);
+    assert(*ret_data);
+
+    return 0;
+}
diff --git a/sysemu.h b/sysemu.h
index 38a20a3..4182aac 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -157,6 +157,11 @@ void pci_device_hot_add(Monitor *mon, const QDict *qdict);
 void drive_hot_add(Monitor *mon, const QDict *qdict);
 void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict);
 
+/* pcie aer error injection */
+void pcie_aer_inject_error_print(Monitor *mon, const QObject *data);
+int do_pcie_aer_inejct_error(Monitor *mon,
+                             const QDict *qdict, QObject **ret_data);
+
 /* serial ports */
 
 #define MAX_SERIAL_PORTS 4
-- 
1.7.1.1

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

* [Qemu-devel] [PATCH v11 4/5] pci: introduce a parser for fw device path to pci device
  2010-12-24  3:14 [Qemu-devel] [PATCH v11 0/5] *** SUBJECT HERE *** Isaku Yamahata
                   ` (2 preceding siblings ...)
  2010-12-24  3:14 ` [Qemu-devel] [PATCH v11 3/5] pcie/aer: glue aer error injection into qemu monitor Isaku Yamahata
@ 2010-12-24  3:14 ` Isaku Yamahata
  2010-12-24  3:14 ` [Qemu-devel] [PATCH v11 5/5] pcie/aer: use fw device path as fallback for aer injection command Isaku Yamahata
  2010-12-24  8:36 ` [Qemu-devel] Re: [PATCH v11 0/5] pcie/aer: glue inject aer error into hmp Michael S. Tsirkin
  5 siblings, 0 replies; 7+ messages in thread
From: Isaku Yamahata @ 2010-12-24  3:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: yamahata, mst

Introduce a function to parse fw device path to pci device.
the format is
/pci@{<ioport>, <mmio>}/[<fw_name>]@<slot>,<func>/.../[<fw_name>]@<slot>,<func>

<ioport> = "i"<ioport addr in hex>
<mmio> = <mmio addr in hex>
<slot> = slot number in hex
<func> = func number in hex

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

diff --git a/hw/pci.c b/hw/pci.c
index 44bb3b9..752dde1 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -2062,3 +2062,132 @@ int pci_qdev_find_device(const char *id, PCIDevice **pdev)
 
     return rc;
 }
+
+/*
+ * Parse format and get PCIDevice
+ * return 0 on success
+ *       <0 on error: format is invalid or device isn't found.
+ *
+ * Format:
+ * /pci@{<ioport>, <mmio>}/[<fw_name>]@<slot>,<func>/...
+ *                     .../[<fw_name>]@<slot>,<func>
+ *
+ * <ioport> = "i"<ioport addr in hex>
+ * <mmio> = <mmio addr in hex>
+ * <slot> = slot number in hex
+ * <func> = func number in hex
+ *
+ */
+int pci_parse_fw_dev_path(const char *path, PCIDevice **pdev)
+{
+    const char *p = path;
+    char *e;
+    size_t len;
+    PCIBus *bus;
+    struct PCIHostBus *host;
+
+    if (*p != '/') {
+        return -EINVAL;
+    }
+    e = strchr(p + 1, '/');
+    if (e == NULL) {
+        return -EINVAL;
+    }
+    len = e - p;
+    p = e + 1;
+
+    bus = NULL;
+    QLIST_FOREACH(host, &host_buses, next) {
+        DeviceState *qdev = host->bus->qbus.parent;
+        if (qdev) {
+            char *devpath = qdev_get_fw_dev_path(qdev);
+
+            if (len == strlen(devpath) && !strncmp(devpath, path, len)) {
+                bus = host->bus;
+                qemu_free(devpath);
+                break;
+            }
+            qemu_free(devpath);
+        } else {
+            /* This pci bus doesn't have host-to-pci bridge device.
+             * Check only if the path is pci ignoring other parameters. */
+#define PCI_FW_PATH     "/pci@"
+            if (strncmp(path, PCI_FW_PATH, strlen(PCI_FW_PATH))) {
+                return -EINVAL;
+            }
+            bus = host->bus;
+            break;
+        }
+    }
+
+    for (;;) {
+        char *at;
+        char *comma;
+        unsigned long slot;
+        unsigned long func;
+        PCIDevice *dev;
+        PCIBus *child_bus;
+
+        if (!bus) {
+            return -ENODEV;
+        }
+        if (*p == '\0') {
+            return -EINVAL;
+        }
+
+        at = strchr(p, '@');
+        if (at == NULL) {
+            return -EINVAL;
+        }
+        slot = strtoul(at + 1, &e, 16);
+        if (e == at + 1 || *e != ',') {
+            return -EINVAL;
+        }
+        if (slot >= PCI_SLOT_MAX) {
+            return -EINVAL;
+        }
+
+        comma = e;
+        func = strtoul(comma + 1, &e, 16);
+        if (e == comma + 1 || (*e != '/' && *e != '\0')) {
+            return -EINVAL;
+        }
+        if (func >= PCI_FUNC_MAX) {
+            return -EINVAL;
+        }
+
+        len = e - p;
+        dev = bus->devices[PCI_DEVFN(slot, func)];
+        if (!dev) {
+            return -ENODEV;
+        }
+        if (at != p) {
+            /* fw_name is specified. */
+            char *fw_dev_path = pcibus_get_fw_dev_path(&dev->qdev);
+            if (strncmp(p, fw_dev_path, len)) {
+                qemu_free(fw_dev_path);
+                return -EINVAL;
+            }
+            qemu_free(fw_dev_path);
+        }
+
+        if (*e == '\0') {
+            *pdev = dev;
+            return 0;
+        }
+
+        /*
+         * descending down pci-to-pci bridge.
+         * At the moment, there is no way to safely determine if the given
+         * pci device is really pci-to-pci device.
+         */
+        p = e;
+        QLIST_FOREACH(child_bus, &bus->child, sibling) {
+            if (child_bus->parent_dev == dev) {
+                bus = child_bus;
+                continue;
+            }
+        }
+        bus = NULL;
+    }
+}
diff --git a/hw/pci.h b/hw/pci.h
index 052960e..fc46ada 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -16,6 +16,7 @@
 #define PCI_DEVFN(slot, func)   ((((slot) & 0x1f) << 3) | ((func) & 0x07))
 #define PCI_SLOT(devfn)         (((devfn) >> 3) & 0x1f)
 #define PCI_FUNC(devfn)         ((devfn) & 0x07)
+#define PCI_SLOT_MAX            32
 #define PCI_FUNC_MAX            8
 
 /* Class, Vendor and Device IDs from Linux's pci_ids.h */
@@ -259,6 +260,7 @@ int pci_parse_devaddr(const char *addr, int *domp, int *busp,
                       unsigned int *slotp, unsigned int *funcp);
 int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
                      unsigned *slotp);
+int pci_parse_fw_dev_path(const char *path, PCIDevice **pdev);
 
 void do_pci_info_print(Monitor *mon, const QObject *data);
 void do_pci_info(Monitor *mon, QObject **ret_data);
-- 
1.7.1.1

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

* [Qemu-devel] [PATCH v11 5/5] pcie/aer: use fw device path as fallback for aer injection command
  2010-12-24  3:14 [Qemu-devel] [PATCH v11 0/5] *** SUBJECT HERE *** Isaku Yamahata
                   ` (3 preceding siblings ...)
  2010-12-24  3:14 ` [Qemu-devel] [PATCH v11 4/5] pci: introduce a parser for fw device path to pci device Isaku Yamahata
@ 2010-12-24  3:14 ` Isaku Yamahata
  2010-12-24  8:36 ` [Qemu-devel] Re: [PATCH v11 0/5] pcie/aer: glue inject aer error into hmp Michael S. Tsirkin
  5 siblings, 0 replies; 7+ messages in thread
From: Isaku Yamahata @ 2010-12-24  3:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: yamahata, mst

pcie_aer_inject command: When qdev id failed, try fw device path as
fallback.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hmp-commands.hx |    7 ++++++-
 hw/pcie_aer.c   |   12 ++++++++----
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 8d84ddc..928ded4 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -878,12 +878,17 @@ ETEXI
 	              "id:s,error_status:s,"
 	              "header0:i?,header1:i?,header2:i?,header3:i?,"
 	              "prefix0:i?,prefix1:i?,prefix2:i?,prefix3:i?",
-        .params     = "[-a] [-c] id "
+        .params     = "[-a] [-c] [id|pci_fw_dev_path] "
                       "<error_status> [<tlp header> [<tlp header prefix>]]",
         .help       = "inject pcie aer error\n\t\t\t"
 	              " -a for advisory non fatal error\n\t\t\t"
 	              " -c for correctable error\n\t\t\t"
                       "<id> = qdev device id\n\t\t\t"
+                      "<pci_fw_dev_path> = fw device path to pci device"
+	              "\n\t\t\t/pci@<ioport or mmio(hex)>"
+                      "[<fw_name>]@<slot(hex)>,<func(hex)>/.../"
+                      "[<fw_name>]@<slot(hex)>,<func(hex)>\n\t\t\t"
+	              "e.g. /pci@i0cf8/@1,1\n\t\t\t"
                       "<error_status> = error string or 32bit\n\t\t\t"
                       "<tlb header> = 32bit x 4\n\t\t\t"
                       "<tlb header prefix> = 32bit x 4",
diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c
index 6e653dd..6bad79c 100644
--- a/hw/pcie_aer.c
+++ b/hw/pcie_aer.c
@@ -969,10 +969,14 @@ int do_pcie_aer_inejct_error(Monitor *mon,
 
     ret = pci_qdev_find_device(id, &dev);
     if (ret < 0) {
-        monitor_printf(mon,
-                       "id or pci device path is invalid or device not "
-                       "found. %s\n", id);
-        return ret;
+        /* fall back to fw device path */
+        ret = pci_parse_fw_dev_path(id, &dev);
+        if (ret < 0) {
+            monitor_printf(mon,
+                           "id or pci device path is invalid or device not "
+                           "found. %s\n", id);
+            return ret;
+        }
     }
     if (!pci_is_express(dev)) {
         monitor_printf(mon, "the device doesn't support pci express. %s\n",
-- 
1.7.1.1

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

* [Qemu-devel] Re: [PATCH v11 0/5] pcie/aer: glue inject aer error into hmp
  2010-12-24  3:14 [Qemu-devel] [PATCH v11 0/5] *** SUBJECT HERE *** Isaku Yamahata
                   ` (4 preceding siblings ...)
  2010-12-24  3:14 ` [Qemu-devel] [PATCH v11 5/5] pcie/aer: use fw device path as fallback for aer injection command Isaku Yamahata
@ 2010-12-24  8:36 ` Michael S. Tsirkin
  5 siblings, 0 replies; 7+ messages in thread
From: Michael S. Tsirkin @ 2010-12-24  8:36 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Dec 24, 2010 at 12:14:10PM +0900, Isaku Yamahata wrote:
> This patch series introduces hmp command to inject aer error.
> Now fw device path is used to specify pci function.
> 
> Changes v10 -> v11:
> - use qdev id and use fw dev path as fallback
> 
> Isaku Yamahata (5):
>   qdev: export qdev_find_recursive() for later use
>   pci: introduce a helper function to convert qdev id to PCIDevice
>   pcie/aer: glue aer error injection into qemu monitor

Applied 1-3, thanks.

>   pci: introduce a parser for fw device path to pci device
>   pcie/aer: use fw device path as fallback for aer injection command
> 
>  hmp-commands.hx |   30 +++++++
>  hw/pci-stub.c   |   13 +++
>  hw/pci.c        |  164 +++++++++++++++++++++++++++++++++++++++
>  hw/pci.h        |    3 +
>  hw/pcie_aer.c   |  227 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/qdev.c       |    2 +-
>  hw/qdev.h       |    2 +
>  sysemu.h        |    5 +
>  8 files changed, 445 insertions(+), 1 deletions(-)

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

end of thread, other threads:[~2010-12-24  8:36 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-12-24  3:14 [Qemu-devel] [PATCH v11 0/5] *** SUBJECT HERE *** Isaku Yamahata
2010-12-24  3:14 ` [Qemu-devel] [PATCH v11 1/5] qdev: export qdev_find_recursive() for later use Isaku Yamahata
2010-12-24  3:14 ` [Qemu-devel] [PATCH v11 2/5] pci: introduce a helper function to convert qdev id to PCIDevice Isaku Yamahata
2010-12-24  3:14 ` [Qemu-devel] [PATCH v11 3/5] pcie/aer: glue aer error injection into qemu monitor Isaku Yamahata
2010-12-24  3:14 ` [Qemu-devel] [PATCH v11 4/5] pci: introduce a parser for fw device path to pci device Isaku Yamahata
2010-12-24  3:14 ` [Qemu-devel] [PATCH v11 5/5] pcie/aer: use fw device path as fallback for aer injection command Isaku Yamahata
2010-12-24  8:36 ` [Qemu-devel] Re: [PATCH v11 0/5] pcie/aer: glue inject aer error into hmp Michael S. Tsirkin

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