aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuval Shaia <yuval.shaia@oracle.com>2019-03-11 03:29:09 -0700
committerMarcel Apfelbaum <marcel.apfelbaum@gmail.com>2019-03-16 15:52:44 +0200
commitf4b2c02a2911b164474b998532b1a963fc9b785b (patch)
tree79f2982c291e4f2a78a3892699982f1150b4d419
parentc2dd117b38583f89d6a2e4a6dfc6d693990ffc39 (diff)
downloadqemu-f4b2c02a2911b164474b998532b1a963fc9b785b.zip
qemu-f4b2c02a2911b164474b998532b1a963fc9b785b.tar.gz
qemu-f4b2c02a2911b164474b998532b1a963fc9b785b.tar.bz2
{hmp, hw/pvrdma}: Expose device internals via monitor interface
Allow interrogating device internals through HMP interface. The exposed indicators can be used for troubleshooting by developers or sysadmin. There is no need to expose these attributes to a management system (e.x. libvirt) because (1) most of them are not "device-management' related info and (2) there is no guarantee the interface is stable. Signed-off-by: Yuval Shaia <yuval.shaia@oracle.com> Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Acked-by: Markus Armbruster <armbru@redhat.com> Message-Id: <1552300155-25216-6-git-send-email-yuval.shaia@oracle.com> Reviewed-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com> Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
-rw-r--r--hmp-commands-info.hx14
-rw-r--r--hmp.c27
-rw-r--r--hmp.h1
-rw-r--r--hw/rdma/Makefile.objs2
-rw-r--r--hw/rdma/rdma.c30
-rw-r--r--hw/rdma/rdma_rm.c53
-rw-r--r--hw/rdma/rdma_rm.h1
-rw-r--r--hw/rdma/vmw/pvrdma_main.c26
-rw-r--r--include/hw/rdma/rdma.h40
9 files changed, 193 insertions, 1 deletions
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index cbee8b9..c59444c 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -205,6 +205,20 @@ Show PIC state.
ETEXI
{
+ .name = "rdma",
+ .args_type = "",
+ .params = "",
+ .help = "show RDMA state",
+ .cmd = hmp_info_rdma,
+ },
+
+STEXI
+@item info rdma
+@findex info rdma
+Show RDMA state.
+ETEXI
+
+ {
.name = "pci",
.args_type = "",
.params = "",
diff --git a/hmp.c b/hmp.c
index 4a702d5..fa1e59a 100644
--- a/hmp.c
+++ b/hmp.c
@@ -51,6 +51,7 @@
#include "qemu/error-report.h"
#include "exec/ramlist.h"
#include "hw/intc/intc.h"
+#include "hw/rdma/rdma.h"
#include "migration/snapshot.h"
#include "migration/misc.h"
@@ -1013,6 +1014,32 @@ void hmp_info_pic(Monitor *mon, const QDict *qdict)
hmp_info_pic_foreach, mon);
}
+static int hmp_info_rdma_foreach(Object *obj, void *opaque)
+{
+ RdmaProvider *rdma;
+ RdmaProviderClass *k;
+ Monitor *mon = opaque;
+
+ if (object_dynamic_cast(obj, INTERFACE_RDMA_PROVIDER)) {
+ rdma = RDMA_PROVIDER(obj);
+ k = RDMA_PROVIDER_GET_CLASS(obj);
+ if (k->print_statistics) {
+ k->print_statistics(mon, rdma);
+ } else {
+ monitor_printf(mon, "RDMA statistics not available for %s.\n",
+ object_get_typename(obj));
+ }
+ }
+
+ return 0;
+}
+
+void hmp_info_rdma(Monitor *mon, const QDict *qdict)
+{
+ object_child_foreach_recursive(object_get_root(),
+ hmp_info_rdma_foreach, mon);
+}
+
void hmp_info_pci(Monitor *mon, const QDict *qdict)
{
PciInfoList *info_list, *info;
diff --git a/hmp.h b/hmp.h
index e0f32f0..43617f2 100644
--- a/hmp.h
+++ b/hmp.h
@@ -36,6 +36,7 @@ void hmp_info_spice(Monitor *mon, const QDict *qdict);
void hmp_info_balloon(Monitor *mon, const QDict *qdict);
void hmp_info_irq(Monitor *mon, const QDict *qdict);
void hmp_info_pic(Monitor *mon, const QDict *qdict);
+void hmp_info_rdma(Monitor *mon, const QDict *qdict);
void hmp_info_pci(Monitor *mon, const QDict *qdict);
void hmp_info_block_jobs(Monitor *mon, const QDict *qdict);
void hmp_info_tpm(Monitor *mon, const QDict *qdict);
diff --git a/hw/rdma/Makefile.objs b/hw/rdma/Makefile.objs
index bd36cbf..c354e60 100644
--- a/hw/rdma/Makefile.objs
+++ b/hw/rdma/Makefile.objs
@@ -1,5 +1,5 @@
ifeq ($(CONFIG_PVRDMA),y)
-obj-$(CONFIG_PCI) += rdma_utils.o rdma_backend.o rdma_rm.o
+obj-$(CONFIG_PCI) += rdma_utils.o rdma_backend.o rdma_rm.o rdma.o
obj-$(CONFIG_PCI) += vmw/pvrdma_dev_ring.o vmw/pvrdma_cmd.o \
vmw/pvrdma_qp_ops.o vmw/pvrdma_main.o
endif
diff --git a/hw/rdma/rdma.c b/hw/rdma/rdma.c
new file mode 100644
index 0000000..7bec0d0
--- /dev/null
+++ b/hw/rdma/rdma.c
@@ -0,0 +1,30 @@
+/*
+ * RDMA device interface
+ *
+ * Copyright (C) 2018 Oracle
+ * Copyright (C) 2018 Red Hat Inc
+ *
+ * Authors:
+ * Yuval Shaia <yuval.shaia@oracle.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/rdma/rdma.h"
+#include "qemu/module.h"
+
+static const TypeInfo rdma_hmp_info = {
+ .name = INTERFACE_RDMA_PROVIDER,
+ .parent = TYPE_INTERFACE,
+ .class_size = sizeof(RdmaProviderClass),
+};
+
+static void rdma_register_types(void)
+{
+ type_register_static(&rdma_hmp_info);
+}
+
+type_init(rdma_register_types)
diff --git a/hw/rdma/rdma_rm.c b/hw/rdma/rdma_rm.c
index 35fa1ab..b50e192 100644
--- a/hw/rdma/rdma_rm.c
+++ b/hw/rdma/rdma_rm.c
@@ -16,6 +16,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "cpu.h"
+#include "monitor/monitor.h"
#include "trace.h"
#include "rdma_utils.h"
@@ -26,6 +27,58 @@
#define PG_DIR_SZ { TARGET_PAGE_SIZE / sizeof(__u64) }
#define PG_TBL_SZ { TARGET_PAGE_SIZE / sizeof(__u64) }
+void rdma_dump_device_counters(Monitor *mon, RdmaDeviceResources *dev_res)
+{
+ monitor_printf(mon, "\ttx : %" PRId64 "\n",
+ dev_res->stats.tx);
+ monitor_printf(mon, "\ttx_len : %" PRId64 "\n",
+ dev_res->stats.tx_len);
+ monitor_printf(mon, "\ttx_err : %" PRId64 "\n",
+ dev_res->stats.tx_err);
+ monitor_printf(mon, "\trx_bufs : %" PRId64 "\n",
+ dev_res->stats.rx_bufs);
+ monitor_printf(mon, "\trx_bufs_len : %" PRId64 "\n",
+ dev_res->stats.rx_bufs_len);
+ monitor_printf(mon, "\trx_bufs_err : %" PRId64 "\n",
+ dev_res->stats.rx_bufs_err);
+ monitor_printf(mon, "\tcomps : %" PRId64 "\n",
+ dev_res->stats.completions);
+ monitor_printf(mon, "\tmissing_comps : %" PRId32 "\n",
+ dev_res->stats.missing_cqe);
+ monitor_printf(mon, "\tpoll_cq (bk) : %" PRId64 "\n",
+ dev_res->stats.poll_cq_from_bk);
+ monitor_printf(mon, "\tpoll_cq_ppoll_to : %" PRId64 "\n",
+ dev_res->stats.poll_cq_ppoll_to);
+ monitor_printf(mon, "\tpoll_cq (fe) : %" PRId64 "\n",
+ dev_res->stats.poll_cq_from_guest);
+ monitor_printf(mon, "\tpoll_cq_empty : %" PRId64 "\n",
+ dev_res->stats.poll_cq_from_guest_empty);
+ monitor_printf(mon, "\tmad_tx : %" PRId64 "\n",
+ dev_res->stats.mad_tx);
+ monitor_printf(mon, "\tmad_tx_err : %" PRId64 "\n",
+ dev_res->stats.mad_tx_err);
+ monitor_printf(mon, "\tmad_rx : %" PRId64 "\n",
+ dev_res->stats.mad_rx);
+ monitor_printf(mon, "\tmad_rx_err : %" PRId64 "\n",
+ dev_res->stats.mad_rx_err);
+ monitor_printf(mon, "\tmad_rx_bufs : %" PRId64 "\n",
+ dev_res->stats.mad_rx_bufs);
+ monitor_printf(mon, "\tmad_rx_bufs_err : %" PRId64 "\n",
+ dev_res->stats.mad_rx_bufs_err);
+ monitor_printf(mon, "\tPDs : %" PRId32 "\n",
+ dev_res->pd_tbl.used);
+ monitor_printf(mon, "\tMRs : %" PRId32 "\n",
+ dev_res->mr_tbl.used);
+ monitor_printf(mon, "\tUCs : %" PRId32 "\n",
+ dev_res->uc_tbl.used);
+ monitor_printf(mon, "\tQPs : %" PRId32 "\n",
+ dev_res->qp_tbl.used);
+ monitor_printf(mon, "\tCQs : %" PRId32 "\n",
+ dev_res->cq_tbl.used);
+ monitor_printf(mon, "\tCEQ_CTXs : %" PRId32 "\n",
+ dev_res->cqe_ctx_tbl.used);
+}
+
static inline void res_tbl_init(const char *name, RdmaRmResTbl *tbl,
uint32_t tbl_sz, uint32_t res_sz)
{
diff --git a/hw/rdma/rdma_rm.h b/hw/rdma/rdma_rm.h
index f9b2ec5..4f03f9b 100644
--- a/hw/rdma/rdma_rm.h
+++ b/hw/rdma/rdma_rm.h
@@ -81,5 +81,6 @@ static inline union ibv_gid *rdma_rm_get_gid(RdmaDeviceResources *dev_res,
{
return &dev_res->port.gid_tbl[sgid_idx].gid;
}
+void rdma_dump_device_counters(Monitor *mon, RdmaDeviceResources *dev_res);
#endif
diff --git a/hw/rdma/vmw/pvrdma_main.c b/hw/rdma/vmw/pvrdma_main.c
index dd35646..729a2df 100644
--- a/hw/rdma/vmw/pvrdma_main.c
+++ b/hw/rdma/vmw/pvrdma_main.c
@@ -25,6 +25,8 @@
#include "cpu.h"
#include "trace.h"
#include "sysemu/sysemu.h"
+#include "monitor/monitor.h"
+#include "hw/rdma/rdma.h"
#include "../rdma_rm.h"
#include "../rdma_backend.h"
@@ -55,6 +57,26 @@ static Property pvrdma_dev_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
+static void pvrdma_print_statistics(Monitor *mon, RdmaProvider *obj)
+{
+ PVRDMADev *dev = PVRDMA_DEV(obj);
+ PCIDevice *pdev = PCI_DEVICE(dev);
+
+ monitor_printf(mon, "%s, %x.%x\n", pdev->name, PCI_SLOT(pdev->devfn),
+ PCI_FUNC(pdev->devfn));
+ monitor_printf(mon, "\tcommands : %" PRId64 "\n",
+ dev->stats.commands);
+ monitor_printf(mon, "\tregs_reads : %" PRId64 "\n",
+ dev->stats.regs_reads);
+ monitor_printf(mon, "\tregs_writes : %" PRId64 "\n",
+ dev->stats.regs_writes);
+ monitor_printf(mon, "\tuar_writes : %" PRId64 "\n",
+ dev->stats.uar_writes);
+ monitor_printf(mon, "\tinterrupts : %" PRId64 "\n",
+ dev->stats.interrupts);
+ rdma_dump_device_counters(mon, &dev->rdma_dev_res);
+}
+
static void free_dev_ring(PCIDevice *pci_dev, PvrdmaRing *ring,
void *ring_state)
{
@@ -639,6 +661,7 @@ static void pvrdma_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ RdmaProviderClass *ir = INTERFACE_RDMA_PROVIDER_CLASS(klass);
k->realize = pvrdma_realize;
k->exit = pvrdma_exit;
@@ -650,6 +673,8 @@ static void pvrdma_class_init(ObjectClass *klass, void *data)
dc->desc = "RDMA Device";
dc->props = pvrdma_dev_properties;
set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
+
+ ir->print_statistics = pvrdma_print_statistics;
}
static const TypeInfo pvrdma_info = {
@@ -659,6 +684,7 @@ static const TypeInfo pvrdma_info = {
.class_init = pvrdma_class_init,
.interfaces = (InterfaceInfo[]) {
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
+ { INTERFACE_RDMA_PROVIDER },
{ }
}
};
diff --git a/include/hw/rdma/rdma.h b/include/hw/rdma/rdma.h
new file mode 100644
index 0000000..68290fb
--- /dev/null
+++ b/include/hw/rdma/rdma.h
@@ -0,0 +1,40 @@
+/*
+ * RDMA device interface
+ *
+ * Copyright (C) 2019 Oracle
+ * Copyright (C) 2019 Red Hat Inc
+ *
+ * Authors:
+ * Yuval Shaia <yuval.shaia@oracle.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef RDMA_H
+#define RDMA_H
+
+#include "qom/object.h"
+
+#define INTERFACE_RDMA_PROVIDER "rdma"
+
+#define INTERFACE_RDMA_PROVIDER_CLASS(klass) \
+ OBJECT_CLASS_CHECK(RdmaProviderClass, (klass), \
+ INTERFACE_RDMA_PROVIDER)
+#define RDMA_PROVIDER_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(RdmaProviderClass, (obj), \
+ INTERFACE_RDMA_PROVIDER)
+#define RDMA_PROVIDER(obj) \
+ INTERFACE_CHECK(RdmaProvider, (obj), \
+ INTERFACE_RDMA_PROVIDER)
+
+typedef struct RdmaProvider RdmaProvider;
+
+typedef struct RdmaProviderClass {
+ InterfaceClass parent;
+
+ void (*print_statistics)(Monitor *mon, RdmaProvider *obj);
+} RdmaProviderClass;
+
+#endif