All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Lluís Vilanova" <vilanova@ac.upc.edu>
To: qemu-devel@nongnu.org
Cc: "Markus Armbruster" <armbru@redhat.com>,
	"Eric Blake" <eblake@redhat.com>,
	"Emilio G. Cota" <cota@braap.org>,
	"Stefan Hajnoczi" <stefanha@redhat.com>,
	"Lluís Vilanova" <vilanova@ac.upc.edu>,
	"Paolo Bonzini" <pbonzini@redhat.com>
Subject: [Qemu-devel] [PATCH v5 09/22] instrument: Add basic control interface
Date: Wed, 13 Sep 2017 00:38:03 +0300	[thread overview]
Message-ID: <150525228289.15988.9844115871305476442.stgit@frigg.lan> (raw)
In-Reply-To: <150525010239.15988.8172586618197849619.stgit@frigg.lan>

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 Makefile                        |    4 +++
 configure                       |    1 +
 include/qemu/compiler.h         |   19 ++++++++++++++++
 instrument/Makefile.objs        |    1 +
 instrument/control.c            |   28 ++++++++++++++++++++++++
 instrument/control.h            |   44 +++++++++++++++++++++++++++++++++++++
 instrument/control.inc.h        |   25 +++++++++++++++++++++
 instrument/error.h              |   28 ++++++++++++++++++++++++
 instrument/events.h             |   37 +++++++++++++++++++++++++++++++
 instrument/events.inc.h         |   11 +++++++++
 instrument/load.c               |   13 +++++++++++
 instrument/qemu-instr/control.h |   46 +++++++++++++++++++++++++++++++++++++++
 stubs/instrument.c              |    4 +++
 13 files changed, 261 insertions(+)
 create mode 100644 instrument/control.c
 create mode 100644 instrument/control.h
 create mode 100644 instrument/control.inc.h
 create mode 100644 instrument/error.h
 create mode 100644 instrument/events.h
 create mode 100644 instrument/events.inc.h
 create mode 100644 instrument/qemu-instr/control.h

diff --git a/Makefile b/Makefile
index 3861b3f49c..c3d9a4bcd9 100644
--- a/Makefile
+++ b/Makefile
@@ -599,6 +599,10 @@ ifdef CONFIG_VIRTFS
 	$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
 	$(INSTALL_DATA) fsdev/virtfs-proxy-helper.1 "$(DESTDIR)$(mandir)/man1"
 endif
+ifdef CONFIG_INSTRUMENT
+	$(INSTALL_DIR) "$(DESTDIR)$(includedir)/qemu-instr/"
+	$(INSTALL_DATA) $(SRC_PATH)/instrument/qemu-instr/control.h "$(DESTDIR)$(includedir)/qemu-instr/"
+endif
 
 install-datadir:
 	$(INSTALL_DIR) "$(DESTDIR)$(qemu_datadir)"
diff --git a/configure b/configure
index 5175151317..18810eae84 100755
--- a/configure
+++ b/configure
@@ -6030,6 +6030,7 @@ if test "$instrument" = "yes"; then
   LIBS="-ldl $LIBS"
   echo "CONFIG_INSTRUMENT=y" >> $config_host_mak
 fi
+QEMU_INCLUDES="-I\$(SRC_PATH)/instrument $QEMU_INCLUDES"
 
 if test "$rdma" = "yes" ; then
   echo "CONFIG_RDMA=y" >> $config_host_mak
diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
index 340e5fdc09..e86bd34e2c 100644
--- a/include/qemu/compiler.h
+++ b/include/qemu/compiler.h
@@ -111,4 +111,23 @@
 #define GCC_FMT_ATTR(n, m)
 #endif
 
+/*
+ * Export symbol to dlopen()'ed libraries'.
+ *
+ * This code is taken from http://gcc.gnu.org/wiki/Visibility.
+ */
+#if defined _WIN32 || defined __CYGWIN__
+  #ifdef __GNUC__
+    #define SYM_PUBLIC __attribute__ ((dllimport))
+  #else
+    #define SYM_PUBLIC __declspec(dllimport)
+  #endif
+#else
+  #if __GNUC__ >= 4
+    #define SYM_PUBLIC __attribute__ ((visibility("default")))
+  #else
+    #define SYM_PUBLIC
+  #endif
+#endif
+
 #endif /* COMPILER_H */
diff --git a/instrument/Makefile.objs b/instrument/Makefile.objs
index 7bf4e27e3c..ec76b2080b 100644
--- a/instrument/Makefile.objs
+++ b/instrument/Makefile.objs
@@ -3,3 +3,4 @@
 target-obj-$(CONFIG_INSTRUMENT) += cmdline.o
 target-obj-$(CONFIG_INSTRUMENT) += load.o
 target-obj-$(CONFIG_INSTRUMENT) += qmp.o
+target-obj-$(CONFIG_INSTRUMENT) += control.o
diff --git a/instrument/control.c b/instrument/control.c
new file mode 100644
index 0000000000..3630d6b3be
--- /dev/null
+++ b/instrument/control.c
@@ -0,0 +1,28 @@
+/*
+ * Control instrumentation during program (de)initialization.
+ *
+ * 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 "instrument/control.h"
+#include "instrument/error.h"
+#include "instrument/events.h"
+#include "instrument/load.h"
+#include "instrument/qemu-instr/control.h"
+#include "qemu/compiler.h"
+
+__thread InstrState instr_cur_state;
+
+
+qi_fini_fn instr_event__fini_fn;
+void *instr_event__fini_data;
+
+SYM_PUBLIC void qi_set_fini(qi_fini_fn fn, void *data)
+{
+    ERROR_IF(!instr_get_state(), "called outside instrumentation");
+    instr_set_event(fini_fn, fn);
+    instr_set_event(fini_data, data);
+}
diff --git a/instrument/control.h b/instrument/control.h
new file mode 100644
index 0000000000..f2b085f69b
--- /dev/null
+++ b/instrument/control.h
@@ -0,0 +1,44 @@
+/*
+ * Control instrumentation during program (de)initialization.
+ *
+ * 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
+
+
+/**
+ * InstrState:
+ * @INSTR_STATE_DISABLE: Intrumentation API not available.
+ * @INSTR_STATE_ENABLE: Intrumentation API available.
+ *
+ * Instrumentation state of current host thread. Used to ensure instrumentation
+ * clients use QEMU's API only in expected points.
+ */
+typedef enum {
+    INSTR_STATE_DISABLE,
+    INSTR_STATE_ENABLE,
+} InstrState;
+
+/**
+ * instr_set_state:
+ *
+ * Set the instrumentation state of the current host thread.
+ */
+static inline void instr_set_state(InstrState state);
+
+/**
+ * instr_get_state:
+ *
+ * Get the instrumentation state of the current host thread.
+ */
+static inline InstrState instr_get_state(void);
+
+
+#include "instrument/control.inc.h"
+
+#endif  /* INSTRUMENT__CONTROL_H */
diff --git a/instrument/control.inc.h b/instrument/control.inc.h
new file mode 100644
index 0000000000..0f649f4caa
--- /dev/null
+++ b/instrument/control.inc.h
@@ -0,0 +1,25 @@
+/*
+ * Control instrumentation during program (de)initialization.
+ *
+ * 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/atomic.h"
+#include "qemu/compiler.h"
+#include <stdbool.h>
+
+
+extern __thread InstrState instr_cur_state;
+
+static inline void instr_set_state(InstrState state)
+{
+    atomic_store_release(&instr_cur_state, state);
+}
+
+static inline InstrState instr_get_state(void)
+{
+    return atomic_load_acquire(&instr_cur_state);
+}
diff --git a/instrument/error.h b/instrument/error.h
new file mode 100644
index 0000000000..f8d1dd4b16
--- /dev/null
+++ b/instrument/error.h
@@ -0,0 +1,28 @@
+/*
+ * Helpers for controlling errors in instrumentation libraries.
+ *
+ * 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_ERROR_H
+#define INSTRUMENT_ERROR_H
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+
+
+#define _ERROR(msg, args...)                            \
+    do {                                                \
+        error_report("%s:" msg, __func__, ##args);      \
+    } while (0)
+
+#define ERROR_IF(cond, msg, args...) \
+    if (unlikely(cond)) {            \
+        _ERROR(msg, ##args);         \
+        return;                      \
+    }
+
+#endif  /* INSTRUMENT_ERROR_H */
diff --git a/instrument/events.h b/instrument/events.h
new file mode 100644
index 0000000000..82ad0bd827
--- /dev/null
+++ b/instrument/events.h
@@ -0,0 +1,37 @@
+/*
+ * Internal API for triggering instrumentation events.
+ *
+ * Copyright (C) 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__EVENTS_H
+#define INSTRUMENT__EVENTS_H
+
+#include "instrument/qemu-instr/control.h"
+
+/**
+ * instr_get_event:
+ *
+ * Get value set by instrumentation library.
+ */
+#define instr_get_event(name)                   \
+    atomic_load_acquire(&instr_event__ ## name)
+
+/**
+ * instr_get_event:
+ *
+ * Set value from instrumentation library.
+ */
+#define instr_set_event(name, fn)               \
+    atomic_store_release(&instr_event__ ## name, fn)
+
+
+extern qi_fini_fn instr_event__fini_fn;
+extern void *instr_event__fini_data;
+
+#include "instrument/events.inc.h"
+
+#endif  /* INSTRUMENT__EVENTS_H */
diff --git a/instrument/events.inc.h b/instrument/events.inc.h
new file mode 100644
index 0000000000..8b1ce7fcb2
--- /dev/null
+++ b/instrument/events.inc.h
@@ -0,0 +1,11 @@
+/*
+ * Internal API for triggering instrumentation events.
+ *
+ * Copyright (C) 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.
+ */
+
+
+
diff --git a/instrument/load.c b/instrument/load.c
index af98f4ce38..a01d66a4d4 100644
--- a/instrument/load.c
+++ b/instrument/load.c
@@ -11,6 +11,8 @@
 #include "qemu-common.h"
 
 #include <dlfcn.h>
+#include "instrument/control.h"
+#include "instrument/events.h"
 #include "instrument/load.h"
 #include "qemu/config-file.h"
 #include "qemu/error-report.h"
@@ -96,8 +98,11 @@ InstrLoadError instr_load(const char *path, int argc, const char **argv,
         res = INSTR_LOAD_DLERROR;
         goto err;
     }
+    instr_set_event(fini_fn, NULL);
 
+    instr_set_state(INSTR_STATE_ENABLE);
     main_res = main_cb(argc, argv);
+    instr_set_state(INSTR_STATE_DISABLE);
 
     if (main_res != 0) {
         res = INSTR_LOAD_ERROR;
@@ -126,6 +131,14 @@ InstrUnloadError instr_unload(const char *id)
         goto out;
     }
 
+    qi_fini_fn fini_fn = instr_get_event(fini_fn);
+    if (fini_fn) {
+        void *fini_data = instr_get_event(fini_data);
+        fini_fn(fini_data);
+    }
+
+    instr_set_event(fini_fn, NULL);
+
     /* this should never fail */
     if (dlclose(handle->dlhandle) < 0) {
         res = INSTR_UNLOAD_DLERROR;
diff --git a/instrument/qemu-instr/control.h b/instrument/qemu-instr/control.h
new file mode 100644
index 0000000000..b841afaa31
--- /dev/null
+++ b/instrument/qemu-instr/control.h
@@ -0,0 +1,46 @@
+/*
+ * Main instrumentation interface for QEMU.
+ *
+ * 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>
+
+
+/**
+ * SECTION:control
+ * @section_id: qi-control
+ * @title: Event control API for QEMU event instrumentation
+ */
+
+typedef void (*qi_fini_fn)(void *arg);
+
+/**
+ * qi_set_fini:
+ * @fn: Finalization function.
+ * @data: Argument to pass to the finalization function.
+ *
+ * Set the function to call when finalizing (unloading) the instrumentation
+ * library.
+ *
+ * NOTE: Calls to printf() might not be shown if the library is unloaded when
+ *       QEMU terminates.
+ */
+void qi_set_fini(qi_fini_fn fn, void *data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* QI__CONTROL_H */
diff --git a/stubs/instrument.c b/stubs/instrument.c
index 79cd0fd2d1..9498fcdfe5 100644
--- a/stubs/instrument.c
+++ b/stubs/instrument.c
@@ -10,6 +10,7 @@
 #include "qemu/osdep.h"
 
 #include "instrument/cmdline.h"
+#include "instrument/control.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
 
@@ -42,3 +43,6 @@ void qmp_instr_unload(const char *id, Error **errp)
 {
     error_setg(errp, QERR_UNSUPPORTED);
 }
+
+
+__thread InstrState instr_cur_state;

  parent reply	other threads:[~2017-09-12 21:38 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-12 21:01 [Qemu-devel] [PATCH v5 00/22] instrument: Add basic event instrumentation Lluís Vilanova
2017-09-12 21:05 ` [Qemu-devel] [PATCH v5 01/22] instrument: Add documentation Lluís Vilanova
2017-09-12 21:09 ` [Qemu-devel] [PATCH v5 02/22] instrument: Add configure-time flag Lluís Vilanova
2017-09-12 21:13 ` [Qemu-devel] [PATCH v5 03/22] instrument: Add generic library loader Lluís Vilanova
2017-09-12 21:17 ` [Qemu-devel] [PATCH v5 04/22] instrument: [linux-user] Add command line " Lluís Vilanova
2017-09-12 21:21 ` [Qemu-devel] [PATCH v5 05/22] instrument: [bsd-user] " Lluís Vilanova
2017-09-12 21:25 ` [Qemu-devel] [PATCH v5 06/22] instrument: [softmmu] " Lluís Vilanova
2017-09-12 21:29 ` [Qemu-devel] [PATCH v5 07/22] instrument: [qapi] Add " Lluís Vilanova
2017-09-12 21:34 ` [Qemu-devel] [PATCH v5 08/22] instrument: [hmp] " Lluís Vilanova
2017-09-12 21:38 ` Lluís Vilanova [this message]
2017-09-12 21:42 ` [Qemu-devel] [PATCH v5 10/22] instrument: Add support for tracing events Lluís Vilanova
2017-09-12 21:46 ` [Qemu-devel] [PATCH v5 11/22] instrument: Track vCPUs Lluís Vilanova
2017-09-12 21:50 ` [Qemu-devel] [PATCH v5 12/22] instrument: Add event 'guest_cpu_enter' Lluís Vilanova
2017-09-12 21:54 ` [Qemu-devel] [PATCH v5 13/22] instrument: Support synchronous modification of vCPU state Lluís Vilanova
2017-09-12 21:58 ` [Qemu-devel] [PATCH v5 14/22] exec: Add function to synchronously flush TB on a stopped vCPU Lluís Vilanova
2017-09-12 22:02 ` [Qemu-devel] [PATCH v5 15/22] instrument: Add event 'guest_cpu_exit' Lluís Vilanova
2017-09-12 22:06 ` [Qemu-devel] [PATCH v5 16/22] instrument: Add event 'guest_cpu_reset' Lluís Vilanova
2017-09-12 22:10 ` [Qemu-devel] [PATCH v5 17/22] trace: Introduce a proper structure to describe memory accesses Lluís Vilanova
2017-09-12 22:14 ` [Qemu-devel] [PATCH v5 18/22] instrument: Add event 'guest_mem_before_trans' Lluís Vilanova
2017-09-12 22:18 ` [Qemu-devel] [PATCH v5 19/22] instrument: Add event 'guest_mem_before_exec' Lluís Vilanova
2017-09-12 22:22 ` [Qemu-devel] [PATCH v5 20/22] instrument: Add event 'guest_user_syscall' Lluís Vilanova
2017-09-12 22:26 ` [Qemu-devel] [PATCH v5 21/22] instrument: Add event 'guest_user_syscall_ret' Lluís Vilanova
2017-09-12 22:30 ` [Qemu-devel] [PATCH v5 22/22] instrument: Add API to manipulate guest memory Lluís Vilanova
2017-09-12 22:34 ` [Qemu-devel] [PATCH v5 00/22] instrument: Add basic event instrumentation no-reply
2017-09-13  9:45   ` Lluís Vilanova
2017-09-12 22:36 ` no-reply
2017-09-13  9:50   ` Lluís Vilanova
2017-09-14 14:54 ` Peter Maydell
2017-09-15 13:45   ` Lluís Vilanova
2017-09-15 13:49     ` Peter Maydell

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=150525228289.15988.9844115871305476442.stgit@frigg.lan \
    --to=vilanova@ac.upc.edu \
    --cc=armbru@redhat.com \
    --cc=cota@braap.org \
    --cc=eblake@redhat.com \
    --cc=pbonzini@redhat.com \
    --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.