mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
perf: add support to perf event for MBM
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 <qiaowei.ren@intel.com>
This commit is contained in:
parent
e4cbfa717a
commit
90b9995d1d
@ -1900,10 +1900,34 @@ void virDomainStatsRecordListFree(virDomainStatsRecordPtr *stats);
|
||||
/**
|
||||
* VIR_PERF_PARAM_CMT:
|
||||
*
|
||||
* Macro for typed parameter name that represents CMT perf event.
|
||||
* Macro for typed parameter name that represents CMT perf event
|
||||
* which can be used to measure the usage of cache (bytes) by
|
||||
* applications running on the platform. It corresponds to the
|
||||
* "perf.cmt" field in the *Stats APIs.
|
||||
*/
|
||||
# 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. It corresponds to the
|
||||
* "perf.mbmt" field in the *Stats APIs.
|
||||
|
||||
*/
|
||||
# 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. It corresponds to
|
||||
* the "perf.mbml" field in the *Stats APIs.
|
||||
*/
|
||||
# define VIR_PERF_PARAM_MBML "mbml"
|
||||
|
||||
int virDomainGetPerfEvents(virDomainPtr dom,
|
||||
virTypedParameterPtr *params,
|
||||
int *nparams,
|
||||
|
@ -11441,6 +11441,18 @@ virConnectGetDomainCapabilities(virConnectPtr conn,
|
||||
* "block.<num>.physical" - physical size in bytes of the container of the
|
||||
* backing image as unsigned long long.
|
||||
*
|
||||
* VIR_DOMAIN_STATS_PERF: Return perf event statistics.
|
||||
* The typed parameter keys are in this format:
|
||||
* "perf.cmt" - the usage of l3 cache (bytes) by applications running on the
|
||||
* platform as unsigned long long. It is produced by cmt perf
|
||||
* event.
|
||||
* "perf.mbmt" - the total system bandwidth (bytes/s) from one level of cache
|
||||
* to another as unsigned long long. It is produced by mbmt perf
|
||||
* event.
|
||||
* "perf.mbml" - the amount of data (bytes/s) sent through the memory controller
|
||||
* on the socket as unsigned long long. It is produced by mbml
|
||||
* perf event.
|
||||
*
|
||||
* Note that entire stats groups or individual stat fields may be missing from
|
||||
* the output in case they are not supported by the given hypervisor, are not
|
||||
* applicable for the current state of the guest domain, or their retrieval
|
||||
|
@ -10038,6 +10038,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;
|
||||
|
||||
@ -19479,20 +19481,25 @@ 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;
|
||||
char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
|
||||
uint64_t value = 0;
|
||||
|
||||
if (virPerfReadEvent(perf, VIR_PERF_EVENT_CMT, &cache) < 0)
|
||||
if (virPerfReadEvent(perf, type, &value) < 0)
|
||||
return -1;
|
||||
|
||||
snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, "perf.%s",
|
||||
virPerfEventTypeToString(type));
|
||||
|
||||
if (virTypedParamsAddULLong(&record->params,
|
||||
&record->nparams,
|
||||
maxparams,
|
||||
"perf.cache",
|
||||
cache) < 0)
|
||||
param_name,
|
||||
value) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
@ -19515,7 +19522,9 @@ 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;
|
||||
}
|
||||
|
@ -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_attr rdt_attr;
|
||||
char *buf = NULL;
|
||||
char *tmp = NULL;
|
||||
unsigned int event_type, scale;
|
||||
@ -127,32 +127,42 @@ virPerfCmtEnable(virPerfEventPtr event,
|
||||
|
||||
if (virStrToLong_ui(buf, NULL, 10, &event_type) < 0) {
|
||||
virReportSystemError(errno, "%s",
|
||||
_("failed to get cmt event type"));
|
||||
_("failed to get rdt event type"));
|
||||
goto error;
|
||||
}
|
||||
VIR_FREE(buf);
|
||||
|
||||
if (virFileReadAll("/sys/devices/intel_cqm/events/llc_occupancy.scale",
|
||||
10, &buf) < 0)
|
||||
goto error;
|
||||
memset(&rdt_attr, 0, sizeof(rdt_attr));
|
||||
rdt_attr.size = sizeof(rdt_attr);
|
||||
rdt_attr.type = event_type;
|
||||
rdt_attr.inherit = 1;
|
||||
rdt_attr.disabled = 1;
|
||||
rdt_attr.enable_on_exec = 0;
|
||||
|
||||
if (virStrToLong_ui(buf, NULL, 10, &scale) < 0) {
|
||||
virReportSystemError(errno, "%s",
|
||||
_("failed to get cmt scaling factor"));
|
||||
goto error;
|
||||
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;
|
||||
|
||||
rdt_attr.config = 1;
|
||||
break;
|
||||
case VIR_PERF_EVENT_MBMT:
|
||||
rdt_attr.config = 2;
|
||||
break;
|
||||
case VIR_PERF_EVENT_MBML:
|
||||
rdt_attr.config = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
event->fd = syscall(__NR_perf_event_open, &cmt_attr, pid, -1, -1, 0);
|
||||
event->fd = syscall(__NR_perf_event_open, &rdt_attr, pid, -1, -1, 0);
|
||||
if (event->fd < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to open perf type=%d for pid=%d"),
|
||||
@ -161,8 +171,9 @@ virPerfCmtEnable(virPerfEventPtr event,
|
||||
}
|
||||
|
||||
if (ioctl(event->fd, PERF_EVENT_IOC_ENABLE) < 0) {
|
||||
virReportSystemError(errno, "%s",
|
||||
_("Unable to enable perf event for CMT"));
|
||||
virReportSystemError(errno,
|
||||
_("Unable to enable perf event for %s"),
|
||||
virPerfEventTypeToString(event->type));
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -186,7 +197,9 @@ virPerfEventEnable(virPerfPtr perf,
|
||||
|
||||
switch (type) {
|
||||
case VIR_PERF_EVENT_CMT:
|
||||
if (virPerfCmtEnable(event, pid) < 0)
|
||||
case VIR_PERF_EVENT_MBMT:
|
||||
case VIR_PERF_EVENT_MBML:
|
||||
if (virPerfRdtEnable(event, pid) < 0)
|
||||
return -1;
|
||||
break;
|
||||
case VIR_PERF_EVENT_LAST:
|
||||
|
@ -26,6 +26,8 @@
|
||||
|
||||
typedef enum {
|
||||
VIR_PERF_EVENT_CMT,
|
||||
VIR_PERF_EVENT_MBMT,
|
||||
VIR_PERF_EVENT_MBML,
|
||||
|
||||
VIR_PERF_EVENT_LAST
|
||||
} virPerfEventType;
|
||||
|
Loading…
Reference in New Issue
Block a user