qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH, RFC] trace: implement guest tracepoint passthrough


From: Blue Swirl
Subject: [Qemu-devel] [PATCH, RFC] trace: implement guest tracepoint passthrough
Date: Fri, 26 Aug 2011 19:06:28 +0000

Let guests inject tracepoint data via fw_cfg device.

Signed-off-by: Blue Swirl <address@hidden>
---
The patch is used like this:
../configure --with-guest-trace-file=/src/openbios-devel/trace-events
make
sparc64-softmmu/qemu-system-sparc64 -trace file=foo
# ugly hack to combine the file, but my laziness^Wpython-fu is too
weak to add handling of "--guest-trace-file
/src/openbios-devel/trace-events" to simpletrace.py
cat ../trace-events /src/openbios-devel/trace-events >/tmp/trace-events
# examine trace file with OpenBIOS trace data with simpletrace.py
../scripts/simpletrace.py /tmp/trace-events foo
ob_ide_read_blocks 0.000 dest=0xfff0bed0 blk=0x0 n=0x1
ob_ide_read_blocks 6491.806 dest=0xfff0bed0 blk=0x0 n=0x1

An example of a generated guest-trace.c file:
/* This file is autogenerated by tracetool, do not edit. */
#include "trace.h"
#include "guest-trace.h"

void guest_trace(uint64_t event_id, uint64_t arg1, uint64_t arg2,
                 uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6)

{
    switch (event_id) {

    case 0:
        trace_esp_do_command(arg1, arg2, arg3);
        break;

    case 1:
        trace_ob_ide_pio_insw(arg1);
        break;

    case 2:
        trace_ob_ide_read_blocks(arg1, arg2, arg3);
        break;

    default:
        break;
   }
}

---
 Makefile.objs     |   15 +++++++++++-
 configure         |    9 +++++++-
 guest-trace.h     |    3 ++
 hw/fw_cfg.c       |   31 +++++++++++++++++++++++++++
 hw/fw_cfg.h       |   10 ++++++--
 scripts/tracetool |   60 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 6 files changed, 120 insertions(+), 8 deletions(-)
 create mode 100644 guest-trace.h

diff --git a/Makefile.objs b/Makefile.objs
index df11aec..7412e1a 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -340,12 +340,12 @@ else
 trace.h: trace.h-timestamp
 endif
 trace.h-timestamp: $(SRC_PATH)/trace-events config-host.mak
-       $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool
--$(TRACE_BACKEND) -h < $< > $@,"  GEN   trace.h")
+       $(call quiet-command,cat $< $(CONFIG_GUEST_TRACE_FILE) | sh
$(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -h > $@,"  GEN
trace.h")
        @cmp -s $@ trace.h || cp $@ trace.h

 trace.c: trace.c-timestamp
 trace.c-timestamp: $(SRC_PATH)/trace-events config-host.mak
-       $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool
--$(TRACE_BACKEND) -c < $< > $@,"  GEN   trace.c")
+       $(call quiet-command,cat $< $(CONFIG_GUEST_TRACE_FILE) | sh
$(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -c > $@,"  GEN
trace.c")
        @cmp -s $@ trace.c || cp $@ trace.c

 trace.o: trace.c $(GENERATED_HEADERS)
@@ -384,6 +384,17 @@ user-obj-y += qemu-timer-common.o
 endif
 endif

+ifneq ($(CONFIG_GUEST_TRACE_FILE),)
+guest-trace.c: guest-trace.c-timestamp
+guest-trace.c-timestamp: $(CONFIG_GUEST_TRACE_FILE) config-host.mak
+       $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool
--$(TRACE_BACKEND) -g < $< > $@,"  GEN   guest-trace.c")
+       @cmp -s $@ guest-trace.c || cp $@ guest-trace.c
+
+guest-trace.o: guest-trace.c $(GENERATED_HEADERS)
+trace-obj-y += guest-trace.o
+fw_cfg.o: fw_cfg.c $(GENERATED_HEADERS)
+endif
+
 ######################################################################
 # smartcard

diff --git a/configure b/configure
index 1340c33..a120774 100755
--- a/configure
+++ b/configure
@@ -175,6 +175,7 @@ user_pie="no"
 zero_malloc=""
 trace_backend="nop"
 trace_file="trace"
+guest_trace_file=""
 spice=""
 rbd=""
 smartcard=""
@@ -537,6 +538,8 @@ for opt do
   ;;
   --with-trace-file=*) trace_file="$optarg"
   ;;
+  --with-guest-trace-file=*) guest_trace_file="$optarg"
+  ;;
   --enable-gprof) gprof="yes"
   ;;
   --static)
@@ -1033,6 +1036,7 @@ echo "  --enable-trace-backend=B Set trace backend"
 echo "                           Available backends:"
$("$source_path"/scripts/tracetool --list-backends)
 echo "  --with-trace-file=NAME   Full PATH,NAME of file to store traces"
 echo "                           Default:trace-<pid>"
+echo "  --with-guest-trace-file=NAME   Full PATH,NAME for guest trace events"
 echo "  --disable-spice          disable spice"
 echo "  --enable-spice           enable spice"
 echo "  --enable-rbd             enable building the rados block device (rbd)"
@@ -2724,6 +2728,7 @@ echo "uuid support      $uuid"
 echo "vhost-net support $vhost_net"
 echo "Trace backend     $trace_backend"
 echo "Trace output file $trace_file-<pid>"
+echo "Guest trace file  $guest_trace_file"
 echo "spice support     $spice"
 echo "rbd support       $rbd"
 echo "xfsctl support    $xfs"
@@ -3076,7 +3081,9 @@ if test "$trace_backend" = "dtrace" -a
"$trace_backend_stap" = "yes" ; then
   echo "CONFIG_SYSTEMTAP_TRACE=y" >> $config_host_mak
 fi
 echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak
-
+if test "x$guest_trace_file" != "x"; then
+    echo "CONFIG_GUEST_TRACE_FILE=$guest_trace_file" >> $config_host_mak
+fi
 echo "TOOLS=$tools" >> $config_host_mak
 echo "ROMS=$roms" >> $config_host_mak
 echo "MAKE=$make" >> $config_host_mak
diff --git a/guest-trace.h b/guest-trace.h
new file mode 100644
index 0000000..db6bb2b
--- /dev/null
+++ b/guest-trace.h
@@ -0,0 +1,3 @@
+#include <stdint.h>
+void guest_trace(uint64_t event_id, uint64_t arg1, uint64_t arg2,
+                 uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6);
diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
index 8df265c..a6b0dbc 100644
--- a/hw/fw_cfg.c
+++ b/hw/fw_cfg.c
@@ -27,6 +27,9 @@
 #include "fw_cfg.h"
 #include "sysbus.h"
 #include "qemu-error.h"
+#ifdef CONFIG_GUEST_TRACE_FILE
+#include "guest-trace.h"
+#endif

 /* debug firmware config */
 //#define DEBUG_FW_CFG
@@ -55,6 +58,12 @@ struct FWCfgState {
     uint16_t cur_entry;
     uint32_t cur_offset;
     Notifier machine_ready;
+#define GUEST_TRACE_ARGS 7
+#define GUEST_TRACE_BUF_SIZE (sizeof(uint64_t) * GUEST_TRACE_ARGS)
+    union {
+        uint8_t guest_trace_buf[GUEST_TRACE_BUF_SIZE];
+        uint64_t guest_trace_args[GUEST_TRACE_ARGS];
+    } u;
 };

 #define JPG_FILE 0
@@ -477,6 +486,27 @@ static void fw_cfg_machine_ready(struct Notifier
*n, void *data)
     fw_cfg_add_file(s, "bootorder", (uint8_t*)bootindex, len);
 }

+static void fw_cfg_guest_trace(void *opaque, uint8_t *data)
+{
+#ifdef CONFIG_GUEST_TRACE_FILE
+    FWCfgState *s = opaque;
+
+    guest_trace(le64_to_cpu(s->u.guest_trace_args[0]),
+                le64_to_cpu(s->u.guest_trace_args[1]),
+                le64_to_cpu(s->u.guest_trace_args[2]),
+                le64_to_cpu(s->u.guest_trace_args[3]),
+                le64_to_cpu(s->u.guest_trace_args[4]),
+                le64_to_cpu(s->u.guest_trace_args[5]),
+                le64_to_cpu(s->u.guest_trace_args[6]));
+#endif
+}
+
+static void fw_cfg_guest_trace_init(FWCfgState *s, uint16_t key)
+{
+    fw_cfg_add_callback(s, key, fw_cfg_guest_trace, s,
+                        s->u.guest_trace_buf, sizeof(s->u.guest_trace_buf));
+}
+
 FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
                         target_phys_addr_t ctl_addr,
target_phys_addr_t data_addr)
 {
@@ -504,6 +534,7 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port,
uint32_t data_port,
     fw_cfg_add_i16(s, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
     fw_cfg_add_i16(s, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
     fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu);
+    fw_cfg_guest_trace_init(s, FW_CFG_GUEST_TRACE);
     fw_cfg_bootsplash(s);

     s->machine_ready.notify = fw_cfg_machine_ready;
diff --git a/hw/fw_cfg.h b/hw/fw_cfg.h
index 856bf91..45b6396 100644
--- a/hw/fw_cfg.h
+++ b/hw/fw_cfg.h
@@ -1,6 +1,9 @@
 #ifndef FW_CFG_H
 #define FW_CFG_H

+#define FW_CFG_WRITE_CHANNEL    0x4000
+#define FW_CFG_ARCH_LOCAL       0x8000
+
 #define FW_CFG_SIGNATURE        0x00
 #define FW_CFG_ID               0x01
 #define FW_CFG_UUID             0x02
@@ -30,10 +33,11 @@

 #define FW_CFG_FILE_FIRST       0x20
 #define FW_CFG_FILE_SLOTS       0x10
-#define FW_CFG_MAX_ENTRY        (FW_CFG_FILE_FIRST+FW_CFG_FILE_SLOTS)

-#define FW_CFG_WRITE_CHANNEL    0x4000
-#define FW_CFG_ARCH_LOCAL       0x8000
+#define FW_CFG_GUEST_TRACE      (FW_CFG_WRITE_CHANNEL |
(FW_CFG_FILE_FIRST+FW_CFG_FILE_SLOTS))
+
+#define FW_CFG_MAX_ENTRY        (FW_CFG_FILE_FIRST+FW_CFG_FILE_SLOTS + 1)
+
 #define FW_CFG_ENTRY_MASK       ~(FW_CFG_WRITE_CHANNEL | FW_CFG_ARCH_LOCAL)

 #define FW_CFG_INVALID          0xffff
diff --git a/scripts/tracetool b/scripts/tracetool
index 2155a57..78e7897 100755
--- a/scripts/tracetool
+++ b/scripts/tracetool
@@ -13,7 +13,7 @@ set -f
 usage()
 {
     cat >&2 <<EOF
-usage: $0 [--nop | --simple | --stderr | --ust | --dtrace] [-h | -c]
+usage: $0 [--nop | --simple | --stderr | --ust | --dtrace] [-h | -c | -d | -g]
 Generate tracing code for a file on stdin.

 Backends:
@@ -27,6 +27,7 @@ Output formats:
   -h     Generate .h file
   -c     Generate .c file
   -d     Generate .d file (DTrace only)
+  -g     Generate guest trace .c file
   --stap Generate .stp file (DTrace with SystemTAP only)

 Options:
@@ -35,6 +36,7 @@ Options:
   --target-type  [type]    QEMU emulator target type ('system' or 'user')
   --probe-prefix [prefix]  Prefix for dtrace probe names
                            (default: qemu-\$targettype-\$targetarch)
+  --guest-trace            Generate guest trace function

 EOF
     exit 1
@@ -502,6 +504,51 @@ linetostap_end_dtrace()
     return
 }

+linetog_begin_all()
+{
+    id=0
+    cat <<EOF
+#include "trace.h"
+#include "guest-trace.h"
+
+void guest_trace(uint64_t event_id, uint64_t arg1, uint64_t arg2,
+                 uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6)
+
+{
+    switch (event_id) {
+EOF
+}
+
+linetog_all()
+{
+    local name args argc arg
+    name=$(get_name "$1")
+    argc=$(get_argc "$1")
+    fieldno=1
+    args=
+    for arg in $(get_argnames "$1", ","); do
+        args="${args}arg$fieldno"
+        [ "$fieldno" = "$argc" ] || args="$args, "
+        fieldno="$((fieldno + 1))"
+    done
+    cat <<EOF
+    case $id:
+        trace_$name($args);
+        break;
+EOF
+    id="$((id + 1))"
+}
+
+linetog_end_all()
+{
+    cat <<EOF
+    default:
+        break;
+   }
+}
+EOF
+}
+
 # Process stdin by calling begin, line, and end functions for the backend
 convert()
 {
@@ -557,6 +604,13 @@ tracetoc()
     convert c
 }

+tracetog()
+{
+    echo "/* This file is autogenerated by tracetool, do not edit. */"
+    backend=all
+    convert g
+}
+
 tracetod()
 {
     if [ $backend != "dtrace" ]; then
@@ -599,6 +653,7 @@ binary=
 targettype=
 targetarch=
 probeprefix=
+guesttrace=


 until [ -z "$1" ]
@@ -610,8 +665,9 @@ do
     "--target-arch") shift ; targetarch="$1" ;;
     "--target-type") shift ; targettype="$1" ;;
     "--probe-prefix") shift ; probeprefix="$1" ;;
+    "--guest-trace") guesttrace="yes" ;;

-    "-h" | "-c" | "-d") output="${1#-}" ;;
+    "-h" | "-c" | "-d" | "-g") output="${1#-}" ;;
     "--stap") output="${1#--}" ;;

     "--check-backend") exit 0 ;; # used by ./configure to test for backend
-- 
1.6.2.4

Attachment: 0001-trace-implement-guest-tracepoint-passthrough.patch
Description: Text Data

Attachment: 0001-Introduce-tracing-system-from-QEMU.patch
Description: Text Data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]