This patch implement the internal driver API for perf event into
qemu driver.
Signed-off-by: Qiaowei Ren <qiaowei.ren(a)intel.com>
---
include/libvirt/libvirt-domain.h | 1 +
src/qemu/qemu_domain.h | 3 +
src/qemu/qemu_driver.c | 133 +++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_process.c | 6 ++
4 files changed, 143 insertions(+)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 5e39bb3..dff260a 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -1771,6 +1771,7 @@ typedef enum {
VIR_DOMAIN_STATS_VCPU = (1 << 3), /* return domain virtual CPU info */
VIR_DOMAIN_STATS_INTERFACE = (1 << 4), /* return domain interfaces info */
VIR_DOMAIN_STATS_BLOCK = (1 << 5), /* return domain block info */
+ VIR_DOMAIN_STATS_PERF = (1 << 6), /* return domain perf event info */
} virDomainStatsTypes;
typedef enum {
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 7fc4fff..2db4342 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -26,6 +26,7 @@
# include "virthread.h"
# include "vircgroup.h"
+# include "virperf.h"
# include "domain_addr.h"
# include "domain_conf.h"
# include "snapshot_conf.h"
@@ -191,6 +192,8 @@ struct _qemuDomainObjPrivate {
virCgroupPtr cgroup;
+ virPerfPtr perf;
+
virCond unplugFinished; /* signals that unpluggingDevice was unplugged */
const char *unpluggingDevice; /* alias of the device that is being unplugged */
char **qemuDevices; /* NULL-terminated list of devices aliases known to QEMU */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index abcdbe6..58d6015 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -98,6 +98,7 @@
#include "virhostdev.h"
#include "domain_capabilities.h"
#include "vircgroup.h"
+#include "virperf.h"
#include "virnuma.h"
#include "dirname.h"
#include "network/bridge_driver.h"
@@ -10320,6 +10321,86 @@ qemuDomainGetNumaParameters(virDomainPtr dom,
}
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
qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
unsigned long long period, long long quota)
{
@@ -19497,6 +19578,55 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
#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
(*qemuDomainGetStatsFunc)(virQEMUDriverPtr driver,
virDomainObjPtr dom,
@@ -19517,6 +19647,7 @@ static struct qemuDomainGetStatsWorker qemuDomainGetStatsWorkers[]
= {
{ qemuDomainGetStatsVcpu, VIR_DOMAIN_STATS_VCPU, false },
{ qemuDomainGetStatsInterface, VIR_DOMAIN_STATS_INTERFACE, false },
{ qemuDomainGetStatsBlock, VIR_DOMAIN_STATS_BLOCK, true },
+ { qemuDomainGetStatsPerf, VIR_DOMAIN_STATS_PERF, false },
{ NULL, 0, false }
};
@@ -20277,6 +20408,8 @@ static virHypervisorDriver qemuHypervisorDriver = {
.domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */
.domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */
.domainSendKey = qemuDomainSendKey, /* 0.9.4 */
+ .domainGetPerfEvents = qemuDomainGetPerfEvents, /* 1.3.1 */
+ .domainSetPerfEvents = qemuDomainSetPerfEvents, /* 1.3.1 */
.domainBlockJobAbort = qemuDomainBlockJobAbort, /* 0.9.4 */
.domainGetBlockJobInfo = qemuDomainGetBlockJobInfo, /* 0.9.4 */
.domainBlockJobSetSpeed = qemuDomainBlockJobSetSpeed, /* 0.9.4 */
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index ee94d3f..ae4b9ba 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4940,6 +4940,10 @@ qemuProcessLaunch(virConnectPtr conn,
if (qemuSetupCgroup(driver, vm, nnicindexes, nicindexes) < 0)
goto cleanup;
+ priv->perf = virPerfNew();
+ if (!priv->perf)
+ goto cleanup;
+
/* This must be done after cgroup placement to avoid resetting CPU
* affinity */
if (!vm->def->cputune.emulatorpin &&
@@ -5487,6 +5491,8 @@ void qemuProcessStop(virQEMUDriverPtr driver,
}
virCgroupFree(&priv->cgroup);
+ virPerfFree(priv->perf);
+
qemuProcessRemoveDomainStatus(driver, vm);
/* Remove VNC and Spice ports from port reservation bitmap, but only if
--
1.9.1