perf: Adjust the perf initialization

Introduce a static attr table and refactor virPerfEventEnable() for
general purpose usage.

This patch creates a static table/matrix that converts the VIR_PERF_EVENT_*
events into their respective "attr.type" and "attr.config" so that
virPerfEventEnable doesn't have the switch the calling function passes
by value the 'type'.

Signed-off-by: Qiaowei Ren <qiaowei.ren@intel.com>
This commit is contained in:
Qiaowei Ren 2016-08-03 13:23:31 -04:00 committed by John Ferlan
parent 63358e0b87
commit b00d7f298b

View File

@ -61,6 +61,72 @@ struct virPerf {
# include <linux/perf_event.h>
struct virPerfEventAttr {
int type;
unsigned int attrType;
unsigned long long attrConfig;
};
static struct virPerfEventAttr attrs[] = {
{.type = VIR_PERF_EVENT_CMT, .attrType = 0, .attrConfig = 1},
{.type = VIR_PERF_EVENT_MBMT, .attrType = 0, .attrConfig = 2},
{.type = VIR_PERF_EVENT_MBML, .attrType = 0, .attrConfig = 3},
};
typedef struct virPerfEventAttr *virPerfEventAttrPtr;
static virPerfEventAttrPtr
virPerfGetEventAttr(virPerfEventType type)
{
size_t i;
if (type >= VIR_PERF_EVENT_LAST) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Event '%d' is not supported"),
type);
return NULL;
}
for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
if (i == type)
return attrs + i;
}
return NULL;
}
static int
virPerfRdtAttrInit(void)
{
char *buf = NULL;
char *tmp = NULL;
unsigned int attr_type = 0;
if (virFileReadAll("/sys/devices/intel_cqm/type", 10, &buf) < 0)
goto error;
if ((tmp = strchr(buf, '\n')))
*tmp = '\0';
if (virStrToLong_ui(buf, NULL, 10, &attr_type) < 0) {
virReportSystemError(errno, "%s",
_("failed to get rdt event type"));
goto error;
}
VIR_FREE(buf);
attrs[VIR_PERF_EVENT_CMT].attrType = attr_type;
attrs[VIR_PERF_EVENT_MBMT].attrType = attr_type;
attrs[VIR_PERF_EVENT_MBML].attrType = attr_type;
return 0;
error:
VIR_FREE(buf);
return -1;
}
static virPerfEventPtr
virPerfGetEvent(virPerfPtr perf,
virPerfEventType type)
@ -78,64 +144,55 @@ virPerfGetEvent(virPerfPtr perf,
return perf->events + type;
}
static int
virPerfRdtEnable(virPerfEventPtr event,
pid_t pid)
int
virPerfEventEnable(virPerfPtr perf,
virPerfEventType type,
pid_t pid)
{
struct perf_event_attr rdt_attr;
char *buf = NULL;
char *tmp = NULL;
unsigned int event_type, scale;
struct perf_event_attr attr;
virPerfEventPtr event = virPerfGetEvent(perf, type);
virPerfEventAttrPtr event_attr = virPerfGetEventAttr(type);
if (virFileReadAll("/sys/devices/intel_cqm/type",
10, &buf) < 0)
goto error;
if (!event || !event_attr)
return -1;
if ((tmp = strchr(buf, '\n')))
*tmp = '\0';
if (virStrToLong_ui(buf, NULL, 10, &event_type) < 0) {
virReportSystemError(errno, "%s",
_("failed to get rdt event type"));
goto error;
if (event_attr->attrType == 0 && (type == VIR_PERF_EVENT_CMT ||
type == VIR_PERF_EVENT_MBMT ||
type == VIR_PERF_EVENT_MBML)) {
virReportSystemError(errno,
_("Unable to open perf event for %s"),
virPerfEventTypeToString(event->type));
return -1;
}
VIR_FREE(buf);
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;
switch (event->type) {
case VIR_PERF_EVENT_CMT:
if (type == 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) {
if (virStrToLong_i(buf, NULL, 10, &event->efields.cmt.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;
VIR_FREE(buf);
}
event->fd = syscall(__NR_perf_event_open, &rdt_attr, pid, -1, -1, 0);
memset(&attr, 0, sizeof(attr));
attr.size = sizeof(attr);
attr.inherit = 1;
attr.disabled = 1;
attr.enable_on_exec = 0;
attr.type = event_attr->attrType;
attr.config = event_attr->attrConfig;
event->fd = syscall(__NR_perf_event_open, &attr, pid, -1, -1, 0);
if (event->fd < 0) {
virReportSystemError(errno,
_("Unable to open perf type=%d for pid=%d"),
event_type, pid);
_("Unable to open perf event for %s"),
virPerfEventTypeToString(event->type));
goto error;
}
@ -155,31 +212,6 @@ virPerfRdtEnable(virPerfEventPtr event,
return -1;
}
int
virPerfEventEnable(virPerfPtr perf,
virPerfEventType type,
pid_t pid)
{
virPerfEventPtr event = virPerfGetEvent(perf, type);
if (event == NULL)
return -1;
switch (type) {
case VIR_PERF_EVENT_CMT:
case VIR_PERF_EVENT_MBMT:
case VIR_PERF_EVENT_MBML:
if (virPerfRdtEnable(event, pid) < 0)
return -1;
break;
case VIR_PERF_EVENT_LAST:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected perf event type=%d"), type);
return -1;
}
return 0;
}
int
virPerfEventDisable(virPerfPtr perf,
virPerfEventType type)
@ -232,6 +264,13 @@ virPerfReadEvent(virPerfPtr perf,
}
#else
static int
virPerfRdtAttrInit(void)
{
return 0;
}
int
virPerfEventEnable(virPerfPtr perf ATTRIBUTE_UNUSED,
virPerfEventType type ATTRIBUTE_UNUSED,
@ -285,6 +324,9 @@ virPerfNew(void)
perf->events[i].enabled = false;
}
if (virPerfRdtAttrInit() < 0)
virResetLastError();
return perf;
}