All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 01/18] backdoor: Handle config-time activation
  2010-10-22 18:53 ` Lluís
@ 2010-10-18 17:24   ` Lluís
  2010-10-18 17:40   ` [Qemu-devel] [PATCH 04/18] backdoor: Declare guest-side interface macros Lluís
                     ` (16 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-18 17:24 UTC (permalink / raw)
  To: qemu-devel

Add a '--with-backdoor' configuration option pointing to user-provided backdoor
callback implementation.

Make is invoked on the user-provided directory, which must build a static
library containing, at least, the implementation of the backdoor helpers.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 Makefile.target |   40 ++++++++++++++++++++++++++++++++++++----
 configure       |   21 +++++++++++++++++++++
 2 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/Makefile.target b/Makefile.target
index c48cbcc..9152723 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -29,7 +29,7 @@ QEMU_PROG=qemu-system-$(TARGET_ARCH2)$(EXESUF)
 endif
 endif
 
-PROGS=$(QEMU_PROG)
+PROGS=$(QEMU_PROG)-prepare $(QEMU_PROG)
 
 ifndef CONFIG_HAIKU
 LIBS+=-lm
@@ -323,8 +323,40 @@ endif # CONFIG_SOFTMMU
 obj-y += $(addprefix ../, $(trace-obj-y))
 obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o
 
-$(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)
-	$(call LINK,$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y))
+
+.PHONY: force
+force:
+
+#########################################################
+# backdoor communication channel
+ifdef CONFIG_BACKDOOR
+VPATH := $(VPATH):$(BACKDOOR_PATH)
+
+LIBBACKDOOR_LIB = libbackdoor/libbackdoor.a
+LIBBACKDOOR_CLEAN = libbackdoor-clean
+
+libbackdoor/Makefile:
+	$(call quiet-command, mkdir -p libbackdoor, "  CREAT $(TARGET_DIR)$@")
+	$(call quiet-command, rm -f libbackdoor/Makefile)
+	$(call quiet-command, ln -s $(BACKDOOR_PATH)/Makefile libbackdoor/Makefile)
+
+libbackdoor/libbackdoor.a: libbackdoor/Makefile force
+	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libbackdoor		\
+		QEMU_CFLAGS="$(QEMU_CFLAGS) -I../target-$(TARGET_BASE_ARCH)"	\
+		TARGET_DIR=$(TARGET_DIR)libbackdoor/ VPATH=$(VPATH)		\
+		SRC_PATH=$(SRC_PATH) V="$(V)" libbackdoor.a)
+
+libbackdoor-clean:
+	$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(LIBBACKDOOR_DIR)			\
+		VPATH=$(VPATH) SRC_PATH=$(SRC_PATH) V="$(V)" clean || true
+endif
+
+
+
+$(QEMU_PROG)-prepare: $(GENERATED_HEADERS) $(LIBBACKDOOR_LIB) $(QEMU_PROG)
+
+$(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y) $(LIBBACKDOOR_LIB)
+	$(call LINK,$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)) $(LIBBACKDOOR_LIB)
 
 
 gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/feature_to_c.sh
@@ -336,7 +368,7 @@ hmp-commands.h: $(SRC_PATH)/hmp-commands.hx
 qmp-commands.h: $(SRC_PATH)/qmp-commands.hx
 	$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@,"  GEN   $(TARGET_DIR)$@")
 
-clean:
+clean: $(LIBBACKDOOR_CLEAN)
 	rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o
 	rm -f *.d */*.d tcg/*.o ide/*.o
 	rm -f hmp-commands.h qmp-commands.h gdbstub-xml.c
diff --git a/configure b/configure
index a079a49..0de937e 100755
--- a/configure
+++ b/configure
@@ -332,6 +332,8 @@ trace_backend="nop"
 trace_file="trace"
 spice=""
 
+backdoor=""
+
 # OS specific
 if check_define __linux__ ; then
   targetos="Linux"
@@ -740,6 +742,14 @@ for opt do
   ;;
   --*dir)
   ;;
+  --with-backdoor=*) backdoor="$optarg"
+  if test ! -f "$backdoor/Makefile"; then
+      echo "ERROR: cannot make into $backdoor"
+      show_help="yes"
+  else
+      backdoor=`readlink -f $backdoor`
+  fi
+  ;;
   *) echo "ERROR: unknown option $opt"; show_help="yes"
   ;;
   esac
@@ -931,6 +941,7 @@ echo "  --trace-file=NAME        Full PATH,NAME of file to store traces"
 echo "                           Default:trace-<pid>"
 echo "  --disable-spice          disable spice"
 echo "  --enable-spice           enable spice"
+echo "  --with-backdoor=PATH     enable backdoor communication and compile implementation in PATH"
 echo ""
 echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
@@ -2321,6 +2332,10 @@ echo "Trace backend     $trace_backend"
 echo "Trace output file $trace_file-<pid>"
 echo "spice support     $spice"
 
+if test -n "$backdoor"; then
+    echo "Backdoor comm.    $backdoor"
+fi
+
 if test $sdl_too_old = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
 fi
@@ -2579,6 +2594,12 @@ if test "$spice" = "yes" ; then
   echo "CONFIG_SPICE=y" >> $config_host_mak
 fi
 
+if test -n "$backdoor"; then
+  echo "CONFIG_BACKDOOR=y" >> $config_host_mak
+  echo "BACKDOOR_PATH=$backdoor" >> $config_host_mak
+  rm -rf *-{linux-user,softmmu}/libbackdoor/
+fi
+
 # XXX: suppress that
 if [ "$bsd" = "yes" ] ; then
   echo "CONFIG_BSD=y" >> $config_host_mak
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 04/18] backdoor: Declare guest-side interface macros
  2010-10-22 18:53 ` Lluís
  2010-10-18 17:24   ` [Qemu-devel] [PATCH 01/18] backdoor: Handle config-time activation Lluís
@ 2010-10-18 17:40   ` Lluís
  2010-10-18 18:08   ` [Qemu-devel] [PATCH 06/18] backdoor: [i386] " Lluís
                     ` (15 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-18 17:40 UTC (permalink / raw)
  To: qemu-devel


Header for the user to include when compiling guest applications that want to
communicate with QEMU through backdoor instructions.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 backdoor/guest.h |   36 ++++++++++++++++++++++++++++++++++++
 1 files changed, 36 insertions(+), 0 deletions(-)
 create mode 100644 backdoor/guest.h

diff --git a/backdoor/guest.h b/backdoor/guest.h
new file mode 100644
index 0000000..58847e2
--- /dev/null
+++ b/backdoor/guest.h
@@ -0,0 +1,36 @@
+/*
+ * Guest-side interface for instruction-based backdoor communication.
+ *
+ *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef BACKDOOR_GUEST_H
+#define BACKDOOR_GUEST_H
+
+/* Backdoor macro names define the types of its arguments:
+ *
+ * - i8: immediate of 8 bits
+ * -  V: value passed in register
+ */
+
+#error Undefined instruction-based backdoor interface for guest architecture
+
+#define __str(s) #s
+#define __xstr(s) __str(s)
+
+#define __BACKDOOR_i8(b) asm volatile (".byte " __xstr(b))
+
+#endif /* BACKDOOR_GUEST_H */
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 06/18] backdoor: [i386] Declare guest-side interface macros
  2010-10-22 18:53 ` Lluís
  2010-10-18 17:24   ` [Qemu-devel] [PATCH 01/18] backdoor: Handle config-time activation Lluís
  2010-10-18 17:40   ` [Qemu-devel] [PATCH 04/18] backdoor: Declare guest-side interface macros Lluís
@ 2010-10-18 18:08   ` Lluís
  2010-10-18 18:27   ` [Qemu-devel] [PATCH 08/18] instrument: Handle config-time activation Lluís
                     ` (14 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-18 18:08 UTC (permalink / raw)
  To: qemu-devel


Guest-side macros to generate backdoor instructions.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 backdoor/guest.h |   24 ++++++++++++++++++++++++
 1 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/backdoor/guest.h b/backdoor/guest.h
index 58847e2..17029d3 100644
--- a/backdoor/guest.h
+++ b/backdoor/guest.h
@@ -26,8 +26,32 @@
  * -  V: value passed in register
  */
 
+#if __i386__ || __i486__ || __x86_64__
+
+#define __BACKDOOR_BASE asm volatile (".byte 0x0f, 0x04")
+#define __BACKDOOR_V(v) asm volatile ("movl %0, %%eax" : : "g"(v) : "%eax")
+
+#define BACKDOOR_i8(cmd)                                        \
+    do {                                                        \
+        __BACKDOOR_BASE;                                        \
+        __BACKDOOR_i8(0x00);                                    \
+        __BACKDOOR_i8(cmd);                                     \
+    } while (0)
+
+#define BACKDOOR_i8_V(cmd, value)                               \
+    do {                                                        \
+        __BACKDOOR_V(value);                                    \
+        __BACKDOOR_BASE;                                        \
+        __BACKDOOR_i8(0x01);                                    \
+        __BACKDOOR_i8(cmd);                                     \
+    } while (0)
+
+#else
+
 #error Undefined instruction-based backdoor interface for guest architecture
 
+#endif
+
 #define __str(s) #s
 #define __xstr(s) __str(s)
 
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 08/18] instrument: Handle config-time activation
  2010-10-22 18:53 ` Lluís
                     ` (2 preceding siblings ...)
  2010-10-18 18:08   ` [Qemu-devel] [PATCH 06/18] backdoor: [i386] " Lluís
@ 2010-10-18 18:27   ` Lluís
  2010-10-19 19:14   ` [Qemu-devel] [PATCH 05/18] backdoor: [i386] Decode backdoor instructions Lluís
                     ` (13 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-18 18:27 UTC (permalink / raw)
  To: qemu-devel


Add a '--with-instrument' configuration option pointing to user-provided
instrumentation callbacks.

Make is invoked on the user-provided directory, which must build a static
library that might contain extra code needed by the user-provided
instrumentation.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 Makefile.target |   29 ++++++++++++++++++++++++++---
 configure       |   19 +++++++++++++++++++
 2 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/Makefile.target b/Makefile.target
index 9152723..90867e7 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -351,12 +351,35 @@ libbackdoor-clean:
 		VPATH=$(VPATH) SRC_PATH=$(SRC_PATH) V="$(V)" clean || true
 endif
 
+#########################################################
+# static instrumentation
+ifdef CONFIG_INSTRUMENT
+VPATH := $(VPATH):$(INSTRUMENT_PATH)
+
+LIBINSTRUMENT_LIB = libinstrument/libinstrument.a
+LIBINSTRUMENT_CLEAN = libinstrument-clean
+
+libinstrument/Makefile:
+	$(call quiet-command, mkdir -p libinstrument, "  CREAT $(TARGET_DIR)$@")
+	$(call quiet-command, rm -f libinstrument/Makefile)
+	$(call quiet-command, ln -s $(INSTRUMENT_PATH)/Makefile libinstrument/Makefile)
+
+libinstrument/libinstrument.a: libinstrument/Makefile force
+	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libinstrument	\
+		QEMU_CFLAGS="$(QEMU_CFLAGS) -I../target-$(TARGET_BASE_ARCH)"	\
+		TARGET_DIR=$(TARGET_DIR)libinstrument/ VPATH=$(VPATH)		\
+		SRC_PATH=$(SRC_PATH) V="$(V)" libinstrument.a)
+
+libinstrument-clean:
+	$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(LIBINSTRUMENT_DIR)			\
+		VPATH=$(VPATH) SRC_PATH=$(SRC_PATH) V="$(V)" clean || true
+endif
 
 
-$(QEMU_PROG)-prepare: $(GENERATED_HEADERS) $(LIBBACKDOOR_LIB) $(QEMU_PROG)
+$(QEMU_PROG)-prepare: $(GENERATED_HEADERS) $(LIBBACKDOOR_LIB) $(LIBINSTRUMENT_LIB) $(QEMU_PROG)
 
-$(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y) $(LIBBACKDOOR_LIB)
-	$(call LINK,$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)) $(LIBBACKDOOR_LIB)
+$(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y) $(LIBBACKDOOR_LIB) $(LIBINSTRUMENT_LIB)
+	$(call LINK,$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)) $(LIBBACKDOOR_LIB) $(LIBINSTRUMENT_LIB)
 
 
 gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/feature_to_c.sh
diff --git a/configure b/configure
index 0de937e..454124c 100755
--- a/configure
+++ b/configure
@@ -333,6 +333,7 @@ trace_file="trace"
 spice=""
 
 backdoor=""
+instrument=""
 
 # OS specific
 if check_define __linux__ ; then
@@ -750,6 +751,14 @@ for opt do
       backdoor=`readlink -f $backdoor`
   fi
   ;;
+  --with-instrument=*) instrument="$optarg"
+  if test ! -f "$instrument/Makefile"; then
+      echo "ERROR: cannot make into $instrument"
+      show_help="yes"
+  else
+      instrument=`readlink -f $instrument`
+  fi
+  ;;
   *) echo "ERROR: unknown option $opt"; show_help="yes"
   ;;
   esac
@@ -942,6 +951,7 @@ echo "                           Default:trace-<pid>"
 echo "  --disable-spice          disable spice"
 echo "  --enable-spice           enable spice"
 echo "  --with-backdoor=PATH     enable backdoor communication and compile implementation in PATH"
+echo "  --with-instrument=PATH   enable static instrumentation and compile user code in PATH"
 echo ""
 echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
@@ -2335,6 +2345,9 @@ echo "spice support     $spice"
 if test -n "$backdoor"; then
     echo "Backdoor comm.    $backdoor"
 fi
+if test -n "$instrument"; then
+    echo "Instrumentation   $instrument"
+fi
 
 if test $sdl_too_old = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -2599,6 +2612,12 @@ if test -n "$backdoor"; then
   echo "BACKDOOR_PATH=$backdoor" >> $config_host_mak
   rm -rf *-{linux-user,softmmu}/libbackdoor/
 fi
+if test -n "$instrument"; then
+  echo "CONFIG_INSTRUMENT=y" >> $config_host_mak
+  echo "INSTRUMENT_PATH=$instrument" >> $config_host_mak
+  QEMU_CFLAGS="-I$instrument $QEMU_CFLAGS"
+  rm -rf *-{linux-user,softmmu}/libinstrument/
+fi
 
 # XXX: suppress that
 if [ "$bsd" = "yes" ] ; then
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 05/18] backdoor: [i386] Decode backdoor instructions
  2010-10-22 18:53 ` Lluís
                     ` (3 preceding siblings ...)
  2010-10-18 18:27   ` [Qemu-devel] [PATCH 08/18] instrument: Handle config-time activation Lluís
@ 2010-10-19 19:14   ` Lluís
  2010-10-19 19:22   ` [Qemu-devel] [PATCH 02/18] backdoor: Declare host-side backdoor helpers Lluís
                     ` (12 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-19 19:14 UTC (permalink / raw)
  To: qemu-devel


Decode backdoor instructions following "backdoor/guest.h" and call the
user-defined backdoor helpers.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target-i386/translate.c |   30 ++++++++++++++++++++++++++++++
 1 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 7b6e3c2..b54a823 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -4105,6 +4105,31 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
     x86_64_hregs = 0;
 #endif
     s->rip_offset = 0; /* for relative ip address */
+
+#if defined(CONFIG_BACKDOOR)
+    if (ldub_code(s->pc) == 0x0f &&  ldub_code(s->pc + 1) == 0x04) {
+        uint8_t type = ldub_code(s->pc + 2);
+        TCGv_i32 cmd;
+        /* TODO: should break TB, but gen_eob generates an infinite loop */
+        switch (type) {
+        case 0x00:                      /* i8 */
+            cmd = tcg_const_i32((uint32_t)ldub_code(s->pc + 3));
+            gen_helper_backdoor_i8(cmd);
+            break;
+        case 0x01:                      /* i8 v */
+            cmd = tcg_const_i32(ldub_code(s->pc + 3));
+            gen_helper_backdoor_i8_v(cmd, cpu_regs[R_EAX]);
+            break;
+        default:
+            goto illegal_op;
+        }
+        s->pc += 4;
+        gen_jmp_im(s->pc);
+        gen_eob(s);
+        goto backdoor_done;
+    }
+#endif
+
  next_byte:
     b = ldub_code(s->pc);
     s->pc++;
@@ -7636,6 +7661,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
     default:
         goto illegal_op;
     }
+
+#if defined(CONFIG_BACKDOOR)
+backdoor_done:
+#endif
+
     /* lock generation */
     if (s->prefix & PREFIX_LOCK)
         gen_helper_unlock();
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 02/18] backdoor: Declare host-side backdoor helpers
  2010-10-22 18:53 ` Lluís
                     ` (4 preceding siblings ...)
  2010-10-19 19:14   ` [Qemu-devel] [PATCH 05/18] backdoor: [i386] Decode backdoor instructions Lluís
@ 2010-10-19 19:22   ` Lluís
  2010-10-19 19:33   ` [Qemu-devel] [PATCH 03/18] backdoor: [all] Include backdoor helper declarations Lluís
                     ` (11 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-19 19:22 UTC (permalink / raw)
  To: qemu-devel

These helpers must be implemented by the user on "libbackdoor.a".

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 backdoor/helper.h |   21 +++++++++++++++++++++
 1 files changed, 21 insertions(+), 0 deletions(-)
 create mode 100644 backdoor/helper.h

diff --git a/backdoor/helper.h b/backdoor/helper.h
new file mode 100644
index 0000000..18b53ac
--- /dev/null
+++ b/backdoor/helper.h
@@ -0,0 +1,21 @@
+/*
+ * Helpers for instruction-based backdoor communication.
+ *
+ *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+DEF_HELPER_1(backdoor_i8, void, i32);
+DEF_HELPER_2(backdoor_i8_v, void, i32, tl);
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 03/18] backdoor: [all] Include backdoor helper declarations
  2010-10-22 18:53 ` Lluís
                     ` (5 preceding siblings ...)
  2010-10-19 19:22   ` [Qemu-devel] [PATCH 02/18] backdoor: Declare host-side backdoor helpers Lluís
@ 2010-10-19 19:33   ` Lluís
  2010-10-19 20:05   ` [Qemu-devel] [PATCH 07/18] backdoor: Add a simple example Lluís
                     ` (10 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-19 19:33 UTC (permalink / raw)
  To: qemu-devel


Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target-alpha/helper.h      |    4 ++++
 target-arm/helper.h        |    4 ++++
 target-cris/helper.h       |    4 ++++
 target-i386/helper.h       |    4 ++++
 target-m68k/helper.h       |    4 ++++
 target-microblaze/helper.h |    4 ++++
 target-mips/helper.h       |    4 ++++
 target-ppc/helper.h        |    4 ++++
 target-sh4/helper.h        |    4 ++++
 target-sparc/helper.h      |    4 ++++
 10 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index ccf6a2a..d2ec252 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -123,4 +123,8 @@ DEF_HELPER_2(stl_c_raw, i64, i64, i64)
 DEF_HELPER_2(stq_c_raw, i64, i64, i64)
 #endif
 
+#if defined(CONFIG_BACKDOOR)
+#include "backdoor/helper.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 0d1bc47..b46f04c 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -447,4 +447,8 @@ DEF_HELPER_3(iwmmxt_muladdswl, i64, i64, i32, i32)
 
 DEF_HELPER_2(set_teecr, void, env, i32)
 
+#if defined(CONFIG_BACKDOOR)
+#include "backdoor/helper.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-cris/helper.h b/target-cris/helper.h
index 093063a..72fabce 100644
--- a/target-cris/helper.h
+++ b/target-cris/helper.h
@@ -23,4 +23,8 @@ DEF_HELPER_FLAGS_2(evaluate_flags_move_2, TCG_CALL_PURE, i32, i32, i32)
 DEF_HELPER_0(evaluate_flags, void)
 DEF_HELPER_0(top_evaluate_flags, void)
 
+#if defined(CONFIG_BACKDOOR)
+#include "backdoor/helper.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-i386/helper.h b/target-i386/helper.h
index 6b518ad..979d94e 100644
--- a/target-i386/helper.h
+++ b/target-i386/helper.h
@@ -217,4 +217,8 @@ DEF_HELPER_2(rclq, tl, tl, tl)
 DEF_HELPER_2(rcrq, tl, tl, tl)
 #endif
 
+#if defined(CONFIG_BACKDOOR)
+#include "backdoor/helper.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index cb8a0c7..06e8a47 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -51,4 +51,8 @@ DEF_HELPER_3(set_mac_extu, void, env, i32, i32)
 DEF_HELPER_2(flush_flags, void, env, i32)
 DEF_HELPER_1(raise_exception, void, i32)
 
+#if defined(CONFIG_BACKDOOR)
+#include "backdoor/helper.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h
index 11ad1b6..473ed78 100644
--- a/target-microblaze/helper.h
+++ b/target-microblaze/helper.h
@@ -34,4 +34,8 @@ DEF_HELPER_2(mmu_write, void, i32, i32)
 
 DEF_HELPER_4(memalign, void, i32, i32, i32, i32)
 
+#if defined(CONFIG_BACKDOOR)
+#include "backdoor/helper.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-mips/helper.h b/target-mips/helper.h
index cb13fb2..cbee380 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -287,4 +287,8 @@ DEF_HELPER_0(rdhwr_ccres, tl)
 DEF_HELPER_1(pmon, void, int)
 DEF_HELPER_0(wait, void)
 
+#if defined(CONFIG_BACKDOOR)
+#include "backdoor/helper.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 2bf9283..eeb7487 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -401,4 +401,8 @@ DEF_HELPER_2(store_601_batl, void, i32, tl)
 DEF_HELPER_2(store_601_batu, void, i32, tl)
 #endif
 
+#if defined(CONFIG_BACKDOOR)
+#include "backdoor/helper.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-sh4/helper.h b/target-sh4/helper.h
index 4b2fcdd..dbea9e1 100644
--- a/target-sh4/helper.h
+++ b/target-sh4/helper.h
@@ -50,4 +50,8 @@ DEF_HELPER_1(fsqrt_DT, i64, i64)
 DEF_HELPER_1(ftrc_FT, i32, i32)
 DEF_HELPER_1(ftrc_DT, i32, i64)
 
+#if defined(CONFIG_BACKDOOR)
+#include "backdoor/helper.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 6f103e7..b88f0ac 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -160,4 +160,8 @@ VIS_CMPHELPER(cmpne);
 DEF_HELPER_0(compute_psr, void);
 DEF_HELPER_0(compute_C_icc, i32);
 
+#if defined(CONFIG_BACKDOOR)
+#include "backdoor/helper.h"
+#endif
+
 #include "def-helper.h"
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 07/18] backdoor: Add a simple example
  2010-10-22 18:53 ` Lluís
                     ` (6 preceding siblings ...)
  2010-10-19 19:33   ` [Qemu-devel] [PATCH 03/18] backdoor: [all] Include backdoor helper declarations Lluís
@ 2010-10-19 20:05   ` Lluís
  2010-10-19 21:11   ` [Qemu-devel] [PATCH 13/18] instrument: Add FETCH point Lluís
                     ` (9 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-19 20:05 UTC (permalink / raw)
  To: qemu-devel


Provides a guest application that exercices the instruction-based backdoor
communication, as well as a backdoor callback implementation that prints the
guest requests.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 .gitignore                             |    1 +
 backdoor/examples/print/README         |   13 +++++++++++
 backdoor/examples/print/guest/Makefile |    7 ++++++
 backdoor/examples/print/guest/test.c   |   33 +++++++++++++++++++++++++++++
 backdoor/examples/print/host/Makefile  |   13 +++++++++++
 backdoor/examples/print/host/printcb.c |   36 ++++++++++++++++++++++++++++++++
 6 files changed, 103 insertions(+), 0 deletions(-)
 create mode 100644 backdoor/examples/print/README
 create mode 100644 backdoor/examples/print/guest/Makefile
 create mode 100644 backdoor/examples/print/guest/test.c
 create mode 100644 backdoor/examples/print/host/Makefile
 create mode 100644 backdoor/examples/print/host/printcb.c

diff --git a/.gitignore b/.gitignore
index a43e4d1..e4a351d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,3 +58,4 @@ pc-bios/optionrom/multiboot.bin
 pc-bios/optionrom/multiboot.raw
 .stgit-*
 cscope.*
+backdoor/examples/print/guest/test
diff --git a/backdoor/examples/print/README b/backdoor/examples/print/README
new file mode 100644
index 0000000..0675f16
--- /dev/null
+++ b/backdoor/examples/print/README
@@ -0,0 +1,13 @@
+This example simply defines instruction-based backdoors to print their
+arguments, along with a guest example code that makes use of backdoor
+instructions.
+
+To compile the host (quemu) run:
+   /path/to/qemu/configure --with-backdoor=/path/to/qemu/backdoor/examples/print/host/
+   make
+
+To compile the guest program run:
+   make -C /path/to/qemu/backdoor/examples/print/guest/
+
+Now you can run it with:
+   /path/to/qemu/i386-linux-user/qemu-i386 /path/to/qemu/backdoor/examples/print/guest/test
diff --git a/backdoor/examples/print/guest/Makefile b/backdoor/examples/print/guest/Makefile
new file mode 100644
index 0000000..ea266f2
--- /dev/null
+++ b/backdoor/examples/print/guest/Makefile
@@ -0,0 +1,7 @@
+CFLAGS += -I../../../../
+PROGS = test
+
+all: $(PROGS)
+
+clean:
+	rm -f $(PROGS)
diff --git a/backdoor/examples/print/guest/test.c b/backdoor/examples/print/guest/test.c
new file mode 100644
index 0000000..8146c3d
--- /dev/null
+++ b/backdoor/examples/print/guest/test.c
@@ -0,0 +1,33 @@
+/*
+ * Sample guest program exercising instruction-based backdoor communication.
+ *
+ *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+
+#include "backdoor/guest.h"
+
+int main ()
+{
+    int i = 23;
+    printf("i8 1\n");
+    BACKDOOR_i8(0x01);
+    printf("i8_v 1 32\n");
+    BACKDOOR_i8_V(0x01, 32);
+    printf("i8_v 2 i (%d)\n", i);
+    BACKDOOR_i8_V(0x02, i);
+}
diff --git a/backdoor/examples/print/host/Makefile b/backdoor/examples/print/host/Makefile
new file mode 100644
index 0000000..bfd6311
--- /dev/null
+++ b/backdoor/examples/print/host/Makefile
@@ -0,0 +1,13 @@
+# Makefile for user-provided backdoor code
+
+include $(SRC_PATH)/config-host.mak
+include $(SRC_PATH)/rules.mak
+include $(SRC_PATH)/Makefile.objs
+
+objs = printcb.o
+
+libbackdoor.a: $(objs)
+	$(call quiet-command,rm -f $@ && $(AR) rcs $@ $^,"  AR    $(TARGET_DIR)$@")
+
+clean:
+	rm -f libbackdoor.a $(objs)
diff --git a/backdoor/examples/print/host/printcb.c b/backdoor/examples/print/host/printcb.c
new file mode 100644
index 0000000..b267b6c
--- /dev/null
+++ b/backdoor/examples/print/host/printcb.c
@@ -0,0 +1,36 @@
+/*
+ * Sample user-defined callbacks for backdoor communication.
+ *
+ *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+
+#include "cpu.h"
+#include "helper.h"
+
+
+void
+helper_backdoor_i8 (uint32_t imm)
+{
+    printf("backdoor_i8: %u\n", imm);
+}
+
+void
+helper_backdoor_i8_v (uint32_t imm, target_ulong value)
+{
+    printf("backdoor_i8_v: %u "TARGET_FMT_ld"\n", imm, value);
+}
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 13/18] instrument: Add FETCH point
  2010-10-22 18:53 ` Lluís
                     ` (7 preceding siblings ...)
  2010-10-19 20:05   ` [Qemu-devel] [PATCH 07/18] backdoor: Add a simple example Lluís
@ 2010-10-19 21:11   ` Lluís
  2010-10-19 21:12   ` [Qemu-devel] [PATCH 15/18] instrument: Add VMEM point Lluís
                     ` (8 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-19 21:11 UTC (permalink / raw)
  To: qemu-devel


Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 cpu-all.h                                          |    6 +++
 instrument/examples/dynprint/guest/test.c          |   10 +++++
 instrument/examples/dynprint/host/backdoor.c       |    8 ++++
 instrument/examples/dynprint/host/helpers.c        |   43 ++++++++++++++++++++
 .../dynprint/host/instrument-host-helpers.h        |    2 +
 .../examples/dynprint/host/instrument-host.h       |   14 ++++++
 instrument/generate.h                              |    2 +
 instrument/host-stub.h                             |    9 ++++
 instrument/types.h                                 |   17 +++++---
 9 files changed, 105 insertions(+), 6 deletions(-)

diff --git a/cpu-all.h b/cpu-all.h
index b15253f..88970a2 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -24,11 +24,17 @@
 
 #if defined(CONFIG_INSTRUMENT)
 
+#define INSTR_REGS_SET(regs, reg)                               \
+    do { (regs) |= (((typeof(regs)) 1) << (reg)); } while (0)
 #include "instrument/types.h"
 #include "instrument/generate.h"
 #include "instrument/control.h"
 #include "instrument/state.h"
 
+#else  /* defined(CONFIG_INSTRUMENT) */
+
+#define INSTR_REGS_SET(regs, reg)
+
 #endif  /* defined(CONFIG_INSTRUMENT) */
 
 /* some important defines:
diff --git a/instrument/examples/dynprint/guest/test.c b/instrument/examples/dynprint/guest/test.c
index 7ddd5be..b6b5788 100644
--- a/instrument/examples/dynprint/guest/test.c
+++ b/instrument/examples/dynprint/guest/test.c
@@ -20,6 +20,7 @@
 #include <stdio.h>
 
 #include "backdoor/guest.h"
+#include "../host/instrument-host.h"
 
 #define TOTAL_ITERS 100
 
@@ -32,18 +33,27 @@ main ()
     BACKDOOR_i8(0x01);                  /* enable instrumentation */
 
     printf("start\n");
+    BACKDOOR_i8_V(0x01, INSTR_TYPE_PC); /* show executed PCs */
 
     for (i = 0; i < TOTAL_ITERS; i++) {
         /* disable an iteration every 10 iterations */
         if (i % 10 == 0) {
             BACKDOOR_i8(0x00);
         }
+        /* be completely verbose on even iterations */
+        if (i % 2 == 0) {
+            BACKDOOR_i8_V(0x01, INSTR_TYPE_ALL);
+        }
         printf("iteration\n");
+        if (i % 2 == 0) {
+            BACKDOOR_i8_V(0x00, INSTR_TYPE_ALL);
+        }
         if (i % 10 == 0) {
             BACKDOOR_i8(0x01);
         }
     }
 
+    BACKDOOR_i8_V(0x00, INSTR_TYPE_PC); /* stop showing PCs */
     printf("stop\n");
 
     BACKDOOR_i8(0x00);                  /* disable instrumentation */
diff --git a/instrument/examples/dynprint/host/backdoor.c b/instrument/examples/dynprint/host/backdoor.c
index 27f612b..7c3e4b7 100644
--- a/instrument/examples/dynprint/host/backdoor.c
+++ b/instrument/examples/dynprint/host/backdoor.c
@@ -46,6 +46,14 @@ void
 helper_backdoor_i8_v (uint32_t imm, target_ulong value)
 {
     switch (imm) {
+    case 0:
+        printf("backdoor: -"TARGET_FMT_lu"\n", value);
+        instr_disable_type(value);
+        break;
+    case 1:
+        printf("backdoor: +"TARGET_FMT_lu"\n", value);
+        instr_enable_type(value);
+        break;
     default:
         printf("Unexpected use of instrumentation backdoor\n");
         abort();
diff --git a/instrument/examples/dynprint/host/helpers.c b/instrument/examples/dynprint/host/helpers.c
index 656b716..173d0ec 100644
--- a/instrument/examples/dynprint/host/helpers.c
+++ b/instrument/examples/dynprint/host/helpers.c
@@ -17,3 +17,46 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <stdio.h>
+
+#include "cpu.h"
+#include "helper.h"
+
+#include "disas.h"
+#include "instrument/types.h"
+
+
+void
+helper_pc (target_ulong addr)
+{
+    printf("-> 0x"TARGET_FMT_lx"\n", addr);
+}
+
+static void
+print_registers (const char * msg, const instr_regs_t regs)
+{
+    int i, count = 0;
+    printf("%s", msg);
+    for (i = 0; i < sizeof(regs) * 8; i++) {
+        if (( ((instr_regs_t)1) << i) & regs) {
+            count++;
+            printf(" r%02d", i);
+        }
+    }
+    if (!count) {
+        printf(" -");
+    }
+    printf("\n");
+}
+
+void
+helper_all_fetch (target_ulong addr, uint32_t size,
+                  instr_regs_t used, instr_regs_t defined)
+{
+    printf("F: ");
+    target_disas(stdout, addr, size, 0);
+
+    printf("   size   : %d\n", size);
+    print_registers("   used   :", used);
+    print_registers("   defined:", defined);
+}
diff --git a/instrument/examples/dynprint/host/instrument-host-helpers.h b/instrument/examples/dynprint/host/instrument-host-helpers.h
index e88738d..947cf57 100644
--- a/instrument/examples/dynprint/host/instrument-host-helpers.h
+++ b/instrument/examples/dynprint/host/instrument-host-helpers.h
@@ -17,3 +17,5 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
+DEF_HELPER_1(pc, void, tl);
+DEF_HELPER_4(all_fetch, void, tl, i32, i64, i64);
diff --git a/instrument/examples/dynprint/host/instrument-host.h b/instrument/examples/dynprint/host/instrument-host.h
index 92a4c14..15911e7 100644
--- a/instrument/examples/dynprint/host/instrument-host.h
+++ b/instrument/examples/dynprint/host/instrument-host.h
@@ -29,7 +29,21 @@ typedef enum {
                          * global state of tracing is wasteful, but hey, this is
                          * just an example.
                          */
+    INSTR_TYPE_PC,      /* Print fetched PC                                  */
+    INSTR_TYPE_ALL,     /* Print all instruction information                 */
     INSTR_TYPE_COUNT    /* Total number of instrumentation types (mandatory) */
 } instr_type_t;
 
+
+#define INSTR_GEN_FETCH(taddr, addr, tlength, length,                   \
+                        tused, used, tdefined, defined)                 \
+    do {                                                                \
+        if (INSTR_TYPE(ENABLED) && INSTR_TYPE(PC)) {                    \
+            INSTR_GEN_1(pc, taddr, addr);                               \
+        }                                                               \
+        if (INSTR_TYPE(ENABLED) && INSTR_TYPE(ALL)) {                   \
+            INSTR_GEN_4(all_fetch, taddr, addr, tlength, length,        \
+                        tused, used, tdefined, defined);                \
+        }                                                               \
+    } while (0)
 #endif /* INSTRUMENT_HOST_H */
diff --git a/instrument/generate.h b/instrument/generate.h
index 7e4b35c..60f0c31 100644
--- a/instrument/generate.h
+++ b/instrument/generate.h
@@ -102,6 +102,7 @@
 #define __INSTR_ARG_TUL_DECL(tcg, value)      __INSTR_ARG_I32_DECL(tcg, value)
 #define __INSTR_ARG_TCGv_i32_DECL(tcg, value) TCGv_i32 tcg = value
 #endif
+#define __INSTR_ARG_REGS_DECL(tcg, value)     __INSTR_ARG_I64_DECL(tcg, value)
 
 #define __INSTR_ARG_DECL(tcg, type, value)    __INSTR_ARG_ ##type ##_DECL(tcg, value)
 
@@ -118,6 +119,7 @@
 #define __INSTR_ARG_TCGv_i64_FREE(tcg)
 #define __INSTR_ARG_TCGv_i32_FREE(tcg)
 #define __INSTR_ARG_TCGv_FREE(tcg)
+#define __INSTR_ARG_REGS_FREE(tcg)     __INSTR_ARG_I64_FREE(tcg)
 
 #define __INSTR_ARG_FREE(tcg, type)    __INSTR_ARG_ ##type ##_FREE(tcg)
 
diff --git a/instrument/host-stub.h b/instrument/host-stub.h
index 4178559..30d2cba 100644
--- a/instrument/host-stub.h
+++ b/instrument/host-stub.h
@@ -45,4 +45,13 @@ typedef enum {
  *   On all cases, the use of "instrument/state.h" is supported.
  */
 
+/** Signal the fetch and decode of a new instruction.
+ * @param addr Virtual address of the instruction (target_ulong)
+ * @param length Length of the instruction in bytes (uint32_t)
+ * @param used Set of used registers (instr_regs_t)
+ * @param defined Set of defined registers (instr_regs_t)
+ */
+#define INSTR_GEN_FETCH(taddr, addr, tlength, length,   \
+                        tused, used, tdefined, defined)
+
 #endif /* INSTRUMENT__HOST_STUB_H */
diff --git a/instrument/types.h b/instrument/types.h
index eb4036b..ba2b0c2 100644
--- a/instrument/types.h
+++ b/instrument/types.h
@@ -22,12 +22,17 @@
 
 /** Instrumentation argument types. */
 typedef enum {
-    INSTR_ARG_I32,                      /**< immediate of 32bits     */
-    INSTR_ARG_I64,                      /**< immediate of 64bits     */
-    INSTR_ARG_TUL,                      /**< immediate target_ulong  */
-    INSTR_ARG_TCGv_i32,                 /**< 32-bit TCGv variable    */
-    INSTR_ARG_TCGv_i64,                 /**< 64-bit TCGv variable    */
-    INSTR_ARG_TCGv,                     /**< target-bit TCGv variable*/
+    INSTR_ARG_I32,                      /**< immediate of 32bits         */
+    INSTR_ARG_I64,                      /**< immediate of 64bits         */
+    INSTR_ARG_TUL,                      /**< immediate target_ulong      */
+    INSTR_ARG_TCGv_i32,                 /**< 32-bit TCGv variable        */
+    INSTR_ARG_TCGv_i64,                 /**< 64-bit TCGv variable        */
+    INSTR_ARG_TCGv,                     /**< target-bit TCGv variable    */
+    INSTR_ARG_REGS,                     /**< register set (instr_regs_t) */
 } instr_arg_type_t;
 
+
+/** Register set. */
+typedef uint64_t instr_regs_t;
+
 #endif  /* INSTRUMENT__TYPES_H */
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 15/18] instrument: Add VMEM point
  2010-10-22 18:53 ` Lluís
                     ` (8 preceding siblings ...)
  2010-10-19 21:11   ` [Qemu-devel] [PATCH 13/18] instrument: Add FETCH point Lluís
@ 2010-10-19 21:12   ` Lluís
  2010-10-19 21:36   ` [Qemu-devel] [PATCH 18/18] instrument: [i386] Call PLVL point Lluís
                     ` (7 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-19 21:12 UTC (permalink / raw)
  To: qemu-devel


Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 instrument/examples/dynprint/host/helpers.c        |   24 ++++++
 .../dynprint/host/instrument-host-helpers.h        |    1 +
 .../examples/dynprint/host/instrument-host.h       |   19 ++++
 instrument/gen-vmem-wrappers.h                     |   88 ++++++++++++++++++++
 instrument/generate.h                              |    2 +
 instrument/host-stub.h                             |   17 ++++
 instrument/types.h                                 |    6 ++
 7 files changed, 157 insertions(+), 0 deletions(-)
 create mode 100644 instrument/gen-vmem-wrappers.h

diff --git a/instrument/examples/dynprint/host/helpers.c b/instrument/examples/dynprint/host/helpers.c
index 173d0ec..6355f43 100644
--- a/instrument/examples/dynprint/host/helpers.c
+++ b/instrument/examples/dynprint/host/helpers.c
@@ -60,3 +60,27 @@ helper_all_fetch (target_ulong addr, uint32_t size,
     print_registers("   used   :", used);
     print_registers("   defined:", defined);
 }
+
+inline
+void
+helper_all_mem (target_ulong addr, uint32_t size, instr_mem_mode_t mode)
+{
+    char smode;
+    switch (mode) {
+    case INSTR_MEM_RD:
+        smode = 'r';
+        break;
+    case INSTR_MEM_WR:
+        smode = 'w';
+        break;
+    default:
+        smode = '?';
+    }
+    printf("M: [%c] 0x"TARGET_FMT_lx" (%d)\n", smode, addr, size);
+}
+
+void
+helper_all_mem_direct (target_ulong addr, uint32_t size, instr_mem_mode_t mode)
+{
+    helper_all_mem(addr, size, mode);
+}
diff --git a/instrument/examples/dynprint/host/instrument-host-helpers.h b/instrument/examples/dynprint/host/instrument-host-helpers.h
index 947cf57..d0de0a1 100644
--- a/instrument/examples/dynprint/host/instrument-host-helpers.h
+++ b/instrument/examples/dynprint/host/instrument-host-helpers.h
@@ -19,3 +19,4 @@
 
 DEF_HELPER_1(pc, void, tl);
 DEF_HELPER_4(all_fetch, void, tl, i32, i64, i64);
+DEF_HELPER_3(all_mem, void, tl, i32, i32);
diff --git a/instrument/examples/dynprint/host/instrument-host.h b/instrument/examples/dynprint/host/instrument-host.h
index 15911e7..30eb7d4 100644
--- a/instrument/examples/dynprint/host/instrument-host.h
+++ b/instrument/examples/dynprint/host/instrument-host.h
@@ -22,6 +22,9 @@
 
 /* See "instrument/host-stub.h" for a description of macro arguments. */
 
+/* Cannot use helpers in DO macros. */
+void helper_all_mem_direct (target_ulong, uint32_t, uint32_t);
+
 /* Instrumentation types */
 typedef enum {
     INSTR_TYPE_ENABLED, /* Instrumentation enabled.
@@ -46,4 +49,20 @@ typedef enum {
                         tused, used, tdefined, defined);                \
         }                                                               \
     } while (0)
+
+#define INSTR_GEN_VMEM(taddr, addr, tlength, length, tmode, mode)       \
+    do {                                                                \
+        if (INSTR_TYPE(ENABLED) && INSTR_TYPE(ALL)) {                   \
+            INSTR_GEN_3(all_mem, taddr, addr, tlength, length,          \
+                        tmode, mode);                                   \
+        }                                                               \
+    } while (0)
+
+#define INSTR_DO_VMEM(cpu, addr, length, mode)                          \
+    do {                                                                \
+        if (INSTR_TYPE(ENABLED) && INSTR_TYPE(ALL)) {                   \
+            helper_all_mem_direct(addr, length, mode);                  \
+        }                                                               \
+    } while (0)
+
 #endif /* INSTRUMENT_HOST_H */
diff --git a/instrument/gen-vmem-wrappers.h b/instrument/gen-vmem-wrappers.h
new file mode 100644
index 0000000..7b376ff
--- /dev/null
+++ b/instrument/gen-vmem-wrappers.h
@@ -0,0 +1,88 @@
+/*
+ * Wrappers for code generation of virtual memory accesses.
+ *
+ *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INSTRUMENT__GEN_VMEM_WRAPPERS_H
+#define INSTRUMENT__GEN_VMEM_WRAPPERS_H
+
+/* Capture code generation for virtual memory accesses.
+ *
+ * Assumes that no other lower-level call will be performed by target
+ * architecture disassembly code on TCG instructions.
+ *
+ * TODO: lacks physical accesses (ld/st*_phys ?)
+ * TODO: lacks accesses performed by DMA
+ */
+
+#define tcg_gen_qemu_ld8u(arg, addr, mem_index)                 \
+    do {                                                        \
+        INSTR_GEN_VMEM(TCGv, addr, I32, 1, MEM_MODE, RD);       \
+        (tcg_gen_qemu_ld8u)(arg, addr, mem_index);              \
+    } while (0)
+#define tcg_gen_qemu_ld8s(arg, addr, mem_index)                 \
+    do {                                                        \
+        INSTR_GEN_VMEM(TCGv, addr, I32, 1, MEM_MODE, RD);       \
+        (tcg_gen_qemu_ld8s)(arg, addr, mem_index);              \
+    } while (0)
+#define tcg_gen_qemu_ld16u(arg, addr, mem_index)                \
+    do {                                                        \
+        INSTR_GEN_VMEM(TCGv, addr, I32, 2, MEM_MODE, RD);       \
+        (tcg_gen_qemu_ld16u)(arg, addr, mem_index);             \
+    } while (0)
+#define tcg_gen_qemu_ld16s(arg, addr, mem_index)                \
+    do {                                                        \
+        INSTR_GEN_VMEM(TCGv, addr, I32, 2, MEM_MODE, RD);       \
+        (tcg_gen_qemu_ld16s)(arg, addr, mem_index);             \
+    } while (0)
+#define tcg_gen_qemu_ld32u(arg, addr, mem_index)                \
+    do {                                                        \
+        INSTR_GEN_VMEM(TCGv, addr, I32, 4, MEM_MODE, RD);       \
+        (tcg_gen_qemu_ld32u)(arg, addr, mem_index);             \
+    } while (0)
+#define tcg_gen_qemu_ld32s(arg, addr, mem_index)                \
+    do {                                                        \
+        INSTR_GEN_VMEM(TCGv, addr, I32, 4, MEM_MODE, RD);       \
+        (tcg_gen_qemu_ld32s)(arg, addr, mem_index);             \
+    } while (0)
+#define tcg_gen_qemu_ld64(arg, addr, mem_index)                 \
+    do {                                                        \
+        INSTR_GEN_VMEM(TCGv, addr, I32, 8, MEM_MODE, RD);       \
+        (tcg_gen_qemu_ld64)(arg, addr, mem_index);              \
+    } while (0)
+#define tcg_gen_qemu_st8(arg, addr, mem_index)                  \
+    do {                                                        \
+        INSTR_GEN_VMEM(TCGv, addr, I32, 1, MEM_MODE, WR);       \
+        (tcg_gen_qemu_st8)(arg, addr, mem_index);               \
+    } while (0)
+#define tcg_gen_qemu_st16(arg, addr, mem_index)                 \
+    do {                                                        \
+        INSTR_GEN_VMEM(TCGv, addr, I32, 2, MEM_MODE, WR);       \
+        (tcg_gen_qemu_st16)(arg, addr, mem_index);              \
+    } while (0)
+#define tcg_gen_qemu_st32(arg, addr, mem_index)                 \
+    do {                                                        \
+        INSTR_GEN_VMEM(TCGv, addr, I32, 4, MEM_MODE, WR);       \
+        (tcg_gen_qemu_st32)(arg, addr, mem_index);              \
+    } while (0)
+#define tcg_gen_qemu_st64(arg, addr, mem_index)                 \
+    do {                                                        \
+        INSTR_GEN_VMEM(TCGv, addr, I32, 8, MEM_MODE, WR);       \
+        (tcg_gen_qemu_st64)(arg, addr, mem_index);              \
+    } while (0)
+
+#endif  /* INSTRUMEN__GEN_VMEM_WRAPPERS_H */
diff --git a/instrument/generate.h b/instrument/generate.h
index 60f0c31..53b44de 100644
--- a/instrument/generate.h
+++ b/instrument/generate.h
@@ -103,6 +103,7 @@
 #define __INSTR_ARG_TCGv_i32_DECL(tcg, value) TCGv_i32 tcg = value
 #endif
 #define __INSTR_ARG_REGS_DECL(tcg, value)     __INSTR_ARG_I64_DECL(tcg, value)
+#define __INSTR_ARG_MEM_MODE_DECL(tcg, value) __INSTR_ARG_I32_DECL(tcg, INSTR_MEM_ ##value)
 
 #define __INSTR_ARG_DECL(tcg, type, value)    __INSTR_ARG_ ##type ##_DECL(tcg, value)
 
@@ -120,6 +121,7 @@
 #define __INSTR_ARG_TCGv_i32_FREE(tcg)
 #define __INSTR_ARG_TCGv_FREE(tcg)
 #define __INSTR_ARG_REGS_FREE(tcg)     __INSTR_ARG_I64_FREE(tcg)
+#define __INSTR_ARG_MEM_MODE_FREE(tcg) __INSTR_ARG_I32_FREE(tcg)
 
 #define __INSTR_ARG_FREE(tcg, type)    __INSTR_ARG_ ##type ##_FREE(tcg)
 
diff --git a/instrument/host-stub.h b/instrument/host-stub.h
index 30d2cba..bfe5b06 100644
--- a/instrument/host-stub.h
+++ b/instrument/host-stub.h
@@ -54,4 +54,21 @@ typedef enum {
 #define INSTR_GEN_FETCH(taddr, addr, tlength, length,   \
                         tused, used, tdefined, defined)
 
+/** Signal a virtual memory access.
+ * This is called before checking if the memory access is allowed.
+ * @param addr Address of the memory access (TCGv)
+ * @param length Length of the memory access in bytes (uint32_t)
+ * @param mode Access mode (instr_mem_mode_t)
+ */
+#define INSTR_GEN_VMEM(taddr, addr, tlength, length, tmode, mode)
+
+/** Signal a virtual memory access.
+ * This is called before checking if the memory access is allowed.
+ * @param cpu  CPU performing the operation (CPUState*)
+ * @param addr Address of the memory access (target_ulong)
+ * @param length Length of the memory access in bytes (uint32_t)
+ * @param mode Access mode (instr_mem_mode_t)
+ */
+#define INSTR_DO_VMEM(cpu, addr, length, mode)
+
 #endif /* INSTRUMENT__HOST_STUB_H */
diff --git a/instrument/types.h b/instrument/types.h
index ba2b0c2..4e5b7a3 100644
--- a/instrument/types.h
+++ b/instrument/types.h
@@ -35,4 +35,10 @@ typedef enum {
 /** Register set. */
 typedef uint64_t instr_regs_t;
 
+/** Memory access type. */
+typedef enum {
+    INSTR_MEM_RD,                       /**< read memory  */
+    INSTR_MEM_WR,                       /**< write memory */
+} instr_mem_mode_t;
+
 #endif  /* INSTRUMENT__TYPES_H */
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 18/18] instrument: [i386] Call PLVL point
  2010-10-22 18:53 ` Lluís
                     ` (9 preceding siblings ...)
  2010-10-19 21:12   ` [Qemu-devel] [PATCH 15/18] instrument: Add VMEM point Lluís
@ 2010-10-19 21:36   ` Lluís
  2010-10-19 21:36   ` [Qemu-devel] [PATCH 17/18] instrument: Add " Lluís
                     ` (6 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-19 21:36 UTC (permalink / raw)
  To: qemu-devel


Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 instrument/host.h |   31 -------------------------------
 target-i386/cpu.h |   21 +++++++++++----------
 2 files changed, 11 insertions(+), 41 deletions(-)
 delete mode 100644 instrument/host.h

diff --git a/instrument/host.h b/instrument/host.h
deleted file mode 100644
index cd120d0..0000000
--- a/instrument/host.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Static instrumentation points.
- *
- *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef INSTRUMENT__HOST_H
-#define INSTRUMENT__HOST_H
-
-#if defined(CONFIG_INSTRUMENT)
-/* user-provided definitions */
-#include "instrument-host.h"
-#else
-/* empty stub definitions */
-#include "instrument/host-stub.h"
-#endif
-
-#endif  /* INSTRUMENT__HOST_H */
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 1144d4e..e8d3953 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -810,16 +810,6 @@ int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
                             target_ulong *base, unsigned int *limit,
                             unsigned int *flags);
 
-/* wrapper, just in case memory mappings must be changed */
-static inline void cpu_x86_set_cpl(CPUX86State *s, int cpl)
-{
-#if HF_CPL_MASK == 3
-    s->hflags = (s->hflags & ~HF_CPL_MASK) | cpl;
-#else
-#error HF_CPL_MASK is hardcoded
-#endif
-}
-
 /* op_helper.c */
 /* used for debug or cpu save/restore */
 void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f);
@@ -939,6 +929,17 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
 #include "hw/apic.h"
 #endif
 
+/* wrapper, just in case memory mappings must be changed */
+static inline void cpu_x86_set_cpl(CPUX86State *s, int cpl)
+{
+    INSTR_DO_PLVL(s, cpl);
+#if HF_CPL_MASK == 3
+    s->hflags = (s->hflags & ~HF_CPL_MASK) | cpl;
+#else
+#error HF_CPL_MASK is hardcoded
+#endif
+}
+
 static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 17/18] instrument: Add PLVL point
  2010-10-22 18:53 ` Lluís
                     ` (10 preceding siblings ...)
  2010-10-19 21:36   ` [Qemu-devel] [PATCH 18/18] instrument: [i386] Call PLVL point Lluís
@ 2010-10-19 21:36   ` Lluís
  2010-10-19 21:37   ` [Qemu-devel] [PATCH 10/18] instrument: Dynamic per-CPU state of static instrumentation points Lluís
                     ` (5 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-19 21:36 UTC (permalink / raw)
  To: qemu-devel


Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 instrument/examples/dynprint/guest/test.c          |    1 +
 .../examples/dynprint/host/instrument-host.h       |   21 ++++++++++++++++---
 instrument/host-stub.h                             |    7 ++++++
 3 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/instrument/examples/dynprint/guest/test.c b/instrument/examples/dynprint/guest/test.c
index b6b5788..ce43a48 100644
--- a/instrument/examples/dynprint/guest/test.c
+++ b/instrument/examples/dynprint/guest/test.c
@@ -31,6 +31,7 @@ main ()
     int i;
 
     BACKDOOR_i8(0x01);                  /* enable instrumentation */
+    BACKDOOR_i8_V(0x01, INSTR_TYPE_USER);
 
     printf("start\n");
     BACKDOOR_i8_V(0x01, INSTR_TYPE_PC); /* show executed PCs */
diff --git a/instrument/examples/dynprint/host/instrument-host.h b/instrument/examples/dynprint/host/instrument-host.h
index 30eb7d4..24b6ece 100644
--- a/instrument/examples/dynprint/host/instrument-host.h
+++ b/instrument/examples/dynprint/host/instrument-host.h
@@ -32,6 +32,7 @@ typedef enum {
                          * global state of tracing is wasteful, but hey, this is
                          * just an example.
                          */
+    INSTR_TYPE_USER,    /* Executing at user-level                           */
     INSTR_TYPE_PC,      /* Print fetched PC                                  */
     INSTR_TYPE_ALL,     /* Print all instruction information                 */
     INSTR_TYPE_COUNT    /* Total number of instrumentation types (mandatory) */
@@ -41,10 +42,10 @@ typedef enum {
 #define INSTR_GEN_FETCH(taddr, addr, tlength, length,                   \
                         tused, used, tdefined, defined)                 \
     do {                                                                \
-        if (INSTR_TYPE(ENABLED) && INSTR_TYPE(PC)) {                    \
+        if (INSTR_TYPE(ENABLED) && INSTR_TYPE(PC) && INSTR_TYPE(USER)) { \
             INSTR_GEN_1(pc, taddr, addr);                               \
         }                                                               \
-        if (INSTR_TYPE(ENABLED) && INSTR_TYPE(ALL)) {                   \
+        if (INSTR_TYPE(ENABLED) && INSTR_TYPE(ALL) && INSTR_TYPE(USER)) { \
             INSTR_GEN_4(all_fetch, taddr, addr, tlength, length,        \
                         tused, used, tdefined, defined);                \
         }                                                               \
@@ -52,7 +53,7 @@ typedef enum {
 
 #define INSTR_GEN_VMEM(taddr, addr, tlength, length, tmode, mode)       \
     do {                                                                \
-        if (INSTR_TYPE(ENABLED) && INSTR_TYPE(ALL)) {                   \
+        if (INSTR_TYPE(ENABLED) && INSTR_TYPE(ALL) && INSTR_TYPE(USER)) { \
             INSTR_GEN_3(all_mem, taddr, addr, tlength, length,          \
                         tmode, mode);                                   \
         }                                                               \
@@ -60,9 +61,21 @@ typedef enum {
 
 #define INSTR_DO_VMEM(cpu, addr, length, mode)                          \
     do {                                                                \
-        if (INSTR_TYPE(ENABLED) && INSTR_TYPE(ALL)) {                   \
+        if (INSTR_TYPE(ENABLED) && INSTR_TYPE(ALL) && INSTR_TYPE(USER)) { \
             helper_all_mem_direct(addr, length, mode);                  \
         }                                                               \
     } while (0)
 
+#define INSTR_DO_PLVL(cpu, plvl)                        \
+    do {                                                \
+        if (INSTR_CPU_TYPE(cpu, ENABLED)) {             \
+            if (plvl == 0) {                            \
+                instr_disable_type(INSTR_TYPE_USER);    \
+            }                                           \
+            else{                                       \
+                instr_enable_type(INSTR_TYPE_USER);     \
+            }                                           \
+        }                                               \
+    } while (0)
+
 #endif /* INSTRUMENT_HOST_H */
diff --git a/instrument/host-stub.h b/instrument/host-stub.h
index bfe5b06..5cba4f2 100644
--- a/instrument/host-stub.h
+++ b/instrument/host-stub.h
@@ -71,4 +71,11 @@ typedef enum {
  */
 #define INSTR_DO_VMEM(cpu, addr, length, mode)
 
+/** Signal a privilege level change.
+ * This is called before actually changing the privilege level.
+ * @param cpu  CPU performing the operation (CPUState*)
+ * @param plvl New value for the privilege level (uint32_t)
+ */
+#define INSTR_DO_PLVL(cpu, plvl)
+
 #endif /* INSTRUMENT__HOST_STUB_H */
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 10/18] instrument: Dynamic per-CPU state of static instrumentation points
  2010-10-22 18:53 ` Lluís
                     ` (11 preceding siblings ...)
  2010-10-19 21:36   ` [Qemu-devel] [PATCH 17/18] instrument: Add " Lluís
@ 2010-10-19 21:37   ` Lluís
  2010-10-19 21:40   ` [Qemu-devel] [PATCH 14/18] instrument: [i386] Call FETCH point Lluís
                     ` (4 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-19 21:37 UTC (permalink / raw)
  To: qemu-devel


The user-provided implementation for instrumentation points can define and use
"instrumentation types" as the atomic unit of instrumentation point
(de)activation.

The set of "instrumentation types" is named as "instrumentation state" (just a
bitset, one bit per type), which can be independently controlled on each
emulated CPU.

Thus, during guest code translation, instrumentation points execute arbitrary
code, including generating new TCG code, which will be generated only for CPUs
with an instrumentation state that matches the instrumentation type requirements
of the user-provided instrumentation point implementation.

This is efficiently supported by having one translation block table for each
possible instrumentation state, such that code translations can be efficiently
reused even if the CPUs are constantly changing their instrumentation state.

The net effect is similar (in terms of avoiding TB flushes) to that of the
execution of TBs that are marked to be available only under certain CPU
privilege levels.

Note that for simplicity, every CPU state change flushes the virtual translation
block table of the afected CPU ('tb_jmp_cache'), but not the global physical
translation block table ('tb_phys_hash'), which is the one containing one set of
translations for each instrumentation state.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 Makefile.target                                    |    8 ++-
 cpu-all.h                                          |    7 ++
 cpu-defs.h                                         |   24 ++++++
 cpu-exec.c                                         |    8 ++-
 cpus.c                                             |    8 ++
 exec-all.h                                         |    5 +-
 exec.c                                             |   50 +++++++++-----
 instrument/control.c                               |   74 ++++++++++++++++++++
 instrument/control.h                               |   44 ++++++++++++
 instrument/examples/dynprint/guest/test.c          |   12 +++
 instrument/examples/dynprint/host/backdoor.c       |    9 +++
 .../examples/dynprint/host/instrument-host.h       |    5 ++
 instrument/host-stub.h                             |   48 +++++++++++++
 instrument/host.h                                  |   31 ++++++++
 instrument/state.h                                 |   61 ++++++++++++++++
 qemu-common.h                                      |    4 +
 target-microblaze/translate.c                      |    6 ++
 17 files changed, 383 insertions(+), 21 deletions(-)
 create mode 100644 instrument/control.c
 create mode 100644 instrument/control.h
 create mode 100644 instrument/host-stub.h
 create mode 100644 instrument/host.h
 create mode 100644 instrument/state.h

diff --git a/Makefile.target b/Makefile.target
index 90867e7..72849b3 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -353,12 +353,18 @@ endif
 
 #########################################################
 # static instrumentation
+obj-$(CONFIG_INSTRUMENT) += instrument/control.o
+
 ifdef CONFIG_INSTRUMENT
 VPATH := $(VPATH):$(INSTRUMENT_PATH)
 
+INSTRUMENT_DIR = instrument
 LIBINSTRUMENT_LIB = libinstrument/libinstrument.a
 LIBINSTRUMENT_CLEAN = libinstrument-clean
 
+instrument:
+	$(call quiet-command, mkdir -p instrument, "  MKDIR $(TARGET_DIR)$@")
+
 libinstrument/Makefile:
 	$(call quiet-command, mkdir -p libinstrument, "  CREAT $(TARGET_DIR)$@")
 	$(call quiet-command, rm -f libinstrument/Makefile)
@@ -376,7 +382,7 @@ libinstrument-clean:
 endif
 
 
-$(QEMU_PROG)-prepare: $(GENERATED_HEADERS) $(LIBBACKDOOR_LIB) $(LIBINSTRUMENT_LIB) $(QEMU_PROG)
+$(QEMU_PROG)-prepare: $(GENERATED_HEADERS) $(LIBBACKDOOR_LIB) $(INSTRUMENT_DIR) $(LIBINSTRUMENT_LIB) $(QEMU_PROG)
 
 $(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y) $(LIBBACKDOOR_LIB) $(LIBINSTRUMENT_LIB)
 	$(call LINK,$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)) $(LIBBACKDOOR_LIB) $(LIBINSTRUMENT_LIB)
diff --git a/cpu-all.h b/cpu-all.h
index 67a3266..1be1c60 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -22,6 +22,13 @@
 #include "qemu-common.h"
 #include "cpu-common.h"
 
+#if defined(CONFIG_INSTRUMENT)
+
+#include "instrument/control.h"
+#include "instrument/state.h"
+
+#endif  /* defined(CONFIG_INSTRUMENT) */
+
 /* some important defines:
  *
  * WORDS_ALIGNED : if defined, the host cpu can only make word aligned
diff --git a/cpu-defs.h b/cpu-defs.h
index 8d4bf86..f896844 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -147,6 +147,28 @@ typedef struct CPUWatchpoint {
     QTAILQ_ENTRY(CPUWatchpoint) entry;
 } CPUWatchpoint;
 
+
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument-host.h"
+#include "instrument/state.h"
+
+/* Extra attributes for CPUState */
+#define INSTR_CPUState                                          \
+    /** Current instrumentation state. */                       \
+    instr_state_t instr_state;                                  \
+    /** Inidcate a pending instrumentation state change. */     \
+    instr_state_t instr_state_request;
+
+#else  /* defined(CONFIG_INSTRUMENT) */
+
+#include "instrument/host-stub.h"
+#include "instrument/state.h"
+
+#define INSTR_CPUState
+
+#endif  /* defined(CONFIG_INSTRUMENT) */
+
+
 #define CPU_TEMP_BUF_NLONGS 128
 #define CPU_COMMON                                                      \
     struct TranslationBlock *current_tb; /* currently executing TB  */  \
@@ -166,6 +188,8 @@ typedef struct CPUWatchpoint {
     /* buffer for temporaries in the code generator */                  \
     long temp_buf[CPU_TEMP_BUF_NLONGS];                                 \
                                                                         \
+    INSTR_CPUState;                                                     \
+                                                                        \
     int64_t icount_extra; /* Instructions until next timer event.  */   \
     /* Number of cycles left, with interrupt flag in high bit.          \
        This allows a single read-compare-cbranch-write sequence to test \
diff --git a/cpu-exec.c b/cpu-exec.c
index dbdfdcc..d925ee9 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -140,7 +140,7 @@ static TranslationBlock *tb_find_slow(target_ulong pc,
     phys_page1 = phys_pc & TARGET_PAGE_MASK;
     phys_page2 = -1;
     h = tb_phys_hash_func(phys_pc);
-    ptb1 = &tb_phys_hash[h];
+    ptb1 = &tb_phys_hash[INSTR_CURR_STATE][h];
     for(;;) {
         tb = *ptb1;
         if (!tb)
@@ -553,6 +553,12 @@ int cpu_exec(CPUState *env1)
                     env->exception_index = EXCP_INTERRUPT;
                     cpu_loop_exit();
                 }
+#if defined(CONFIG_INSTRUMENT)
+                if (unlikely(env->instr_state != env->instr_state_request)) {
+                    instr_cpu_do_state_change(env);
+                    next_tb = 0;
+                }
+#endif
 #if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
                 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
                     /* restore flags in standard format */
diff --git a/cpus.c b/cpus.c
index b09f5e3..47dc22d 100644
--- a/cpus.c
+++ b/cpus.c
@@ -256,6 +256,10 @@ void qemu_init_vcpu(void *_env)
 {
     CPUState *env = _env;
 
+#if defined(CONFIG_INSTRUMENT)
+    instr_init_vcpu(env);
+#endif
+
     env->nr_cores = smp_cores;
     env->nr_threads = smp_threads;
     if (kvm_enabled())
@@ -700,6 +704,10 @@ void qemu_init_vcpu(void *_env)
 {
     CPUState *env = _env;
 
+#if defined(CONFIG_INSTRUMENT)
+    instr_init_vcpu(env);
+#endif
+
     env->nr_cores = smp_cores;
     env->nr_threads = smp_threads;
     if (kvm_enabled())
diff --git a/exec-all.h b/exec-all.h
index 2ae09c5..35d2a57 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -158,6 +158,9 @@ struct TranslationBlock {
     struct TranslationBlock *jmp_next[2];
     struct TranslationBlock *jmp_first;
     uint32_t icount;
+#if defined(CONFIG_INSTRUMENT)
+    instr_state_t instr_state;
+#endif
 };
 
 static inline unsigned int tb_jmp_cache_hash_page(target_ulong pc)
@@ -189,7 +192,7 @@ void tb_link_page(TranslationBlock *tb,
                   tb_page_addr_t phys_pc, tb_page_addr_t phys_page2);
 void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
 
-extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
+extern TranslationBlock *tb_phys_hash[INSTR_STATE_COUNT][CODE_GEN_PHYS_HASH_SIZE];
 
 #if defined(USE_DIRECT_JUMP)
 
diff --git a/exec.c b/exec.c
index 516960a..24ade3c 100644
--- a/exec.c
+++ b/exec.c
@@ -81,7 +81,7 @@
 
 static TranslationBlock *tbs;
 static int code_gen_max_blocks;
-TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
+TranslationBlock *tb_phys_hash[INSTR_STATE_COUNT][CODE_GEN_PHYS_HASH_SIZE];
 static int nb_tbs;
 /* any access to the tbs or the page table must use this lock */
 spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
@@ -713,7 +713,8 @@ void tb_flush(CPUState *env1)
         tb_flush_jmp_cache(env);
     }
 
-    memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
+    memset (tb_phys_hash, 0,
+            INSTR_STATE_COUNT * CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
     page_flush_tb();
 
     code_gen_ptr = code_gen_buffer;
@@ -727,15 +728,18 @@ void tb_flush(CPUState *env1)
 static void tb_invalidate_check(target_ulong address)
 {
     TranslationBlock *tb;
+    instr_state_t s;
     int i;
     address &= TARGET_PAGE_MASK;
-    for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
-        for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
-            if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
-                  address >= tb->pc + tb->size)) {
-                printf("ERROR invalidate: address=" TARGET_FMT_lx
-                       " PC=%08lx size=%04x\n",
-                       address, (long)tb->pc, tb->size);
+    for (s = 0; s < INSTR_STATE_COUNT; s++) {
+        for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
+            for(tb = tb_phys_hash[s][i]; tb != NULL; tb = tb->phys_hash_next) {
+                if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
+                      address >= tb->pc + tb->size)) {
+                    printf("ERROR invalidate: address=" TARGET_FMT_lx
+                           " PC=%08lx size=%04x\n",
+                           address, (long)tb->pc, tb->size);
+                }
             }
         }
     }
@@ -745,15 +749,18 @@ static void tb_invalidate_check(target_ulong address)
 static void tb_page_check(void)
 {
     TranslationBlock *tb;
+    instr_state_t s;
     int i, flags1, flags2;
 
-    for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
-        for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
-            flags1 = page_get_flags(tb->pc);
-            flags2 = page_get_flags(tb->pc + tb->size - 1);
-            if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
-                printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
-                       (long)tb->pc, tb->size, flags1, flags2);
+    for(s = 0; s < INSTR_STATE_COUNT; s++) {
+        for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
+            for(tb = tb_phys_hash[s][i]; tb != NULL; tb = tb->phys_hash_next) {
+                flags1 = page_get_flags(tb->pc);
+                flags2 = page_get_flags(tb->pc + tb->size - 1);
+                if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
+                    printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
+                           (long)tb->pc, tb->size, flags1, flags2);
+                }
             }
         }
     }
@@ -839,7 +846,7 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
     /* remove the TB from the hash list */
     phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
     h = tb_phys_hash_func(phys_pc);
-    tb_remove(&tb_phys_hash[h], tb,
+    tb_remove(&tb_phys_hash[INSTR_TB_STATE(tb)][h], tb,
               offsetof(TranslationBlock, phys_hash_next));
 
     /* remove the TB from the page list */
@@ -964,6 +971,9 @@ TranslationBlock *tb_gen_code(CPUState *env,
     tb->cs_base = cs_base;
     tb->flags = flags;
     tb->cflags = cflags;
+#if defined(CONFIG_INSTRUMENT)
+    tb->instr_state = env->instr_state;
+#endif
     cpu_gen_code(env, tb, &code_gen_size);
     code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
 
@@ -1269,7 +1279,7 @@ void tb_link_page(TranslationBlock *tb,
     mmap_lock();
     /* add in the physical hash table */
     h = tb_phys_hash_func(phys_pc);
-    ptb = &tb_phys_hash[h];
+    ptb = &tb_phys_hash[INSTR_TB_STATE(tb)][h];
     tb->phys_hash_next = *ptb;
     *ptb = tb;
 
@@ -3139,6 +3149,8 @@ static void check_watchpoint(int offset, int len_mask, int flags)
                               "pc=%p", (void *)env->mem_io_pc);
                 }
                 cpu_restore_state(tb, env, env->mem_io_pc, NULL);
+                /* XXX: It is OK to invalidate only this TB (and not for all
+                 * states), as this is the one triggering the memory access */
                 tb_phys_invalidate(tb, -1);
                 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
                     env->exception_index = EXCP_DEBUG;
@@ -4079,6 +4091,8 @@ void cpu_io_recompile(CPUState *env, void *retaddr)
     pc = tb->pc;
     cs_base = tb->cs_base;
     flags = tb->flags;
+    /* XXX: It is OK to invalidate only this TB (and not for all states), as
+     * this is the one triggering the memory access */
     tb_phys_invalidate(tb, -1);
     /* FIXME: In theory this could raise an exception.  In practice
        we have already translated the block once so it's probably ok.  */
diff --git a/instrument/control.c b/instrument/control.c
new file mode 100644
index 0000000..c2c7476
--- /dev/null
+++ b/instrument/control.c
@@ -0,0 +1,74 @@
+/*
+ * Dynamic control of instrumentation states.
+ *
+ *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+
+#include "exec-all.h"
+#include "instrument/control.h"
+
+
+void
+instr_enable_type (instr_type_t type)
+{
+    CPUState *cpu;
+    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
+        instr_cpu_enable_type(cpu, type);
+    }
+}
+
+void
+instr_disable_type (instr_type_t type)
+{
+    CPUState *cpu;
+    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
+        instr_cpu_disable_type(cpu, type);
+    }
+}
+
+void
+instr_cpu_enable_type (CPUState * cpu, instr_type_t type)
+{
+    cpu->instr_state_request |= (1 << type);
+}
+
+void
+instr_cpu_disable_type (CPUState * cpu, instr_type_t type)
+{
+    cpu->instr_state_request &= ~(1 << type);
+}
+
+void
+instr_cpu_do_state_change (CPUState * cpu)
+{
+    cpu->instr_state = cpu->instr_state_request;
+    tb_flush_jmp_cache(cpu);
+}
+
+void
+instr_init_vcpu (CPUState * cpu)
+{
+    int bits = sizeof(cpu->instr_state) * 8;
+    if (INSTR_TYPE_COUNT > bits) {
+        fprintf(stderr, "Can only support at most %d instrumentation types\n",
+                bits);
+        abort();
+    }
+    cpu->instr_state = 0;
+    cpu->instr_state_request = cpu->instr_state;
+}
diff --git a/instrument/control.h b/instrument/control.h
new file mode 100644
index 0000000..c4ee12c
--- /dev/null
+++ b/instrument/control.h
@@ -0,0 +1,44 @@
+/*
+ * Dynamic control of instrumentation states.
+ *
+ *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INSTRUMENT__CONTROL_H
+#define INSTRUMENT__CONTROL_H
+
+#include "instrument-host.h"
+
+/** Enable instrumentation for given type on all CPUs. */
+void instr_enable_type (instr_type_t type);
+/** Disable instrumentation for given type on all CPUs. */
+void instr_disable_type (instr_type_t type);
+
+/** Enable instrumentation for given type on given CPU. */
+void instr_cpu_enable_type (CPUState * cpu, instr_type_t type);
+/** Disable instrumentation for given type on given CPU. */
+void instr_cpu_disable_type (CPUState * cpu, instr_type_t type);
+
+
+/* Internal API */
+
+/** Apply instrumentation state changes. */
+void instr_cpu_do_state_change (CPUState * cpu);
+
+/** Initialize per-cpu insrumentation variables. */
+void instr_init_vcpu (CPUState * cpu);
+
+#endif /* INSTRUMENT__CONTROL_H */
diff --git a/instrument/examples/dynprint/guest/test.c b/instrument/examples/dynprint/guest/test.c
index 254ebcf..7ddd5be 100644
--- a/instrument/examples/dynprint/guest/test.c
+++ b/instrument/examples/dynprint/guest/test.c
@@ -19,6 +19,8 @@
 
 #include <stdio.h>
 
+#include "backdoor/guest.h"
+
 #define TOTAL_ITERS 100
 
 
@@ -27,13 +29,23 @@ main ()
 {
     int i;
 
+    BACKDOOR_i8(0x01);                  /* enable instrumentation */
+
     printf("start\n");
 
     for (i = 0; i < TOTAL_ITERS; i++) {
+        /* disable an iteration every 10 iterations */
+        if (i % 10 == 0) {
+            BACKDOOR_i8(0x00);
+        }
         printf("iteration\n");
+        if (i % 10 == 0) {
+            BACKDOOR_i8(0x01);
+        }
     }
 
     printf("stop\n");
 
+    BACKDOOR_i8(0x00);                  /* disable instrumentation */
     return 0;
 }
diff --git a/instrument/examples/dynprint/host/backdoor.c b/instrument/examples/dynprint/host/backdoor.c
index 7b4e883..27f612b 100644
--- a/instrument/examples/dynprint/host/backdoor.c
+++ b/instrument/examples/dynprint/host/backdoor.c
@@ -21,12 +21,21 @@
 
 #include "cpu.h"
 #include "helper.h"
+#include "instrument/control.h"
 
 
 void
 helper_backdoor_i8 (uint32_t imm)
 {
     switch (imm) {
+    case 0:
+        printf("backdoor: -%d\n", INSTR_TYPE_ENABLED);
+        instr_disable_type(INSTR_TYPE_ENABLED);
+        break;
+    case 1:
+        printf("backdoor: +%d\n", INSTR_TYPE_ENABLED);
+        instr_enable_type(INSTR_TYPE_ENABLED);
+        break;
     default:
         printf("Unexpected use of instrumentation backdoor\n");
         abort();
diff --git a/instrument/examples/dynprint/host/instrument-host.h b/instrument/examples/dynprint/host/instrument-host.h
index 9ede6af..92a4c14 100644
--- a/instrument/examples/dynprint/host/instrument-host.h
+++ b/instrument/examples/dynprint/host/instrument-host.h
@@ -24,6 +24,11 @@
 
 /* Instrumentation types */
 typedef enum {
+    INSTR_TYPE_ENABLED, /* Instrumentation enabled.
+                         * Using an instrumentation type for identifying a
+                         * global state of tracing is wasteful, but hey, this is
+                         * just an example.
+                         */
     INSTR_TYPE_COUNT    /* Total number of instrumentation types (mandatory) */
 } instr_type_t;
 
diff --git a/instrument/host-stub.h b/instrument/host-stub.h
new file mode 100644
index 0000000..4178559
--- /dev/null
+++ b/instrument/host-stub.h
@@ -0,0 +1,48 @@
+/*
+ * Stub for empty static instrumentation points.
+ *
+ *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INSTRUMENT__HOST_STUB_H
+#define INSTRUMENT__HOST_STUB_H
+
+/** Instrumentation types. */
+typedef enum {
+    INSTR_TYPE_COUNT   /**< Total number of instrumentation types (mandatory) */
+} instr_type_t;
+
+/* All instrumentation point macros follow a strict naming scheme:
+ *    INSTR_<when>_<point>
+ *
+ * - <point>
+ *   A name for a conceptual generic event.
+ *
+ * - <when>
+ *   Describes when the instrumentation point is invoked:
+ *
+ *   - GEN
+ *     Invoked at TB generation time. If information is to be used, it must be
+ *     so through the use of "instrument/generate.h".
+ *
+ *   - DO
+ *     Invoked at instruction emulation time. If information is to be used, it
+ *     must be so by simply providing extra code.
+ *
+ *   On all cases, the use of "instrument/state.h" is supported.
+ */
+
+#endif /* INSTRUMENT__HOST_STUB_H */
diff --git a/instrument/host.h b/instrument/host.h
new file mode 100644
index 0000000..cd120d0
--- /dev/null
+++ b/instrument/host.h
@@ -0,0 +1,31 @@
+/*
+ * Static instrumentation points.
+ *
+ *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INSTRUMENT__HOST_H
+#define INSTRUMENT__HOST_H
+
+#if defined(CONFIG_INSTRUMENT)
+/* user-provided definitions */
+#include "instrument-host.h"
+#else
+/* empty stub definitions */
+#include "instrument/host-stub.h"
+#endif
+
+#endif  /* INSTRUMENT__HOST_H */
diff --git a/instrument/state.h b/instrument/state.h
new file mode 100644
index 0000000..60221c1
--- /dev/null
+++ b/instrument/state.h
@@ -0,0 +1,61 @@
+/*
+ * Instrumentation state information.
+ *
+ *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INSTRUMENT__STATE_H
+#define INSTRUMENT__STATE_H
+
+/** Instrumentation state. */
+typedef uint16_t instr_state_t;
+
+/** Number of available instrumentation states. */
+#define INSTR_STATE_COUNT (((instr_state_t)1) << INSTR_TYPE_COUNT)
+
+/** Get instrumentation state of current CPU.
+ * This macro will also work when instrumentation is not compiled in.
+ */
+#define INSTR_CURR_STATE INSTR_CPU_STATE(cpu_single_env)
+
+
+#if defined(CONFIG_INSTRUMENT)
+
+/** Check if given instrumentation type is enabled on current CPU. */
+#define INSTR_TYPE(type) (INSTR_CURR_STATE & (1 << INSTR_TYPE_ ##type))
+
+/** Check if given instrumentation type is enabled on given CPU. */
+#define INSTR_CPU_TYPE(cpu, type)                       \
+    (INSTR_CPU_STATE(cpu) & (1 << INSTR_TYPE_ ##type))
+
+/** Get instrumentation state of given CPU.
+ * This macro will also work when instrumentation is not compiled in.
+ */
+#define INSTR_CPU_STATE(cpu) ((cpu)->instr_state)
+
+/** Get instrumentation state of given TranslationBLock.
+ * This macro will also work when instrumentation is not compiled in.
+ */
+#define INSTR_TB_STATE(tb) ((tb)->instr_state)
+
+#else  /* defined(CONFIG_INSTRUMENT) */
+
+#define INSTR_CPU_STATE(cpu) 0
+#define INSTR_TB_STATE(tb) 0
+
+#endif  /* defined(CONFIG_INSTRUMENT) */
+
+#endif /* INSTRUMENT__STATE_H */
diff --git a/qemu-common.h b/qemu-common.h
index 81aafa0..e0063a7 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -278,7 +278,11 @@ struct qemu_work_item {
 };
 
 #ifdef CONFIG_USER_ONLY
+#if defined(CONFIG_INSTRUMENT)
+#define qemu_init_vcpu(env) do { instr_init_vcpu(env); } while (0)
+#else
 #define qemu_init_vcpu(env) do { } while (0)
+#endif
 #else
 void qemu_init_vcpu(void *env);
 #endif
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 38149bb..9dcc78a 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1607,6 +1607,12 @@ CPUState *cpu_mb_init (const char *cpu_model)
                           offsetof(CPUState, sregs[i]),
                           special_regnames[i]);
     }
+
+#if defined(CONFIG_INSTRUMENT)
+    /* XXX: Here only because qemu_init_vcpu is not called in this target */
+    instr_init_vcpu(env);
+#endif
+
 #define GEN_HELPER 2
 #include "helper.h"
 
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 14/18] instrument: [i386] Call FETCH point
  2010-10-22 18:53 ` Lluís
                     ` (12 preceding siblings ...)
  2010-10-19 21:37   ` [Qemu-devel] [PATCH 10/18] instrument: Dynamic per-CPU state of static instrumentation points Lluís
@ 2010-10-19 21:40   ` Lluís
  2010-10-21 14:36   ` [Qemu-devel] [PATCH 11/18] instrument: Code-generation macros Lluís
                     ` (3 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-19 21:40 UTC (permalink / raw)
  To: qemu-devel


Provides an instrumentation point for instruction fetch/decode events.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target-i386/translate.c |  113 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 113 insertions(+), 0 deletions(-)

diff --git a/target-i386/translate.c b/target-i386/translate.c
index b54a823..02a93a4 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -32,6 +32,32 @@
 #define GEN_HELPER 1
 #include "helper.h"
 
+#if defined(CONFIG_INSTRUMENT)
+static inline void
+mem_exchange (void * tmp, void * start1, size_t size1,
+              void * start2, size_t size2)
+{
+    memcpy(tmp      , start2, size2);
+    memcpy(tmp+size2, start1, size1);
+    memcpy(start1   , tmp   , size1+size2);
+}
+#endif
+
+
+/* tracking of register usage */
+#if defined(CONFIG_INSTRUMENT)
+struct DisasContext;
+/* Have current context always accessible */
+struct DisasContext * instr_disas = NULL;
+#endif
+
+#define INSTR_REGS_SET_GP(s, r) INSTR_REGS_SET(instr_disas->instr_regs_ ##s, r)
+/* TODO: access to env->regs in helper functions */
+/* TODO: not tracking register sets for: eflags, segments, floating point,
+ *       crX, ...
+ */
+
+
 #define PREFIX_REPZ   0x01
 #define PREFIX_REPNZ  0x02
 #define PREFIX_LOCK   0x04
@@ -116,6 +142,11 @@ typedef struct DisasContext {
     int cpuid_ext_features;
     int cpuid_ext2_features;
     int cpuid_ext3_features;
+#if defined(CONFIG_INSTRUMENT)
+    /* temporal vars for FETCH instrumentation */
+    instr_regs_t instr_regs_used;
+    instr_regs_t instr_regs_defined;
+#endif
 } DisasContext;
 
 static void gen_eob(DisasContext *s);
@@ -281,9 +312,13 @@ static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
         tmp = tcg_temp_new();
         tcg_gen_ext8u_tl(tmp, t0);
         if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) {
+            INSTR_REGS_SET_GP(used, reg);
+            INSTR_REGS_SET_GP(defined, reg);
             tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xff);
             tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], tmp);
         } else {
+            INSTR_REGS_SET_GP(used, reg - 4);
+            INSTR_REGS_SET_GP(defined, reg - 4);
             tcg_gen_shli_tl(tmp, tmp, 8);
             tcg_gen_andi_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], ~0xff00);
             tcg_gen_or_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], tmp);
@@ -293,6 +328,8 @@ static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
     case OT_WORD:
         tmp = tcg_temp_new();
         tcg_gen_ext16u_tl(tmp, t0);
+        INSTR_REGS_SET_GP(used, reg);
+        INSTR_REGS_SET_GP(defined, reg);
         tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff);
         tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], tmp);
         tcg_temp_free(tmp);
@@ -301,10 +338,12 @@ static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
     case OT_LONG:
         /* For x86_64, this sets the higher half of register to zero.
            For i386, this is equivalent to a mov. */
+        INSTR_REGS_SET_GP(defined, reg);
         tcg_gen_ext32u_tl(cpu_regs[reg], t0);
         break;
 #ifdef TARGET_X86_64
     case OT_QUAD:
+        INSTR_REGS_SET_GP(defined, reg);
         tcg_gen_mov_tl(cpu_regs[reg], t0);
         break;
 #endif
@@ -329,6 +368,8 @@ static inline void gen_op_mov_reg_A0(int size, int reg)
     case 0:
         tmp = tcg_temp_new();
         tcg_gen_ext16u_tl(tmp, cpu_A0);
+        INSTR_REGS_SET_GP(used, reg);
+        INSTR_REGS_SET_GP(defined, reg);
         tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff);
         tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], tmp);
         tcg_temp_free(tmp);
@@ -337,10 +378,12 @@ static inline void gen_op_mov_reg_A0(int size, int reg)
     case 1:
         /* For x86_64, this sets the higher half of register to zero.
            For i386, this is equivalent to a mov. */
+        INSTR_REGS_SET_GP(defined, reg);
         tcg_gen_ext32u_tl(cpu_regs[reg], cpu_A0);
         break;
 #ifdef TARGET_X86_64
     case 2:
+        INSTR_REGS_SET_GP(defined, reg);
         tcg_gen_mov_tl(cpu_regs[reg], cpu_A0);
         break;
 #endif
@@ -354,12 +397,14 @@ static inline void gen_op_mov_v_reg(int ot, TCGv t0, int reg)
         if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) {
             goto std_case;
         } else {
+            INSTR_REGS_SET_GP(used, reg - 4);
             tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8);
             tcg_gen_ext8u_tl(t0, t0);
         }
         break;
     default:
     std_case:
+        INSTR_REGS_SET_GP(used, reg);
         tcg_gen_mov_tl(t0, cpu_regs[reg]);
         break;
     }
@@ -372,6 +417,7 @@ static inline void gen_op_mov_TN_reg(int ot, int t_index, int reg)
 
 static inline void gen_op_movl_A0_reg(int reg)
 {
+    INSTR_REGS_SET_GP(used, reg);
     tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
 }
 
@@ -414,12 +460,16 @@ static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
 {
     switch(size) {
     case 0:
+        INSTR_REGS_SET_GP(used, reg);
+        INSTR_REGS_SET_GP(defined, reg);
         tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
         tcg_gen_ext16u_tl(cpu_tmp0, cpu_tmp0);
         tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff);
         tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0);
         break;
     case 1:
+        INSTR_REGS_SET_GP(used, reg);
+        INSTR_REGS_SET_GP(defined, reg);
         tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
         /* For x86_64, this sets the higher half of register to zero.
            For i386, this is equivalent to a nop. */
@@ -428,6 +478,8 @@ static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
         break;
 #ifdef TARGET_X86_64
     case 2:
+        INSTR_REGS_SET_GP(used, reg);
+        INSTR_REGS_SET_GP(defined, reg);
         tcg_gen_addi_tl(cpu_regs[reg], cpu_regs[reg], val);
         break;
 #endif
@@ -438,12 +490,16 @@ static inline void gen_op_add_reg_T0(int size, int reg)
 {
     switch(size) {
     case 0:
+        INSTR_REGS_SET_GP(used, reg);
+        INSTR_REGS_SET_GP(defined, reg);
         tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
         tcg_gen_ext16u_tl(cpu_tmp0, cpu_tmp0);
         tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff);
         tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0);
         break;
     case 1:
+        INSTR_REGS_SET_GP(used, reg);
+        INSTR_REGS_SET_GP(defined, reg);
         tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
         /* For x86_64, this sets the higher half of register to zero.
            For i386, this is equivalent to a nop. */
@@ -452,6 +508,8 @@ static inline void gen_op_add_reg_T0(int size, int reg)
         break;
 #ifdef TARGET_X86_64
     case 2:
+        INSTR_REGS_SET_GP(used, reg);
+        INSTR_REGS_SET_GP(defined, reg);
         tcg_gen_add_tl(cpu_regs[reg], cpu_regs[reg], cpu_T[0]);
         break;
 #endif
@@ -465,6 +523,7 @@ static inline void gen_op_set_cc_op(int32_t val)
 
 static inline void gen_op_addl_A0_reg_sN(int shift, int reg)
 {
+    INSTR_REGS_SET_GP(used, reg);
     tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
     if (shift != 0)
         tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
@@ -502,11 +561,13 @@ static inline void gen_op_addq_A0_seg(int reg)
 
 static inline void gen_op_movq_A0_reg(int reg)
 {
+    INSTR_REGS_SET_GP(used, reg);
     tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
 }
 
 static inline void gen_op_addq_A0_reg_sN(int shift, int reg)
 {
+    INSTR_REGS_SET_GP(used, reg);
     tcg_gen_mov_tl(cpu_tmp0, cpu_regs[reg]);
     if (shift != 0)
         tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);
@@ -707,6 +768,7 @@ static void gen_exts(int ot, TCGv reg)
 
 static inline void gen_op_jnz_ecx(int size, int label1)
 {
+    INSTR_REGS_SET_GP(used, R_ECX);
     tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
     gen_extu(size + 1, cpu_tmp0);
     tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1);
@@ -714,6 +776,7 @@ static inline void gen_op_jnz_ecx(int size, int label1)
 
 static inline void gen_op_jz_ecx(int size, int label1)
 {
+    INSTR_REGS_SET_GP(used, R_ECX);
     tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
     gen_extu(size + 1, cpu_tmp0);
     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
@@ -4090,6 +4153,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
     target_ulong next_eip, tval;
     int rex_w, rex_r;
 
+#if defined(CONFIG_INSTRUMENT)
+    uint16_t * instr_gen_opc_ptr = gen_opc_ptr;
+    TCGArg * instr_gen_opparam_ptr = gen_opparam_ptr;
+#endif
+
     if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
         tcg_gen_debug_insn_start(pc_start);
     s->pc = pc_start;
@@ -4105,6 +4173,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
     x86_64_hregs = 0;
 #endif
     s->rip_offset = 0; /* for relative ip address */
+#if defined(CONFIG_INSTRUMENT)
+    s->instr_regs_used = 0;
+    s->instr_regs_defined = 0;
+#endif
 
 #if defined(CONFIG_BACKDOOR)
     if (ldub_code(s->pc) == 0x0f &&  ldub_code(s->pc + 1) == 0x04) {
@@ -4118,6 +4190,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             break;
         case 0x01:                      /* i8 v */
             cmd = tcg_const_i32(ldub_code(s->pc + 3));
+            INSTR_REGS_SET_GP(used, R_EAX);
             gen_helper_backdoor_i8_v(cmd, cpu_regs[R_EAX]);
             break;
         default:
@@ -4901,6 +4974,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                 rm = 0; /* avoid warning */
             }
             label1 = gen_new_label();
+            INSTR_REGS_SET_GP(used, R_EAX);
             tcg_gen_sub_tl(t2, cpu_regs[R_EAX], t0);
             gen_extu(ot, t2);
             tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1);
@@ -5476,6 +5550,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             val = ldub_code(s->pc++);
             tcg_gen_movi_tl(cpu_T3, val);
         } else {
+            INSTR_REGS_SET_GP(used, R_ECX);
             tcg_gen_mov_tl(cpu_T3, cpu_regs[R_ECX]);
         }
         gen_shiftd_rm_T1_T3(s, ot, opreg, op);
@@ -6386,6 +6461,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
                 /* XXX: specific Intel behaviour ? */
                 l1 = gen_new_label();
                 gen_jcc1(s, s->cc_op, b ^ 1, l1);
+                INSTR_REGS_SET_GP(defined, reg);
                 tcg_gen_mov_tl(cpu_regs[reg], t0);
                 gen_set_label(l1);
                 tcg_gen_ext32u_tl(cpu_regs[reg], cpu_regs[reg]);
@@ -7666,6 +7742,36 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
 backdoor_done:
 #endif
 
+#if defined(CONFIG_INSTRUMENT)
+    {
+        uint16_t * old_gen_opc_ptr = gen_opc_ptr;
+        TCGArg * old_gen_opparam_ptr = gen_opparam_ptr;
+
+        INSTR_GEN_FETCH(TUL, pc_start,
+                        I32, s->pc - pc_start,
+                        REGS, s->instr_regs_used,
+                        REGS, s->instr_regs_defined);
+
+        /* Move TCG code generated by instrumentation callback */
+
+        if (old_gen_opc_ptr != gen_opc_ptr) {
+            typeof(*gen_opc_ptr) tmp[OPC_BUF_SIZE];
+            mem_exchange(tmp, instr_gen_opc_ptr,
+                         (old_gen_opc_ptr - instr_gen_opc_ptr) * sizeof(*gen_opc_ptr),
+                         old_gen_opc_ptr,
+                         (gen_opc_ptr - old_gen_opc_ptr) * sizeof(*gen_opc_ptr));
+        }
+
+        if (old_gen_opparam_ptr != gen_opparam_ptr) {
+            typeof(*gen_opparam_ptr) tmp[OPPARAM_BUF_SIZE];
+            mem_exchange(tmp, instr_gen_opparam_ptr,
+                         (old_gen_opparam_ptr - instr_gen_opparam_ptr) * sizeof(*gen_opparam_ptr),
+                         old_gen_opparam_ptr,
+                         (gen_opparam_ptr - old_gen_opparam_ptr) * sizeof(*gen_opparam_ptr));
+        }
+    }
+#endif
+
     /* lock generation */
     if (s->prefix & PREFIX_LOCK)
         gen_helper_unlock();
@@ -7812,6 +7918,9 @@ static inline void gen_intermediate_code_internal(CPUState *env,
                     || (flags & HF_SOFTMMU_MASK)
 #endif
                     );
+#if defined(CONFIG_INSTRUMENT)
+    instr_disas = dc;
+#endif
 #if 0
     /* check addseg logic */
     if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
@@ -7930,6 +8039,10 @@ static inline void gen_intermediate_code_internal(CPUState *env,
         tb->size = pc_ptr - pc_start;
         tb->icount = num_insns;
     }
+
+#if defined(CONFIG_INSTRUMENT)
+    instr_disas = NULL;
+#endif
 }
 
 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 11/18] instrument: Code-generation macros
  2010-10-22 18:53 ` Lluís
                     ` (13 preceding siblings ...)
  2010-10-19 21:40   ` [Qemu-devel] [PATCH 14/18] instrument: [i386] Call FETCH point Lluís
@ 2010-10-21 14:36   ` Lluís
  2010-10-21 17:42   ` [Qemu-devel] [PATCH 09/18] instrument: Add initial instrumentation example Lluís
                     ` (2 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-21 14:36 UTC (permalink / raw)
  To: qemu-devel


Provides some code-generation macros intended to be used by the user when
generating code on instrumentation points.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 cpu-all.h             |    2 +
 instrument/generate.h |  124 +++++++++++++++++++++++++++++++++++++++++++++++++
 instrument/types.h    |   33 +++++++++++++
 3 files changed, 159 insertions(+), 0 deletions(-)
 create mode 100644 instrument/generate.h
 create mode 100644 instrument/types.h

diff --git a/cpu-all.h b/cpu-all.h
index 1be1c60..b15253f 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -24,6 +24,8 @@
 
 #if defined(CONFIG_INSTRUMENT)
 
+#include "instrument/types.h"
+#include "instrument/generate.h"
 #include "instrument/control.h"
 #include "instrument/state.h"
 
diff --git a/instrument/generate.h b/instrument/generate.h
new file mode 100644
index 0000000..7e4b35c
--- /dev/null
+++ b/instrument/generate.h
@@ -0,0 +1,124 @@
+/*
+ * User macros for code generation in static instrumentation points.
+ *
+ *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INSTRUMENT__GENERATE_H
+#define INSTRUMENT__GENERATE_H
+
+/* Generate calls to code helpers (callback) with the provided arguments.
+ *
+ * Note that each argument comes in pairs: the type (instr_arg_type_t) and the
+ * value.
+ */
+
+#define INSTR_GEN_0(callback)                                           \
+    do {                                                                \
+        gen_helper_ ##callback();                                       \
+    } while(0)
+
+#define INSTR_GEN_1(callback, type1, arg1)                              \
+    do {                                                                \
+        __INSTR_ARG_DECL(tmp1, type1, arg1);                            \
+        gen_helper_ ##callback (tmp1);                                  \
+        __INSTR_ARG_FREE(tmp1, type1);                                  \
+    } while(0)
+
+#define INSTR_GEN_2(callback, type1, arg1, type2, arg2)                 \
+    do {                                                                \
+        __INSTR_ARG_DECL(tmp1, type1, arg1);                            \
+        __INSTR_ARG_DECL(tmp2, type2, arg2);                            \
+        gen_helper_ ##callback (tmp1, tmp2);                            \
+        __INSTR_ARG_FREE(tmp1, type1);                                  \
+        __INSTR_ARG_FREE(tmp2, type2);                                  \
+    } while(0)
+
+#define INSTR_GEN_3(callback, type1, arg1, type2, arg2, type3, arg3)    \
+    do {                                                                \
+        __INSTR_ARG_DECL(tmp1, type1, arg1);                            \
+        __INSTR_ARG_DECL(tmp2, type2, arg2);                            \
+        __INSTR_ARG_DECL(tmp3, type3, arg3);                            \
+        gen_helper_ ##callback (tmp1, tmp2, tmp3);                      \
+        __INSTR_ARG_FREE(tmp1, type1);                                  \
+        __INSTR_ARG_FREE(tmp2, type2);                                  \
+        __INSTR_ARG_FREE(tmp3, type3);                                  \
+    } while(0)
+
+#define INSTR_GEN_4(callback, type1, arg1, type2, arg2, type3, arg3,    \
+                    type4, arg4)                                        \
+    do {                                                                \
+        __INSTR_ARG_DECL(tmp1, type1, arg1);                            \
+        __INSTR_ARG_DECL(tmp2, type2, arg2);                            \
+        __INSTR_ARG_DECL(tmp3, type3, arg3);                            \
+        __INSTR_ARG_DECL(tmp4, type4, arg4);                            \
+        gen_helper_ ##callback (tmp1, tmp2, tmp3, tmp4);                \
+        __INSTR_ARG_FREE(tmp1, type1);                                  \
+        __INSTR_ARG_FREE(tmp2, type2);                                  \
+        __INSTR_ARG_FREE(tmp3, type3);                                  \
+        __INSTR_ARG_FREE(tmp4, type4);                                  \
+    } while(0)
+
+#define INSTR_GEN_5(callback, type1, arg1, type2, arg2, type3, arg3,    \
+                    type4, arg4, type5, arg5)                           \
+    do {                                                                \
+        __INSTR_ARG_DECL(tmp1, type1, arg1);                            \
+        __INSTR_ARG_DECL(tmp2, type2, arg2);                            \
+        __INSTR_ARG_DECL(tmp3, type3, arg3);                            \
+        __INSTR_ARG_DECL(tmp4, type4, arg4);                            \
+        __INSTR_ARG_DECL(tmp5, type5, arg5);                            \
+        gen_helper_ ##callback (tmp1, tmp2, tmp3, tmp4, tmp5);          \
+        __INSTR_ARG_FREE(tmp1, type1);                                  \
+        __INSTR_ARG_FREE(tmp2, type2);                                  \
+        __INSTR_ARG_FREE(tmp3, type3);                                  \
+        __INSTR_ARG_FREE(tmp4, type4);                                  \
+        __INSTR_ARG_FREE(tmp5, type5);                                  \
+    } while(0)
+
+
+/* Internal API */
+
+/* Argument type conversion into TCGv temporaries */
+
+#define __INSTR_ARG_I32_DECL(tcg, value)      TCGv_i32 tcg = tcg_const_i32((value))
+#define __INSTR_ARG_I64_DECL(tcg, value)      TCGv_i64 tcg = tcg_const_i64((value))
+#if TARGET_LONG_BITS == 64
+#define __INSTR_ARG_TUL_DECL(tcg, value)      __INSTR_ARG_I64_DECL(tcg, value)
+#define __INSTR_ARG_TCGv_i64_DECL(tcg, value) TCGv_i64 tcg = value
+#else
+#define __INSTR_ARG_TUL_DECL(tcg, value)      __INSTR_ARG_I32_DECL(tcg, value)
+#define __INSTR_ARG_TCGv_i32_DECL(tcg, value) TCGv_i32 tcg = value
+#endif
+
+#define __INSTR_ARG_DECL(tcg, type, value)    __INSTR_ARG_ ##type ##_DECL(tcg, value)
+
+
+/* Free TCGv temporaries  */
+
+#define __INSTR_ARG_I32_FREE(tcg)      tcg_temp_free_i32(tcg)
+#define __INSTR_ARG_I64_FREE(tcg)      tcg_temp_free_i64(tcg)
+#if TARGET_LONG_BITS == 64
+#define __INSTR_ARG_TUL_FREE(tcg)      __INSTR_ARG_I64_FREE(tcg)
+#else
+#define __INSTR_ARG_TUL_FREE(tcg)      __INSTR_ARG_I32_FREE(tcg)
+#endif
+#define __INSTR_ARG_TCGv_i64_FREE(tcg)
+#define __INSTR_ARG_TCGv_i32_FREE(tcg)
+#define __INSTR_ARG_TCGv_FREE(tcg)
+
+#define __INSTR_ARG_FREE(tcg, type)    __INSTR_ARG_ ##type ##_FREE(tcg)
+
+#endif  /* INSTRUMENT__GENERATE_H */
diff --git a/instrument/types.h b/instrument/types.h
new file mode 100644
index 0000000..eb4036b
--- /dev/null
+++ b/instrument/types.h
@@ -0,0 +1,33 @@
+/*
+ * Static instrumentation data types.
+ *
+ *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INSTRUMENT__TYPES_H
+#define INSTRUMENT__TYPES_H
+
+/** Instrumentation argument types. */
+typedef enum {
+    INSTR_ARG_I32,                      /**< immediate of 32bits     */
+    INSTR_ARG_I64,                      /**< immediate of 64bits     */
+    INSTR_ARG_TUL,                      /**< immediate target_ulong  */
+    INSTR_ARG_TCGv_i32,                 /**< 32-bit TCGv variable    */
+    INSTR_ARG_TCGv_i64,                 /**< 64-bit TCGv variable    */
+    INSTR_ARG_TCGv,                     /**< target-bit TCGv variable*/
+} instr_arg_type_t;
+
+#endif  /* INSTRUMENT__TYPES_H */
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 09/18] instrument: Add initial instrumentation example
  2010-10-22 18:53 ` Lluís
                     ` (14 preceding siblings ...)
  2010-10-21 14:36   ` [Qemu-devel] [PATCH 11/18] instrument: Code-generation macros Lluís
@ 2010-10-21 17:42   ` Lluís
  2010-10-21 20:55   ` [Qemu-devel] [PATCH 12/18] instrument: [all] Include instrumentation helper declarations Lluís
  2010-10-22 14:00   ` [Qemu-devel] [PATCH 16/18] instrument: [all] Call VMEM point Lluís
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-21 17:42 UTC (permalink / raw)
  To: qemu-devel


---
 .gitignore                                         |    1 +
 instrument/examples/dynprint/README                |   16 +++++++
 instrument/examples/dynprint/guest/Makefile        |    7 +++
 instrument/examples/dynprint/guest/test.c          |   39 +++++++++++++++++
 instrument/examples/dynprint/host/Makefile         |   14 ++++++
 instrument/examples/dynprint/host/backdoor.c       |   44 ++++++++++++++++++++
 instrument/examples/dynprint/host/helpers.c        |   19 ++++++++
 .../dynprint/host/instrument-host-helpers.h        |   19 ++++++++
 .../examples/dynprint/host/instrument-host.h       |   30 +++++++++++++
 9 files changed, 189 insertions(+), 0 deletions(-)
 create mode 100644 instrument/examples/dynprint/README
 create mode 100644 instrument/examples/dynprint/guest/Makefile
 create mode 100644 instrument/examples/dynprint/guest/test.c
 create mode 100644 instrument/examples/dynprint/host/Makefile
 create mode 100644 instrument/examples/dynprint/host/backdoor.c
 create mode 100644 instrument/examples/dynprint/host/helpers.c
 create mode 100644 instrument/examples/dynprint/host/instrument-host-helpers.h
 create mode 100644 instrument/examples/dynprint/host/instrument-host.h

diff --git a/.gitignore b/.gitignore
index e4a351d..7fd5e88 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,3 +59,4 @@ pc-bios/optionrom/multiboot.raw
 .stgit-*
 cscope.*
 backdoor/examples/print/guest/test
+instrument/examples/dynprint/guest/test
diff --git a/instrument/examples/dynprint/README b/instrument/examples/dynprint/README
new file mode 100644
index 0000000..a1aa7f1
--- /dev/null
+++ b/instrument/examples/dynprint/README
@@ -0,0 +1,16 @@
+This example defines two instrumentation states:
+  * one printing the address of each fetched instruction
+  * one printing all the available information of each fetched instruction
+
+along with an instruction-based backdoor to dynamically (de)activate such
+states.
+
+To compile the host (quemu) run:
+   /path/to/qemu/configure --with-backdoor=/path/to/qemu/instrument/examples/dynprint/host/ --with-instrument=/path/to/qemu/instrument/examples/dynprint/host/
+   make
+
+To compile the guest program run:
+   make -C /path/to/qemu/instrument/examples/dynprint/guest/
+
+Now you can run it with:
+   /path/to/qemu/i386-linux-user/qemu-i386 /path/to/qemu/instrument/examples/dynprint/guest/test
diff --git a/instrument/examples/dynprint/guest/Makefile b/instrument/examples/dynprint/guest/Makefile
new file mode 100644
index 0000000..ea266f2
--- /dev/null
+++ b/instrument/examples/dynprint/guest/Makefile
@@ -0,0 +1,7 @@
+CFLAGS += -I../../../../
+PROGS = test
+
+all: $(PROGS)
+
+clean:
+	rm -f $(PROGS)
diff --git a/instrument/examples/dynprint/guest/test.c b/instrument/examples/dynprint/guest/test.c
new file mode 100644
index 0000000..254ebcf
--- /dev/null
+++ b/instrument/examples/dynprint/guest/test.c
@@ -0,0 +1,39 @@
+/*
+ * Sample guest program exercising instruction-based backdoor communication.
+ *
+ *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+
+#define TOTAL_ITERS 100
+
+
+int
+main ()
+{
+    int i;
+
+    printf("start\n");
+
+    for (i = 0; i < TOTAL_ITERS; i++) {
+        printf("iteration\n");
+    }
+
+    printf("stop\n");
+
+    return 0;
+}
diff --git a/instrument/examples/dynprint/host/Makefile b/instrument/examples/dynprint/host/Makefile
new file mode 100644
index 0000000..45213d1
--- /dev/null
+++ b/instrument/examples/dynprint/host/Makefile
@@ -0,0 +1,14 @@
+# Makefile for user-provided backdoor and instrumentation code
+
+include $(SRC_PATH)/config-host.mak
+include $(SRC_PATH)/rules.mak
+include $(SRC_PATH)/Makefile.objs
+
+libbackdoor.a: backdoor.o
+	$(call quiet-command,rm -f $@ && $(AR) rcs $@ $^,"  AR    $(TARGET_DIR)$@")
+
+libinstrument.a: helpers.o
+	$(call quiet-command,rm -f $@ && $(AR) rcs $@ $^,"  AR    $(TARGET_DIR)$@")
+
+clean:
+	rm -f libinstrument.a $(objs)
diff --git a/instrument/examples/dynprint/host/backdoor.c b/instrument/examples/dynprint/host/backdoor.c
new file mode 100644
index 0000000..7b4e883
--- /dev/null
+++ b/instrument/examples/dynprint/host/backdoor.c
@@ -0,0 +1,44 @@
+/*
+ * Example of dynamic control of instrumentation states.
+ *
+ *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+
+#include "cpu.h"
+#include "helper.h"
+
+
+void
+helper_backdoor_i8 (uint32_t imm)
+{
+    switch (imm) {
+    default:
+        printf("Unexpected use of instrumentation backdoor\n");
+        abort();
+    }
+}
+
+void
+helper_backdoor_i8_v (uint32_t imm, target_ulong value)
+{
+    switch (imm) {
+    default:
+        printf("Unexpected use of instrumentation backdoor\n");
+        abort();
+    }
+}
diff --git a/instrument/examples/dynprint/host/helpers.c b/instrument/examples/dynprint/host/helpers.c
new file mode 100644
index 0000000..656b716
--- /dev/null
+++ b/instrument/examples/dynprint/host/helpers.c
@@ -0,0 +1,19 @@
+/*
+ * Example of static instrumentation point callbacks.
+ *
+ *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
diff --git a/instrument/examples/dynprint/host/instrument-host-helpers.h b/instrument/examples/dynprint/host/instrument-host-helpers.h
new file mode 100644
index 0000000..e88738d
--- /dev/null
+++ b/instrument/examples/dynprint/host/instrument-host-helpers.h
@@ -0,0 +1,19 @@
+/*
+ * Example of static instrumentation point callback definitions.
+ *
+ *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
diff --git a/instrument/examples/dynprint/host/instrument-host.h b/instrument/examples/dynprint/host/instrument-host.h
new file mode 100644
index 0000000..9ede6af
--- /dev/null
+++ b/instrument/examples/dynprint/host/instrument-host.h
@@ -0,0 +1,30 @@
+/*
+ * Example of static instrumentation points.
+ *
+ *  Copyright (c) 2010 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INSTRUMENT_HOST_H
+#define INSTRUMENT_HOST_H
+
+/* See "instrument/host-stub.h" for a description of macro arguments. */
+
+/* Instrumentation types */
+typedef enum {
+    INSTR_TYPE_COUNT    /* Total number of instrumentation types (mandatory) */
+} instr_type_t;
+
+#endif /* INSTRUMENT_HOST_H */
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 12/18] instrument: [all] Include instrumentation helper declarations
  2010-10-22 18:53 ` Lluís
                     ` (15 preceding siblings ...)
  2010-10-21 17:42   ` [Qemu-devel] [PATCH 09/18] instrument: Add initial instrumentation example Lluís
@ 2010-10-21 20:55   ` Lluís
  2010-10-22 14:00   ` [Qemu-devel] [PATCH 16/18] instrument: [all] Call VMEM point Lluís
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-21 20:55 UTC (permalink / raw)
  To: qemu-devel


---
 target-alpha/helper.h      |    4 ++++
 target-arm/helper.h        |    4 ++++
 target-cris/helper.h       |    4 ++++
 target-i386/helper.h       |    4 ++++
 target-m68k/helper.h       |    4 ++++
 target-microblaze/helper.h |    4 ++++
 target-mips/helper.h       |    4 ++++
 target-ppc/helper.h        |    4 ++++
 target-sh4/helper.h        |    4 ++++
 target-sparc/helper.h      |    4 ++++
 10 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index d2ec252..4456205 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -127,4 +127,8 @@ DEF_HELPER_2(stq_c_raw, i64, i64, i64)
 #include "backdoor/helper.h"
 #endif
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument-host-helpers.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-arm/helper.h b/target-arm/helper.h
index b46f04c..b1d24f7 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -451,4 +451,8 @@ DEF_HELPER_2(set_teecr, void, env, i32)
 #include "backdoor/helper.h"
 #endif
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument-host-helpers.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-cris/helper.h b/target-cris/helper.h
index 72fabce..8f7e976 100644
--- a/target-cris/helper.h
+++ b/target-cris/helper.h
@@ -27,4 +27,8 @@ DEF_HELPER_0(top_evaluate_flags, void)
 #include "backdoor/helper.h"
 #endif
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument-host-helpers.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-i386/helper.h b/target-i386/helper.h
index 979d94e..1b8e6e8 100644
--- a/target-i386/helper.h
+++ b/target-i386/helper.h
@@ -221,4 +221,8 @@ DEF_HELPER_2(rcrq, tl, tl, tl)
 #include "backdoor/helper.h"
 #endif
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument-host-helpers.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index 06e8a47..523fde2 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -55,4 +55,8 @@ DEF_HELPER_1(raise_exception, void, i32)
 #include "backdoor/helper.h"
 #endif
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument-host-helpers.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h
index 473ed78..6f8e274 100644
--- a/target-microblaze/helper.h
+++ b/target-microblaze/helper.h
@@ -38,4 +38,8 @@ DEF_HELPER_4(memalign, void, i32, i32, i32, i32)
 #include "backdoor/helper.h"
 #endif
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument-host-helpers.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-mips/helper.h b/target-mips/helper.h
index cbee380..0953815 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -291,4 +291,8 @@ DEF_HELPER_0(wait, void)
 #include "backdoor/helper.h"
 #endif
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument-host-helpers.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index eeb7487..960ba5e 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -405,4 +405,8 @@ DEF_HELPER_2(store_601_batu, void, i32, tl)
 #include "backdoor/helper.h"
 #endif
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument-host-helpers.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-sh4/helper.h b/target-sh4/helper.h
index dbea9e1..361a15f 100644
--- a/target-sh4/helper.h
+++ b/target-sh4/helper.h
@@ -54,4 +54,8 @@ DEF_HELPER_1(ftrc_DT, i32, i64)
 #include "backdoor/helper.h"
 #endif
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument-host-helpers.h"
+#endif
+
 #include "def-helper.h"
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index b88f0ac..a1f177c 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -164,4 +164,8 @@ DEF_HELPER_0(compute_C_icc, i32);
 #include "backdoor/helper.h"
 #endif
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument-host-helpers.h"
+#endif
+
 #include "def-helper.h"
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 16/18] instrument: [all] Call VMEM point
  2010-10-22 18:53 ` Lluís
                     ` (16 preceding siblings ...)
  2010-10-21 20:55   ` [Qemu-devel] [PATCH 12/18] instrument: [all] Include instrumentation helper declarations Lluís
@ 2010-10-22 14:00   ` Lluís
  17 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-22 14:00 UTC (permalink / raw)
  To: qemu-devel


Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 cpu-all.h                     |   59 +++++++++++++++++++++-------------------
 exec-all.h                    |    2 +
 linux-user/main.c             |   12 ++++++++
 softmmu_header.h              |   15 ++++++++++
 target-alpha/translate.c      |    4 +++
 target-arm/translate.c        |    4 +++
 target-cris/translate.c       |    4 +++
 target-i386/translate.c       |    4 +++
 target-m68k/translate.c       |    4 +++
 target-microblaze/translate.c |    4 +++
 target-mips/translate.c       |    4 +++
 target-ppc/translate.c        |    4 +++
 target-s390x/translate.c      |    4 +++
 target-sh4/translate.c        |    4 +++
 target-sparc/translate.c      |    4 +++
 15 files changed, 104 insertions(+), 28 deletions(-)

diff --git a/cpu-all.h b/cpu-all.h
index 88970a2..2e666e4 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -697,21 +697,24 @@ extern unsigned long reserved_va;
 
 #if defined(CONFIG_USER_ONLY)
 
+/* XXX: INSTRUMENT can capture these when enabled. */
+/* TODO: INSTRUMENT might find a NULL 'cpu_single_env', should check... */
+
 /* if user mode, no other memory access functions */
-#define ldub(p) ldub_raw(p)
-#define ldsb(p) ldsb_raw(p)
-#define lduw(p) lduw_raw(p)
-#define ldsw(p) ldsw_raw(p)
-#define ldl(p) ldl_raw(p)
-#define ldq(p) ldq_raw(p)
-#define ldfl(p) ldfl_raw(p)
-#define ldfq(p) ldfq_raw(p)
-#define stb(p, v) stb_raw(p, v)
-#define stw(p, v) stw_raw(p, v)
-#define stl(p, v) stl_raw(p, v)
-#define stq(p, v) stq_raw(p, v)
-#define stfl(p, v) stfl_raw(p, v)
-#define stfq(p, v) stfq_raw(p, v)
+#define ldub(p)    ({ INSTR_DO_VMEM(cpu_single_env, p, 1, INSTR_MEM_RD); ldub_raw(p);    })
+#define ldsb(p)    ({ INSTR_DO_VMEM(cpu_single_env, p, 1, INSTR_MEM_RD); ldsb_raw(p);    })
+#define lduw(p)    ({ INSTR_DO_VMEM(cpu_single_env, p, 2, INSTR_MEM_RD); lduw_raw(p);    })
+#define ldsw(p)    ({ INSTR_DO_VMEM(cpu_single_env, p, 2, INSTR_MEM_RD); ldsw_raw(p);    })
+#define ldl(p)     ({ INSTR_DO_VMEM(cpu_single_env, p, 4, INSTR_MEM_RD); ldl_raw(p);     })
+#define ldq(p)     ({ INSTR_DO_VMEM(cpu_single_env, p, 8, INSTR_MEM_RD); ldq_raw(p);     })
+#define ldfl(p)    ({ INSTR_DO_VMEM(cpu_single_env, p, 4, INSTR_MEM_RD); ldfl_raw(p);    })
+#define ldfq(p)    ({ INSTR_DO_VMEM(cpu_single_env, p, 8, INSTR_MEM_RD); ldfq_raw(p);    })
+#define stb(p, v)  ({ INSTR_DO_VMEM(cpu_single_env, p, 1, INSTR_MEM_WR); stb_raw(p, v);  })
+#define stw(p, v)  ({ INSTR_DO_VMEM(cpu_single_env, p, 2, INSTR_MEM_WR); stw_raw(p, v);  })
+#define stl(p, v)  ({ INSTR_DO_VMEM(cpu_single_env, p, 4, INSTR_MEM_WR); stl_raw(p, v);  })
+#define stq(p, v)  ({ INSTR_DO_VMEM(cpu_single_env, p, 8, INSTR_MEM_WR); stq_raw(p, v);  })
+#define stfl(p, v) ({ INSTR_DO_VMEM(cpu_single_env, p, 4, INSTR_MEM_WR); stfl_raw(p, v); })
+#define stfq(p, v) ({ INSTR_DO_VMEM(cpu_single_env, p, 8, INSTR_MEM_WR); stfq_raw(p, v); })
 
 #define ldub_code(p) ldub_raw(p)
 #define ldsb_code(p) ldsb_raw(p)
@@ -720,20 +723,20 @@ extern unsigned long reserved_va;
 #define ldl_code(p) ldl_raw(p)
 #define ldq_code(p) ldq_raw(p)
 
-#define ldub_kernel(p) ldub_raw(p)
-#define ldsb_kernel(p) ldsb_raw(p)
-#define lduw_kernel(p) lduw_raw(p)
-#define ldsw_kernel(p) ldsw_raw(p)
-#define ldl_kernel(p) ldl_raw(p)
-#define ldq_kernel(p) ldq_raw(p)
-#define ldfl_kernel(p) ldfl_raw(p)
-#define ldfq_kernel(p) ldfq_raw(p)
-#define stb_kernel(p, v) stb_raw(p, v)
-#define stw_kernel(p, v) stw_raw(p, v)
-#define stl_kernel(p, v) stl_raw(p, v)
-#define stq_kernel(p, v) stq_raw(p, v)
-#define stfl_kernel(p, v) stfl_raw(p, v)
-#define stfq_kernel(p, vt) stfq_raw(p, v)
+#define ldub_kernel(p)     ({ INSTR_DO_VMEM(cpu_single_env, p, 1, INSTR_MEM_RD); ldub_raw(p);    })
+#define ldsb_kernel(p)     ({ INSTR_DO_VMEM(cpu_single_env, p, 1, INSTR_MEM_RD); ldsb_raw(p);    })
+#define lduw_kernel(p)     ({ INSTR_DO_VMEM(cpu_single_env, p, 2, INSTR_MEM_RD); lduw_raw(p);    })
+#define ldsw_kernel(p)     ({ INSTR_DO_VMEM(cpu_single_env, p, 2, INSTR_MEM_RD); ldsw_raw(p);    })
+#define ldl_kernel(p)      ({ INSTR_DO_VMEM(cpu_single_env, p, 4, INSTR_MEM_RD); ldl_raw(p);     })
+#define ldq_kernel(p)      ({ INSTR_DO_VMEM(cpu_single_env, p, 8, INSTR_MEM_RD); ldq_raw(p);     })
+#define ldfl_kernel(p)     ({ INSTR_DO_VMEM(cpu_single_env, p, 4, INSTR_MEM_RD); ldfl_raw(p);    })
+#define ldfq_kernel(p)     ({ INSTR_DO_VMEM(cpu_single_env, p, 8, INSTR_MEM_RD); ldfq_raw(p);    })
+#define stb_kernel(p, v)   ({ INSTR_DO_VMEM(cpu_single_env, p, 1, INSTR_MEM_WR); stb_raw(p, v);  })
+#define stw_kernel(p, v)   ({ INSTR_DO_VMEM(cpu_single_env, p, 2, INSTR_MEM_WR); stw_raw(p, v);  })
+#define stl_kernel(p, v)   ({ INSTR_DO_VMEM(cpu_single_env, p, 4, INSTR_MEM_WR); stl_raw(p, v);  })
+#define stq_kernel(p, v)   ({ INSTR_DO_VMEM(cpu_single_env, p, 8, INSTR_MEM_WR); stq_raw(p, v);  })
+#define stfl_kernel(p, v)  ({ INSTR_DO_VMEM(cpu_single_env, p, 4, INSTR_MEM_WR); stfl_raw(p, v); })
+#define stfq_kernel(p, vt) ({ INSTR_DO_VMEM(cpu_single_env, p, 8, INSTR_MEM_WR); stfq_raw(p, v); })
 
 #endif /* defined(CONFIG_USER_ONLY) */
 
diff --git a/exec-all.h b/exec-all.h
index 35d2a57..4c2c1d2 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -288,6 +288,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx,
 #include "softmmu_defs.h"
 
 #define ACCESS_TYPE (NB_MMU_MODES + 1)
+#define INSTR_CODE_ACCESSOR 1          /* do not instrument '*_code' accesses */
 #define MEMSUFFIX _code
 #define env cpu_single_env
 
@@ -304,6 +305,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx,
 #include "softmmu_header.h"
 
 #undef ACCESS_TYPE
+#undef INSTR_CODE_ACCESSOR
 #undef MEMSUFFIX
 #undef env
 
diff --git a/linux-user/main.c b/linux-user/main.c
index dbba8be..b82d53c 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2948,6 +2948,12 @@ int main(int argc, char **argv, char **envp)
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
+
+#if defined(CONFIG_INSTRUMENT)
+    /* hack around 'env' vs 'cpu_single_env' */
+    cpu_single_env = env;
+#endif
+
 #if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
     cpu_reset(env);
 #endif
@@ -3369,6 +3375,12 @@ int main(int argc, char **argv, char **envp)
         gdbserver_start (gdbstub_port);
         gdb_handlesig(env, 0);
     }
+
+#if defined(CONFIG_INSTRUMENT)
+    /* hack around 'env' vs 'cpu_single_env' */
+    cpu_single_env = NULL;
+#endif
+
     cpu_loop(env);
     /* never exits */
     return 0;
diff --git a/softmmu_header.h b/softmmu_header.h
index 2f95c33..b6052f3 100644
--- a/softmmu_header.h
+++ b/softmmu_header.h
@@ -79,6 +79,11 @@ static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
     unsigned long physaddr;
     int mmu_idx;
 
+#if !defined(INSTR_CODE_ACCESSOR)       /* XXX: kind of hackish, but couldn't
+                                         * find another way */
+    INSTR_DO_VMEM(env, ptr, DATA_SIZE, INSTR_MEM_RD);
+#endif
+
     addr = ptr;
     page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
     mmu_idx = CPU_MMU_INDEX;
@@ -100,6 +105,11 @@ static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
     unsigned long physaddr;
     int mmu_idx;
 
+#if !defined(INSTR_CODE_ACCESSOR)       /* XXX: kind of hackish, but couldn't
+                                         * find another way */
+    INSTR_DO_VMEM(env, ptr, DATA_SIZE, INSTR_MEM_RD);
+#endif
+
     addr = ptr;
     page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
     mmu_idx = CPU_MMU_INDEX;
@@ -125,6 +135,11 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE
     unsigned long physaddr;
     int mmu_idx;
 
+#if !defined(INSTR_CODE_ACCESSOR)       /* XXX: kind of hackish, but couldn't
+                                         * find another way */
+    INSTR_DO_VMEM(env, ptr, DATA_SIZE, INSTR_MEM_WR);
+#endif
+
     addr = ptr;
     page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
     mmu_idx = CPU_MMU_INDEX;
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 3a1c625..1e7e66b 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -32,6 +32,10 @@
 #define GEN_HELPER 1
 #include "helper.h"
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument/gen-vmem-wrappers.h"
+#endif
+
 #undef ALPHA_DEBUG_DISAS
 #define CONFIG_SOFTFLOAT_INLINE
 
diff --git a/target-arm/translate.c b/target-arm/translate.c
index a9fbe5b..8c47e34 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -34,6 +34,10 @@
 #define GEN_HELPER 1
 #include "helper.h"
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument/gen-vmem-wrappers.h"
+#endif
+
 #define ENABLE_ARCH_5J    0
 #define ENABLE_ARCH_6     arm_feature(env, ARM_FEATURE_V6)
 #define ENABLE_ARCH_6K   arm_feature(env, ARM_FEATURE_V6K)
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 8361369..8f43ae5 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -41,6 +41,10 @@
 #define GEN_HELPER 1
 #include "helper.h"
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument/gen-vmem-wrappers.h"
+#endif
+
 #define DISAS_CRIS 0
 #if DISAS_CRIS
 #  define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 02a93a4..aa3b307 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -33,6 +33,10 @@
 #include "helper.h"
 
 #if defined(CONFIG_INSTRUMENT)
+#include "instrument/gen-vmem-wrappers.h"
+#endif
+
+#if defined(CONFIG_INSTRUMENT)
 static inline void
 mem_exchange (void * tmp, void * start1, size_t size1,
               void * start2, size_t size2)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 0c6f0e2..e212392 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -34,6 +34,10 @@
 #define GEN_HELPER 1
 #include "helper.h"
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument/gen-vmem-wrappers.h"
+#endif
+
 //#define DEBUG_DISPATCH 1
 
 /* Fake floating point.  */
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 9dcc78a..0adf173 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -35,6 +35,10 @@
 #define GEN_HELPER 1
 #include "helper.h"
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument/gen-vmem-wrappers.h"
+#endif
+
 #define SIM_COMPAT 0
 #define DISAS_GNU 1
 #define DISAS_MB 1
diff --git a/target-mips/translate.c b/target-mips/translate.c
index d62c615..a92ac7f 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -36,6 +36,10 @@
 #define GEN_HELPER 1
 #include "helper.h"
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument/gen-vmem-wrappers.h"
+#endif
+
 //#define MIPS_DEBUG_DISAS
 //#define MIPS_DEBUG_SIGN_EXTENSIONS
 
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index fd06861..555658c 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -33,6 +33,10 @@
 #define GEN_HELPER 1
 #include "helper.h"
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument/gen-vmem-wrappers.h"
+#endif
+
 #define CPU_SINGLE_STEP 0x1
 #define CPU_BRANCH_STEP 0x2
 #define GDBSTUB_SINGLE_STEP 0x4
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 44dfa65..168017f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -23,6 +23,10 @@
 #include "tcg-op.h"
 #include "qemu-log.h"
 
+#ifdef CONFIG_INSTRUMENT
+#include "instrument/gen-vmem-wrappers.h"
+#endif
+
 void cpu_dump_state(CPUState *env, FILE *f,
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags)
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index deee939..5e232e5 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -36,6 +36,10 @@
 #define GEN_HELPER 1
 #include "helper.h"
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument/gen-vmem-wrappers.h"
+#endif
+
 typedef struct DisasContext {
     struct TranslationBlock *tb;
     target_ulong pc;
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 23f9519..2c2c505 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -33,6 +33,10 @@
 #define GEN_HELPER 1
 #include "helper.h"
 
+#if defined(CONFIG_INSTRUMENT)
+#include "instrument/gen-vmem-wrappers.h"
+#endif
+
 #define DEBUG_DISAS
 
 #define DYNAMIC_PC  1 /* dynamic pc value */
-- 
1.7.1

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation
@ 2010-10-22 18:32 Lluís
  2010-10-22 18:53 ` Lluís
  2010-10-23 12:40 ` [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation Blue Swirl
  0 siblings, 2 replies; 33+ messages in thread
From: Lluís @ 2010-10-22 18:32 UTC (permalink / raw)
  To: qemu-devel

Here's a set of patches with the current state of static
instrumentation.

Hope that this organization will help understanding the point of
it. Patch 9 describes the taken approach for instrumenting during code
generation, which is the main point of this.

Code can also be reached at:
     https://projects.gso.ac.upc.edu/projects/qemu-instrument
     https://code.gso.ac.upc.edu/git/qemu-instrument

Lluís Vilanova (17):
  backdoor: Declare host-side backdoor helpers
  backdoor: [all] Include backdoor helper declarations
  backdoor: Declare guest-side interface macros
  backdoor: [i386] Decode backdoor instructions
  backdoor: [i386] Declare guest-side interface macros
  backdoor: Add a simple example
  instrument: Handle config-time activation
  instrument: Add initial instrumentation example
  instrument: Dynamic per-CPU state of static instrumentation points
  instrument: Code-generation macros
  instrument: [all] Include instrumentation helper declarations
  instrument: Add FETCH point
  instrument: [i386] Call FETCH point
  instrument: Add VMEM point
  instrument: [all] Call VMEM point
  instrument: Add PLVL point
  instrument: [i386] Call PLVL point

 .gitignore                                         |    2 +
 Makefile.target                                    |   35 +++++-
 backdoor/examples/print/README                     |   13 ++
 backdoor/examples/print/guest/Makefile             |    7 +
 backdoor/examples/print/guest/test.c               |   33 +++++
 backdoor/examples/print/host/Makefile              |   13 ++
 backdoor/examples/print/host/printcb.c             |   36 +++++
 backdoor/guest.h                                   |   60 ++++++++
 backdoor/helper.h                                  |   21 +++
 configure                                          |   19 +++
 cpu-all.h                                          |   74 ++++++----
 cpu-defs.h                                         |   24 +++
 cpu-exec.c                                         |    8 +-
 cpus.c                                             |    8 +
 exec-all.h                                         |    7 +-
 exec.c                                             |   50 +++++---
 instrument/control.c                               |   74 ++++++++++
 instrument/control.h                               |   44 ++++++
 instrument/examples/dynprint/README                |   16 ++
 instrument/examples/dynprint/guest/Makefile        |    7 +
 instrument/examples/dynprint/guest/test.c          |   62 ++++++++
 instrument/examples/dynprint/host/Makefile         |   14 ++
 instrument/examples/dynprint/host/backdoor.c       |   61 ++++++++
 instrument/examples/dynprint/host/helpers.c        |   86 ++++++++++++
 .../dynprint/host/instrument-host-helpers.h        |   22 +++
 .../examples/dynprint/host/instrument-host.h       |   81 +++++++++++
 instrument/gen-vmem-wrappers.h                     |   88 ++++++++++++
 instrument/generate.h                              |  128 +++++++++++++++++
 instrument/host-stub.h                             |   81 +++++++++++
 instrument/state.h                                 |   61 ++++++++
 instrument/types.h                                 |   44 ++++++
 linux-user/main.c                                  |   12 ++
 qemu-common.h                                      |    4 +
 softmmu_header.h                                   |   15 ++
 target-alpha/helper.h                              |    8 +
 target-alpha/translate.c                           |    4 +
 target-arm/helper.h                                |    8 +
 target-arm/translate.c                             |    4 +
 target-cris/helper.h                               |    8 +
 target-cris/translate.c                            |    4 +
 target-i386/cpu.h                                  |   21 ++--
 target-i386/helper.h                               |    8 +
 target-i386/translate.c                            |  147 ++++++++++++++++++++
 target-m68k/helper.h                               |    8 +
 target-m68k/translate.c                            |    4 +
 target-microblaze/helper.h                         |    8 +
 target-microblaze/translate.c                      |   10 ++
 target-mips/helper.h                               |    8 +
 target-mips/translate.c                            |    4 +
 target-ppc/helper.h                                |    8 +
 target-ppc/translate.c                             |    4 +
 target-s390x/translate.c                           |    4 +
 target-sh4/helper.h                                |    8 +
 target-sh4/translate.c                             |    4 +
 target-sparc/helper.h                              |    8 +
 target-sparc/translate.c                           |    4 +
 56 files changed, 1543 insertions(+), 61 deletions(-)
 create mode 100644 backdoor/examples/print/README
 create mode 100644 backdoor/examples/print/guest/Makefile
 create mode 100644 backdoor/examples/print/guest/test.c
 create mode 100644 backdoor/examples/print/host/Makefile
 create mode 100644 backdoor/examples/print/host/printcb.c
 create mode 100644 backdoor/guest.h
 create mode 100644 backdoor/helper.h
 create mode 100644 instrument/control.c
 create mode 100644 instrument/control.h
 create mode 100644 instrument/examples/dynprint/README
 create mode 100644 instrument/examples/dynprint/guest/Makefile
 create mode 100644 instrument/examples/dynprint/guest/test.c
 create mode 100644 instrument/examples/dynprint/host/Makefile
 create mode 100644 instrument/examples/dynprint/host/backdoor.c
 create mode 100644 instrument/examples/dynprint/host/helpers.c
 create mode 100644 instrument/examples/dynprint/host/instrument-host-helpers.h
 create mode 100644 instrument/examples/dynprint/host/instrument-host.h
 create mode 100644 instrument/gen-vmem-wrappers.h
 create mode 100644 instrument/generate.h
 create mode 100644 instrument/host-stub.h
 create mode 100644 instrument/state.h
 create mode 100644 instrument/types.h

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation
  2010-10-22 18:32 [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation Lluís
@ 2010-10-22 18:53 ` Lluís
  2010-10-18 17:24   ` [Qemu-devel] [PATCH 01/18] backdoor: Handle config-time activation Lluís
                     ` (17 more replies)
  2010-10-23 12:40 ` [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation Blue Swirl
  1 sibling, 18 replies; 33+ messages in thread
From: Lluís @ 2010-10-22 18:53 UTC (permalink / raw)
  To: qemu-devel

Sorry, the last cover had a bad starting commit. Patches continue from
here.

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation
  2010-10-22 18:32 [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation Lluís
  2010-10-22 18:53 ` Lluís
@ 2010-10-23 12:40 ` Blue Swirl
  2010-10-25 10:54   ` backdoor [Was: Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation] Lluís
  2010-10-25 11:13   ` instrument [Was: Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation] Lluís
  1 sibling, 2 replies; 33+ messages in thread
From: Blue Swirl @ 2010-10-23 12:40 UTC (permalink / raw)
  To: Lluís; +Cc: qemu-devel

On Fri, Oct 22, 2010 at 6:32 PM, Lluís <xscript@gmx.net> wrote:
> Here's a set of patches with the current state of static
> instrumentation.
>
> Hope that this organization will help understanding the point of
> it. Patch 9 describes the taken approach for instrumenting during code
> generation, which is the main point of this.

The patches are now more readable, thanks for the effort.

> Code can also be reached at:
>     https://projects.gso.ac.upc.edu/projects/qemu-instrument
>     https://code.gso.ac.upc.edu/git/qemu-instrument
>
> Lluís Vilanova (17):
>  backdoor: Declare host-side backdoor helpers
>  backdoor: [all] Include backdoor helper declarations
>  backdoor: Declare guest-side interface macros
>  backdoor: [i386] Decode backdoor instructions
>  backdoor: [i386] Declare guest-side interface macros
>  backdoor: Add a simple example

The backdoor instruction is problematic. For example, handling that in
KVM may be difficult and there are guest visible side effects. The
same effect can be achieved with a MMIO/PIO device or instrumented
breakpoints/watchpoints.

For the MMIO/PIO device solution, there are several PV devices
available, for example virtio devices and fw_cfg. Instead of a
backdoor instruction, the guest should simply issue MMIO or PIO using
regular instructions. For Linux user, a new syscall can be added.
Anyway, the guest still needs to be modified.

Instrumenting GDB watchpoint and/or breakpoint support would be more
attractive because this would be completely invisible to the guest and
it may be controlled from GDB.

>  instrument: Handle config-time activation
>  instrument: Add initial instrumentation example
>  instrument: Dynamic per-CPU state of static instrumentation points
>  instrument: Code-generation macros
>  instrument: [all] Include instrumentation helper declarations
>  instrument: Add FETCH point
>  instrument: [i386] Call FETCH point
>  instrument: Add VMEM point
>  instrument: [all] Call VMEM point
>  instrument: Add PLVL point
>  instrument: [i386] Call PLVL point

At least in these examples, the instrumentation code just prints out a
few interesting fields, so they are almost identical to tracepoints.

The general approach seems to be that when an interesting event
happens, call the instrumentation code directly. A lot of internal
state needs to be made available to the instrumentation code, which is
a problem if that is considered as an API. Perhaps this could be
changed so that when the event happens, the only effect is that the VM
is stopped with some kind of notification. Then a controlling
application (external to QEMU) can inspect the state and
enable/disable tracepoints as it wishes, but using only the tools that
are available for tracepoints, QMP or GDB. Performance would be much
lower, though.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* backdoor [Was: Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation]
  2010-10-23 12:40 ` [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation Blue Swirl
@ 2010-10-25 10:54   ` Lluís
  2010-10-25 12:29     ` [Qemu-devel] Re: backdoor [Was: " Paolo Bonzini
  2010-10-25 17:27     ` backdoor [Was: Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation] Blue Swirl
  2010-10-25 11:13   ` instrument [Was: Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation] Lluís
  1 sibling, 2 replies; 33+ messages in thread
From: Lluís @ 2010-10-25 10:54 UTC (permalink / raw)
  To: Blue Swirl; +Cc: qemu-devel

Blue Swirl writes:

> On Fri, Oct 22, 2010 at 6:32 PM, Lluís <xscript@gmx.net> wrote:
>> Lluís Vilanova (17):
>>  backdoor: Declare host-side backdoor helpers
>>  backdoor: [all] Include backdoor helper declarations
>>  backdoor: Declare guest-side interface macros
>>  backdoor: [i386] Decode backdoor instructions
>>  backdoor: [i386] Declare guest-side interface macros
>>  backdoor: Add a simple example

> The backdoor instruction is problematic. For example, handling that in
> KVM may be difficult

I thought about implementing guest-directed KVM control, such that the
guest will be able to enable/disable KVM at will, but I'm not sure how
this can be accomplished in a generic way (i.e., x86 has vmcall/vmmcall
as you told me a lot of time ago).


> and there are guest visible side effects.

I don't understand what you mean with guest-visible effects.


> The same effect can be achieved with a MMIO/PIO device or instrumented
> breakpoints/watchpoints.

> For the MMIO/PIO device solution, there are several PV devices
> available, for example virtio devices and fw_cfg. Instead of a
> backdoor instruction, the guest should simply issue MMIO or PIO using
> regular instructions. For Linux user, a new syscall can be added.
> Anyway, the guest still needs to be modified.

> Instrumenting GDB watchpoint and/or breakpoint support would be more
> attractive because this would be completely invisible to the guest and
> it may be controlled from GDB.

Ok, so far I see different approaches available:

* MMIO/PIO device
  Needs no undocumented extensions to the ISA, but requires modifying
  the guest OS (adding a device driver).

* New syscall
  Needs no undocumented extensions to the ISA, but will only work with
  *-user emulation.

* watchpoint/breapoint
  Needs no undocumented extensions to the ISA, but will only work with
  softmmu emulation, and only as long as the backdoor channel requires
  no arguments.

* ISA extensions
  Needs a per-target decoding of the instruction and won't work when
  running under KVM.

What I used until now (with my old bochs-based implementation), is the
presented ISA extensions, which are used through library interposition
(e.g., in softmmu emulation, launch the application with a library in
LD_PRELOAD that enables/disables simulation using a
constructor/destructor attribute, plus some extra backdoor communication
to simulate specific processes by interposing on the fork/clone
syscall).

My requirements here are:

* Backdoor channels need to provide arguments.
* It's better to provide the same mechanism for both *-user and softmmu
  (otherwise the application to simulate or the interposed librariy
  should be compiled differently on every case).
* Some applications are not fully simulated, but just some pre-defined
  loops are, such that I would run the application (on KVM mode if
  possible) until the interesting loop starts executing, switch to
  simulation mode, simulate an arbitrary number of loops, switch back to
  non-simulated mode, run until another specific loop or iteration is
  reached, repeat the process again.
  This obviously requires some application modification to insert the
  communication points, unless these can be identified using symbol
  interposition (e.g., calls to the OpenMP runtime to simulate certain
  parallel loops).

The instrumented watchpoint/breakpoint sounds as an interesting
approach, but I don't see how I can:

* Differentiate among instrumented and non-instrumented
  watchpoints/breakpoints
* Pass arguments to the instrumentation backend


Thanks,
  Lluis

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply	[flat|nested] 33+ messages in thread

* instrument [Was: Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation]
  2010-10-23 12:40 ` [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation Blue Swirl
  2010-10-25 10:54   ` backdoor [Was: Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation] Lluís
@ 2010-10-25 11:13   ` Lluís
  2010-10-25 18:31     ` Blue Swirl
  1 sibling, 1 reply; 33+ messages in thread
From: Lluís @ 2010-10-25 11:13 UTC (permalink / raw)
  To: Blue Swirl; +Cc: qemu-devel

Blue Swirl writes:

> On Fri, Oct 22, 2010 at 6:32 PM, Lluís <xscript@gmx.net> wrote:
>>  instrument: Handle config-time activation
>>  instrument: Add initial instrumentation example
>>  instrument: Dynamic per-CPU state of static instrumentation points
>>  instrument: Code-generation macros
>>  instrument: [all] Include instrumentation helper declarations
>>  instrument: Add FETCH point
>>  instrument: [i386] Call FETCH point
>>  instrument: Add VMEM point
>>  instrument: [all] Call VMEM point
>>  instrument: Add PLVL point
>>  instrument: [i386] Call PLVL point

> At least in these examples, the instrumentation code just prints out a
> few interesting fields, so they are almost identical to tracepoints.

Right, but that's because that is the simplest usage example I could
think of.


> The general approach seems to be that when an interesting event
> happens, call the instrumentation code directly.

That's the idea, so that one can go from calling tracing routines to
providing hand-crafted code generators.


> A lot of internal state needs to be made available to the
> instrumentation code, which is a problem if that is considered as an
> API. 

I don't get what you mean by that. In principle, only the macro
arguments and the cpu instrumentation state are used.

I tried using static inlined functions on a first draft, but
"instrument-host.h" is included on too many places and not every
argument type was available at the include point. Maybe I could try to
work this out again, such that routines are more self, contained, but
there's still the problem of CPUState poisoning.


> Perhaps this could be changed so that when the event happens, the only
> effect is that the VM is stopped with some kind of notification. Then
> a controlling application (external to QEMU) can inspect the state and
> enable/disable tracepoints as it wishes, but using only the tools that
> are available for tracepoints, QMP or GDB. Performance would be much
> lower, though.

Hmmm... as I see it, if tracing provided a two-level backend, I could
work this out.

I mean, for me, trace-points are just user-definable macros, I could
provide instrumentation points through that, such that trace.h can
include (if directed to do it) an extra user-provided header. Then,
trace.h could look like:

  #include "qemu-common.h"

  #include "trace-override.h" // user defines trace_whatever
   
  #ifndef trace_whatever
  // maybe provide a separate trace-events-override file and do not
  // generate this with tracetool from trace-events
  static inline void trace_whatever(args...)
  {
    call trace backend
  }
  #endif

Of course, instrumentation points found during code generation still
need a different treatment even if they are to be used as plain
trace-points, as they're not called at run-time unless you generate a
call to a helper, so maybe a new trace-point type should be handled on
'tracetool' (like trace_generate_<whatever> or something like that),
that generates a call to the tracing backend instead of simply calling
it.

This way, trace generation from these points can be neatly integrated
with all the other tracing points.

But still, the instrumentation state is a critical performance issue for
'trace_generate_' points.

What do you think?

Lluis

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [Qemu-devel] Re: backdoor [Was: Re: [PATCH 00/17] [RFC] static instrumentation]
  2010-10-25 10:54   ` backdoor [Was: Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation] Lluís
@ 2010-10-25 12:29     ` Paolo Bonzini
  2010-10-25 13:37       ` [Qemu-devel] Re: backdoor Lluís
  2010-10-25 17:27     ` backdoor [Was: Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation] Blue Swirl
  1 sibling, 1 reply; 33+ messages in thread
From: Paolo Bonzini @ 2010-10-25 12:29 UTC (permalink / raw)
  To: Blue Swirl, qemu-devel, xscript

On 10/25/2010 12:54 PM, Lluís wrote:
> * Backdoor channels need to provide arguments.
> * It's better to provide the same mechanism for both *-user and softmmu
>    (otherwise the application to simulate or the interposed librariy
>    should be compiled differently on every case).

You can add the syscall and, if it returns with ENOSYS, fall back to 
MMIO/PIO (you don't really need a special driver, only some chmod since 
BARs are accessible from /sys) or watchpoint/breakpoint.

> * Some applications are not fully simulated, but just some pre-defined
>    loops are, such that I would run the application (on KVM mode if
>    possible) until the interesting loop starts executing, switch to
>    simulation mode, simulate an arbitrary number of loops, switch back to
>    non-simulated mode, run until another specific loop or iteration is
>    reached, repeat the process again.
>    This obviously requires some application modification to insert the
>    communication points, unless these can be identified using symbol
>    interposition (e.g., calls to the OpenMP runtime to simulate certain
>    parallel loops).

Switching between KVM and TCG is not possible at the moment, even though 
in principle it should be feasible for non-SMP guests.

Paolo

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [Qemu-devel] Re: backdoor
  2010-10-25 12:29     ` [Qemu-devel] Re: backdoor [Was: " Paolo Bonzini
@ 2010-10-25 13:37       ` Lluís
  2010-10-25 21:20         ` Anthony Liguori
  0 siblings, 1 reply; 33+ messages in thread
From: Lluís @ 2010-10-25 13:37 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Paolo Bonzini writes:

> On 10/25/2010 12:54 PM, Lluís wrote:
>> * Backdoor channels need to provide arguments.
>> * It's better to provide the same mechanism for both *-user and softmmu
>> (otherwise the application to simulate or the interposed librariy
>> should be compiled differently on every case).

> You can add the syscall and, if it returns with ENOSYS, fall back to MMIO/PIO
> (you don't really need a special driver, only some chmod since BARs are
> accessible from /sys) or watchpoint/breakpoint.

That sounds nice, but would only work with Linux. I, for example, did
some full-system simulations with a QNX guest.

I know extending the ISA is not nice at all, but I think that's much
more maintainable than a per-guest OS interface (supposing some will
need extra guest drivers).

Another option is going along the path of PPC, where "meanlingless"
operations such OR'ing two zeros is, in fact, an obscure extension of
the ISA to communicate with the hardware SMT priority manager. Or, for
example, using "special" arguments during a cpuid on x86 targets.

But there's still another option. Simply using the recently-posted
virtproxy infrastructure.

The downside of this last method is that this backdoor channel will
appear as the execution of a lot of regular code on the simulation
(e.g., a syscall to write on a socket). If it's just an mmap'ed device,
then we're back on the MMIO/PIO case.

The point here is that the ISA-based backdoor (whether using invalid
opcodes or overloading certain pre-existing operations) is the one
providing the least interference on the guest-side.


>> * Some applications are not fully simulated, but just some pre-defined
>> loops are, such that I would run the application (on KVM mode if
>> possible) until the interesting loop starts executing, switch to
>> simulation mode, simulate an arbitrary number of loops, switch back to
>> non-simulated mode, run until another specific loop or iteration is
>> reached, repeat the process again.
>> This obviously requires some application modification to insert the
>> communication points, unless these can be identified using symbol
>> interposition (e.g., calls to the OpenMP runtime to simulate certain
>> parallel loops).

> Switching between KVM and TCG is not possible at the moment, even though in
> principle it should be feasible for non-SMP guests.

Aaahh... I was going to look into that after instrumenting physical
memory accesses, but if you say it's not possible...

I just looked into how kvm_cpu_exec is called from cpu_exec, and assumed
that state can be transferred from/to each side at any time (e.g., using
kvm_arch_get_registers/kvm_arch_put_registers).

And why isn't it feasible on SMP guests? I suppose it's because each
vCPU is running on a different pthread, and most of the QEMU code is not
thread safe.

If that's the reason, that seems like a lot more work than I'm able to
do right now, but I see two possible solutions:

* provide a crude hack on KVM-enabled QEMU builds to run all vCPUS only
  on one pthread when any of them switch off from KVM-mode

* integrate part of the work from the coremu project, such that QEMU is
  effectively able to run cores on separate threads, even when using
  TCG.


Lluis

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: backdoor [Was: Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation]
  2010-10-25 10:54   ` backdoor [Was: Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation] Lluís
  2010-10-25 12:29     ` [Qemu-devel] Re: backdoor [Was: " Paolo Bonzini
@ 2010-10-25 17:27     ` Blue Swirl
  2010-10-25 20:54       ` [Qemu-devel] Re: backdoor Lluís
  1 sibling, 1 reply; 33+ messages in thread
From: Blue Swirl @ 2010-10-25 17:27 UTC (permalink / raw)
  To: qemu-devel

On Mon, Oct 25, 2010 at 10:54 AM, Lluís <xscript@gmx.net> wrote:
> Blue Swirl writes:
>
>> On Fri, Oct 22, 2010 at 6:32 PM, Lluís <xscript@gmx.net> wrote:
>>> Lluís Vilanova (17):
>>>  backdoor: Declare host-side backdoor helpers
>>>  backdoor: [all] Include backdoor helper declarations
>>>  backdoor: Declare guest-side interface macros
>>>  backdoor: [i386] Decode backdoor instructions
>>>  backdoor: [i386] Declare guest-side interface macros
>>>  backdoor: Add a simple example
>
>> The backdoor instruction is problematic. For example, handling that in
>> KVM may be difficult
>
> I thought about implementing guest-directed KVM control, such that the
> guest will be able to enable/disable KVM at will, but I'm not sure how
> this can be accomplished in a generic way (i.e., x86 has vmcall/vmmcall
> as you told me a lot of time ago).
>
>
>> and there are guest visible side effects.
>
> I don't understand what you mean with guest-visible effects.

The guest can examine itself and determine that it has been modified.
Also, the guest needs to be recompiled and adding the extra
instructions changes the memory layout etc. Furthermore, the source
code needs to be available for recompilation.

>> The same effect can be achieved with a MMIO/PIO device or instrumented
>> breakpoints/watchpoints.
>
>> For the MMIO/PIO device solution, there are several PV devices
>> available, for example virtio devices and fw_cfg. Instead of a
>> backdoor instruction, the guest should simply issue MMIO or PIO using
>> regular instructions. For Linux user, a new syscall can be added.
>> Anyway, the guest still needs to be modified.
>
>> Instrumenting GDB watchpoint and/or breakpoint support would be more
>> attractive because this would be completely invisible to the guest and
>> it may be controlled from GDB.
>
> Ok, so far I see different approaches available:
>
> * MMIO/PIO device
>  Needs no undocumented extensions to the ISA, but requires modifying
>  the guest OS (adding a device driver).

Also the guest application needs to be modified.

> * New syscall
>  Needs no undocumented extensions to the ISA, but will only work with
>  *-user emulation.
>
> * watchpoint/breapoint
>  Needs no undocumented extensions to the ISA, but will only work with
>  softmmu emulation, and only as long as the backdoor channel requires
>  no arguments.

We have GDB support also for user emulators. The arguments could be
set up by GDB monitor command.

> * ISA extensions
>  Needs a per-target decoding of the instruction and won't work when
>  running under KVM.
>
> What I used until now (with my old bochs-based implementation), is the
> presented ISA extensions, which are used through library interposition
> (e.g., in softmmu emulation, launch the application with a library in
> LD_PRELOAD that enables/disables simulation using a
> constructor/destructor attribute, plus some extra backdoor communication
> to simulate specific processes by interposing on the fork/clone
> syscall).
>
> My requirements here are:
>
> * Backdoor channels need to provide arguments.
> * It's better to provide the same mechanism for both *-user and softmmu
>  (otherwise the application to simulate or the interposed librariy
>  should be compiled differently on every case).
> * Some applications are not fully simulated, but just some pre-defined
>  loops are, such that I would run the application (on KVM mode if
>  possible) until the interesting loop starts executing, switch to
>  simulation mode, simulate an arbitrary number of loops, switch back to
>  non-simulated mode, run until another specific loop or iteration is
>  reached, repeat the process again.
>  This obviously requires some application modification to insert the
>  communication points, unless these can be identified using symbol
>  interposition (e.g., calls to the OpenMP runtime to simulate certain
>  parallel loops).
>
> The instrumented watchpoint/breakpoint sounds as an interesting
> approach, but I don't see how I can:
>
> * Differentiate among instrumented and non-instrumented
>  watchpoints/breakpoints

Make the instrumentation selectable for each watchpoint/breakpoint.

> * Pass arguments to the instrumentation backend

Together with the breakpoint structure in CPUState, there should be an
extra storage for the arguments (and a flag whether to enable
instrumentation or not) . This could be set up by monitor commands.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: instrument [Was: Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation]
  2010-10-25 11:13   ` instrument [Was: Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation] Lluís
@ 2010-10-25 18:31     ` Blue Swirl
  2010-10-25 21:48       ` [Qemu-devel] Re: instrument Lluís
  0 siblings, 1 reply; 33+ messages in thread
From: Blue Swirl @ 2010-10-25 18:31 UTC (permalink / raw)
  To: qemu-devel

On Mon, Oct 25, 2010 at 11:13 AM, Lluís <xscript@gmx.net> wrote:
> Blue Swirl writes:
>
>> On Fri, Oct 22, 2010 at 6:32 PM, Lluís <xscript@gmx.net> wrote:
>>>  instrument: Handle config-time activation
>>>  instrument: Add initial instrumentation example
>>>  instrument: Dynamic per-CPU state of static instrumentation points
>>>  instrument: Code-generation macros
>>>  instrument: [all] Include instrumentation helper declarations
>>>  instrument: Add FETCH point
>>>  instrument: [i386] Call FETCH point
>>>  instrument: Add VMEM point
>>>  instrument: [all] Call VMEM point
>>>  instrument: Add PLVL point
>>>  instrument: [i386] Call PLVL point
>
>> At least in these examples, the instrumentation code just prints out a
>> few interesting fields, so they are almost identical to tracepoints.
>
> Right, but that's because that is the simplest usage example I could
> think of.
>
>
>> The general approach seems to be that when an interesting event
>> happens, call the instrumentation code directly.
>
> That's the idea, so that one can go from calling tracing routines to
> providing hand-crafted code generators.
>
>
>> A lot of internal state needs to be made available to the
>> instrumentation code, which is a problem if that is considered as an
>> API.
>
> I don't get what you mean by that. In principle, only the macro
> arguments and the cpu instrumentation state are used.

I was referring to instr_disas, cpu_single_env hacks.

> I tried using static inlined functions on a first draft, but
> "instrument-host.h" is included on too many places and not every
> argument type was available at the include point. Maybe I could try to
> work this out again, such that routines are more self, contained, but
> there's still the problem of CPUState poisoning.
>
>
>> Perhaps this could be changed so that when the event happens, the only
>> effect is that the VM is stopped with some kind of notification. Then
>> a controlling application (external to QEMU) can inspect the state and
>> enable/disable tracepoints as it wishes, but using only the tools that
>> are available for tracepoints, QMP or GDB. Performance would be much
>> lower, though.
>
> Hmmm... as I see it, if tracing provided a two-level backend, I could
> work this out.
>
> I mean, for me, trace-points are just user-definable macros, I could
> provide instrumentation points through that, such that trace.h can
> include (if directed to do it) an extra user-provided header. Then,
> trace.h could look like:
>
>  #include "qemu-common.h"
>
>  #include "trace-override.h" // user defines trace_whatever
>
>  #ifndef trace_whatever
>  // maybe provide a separate trace-events-override file and do not
>  // generate this with tracetool from trace-events
>  static inline void trace_whatever(args...)
>  {
>    call trace backend
>  }
>  #endif

I had a pretty similar concept in mind when I suggested that
tracepoints could be extended, the syntax for trace-events could
become from:
disable apic_set_irq(int apic_irq_delivered) "coalescing %d"
to something like:
disable apic_set_irq(int apic_irq_delivered) "coalescing %d"
apic_irq_instr(void)

> Of course, instrumentation points found during code generation still
> need a different treatment even if they are to be used as plain
> trace-points, as they're not called at run-time unless you generate a
> call to a helper, so maybe a new trace-point type should be handled on
> 'tracetool' (like trace_generate_<whatever> or something like that),
> that generates a call to the tracing backend instead of simply calling
> it.
>
> This way, trace generation from these points can be neatly integrated
> with all the other tracing points.

Maybe the tracepoints should be separate from these helpers (which may
or may not have tracepoints).

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [Qemu-devel] Re: backdoor
  2010-10-25 17:27     ` backdoor [Was: Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation] Blue Swirl
@ 2010-10-25 20:54       ` Lluís
  0 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-25 20:54 UTC (permalink / raw)
  To: qemu-devel

Blue Swirl writes:

> On Mon, Oct 25, 2010 at 10:54 AM, Lluís <xscript@gmx.net> wrote:
>> Blue Swirl writes:
>>
>>> and there are guest visible side effects.
>> 
>> I don't understand what you mean with guest-visible effects.

> The guest can examine itself and determine that it has been modified.

Well, yes, but backdoor instructions are not available on real hardware,
so I think that the case of the guest actively trying to detect if it is
being virtualized is not an issue here (e.g., no blue pill problem on
the scenarios I plan to use it).


> Also, the guest needs to be recompiled and adding the extra
> instructions changes the memory layout etc. Furthermore, the source
> code needs to be available for recompilation.

Well, as I see it, the backdoor implementation _must_ be enabled through
recompilation, and be _not_ activated on official binary releases.

For me, it is the only communication channel I could think of that
provides the minimal overhead on the guest, and has a use only for
peeking into the underlying simulator.


>> Ok, so far I see different approaches available:
>> 
>> * MMIO/PIO device
>>  Needs no undocumented extensions to the ISA, but requires modifying
>>  the guest OS (adding a device driver).

> Also the guest application needs to be modified.

True. But as I said this is a non-issue in my case, although I
understand that such a scheme has no practical use to the Qemu
community. It's just that if the instrumentation is ported to other qemu
targets, both backdoor+instrumentation can serve as a pretty solid
emulation building block for fine-grained analysis of guest code
(including building simulators).


>> * New syscall
>>  Needs no undocumented extensions to the ISA, but will only work with
>>  *-user emulation.
>> 
>> * watchpoint/breapoint
>>  Needs no undocumented extensions to the ISA, but will only work with
>>  softmmu emulation, and only as long as the backdoor channel requires
>>  no arguments.

> We have GDB support also for user emulators. The arguments could be
> set up by GDB monitor command.

Still I don't understand how could I cover the case where I manually
insert code in the guest to communicate directly with Qemu (e.g., start
simulating on an arbitrary point in the guest code).


>> * ISA extensions
>>  Needs a per-target decoding of the instruction and won't work when
>>  running under KVM.
[...]
>> 
>> The instrumented watchpoint/breakpoint sounds as an interesting
>> approach, but I don't see how I can:
>> 
>> * Differentiate among instrumented and non-instrumented
>>  watchpoints/breakpoints

> Make the instrumentation selectable for each watchpoint/breakpoint.

But the only way to control this is through QMP, right? And as I said
before, I don't know how the guest can communicate with QMP in a
_lightweight_ way (if I already can, then I already have a suitable
backdoor channel). Maybe I'm missing something here, as this is my first
contact with qemu.


>> * Pass arguments to the instrumentation backend

> Together with the breakpoint structure in CPUState, there should be an
> extra storage for the arguments (and a flag whether to enable
> instrumentation or not) . This could be set up by monitor commands.

Arguments can be dynamic. For example, see the following guest code:

guest library in LD_PRELOAD:

  int fork ();
  static int (*old_fork) ();

  static void lib_init () __attribute__ ((constructor))
  {
      old_fork = dlsym(RTLD_NEXT, "fork");
  }

  int
  fork ()
  {
      int res = old_fork();
      if (!res) {
         backdoor_trace_me(getpid());
      }
      return res;
  }

Here I can instrument all processes fork'ed from my main instrumented
application, but leave the other system processes uninstrumented (e.g.,
record the current cr3 and enable instrumentation only when recorded cr3
values are running).


Lluis

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [Qemu-devel] Re: backdoor
  2010-10-25 13:37       ` [Qemu-devel] Re: backdoor Lluís
@ 2010-10-25 21:20         ` Anthony Liguori
  2010-10-25 22:48           ` Lluís
  0 siblings, 1 reply; 33+ messages in thread
From: Anthony Liguori @ 2010-10-25 21:20 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel

On 10/25/2010 08:37 AM, Lluís wrote:
> Paolo Bonzini writes:
>
>    
>> On 10/25/2010 12:54 PM, Lluís wrote:
>>      
>>> * Backdoor channels need to provide arguments.
>>> * It's better to provide the same mechanism for both *-user and softmmu
>>> (otherwise the application to simulate or the interposed librariy
>>> should be compiled differently on every case).
>>>        
>    
>> You can add the syscall and, if it returns with ENOSYS, fall back to MMIO/PIO
>> (you don't really need a special driver, only some chmod since BARs are
>> accessible from /sys) or watchpoint/breakpoint.
>>      
> That sounds nice, but would only work with Linux. I, for example, did
> some full-system simulations with a QNX guest.
>
> I know extending the ISA is not nice at all, but I think that's much
> more maintainable than a per-guest OS interface (supposing some will
> need extra guest drivers).
>    

On x86, there are some architecturally nicer ways to do this.

For instance, a CPUID leaf could be used in the 0x40001xxx range.

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [Qemu-devel] Re: instrument
  2010-10-25 18:31     ` Blue Swirl
@ 2010-10-25 21:48       ` Lluís
  0 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-25 21:48 UTC (permalink / raw)
  To: Blue Swirl; +Cc: qemu-devel

Blue Swirl writes:

> On Mon, Oct 25, 2010 at 11:13 AM, Lluís <xscript@gmx.net> wrote:
>> Blue Swirl writes:
>> 
>>> A lot of internal state needs to be made available to the
>>> instrumentation code, which is a problem if that is considered as an
>>> API.
>> 
>> I don't get what you mean by that. In principle, only the macro
>> arguments and the cpu instrumentation state are used.

> I was referring to instr_disas, cpu_single_env hacks.

Aaahhh... yes, those are _extremely_ nasty hacks.

The 'instr_disas' case is mainly because:

1) It is not passed down to all gen_* functions in
   target-i386/translate.c, and I thought passing it would be too
   disruptive (plus could add some extra overheads if the compiler does
   not do a good job optimizing the argument passing).

2) On other non-CISC targets, obtaining all the opcode and register
   usage information can be easily accomplished by, e.g.,
   embedding/parsing the info on the opcode translation tables (e.g.,
   'opcodes' table in target-ppc).

The 'cpu_single_env' case I think is less serious, as it is expected to
contain a valid pointer when translating and executing code (all inside
cpu_exec). The hack I added in linux-user/exec.c was just for an early
initialization thing.

Maybe there's a better approach, but that's the only way I could find to
access the current per-CPU instrumentation state.


>> Hmmm... as I see it, if tracing provided a two-level backend, I could
>> work this out.
>> 
>> I mean, for me, trace-points are just user-definable macros, I could
>> provide instrumentation points through that, such that trace.h can
>> include (if directed to do it) an extra user-provided header. Then,
>> trace.h could look like:
>> 
>>  #include "qemu-common.h"
>> 
>>  #include "trace-override.h" // user defines trace_whatever
>> 
>>  #ifndef trace_whatever
>>  // maybe provide a separate trace-events-override file and do not
>>  // generate this with tracetool from trace-events
>>  static inline void trace_whatever(args...)
>>  {
>>    call trace backend
>>  }
>>  #endif

> I had a pretty similar concept in mind when I suggested that
> tracepoints could be extended, the syntax for trace-events could
> become from:
> disable apic_set_irq(int apic_irq_delivered) "coalescing %d"
> to something like:
> disable apic_set_irq(int apic_irq_delivered) "coalescing %d"
> apic_irq_instr(void)

Well, if it is to be openly exposed, I could rewrite tracetool to parse
lines in "trace-events" like:

 [disable|instrument] <point_name>(<args>) <format>

Thus, using the keyword "instrument" would indicate "tracetool" to avoid
generating any code for that point, and include a pre-defined header
where the user is expected to provide the declaration/implementation of
that point.

This is less elegant than providing two fully-separate layers (e.g.,
QEMU code only calls instrumentation points, and enabling tracing
provides a default instrumentation implementation that calls the
selected tracing method), but is much easier to maintain, as it spans a
single "trace-events" file and is managed by a single "tracetool" file.

I'd prefer building tracing as a specific instrumentation case, but then
probably some developers would suddenly want to kill me :)


Still, two points remain open:

1) Some events cannot be translated into a simple tracing call.  The
   only way I see to circumvent this is to add some keyword to the point
   name, such that tracetool is able to generate a TCG call to the
   tracing backend.

   For example, calling 'trace_name' refers to 'name' in "trace-events",
   and calling 'instr_name' refers to 'instr_name' in
   "trace-events". Although the naming scheme is not simmetric.

2) Without some notion of the per-CPU instrumentation state, points
   inserted during TCG code generation will show an excessive slow down
   on environments with selective dynamic tracing.


>> Of course, instrumentation points found during code generation still
>> need a different treatment even if they are to be used as plain
>> trace-points, as they're not called at run-time unless you generate a
>> call to a helper, so maybe a new trace-point type should be handled on
>> 'tracetool' (like trace_generate_<whatever> or something like that),
>> that generates a call to the tracing backend instead of simply calling
>> it.
>> 
>> This way, trace generation from these points can be neatly integrated
>> with all the other tracing points.

> Maybe the tracepoints should be separate from these helpers (which may
> or may not have tracepoints).

Well, using "disable" on a point prefixed with "instr_" could default to
producing an empty stub even when tracing is configured in.


Lluis

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [Qemu-devel] Re: backdoor
  2010-10-25 21:20         ` Anthony Liguori
@ 2010-10-25 22:48           ` Lluís
  2010-10-25 23:06             ` Anthony Liguori
  0 siblings, 1 reply; 33+ messages in thread
From: Lluís @ 2010-10-25 22:48 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Paolo Bonzini, qemu-devel

Anthony Liguori writes:

> On 10/25/2010 08:37 AM, Lluís wrote:
>> I know extending the ISA is not nice at all, but I think that's much
>> more maintainable than a per-guest OS interface (supposing some will
>> need extra guest drivers).

> On x86, there are some architecturally nicer ways to do this.

> For instance, a CPUID leaf could be used in the 0x40001xxx range.

Right, I commented this in a previous mail as a much nicer way to do it,
but I was just too lazy to look up how CPUID works and instead ported
the implementation I already had in bochs :)

Although I can port it to CPUID if people find it useful to have
upstream. I just need a way to provide an immediate and a register-based
argument (at the same time), which does not require executing more than
a couple of extra instructions (right now everything fits on a single
instruction).

Being able te receive back information would be a plus, which I think
CPUID already does to return its results; although I think the ISA says
that _all_ registers are "used" after executing it.

Lluis

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [Qemu-devel] Re: backdoor
  2010-10-25 22:48           ` Lluís
@ 2010-10-25 23:06             ` Anthony Liguori
  2010-10-26 20:03               ` Lluís
  0 siblings, 1 reply; 33+ messages in thread
From: Anthony Liguori @ 2010-10-25 23:06 UTC (permalink / raw)
  To: Lluís; +Cc: Paolo Bonzini, qemu-devel

On 10/25/2010 05:48 PM, Lluís wrote:
>> For instance, a CPUID leaf could be used in the 0x40001xxx range.
>>      
> Right, I commented this in a previous mail as a much nicer way to do it,
> but I was just too lazy to look up how CPUID works and instead ported
> the implementation I already had in bochs :)
>
> Although I can port it to CPUID if people find it useful to have
> upstream. I just need a way to provide an immediate and a register-based
> argument (at the same time), which does not require executing more than
> a couple of extra instructions (right now everything fits on a single
> instruction).
>
> Being able te receive back information would be a plus, which I think
> CPUID already does to return its results; although I think the ISA says
> that _all_ registers are "used" after executing it.
>    

I think just the base 6 GP registers.  I don't think any of the extended 
registers in 64-bit mode are affected but I would have to look it up.

Regards,

Anthony Liguori

> Lluis
>
>    

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [Qemu-devel] Re: backdoor
  2010-10-25 23:06             ` Anthony Liguori
@ 2010-10-26 20:03               ` Lluís
  0 siblings, 0 replies; 33+ messages in thread
From: Lluís @ 2010-10-26 20:03 UTC (permalink / raw)
  To: qemu-devel

Anthony Liguori writes:

> On 10/25/2010 05:48 PM, Lluís wrote:
>>> For instance, a CPUID leaf could be used in the 0x40001xxx range.
>>> 
>> Right, I commented this in a previous mail as a much nicer way to do it,
>> but I was just too lazy to look up how CPUID works and instead ported
>> the implementation I already had in bochs :)
>> 
>> Although I can port it to CPUID if people find it useful to have
>> upstream. I just need a way to provide an immediate and a register-based
>> argument (at the same time), which does not require executing more than
>> a couple of extra instructions (right now everything fits on a single
>> instruction).
>> 
>> Being able te receive back information would be a plus, which I think
>> CPUID already does to return its results; although I think the ISA says
>> that _all_ registers are "used" after executing it.
>> 

> I think just the base 6 GP registers.  I don't think any of the extended
> registers in 64-bit mode are affected but I would have to look it up.

Right, only the 6 GPRs are defined after a CPUID call.

I'll port my current backdoor implementation to use an unused CPUID
command (by defining EAX), and use the remaining 5 GPRs to provide up to
5 inputs to the backdoor backend.

The plus of this is that it won't crash applications when not running
under QEMU emulation.

The down side is that although both SVM and VMX support intercepting
CPUID calls, KVM does not export this (because it's not a portable form
of hypercall), so I'll still need PIO or MMIO to switch to/from KVM
(vmcall/vmmcall are neither an option as I understand they are
deprecated [1]).

[1] http://lxr.linux.no/linux+v2.6.36/Documentation/kvm/api.txt#L1152

What I thought is that as I'll probably need MMIO to switch between KVM
and emulation, providing also a "-device mon" might come in handy, so
that the guest can issue QMP commands to itself using MMIO, including
trace/instrumentation control commands.

Is anyone already implementing this?


Lluis

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2010-10-26 20:03 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-22 18:32 [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation Lluís
2010-10-22 18:53 ` Lluís
2010-10-18 17:24   ` [Qemu-devel] [PATCH 01/18] backdoor: Handle config-time activation Lluís
2010-10-18 17:40   ` [Qemu-devel] [PATCH 04/18] backdoor: Declare guest-side interface macros Lluís
2010-10-18 18:08   ` [Qemu-devel] [PATCH 06/18] backdoor: [i386] " Lluís
2010-10-18 18:27   ` [Qemu-devel] [PATCH 08/18] instrument: Handle config-time activation Lluís
2010-10-19 19:14   ` [Qemu-devel] [PATCH 05/18] backdoor: [i386] Decode backdoor instructions Lluís
2010-10-19 19:22   ` [Qemu-devel] [PATCH 02/18] backdoor: Declare host-side backdoor helpers Lluís
2010-10-19 19:33   ` [Qemu-devel] [PATCH 03/18] backdoor: [all] Include backdoor helper declarations Lluís
2010-10-19 20:05   ` [Qemu-devel] [PATCH 07/18] backdoor: Add a simple example Lluís
2010-10-19 21:11   ` [Qemu-devel] [PATCH 13/18] instrument: Add FETCH point Lluís
2010-10-19 21:12   ` [Qemu-devel] [PATCH 15/18] instrument: Add VMEM point Lluís
2010-10-19 21:36   ` [Qemu-devel] [PATCH 18/18] instrument: [i386] Call PLVL point Lluís
2010-10-19 21:36   ` [Qemu-devel] [PATCH 17/18] instrument: Add " Lluís
2010-10-19 21:37   ` [Qemu-devel] [PATCH 10/18] instrument: Dynamic per-CPU state of static instrumentation points Lluís
2010-10-19 21:40   ` [Qemu-devel] [PATCH 14/18] instrument: [i386] Call FETCH point Lluís
2010-10-21 14:36   ` [Qemu-devel] [PATCH 11/18] instrument: Code-generation macros Lluís
2010-10-21 17:42   ` [Qemu-devel] [PATCH 09/18] instrument: Add initial instrumentation example Lluís
2010-10-21 20:55   ` [Qemu-devel] [PATCH 12/18] instrument: [all] Include instrumentation helper declarations Lluís
2010-10-22 14:00   ` [Qemu-devel] [PATCH 16/18] instrument: [all] Call VMEM point Lluís
2010-10-23 12:40 ` [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation Blue Swirl
2010-10-25 10:54   ` backdoor [Was: Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation] Lluís
2010-10-25 12:29     ` [Qemu-devel] Re: backdoor [Was: " Paolo Bonzini
2010-10-25 13:37       ` [Qemu-devel] Re: backdoor Lluís
2010-10-25 21:20         ` Anthony Liguori
2010-10-25 22:48           ` Lluís
2010-10-25 23:06             ` Anthony Liguori
2010-10-26 20:03               ` Lluís
2010-10-25 17:27     ` backdoor [Was: Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation] Blue Swirl
2010-10-25 20:54       ` [Qemu-devel] Re: backdoor Lluís
2010-10-25 11:13   ` instrument [Was: Re: [Qemu-devel] [PATCH 00/17] [RFC] static instrumentation] Lluís
2010-10-25 18:31     ` Blue Swirl
2010-10-25 21:48       ` [Qemu-devel] Re: instrument Lluís

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.