[libvirt] [PATCH 1/1] perf: add support to perf event for MBM

2016-05-11 Thread Qiaowei Ren
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 
---
 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_att

[libvirt] [PATCH 1/1] perf: add support to perf event for MBM

2016-05-12 Thread Qiaowei Ren
Some Intel processor families (e.g. the Intel Xeon processor E5 v3
family) introduced some RDT (Resource Director Technology) features
to monitor or control shared resource. Among these features, MBM
(Memory Bandwidth Monitoring), which is build on the CMT (Cache
Monitoring Technology) infrastructure, provides OS/VMM a way to
monitor bandwidth from one level of cache to another.

With current perf framework, this patch adds support to perf event
for MBM.

Signed-off-by: Qiaowei Ren 
---
 include/libvirt/libvirt-domain.h | 18 
 src/qemu/qemu_driver.c   | 35 +++
 src/util/virperf.c   | 60 
 src/util/virperf.h   |  2 ++
 4 files changed, 85 insertions(+), 30 deletions(-)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 160f20f..e4594f0 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -1904,6 +1904,24 @@ void 
virDomainStatsRecordListFree(virDomainStatsRecordPtr *stats);
  */
 # define VIR_PERF_PARAM_CMT "cmt"
 
+/**
+ * VIR_PERF_PARAM_MBMT:
+ *
+ * Macro for typed parameter name that represents MBMT perf event
+ * which can be used to monitor total system bandwidth (bytes/s)
+ * from one level of cache to another.
+ */
+# define VIR_PERF_PARAM_MBMT "mbmt"
+
+/**
+ * VIR_PERF_PARAM_MBML:
+ *
+ * Macro for typed parameter name that represents MBML perf event
+ * which can be used to monitor the amount of data (bytes/s) sent
+ * through the memory controller on the socket.
+ */
+# 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..a3bd7ec 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;
 
@@ -19495,20 +19497,38 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
 #undef QEMU_ADD_COUNT_PARAM
 
 static int
-qemuDomainGetStatsPerfCmt(virPerfPtr perf,
+qemuDomainGetStatsPerfRdt(virPerfPtr perf,
+  virPerfEventType type,
   virDomainStatsRecordPtr record,
   int *maxparams)
 {
-uint64_t cache = 0;
+uint64_t value = 0;
 
-if (virPerfReadEvent(perf, VIR_PERF_EVENT_CMT, &cache) < 0)
+if (virPerfReadEvent(perf, type, &value) < 0)
 return -1;
 
-if (virTypedParamsAddULLong(&record->params,
+if (type == VIR_PERF_EVENT_CMT &&
+virTypedParamsAddULLong(&record->params,
 &record->nparams,
 maxparams,
 "perf.cache",
-cache) < 0)
+value) < 0)
+return -1;
+
+if (type == VIR_PERF_EVENT_MBMT &&
+virTypedParamsAddULLong(&record->params,
+&record->nparams,
+maxparams,
+"perf.total_bytes",
+value) < 0)
+return -1;
+
+if (type == VIR_PERF_EVENT_MBML &&
+virTypedParamsAddULLong(&record->params,
+&record->nparams,
+maxparams,
+"perf.local_bytes",
+value) < 0)
 return -1;
 
 return 0;
@@ -19531,7 +19551,10 @@ qemuDomainGetStatsPerf(virQEMUDriverPtr driver 
ATTRIBUTE_UNUSED,
 
 switch (i) {
 case VIR_PERF_EVENT_CMT:
-if (qemuDomainGetStatsPerfCmt(priv->perf, record, maxparams) < 0)
+case VIR_PERF_EVENT_MBMT:
+case VIR_PERF_EVENT_MBML:
+if (qemuDomainGetStatsPerfRdt(priv->perf, i,
+  record, maxparams) < 0)
 goto cleanup;
 break;
 }
diff --git a/src/util/virperf.c b/src/util/virperf.c
index bd65587..826d36a 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;
@@ -110,10 +110,10 @@ virPerfGetEvent(virPerfPtr perf,
 }
 
 static int
-virPerfCmtEnable(virPerfEventPtr event,
+virPerfRdtEnable(virPerfEventPtr event,
  pid_t pid)
 {
-struct perf_event_attr cmt_attr;
+struct perf_event_att

Re: [libvirt] [PATCH 1/1] perf: add support to perf event for MBM

2016-05-11 Thread Peter Krempa
On Wed, May 11, 2016 at 17:09:01 +0800, Qiaowei Ren wrote:
> 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 
> ---
>  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"

Neither of those documents the unit or meaning of the value.


[...]

> 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

[...]

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

Memory bandwidth seems like it's in MiB/s thus dividing by 1 000 000
is not the right conversion. Additionally we should report it in
bytes/s. The users can always convert it to any value they like.

> +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;
> +}

Both above functions are almost identical. I think  you could merge them
and pass the difference as an argument.

> +
> +static int
>  qemuDomainGetStatsPerf(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
> virDomainObjPtr dom,
> virDomainStatsRecordPtr record,

[...]


> 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

[...]

> @@ -132,26 +132,36 @@ virPerfCmtEnable(virPerfEventPtr event,

This does not seem to be the correct function to put this. All the
variables and name hint that it's CMT specific ...

>  }
>  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;

Re: [libvirt] [PATCH 1/1] perf: add support to perf event for MBM

2016-05-12 Thread Peter Krempa
On Thu, May 12, 2016 at 14:55:16 +0800, Qiaowei Ren wrote:
> Some Intel processor families (e.g. the Intel Xeon processor E5 v3
> family) introduced some RDT (Resource Director Technology) features
> to monitor or control shared resource. Among these features, MBM
> (Memory Bandwidth Monitoring), which is build on the CMT (Cache
> Monitoring Technology) infrastructure, provides OS/VMM a way to
> monitor bandwidth from one level of cache to another.
> 
> With current perf framework, this patch adds support to perf event
> for MBM.
> 
> Signed-off-by: Qiaowei Ren 
> ---
>  include/libvirt/libvirt-domain.h | 18 
>  src/qemu/qemu_driver.c   | 35 +++
>  src/util/virperf.c   | 60 
> 
>  src/util/virperf.h   |  2 ++
>  4 files changed, 85 insertions(+), 30 deletions(-)
> 
> diff --git a/include/libvirt/libvirt-domain.h 
> b/include/libvirt/libvirt-domain.h
> index 160f20f..e4594f0 100644
> --- a/include/libvirt/libvirt-domain.h
> +++ b/include/libvirt/libvirt-domain.h
> @@ -1904,6 +1904,24 @@ void 
> virDomainStatsRecordListFree(virDomainStatsRecordPtr *stats);
>   */
>  # define VIR_PERF_PARAM_CMT "cmt"
>  
> +/**
> + * VIR_PERF_PARAM_MBMT:
> + *
> + * Macro for typed parameter name that represents MBMT perf event
> + * which can be used to monitor total system bandwidth (bytes/s)
> + * from one level of cache to another.
> + */
> +# define VIR_PERF_PARAM_MBMT "mbmt"
> +
> +/**
> + * VIR_PERF_PARAM_MBML:
> + *
> + * Macro for typed parameter name that represents MBML perf event
> + * which can be used to monitor the amount of data (bytes/s) sent
> + * through the memory controller on the socket.
> + */
> +# define VIR_PERF_PARAM_MBML "mbml"


So I was a little bit mistaken what this is documenting. So these
document the arguments for virDomainSetPerfEvents where the perf stuff
is enabled.

I was actually thinking this is documenting the values that are returned
via the virConnectGetAllDomainStats/virDomainListGetStats APIs. I've
just noticed that the perf events are not documented at all there.

This should be fixed also for the CMT event. This part of the
documentation should then state which fields in the *Stats APIs the perf
events correspond to.

In the documentation for the fields returned bulk Stats API the 
individual fields should be marked by which event they are produced.

> +
>  int virDomainGetPerfEvents(virDomainPtr dom,
> virTypedParameterPtr *params,
> int *nparams,
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index c4c4968..a3bd7ec 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;
>  
> @@ -19495,20 +19497,38 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
>  #undef QEMU_ADD_COUNT_PARAM
>  
>  static int
> -qemuDomainGetStatsPerfCmt(virPerfPtr perf,
> +qemuDomainGetStatsPerfRdt(virPerfPtr perf,
> +  virPerfEventType type,
>virDomainStatsRecordPtr record,
>int *maxparams)
>  {
> -uint64_t cache = 0;
> +uint64_t value = 0;
>  
> -if (virPerfReadEvent(perf, VIR_PERF_EVENT_CMT, &cache) < 0)
> +if (virPerfReadEvent(perf, type, &value) < 0)
>  return -1;
>  
> -if (virTypedParamsAddULLong(&record->params,
> +if (type == VIR_PERF_EVENT_CMT &&
> +virTypedParamsAddULLong(&record->params,
>  &record->nparams,
>  maxparams,
>  "perf.cache",
> -cache) < 0)
> +value) < 0)
> +return -1;
> +
> +if (type == VIR_PERF_EVENT_MBMT &&
> +virTypedParamsAddULLong(&record->params,
> +&record->nparams,
> +maxparams,
> +"perf.total_bytes",

If you pass this string into this function you won't need to special
case all the different types.

Also by naming the fields similarly to the name of the feature
(virPerfEvent enum) you could entirely avoid the need to pass the name
of the value as it could be generated by the virPerfEventTypeToString.
(concatenate it with 'perf.' to get 'perf.mbmt', 'perf.cmt' and
'perf.mbml').

Unfortunately the implementation of the CMT event already used a
different name for the stats entry.

Since this actually was never documented I would be in favor of changing
perf.cache to perf.cmt, s

Re: [libvirt] [PATCH 1/1] perf: add support to perf event for MBM

2016-05-12 Thread Ren, Qiaowei

> -Original Message-
> From: Peter Krempa [mailto:pkre...@redhat.com]
> Sent: Thursday, May 12, 2016 4:31 PM
> To: Ren, Qiaowei 
> Cc: libvir-list@redhat.com; berra...@redhat.com
> Subject: Re: [libvirt] [PATCH 1/1] perf: add support to perf event for MBM
> 
> On Thu, May 12, 2016 at 14:55:16 +0800, Qiaowei Ren wrote:
> > Some Intel processor families (e.g. the Intel Xeon processor E5 v3
> > family) introduced some RDT (Resource Director Technology) features to
> > monitor or control shared resource. Among these features, MBM (Memory
> > Bandwidth Monitoring), which is build on the CMT (Cache Monitoring
> > Technology) infrastructure, provides OS/VMM a way to monitor bandwidth
> > from one level of cache to another.
> >
> > With current perf framework, this patch adds support to perf event for
> > MBM.
> >
> > Signed-off-by: Qiaowei Ren 
> > ---
> >  include/libvirt/libvirt-domain.h | 18 
> >  src/qemu/qemu_driver.c   | 35 +++
> >  src/util/virperf.c   | 60 
> > 
> >  src/util/virperf.h   |  2 ++
> >  4 files changed, 85 insertions(+), 30 deletions(-)
> >
> > diff --git a/include/libvirt/libvirt-domain.h
> > b/include/libvirt/libvirt-domain.h
> > index 160f20f..e4594f0 100644
> > --- a/include/libvirt/libvirt-domain.h
> > +++ b/include/libvirt/libvirt-domain.h
> > @@ -1904,6 +1904,24 @@ void
> virDomainStatsRecordListFree(virDomainStatsRecordPtr *stats);
> >   */
> >  # define VIR_PERF_PARAM_CMT "cmt"
> >
> > +/**
> > + * VIR_PERF_PARAM_MBMT:
> > + *
> > + * Macro for typed parameter name that represents MBMT perf event
> > + * which can be used to monitor total system bandwidth (bytes/s)
> > + * from one level of cache to another.
> > + */
> > +# define VIR_PERF_PARAM_MBMT "mbmt"
> > +
> > +/**
> > + * VIR_PERF_PARAM_MBML:
> > + *
> > + * Macro for typed parameter name that represents MBML perf event
> > + * which can be used to monitor the amount of data (bytes/s) sent
> > + * through the memory controller on the socket.
> > + */
> > +# define VIR_PERF_PARAM_MBML "mbml"
> 
> 
> So I was a little bit mistaken what this is documenting. So these document the
> arguments for virDomainSetPerfEvents where the perf stuff is enabled.
> 
> I was actually thinking this is documenting the values that are returned via 
> the
> virConnectGetAllDomainStats/virDomainListGetStats APIs. I've just noticed that
> the perf events are not documented at all there.
> 
> This should be fixed also for the CMT event. This part of the documentation
> should then state which fields in the *Stats APIs the perf events correspond 
> to.
> 
> In the documentation for the fields returned bulk Stats API the individual 
> fields
> should be marked by which event they are produced.
> 

Sure. The documentation will be added.

> > +
> >  int virDomainGetPerfEvents(virDomainPtr dom,
> > virTypedParameterPtr *params,
> > int *nparams, diff --git
> > a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index
> > c4c4968..a3bd7ec 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;
> >
> > @@ -19495,20 +19497,38 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr
> > driver,  #undef QEMU_ADD_COUNT_PARAM
> >
> >  static int
> > -qemuDomainGetStatsPerfCmt(virPerfPtr perf,
> > +qemuDomainGetStatsPerfRdt(virPerfPtr perf,
> > +  virPerfEventType type,
> >virDomainStatsRecordPtr record,
> >int *maxparams)  {
> > -uint64_t cache = 0;
> > +uint64_t value = 0;
> >
> > -if (virPerfReadEvent(perf, VIR_PERF_EVENT_CMT, &cache) < 0)
> > +if (virPerfReadEvent(perf, type, &value) < 0)
> >  return -1;
> >
> > -if (virTypedParamsAddULLong(&record->params,
> > +if (type == VIR_PERF_EVENT_CMT &&