All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Lluís Vilanova" <vilanova@ac.upc.edu>
To: qemu-devel@nongnu.org
Cc: "Emilio G. Cota" <cota@braap.org>, Stefan Hajnoczi <stefanha@redhat.com>
Subject: [Qemu-devel] [PATCH 06/13] instrument: Add event control interface
Date: Mon, 24 Jul 2017 20:26:39 +0300	[thread overview]
Message-ID: <150091719881.30739.10096572040779058122.stgit@frigg.lan> (raw)
In-Reply-To: <150091574424.30739.4131793221953168474.stgit@frigg.lan>

Adds public and internal APIs to control event instrumentation.

It also adds an event object (QI_EVENT_${NAME}) and define to know if it's staically enabled (QI_EVENT_${NAME}_ENABLED).

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 Makefile                                   |    1 
 configure                                  |    4 
 instrument/Makefile.objs                   |    5 
 instrument/control.c                       |  316 ++++++++++++++++++++++++++++
 instrument/control.h                       |   86 ++++++++
 instrument/qemu-instr/control.h            |  128 +++++++++++
 instrument/qemu-instr/types.h              |    8 +
 scripts/tracetool/backend/instr_dynamic.py |   14 +
 scripts/tracetool/format/c.py              |   37 +++
 scripts/tracetool/format/instr_api_h.py    |   13 +
 trace/event-internal.h                     |   10 +
 11 files changed, 615 insertions(+), 7 deletions(-)
 create mode 100644 instrument/control.c
 create mode 100644 instrument/control.h
 create mode 100644 instrument/qemu-instr/control.h

diff --git a/Makefile b/Makefile
index c8be326790..ee54b7e17a 100644
--- a/Makefile
+++ b/Makefile
@@ -688,6 +688,7 @@ ifeq ($(TRACE_INSTRUMENT_BACKEND),instr-dynamic)
 	$(INSTALL_DIR) "$(DESTDIR)$(includedir)/qemu-instr"
 	$(INSTALL_DATA) $(SRC_PATH)/instrument/qemu-instr/types.h "$(DESTDIR)$(includedir)/qemu-instr/"
 	$(INSTALL_DATA) $(SRC_PATH)/instrument/qemu-instr/visibility-internal.h "$(DESTDIR)$(includedir)/qemu-instr/"
+	$(INSTALL_DATA) $(SRC_PATH)/instrument/qemu-instr/control.h "$(DESTDIR)$(includedir)/qemu-instr/"
 	$(INSTALL_DATA) $(BUILD_DIR)/instrument/qemu-instr/events.h "$(DESTDIR)$(includedir)/qemu-instr/"
 endif
 
diff --git a/configure b/configure
index ca61665874..320309e0c0 100755
--- a/configure
+++ b/configure
@@ -6019,10 +6019,14 @@ QEMU_INCLUDES="-I\$(SRC_PATH)/tcg $QEMU_INCLUDES"
 echo "TRACE_INSTRUMENT_BACKEND=instr-$trace_instrument_backend" >> $config_host_mak
 if test "$trace_instrument" = "yes"; then
     echo "CONFIG_INSTRUMENT=y" >> $config_host_mak
+    libs_qga="-ldl $libs_qga"
+    LDFLAGS="-rdynamic $LDFLAGS"
 fi
 if test -n "$instrument_events"; then
     echo "CONFIG_INSTRUMENT_EVENTS=$instrument_events" >> $config_host_mak
 fi
+# code requiring it is always compiled-in
+LIBS="-ldl $LIBS"
 ##########################################
 
 echo "TOOLS=$tools" >> $config_host_mak
diff --git a/instrument/Makefile.objs b/instrument/Makefile.objs
index c2289aba85..244936aa8c 100644
--- a/instrument/Makefile.objs
+++ b/instrument/Makefile.objs
@@ -38,3 +38,8 @@ $(obj)/qemu-instr/events.h-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_DIR)
 		--backend=$(TRACE_INSTRUMENT_BACKEND) \
 		$(TRACETOOL_INSTR_STATIC) \
 		$< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
+
+######################################################################
+# Control code
+
+target-obj-y += control.o
diff --git a/instrument/control.c b/instrument/control.c
new file mode 100644
index 0000000000..309228f15d
--- /dev/null
+++ b/instrument/control.c
@@ -0,0 +1,316 @@
+/*
+ * Interface for controlling dynamic trace instrumentation.
+ *
+ * Copyright (C) 2012-2017 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+
+#include <dlfcn.h>
+#include "instrument/control.h"
+#include "qemu/thread.h"
+#include "qemu-instr/control.h"
+#include "qemu/error-report.h"
+
+
+typedef int64_t HandleID;
+
+typedef struct Handle
+{
+    HandleID id;
+    void *dlhandle;
+    void (*init)(int, const char **);
+    void (*fini)(void);
+    QSLIST_ENTRY(Handle) list;
+} Handle;
+
+HandleID handle_last_id;
+QSLIST_HEAD(, Handle) handles = QSLIST_HEAD_INITIALIZER(handles);
+static QemuMutex instr_lock;
+
+
+static Handle *handle_get(void)
+{
+    Handle *res = g_malloc0(sizeof(Handle));
+    res->id = handle_last_id++;
+    QSLIST_INSERT_HEAD(&handles, res, list);
+    return res;
+}
+
+static bool handle_put(HandleID id)
+{
+    Handle *prev = NULL;
+    Handle *handle;
+    QSLIST_FOREACH(handle, &handles, list) {
+        if (handle->id == id) {
+            break;
+        }
+        prev = handle;
+    }
+    if (handle == NULL) {
+        return false;
+    } else {
+        if (prev == NULL) {
+            QSLIST_REMOVE_HEAD(&handles, list);
+        } else {
+            QSLIST_REMOVE_AFTER(prev, list);
+        }
+        g_free(handle);
+        return true;
+    }
+}
+
+#if defined(CONFIG_INSTRUMENT)
+static Handle *handle_find(HandleID id)
+{
+    Handle *handle;
+    QSLIST_FOREACH(handle, &handles, list) {
+        if (handle->id == id) {
+            return handle;
+        }
+    }
+    return NULL;
+}
+#endif
+
+static bool instr_available(void)
+{
+#if defined(CONFIG_INSTRUMENT)
+    return true;
+#else
+    return false;
+#endif
+}
+
+InstrLoadError instr_load(const char * path, int argc, const char ** argv,
+                          int64_t *handle_id)
+{
+    InstrLoadError res;
+
+    qemu_rec_mutex_lock(&instr_lock);
+
+    *handle_id = -1;
+    if (!instr_available()) {
+        res = INSTR_LOAD_UNAVAILABLE;
+        goto out;
+    }
+
+    if (!QSLIST_EMPTY(&handles) > 0) {
+        /* XXX: This is in fact a hard-coded limit, but there's no reason why a
+         *      real multi-library implementation should fail with something like
+         *      "too many open libraries".
+         */
+        res = INSTR_LOAD_UNAVAILABLE;
+        goto out;
+    }
+
+    Handle * handle = handle_get();
+    handle->dlhandle = dlopen(path, RTLD_NOW);
+    if (handle->dlhandle == NULL) {
+        goto err;
+    }
+
+    handle->init = dlsym(handle->dlhandle, "qi_init");
+    if (handle->init == NULL) {
+        goto err;
+    }
+    handle->fini = dlsym(handle->dlhandle, "qi_fini");
+    if (handle->fini == NULL) {
+        goto err;
+    }
+
+    handle->init(argc, argv);
+
+    *handle_id = handle->id;
+    res = INSTR_LOAD_OK;
+    goto out;
+
+err:
+    handle_put(handle->id);
+    res = INSTR_LOAD_ERROR;
+out:
+    qemu_rec_mutex_unlock(&instr_lock);
+    return res;
+}
+
+static inline bool instr_event_is_instrument(TraceEvent *ev)
+{
+#if defined(CONFIG_INSTRUMENT)
+    return ev->is_instr;
+#else
+    return false;
+#endif
+}
+
+InstrUnloadError instr_unload(int64_t handle_id)
+{
+    InstrLoadError res;
+
+    qemu_rec_mutex_lock(&instr_lock);
+
+    if (!instr_available()) {
+        res = INSTR_UNLOAD_UNAVAILABLE;
+        goto out;
+    }
+
+#if defined(CONFIG_INSTRUMENT)
+    Handle *handle = handle_find(handle_id);
+    if (handle == NULL) {
+        res = INSTR_UNLOAD_INVALID;
+        goto out;
+    }
+
+    handle->fini();
+
+    TraceEventIter iter;
+    TraceEvent *ev = NULL;
+    trace_event_iter_init(&iter, NULL);
+    while ((ev = trace_event_iter_next(&iter)) != NULL) {
+        if (instr_event_is_instrument(ev)) {
+            *ev->instr_cb = ev->instr_cb_default;
+        }
+    }
+
+    /* this should never fail */
+    if (dlclose(handle->dlhandle) < 0) {
+        res = INSTR_UNLOAD_ERROR;
+    } else {
+        res = INSTR_UNLOAD_OK;
+    }
+    handle_put(handle->id);
+#endif
+
+out:
+    qemu_rec_mutex_unlock(&instr_lock);
+    return res;
+}
+
+InstrUnloadError instr_unload_all(void)
+{
+    InstrUnloadError res = INSTR_UNLOAD_OK;
+
+    qemu_rec_mutex_lock(&instr_lock);
+    while (true) {
+        Handle *handle = QSLIST_FIRST(&handles);
+        if (handle == NULL) {
+            break;
+        } else {
+            res = instr_unload(handle->id);
+            if (res != INSTR_UNLOAD_OK) {
+                break;
+            }
+        }
+    }
+    qemu_rec_mutex_unlock(&instr_lock);
+
+    return res;
+}
+
+void qi_ctrl_event_set(QIEvent *ev, void *cb)
+{
+    TraceEvent *tev = (TraceEvent *)ev;
+
+    if (unlikely(tev == NULL)) {
+        error_report("qi_ctrl_event_set: event is NULL");
+        return;
+    }
+
+#if defined(CONFIG_INSTRUMENT)
+    if (unlikely(!tev->is_instr)) {
+        error_report("qi_ctrl_event_set: event is not instrumentable");
+        return;
+    }
+
+    if (cb == NULL) {
+        *tev->instr_cb = tev->instr_cb_default;
+    } else {
+        *tev->instr_cb = cb;
+    }
+#else
+    assert(false);
+#endif  /* defined(CONFIG_INSTRUMENT) */
+}
+
+bool qi_trace_event_get_state_static(QIEvent *ev)
+{
+    if (unlikely(ev == NULL)) {
+        error_report("qi_trace_event_get_state_static: event is NULL");
+        return false;
+    }
+    return trace_event_get_state_static((TraceEvent *)ev);
+}
+
+bool qi_trace_event_get_state_dynamic(QIEvent *ev)
+{
+    if (unlikely(ev == NULL)) {
+        error_report("qi_trace_event_get_state_dynamic: event is NULL");
+        return false;
+    }
+    return trace_event_get_state_dynamic((TraceEvent *)ev);
+}
+
+bool qi_trace_event_get_vcpu_state_dynamic(QICPU *vcpu, QIEvent *ev)
+{
+    TraceEvent *tev = (TraceEvent *)ev;
+
+    if (unlikely(vcpu == NULL)) {
+        error_report("qi_trace_event_get_vcpu_state_dynamic: vcpu is NULL");
+        return false;
+    }
+    if (unlikely(tev == NULL)) {
+        error_report("qi_trace_event_get_vcpu_state_dynamic: event is NULL");
+        return false;
+    }
+    if (unlikely(!trace_event_is_vcpu(tev))) {
+        error_report("qi_trace_event_get_vcpu_state_dynamic: event does not have 'vcpu' property");
+        return false;
+    }
+    return trace_event_get_vcpu_state_dynamic((CPUState *)vcpu, tev);
+}
+
+void qi_trace_event_set_state_dynamic(QIEvent *ev, bool state)
+{
+    TraceEvent *tev = (TraceEvent *)ev;
+
+    if (unlikely(tev == NULL)) {
+        error_report("qi_trace_event_set_state_dynamic: event is NULL");
+        return;
+    }
+    if (unlikely(!trace_event_get_state_static(tev))) {
+        error_report("qi_trace_event_set_state_dynamic: event is statically disabled");
+        return;
+    }
+    trace_event_set_state_dynamic(tev, state);
+}
+
+void qi_trace_event_set_vcpu_state_dynamic(QICPU *vcpu, QIEvent *ev, bool state)
+{
+    TraceEvent *tev = (TraceEvent *)ev;
+
+    if (unlikely(vcpu == NULL)) {
+        error_report("qi_trace_event_set_vcpu_state_dynamic: vcpu is NULL");
+        return;
+    }
+    if (unlikely(tev == NULL)) {
+        error_report("qi_trace_event_set_vcpu_state_dynamic: event is NULL");
+        return;
+    }
+    if (unlikely(!trace_event_is_vcpu(tev))) {
+        error_report("qi_trace_event_set_vcpu_state_dynamic: event does not have 'vcpu' property");
+        return;
+    }
+    if (unlikely(!trace_event_get_state_static(tev))) {
+        error_report("qi_trace_event_set_vcpu_state_dynamic: event is statically disabled");
+        return;
+    }
+    trace_event_set_vcpu_state_dynamic((CPUState *)vcpu, tev, state);
+}
+
+static void __attribute__((constructor)) instr_lock_init(void)
+{
+    qemu_rec_mutex_init(&instr_lock);
+}
diff --git a/instrument/control.h b/instrument/control.h
new file mode 100644
index 0000000000..a83a350faf
--- /dev/null
+++ b/instrument/control.h
@@ -0,0 +1,86 @@
+/*
+ * Interface for controlling dynamic trace instrumentation.
+ *
+ * Copyright (C) 2012-2017 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef INSTRUMENT__CONTROL_H
+#define INSTRUMENT__CONTROL_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "qapi-types.h"
+#include "trace/control.h"
+
+
+/**
+ * InstrLoadError:
+ * @INSTR_LOAD_OK: Correctly loaded.
+ * @INSTR_LOAD_UNAVAILABLE: Service not available.
+ * @INSTR_LOAD_ERROR: Error with libdl (see dlerror).
+ *
+ * Error codes for instr_load().
+ *
+ * Warning: Keep in sync with #InstrLoadCode
+ */
+typedef enum {
+    INSTR_LOAD_OK,
+    INSTR_LOAD_UNAVAILABLE,
+    INSTR_LOAD_ERROR,
+} InstrLoadError;
+
+/**
+ * InstrUnloadError:
+ * @INSTR_UNLOAD_OK: Correctly unloaded.
+ * @INSTR_UNLOAD_UNAVAILABLE: Service not available.
+ * @INSTR_UNLOAD_INVALID: Invalid handle.
+ * @INSTR_UNLOAD_ERROR: Error with libdl (see dlerror).
+ *
+ * Error codes for instr_unload().
+ *
+ * Warning: Keep in sync with #InstrUnloadCode
+ */
+typedef enum {
+    INSTR_UNLOAD_OK,
+    INSTR_UNLOAD_UNAVAILABLE,
+    INSTR_UNLOAD_INVALID,
+    INSTR_UNLOAD_ERROR,
+} InstrUnloadError;
+
+/**
+ * instr_load:
+ * @path: Path to the shared library to load.
+ * @argc: Number of arguments passed to the initialization function of the library.
+ * @argv: Arguments passed to the initialization function of the library.
+ * @handle: Instrumentation library handle (undefined in case of error).
+ *
+ * Load a dynamic trace instrumentation library.
+ *
+ * Returns: Whether the library could be loaded.
+ */
+InstrLoadError instr_load(const char * path, int argc, const char ** argv,
+                          int64_t *handle);
+
+/**
+ * instr_unload:
+ * @handle: Instrumentation library handle returned by instr_load().
+ *
+ * Unload the given instrumentation library.
+ *
+ * Returns: Whether the library could be unloaded.
+ */
+InstrUnloadError instr_unload(int64_t handle);
+
+/**
+ * instr_unload_all:
+ *
+ * Unload all instrumentation libraries.
+ *
+ * Returns: Whether any library could not be unloaded.
+ */
+InstrUnloadError instr_unload_all(void);
+
+#endif  /* INSTRUMENT__CONTROL_H */
diff --git a/instrument/qemu-instr/control.h b/instrument/qemu-instr/control.h
new file mode 100644
index 0000000000..83f20d42f2
--- /dev/null
+++ b/instrument/qemu-instr/control.h
@@ -0,0 +1,128 @@
+/*
+ * Interface for controlling the state of events.
+ *
+ * Copyright (C) 2012-2017 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef QI__CONTROL_H
+#define QI__CONTROL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#include <qemu-instr/types.h>
+#include <qemu-instr/visibility-internal.h>
+
+
+/**
+ * SECTION:control
+ * @section_id: qi-control
+ * @title: Event control API for QEMU event instrumentation
+ */
+
+/**
+ * qi_ctrl_event_set:
+ * @ev: Event descriptor.
+ * @cb: Pointer to instrumentation callback.
+ *
+ * Set the instrumentation callback for the given event.
+ *
+ * @cb can also be set to #NULL to restore the default callback.
+ */
+QI_VPUBLIC void qi_ctrl_event_set(QIEvent *ev, void *cb);
+
+/**
+ * qi_trace_event_get_state:
+ * @ev: Event identifier name.
+ *
+ * Get the tracing state of an event (both static and dynamic).
+ *
+ * If the event has the disabled property, the check will have no performance
+ * impact.
+ */
+#define qi_trace_event_get_state(ev)                                    \
+    ((ev ##_ENABLED) && qi_trace_event_get_state_dynamic(ev))
+
+/**
+ * qi_trace_event_get_vcpu_state:
+ * @vcpu: Target vCPU.
+ * @ev: Event identifier name.
+ *
+ * Get the tracing state of an event (both static and dynamic) for the given
+ * vCPU.
+ *
+ * If the event has the disabled property, the check will have no performance
+ * impact.
+ */
+#define qi_trace_event_get_vcpu_state(vcpu, ev)                         \
+    ((ev ##_ENABLED) &&                                                 \
+     qi_trace_event_get_vcpu_state_dynamic(vcpu, ev))
+
+/**
+ * qi_trace_event_get_state_static:
+ * @ev: Event identifier.
+ *
+ * Get the static tracing state of an event.
+ *
+ * Use the define 'QI_EVENT_${EVENT}_ENABLED' for compile-time checks (it will
+ * be set to 1 or 0 according to the presence of the disabled property).
+ */
+QI_VPUBLIC bool qi_trace_event_get_state_static(QIEvent *ev);
+
+/**
+ * qi_trace_event_get_state_dynamic:
+ * @ev: Event identifier.
+ *
+ * Get the dynamic tracing state of an event.
+ */
+QI_VPUBLIC bool qi_trace_event_get_state_dynamic(QIEvent *ev);
+
+/**
+ * qi_trace_event_get_vcpu_state_dynamic:
+ * @vcpu: Target vCPU.
+ * @ev: Event identifier.
+ *
+ * Get the dynamic tracing state of an event for the given vCPU.
+ */
+QI_VPUBLIC bool qi_trace_event_get_vcpu_state_dynamic(QICPU *vcpu,
+                                                      QIEvent *ev);
+
+/**
+ * qi_trace_event_set_state_dynamic:
+ * @ev: Event identifier.
+ * @state: Target tracing state.
+ *
+ * Set the dynamic tracing state of an event.
+ *
+ * Pre-condition: qi_trace_event_get_state_static(ev) == true
+ */
+QI_VPUBLIC void qi_trace_event_set_state_dynamic(QIEvent *ev, bool state);
+
+/**
+ * qi_trace_event_set_vcpu_state_dynamic:
+ * @vcpu: Target vCPU.
+ * @ev: Event identifier.
+ * @state: Target tracing state.
+ *
+ * Set the dynamic tracing state of an event for the given vCPU.
+ *
+ * Pre-condition: qi_trace_event_get_state_static(ev) == true
+ *
+ * Note: Changes for execution-time events with the 'tcg' property will not be
+ *       propagated until the next TB is executed (iff executing in TCG mode).
+ */
+QI_VPUBLIC void qi_trace_event_set_vcpu_state_dynamic(QICPU *vcpu,
+                                                      QIEvent *ev, bool state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* QI__CONTROL_H */
diff --git a/instrument/qemu-instr/types.h b/instrument/qemu-instr/types.h
index d3d26bbf73..58a84b6d01 100644
--- a/instrument/qemu-instr/types.h
+++ b/instrument/qemu-instr/types.h
@@ -25,6 +25,14 @@ extern "C" {
  */
 
 /**
+ * QIEvent:
+ *
+ * Opaque structure defining an instrumentation event.
+ */
+struct QIEvent;
+typedef struct QIEvent QIEvent;
+
+/**
  * QICPU:
  *
  * Opaque guest CPU pointer.
diff --git a/scripts/tracetool/backend/instr_dynamic.py b/scripts/tracetool/backend/instr_dynamic.py
index 6f9f8e49fb..2efd4a7eb1 100644
--- a/scripts/tracetool/backend/instr_dynamic.py
+++ b/scripts/tracetool/backend/instr_dynamic.py
@@ -90,7 +90,8 @@ def generate_instr_tcg_c(event, group):
     qargs = ["(%s)%s" % (arg[0], arg[1])
              for arg in iargs]
 
-    out('QI_VPUBLIC void %(nop)s(%(api_args)s)',
+    out('QIEvent *%(qevent)s = (QIEvent *)&%(tevent)s;',
+        'QI_VPUBLIC void %(nop)s(%(api_args)s)',
         '{',
         '}',
         'QI_VPUBLIC void %(trace)s(%(api_args)s)',
@@ -99,7 +100,10 @@ def generate_instr_tcg_c(event, group):
         '}',
         'QI_VPUBLIC void %(gen)s(%(api_args)s)',
         '{',
+        # does not exist when event is disabled
+        '#if %(teventu)s_ENABLED',
         '     %(b_gen)s(%(qgargs)s);',
+        '#endif',
         '}',
         'QI_VPUBLIC void %(trace_gen)s(%(api_args)s)',
         '{',
@@ -107,6 +111,9 @@ def generate_instr_tcg_c(event, group):
         '}',
         'void *%(qi_cb)s_cb = %(trace_gen)s;',
         '',
+        qevent=event.api(event.QI_TRACE_INSTRUMENT).upper(),
+        tevent=event.api(event.QEMU_EVENT),
+        teventu=event.api(event.QEMU_TRACE).upper(),
         api_args=api_args,
         nop=event.api(event.QI_TRACE_NOP),
         trace=event.api(event.QI_TRACE_TRACE),
@@ -133,7 +140,8 @@ def generate_instr_c(event, group):
     args = event.args.transform(TCG_2_QI_TCG)
     qargs = ["(%s)%s" % (arg[0], arg[1])
              for arg in event.args]
-    out('QI_VPUBLIC void %(nop)s(%(args)s)',
+    out('QIEvent *%(qevent)s = (QIEvent *)&%(tevent)s;',
+        'QI_VPUBLIC void %(nop)s(%(args)s)',
         '{',
         '}',
         'QI_VPUBLIC void %(trace)s(%(args)s)',
@@ -142,6 +150,8 @@ def generate_instr_c(event, group):
         '}',
         'void *%(qi_cb)s_cb = %(qi_trace)s;',
         '',
+        qevent=event.api(event.QI_TRACE_INSTRUMENT).upper(),
+        tevent=event.api(event.QEMU_EVENT),
         args=args,
         nop=event.api(event.QI_TRACE_NOP),
         trace=event.api(event.QI_TRACE_TRACE),
diff --git a/scripts/tracetool/format/c.py b/scripts/tracetool/format/c.py
index 833c05a022..0b8bb98d24 100644
--- a/scripts/tracetool/format/c.py
+++ b/scripts/tracetool/format/c.py
@@ -6,7 +6,7 @@ trace/generated-tracers.c
 """
 
 __author__     = "Lluís Vilanova <vilanova@ac.upc.edu>"
-__copyright__  = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__  = "Copyright 2012-2017, Lluís Vilanova <vilanova@ac.upc.edu>"
 __license__    = "GPL version 2 or (at your option) any later version"
 
 __maintainer__ = "Stefan Hajnoczi"
@@ -39,18 +39,49 @@ def generate(events, backend, group):
             vcpu_id = 0
         else:
             vcpu_id = "TRACE_VCPU_EVENT_NONE"
+
+        if "instrument" in e.properties:
+            is_instr = "true"
+            out('#if defined(CONFIG_INSTRUMENT)')
+            if "tcg-trans" in e.properties:
+                instr_cb = e.original.api(e.QI_TRACE_INSTRUMENT_TCG) + "_cb"
+                instr_cb_default = e.api(e.QI_TRACE_TRACEGEN)
+                out('static void *_tmp__%(name1)s;',
+                    'extern void *%(name1)s __attribute__((weak, alias("_tmp__%(name1)s")));',
+                    name1=instr_cb)
+            else:
+                instr_cb = e.api(e.QI_TRACE_INSTRUMENT) + "_cb"
+                instr_cb_default = e.api(e.QI_TRACE_TRACE)
+            out('static void _tmp__%(name2)s(void) {};',
+                'void %(name2)s(void) __attribute__((weak, alias("_tmp__%(name2)s")));',
+                '#endif',
+                name2=instr_cb_default)
+            instr_cb = "&" + instr_cb
+        else:
+            is_instr = "false"
+            instr_cb = "NULL"
+            instr_cb_default = "NULL"
+
         out('TraceEvent %(event)s = {',
             '    .id = 0,',
             '    .vcpu_id = %(vcpu_id)s,',
             '    .name = \"%(name)s\",',
             '    .sstate = %(sstate)s,',
-            '    .dstate = &%(dstate)s ',
+            '    .dstate = &%(dstate)s,',
+            '#if defined(CONFIG_INSTRUMENT)',
+            '    .is_instr = %(is_instr)s,',
+            '    .instr_cb = %(instr_cb)s,',
+            '    .instr_cb_default = %(instr_cb_default)s,',
+            '#endif',
             '};',
             event = e.api(e.QEMU_EVENT),
             vcpu_id = vcpu_id,
             name = e.name,
             sstate = "TRACE_%s_ENABLED" % e.name.upper(),
-            dstate = e.api(e.QEMU_DSTATE))
+            dstate = e.api(e.QEMU_DSTATE),
+            is_instr=is_instr,
+            instr_cb=instr_cb,
+            instr_cb_default=instr_cb_default)
 
     out('TraceEvent *%(group)s_trace_events[] = {',
         group = group.lower())
diff --git a/scripts/tracetool/format/instr_api_h.py b/scripts/tracetool/format/instr_api_h.py
index d85f64df45..812a5d44ec 100644
--- a/scripts/tracetool/format/instr_api_h.py
+++ b/scripts/tracetool/format/instr_api_h.py
@@ -40,13 +40,24 @@ def generate(events, backend, group):
         '')
 
     for e in events:
+        if "disable" in e.properties:
+            enabled = 0
+        else:
+            enabled = 1
+
         if "tcg-trans" in e.properties:
             args = tracetool.vcpu.transform_args("tcg_h", e.original)
             args = args.transform(TCG_2_QI_TCG)
         else:
             args = e.args.transform(TCG_2_QI_TCG)
-        out('QI_VPUBLIC void %(nop)s(%(args)s);',
+
+        out('#define %(qeventu)s_ENABLED %(enabled)d',
+            'extern QI_VPUBLIC QIEvent *%(event)s;',
+            'QI_VPUBLIC void %(nop)s(%(args)s);',
             'QI_VPUBLIC void %(trace)s(%(args)s);',
+            qeventu=e.api(e.QI_TRACE_INSTRUMENT).upper(),
+            enabled=enabled,
+            event=e.api(e.QI_TRACE_INSTRUMENT).upper(),
             args=args,
             nop=e.api(e.QI_TRACE_NOP),
             trace=e.api(e.QI_TRACE_TRACE))
diff --git a/trace/event-internal.h b/trace/event-internal.h
index f63500b37e..b12cc110b6 100644
--- a/trace/event-internal.h
+++ b/trace/event-internal.h
@@ -1,7 +1,7 @@
 /*
  * Interface for configuring and controlling the state of tracing events.
  *
- * Copyright (C) 2012-2016 Lluís Vilanova <vilanova@ac.upc.edu>
+ * Copyright (C) 2012-2017 Lluís Vilanova <vilanova@ac.upc.edu>
  *
  * This work is licensed under the terms of the GNU GPL, version 2 or later.
  * See the COPYING file in the top-level directory.
@@ -23,6 +23,9 @@
  * @name: Event name.
  * @sstate: Static tracing state.
  * @dstate: Dynamic tracing state
+ * @is_instr: Whether the event is instrumentable.
+ * @instr_cb: Current instrumentation callback.
+ * @instr_cb_default: Default instrumentation callback.
  *
  * Interpretation of @dstate depends on whether the event has the 'vcpu'
  *  property:
@@ -37,6 +40,11 @@ typedef struct TraceEvent {
     const char * name;
     const bool sstate;
     uint16_t *dstate;
+#if defined(CONFIG_INSTRUMENT)
+    bool is_instr;
+    void **instr_cb;
+    void *instr_cb_default;
+#endif
 } TraceEvent;
 
 void trace_event_set_state_dynamic_init(TraceEvent *ev, bool state);

  parent reply	other threads:[~2017-07-24 17:26 UTC|newest]

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-24 17:02 [Qemu-devel] [PATCH 00/13] instrument: Add basic event instrumentation Lluís Vilanova
2017-07-24 17:06 ` [Qemu-devel] [PATCH 01/13] instrument: Add documentation Lluís Vilanova
2017-07-24 17:10 ` [Qemu-devel] [PATCH 02/13] instrument: [none] Add null instrumentation mode Lluís Vilanova
2017-07-24 17:14 ` [Qemu-devel] [PATCH 03/13] instrument: [dynamic] Add dynamic " Lluís Vilanova
2017-07-24 17:18 ` [Qemu-devel] [PATCH 04/13] instrument: Allow adding the "instrument" property without modifying event files Lluís Vilanova
2017-07-24 17:22 ` [Qemu-devel] [PATCH 05/13] instrument: [dynamic] Add default public per-event functions Lluís Vilanova
2017-07-24 17:26 ` Lluís Vilanova [this message]
2017-07-24 17:30 ` [Qemu-devel] [PATCH 07/13] instrument: Add generic command line library loader Lluís Vilanova
2017-07-24 17:34 ` [Qemu-devel] [PATCH 08/13] instrument: [linux-user] Add " Lluís Vilanova
2017-07-24 17:38 ` [Qemu-devel] [PATCH 09/13] instrument: [bsd-user] " Lluís Vilanova
2017-07-24 17:42 ` [Qemu-devel] [PATCH 10/13] instrument: [softmmu] " Lluís Vilanova
2017-07-24 17:46 ` [Qemu-devel] [PATCH 11/13] instrument: [qapi] Add " Lluís Vilanova
2017-07-24 18:03   ` Eric Blake
2017-07-25  8:24     ` Lluís Vilanova
2017-07-25 11:30       ` Eric Blake
2017-07-25 11:51         ` Lluís Vilanova
2017-07-24 17:50 ` [Qemu-devel] [PATCH 12/13] instrument: [hmp] " Lluís Vilanova
2017-07-24 17:54 ` [Qemu-devel] [PATCH 13/13] trace: Rename C++-specific names in event arguments Lluís Vilanova
2017-07-25 13:19 ` [Qemu-devel] [PATCH 00/13] instrument: Add basic event instrumentation Stefan Hajnoczi
2017-07-25 13:30   ` Peter Maydell
2017-07-25 15:11     ` Lluís Vilanova
2017-07-26 11:22       ` Stefan Hajnoczi
2017-07-26 12:44         ` Lluís Vilanova
2017-07-27 10:32           ` Stefan Hajnoczi
2017-07-27 10:40             ` Peter Maydell
2017-07-28 13:42               ` Stefan Hajnoczi
2017-07-28 16:21                 ` Lluís Vilanova
2017-08-02 11:04                   ` Stefan Hajnoczi
2017-07-26 11:26     ` Stefan Hajnoczi
2017-07-26 11:49       ` Peter Maydell
2017-07-26 12:26         ` Lluís Vilanova
2017-07-27 10:43         ` Daniel P. Berrange
2017-07-27 10:54           ` Peter Maydell
2017-07-27 14:58             ` Lluís Vilanova
2017-07-27 15:21             ` Daniel P. Berrange
2017-07-27 15:33               ` Peter Maydell
2017-07-27 15:45                 ` Daniel P. Berrange
2017-07-28 13:34                   ` Stefan Hajnoczi
2017-07-28 13:41                     ` Peter Maydell
2017-07-28 14:06                       ` Daniel P. Berrange
2017-07-28 16:05                         ` Lluís Vilanova
2017-08-01 13:48                           ` Stefan Hajnoczi
2017-08-01 13:54                             ` Peter Maydell
2017-08-02 11:04                               ` Stefan Hajnoczi
2017-08-02 11:10                                 ` Peter Maydell
2017-08-02 14:49                                   ` Stefan Hajnoczi
2017-08-02 15:19                                     ` Lluís Vilanova
2017-08-03 11:54                                       ` Stefan Hajnoczi
2017-08-26  0:14                                         ` Emilio G. Cota
2017-08-26  0:02                           ` Emilio G. Cota
2017-08-29  9:19                             ` Peter Maydell
2017-07-28 13:52                     ` Daniel P. Berrange
2017-07-28 16:14                       ` Lluís Vilanova
2017-08-01 13:13                         ` Stefan Hajnoczi
2017-07-28 15:10                     ` Lluís Vilanova
2017-07-27 19:55               ` Lluís Vilanova
2017-07-25 14:47   ` Lluís Vilanova
2017-07-26 11:29     ` Stefan Hajnoczi
2017-07-26 12:31       ` Lluís Vilanova

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=150091719881.30739.10096572040779058122.stgit@frigg.lan \
    --to=vilanova@ac.upc.edu \
    --cc=cota@braap.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.