[libvirt] [PATCH v4 4/8] qemu_driver: add support to perf event

Qiaowei Ren qiaowei.ren at intel.com
Mon Mar 28 13:30:29 UTC 2016


This patch implement the internal driver API for perf event into
qemu driver.

Signed-off-by: Qiaowei Ren <qiaowei.ren at 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 b171cdf..552a40b 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -1804,6 +1804,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 573968c..4d581d7 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"
@@ -195,6 +196,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 da039c4..599d5ed 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -99,6 +99,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"
@@ -10037,6 +10038,86 @@ qemuSetGlobalBWLive(virCgroupPtr cgroup, unsigned long long period,
 }
 
 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 = &params[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)
 {
@@ -19401,6 +19482,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,
@@ -19421,6 +19551,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 }
 };
 
@@ -20177,6 +20308,8 @@ static virHypervisorDriver qemuHypervisorDriver = {
     .domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */
     .domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */
     .domainSendKey = qemuDomainSendKey, /* 0.9.4 */
+    .domainGetPerfEvents = qemuDomainGetPerfEvents, /* 1.3.3 */
+    .domainSetPerfEvents = qemuDomainSetPerfEvents, /* 1.3.3 */
     .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 6ec7b76..f7d30e9 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5253,6 +5253,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 &&
@@ -5890,6 +5894,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




More information about the libvir-list mailing list