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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

Signed-off-by: Qiaowei Ren <qiaowei.ren@xxxxxxxxx>
---
 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 cc1b29b..4f29f54 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 14892fd..080498e 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 ae1d8e7..888241f 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"
@@ -10249,6 +10250,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 = &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)
 {
@@ -19427,6 +19508,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))
+                goto cleanup;
+            break;
+        }
+    }
+
+    ret = 0;
+
+ cleanup:
+    return ret;
+}
+
 typedef int
 (*qemuDomainGetStatsFunc)(virQEMUDriverPtr driver,
                           virDomainObjPtr dom,
@@ -19447,6 +19577,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 }
 };
 
@@ -20207,6 +20338,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 4201962..8679d29 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4844,6 +4844,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 &&
@@ -5391,6 +5395,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

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list



[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]