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