MBM (Memory Bandwidth Monitoring) is a new feature introduced in some
Intel processor families. MBM is build on the CMT (Cache Monitoring
Technology) infrastructure to allow monitoring of bandwidth from one
level of the cache hierarchy to the next. With current perf framework,
this patch adds support to perf event for MBM.
Signed-off-by: Qiaowei Ren <qiaowei.ren(a)intel.com>
---
include/libvirt/libvirt-domain.h | 14 +++++++++++
src/qemu/qemu_driver.c | 50 ++++++++++++++++++++++++++++++++++++++++
src/util/virperf.c | 40 +++++++++++++++++++++-----------
src/util/virperf.h | 2 ++
4 files changed, 92 insertions(+), 14 deletions(-)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 160f20f..9c3795c 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -1904,6 +1904,20 @@ void virDomainStatsRecordListFree(virDomainStatsRecordPtr *stats);
*/
# define VIR_PERF_PARAM_CMT "cmt"
+/**
+ * VIR_PERF_PARAM_MBMT:
+ *
+ * Macro for typed parameter name that represents MBMT perf event.
+ */
+# define VIR_PERF_PARAM_MBMT "mbmt"
+
+/**
+ * VIR_PERF_PARAM_MBML:
+ *
+ * Macro for typed parameter name that represents MBML perf event.
+ */
+# define VIR_PERF_PARAM_MBML "mbml"
+
int virDomainGetPerfEvents(virDomainPtr dom,
virTypedParameterPtr *params,
int *nparams,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index c4c4968..8c79e49 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -10051,6 +10051,8 @@ qemuDomainSetPerfEvents(virDomainPtr dom,
if (virTypedParamsValidate(params, nparams,
VIR_PERF_PARAM_CMT, VIR_TYPED_PARAM_BOOLEAN,
+ VIR_PERF_PARAM_MBMT, VIR_TYPED_PARAM_BOOLEAN,
+ VIR_PERF_PARAM_MBML, VIR_TYPED_PARAM_BOOLEAN,
NULL) < 0)
return -1;
@@ -19515,6 +19517,46 @@ qemuDomainGetStatsPerfCmt(virPerfPtr perf,
}
static int
+qemuDomainGetStatsPerfMbmt(virPerfPtr perf,
+ virDomainStatsRecordPtr record,
+ int *maxparams)
+{
+ uint64_t total_bytes = 0;
+
+ if (virPerfReadEvent(perf, VIR_PERF_EVENT_MBMT, &total_bytes) < 0)
+ return -1;
+
+ if (virTypedParamsAddDouble(&record->params,
+ &record->nparams,
+ maxparams,
+ "perf.total_bytes",
+ total_bytes*1e-6) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+qemuDomainGetStatsPerfMbml(virPerfPtr perf,
+ virDomainStatsRecordPtr record,
+ int *maxparams)
+{
+ uint64_t local_bytes = 0;
+
+ if (virPerfReadEvent(perf, VIR_PERF_EVENT_MBML, &local_bytes) < 0)
+ return -1;
+
+ if (virTypedParamsAddDouble(&record->params,
+ &record->nparams,
+ maxparams,
+ "perf.local_bytes",
+ local_bytes*1e-6) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int
qemuDomainGetStatsPerf(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
virDomainObjPtr dom,
virDomainStatsRecordPtr record,
@@ -19534,6 +19576,14 @@ qemuDomainGetStatsPerf(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
if (qemuDomainGetStatsPerfCmt(priv->perf, record, maxparams) < 0)
goto cleanup;
break;
+ case VIR_PERF_EVENT_MBMT:
+ if (qemuDomainGetStatsPerfMbmt(priv->perf, record, maxparams) < 0)
+ goto cleanup;
+ break;
+ case VIR_PERF_EVENT_MBML:
+ if (qemuDomainGetStatsPerfMbml(priv->perf, record, maxparams) < 0)
+ goto cleanup;
+ break;
}
}
diff --git a/src/util/virperf.c b/src/util/virperf.c
index bd65587..7cfdd77 100644
--- a/src/util/virperf.c
+++ b/src/util/virperf.c
@@ -38,7 +38,7 @@ VIR_LOG_INIT("util.perf");
#define VIR_FROM_THIS VIR_FROM_PERF
VIR_ENUM_IMPL(virPerfEvent, VIR_PERF_EVENT_LAST,
- "cmt");
+ "cmt", "mbmt", "mbml");
struct virPerfEvent {
int type;
@@ -132,26 +132,36 @@ virPerfCmtEnable(virPerfEventPtr event,
}
VIR_FREE(buf);
- if (virFileReadAll("/sys/devices/intel_cqm/events/llc_occupancy.scale",
- 10, &buf) < 0)
- goto error;
-
- if (virStrToLong_ui(buf, NULL, 10, &scale) < 0) {
- virReportSystemError(errno, "%s",
- _("failed to get cmt scaling factor"));
- goto error;
- }
-
- event->efields.cmt.scale = scale;
-
memset(&cmt_attr, 0, sizeof(cmt_attr));
cmt_attr.size = sizeof(cmt_attr);
cmt_attr.type = event_type;
- cmt_attr.config = 1;
cmt_attr.inherit = 1;
cmt_attr.disabled = 1;
cmt_attr.enable_on_exec = 0;
+ switch (event->type) {
+ case VIR_PERF_EVENT_CMT:
+ if
(virFileReadAll("/sys/devices/intel_cqm/events/llc_occupancy.scale",
+ 10, &buf) < 0)
+ goto error;
+
+ if (virStrToLong_ui(buf, NULL, 10, &scale) < 0) {
+ virReportSystemError(errno, "%s",
+ _("failed to get cmt scaling factor"));
+ goto error;
+ }
+ event->efields.cmt.scale = scale;
+
+ cmt_attr.config = 1;
+ break;
+ case VIR_PERF_EVENT_MBMT:
+ cmt_attr.config = 2;
+ break;
+ case VIR_PERF_EVENT_MBML:
+ cmt_attr.config = 3;
+ break;
+ }
+
event->fd = syscall(__NR_perf_event_open, &cmt_attr, pid, -1, -1, 0);
if (event->fd < 0) {
virReportSystemError(errno,
@@ -186,6 +196,8 @@ virPerfEventEnable(virPerfPtr perf,
switch (type) {
case VIR_PERF_EVENT_CMT:
+ case VIR_PERF_EVENT_MBMT:
+ case VIR_PERF_EVENT_MBML:
if (virPerfCmtEnable(event, pid) < 0)
return -1;
break;
diff --git a/src/util/virperf.h b/src/util/virperf.h
index 8ec8753..769e85a 100644
--- a/src/util/virperf.h
+++ b/src/util/virperf.h
@@ -26,6 +26,8 @@
typedef enum {
VIR_PERF_EVENT_CMT,
+ VIR_PERF_EVENT_MBMT,
+ VIR_PERF_EVENT_MBML,
VIR_PERF_EVENT_LAST
} virPerfEventType;
--
1.9.1