mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
qemu_driver: add support to perf event
This patch implement the internal driver API for perf event into qemu driver. Signed-off-by: Qiaowei Ren <qiaowei.ren@intel.com> Message-id: 1459171833-26416-5-git-send-email-qiaowei.ren@intel.com
This commit is contained in:
parent
28b446292b
commit
0dd0165c03
@ -1804,6 +1804,7 @@ typedef enum {
|
|||||||
VIR_DOMAIN_STATS_VCPU = (1 << 3), /* return domain virtual CPU info */
|
VIR_DOMAIN_STATS_VCPU = (1 << 3), /* return domain virtual CPU info */
|
||||||
VIR_DOMAIN_STATS_INTERFACE = (1 << 4), /* return domain interfaces info */
|
VIR_DOMAIN_STATS_INTERFACE = (1 << 4), /* return domain interfaces info */
|
||||||
VIR_DOMAIN_STATS_BLOCK = (1 << 5), /* return domain block info */
|
VIR_DOMAIN_STATS_BLOCK = (1 << 5), /* return domain block info */
|
||||||
|
VIR_DOMAIN_STATS_PERF = (1 << 6), /* return domain perf event info */
|
||||||
} virDomainStatsTypes;
|
} virDomainStatsTypes;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
# include "virthread.h"
|
# include "virthread.h"
|
||||||
# include "vircgroup.h"
|
# include "vircgroup.h"
|
||||||
|
# include "virperf.h"
|
||||||
# include "domain_addr.h"
|
# include "domain_addr.h"
|
||||||
# include "domain_conf.h"
|
# include "domain_conf.h"
|
||||||
# include "snapshot_conf.h"
|
# include "snapshot_conf.h"
|
||||||
@ -195,6 +196,8 @@ struct _qemuDomainObjPrivate {
|
|||||||
|
|
||||||
virCgroupPtr cgroup;
|
virCgroupPtr cgroup;
|
||||||
|
|
||||||
|
virPerfPtr perf;
|
||||||
|
|
||||||
virCond unplugFinished; /* signals that unpluggingDevice was unplugged */
|
virCond unplugFinished; /* signals that unpluggingDevice was unplugged */
|
||||||
const char *unpluggingDevice; /* alias of the device that is being unplugged */
|
const char *unpluggingDevice; /* alias of the device that is being unplugged */
|
||||||
char **qemuDevices; /* NULL-terminated list of devices aliases known to QEMU */
|
char **qemuDevices; /* NULL-terminated list of devices aliases known to QEMU */
|
||||||
|
@ -99,6 +99,7 @@
|
|||||||
#include "virhostdev.h"
|
#include "virhostdev.h"
|
||||||
#include "domain_capabilities.h"
|
#include "domain_capabilities.h"
|
||||||
#include "vircgroup.h"
|
#include "vircgroup.h"
|
||||||
|
#include "virperf.h"
|
||||||
#include "virnuma.h"
|
#include "virnuma.h"
|
||||||
#include "dirname.h"
|
#include "dirname.h"
|
||||||
#include "network/bridge_driver.h"
|
#include "network/bridge_driver.h"
|
||||||
@ -10036,6 +10037,86 @@ qemuSetGlobalBWLive(virCgroupPtr cgroup, unsigned long long period,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuDomainSetPerfEvents(virDomainPtr dom,
|
||||||
|
virTypedParameterPtr params,
|
||||||
|
int nparams)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
virDomainObjPtr vm = NULL;
|
||||||
|
qemuDomainObjPrivatePtr priv;
|
||||||
|
int ret = -1;
|
||||||
|
virPerfEventType type;
|
||||||
|
bool enabled;
|
||||||
|
|
||||||
|
if (virTypedParamsValidate(params, nparams, VIR_PERF_PARAMETERS) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!(vm = qemuDomObjFromDomain(dom)))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
priv = vm->privateData;
|
||||||
|
|
||||||
|
if (virDomainSetPerfEventsEnsureACL(dom->conn, vm->def) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
for (i = 0; i < nparams; i++) {
|
||||||
|
virTypedParameterPtr param = ¶ms[i];
|
||||||
|
enabled = params->value.b;
|
||||||
|
type = virPerfEventTypeFromString(param->field);
|
||||||
|
|
||||||
|
if (!enabled && virPerfEventDisable(priv->perf, type))
|
||||||
|
goto cleanup;
|
||||||
|
if (enabled && virPerfEventEnable(priv->perf, type, vm->pid))
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virDomainObjEndAPI(&vm);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuDomainGetPerfEvents(virDomainPtr dom,
|
||||||
|
virTypedParameterPtr *params,
|
||||||
|
int *nparams)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
virDomainObjPtr vm = NULL;
|
||||||
|
qemuDomainObjPrivatePtr priv;
|
||||||
|
int ret = -1;
|
||||||
|
virTypedParameterPtr par = NULL;
|
||||||
|
int maxpar = 0;
|
||||||
|
int npar = 0;
|
||||||
|
|
||||||
|
if (!(vm = qemuDomObjFromDomain(dom)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
priv = vm->privateData;
|
||||||
|
|
||||||
|
if (virDomainGetPerfEventsEnsureACL(dom->conn, vm->def) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
|
||||||
|
if (virTypedParamsAddBoolean(&par, &npar, &maxpar,
|
||||||
|
virPerfEventTypeToString(i),
|
||||||
|
virPerfEventIsEnabled(priv->perf, i)) < 0) {
|
||||||
|
virTypedParamsFree(par, npar);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*params = par;
|
||||||
|
*nparams = npar;
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virDomainObjEndAPI(&vm);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
|
qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
|
||||||
unsigned long long period, long long quota)
|
unsigned long long period, long long quota)
|
||||||
@ -19401,6 +19482,55 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
|
|||||||
|
|
||||||
#undef QEMU_ADD_COUNT_PARAM
|
#undef QEMU_ADD_COUNT_PARAM
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuDomainGetStatsPerfCmt(virPerfPtr perf,
|
||||||
|
virDomainStatsRecordPtr record,
|
||||||
|
int *maxparams)
|
||||||
|
{
|
||||||
|
uint64_t cache = 0;
|
||||||
|
|
||||||
|
if (virPerfReadEvent(perf, VIR_PERF_EVENT_CMT, &cache) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (virTypedParamsAddULLong(&record->params,
|
||||||
|
&record->nparams,
|
||||||
|
maxparams,
|
||||||
|
"perf.cache",
|
||||||
|
cache) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuDomainGetStatsPerf(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
|
||||||
|
virDomainObjPtr dom,
|
||||||
|
virDomainStatsRecordPtr record,
|
||||||
|
int *maxparams,
|
||||||
|
unsigned int privflags ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
qemuDomainObjPrivatePtr priv = dom->privateData;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
|
||||||
|
if (!virPerfEventIsEnabled(priv->perf, i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (i) {
|
||||||
|
case VIR_PERF_EVENT_CMT:
|
||||||
|
if (qemuDomainGetStatsPerfCmt(priv->perf, record, maxparams) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
typedef int
|
typedef int
|
||||||
(*qemuDomainGetStatsFunc)(virQEMUDriverPtr driver,
|
(*qemuDomainGetStatsFunc)(virQEMUDriverPtr driver,
|
||||||
virDomainObjPtr dom,
|
virDomainObjPtr dom,
|
||||||
@ -19421,6 +19551,7 @@ static struct qemuDomainGetStatsWorker qemuDomainGetStatsWorkers[] = {
|
|||||||
{ qemuDomainGetStatsVcpu, VIR_DOMAIN_STATS_VCPU, false },
|
{ qemuDomainGetStatsVcpu, VIR_DOMAIN_STATS_VCPU, false },
|
||||||
{ qemuDomainGetStatsInterface, VIR_DOMAIN_STATS_INTERFACE, false },
|
{ qemuDomainGetStatsInterface, VIR_DOMAIN_STATS_INTERFACE, false },
|
||||||
{ qemuDomainGetStatsBlock, VIR_DOMAIN_STATS_BLOCK, true },
|
{ qemuDomainGetStatsBlock, VIR_DOMAIN_STATS_BLOCK, true },
|
||||||
|
{ qemuDomainGetStatsPerf, VIR_DOMAIN_STATS_PERF, false },
|
||||||
{ NULL, 0, false }
|
{ NULL, 0, false }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -20177,6 +20308,8 @@ static virHypervisorDriver qemuHypervisorDriver = {
|
|||||||
.domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */
|
.domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */
|
||||||
.domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */
|
.domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */
|
||||||
.domainSendKey = qemuDomainSendKey, /* 0.9.4 */
|
.domainSendKey = qemuDomainSendKey, /* 0.9.4 */
|
||||||
|
.domainGetPerfEvents = qemuDomainGetPerfEvents, /* 1.3.3 */
|
||||||
|
.domainSetPerfEvents = qemuDomainSetPerfEvents, /* 1.3.3 */
|
||||||
.domainBlockJobAbort = qemuDomainBlockJobAbort, /* 0.9.4 */
|
.domainBlockJobAbort = qemuDomainBlockJobAbort, /* 0.9.4 */
|
||||||
.domainGetBlockJobInfo = qemuDomainGetBlockJobInfo, /* 0.9.4 */
|
.domainGetBlockJobInfo = qemuDomainGetBlockJobInfo, /* 0.9.4 */
|
||||||
.domainBlockJobSetSpeed = qemuDomainBlockJobSetSpeed, /* 0.9.4 */
|
.domainBlockJobSetSpeed = qemuDomainBlockJobSetSpeed, /* 0.9.4 */
|
||||||
|
@ -5253,6 +5253,10 @@ qemuProcessLaunch(virConnectPtr conn,
|
|||||||
if (qemuSetupCgroup(driver, vm, nnicindexes, nicindexes) < 0)
|
if (qemuSetupCgroup(driver, vm, nnicindexes, nicindexes) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
priv->perf = virPerfNew();
|
||||||
|
if (!priv->perf)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
/* This must be done after cgroup placement to avoid resetting CPU
|
/* This must be done after cgroup placement to avoid resetting CPU
|
||||||
* affinity */
|
* affinity */
|
||||||
if (!vm->def->cputune.emulatorpin &&
|
if (!vm->def->cputune.emulatorpin &&
|
||||||
@ -5890,6 +5894,8 @@ void qemuProcessStop(virQEMUDriverPtr driver,
|
|||||||
}
|
}
|
||||||
virCgroupFree(&priv->cgroup);
|
virCgroupFree(&priv->cgroup);
|
||||||
|
|
||||||
|
virPerfFree(priv->perf);
|
||||||
|
|
||||||
qemuProcessRemoveDomainStatus(driver, vm);
|
qemuProcessRemoveDomainStatus(driver, vm);
|
||||||
|
|
||||||
/* Remove VNC and Spice ports from port reservation bitmap, but only if
|
/* Remove VNC and Spice ports from port reservation bitmap, but only if
|
||||||
|
Loading…
Reference in New Issue
Block a user