]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu_driver: add support to perf event
authorQiaowei Ren <qiaowei.ren@intel.com>
Mon, 28 Mar 2016 13:30:29 +0000 (21:30 +0800)
committerDaniel P. Berrange <berrange@redhat.com>
Tue, 29 Mar 2016 12:13:05 +0000 (13:13 +0100)
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

include/libvirt/libvirt-domain.h
src/qemu/qemu_domain.h
src/qemu/qemu_driver.c
src/qemu/qemu_process.c

index b171cdfa991c65103f1bca9a3766105bf169e325..552a40b92cd7574afc849ac2f7cc75d498300626 100644 (file)
@@ -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 {
index 573968ce9af5489970a271d3165bc1f0879027c3..4d581d738a79d515ee162f91f55fa3a78299a02b 100644 (file)
@@ -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 */
index da039c42f8c57b9af1cfbbb0ccfd5a9aac56a01c..599d5ed075dc57344c7947d8bdd37502e931951b 100644 (file)
@@ -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"
@@ -10036,6 +10037,86 @@ qemuSetGlobalBWLive(virCgroupPtr cgroup, unsigned long long period,
     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 = &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 */
index 6ec7b76694db4a06926a8155164be9cbe0ebafa5..f7d30e9c59304a048c0a4df3b742247b22a5da7c 100644 (file)
@@ -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