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