All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel
@ 2016-09-05 18:56 Lluís Vilanova
  2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 1/6] hypertrace: Add documentation Lluís Vilanova
                   ` (6 more replies)
  0 siblings, 7 replies; 14+ messages in thread
From: Lluís Vilanova @ 2016-09-05 18:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P Berrange, Luiz Capitulino, Eric Blake, Stefan Hajnoczi

The hypertrace channel allows guest code to emit events in QEMU (the host) using
its tracing infrastructure (see "docs/trace.txt"). This works in both 'system'
and 'user' modes, is architecture-agnostic and introduces minimal noise on the
guest.

See first commit for a full description, use-cases and an example.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---

Changes in v2
=============

* Remove unnecessary casts for g2h() [Eric Blake].
* Use perror() [Eric Blake].
* Avoid expansions in application example [Eric Blake].
* Add copyright in document "hypertrace.txt" [Eric Blake].
* Make the user-mode hypertrace invocations thread-safe [Stefan Hajnoczi].
* Split dynamic hypertrace configuration into a separate "config" channel.

Changes in v3
=============

* Fix calculation of arguments.
* Rebase on e00da55

Lluís Vilanova (6):
      hypertrace: Add documentation
      hypertrace: Add tracing event "guest_hypertrace"
      hypertrace: [*-user] Add QEMU-side proxy to "guest_hypertrace" event
      hypertrace: [softmmu] Add QEMU-side proxy to "guest_hypertrace" event
      hypertrace: Add guest-side user-level library
      hypertrace: Add guest-side Linux module


 Makefile                                           |    8 
 Makefile.objs                                      |    6 
 bsd-user/main.c                                    |   16 +
 bsd-user/mmap.c                                    |   15 +
 bsd-user/syscall.c                                 |   31 +-
 configure                                          |   40 ++
 docs/hypertrace.txt                                |  227 +++++++++++++
 docs/tracing.txt                                   |    3 
 hypertrace/Makefile.objs                           |   21 +
 hypertrace/common.c                                |   26 ++
 hypertrace/common.h                                |   24 +
 hypertrace/guest/linux-module/Kbuild.in            |    7 
 hypertrace/guest/linux-module/Makefile             |   23 +
 .../include/linux/qemu-hypertrace-internal.h       |   46 +++
 .../linux-module/include/linux/qemu-hypertrace.h   |   73 ++++
 hypertrace/guest/linux-module/qemu-hypertrace.c    |  146 +++++++++
 hypertrace/guest/user/Makefile                     |   30 ++
 hypertrace/guest/user/common.c                     |  301 ++++++++++++++++++
 hypertrace/guest/user/qemu-hypertrace.h            |   80 +++++
 hypertrace/softmmu.c                               |  235 ++++++++++++++
 hypertrace/user.c                                  |  339 ++++++++++++++++++++
 hypertrace/user.h                                  |   61 ++++
 include/hw/pci/pci.h                               |    2 
 include/qom/cpu.h                                  |    4 
 linux-user/main.c                                  |   19 +
 linux-user/mmap.c                                  |   17 +
 linux-user/qemu.h                                  |    3 
 linux-user/syscall.c                               |   31 +-
 trace/Makefile.objs                                |    2 
 29 files changed, 1809 insertions(+), 27 deletions(-)
 create mode 100644 docs/hypertrace.txt
 create mode 100644 hypertrace/Makefile.objs
 create mode 100644 hypertrace/common.c
 create mode 100644 hypertrace/common.h
 create mode 100644 hypertrace/guest/linux-module/Kbuild.in
 create mode 100644 hypertrace/guest/linux-module/Makefile
 create mode 100644 hypertrace/guest/linux-module/include/linux/qemu-hypertrace-internal.h
 create mode 100644 hypertrace/guest/linux-module/include/linux/qemu-hypertrace.h
 create mode 100644 hypertrace/guest/linux-module/qemu-hypertrace.c
 create mode 100644 hypertrace/guest/user/Makefile
 create mode 100644 hypertrace/guest/user/common.c
 create mode 100644 hypertrace/guest/user/qemu-hypertrace.h
 create mode 100644 hypertrace/softmmu.c
 create mode 100644 hypertrace/user.c
 create mode 100644 hypertrace/user.h


To: qemu-devel@nongnu.org
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Cc: Eric Blake <eblake@redhat.com>
Cc: Luiz Capitulino <lcapitulino@redhat.com>
Cc: Daniel P Berrange <berrange@redhat.com>

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

* [Qemu-devel] [PATCH v2 1/6] hypertrace: Add documentation
  2016-09-05 18:56 [Qemu-devel] [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel Lluís Vilanova
@ 2016-09-05 18:56 ` Lluís Vilanova
  2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 2/6] hypertrace: Add tracing event "guest_hypertrace" Lluís Vilanova
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Lluís Vilanova @ 2016-09-05 18:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P Berrange, Luiz Capitulino, Eric Blake, Stefan Hajnoczi

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 docs/hypertrace.txt |  227 +++++++++++++++++++++++++++++++++++++++++++++++++++
 docs/tracing.txt    |    3 +
 2 files changed, 230 insertions(+)
 create mode 100644 docs/hypertrace.txt

diff --git a/docs/hypertrace.txt b/docs/hypertrace.txt
new file mode 100644
index 0000000..f061036
--- /dev/null
+++ b/docs/hypertrace.txt
@@ -0,0 +1,227 @@
+= Hypertrace channel =
+
+Copyright (C) 2016 Lluís Vilanova <vilanova@ac.upc.edu>
+
+This work is licensed under the terms of the GNU GPL, version 2 or later.
+See the COPYING file in the top-level directory.
+
+
+The hypertrace channel allows guest code to emit events in QEMU (the host) using
+its tracing infrastructure (see "docs/trace.txt"). This works in both 'system'
+and 'user' modes. Therefore, hypertrace is to tracing what hypercalls are to
+system calls.
+
+The hypertrace channel can be used for various purposes:
+
+* The example below shows how to use this on your guest applications to identify
+  regions of interest where you want to selectively enable certain tracing
+  events, without paying the price of tracing them outside the interest
+  regions.
+
+* You can also invoke hypertrace in your guest code to time the performance of
+  new TCG optimizations. Each hypertrace event comes with a host timestamp,
+  making it easy to compare execution times of interesting guest code regions.
+
+* Calls to hypertrace can also be added along traces generated in the guest to
+  more easily correlate and merge guest and host traces.
+
+Hypertrace highlights:
+
+* Works with 'system' and 'user' mode.
+
+* Minimal setup for the guest; QEMU provides support guest code libraries to
+  make 'system' mode with Linux and 'user' mode work out of the box.
+
+* Independent of guest architecture; the guest code uses accesses to special
+  memory regions, as opposed to redefining instruction semantics.
+
+* Negligible guest overhead; emitting a hypertrace event requires a single guest
+  memory access, making it as unobtrusive as possible.
+
+Warning: The hypertrace channel in 'system' mode is presented as a PCI device,
+and thus will only be available on systems with support for PCI. You can get the
+list of guests with PCI support with 'grep pci.mak default-configs/*'.
+
+
+== Quick guide ==
+
+This shows an example of using the hypertrace channel to trace events only in a
+region of the guest code, which is identified by calls to the hypertrace
+channel.
+
+We are going to trace memory accesses to disk using QEMU's "log" backend, and
+will use QEMU's "dtrace" (SystemTap) backend to control when we want to trace
+them. Tracing is done with "log" because it is more efficient than using
+"dtrace" in high-volume events like memory accesses. The first time the guest
+code invokes the hypertrace channel, we will start tracing the
+"guest_mem_before_exec" event, and then will disable it the second time around.
+
+1. Set the tracing backends and number of arguments for the hypertrace events:
+
+    mkdir /tmp/qemu-build
+    cd /tmp/qemu-build
+    /path/to/qemu-source/configure              \
+        --enable-trace-backends=dtrace,log      \
+        --with-hypertrace-args=1                \
+        --prefix=/tmp/qemu-install
+    make -j install
+
+2. Enable the "guest_mem_before_exec" event:
+
+    sed -i -e 's/disable vcpu tcg guest_mem_before/vcpu tcg guest_mem_before/g' /path/to/qemu-source/trace-events
+
+3. Compile the guest support code:
+
+    make -C /tmp/qemu-build/x86_64-linux-user/hypertrace/guest/user
+    make -C /tmp/qemu-build/x86_64-softmmu/hypertrace/guest/user
+    make -C /tmp/qemu-build/x86_64-softmmu/hypertrace/guest/linux-module
+
+   If you need to cross-compile the guest library, set the 'CC' variable:
+
+    make -C /tmp/qemu-build/mipsel-linux-user/hypertrace/guest/user CC=mipsel-gnu-linux-gcc
+
+3. Create a guest application using "qemu-hypertrace.h" to interact with the
+   hypertrace channel:
+
+    cat > /tmp/my-hypertrace.c <<\EOF
+    #include <stdio.h>
+    #include <errno.h>
+    #include <stdlib.h>
+    #include <string.h>
+    #include <qemu-hypertrace.h>
+    
+    
+    int main(int argc, char **argv)
+    {
+        char *base = NULL;
+        if (argc > 1) {
+            base = argv[1];
+        }
+    
+        /* In 'user' mode this path must be the same we will use to start QEMU. */
+        if (qemu_hypertrace_init(base) != 0) {
+            perror("error: qemu_hypertrace_init");
+            abort();
+        }
+    
+        /* Set additional event arguments */
+        uint64_t client  = 0;
+        uint64_t *data = qemu_hypertrace_data(client);
+        data[0] = 0xbabe;
+        data[1] = 0xdead;
+        data[2] = 0xbeef;
+    
+        /* Emit 1st event */
+        qemu_hypertrace(client, 0xcafe);
+
+        /* Computation in between */
+        printf("Some computation...\n");
+
+        /* Emit 2nd event */
+        qemu_hypertrace(client, 0xcafe);
+    }
+    EOF
+
+    gcc -o /tmp/my-hypertrace-user /tmp/my-hypertrace.c                                    \
+        /tmp/qemu-build/x86_64-linux-user/hypertrace/guest/user/libqemu-hypertrace-guest.a \
+        -I/tmp/qemu-install/include -lpthread
+
+    gcc -o /tmp/my-hypertrace-softmmu /tmp/my-hypertrace.c                              \
+        /tmp/qemu-build/x86_64-softmmu/hypertrace/guest/user/libqemu-hypertrace-guest.a \
+        -I/tmp/qemu-install/include -lpthread
+
+4. Create a SystemTap script to control event tracing:
+
+    cat > /tmp/my-hypertrace-script.stp <<\EOF
+    #!/usr/bin/env stap
+    
+    global hypercount
+    
+    %{
+    #include <linux/delay.h>
+    %}
+    
+    function enable_mem:long()
+    %{
+        char *argv[4] = {"/bin/sh", "-c", "echo 'trace-event guest_mem_before_exec on' | telnet localhost 1234", NULL};
+        printk(KERN_ERR "enable\n");
+        call_usermodehelper(argv[0], argv, NULL, UMH_WAIT_EXEC);
+        /* Wait for changes to apply */
+        msleep(1000);
+        printk(KERN_ERR "enabled\n");
+        STAP_RETURN(0);
+    %}
+    
+    function disable_mem:long()
+    %{
+        char *argv[4] = {"/bin/sh", "-c", "echo 'trace-event guest_mem_before_exec off' | telnet localhost 1234", NULL};
+        printk(KERN_ERR "disable\n");
+        call_usermodehelper(argv[0], argv, NULL, UMH_WAIT_EXEC);
+        msleep(1000);
+        printk(KERN_ERR "disabled\n");
+        STAP_RETURN(0);
+    %}
+    
+    probe process("./install/vanilla/bin/qemu-*").mark("guest_hypertrace")
+    {
+        hypercount++
+        printf("guest_hypertrace: %x\n", $arg1)
+        if (hypercount == 1) {
+            enable_mem()
+        } else if (hypercount == 2) {
+            disable_mem()
+            exit()
+        }
+    }
+    EOF
+
+4. Run a guest system with access to QEMU's hypertrace:
+
+    stap -g /tmp/my-hypertrace-script.stp
+    /tmp/qemu-install/x86_64-softmmu/qemu-system-x86_64 \
+      -device hypertrace                                \
+      -monitor tcp:localhost:1234,server,nowait         \
+      -trace enable=guest_hypertrace -D /dev/stdout     \
+      ...'
+
+   And inside the VM:
+
+    sudo /tmp/my-hypertrace-softmmu
+
+   The result will be something like this:
+
+    VNC server running on ::1:5900
+    23071@1473096085.744211:guest_hypertrace cpu=0x5602e1f49c10  arg1=0x000000000000cafe arg2=0x000000000000babe arg3=0x000000000000dead arg4=0x000000000000beef
+    23071@1473096085.745763:guest_mem_before_trans cpu=0x5602e1f49c10 info=19
+    23071@1473096085.745907:guest_mem_before_trans cpu=0x5602e1f49c10 info=3
+    23071@1473096085.752368:guest_mem_before_trans cpu=0x5602e1f49c10 info=3
+    23071@1473096085.752384:guest_mem_before_trans cpu=0x5602e1f49c10 info=19
+    23071@1473096086.756117:guest_hypertrace cpu=0x5602e1f49c10  arg1=0x000000000000cafe arg2=0x000000000000babe arg3=0x000000000000dead arg4=0x000000000000beef
+
+Similarly, you can enable hypertrace when running standalone guest applications:
+
+    /tmp/qemu-install/bin/qemu-x86_64          \
+      -hypertrace /tmp/hypertrace              \
+      -trace enable=guest* -D /dev/stdout      \
+      /tmp/my-hypertrace-user /tmp/hypertrace
+
+You can also use hypertrace inside the Linux's kernel code with the provided
+guest module (see "/tmp/qemu-install/include/linux/qemu-hypertrace.h"):
+
+    sudo insmod /tmp/qemu-build/x86_64-softmmu/hypertrace/guest/linux-module/qemu-hypertrace.ko
+
+
+== Details ==
+
+To make it more efficient in terms of guest and host time, hypertrace provides
+two different memory areas (channels).
+
+The control channel is used by the guest to tell QEMU that new data is ready to
+be processed in the data channel. Writes to the control channel are intercepted
+by QEMU, which emits the "hypertrace" tracing event.
+
+The data channel is a regular memory buffer used by the guest to write
+additional event arguments before raising the event through the control channel.
+
+Both channels accept different "per-client offsets" to enable multiple guest
+threads or CPUs to use the hypertrace channel without having to synchronize.
diff --git a/docs/tracing.txt b/docs/tracing.txt
index 29f2f9a..f312596 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -5,6 +5,9 @@
 This document describes the tracing infrastructure in QEMU and how to use it
 for debugging, profiling, and observing execution.
 
+See "docs/hypertrace.txt" to correlate guest tracing events with those in the
+QEMU host.
+
 == Quickstart ==
 
 1. Build with the 'simple' trace backend:

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

* [Qemu-devel] [PATCH v2 2/6] hypertrace: Add tracing event "guest_hypertrace"
  2016-09-05 18:56 [Qemu-devel] [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel Lluís Vilanova
  2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 1/6] hypertrace: Add documentation Lluís Vilanova
@ 2016-09-05 18:56 ` Lluís Vilanova
  2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 3/6] hypertrace: [*-user] Add QEMU-side proxy to "guest_hypertrace" event Lluís Vilanova
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Lluís Vilanova @ 2016-09-05 18:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P Berrange, Luiz Capitulino, Eric Blake, Stefan Hajnoczi

Generates the "guest_hypertrace" event with a user-configurable number
of arguments.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 Makefile.objs       |    2 ++
 configure           |   34 ++++++++++++++++++++++++++++++++++
 trace/Makefile.objs |    2 +-
 3 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/Makefile.objs b/Makefile.objs
index 6d5ddcf..3db04b9 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -159,3 +159,5 @@ trace-events-y += target-s390x/trace-events
 trace-events-y += target-ppc/trace-events
 trace-events-y += qom/trace-events
 trace-events-y += linux-user/trace-events
+
+trace-events-gen-y = hypertrace/trace-events
diff --git a/configure b/configure
index 4b808f9..d7ec31f 100755
--- a/configure
+++ b/configure
@@ -273,6 +273,7 @@ pie=""
 qom_cast_debug="yes"
 trace_backends="log"
 trace_file="trace"
+hypertrace="1"
 spice=""
 rbd=""
 smartcard=""
@@ -782,6 +783,8 @@ for opt do
   ;;
   --with-trace-file=*) trace_file="$optarg"
   ;;
+  --with-hypertrace-args=*) hypertrace="$optarg"
+  ;;
   --enable-gprof) gprof="yes"
   ;;
   --enable-gcov) gcov="yes"
@@ -1300,6 +1303,8 @@ Advanced options (experts only):
                            Available backends: $($python $source_path/scripts/tracetool.py --list-backends)
   --with-trace-file=NAME   Full PATH,NAME of file to store traces
                            Default:trace-<pid>
+  --with-hypertrace-args=NUMBER
+                           number of hypertrace arguments (default: $hypertrace)
   --disable-slirp          disable SLIRP userspace network connectivity
   --enable-tcg-interpreter enable TCG with bytecode interpreter (TCI)
   --oss-lib                path to OSS library
@@ -4201,6 +4206,16 @@ if test "$?" -ne 0 ; then
 fi
 
 ##########################################
+# check hypertrace arguments
+case "$hypertrace" in
+    ''|*[!0-9]*) error_exit "invalid number of hypertrace arguments" ;;
+    *) ;;
+esac
+if test $hypertrace = 0; then
+    error_exit "hypertrace arguments must be greater than zero"
+fi
+
+##########################################
 # For 'ust' backend, test if ust headers are present
 if have_backend "ust"; then
   cat > $TMPC << EOF
@@ -4875,6 +4890,7 @@ echo "Trace backends    $trace_backends"
 if have_backend "simple"; then
 echo "Trace output file $trace_file-<pid>"
 fi
+echo "Hypertrace arguments  $hypertrace"
 echo "spice support     $spice $(echo_version $spice $spice_protocol_version/$spice_server_version)"
 echo "rbd support       $rbd"
 echo "xfsctl support    $xfs"
@@ -5503,6 +5519,24 @@ else
 fi
 QEMU_INCLUDES="-I\$(SRC_PATH)/tcg $QEMU_INCLUDES"
 
+# hypertrace
+echo "CONFIG_HYPERTRACE_ARGS=$hypertrace" >> $config_host_mak
+hypertrace_events=hypertrace/trace-events
+mkdir -p $(dirname $hypertrace_events)
+echo "# See docs/trace-events.txt for syntax documentation." >$hypertrace_events
+echo -n 'vcpu guest_hypertrace(' >>$hypertrace_events
+for i in `seq $hypertrace`; do
+    if test $i != 1; then
+        echo -n ", " >>$hypertrace_events
+    fi
+    echo -n "uint64_t arg$i" >>$hypertrace_events
+done
+echo -n ') ' >>$hypertrace_events
+for i in `seq $hypertrace`; do
+    echo -n "\" arg$i=0x%016\"PRIx64" >>$hypertrace_events
+done
+echo >>$hypertrace_events
+
 echo "TOOLS=$tools" >> $config_host_mak
 echo "ROMS=$roms" >> $config_host_mak
 echo "MAKE=$make" >> $config_host_mak
diff --git a/trace/Makefile.objs b/trace/Makefile.objs
index 4d91b3b..b71ec54 100644
--- a/trace/Makefile.objs
+++ b/trace/Makefile.objs
@@ -8,7 +8,7 @@
 tracetool-y = $(SRC_PATH)/scripts/tracetool.py
 tracetool-y += $(shell find $(SRC_PATH)/scripts/tracetool -name "*.py")
 
-$(BUILD_DIR)/trace-events-all: $(trace-events-y:%=$(SRC_PATH)/%)
+$(BUILD_DIR)/trace-events-all: $(trace-events-y:%=$(SRC_PATH)/%) $(trace-events-gen-y:%=$(BUILD_DIR)/%)
 	$(call quiet-command,cat $^ > $@)
 
 ######################################################################

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

* [Qemu-devel] [PATCH v2 3/6] hypertrace: [*-user] Add QEMU-side proxy to "guest_hypertrace" event
  2016-09-05 18:56 [Qemu-devel] [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel Lluís Vilanova
  2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 1/6] hypertrace: Add documentation Lluís Vilanova
  2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 2/6] hypertrace: Add tracing event "guest_hypertrace" Lluís Vilanova
@ 2016-09-05 18:56 ` Lluís Vilanova
  2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 4/6] hypertrace: [softmmu] " Lluís Vilanova
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Lluís Vilanova @ 2016-09-05 18:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P Berrange, Luiz Capitulino, Eric Blake, Stefan Hajnoczi,
	Riku Voipio

QEMU detects when the guest uses 'mmap' on hypertrace's control channel
file, and then uses 'mprotect' to detect accesses to it, which are used
to trigger tracing event "guest_hypertrace".

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 Makefile.objs            |    4 +
 bsd-user/main.c          |   16 ++
 bsd-user/mmap.c          |   15 ++
 bsd-user/syscall.c       |   31 +++-
 hypertrace/Makefile.objs |   18 ++
 hypertrace/common.c      |   26 ++++
 hypertrace/common.h      |   24 +++
 hypertrace/user.c        |  339 ++++++++++++++++++++++++++++++++++++++++++++++
 hypertrace/user.h        |   61 ++++++++
 include/qom/cpu.h        |    4 +
 linux-user/main.c        |   19 +++
 linux-user/mmap.c        |   17 ++
 linux-user/qemu.h        |    3 
 linux-user/syscall.c     |   31 +++-
 14 files changed, 583 insertions(+), 25 deletions(-)
 create mode 100644 hypertrace/Makefile.objs
 create mode 100644 hypertrace/common.c
 create mode 100644 hypertrace/common.h
 create mode 100644 hypertrace/user.c
 create mode 100644 hypertrace/user.h

diff --git a/Makefile.objs b/Makefile.objs
index 3db04b9..56b41c7 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -104,6 +104,10 @@ util-obj-y +=  trace/
 target-obj-y += trace/
 
 ######################################################################
+# hypertrace
+target-obj-y += hypertrace/
+
+######################################################################
 # guest agent
 
 # FIXME: a few definitions from qapi-types.o/qapi-visit.o are needed
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 0fb08e4..0d0a850 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -31,9 +31,12 @@
 #include "tcg.h"
 #include "qemu/timer.h"
 #include "qemu/envlist.h"
+#include "qemu/error-report.h"
 #include "exec/log.h"
 #include "trace/control.h"
 #include "glib-compat.h"
+#include "hypertrace/user.h"
+
 
 int singlestep;
 unsigned long mmap_min_addr;
@@ -694,6 +697,8 @@ static void usage(void)
            "-strace           log system calls\n"
            "-trace            [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
            "                  specify tracing options\n"
+           "-hypertrace       [[base=]<path>][,max-clients=<uint>]\n"
+           "                  specify hypertrace options\n"
            "\n"
            "Environment variables:\n"
            "QEMU_STRACE       Print system calls and arguments similar to the\n"
@@ -744,6 +749,8 @@ int main(int argc, char **argv)
     envlist_t *envlist = NULL;
     char *trace_file = NULL;
     bsd_type = target_openbsd;
+    char *hypertrace_base = NULL;
+    unsigned int hypertrace_max_clients = 0;
 
     if (argc <= 1)
         usage();
@@ -763,6 +770,7 @@ int main(int argc, char **argv)
     cpu_model = NULL;
 
     qemu_add_opts(&qemu_trace_opts);
+    qemu_add_opts(&qemu_hypertrace_opts);
 
     optind = 1;
     for (;;) {
@@ -853,6 +861,9 @@ int main(int argc, char **argv)
         } else if (!strcmp(r, "trace")) {
             g_free(trace_file);
             trace_file = trace_opt_parse(optarg);
+        } else if (!strcmp(r, "hypertrace")) {
+            g_free(hypertrace_file);
+            hypertrace_opt_parse(optarg, &hypertrace_base, &hypertrace_max_clients);
         } else {
             usage();
         }
@@ -987,6 +998,11 @@ int main(int argc, char **argv)
     target_set_brk(info->brk);
     syscall_init();
     signal_init();
+    if (atexit(hypertrace_fini) != 0) {
+        fprintf(stderr, "error: atexit: %s\n", strerror(errno));
+        abort();
+    }
+    hypertrace_init(hypertrace_base, hypertrace_size);
 
     /* Now that we've loaded the binary, GUEST_BASE is fixed.  Delay
        generating the prologue until now so that the prologue can take
diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
index 610f91b..d8ffc1e 100644
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -21,6 +21,7 @@
 #include "qemu.h"
 #include "qemu-common.h"
 #include "bsd-mman.h"
+#include "hypertrace/user.h"
 
 //#define DEBUG_MMAP
 
@@ -251,10 +252,17 @@ static abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
     return addr;
 }
 
-/* NOTE: all the constants are the HOST ones */
 abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
                      int flags, int fd, abi_ulong offset)
 {
+    return target_mmap_cpu(start, len, prot, flags, fd, offset, NULL);
+}
+
+/* NOTE: all the constants are the HOST ones */
+abi_long target_mmap_cpu(abi_ulong start, abi_ulong len, int prot,
+                         int flags, int fd, abi_ulong offset,
+                         CPUState *cpu)
+{
     abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
     unsigned long host_start;
 
@@ -296,6 +304,10 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
         goto the_end;
     real_start = start & qemu_host_page_mask;
 
+    if (!hypertrace_guest_mmap_check(fd, len, offset)) {
+        goto fail;
+    }
+
     if (!(flags & MAP_FIXED)) {
         abi_ulong mmap_start;
         void *p;
@@ -407,6 +419,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
         }
     }
  the_end1:
+    hypertrace_guest_mmap_apply(fd, g2h(start), cpu);
     page_set_flags(start, start + len, prot | PAGE_VALID);
  the_end:
 #ifdef DEBUG_MMAP
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
index 66492aa..d354e7f 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -26,6 +26,7 @@
 
 #include "qemu.h"
 #include "qemu-common.h"
+#include "hypertrace/user.h"
 
 //#define DEBUG
 
@@ -332,6 +333,7 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
         _mcleanup();
 #endif
         gdb_exit(cpu_env, arg1);
+        hypertrace_fini();
         /* XXX: should free thread stack and CPU env */
         _exit(arg1);
         ret = 0; /* avoid warning */
@@ -369,10 +371,11 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
         unlock_user(p, arg1, 0);
         break;
     case TARGET_FREEBSD_NR_mmap:
-        ret = get_errno(target_mmap(arg1, arg2, arg3,
-                                    target_to_host_bitmask(arg4, mmap_flags_tbl),
-                                    arg5,
-                                    arg6));
+        ret = get_errno(target_mmap_cpu(arg1, arg2, arg3,
+                                        target_to_host_bitmask(arg4, mmap_flags_tbl),
+                                        arg5,
+                                        arg6,
+                                        cpu));
         break;
     case TARGET_FREEBSD_NR_mprotect:
         ret = get_errno(target_mprotect(arg1, arg2, arg3));
@@ -430,6 +433,7 @@ abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
         _mcleanup();
 #endif
         gdb_exit(cpu_env, arg1);
+        hypertrace_fini();
         /* XXX: should free thread stack and CPU env */
         _exit(arg1);
         ret = 0; /* avoid warning */
@@ -455,10 +459,11 @@ abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
         unlock_user(p, arg1, 0);
         break;
     case TARGET_NETBSD_NR_mmap:
-        ret = get_errno(target_mmap(arg1, arg2, arg3,
-                                    target_to_host_bitmask(arg4, mmap_flags_tbl),
-                                    arg5,
-                                    arg6));
+        ret = get_errno(target_mmap_cpu(arg1, arg2, arg3,
+                                        target_to_host_bitmask(arg4, mmap_flags_tbl),
+                                        arg5,
+                                        arg6,
+                                        cpu));
         break;
     case TARGET_NETBSD_NR_mprotect:
         ret = get_errno(target_mprotect(arg1, arg2, arg3));
@@ -505,6 +510,7 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
         _mcleanup();
 #endif
         gdb_exit(cpu_env, arg1);
+        hypertrace_fini();
         /* XXX: should free thread stack and CPU env */
         _exit(arg1);
         ret = 0; /* avoid warning */
@@ -530,10 +536,11 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
         unlock_user(p, arg1, 0);
         break;
     case TARGET_OPENBSD_NR_mmap:
-        ret = get_errno(target_mmap(arg1, arg2, arg3,
-                                    target_to_host_bitmask(arg4, mmap_flags_tbl),
-                                    arg5,
-                                    arg6));
+        ret = get_errno(target_mmap_cpu(arg1, arg2, arg3,
+                                        target_to_host_bitmask(arg4, mmap_flags_tbl),
+                                        arg5,
+                                        arg6,
+                                        cpu));
         break;
     case TARGET_OPENBSD_NR_mprotect:
         ret = get_errno(target_mprotect(arg1, arg2, arg3));
diff --git a/hypertrace/Makefile.objs b/hypertrace/Makefile.objs
new file mode 100644
index 0000000..24e8fb4
--- /dev/null
+++ b/hypertrace/Makefile.objs
@@ -0,0 +1,18 @@
+# -*- mode: makefile -*-
+
+target-obj-$(CONFIG_USER_ONLY) += user.o
+target-obj-y += common.o
+
+$(obj)/user.o: $(obj)/emit.c
+
+$(obj)/emit.c: $(obj)/emit.c-timestamp $(BUILD_DIR)/config-host.mak
+	@cmp $< $@ >/dev/null 2>&1 || cp $< $@
+$(obj)/emit.c-timestamp: $(BUILD_DIR)/config-host.mak
+	@echo "static void hypertrace_emit(CPUState *cpu, uint64_t arg1, uint64_t *data)" >$@
+	@echo "{" >>$@
+	@echo -n "    trace_guest_hypertrace(cpu, arg1" >>$@
+	@for i in `seq $$(( $(CONFIG_HYPERTRACE_ARGS) - 1 ))`; do \
+	    echo -n ", data[$$i-1]" >>$@; \
+	done
+	@echo ");" >>$@
+	@echo "}" >>$@
diff --git a/hypertrace/common.c b/hypertrace/common.c
new file mode 100644
index 0000000..baca098
--- /dev/null
+++ b/hypertrace/common.c
@@ -0,0 +1,26 @@
+/*
+ * QEMU-side management of hypertrace in user-level emulation.
+ *
+ * Copyright (C) 2016 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "hypertrace/common.h"
+#include "qemu/osdep.h"
+
+void hypertrace_init_config(struct hypertrace_config *config,
+                            unsigned int max_clients)
+{
+    config->max_clients = max_clients;
+    config->client_args = CONFIG_HYPERTRACE_ARGS;
+    config->client_data_size = config->client_args * sizeof(uint64_t);
+    config->control_size = QEMU_ALIGN_UP(
+        config->max_clients * sizeof(uint64_t), TARGET_PAGE_SIZE);
+    config->data_size = QEMU_ALIGN_UP(
+        config->max_clients * config->client_data_size, TARGET_PAGE_SIZE);
+}
diff --git a/hypertrace/common.h b/hypertrace/common.h
new file mode 100644
index 0000000..dfce161
--- /dev/null
+++ b/hypertrace/common.h
@@ -0,0 +1,24 @@
+/*
+ * QEMU-side management of hypertrace in user-level emulation.
+ *
+ * Copyright (C) 2016 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#if !defined(__KERNEL__)
+#include <stdint.h>
+#endif
+
+struct hypertrace_config
+{
+    uint64_t max_clients;
+    uint64_t client_args;
+    uint64_t client_data_size;
+    uint64_t control_size;
+    uint64_t data_size;
+};
+
+void hypertrace_init_config(struct hypertrace_config *config,
+                            unsigned int max_clients);
diff --git a/hypertrace/user.c b/hypertrace/user.c
new file mode 100644
index 0000000..0e07283
--- /dev/null
+++ b/hypertrace/user.c
@@ -0,0 +1,339 @@
+/*
+ * QEMU-side management of hypertrace in user-level emulation.
+ *
+ * Copyright (C) 2016 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+/*
+ * Implementation details
+ * ======================
+ *
+ * There are 3 channels, each a regular file in the host system, and mmap'ed by
+ * the guest application.
+ *
+ * - Configuration channel: Exposes configuration parameters. Mapped once and
+ *   directly readable.
+ *
+ * - Data channel: Lets guests write argument values. Each guest thread should
+ *   use a different offset to avoid concurrency problems. Mapped once and
+ *   directly accessible.
+ *
+ * - Control channel: Triggers the hypertrace event on a write, providing the
+ *   first argument. Offset in the control channel sets the offset in the data
+ *   channel. Mapped once per thread, using two pages to reliably detect
+ *   accesses and their written value through a SEGV handler.
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+
+#include "hypertrace/common.h"
+#include "hypertrace/user.h"
+#include "qemu/config-file.h"
+#include "qemu/error-report.h"
+#include "trace.h"
+
+
+static struct hypertrace_config config;
+static char *config_path = NULL;
+static int config_fd = -1;
+static uint64_t *qemu_config = NULL;
+
+static char *data_path = NULL;
+static int data_fd = -1;
+static uint64_t *qemu_data = NULL;
+
+static char *control_path = NULL;
+static int control_fd = -1;
+static uint64_t *qemu_control = NULL;
+static struct stat control_fd_stat;
+
+struct sigaction segv_next;
+static void segv_handler(int signum, siginfo_t *siginfo, void *sigctxt);
+
+
+QemuOptsList qemu_hypertrace_opts = {
+    .name = "hypertrace",
+    .implied_opt_name = "path",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_hypertrace_opts.head),
+    .desc = {
+        {
+            .name = "path",
+            .type = QEMU_OPT_STRING,
+        },
+        {
+            .name = "max-clients",
+            .type = QEMU_OPT_NUMBER,
+            .def_value_str = "1",
+        },
+        { /* end of list */ }
+    },
+};
+
+void hypertrace_opt_parse(const char *optarg, char **base, unsigned int *max_clients_)
+{
+    int max_clients;
+    QemuOpts *opts = qemu_opts_parse_noisily(qemu_find_opts("hypertrace"),
+                                             optarg, true);
+    if (!opts) {
+        exit(1);
+    }
+    if (qemu_opt_get(opts, "path")) {
+        *base = g_strdup(qemu_opt_get(opts, "path"));
+    } else {
+        *base = NULL;
+    }
+    max_clients = qemu_opt_get_number(opts, "pages", 1);
+    if (max_clients <= 0) {
+        error_report("Parameter 'max-clients' expects a positive number");
+        exit(EXIT_FAILURE);
+    }
+    *max_clients_ = max_clients;
+}
+
+static void init_channel(const char *base, const char *suffix, size_t size,
+                         char ** path, int *fd, uint64_t **addr)
+{
+    *path = g_malloc(strlen(base) + strlen(suffix) + 1);
+    sprintf(*path, "%s%s", base, suffix);
+
+    *fd = open(*path, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
+    if (*fd == -1) {
+        error_report("error: open(%s): %s", *path, strerror(errno));
+        abort();
+    }
+
+    off_t lres = lseek(*fd, size - 1, SEEK_SET);
+    if (lres == (off_t)-1) {
+        error_report("error: lseek(%s): %s", *path, strerror(errno));
+        abort();
+    }
+
+    char tmp;
+    ssize_t wres = write(*fd, &tmp, 1);
+    if (wres == -1) {
+        error_report("error: write(%s): %s", *path, strerror(errno));
+        abort();
+    }
+
+    if (addr) {
+        *addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0);
+        if (*addr == MAP_FAILED) {
+            error_report("error: mmap(%s): %s", *path, strerror(errno));
+            abort();
+        }
+    }
+}
+
+static void fini_handler(int signum, siginfo_t *siginfo, void *sigctxt)
+{
+    hypertrace_fini();
+}
+
+void hypertrace_init(const char *base, unsigned int max_clients)
+{
+    struct sigaction sigint;
+    struct hypertrace_config *pconfig;
+
+    if (base == NULL) {
+        return;
+    }
+
+    memset(&sigint, 0, sizeof(sigint));
+    sigint.sa_sigaction = fini_handler;
+    sigint.sa_flags = SA_SIGINFO | SA_RESTART;
+    if (sigaction(SIGINT, &sigint, NULL) != 0) {
+        error_report("error: sigaction(SIGINT): %s", strerror(errno));
+        abort();
+    }
+    if (sigaction(SIGABRT, &sigint, NULL) != 0) {
+        error_report("error: sigaction(SIGABRT): %s", strerror(errno));
+        abort();
+    }
+
+    hypertrace_init_config(&config, max_clients);
+    /* We need twice the space for the double-fault protocol */
+    config.control_size *= 2;
+
+    init_channel(base, "-config", TARGET_PAGE_SIZE, &config_path, &config_fd, &qemu_config);
+    pconfig = (struct hypertrace_config*)qemu_config;
+    pconfig->max_clients = tswap64(config.max_clients);
+    pconfig->client_args = tswap64(config.client_args);
+    pconfig->client_data_size = tswap64(config.client_data_size);
+    pconfig->control_size = tswap64(config.control_size);
+    pconfig->data_size = tswap64(config.data_size);
+
+    init_channel(base, "-data", config.data_size, &data_path, &data_fd, &qemu_data);
+    if (fstat(data_fd, &control_fd_stat) == -1) {
+        error_report("error: fstat(hypertrace_control): %s", strerror(errno));
+        abort();
+    }
+    printf("data: dev=%ld ino=%ld ptr=%p\n",
+           control_fd_stat.st_dev, control_fd_stat.st_ino, qemu_data);
+
+    init_channel(base, "-control", config.control_size, &control_path, &control_fd, &qemu_control);
+
+    if (fstat(control_fd, &control_fd_stat) == -1) {
+        error_report("error: fstat(hypertrace_control): %s", strerror(errno));
+        abort();
+    }
+    printf("control: dev=%ld ino=%ld ptr=%p\n",
+           control_fd_stat.st_dev, control_fd_stat.st_ino, qemu_control);
+
+    struct sigaction segv;
+    memset(&segv, 0, sizeof(segv));
+    segv.sa_sigaction = segv_handler;
+    segv.sa_flags = SA_SIGINFO | SA_RESTART;
+    sigemptyset(&segv.sa_mask);
+
+    if (sigaction(SIGSEGV, &segv, &segv_next) != 0) {
+        error_report("error: sigaction(SIGSEGV): %s", strerror(errno));
+        abort();
+    }
+}
+
+
+static void fini_channel(int *fd, char **path)
+{
+    if (*fd != -1) {
+        if (close(*fd) == -1) {
+            error_report("error: close: %s", strerror(errno));
+            abort();
+        }
+        if (unlink(*path) == -1) {
+            error_report("error: unlink(%s): %s", *path, strerror(errno));
+            abort();
+        }
+        *fd = -1;
+    }
+    if (*path != NULL) {
+        g_free(*path);
+        *path =  NULL;
+    }
+}
+
+void hypertrace_fini(void)
+{
+    static bool atexit_in = false;
+    if (atexit_in) {
+        return;
+    }
+    atexit_in = true;
+
+    if (sigaction(SIGSEGV, &segv_next, NULL) != 0) {
+        error_report("error: sigaction(SIGSEGV): %s", strerror(errno));
+        abort();
+    }
+    fini_channel(&config_fd, &config_path);
+    fini_channel(&data_fd, &data_path);
+    fini_channel(&control_fd, &control_path);
+}
+
+
+bool hypertrace_guest_mmap_check(int fd, unsigned long len, unsigned long offset)
+{
+    struct stat s;
+    if (fstat(fd, &s) < 0) {
+        return true;
+    }
+
+    if (s.st_dev != control_fd_stat.st_dev ||
+        s.st_ino != control_fd_stat.st_ino) {
+        return true;
+    }
+
+    return len == (config.control_size) && offset == 0;
+}
+
+void hypertrace_guest_mmap_apply(int fd, void *qemu_addr, CPUState *vcpu)
+{
+    struct stat s;
+
+    if (vcpu == NULL) {
+        return;
+    }
+
+    if (fstat(fd, &s) != 0) {
+        return;
+    }
+
+    if (s.st_dev != control_fd_stat.st_dev ||
+        s.st_ino != control_fd_stat.st_ino) {
+        return;
+    }
+
+    /* it's an mmap of the control channel; split it in two and mprotect it to
+     * detect writes (cmd is written once on each part)
+     */
+    printf("cpu->hypertrace_control=%p %lu %lu\n", qemu_addr, s.st_dev, s.st_ino);
+    vcpu->hypertrace_control = qemu_addr;
+    if (mprotect(vcpu->hypertrace_control, config.control_size / 2, PROT_READ) == -1) {
+        error_report("error: mprotect(hypertrace_control): %s", strerror(errno));
+        abort();
+    }
+}
+
+static void swap_control(void *from, void *to)
+{
+    printf("mprotect: RW %p %lu\n", from, config.control_size / 2);
+    if (mprotect(from, config.control_size / 2, PROT_READ | PROT_WRITE) == -1) {
+        error_report("error: mprotect(from): %s", strerror(errno));
+        abort();
+    }
+    printf("mprotect: R  %p %lu\n", to, config.control_size / 2);
+    if (mprotect(to, config.control_size / 2, PROT_READ) == -1) {
+        error_report("error: mprotect(to): %s", strerror(errno));
+        abort();
+    }
+}
+
+#include "hypertrace/emit.c"
+
+static void segv_handler(int signum, siginfo_t *siginfo, void *sigctxt)
+{
+    CPUState *vcpu = current_cpu;
+    void *control_0 = vcpu->hypertrace_control;
+    void *control_1 = vcpu->hypertrace_control + config.control_size / 2;
+    void *control_2 = control_1 + config.control_size / 2;
+
+    if (control_0 <= siginfo->si_addr && siginfo->si_addr < control_1) {
+
+        /* 1st fault (guest will write cmd) */
+        printf("SEGV 1\n");
+        assert(((unsigned long)siginfo->si_addr % sizeof(uint64_t)) == 0);
+        swap_control(control_0, control_1);
+        printf("SEGV 1!\n");
+
+    } else if (control_1 <= siginfo->si_addr && siginfo->si_addr < control_2) {
+        size_t client = (siginfo->si_addr - control_1) / sizeof(uint64_t);
+        uint64_t vcontrol = ((uint64_t*)control_0)[client];
+        uint64_t *data_ptr = &qemu_data[client * config.client_data_size];
+
+        /* 2nd fault (invoke) */
+        printf("SEGV 2\n");
+        assert(((unsigned long)siginfo->si_addr % sizeof(uint64_t)) == 0);
+        hypertrace_emit(current_cpu, vcontrol, data_ptr);
+        swap_control(control_1, control_0);
+        printf("SEGV 2!\n");
+
+    } else {
+        /* proxy to next handler */
+        printf("SEGV ?\n");
+        if (segv_next.sa_sigaction != NULL) {
+            segv_next.sa_sigaction(signum, siginfo, sigctxt);
+        } else if (segv_next.sa_handler != NULL) {
+            segv_next.sa_handler(signum);
+        }
+        printf("SEGV ?!\n");
+    }
+}
diff --git a/hypertrace/user.h b/hypertrace/user.h
new file mode 100644
index 0000000..9c1f44b
--- /dev/null
+++ b/hypertrace/user.h
@@ -0,0 +1,61 @@
+/*
+ * QEMU-side management of hypertrace in user-level emulation.
+ *
+ * Copyright (C) 2016 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+
+/**
+ * Definition of QEMU options describing hypertrace subsystem configuration
+ */
+extern QemuOptsList qemu_hypertrace_opts;
+
+/**
+ * hypertrace_opt_parse:
+ * @optarg: Input arguments.
+ * @base: Output base path for the hypertrace channel files.
+ * @max_clients: Output maximum number of concurrent clients.
+ *
+ * Parse the commandline arguments for hypertrace.
+ */
+void hypertrace_opt_parse(const char *optarg, char **base, unsigned int *max_clients);
+
+/**
+ * hypertrace_init:
+ * @base: Base path for the hypertrace channel files.
+ * @max_clients: Maximum number of concurrent clients.
+ *
+ * Initialize the backing files for the hypertrace channel.
+ */
+void hypertrace_init(const char *base, unsigned int max_clients);
+
+/**
+ * hypertrace_guest_mmap_check:
+ *
+ * Verify argument validity when mapping the control channel.
+ *
+ * Precondition: defined(CONFIG_USER_ONLY)
+ */
+bool hypertrace_guest_mmap_check(int fd, unsigned long len, unsigned long offset);
+
+/**
+ * hypertrace_guest_mmap_apply:
+ *
+ * Configure initial mprotect if mapping the control channel.
+ *
+ * Precondition: defined(CONFIG_USER_ONLY)
+ */
+void hypertrace_guest_mmap_apply(int fd, void *qemu_addr, CPUState *vcpu);
+
+/**
+ * hypertrace_fini:
+ *
+ * Remove the backing files for the hypertrace channel.
+ */
+void hypertrace_fini(void);
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index ce0c406..c83570a 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -283,6 +283,7 @@ struct qemu_work_item {
  * @work_mutex: Lock to prevent multiple access to queued_work_*.
  * @queued_work_first: First asynchronous work pending.
  * @trace_dstate: Dynamic tracing state of events for this vCPU (bitmask).
+ * @hypertrace_control: Per-vCPU address of the hypertrace control channel.
  *
  * State of one CPU core or thread.
  */
@@ -353,6 +354,9 @@ struct CPUState {
     /* Used for events with 'vcpu' and *without* the 'disabled' properties */
     DECLARE_BITMAP(trace_dstate, TRACE_VCPU_EVENT_COUNT);
 
+    /* Only used when defined(CONFIG_USER_ONLY) */
+    void *hypertrace_control;
+
     /* TODO Move common fields from CPUArchState here. */
     int cpu_index; /* used by alpha TCG */
     uint32_t halted; /* used by alpha, cris, ppc TCG */
diff --git a/linux-user/main.c b/linux-user/main.c
index f2f4d2f..5316a25 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -32,10 +32,12 @@
 #include "tcg.h"
 #include "qemu/timer.h"
 #include "qemu/envlist.h"
+#include "qemu/error-report.h"
 #include "elf.h"
 #include "exec/log.h"
 #include "trace/control.h"
 #include "glib-compat.h"
+#include "hypertrace/user.h"
 
 char *exec_path;
 
@@ -4011,6 +4013,14 @@ static void handle_arg_trace(const char *arg)
     trace_file = trace_opt_parse(arg);
 }
 
+static char *hypertrace_base;
+static unsigned int hypertrace_max_clients;
+static void handle_arg_hypertrace(const char *arg)
+{
+    g_free(hypertrace_base);
+    hypertrace_opt_parse(arg, &hypertrace_base, &hypertrace_max_clients);
+}
+
 struct qemu_argument {
     const char *argv;
     const char *env;
@@ -4060,6 +4070,8 @@ static const struct qemu_argument arg_table[] = {
      "",           "Seed for pseudo-random number generator"},
     {"trace",      "QEMU_TRACE",       true,  handle_arg_trace,
      "",           "[[enable=]<pattern>][,events=<file>][,file=<file>]"},
+    {"hypertrace", "QEMU_HYPERTRACE",  true,  handle_arg_hypertrace,
+     "",           "[[base=]<path>][,max-clients=<uint>]"},
     {"version",    "QEMU_VERSION",     false, handle_arg_version,
      "",           "display version information and exit"},
     {NULL, NULL, false, NULL, NULL, NULL}
@@ -4250,6 +4262,7 @@ int main(int argc, char **argv, char **envp)
     srand(time(NULL));
 
     qemu_add_opts(&qemu_trace_opts);
+    qemu_add_opts(&qemu_hypertrace_opts);
 
     optind = parse_args(argc, argv);
 
@@ -4448,6 +4461,12 @@ int main(int argc, char **argv, char **envp)
     syscall_init();
     signal_init();
 
+    if (atexit(hypertrace_fini)) {
+        fprintf(stderr, "error: atexit: %s\n", strerror(errno));
+        abort();
+    }
+    hypertrace_init(hypertrace_base, hypertrace_max_clients);
+
     /* Now that we've loaded the binary, GUEST_BASE is fixed.  Delay
        generating the prologue until now so that the prologue can take
        the real value of GUEST_BASE into account.  */
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index c4371d9..cfb159c 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -23,6 +23,7 @@
 #include "qemu.h"
 #include "qemu-common.h"
 #include "translate-all.h"
+#include "hypertrace/user.h"
 
 //#define DEBUG_MMAP
 
@@ -357,10 +358,18 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
     }
 }
 
-/* NOTE: all the constants are the HOST ones */
 abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
                      int flags, int fd, abi_ulong offset)
 {
+    return target_mmap_cpu(start, len, prot, flags, fd, offset, NULL);
+}
+
+
+/* NOTE: all the constants are the HOST ones */
+abi_long target_mmap_cpu(abi_ulong start, abi_ulong len, int prot,
+                         int flags, int fd, abi_ulong offset,
+                         CPUState *cpu)
+{
     abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
 
     mmap_lock();
@@ -442,6 +451,10 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
        }
     }
 
+    if (!hypertrace_guest_mmap_check(fd, len, offset)) {
+        goto fail;
+    }
+
     if (!(flags & MAP_FIXED)) {
         unsigned long host_start;
         void *p;
@@ -553,6 +566,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
         }
     }
  the_end1:
+    printf("mmap "TARGET_ABI_FMT_lx" "TARGET_ABI_FMT_lu"\n", start, len);
+    hypertrace_guest_mmap_apply(fd, g2h(start), cpu);
     page_set_flags(start, start + len, prot | PAGE_VALID);
  the_end:
 #ifdef DEBUG_MMAP
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index bef465d..968a6b4 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -411,6 +411,9 @@ void sparc64_get_context(CPUSPARCState *env);
 int target_mprotect(abi_ulong start, abi_ulong len, int prot);
 abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
                      int flags, int fd, abi_ulong offset);
+abi_long target_mmap_cpu(abi_ulong start, abi_ulong len, int prot,
+                         int flags, int fd, abi_ulong offset,
+                         CPUState *cpu);
 int target_munmap(abi_ulong start, abi_ulong len);
 abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
                        abi_ulong new_size, unsigned long flags,
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ca06943..3e8d8fd 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -111,6 +111,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
 #include "uname.h"
 
 #include "qemu.h"
+#include "hypertrace/user.h"
 
 #define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
     CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
@@ -7372,6 +7373,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         _mcleanup();
 #endif
         gdb_exit(cpu_env, arg1);
+        hypertrace_fini();
         _exit(arg1);
         ret = 0; /* avoid warning */
         break;
@@ -8824,15 +8826,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             v5 = tswapal(v[4]);
             v6 = tswapal(v[5]);
             unlock_user(v, arg1, 0);
-            ret = get_errno(target_mmap(v1, v2, v3,
-                                        target_to_host_bitmask(v4, mmap_flags_tbl),
-                                        v5, v6));
+            ret = get_errno(target_mmap_cpu(
+                                v1, v2, v3,
+                                target_to_host_bitmask(v4, mmap_flags_tbl),
+                                v5, v6,
+                                cpu));
         }
 #else
-        ret = get_errno(target_mmap(arg1, arg2, arg3,
-                                    target_to_host_bitmask(arg4, mmap_flags_tbl),
-                                    arg5,
-                                    arg6));
+        ret = get_errno(target_mmap_cpu(
+                            arg1, arg2, arg3,
+                            target_to_host_bitmask(arg4, mmap_flags_tbl),
+                            arg5,
+                            arg6,
+                            cpu));
 #endif
         break;
 #endif
@@ -8841,10 +8847,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #ifndef MMAP_SHIFT
 #define MMAP_SHIFT 12
 #endif
-        ret = get_errno(target_mmap(arg1, arg2, arg3,
-                                    target_to_host_bitmask(arg4, mmap_flags_tbl),
-                                    arg5,
-                                    arg6 << MMAP_SHIFT));
+        ret = get_errno(target_mmap_cpu(
+                            arg1, arg2, arg3,
+                            target_to_host_bitmask(arg4, mmap_flags_tbl),
+                            arg5,
+                            arg6 << MMAP_SHIFT,
+                            cpu));
         break;
 #endif
     case TARGET_NR_munmap:
@@ -9377,6 +9385,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         _mcleanup();
 #endif
         gdb_exit(cpu_env, arg1);
+        hypertrace_fini();
         ret = get_errno(exit_group(arg1));
         break;
 #endif

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

* [Qemu-devel] [PATCH v2 4/6] hypertrace: [softmmu] Add QEMU-side proxy to "guest_hypertrace" event
  2016-09-05 18:56 [Qemu-devel] [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel Lluís Vilanova
                   ` (2 preceding siblings ...)
  2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 3/6] hypertrace: [*-user] Add QEMU-side proxy to "guest_hypertrace" event Lluís Vilanova
@ 2016-09-05 18:56 ` Lluís Vilanova
  2016-09-06  1:43   ` Michael S. Tsirkin
  2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 5/6] hypertrace: Add guest-side user-level library Lluís Vilanova
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Lluís Vilanova @ 2016-09-05 18:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P Berrange, Luiz Capitulino, Eric Blake, Stefan Hajnoczi,
	Michael S. Tsirkin, Marcel Apfelbaum

Uses a virtual device to trigger the hypertrace channel event.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 hypertrace/Makefile.objs |    5 +
 hypertrace/softmmu.c     |  235 ++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/pci/pci.h     |    2 
 3 files changed, 241 insertions(+), 1 deletion(-)
 create mode 100644 hypertrace/softmmu.c

diff --git a/hypertrace/Makefile.objs b/hypertrace/Makefile.objs
index 24e8fb4..0025207 100644
--- a/hypertrace/Makefile.objs
+++ b/hypertrace/Makefile.objs
@@ -1,9 +1,12 @@
 # -*- mode: makefile -*-
 
 target-obj-$(CONFIG_USER_ONLY) += user.o
+ifdef CONFIG_PCI
+target-obj-$(CONFIG_SOFTMMU) += softmmu.o
+endif
 target-obj-y += common.o
 
-$(obj)/user.o: $(obj)/emit.c
+$(obj)/user.o $(obj)/softmmu.o: $(obj)/emit.c
 
 $(obj)/emit.c: $(obj)/emit.c-timestamp $(BUILD_DIR)/config-host.mak
 	@cmp $< $@ >/dev/null 2>&1 || cp $< $@
diff --git a/hypertrace/softmmu.c b/hypertrace/softmmu.c
new file mode 100644
index 0000000..ca4d1ad
--- /dev/null
+++ b/hypertrace/softmmu.c
@@ -0,0 +1,235 @@
+/*
+ * QEMU-side management of hypertrace in softmmu emulation.
+ *
+ * Copyright (C) 2016 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+/*
+ * Implementation details
+ * ======================
+ *
+ * There are 3 channels, each a BAR of a virtual device that can be used through
+ * MMIO.
+ *
+ *
+ * - Configuration channel: Exposes configuration parameters.
+ *
+ * - Data channel: Lets guests write argument values. Each guest client should
+ *   use a different offset to avoid concurrency problems.
+ *
+ * - Control channel: Triggers the hypertrace event on a write, providing the
+ *   first argument. Offset in the control channel sets the offset in the data
+ *   channel.
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/ram_addr.h"
+#include "hypertrace/common.h"
+#include "hw/pci/pci.h"
+#include "migration/migration.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "trace.h"
+
+
+#define PAGE_SIZE TARGET_PAGE_SIZE
+
+
+typedef struct HypertraceState
+{
+    PCIDevice dev;
+
+    uint64_t max_clients;
+    struct hypertrace_config hconfig;
+
+    MemoryRegion config;
+    void *config_ptr;
+    MemoryRegion data;
+    void *data_ptr;
+    MemoryRegion control;
+    void *control_ptr;
+
+    Error *migration_blocker;
+} HypertraceState;
+
+
+static uint64_t hypertrace_control_io_read(void *opaque, hwaddr addr,
+                                           unsigned size)
+{
+    uint64_t res;
+    HypertraceState *s = opaque;
+    char *mem = &((char*)s->control_ptr)[addr];
+
+    switch (size) {
+    case 1:
+    {
+        res = ((uint8_t*)mem)[0];
+        break;
+    }
+    case 2:
+    {
+        res = ((uint16_t*)mem)[0];
+        break;
+    }
+    case 4:
+    {
+        res = ((uint32_t*)mem)[0];
+        break;
+    }
+    case 8:
+    {
+        res = ((uint64_t*)mem)[0];
+        break;
+    }
+    default:
+        error_report("error: hypertrace: Unexpected read of size %d\n", size);
+    }
+
+    return res;
+}
+
+#include "hypertrace/emit.c"
+
+static void hypertrace_control_io_write(void *opaque, hwaddr addr,
+                                        uint64_t data, unsigned size)
+{
+    HypertraceState *s = opaque;
+    char *mem = &((char*)s->control_ptr)[addr];
+
+    switch (size) {
+    case 1:
+    {
+        uint8_t *res = (uint8_t*)mem;
+        *res = (uint8_t)data;
+        break;
+    }
+    case 2:
+    {
+        uint16_t *res = (uint16_t*)mem;
+        *res = (uint16_t)data;
+        break;
+    }
+    case 4:
+    {
+        uint32_t *res = (uint32_t*)mem;
+        *res = (uint32_t)data;
+        break;
+    }
+    case 8:
+    {
+        uint64_t *res = (uint64_t*)mem;
+        *res = (uint64_t)data;
+        break;
+    }
+    default:
+        error_report("error: hypertrace: Unexpected write of size %d\n", size);
+    }
+
+    if ((addr + size) % sizeof(uint64_t) == 0) {
+        uint64_t client = addr / sizeof(uint64_t);
+        uint64_t vcontrol = ((uint64_t*)s->control_ptr)[client];
+        uint64_t *data_ptr = (uint64_t*)s->data_ptr;
+        data_ptr = &data_ptr[client * s->hconfig.client_data_size];
+        hypertrace_emit(current_cpu, vcontrol, data_ptr);
+    }
+}
+
+static const MemoryRegionOps hypertrace_control_ops = {
+    .read = &hypertrace_control_io_read,
+    .write = &hypertrace_control_io_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 8,
+    },
+};
+
+
+static void hypertrace_realize(PCIDevice *dev, Error **errp)
+{
+    struct hypertrace_config *config;
+    HypertraceState *s = DO_UPCAST(HypertraceState, dev, dev);
+    Error *err = NULL;
+
+    if (s->max_clients < 1) {
+        error_setg(errp, "hypertrace: must have at least one client\n");
+        return;
+    }
+
+    hypertrace_init_config(&s->hconfig, s->max_clients);
+
+    error_setg(&s->migration_blocker, "The 'hypertrace' device cannot be migrated");
+    migrate_add_blocker(s->migration_blocker);
+
+    pci_set_word(s->dev.config + PCI_COMMAND,
+                 PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+
+    /* config channel */
+    memory_region_init_ram(&s->config, OBJECT(s), "hypertrace.config",
+                           TARGET_PAGE_SIZE, &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->config);
+    s->config_ptr = qemu_map_ram_ptr(s->config.ram_block, 0);
+    config = s->config_ptr;
+    config->max_clients = tswap64(s->hconfig.max_clients);
+    config->client_args = tswap64(s->hconfig.client_args);
+    config->client_data_size = tswap64(s->hconfig.client_data_size);
+    config->control_size = tswap64(s->hconfig.control_size);
+    config->data_size = tswap64(s->hconfig.data_size);
+
+    /* data channel */
+    memory_region_init_ram(&s->data, OBJECT(s), "hypertrace.data",
+                           s->hconfig.data_size, &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->data);
+    s->data_ptr = qemu_map_ram_ptr(s->data.ram_block, 0);
+
+    /* control channel */
+    memory_region_init_io(&s->control, OBJECT(s), &hypertrace_control_ops, s,
+                          "hypertrace.control", s->hconfig.control_size);
+    pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->control);
+    s->control_ptr = qemu_map_ram_ptr(s->control.ram_block, 0);
+}
+
+
+static Property hypertrace_properties[] = {
+    DEFINE_PROP_UINT64("max-clients", HypertraceState, max_clients, 1),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void hypertrace_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->realize = hypertrace_realize;
+    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    k->device_id = PCI_DEVICE_ID_HYPERTRACE;
+    k->class_id = PCI_CLASS_MEMORY_RAM;
+    dc->desc  = "Hypertrace communication channel",
+    dc->props = hypertrace_properties;
+}
+
+static TypeInfo hypertrace_info = {
+    .name          = "hypertrace",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(HypertraceState),
+    .class_init    = hypertrace_class_init,
+};
+
+static void hypertrace_register_types(void)
+{
+    type_register_static(&hypertrace_info);
+}
+
+type_init(hypertrace_register_types)
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 929ec2f..8973f57 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -80,6 +80,8 @@
 #define PCI_DEVICE_ID_VIRTIO_RNG         0x1005
 #define PCI_DEVICE_ID_VIRTIO_9P          0x1009
 
+#define PCI_DEVICE_ID_HYPERTRACE         0x10f0
+
 #define PCI_VENDOR_ID_REDHAT             0x1b36
 #define PCI_DEVICE_ID_REDHAT_BRIDGE      0x0001
 #define PCI_DEVICE_ID_REDHAT_SERIAL      0x0002

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

* [Qemu-devel] [PATCH v2 5/6] hypertrace: Add guest-side user-level library
  2016-09-05 18:56 [Qemu-devel] [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel Lluís Vilanova
                   ` (3 preceding siblings ...)
  2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 4/6] hypertrace: [softmmu] " Lluís Vilanova
@ 2016-09-05 18:56 ` Lluís Vilanova
  2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 6/6] hypertrace: Add guest-side Linux module Lluís Vilanova
  2016-09-05 19:23 ` [Qemu-devel] [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel no-reply
  6 siblings, 0 replies; 14+ messages in thread
From: Lluís Vilanova @ 2016-09-05 18:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P Berrange, Luiz Capitulino, Eric Blake, Stefan Hajnoczi

Provides guest library "libqemu-hypertrace-guest.a" to abstract access
to the hypertrace channel.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 Makefile                                |    6 +
 configure                               |    2 
 hypertrace/guest/user/Makefile          |   30 +++
 hypertrace/guest/user/common.c          |  301 +++++++++++++++++++++++++++++++
 hypertrace/guest/user/qemu-hypertrace.h |   80 ++++++++
 5 files changed, 418 insertions(+), 1 deletion(-)
 create mode 100644 hypertrace/guest/user/Makefile
 create mode 100644 hypertrace/guest/user/common.c
 create mode 100644 hypertrace/guest/user/qemu-hypertrace.h

diff --git a/Makefile b/Makefile
index 50b4b3a..8fb469b 100644
--- a/Makefile
+++ b/Makefile
@@ -460,9 +460,13 @@ ifneq (,$(findstring qemu-ga,$(TOOLS)))
 endif
 endif
 
+install-hypertrace:
+	$(INSTALL_DIR) "$(DESTDIR)$(includedir)"
+	$(INSTALL_DATA) "$(SRC_PATH)/hypertrace/guest/user/qemu-hypertrace.h" "$(DESTDIR)$(includedir)/"
+
 
 install: all $(if $(BUILD_DOCS),install-doc) \
-install-datadir install-localstatedir
+install-datadir install-localstatedir install-hypertrace
 ifneq ($(TOOLS),)
 	$(call install-prog,$(subst qemu-ga,qemu-ga$(EXESUF),$(TOOLS)),$(DESTDIR)$(bindir))
 endif
diff --git a/configure b/configure
index d7ec31f..ad83fff 100755
--- a/configure
+++ b/configure
@@ -5793,6 +5793,8 @@ if [ "$TARGET_BASE_ARCH" = "" ]; then
 fi
 
 symlink "$source_path/Makefile.target" "$target_dir/Makefile"
+mkdir -p $target_dir/hypertrace/guest/user
+symlink $source_path/hypertrace/guest/user/Makefile $target_dir/hypertrace/guest/user/Makefile
 
 upper() {
     echo "$@"| LC_ALL=C tr '[a-z]' '[A-Z]'
diff --git a/hypertrace/guest/user/Makefile b/hypertrace/guest/user/Makefile
new file mode 100644
index 0000000..85d0839
--- /dev/null
+++ b/hypertrace/guest/user/Makefile
@@ -0,0 +1,30 @@
+include ../../../../config-host.mak
+include ../../../config-target.mak
+include $(SRC_PATH)/rules.mak
+
+vpath % $(SRC_PATH)/hypertrace/guest/user
+
+# do not use QEMU's per-host cflags when building guest code
+QEMU_CFLAGS  = -Werror -Wall
+
+QEMU_CFLAGS += $(GLIB_CFLAGS)
+QEMU_CFLAGS += -I$(SRC_PATH)/include
+QEMU_CFLAGS += -I../../../../linux-headers
+QEMU_CFLAGS += -I../../../../
+QEMU_CFLAGS += -I../../../
+
+ifdef CONFIG_SOFTMMU
+QEMU_CFLAGS += -DNEED_CPU_H
+QEMU_CFLAGS += -I$(SRC_PATH)/target-$(TARGET_BASE_ARCH)
+endif
+
+QEMU_CFLAGS += -g -O2
+
+obj-y = common.o
+
+libqemu-hypertrace-guest.a: $(obj-y)
+
+all: libqemu-hypertrace-guest.a
+
+clean:
+	rm -f $(obj-y) libqemu-hypertrace-guest.a
diff --git a/hypertrace/guest/user/common.c b/hypertrace/guest/user/common.c
new file mode 100644
index 0000000..cf14386
--- /dev/null
+++ b/hypertrace/guest/user/common.c
@@ -0,0 +1,301 @@
+/*
+ * Guest-side management of hypertrace.
+ *
+ * Copyright (C) 2016 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu-hypertrace.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <glob.h>
+
+#include "config-host.h"
+#include "config-target.h"
+#if defined(CONFIG_SOFTMMU)
+#include "qemu/osdep.h"
+#include "hw/pci/pci.h"
+#endif
+#include "hypertrace/common.h"
+
+static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static char *config_path = NULL;
+static int config_fd = -1;
+static uint64_t *config_addr = NULL;
+static struct hypertrace_config *config = NULL;
+
+
+static char *data_path = NULL;
+static int data_fd = -1;
+static uint64_t *data_addr = NULL;
+
+static char *control_path = NULL;
+static int control_fd = -1;
+#if defined(CONFIG_USER_ONLY)
+static __thread uint64_t *control_addr = NULL;
+static __thread uint64_t *control_addr_1 = NULL;
+#else
+static uint64_t *control_addr = NULL;
+#endif
+
+
+static int init_channel_file(const char *base, const char *suffix, size_t size,
+                             char ** path, int *fd, uint64_t **addr, bool write)
+{
+    int prot;
+
+    *path = malloc(strlen(base) + strlen(suffix) + 1);
+    sprintf(*path, "%s%s", base, suffix);
+
+    prot = O_RDONLY;
+    if (write) {
+        prot = O_RDWR;
+    }
+    *fd = open(*path, prot);
+    if (*fd == -1) {
+        return -1;
+    }
+
+    printf("init: %s %ld\n", *path, size);
+    prot = PROT_READ;
+    if (write) {
+        prot |= PROT_WRITE;
+    }
+    *addr = mmap(NULL, size, prot, MAP_SHARED, *fd, 0);
+    if (*addr == MAP_FAILED) {
+        return -1;
+    }
+    return 0;
+}
+
+#if !defined(CONFIG_USER_ONLY) && defined(__linux__)
+static int check_device_id (const char *base, const char *name, uint64_t value)
+{
+    char tmp[1024];
+    sprintf(tmp, "%s/%s", base, name);
+
+    int fd = open(tmp, O_RDONLY);
+    if (fd < 0) {
+        return -1;
+    }
+
+    char v[1024];
+    ssize_t s = read(fd, v, sizeof(v));
+    if (s < 0) {
+        close(fd);
+        return -1;
+    }
+    v[s] = '\0';
+
+    char *end;
+    uint64_t vv = strtoull(v, &end, 16);
+    if (*end == '\n' && vv == value) {
+        return 0;
+    }
+    else {
+        return -1;
+    }
+}
+
+static char* find_device(void)
+{
+    static char tmp[1024];
+    char *res = NULL;
+
+    glob_t g;
+    if (glob("/sys/devices/pci*/*", GLOB_NOSORT, NULL, &g) != 0) {
+        return NULL;
+    }
+
+
+    int i;
+    for (i = 0; i < g.gl_pathc; i++) {
+        char *path = g.gl_pathv[i];
+
+        if (check_device_id(path, "vendor", PCI_VENDOR_ID_REDHAT_QUMRANET) < 0) {
+            continue;
+        }
+        if (check_device_id(path, "device", PCI_DEVICE_ID_HYPERTRACE) < 0) {
+            continue;
+        }
+
+        sprintf(tmp, "%s", path);
+        res = tmp;
+        break;
+    }
+
+    globfree(&g);
+
+    return res;
+}
+#endif
+
+int qemu_hypertrace_init(const char *base)
+{
+#if defined(CONFIG_USER_ONLY)
+    const char *config_suff = "-config";
+    const char *data_suff = "-data";
+    const char *control_suff = "-control";
+#elif defined(__linux__)
+    const char *config_suff = "/resource0";
+    const char *data_suff = "/resource1";
+    const char *control_suff = "/resource2";
+#else
+#error Unsupported OS
+#endif
+
+#if defined(CONFIG_USER_ONLY)
+    if (base == NULL) {
+        errno = ENOENT;
+        return -1;
+    }
+#elif defined(__linux__)
+    if (base == NULL) {
+        /* try to guess the base path */
+        base = find_device();
+        if (base == NULL) {
+            errno = ENOENT;
+            return -1;
+        }
+    }
+#endif
+
+    if (config_addr == NULL) {
+        printf("init config\n");
+        int res;
+
+        if (pthread_mutex_lock(&init_mutex)) {
+            return -1;
+        }
+
+        res = init_channel_file(base, config_suff, getpagesize(),
+                                &config_path, &config_fd, &config_addr,
+                                false);
+        if (res != 0) {
+            return res;
+        }
+
+        config = (struct hypertrace_config*)config_addr;
+
+        if (pthread_mutex_unlock(&init_mutex)) {
+            return -1;
+        }
+    }
+
+    if (data_addr == NULL) {
+        printf("init data\n");
+        int res;
+
+        if (pthread_mutex_lock(&init_mutex)) {
+            return -1;
+        }
+
+        res = init_channel_file(base, data_suff, config->data_size,
+                                &data_path, &data_fd, &data_addr,
+                                true);
+        if (res != 0) {
+            return res;
+        }
+
+        if (pthread_mutex_unlock(&init_mutex)) {
+            return -1;
+        }
+    }
+
+    if (control_addr == NULL) {
+        printf("init control\n");
+        int res;
+        uint64_t control_size = config->control_size;
+
+        if (pthread_mutex_lock(&init_mutex)) {
+            return -1;
+        }
+
+        res = init_channel_file(base, control_suff, control_size,
+                                &control_path, &control_fd, &control_addr,
+                                true);
+        if (res != 0) {
+            return res;
+        }
+
+#if defined(CONFIG_USER_ONLY)
+        control_addr_1 = (uint64_t*)((char*)control_addr + config->control_size / 2);
+#endif
+
+        if (pthread_mutex_unlock(&init_mutex)) {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+
+static int fini_channel(int *fd, char **path)
+{
+    if (*fd != -1) {
+        if (close(*fd) == -1) {
+            return -1;
+        }
+        *fd = -1;
+    }
+    if (*path != NULL) {
+        free(*path);
+        *path =  NULL;
+    }
+    return 0;
+}
+
+int qemu_hypertrace_fini(void)
+{
+    if (fini_channel(&data_fd, &data_path) != 0) {
+        return -1;
+    }
+    if (fini_channel(&control_fd, &control_path) != 0) {
+        return -1;
+    }
+    return 0;
+}
+
+
+uint64_t qemu_hypertrace_max_clients(void)
+{
+    printf("max_clients\n");
+    return config->max_clients;
+}
+
+uint64_t qemu_hypertrace_num_args(void)
+{
+    printf("num_args\n");
+    return config->client_args;
+}
+
+uint64_t *qemu_hypertrace_data(uint64_t client)
+{
+    printf("data\n");
+    return &data_addr[client * CONFIG_HYPERTRACE_ARGS * sizeof(uint64_t)];
+}
+
+void qemu_hypertrace (uint64_t client, uint64_t arg1)
+{
+    uint64_t *ctrl = control_addr;
+    ctrl[client] = arg1;
+#if defined(CONFIG_USER_ONLY)
+    /* QEMU in 'user' mode uses two faulting pages to detect invocations */
+    ctrl = control_addr_1;
+    ctrl[client] = arg1;
+#endif
+}
diff --git a/hypertrace/guest/user/qemu-hypertrace.h b/hypertrace/guest/user/qemu-hypertrace.h
new file mode 100644
index 0000000..aa78bb3
--- /dev/null
+++ b/hypertrace/guest/user/qemu-hypertrace.h
@@ -0,0 +1,80 @@
+/*
+ * Guest-side management of hypertrace.
+ *
+ * Copyright (C) 2016 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+
+/**
+ * qemu_hypertrace_init:
+ * @base: Base path to the hypertrace channel.
+ *
+ * Initialize the hypertrace channel. The operation is idempotent, and must be
+ * called once per thread if running in QEMU's "user" mode.
+ *
+ * The base path to the hypertrace channel depends on the type of QEMU target:
+ *
+ * - User (single-application)
+ *   The base path provided when starting QEMU ("-hypertrace" commandline
+ *   option).
+ *
+ * - System (OS-dependant)
+ *   + Linux
+ *     The base path to the hypertrace channel virtual device; on a default QEMU
+ *     device setup for x86 this is "/sys/devices/pci0000:00/0000:00:04.0". If
+ *     NULL is provided, the hypertrace device will be automatically detected.
+ *
+ * Returns: Zero on success.
+ */
+int qemu_hypertrace_init(const char *base);
+
+/**
+ * qemu_hypertrace_fini:
+ *
+ * Deinitialize the hypertrace channel.
+ *
+ * Returns: Zero on success.
+ */
+int qemu_hypertrace_fini(void);
+
+/**
+ * qemu_hypertrace_max_clients:
+ *
+ * Maximum number of concurrent clients accepted by other calls.
+ */
+uint64_t qemu_hypertrace_max_clients(void);
+
+/**
+ * qemu_hypertrace_num_args:
+ *
+ * Number of uint64_t values read by each call to qemu_hypertrace().
+ */
+uint64_t qemu_hypertrace_num_args(void);
+
+/**
+ * qemu_hypertrace_data:
+ * @client: Client identifier.
+ *
+ * Pointer to the start of the data channel for the given client. Clients must
+ * write their arguments there (all but the first one).
+ */
+uint64_t *qemu_hypertrace_data(uint64_t client);
+
+/**
+ * qemu_hypertrace:
+ * @client: Client identifier.
+ * @arg1: First argument of the hypertrace event.
+ *
+ * Emit a hypertrace event.
+ *
+ * Each of the clients (e.g., thread) must use a different client identifier to
+ * ensure they can work concurrently without using locks (i.e., each uses a
+ * different portion of the data channel).
+ */
+void qemu_hypertrace(uint64_t client, uint64_t arg1);

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

* [Qemu-devel] [PATCH v2 6/6] hypertrace: Add guest-side Linux module
  2016-09-05 18:56 [Qemu-devel] [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel Lluís Vilanova
                   ` (4 preceding siblings ...)
  2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 5/6] hypertrace: Add guest-side user-level library Lluís Vilanova
@ 2016-09-05 18:56 ` Lluís Vilanova
  2016-09-05 19:23 ` [Qemu-devel] [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel no-reply
  6 siblings, 0 replies; 14+ messages in thread
From: Lluís Vilanova @ 2016-09-05 18:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Daniel P Berrange, Luiz Capitulino, Eric Blake, Stefan Hajnoczi

Provides guest Linux kernel module "qemu-hypertrace.ko" to abstract
access to the hypertrace channel.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 Makefile                                           |    4 -
 configure                                          |    4 +
 hypertrace/guest/linux-module/Kbuild.in            |    7 +
 hypertrace/guest/linux-module/Makefile             |   23 +++
 .../include/linux/qemu-hypertrace-internal.h       |   46 ++++++
 .../linux-module/include/linux/qemu-hypertrace.h   |   73 ++++++++++
 hypertrace/guest/linux-module/qemu-hypertrace.c    |  146 ++++++++++++++++++++
 7 files changed, 302 insertions(+), 1 deletion(-)
 create mode 100644 hypertrace/guest/linux-module/Kbuild.in
 create mode 100644 hypertrace/guest/linux-module/Makefile
 create mode 100644 hypertrace/guest/linux-module/include/linux/qemu-hypertrace-internal.h
 create mode 100644 hypertrace/guest/linux-module/include/linux/qemu-hypertrace.h
 create mode 100644 hypertrace/guest/linux-module/qemu-hypertrace.c

diff --git a/Makefile b/Makefile
index 8fb469b..4a47823 100644
--- a/Makefile
+++ b/Makefile
@@ -461,8 +461,10 @@ endif
 endif
 
 install-hypertrace:
-	$(INSTALL_DIR) "$(DESTDIR)$(includedir)"
+	$(INSTALL_DIR) "$(DESTDIR)$(includedir)/linux"
 	$(INSTALL_DATA) "$(SRC_PATH)/hypertrace/guest/user/qemu-hypertrace.h" "$(DESTDIR)$(includedir)/"
+	$(INSTALL_DATA) "$(SRC_PATH)/hypertrace/guest/linux-module/include/linux/qemu-hypertrace.h" "$(DESTDIR)$(includedir)/linux"
+	$(INSTALL_DATA) "$(SRC_PATH)/hypertrace/guest/linux-module/include/linux/qemu-hypertrace-internal.h" "$(DESTDIR)$(includedir)/linux"
 
 
 install: all $(if $(BUILD_DOCS),install-doc) \
diff --git a/configure b/configure
index ad83fff..fadaaf5 100755
--- a/configure
+++ b/configure
@@ -5795,6 +5795,10 @@ fi
 symlink "$source_path/Makefile.target" "$target_dir/Makefile"
 mkdir -p $target_dir/hypertrace/guest/user
 symlink $source_path/hypertrace/guest/user/Makefile $target_dir/hypertrace/guest/user/Makefile
+if test "$target_softmmu" = "yes"; then
+    mkdir -p $target_dir/hypertrace/guest/linux-module
+    symlink $source_path/hypertrace/guest/linux-module/Makefile $target_dir/hypertrace/guest/linux-module/Makefile
+fi
 
 upper() {
     echo "$@"| LC_ALL=C tr '[a-z]' '[A-Z]'
diff --git a/hypertrace/guest/linux-module/Kbuild.in b/hypertrace/guest/linux-module/Kbuild.in
new file mode 100644
index 0000000..56abaea
--- /dev/null
+++ b/hypertrace/guest/linux-module/Kbuild.in
@@ -0,0 +1,7 @@
+# -*- mode: makefile -*-
+
+COMMON_H = $(shell readlink -f $(MOD_SRC_PATH)/../../common.h)
+
+src = $(MOD_SRC_PATH)
+ccflags-y := -I$(src)/include/ -DCOMMON_H=$(COMMON_H)
+obj-m := qemu-hypertrace.o
diff --git a/hypertrace/guest/linux-module/Makefile b/hypertrace/guest/linux-module/Makefile
new file mode 100644
index 0000000..b30cdeb
--- /dev/null
+++ b/hypertrace/guest/linux-module/Makefile
@@ -0,0 +1,23 @@
+include ../../../../config-host.mak
+include ../../../config-target.mak
+include $(SRC_PATH)/rules.mak
+
+MOD_SRC_PATH = $(SRC_PATH)/hypertrace/guest/linux-module
+
+LINUX_BUILD_PATH = /lib/modules/$(shell uname -r)/build
+
+vpath % $(MOD_SRC_PATH)
+
+
+all: Kbuild
+	$(MAKE) -C $(LINUX_BUILD_PATH) M=$(shell pwd) \
+	  MOD_SRC_PATH=$(MOD_SRC_PATH) \
+	  modules
+
+clean: Kbuild
+	$(MAKE) -C $(LINUX_BUILD_PATH) M=$(shell pwd) clean
+	rm -f $<
+
+Kbuild: $(MOD_SRC_PATH)/Kbuild.in Makefile
+	rm -f $@
+	cp $< $@
diff --git a/hypertrace/guest/linux-module/include/linux/qemu-hypertrace-internal.h b/hypertrace/guest/linux-module/include/linux/qemu-hypertrace-internal.h
new file mode 100644
index 0000000..63dfee0
--- /dev/null
+++ b/hypertrace/guest/linux-module/include/linux/qemu-hypertrace-internal.h
@@ -0,0 +1,46 @@
+/* -*- C -*-
+ *
+ * Guest-side management of hypertrace.
+ *
+ * Copyright (C) 2016 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see http://www.gnu.org/licenses/.
+ */
+
+extern uint64_t _qemu_hypertrace_channel_max_clients;
+extern uint64_t _qemu_hypertrace_channel_num_args;
+extern uint64_t *_qemu_hypertrace_channel_data;
+extern uint64_t *_qemu_hypertrace_channel_control;
+
+static inline uint64_t qemu_hypertrace_max_clients(void)
+{
+    return _qemu_hypertrace_channel_max_clients;
+}
+
+static inline uint64_t qemu_hypertrace_num_args(void)
+{
+    return _qemu_hypertrace_channel_num_args;
+}
+
+static inline uint64_t *qemu_hypertrace_data(uint64_t client)
+{
+    size_t args_size = qemu_hypertrace_num_args() * sizeof(uint64_t);
+    return &_qemu_hypertrace_channel_data[client * args_size];
+}
+
+static inline void qemu_hypertrace (uint64_t client, uint64_t arg1)
+{
+    uint64_t *ctrlp = _qemu_hypertrace_channel_control;
+    ctrlp[client] = arg1;
+}
diff --git a/hypertrace/guest/linux-module/include/linux/qemu-hypertrace.h b/hypertrace/guest/linux-module/include/linux/qemu-hypertrace.h
new file mode 100644
index 0000000..f4b70c9
--- /dev/null
+++ b/hypertrace/guest/linux-module/include/linux/qemu-hypertrace.h
@@ -0,0 +1,73 @@
+/* -*- C -*-
+ *
+ * Guest-side management of hypertrace.
+ *
+ * Copyright (C) 2016 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see http://www.gnu.org/licenses/.
+ */
+
+#ifndef QEMU_HYPERTRACE_H
+#define QEMU_HYPERTRACE_H
+
+#include <linux/types.h>
+
+
+/**
+ * qemu_hypertrace_max_clients:
+ *
+ * Maximum number of concurrent clients accepted by other calls.
+ */
+static uint64_t qemu_hypertrace_max_clients(void);
+
+/**
+ * qemu_hypertrace_num_args:
+ *
+ * Number of uint64_t values read by each call to qemu_hypertrace().
+ */
+static uint64_t qemu_hypertrace_num_args(void);
+
+/**
+ * qemu_hypertrace_data:
+ * @client: Client identifier.
+ *
+ * Pointer to the start of the data channel for the given client. Clients must
+ * write their arguments there (all but the first one).
+ */
+static uint64_t *qemu_hypertrace_data(uint64_t client);
+
+/**
+ * qemu_hypertrace:
+ * @client: Client identifier.
+ * @arg1: First argument of the hypertrace event.
+ *
+ * Emit a hypertrace event.
+ *
+ * Each of the clients (e.g., CPU) must use a different client identifier to
+ * ensure they can work concurrently without using locks (i.e., each uses a
+ * different portion of the data channel).
+ *
+ * Note: You should use wmb() before writing into the control channel iff you
+ * have written into the data channel.
+ *
+ * Note: Use preempt_disable() and preempt_enable() if you're using data offsets
+ * based on the CPU identifiers (or else data might be mixed if a task is
+ * re-scheduled).
+ */
+static void qemu_hypertrace(uint64_t client, uint64_t arg1);
+
+
+#include <linux/qemu-hypertrace-internal.h>
+
+#endif  /* QEMU_HYPERTRACE_H */
diff --git a/hypertrace/guest/linux-module/qemu-hypertrace.c b/hypertrace/guest/linux-module/qemu-hypertrace.c
new file mode 100644
index 0000000..901d424
--- /dev/null
+++ b/hypertrace/guest/linux-module/qemu-hypertrace.c
@@ -0,0 +1,146 @@
+/*
+ * Guest-side management of hypertrace.
+ *
+ * Copyright (C) 2016 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see http://www.gnu.org/licenses/.
+ */
+
+#include <linux/qemu-hypertrace.h>
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/uaccess.h>
+
+#define xstr(s) #s
+#define str(s) xstr(s)
+#include str(COMMON_H)
+
+
+#define VERSION_STR "0.1"
+#define PCI_VENDOR_ID_REDHAT_QUMRANET    0x1af4
+#define PCI_DEVICE_ID_HYPERTRACE         0x10f0
+
+
+MODULE_DESCRIPTION("Kernel interface to QEMU's hypertrace device");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lluís Vilanova");
+MODULE_VERSION(VERSION_STR);
+
+
+//////////////////////////////////////////////////////////////////////
+// Kernel interface
+
+uint64_t _qemu_hypertrace_channel_max_clients;
+uint64_t _qemu_hypertrace_channel_num_args;
+static uint64_t *_qemu_hypertrace_channel_config;
+uint64_t *_qemu_hypertrace_channel_data;
+uint64_t *_qemu_hypertrace_channel_control;
+
+EXPORT_SYMBOL(_qemu_hypertrace_channel_max_clients);
+EXPORT_SYMBOL(_qemu_hypertrace_channel_num_args);
+EXPORT_SYMBOL(_qemu_hypertrace_channel_data);
+EXPORT_SYMBOL(_qemu_hypertrace_channel_control);
+
+
+//////////////////////////////////////////////////////////////////////
+// Channel initialization
+
+static
+int
+init_channel (uint64_t **vaddr, struct pci_dev *dev, int bar)
+{
+    void * res;
+    resource_size_t start, size;
+
+    start = pci_resource_start(dev, bar);
+    size = pci_resource_len(dev, bar);
+
+    if (start == 0 || size == 0) {
+        return -ENOENT;
+    }
+
+    res = ioremap(start, size);
+    if (res == 0) {
+        return -EINVAL;
+    }
+
+    *vaddr = res;
+    return 0;
+}
+
+//////////////////////////////////////////////////////////////////////
+// Module (de)initialization
+
+int init_module(void)
+{
+    int res = 0;
+    struct pci_dev *dev = NULL;
+    struct hypertrace_config *config;
+
+    printk(KERN_NOTICE "Loading QEMU hypertrace module (version %s)\n",
+           VERSION_STR);
+
+    dev = pci_get_device(PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_DEVICE_ID_HYPERTRACE, NULL);
+    if (dev == NULL) {
+        res = -ENOENT;
+        printk(KERN_ERR "Unable to find hypertrace device\n");
+        goto error;
+    }
+
+    res = init_channel(&_qemu_hypertrace_channel_config, dev, 0);
+    if (res != 0) {
+        printk(KERN_ERR "Unable to find hypertrace config channel\n");
+        goto error;
+    }
+
+    config = (struct hypertrace_config*)_qemu_hypertrace_channel_config;
+    _qemu_hypertrace_channel_max_clients = config->max_clients;
+    _qemu_hypertrace_channel_num_args = config->client_args;
+
+    res = init_channel(&_qemu_hypertrace_channel_data, dev, 1);
+    if (res != 0) {
+        printk(KERN_ERR "Unable to find hypertrace data channel\n");
+        goto error_config;
+    }
+
+    res = init_channel(&_qemu_hypertrace_channel_control, dev, 0);
+    if (res != 0) {
+        printk(KERN_ERR "Unable to find hypertrace control channel\n");
+        goto error_data;
+    }
+
+    goto ok;
+
+error_data:
+    iounmap(_qemu_hypertrace_channel_data);
+
+error_config:
+    iounmap(_qemu_hypertrace_channel_config);
+    _qemu_hypertrace_channel_config = NULL;
+    _qemu_hypertrace_channel_data = NULL;
+
+error:
+ok:
+    return res;
+}
+
+void cleanup_module(void)
+{
+    printk(KERN_NOTICE "Unloading QEMU hypertrace module\n");
+
+    iounmap(_qemu_hypertrace_channel_config);
+    iounmap(_qemu_hypertrace_channel_data);
+    iounmap(_qemu_hypertrace_channel_control);
+}

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

* Re: [Qemu-devel] [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel
  2016-09-05 18:56 [Qemu-devel] [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel Lluís Vilanova
                   ` (5 preceding siblings ...)
  2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 6/6] hypertrace: Add guest-side Linux module Lluís Vilanova
@ 2016-09-05 19:23 ` no-reply
  2016-09-06  9:11   ` [Qemu-devel] Checkpatch false positives (Was: Re: [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel) Lluís Vilanova
  6 siblings, 1 reply; 14+ messages in thread
From: no-reply @ 2016-09-05 19:23 UTC (permalink / raw)
  To: vilanova; +Cc: famz, qemu-devel, stefanha, lcapitulino

Hi,

Your series seems to have some coding style problems. See output below for
more information:

Subject: [Qemu-devel] [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel
Type: series
Message-id: 147310178240.10840.14758930096407696981.stgit@fimbulvetr.bsc.es

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

# Useful git options
git config --local diff.renamelimit 0
git config --local diff.renames True

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
    echo "Checking PATCH $n/$total: $(git show --no-patch --format=%s $c)..."
    if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
        failed=1
        echo
    fi
    n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]         patchew/1473099234-10882-1-git-send-email-kwolf@redhat.com -> patchew/1473099234-10882-1-git-send-email-kwolf@redhat.com
 * [new tag]         patchew/147310178240.10840.14758930096407696981.stgit@fimbulvetr.bsc.es -> patchew/147310178240.10840.14758930096407696981.stgit@fimbulvetr.bsc.es
 * [new tag]         patchew/alpine.DEB.2.10.1609051159150.4105@sstabellini-ThinkPad-X260 -> patchew/alpine.DEB.2.10.1609051159150.4105@sstabellini-ThinkPad-X260
Switched to a new branch 'test'
0b7ef18 hypertrace: Add guest-side Linux module
1c66cbd hypertrace: Add guest-side user-level library
b67ef31 hypertrace: [softmmu] Add QEMU-side proxy to "guest_hypertrace" event
536c66c hypertrace: [*-user] Add QEMU-side proxy to "guest_hypertrace" event
8861ce2 hypertrace: Add tracing event "guest_hypertrace"
bc68e0b hypertrace: Add documentation

=== OUTPUT BEGIN ===
Checking PATCH 1/6: hypertrace: Add documentation...
ERROR: trailing whitespace
#109: FILE: docs/hypertrace.txt:92:
+    $

ERROR: trailing whitespace
#110: FILE: docs/hypertrace.txt:93:
+    $

ERROR: trailing whitespace
#117: FILE: docs/hypertrace.txt:100:
+    $

ERROR: trailing whitespace
#123: FILE: docs/hypertrace.txt:106:
+    $

ERROR: trailing whitespace
#130: FILE: docs/hypertrace.txt:113:
+    $

ERROR: trailing whitespace
#154: FILE: docs/hypertrace.txt:137:
+    $

ERROR: trailing whitespace
#156: FILE: docs/hypertrace.txt:139:
+    $

ERROR: trailing whitespace
#160: FILE: docs/hypertrace.txt:143:
+    $

ERROR: trailing whitespace
#171: FILE: docs/hypertrace.txt:154:
+    $

ERROR: trailing whitespace
#181: FILE: docs/hypertrace.txt:164:
+    $

total: 10 errors, 0 warnings, 236 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 2/6: hypertrace: Add tracing event "guest_hypertrace"...
Checking PATCH 3/6: hypertrace: [*-user] Add QEMU-side proxy to "guest_hypertrace" event...
WARNING: line over 80 characters
#81: FILE: bsd-user/main.c:866:
+            hypertrace_opt_parse(optarg, &hypertrace_base, &hypertrace_max_clients);

WARNING: line over 80 characters
#176: FILE: bsd-user/syscall.c:375:
+                                        target_to_host_bitmask(arg4, mmap_flags_tbl),

WARNING: line over 80 characters
#200: FILE: bsd-user/syscall.c:463:
+                                        target_to_host_bitmask(arg4, mmap_flags_tbl),

WARNING: line over 80 characters
#224: FILE: bsd-user/syscall.c:540:
+                                        target_to_host_bitmask(arg4, mmap_flags_tbl),

ERROR: architecture specific defines should be avoided
#302: FILE: hypertrace/common.h:10:
+#if !defined(__KERNEL__)

ERROR: open brace '{' following struct go on the same line
#307: FILE: hypertrace/common.h:15:
+struct hypertrace_config
+{

ERROR: do not initialise statics to 0 or NULL
#370: FILE: hypertrace/user.c:48:
+static char *config_path = NULL;

ERROR: do not initialise statics to 0 or NULL
#372: FILE: hypertrace/user.c:50:
+static uint64_t *qemu_config = NULL;

ERROR: do not initialise statics to 0 or NULL
#374: FILE: hypertrace/user.c:52:
+static char *data_path = NULL;

ERROR: do not initialise statics to 0 or NULL
#376: FILE: hypertrace/user.c:54:
+static uint64_t *qemu_data = NULL;

ERROR: do not initialise statics to 0 or NULL
#378: FILE: hypertrace/user.c:56:
+static char *control_path = NULL;

ERROR: do not initialise statics to 0 or NULL
#380: FILE: hypertrace/user.c:58:
+static uint64_t *qemu_control = NULL;

WARNING: line over 80 characters
#405: FILE: hypertrace/user.c:83:
+void hypertrace_opt_parse(const char *optarg, char **base, unsigned int *max_clients_)

ERROR: "foo ** bar" should be "foo **bar"
#427: FILE: hypertrace/user.c:105:
+                         char ** path, int *fd, uint64_t **addr)

ERROR: line over 90 characters
#490: FILE: hypertrace/user.c:168:
+    init_channel(base, "-config", TARGET_PAGE_SIZE, &config_path, &config_fd, &qemu_config);

ERROR: "(foo*)" should be "(foo *)"
#491: FILE: hypertrace/user.c:169:
+    pconfig = (struct hypertrace_config*)qemu_config;

WARNING: line over 80 characters
#498: FILE: hypertrace/user.c:176:
+    init_channel(base, "-data", config.data_size, &data_path, &data_fd, &qemu_data);

ERROR: line over 90 characters
#506: FILE: hypertrace/user.c:184:
+    init_channel(base, "-control", config.control_size, &control_path, &control_fd, &qemu_control);

ERROR: do not initialise statics to 0 or NULL
#549: FILE: hypertrace/user.c:227:
+    static bool atexit_in = false;

WARNING: line over 80 characters
#565: FILE: hypertrace/user.c:243:
+bool hypertrace_guest_mmap_check(int fd, unsigned long len, unsigned long offset)

WARNING: line over 80 characters
#600: FILE: hypertrace/user.c:278:
+    printf("cpu->hypertrace_control=%p %lu %lu\n", qemu_addr, s.st_dev, s.st_ino);

WARNING: line over 80 characters
#602: FILE: hypertrace/user.c:280:
+    if (mprotect(vcpu->hypertrace_control, config.control_size / 2, PROT_READ) == -1) {

WARNING: line over 80 characters
#603: FILE: hypertrace/user.c:281:
+        error_report("error: mprotect(hypertrace_control): %s", strerror(errno));

ERROR: "(foo*)" should be "(foo *)"
#641: FILE: hypertrace/user.c:319:
+        uint64_t vcontrol = ((uint64_t*)control_0)[client];

WARNING: line over 80 characters
#694: FILE: hypertrace/user.h:27:
+void hypertrace_opt_parse(const char *optarg, char **base, unsigned int *max_clients);

WARNING: line over 80 characters
#712: FILE: hypertrace/user.h:45:
+bool hypertrace_guest_mmap_check(int fd, unsigned long len, unsigned long offset);

total: 14 errors, 12 warnings, 833 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 4/6: hypertrace: [softmmu] Add QEMU-side proxy to "guest_hypertrace" event...
ERROR: open brace '{' following struct go on the same line
#81: FILE: hypertrace/softmmu.c:43:
+typedef struct HypertraceState
+{

ERROR: "(foo*)" should be "(foo *)"
#103: FILE: hypertrace/softmmu.c:65:
+    char *mem = &((char*)s->control_ptr)[addr];

ERROR: "(foo*)" should be "(foo *)"
#108: FILE: hypertrace/softmmu.c:70:
+        res = ((uint8_t*)mem)[0];

ERROR: "(foo*)" should be "(foo *)"
#113: FILE: hypertrace/softmmu.c:75:
+        res = ((uint16_t*)mem)[0];

ERROR: "(foo*)" should be "(foo *)"
#118: FILE: hypertrace/softmmu.c:80:
+        res = ((uint32_t*)mem)[0];

ERROR: "(foo*)" should be "(foo *)"
#123: FILE: hypertrace/softmmu.c:85:
+        res = ((uint64_t*)mem)[0];

ERROR: Error messages should not contain newlines
#127: FILE: hypertrace/softmmu.c:89:
+        error_report("error: hypertrace: Unexpected read of size %d\n", size);

ERROR: "(foo*)" should be "(foo *)"
#139: FILE: hypertrace/softmmu.c:101:
+    char *mem = &((char*)s->control_ptr)[addr];

ERROR: "(foo*)" should be "(foo *)"
#144: FILE: hypertrace/softmmu.c:106:
+        uint8_t *res = (uint8_t*)mem;

ERROR: "(foo*)" should be "(foo *)"
#150: FILE: hypertrace/softmmu.c:112:
+        uint16_t *res = (uint16_t*)mem;

ERROR: "(foo*)" should be "(foo *)"
#156: FILE: hypertrace/softmmu.c:118:
+        uint32_t *res = (uint32_t*)mem;

ERROR: "(foo*)" should be "(foo *)"
#162: FILE: hypertrace/softmmu.c:124:
+        uint64_t *res = (uint64_t*)mem;

ERROR: Error messages should not contain newlines
#167: FILE: hypertrace/softmmu.c:129:
+        error_report("error: hypertrace: Unexpected write of size %d\n", size);

ERROR: "(foo*)" should be "(foo *)"
#172: FILE: hypertrace/softmmu.c:134:
+        uint64_t vcontrol = ((uint64_t*)s->control_ptr)[client];

ERROR: "(foo*)" should be "(foo *)"
#173: FILE: hypertrace/softmmu.c:135:
+        uint64_t *data_ptr = (uint64_t*)s->data_ptr;

ERROR: Error messages should not contain newlines
#197: FILE: hypertrace/softmmu.c:159:
+        error_setg(errp, "hypertrace: must have at least one client\n");

WARNING: line over 80 characters
#203: FILE: hypertrace/softmmu.c:165:
+    error_setg(&s->migration_blocker, "The 'hypertrace' device cannot be migrated");

total: 16 errors, 1 warnings, 256 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 5/6: hypertrace: Add guest-side user-level library...
ERROR: do not initialise statics to 0 or NULL
#123: FILE: hypertrace/guest/user/common.c:35:
+static char *config_path = NULL;

ERROR: do not initialise statics to 0 or NULL
#125: FILE: hypertrace/guest/user/common.c:37:
+static uint64_t *config_addr = NULL;

ERROR: do not initialise statics to 0 or NULL
#126: FILE: hypertrace/guest/user/common.c:38:
+static struct hypertrace_config *config = NULL;

ERROR: do not initialise statics to 0 or NULL
#129: FILE: hypertrace/guest/user/common.c:41:
+static char *data_path = NULL;

ERROR: do not initialise statics to 0 or NULL
#131: FILE: hypertrace/guest/user/common.c:43:
+static uint64_t *data_addr = NULL;

ERROR: do not initialise statics to 0 or NULL
#133: FILE: hypertrace/guest/user/common.c:45:
+static char *control_path = NULL;

ERROR: do not initialise statics to 0 or NULL
#136: FILE: hypertrace/guest/user/common.c:48:
+static __thread uint64_t *control_addr = NULL;

ERROR: do not initialise statics to 0 or NULL
#137: FILE: hypertrace/guest/user/common.c:49:
+static __thread uint64_t *control_addr_1 = NULL;

ERROR: do not initialise statics to 0 or NULL
#139: FILE: hypertrace/guest/user/common.c:51:
+static uint64_t *control_addr = NULL;

ERROR: "foo ** bar" should be "foo **bar"
#144: FILE: hypertrace/guest/user/common.c:56:
+                             char ** path, int *fd, uint64_t **addr, bool write)

ERROR: architecture specific defines should be avoided
#172: FILE: hypertrace/guest/user/common.c:84:
+#if !defined(CONFIG_USER_ONLY) && defined(__linux__)

ERROR: space prohibited between function name and open parenthesis '('
#173: FILE: hypertrace/guest/user/common.c:85:
+static int check_device_id (const char *base, const char *name, uint64_t value)

ERROR: consider using qemu_strtoull in preference to strtoull
#192: FILE: hypertrace/guest/user/common.c:104:
+    uint64_t vv = strtoull(v, &end, 16);

ERROR: else should follow close brace '}'
#196: FILE: hypertrace/guest/user/common.c:108:
+    }
+    else {

ERROR: "foo* bar" should be "foo *bar"
#201: FILE: hypertrace/guest/user/common.c:113:
+static char* find_device(void)

WARNING: line over 80 characters
#216: FILE: hypertrace/guest/user/common.c:128:
+        if (check_device_id(path, "vendor", PCI_VENDOR_ID_REDHAT_QUMRANET) < 0) {

ERROR: "(foo*)" should be "(foo *)"
#279: FILE: hypertrace/guest/user/common.c:191:
+        config = (struct hypertrace_config*)config_addr;

WARNING: line over 80 characters
#323: FILE: hypertrace/guest/user/common.c:235:
+        control_addr_1 = (uint64_t*)((char*)control_addr + config->control_size / 2);

ERROR: "(foo*)" should be "(foo *)"
#323: FILE: hypertrace/guest/user/common.c:235:
+        control_addr_1 = (uint64_t*)((char*)control_addr + config->control_size / 2);

ERROR: space prohibited between function name and open parenthesis '('
#380: FILE: hypertrace/guest/user/common.c:292:
+void qemu_hypertrace (uint64_t client, uint64_t arg1)

total: 18 errors, 2 warnings, 433 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 6/6: hypertrace: Add guest-side Linux module...
ERROR: space prohibited between function name and open parenthesis '('
#135: FILE: hypertrace/guest/linux-module/include/linux/qemu-hypertrace-internal.h:42:
+static inline void qemu_hypertrace (uint64_t client, uint64_t arg1)

ERROR: do not use C99 // comments
#266: FILE: hypertrace/guest/linux-module/qemu-hypertrace.c:42:
+//////////////////////////////////////////////////////////////////////

ERROR: do not use C99 // comments
#267: FILE: hypertrace/guest/linux-module/qemu-hypertrace.c:43:
+// Kernel interface

ERROR: do not use C99 // comments
#281: FILE: hypertrace/guest/linux-module/qemu-hypertrace.c:57:
+//////////////////////////////////////////////////////////////////////

ERROR: do not use C99 // comments
#282: FILE: hypertrace/guest/linux-module/qemu-hypertrace.c:58:
+// Channel initialization

ERROR: space prohibited between function name and open parenthesis '('
#286: FILE: hypertrace/guest/linux-module/qemu-hypertrace.c:62:
+init_channel (uint64_t **vaddr, struct pci_dev *dev, int bar)

ERROR: "foo * bar" should be "foo *bar"
#288: FILE: hypertrace/guest/linux-module/qemu-hypertrace.c:64:
+    void * res;

ERROR: do not use C99 // comments
#307: FILE: hypertrace/guest/linux-module/qemu-hypertrace.c:83:
+//////////////////////////////////////////////////////////////////////

ERROR: do not use C99 // comments
#308: FILE: hypertrace/guest/linux-module/qemu-hypertrace.c:84:
+// Module (de)initialization

WARNING: line over 80 characters
#319: FILE: hypertrace/guest/linux-module/qemu-hypertrace.c:95:
+    dev = pci_get_device(PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_DEVICE_ID_HYPERTRACE, NULL);

ERROR: "(foo*)" should be "(foo *)"
#332: FILE: hypertrace/guest/linux-module/qemu-hypertrace.c:108:
+    config = (struct hypertrace_config*)_qemu_hypertrace_channel_config;

total: 10 errors, 1 warnings, 316 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org

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

* Re: [Qemu-devel] [PATCH v2 4/6] hypertrace: [softmmu] Add QEMU-side proxy to "guest_hypertrace" event
  2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 4/6] hypertrace: [softmmu] " Lluís Vilanova
@ 2016-09-06  1:43   ` Michael S. Tsirkin
  2016-09-09 13:19     ` Lluís Vilanova
  2016-09-14 14:37     ` Stefan Hajnoczi
  0 siblings, 2 replies; 14+ messages in thread
From: Michael S. Tsirkin @ 2016-09-06  1:43 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Daniel P Berrange, Luiz Capitulino, Eric Blake,
	Stefan Hajnoczi, Marcel Apfelbaum

On Mon, Sep 05, 2016 at 08:56:44PM +0200, Lluís Vilanova wrote:
> diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
> index 929ec2f..8973f57 100644
> --- a/include/hw/pci/pci.h
> +++ b/include/hw/pci/pci.h
> @@ -80,6 +80,8 @@
>  #define PCI_DEVICE_ID_VIRTIO_RNG         0x1005
>  #define PCI_DEVICE_ID_VIRTIO_9P          0x1009
>  
> +#define PCI_DEVICE_ID_HYPERTRACE         0x10f0
> +
>  #define PCI_VENDOR_ID_REDHAT             0x1b36
>  #define PCI_DEVICE_ID_REDHAT_BRIDGE      0x0001
>  #define PCI_DEVICE_ID_REDHAT_SERIAL      0x0002


There's no need to add IDs to this header.
We should probably drop the ones we currently have in pci.h, too.

-- 
MST

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

* [Qemu-devel] Checkpatch false positives (Was: Re: [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel)
  2016-09-05 19:23 ` [Qemu-devel] [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel no-reply
@ 2016-09-06  9:11   ` Lluís Vilanova
  2016-09-06  9:16     ` Paolo Bonzini
  0 siblings, 1 reply; 14+ messages in thread
From: Lluís Vilanova @ 2016-09-06  9:11 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

no-reply  writes:
> Checking PATCH 1/6: hypertrace: Add documentation...
> ERROR: trailing whitespace
> #109: FILE: docs/hypertrace.txt:92:
> +    $

> ERROR: trailing whitespace
> #110: FILE: docs/hypertrace.txt:93:
> +    $

> ERROR: trailing whitespace
> #117: FILE: docs/hypertrace.txt:100:
> +    $

> ERROR: trailing whitespace
> #123: FILE: docs/hypertrace.txt:106:
> +    $

> ERROR: trailing whitespace
> #130: FILE: docs/hypertrace.txt:113:
> +    $

> ERROR: trailing whitespace
> #154: FILE: docs/hypertrace.txt:137:
> +    $

> ERROR: trailing whitespace
> #156: FILE: docs/hypertrace.txt:139:
> +    $

> ERROR: trailing whitespace
> #160: FILE: docs/hypertrace.txt:143:
> +    $

> ERROR: trailing whitespace
> #171: FILE: docs/hypertrace.txt:154:
> +    $

> ERROR: trailing whitespace
> #181: FILE: docs/hypertrace.txt:164:
> +    $

> total: 10 errors, 0 warnings, 236 lines checked

> Your patch has style problems, please review.  If any of these errors
> are false positives report them to the maintainer, see
> CHECKPATCH in MAINTAINERS.

The errors above are false positives. AFAIR, in .txt files empty lines in code
examples need 4 white spaces to let the wiki properly render them as a single
code example block.


Thanks,
  Lluis

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

* Re: [Qemu-devel] Checkpatch false positives (Was: Re: [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel)
  2016-09-06  9:11   ` [Qemu-devel] Checkpatch false positives (Was: Re: [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel) Lluís Vilanova
@ 2016-09-06  9:16     ` Paolo Bonzini
  2016-09-06 10:19       ` [Qemu-devel] Checkpatch false positives Lluís Vilanova
  0 siblings, 1 reply; 14+ messages in thread
From: Paolo Bonzini @ 2016-09-06  9:16 UTC (permalink / raw)
  To: qemu-devel



On 06/09/2016 11:11, Lluís Vilanova wrote:
> no-reply  writes:
>> Checking PATCH 1/6: hypertrace: Add documentation...
>> ERROR: trailing whitespace
>> #109: FILE: docs/hypertrace.txt:92:
>> +    $
> 
>> ERROR: trailing whitespace
>> #110: FILE: docs/hypertrace.txt:93:
>> +    $
> 
>> ERROR: trailing whitespace
>> #117: FILE: docs/hypertrace.txt:100:
>> +    $
> 
>> ERROR: trailing whitespace
>> #123: FILE: docs/hypertrace.txt:106:
>> +    $
> 
>> ERROR: trailing whitespace
>> #130: FILE: docs/hypertrace.txt:113:
>> +    $
> 
>> ERROR: trailing whitespace
>> #154: FILE: docs/hypertrace.txt:137:
>> +    $
> 
>> ERROR: trailing whitespace
>> #156: FILE: docs/hypertrace.txt:139:
>> +    $
> 
>> ERROR: trailing whitespace
>> #160: FILE: docs/hypertrace.txt:143:
>> +    $
> 
>> ERROR: trailing whitespace
>> #171: FILE: docs/hypertrace.txt:154:
>> +    $
> 
>> ERROR: trailing whitespace
>> #181: FILE: docs/hypertrace.txt:164:
>> +    $
> 
>> total: 10 errors, 0 warnings, 236 lines checked
> 
>> Your patch has style problems, please review.  If any of these errors
>> are false positives report them to the maintainer, see
>> CHECKPATCH in MAINTAINERS.
> 
> The errors above are false positives. AFAIR, in .txt files empty lines in code
> examples need 4 white spaces to let the wiki properly render them as a single
> code example block.

Right, can you make a patch for that?  It should recognize exactly 4
patches and only apply to .txt and .md files.

Paolo

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

* Re: [Qemu-devel] Checkpatch false positives
  2016-09-06  9:16     ` Paolo Bonzini
@ 2016-09-06 10:19       ` Lluís Vilanova
  0 siblings, 0 replies; 14+ messages in thread
From: Lluís Vilanova @ 2016-09-06 10:19 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Paolo Bonzini writes:

> On 06/09/2016 11:11, Lluís Vilanova wrote:
>> no-reply  writes:
>>> Checking PATCH 1/6: hypertrace: Add documentation...
>>> ERROR: trailing whitespace
>>> #109: FILE: docs/hypertrace.txt:92:
>>> +    $
>> 
>>> ERROR: trailing whitespace
>>> #110: FILE: docs/hypertrace.txt:93:
>>> +    $
>> 
>>> ERROR: trailing whitespace
>>> #117: FILE: docs/hypertrace.txt:100:
>>> +    $
>> 
>>> ERROR: trailing whitespace
>>> #123: FILE: docs/hypertrace.txt:106:
>>> +    $
>> 
>>> ERROR: trailing whitespace
>>> #130: FILE: docs/hypertrace.txt:113:
>>> +    $
>> 
>>> ERROR: trailing whitespace
>>> #154: FILE: docs/hypertrace.txt:137:
>>> +    $
>> 
>>> ERROR: trailing whitespace
>>> #156: FILE: docs/hypertrace.txt:139:
>>> +    $
>> 
>>> ERROR: trailing whitespace
>>> #160: FILE: docs/hypertrace.txt:143:
>>> +    $
>> 
>>> ERROR: trailing whitespace
>>> #171: FILE: docs/hypertrace.txt:154:
>>> +    $
>> 
>>> ERROR: trailing whitespace
>>> #181: FILE: docs/hypertrace.txt:164:
>>> +    $
>> 
>>> total: 10 errors, 0 warnings, 236 lines checked
>> 
>>> Your patch has style problems, please review.  If any of these errors
>>> are false positives report them to the maintainer, see
>>> CHECKPATCH in MAINTAINERS.
>> 
>> The errors above are false positives. AFAIR, in .txt files empty lines in code
>> examples need 4 white spaces to let the wiki properly render them as a single
>> code example block.

> Right, can you make a patch for that?  It should recognize exactly 4
> patches and only apply to .txt and .md files.

Ok. I won't properly check this only applies to lines where surrounding text is
4-column-indented, though, so it can have false negatives.

Cheers,
  Lluis

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

* Re: [Qemu-devel] [PATCH v2 4/6] hypertrace: [softmmu] Add QEMU-side proxy to "guest_hypertrace" event
  2016-09-06  1:43   ` Michael S. Tsirkin
@ 2016-09-09 13:19     ` Lluís Vilanova
  2016-09-14 14:37     ` Stefan Hajnoczi
  1 sibling, 0 replies; 14+ messages in thread
From: Lluís Vilanova @ 2016-09-09 13:19 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: qemu-devel, Luiz Capitulino, Stefan Hajnoczi, Marcel Apfelbaum

Michael S Tsirkin writes:

> On Mon, Sep 05, 2016 at 08:56:44PM +0200, Lluís Vilanova wrote:
>> diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
>> index 929ec2f..8973f57 100644
>> --- a/include/hw/pci/pci.h
>> +++ b/include/hw/pci/pci.h
>> @@ -80,6 +80,8 @@
>> #define PCI_DEVICE_ID_VIRTIO_RNG         0x1005
>> #define PCI_DEVICE_ID_VIRTIO_9P          0x1009
>> 
>> +#define PCI_DEVICE_ID_HYPERTRACE         0x10f0
>> +
>> #define PCI_VENDOR_ID_REDHAT             0x1b36
>> #define PCI_DEVICE_ID_REDHAT_BRIDGE      0x0001
>> #define PCI_DEVICE_ID_REDHAT_SERIAL      0x0002


> There's no need to add IDs to this header.
> We should probably drop the ones we currently have in pci.h, too.

You mean these should simply be a define inside each device's code?


Thanks,
  Lluis

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

* Re: [Qemu-devel] [PATCH v2 4/6] hypertrace: [softmmu] Add QEMU-side proxy to "guest_hypertrace" event
  2016-09-06  1:43   ` Michael S. Tsirkin
  2016-09-09 13:19     ` Lluís Vilanova
@ 2016-09-14 14:37     ` Stefan Hajnoczi
  1 sibling, 0 replies; 14+ messages in thread
From: Stefan Hajnoczi @ 2016-09-14 14:37 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Lluís Vilanova, qemu-devel, Daniel P Berrange,
	Luiz Capitulino, Eric Blake, Marcel Apfelbaum

[-- Attachment #1: Type: text/plain, Size: 1011 bytes --]

On Tue, Sep 06, 2016 at 04:43:00AM +0300, Michael S. Tsirkin wrote:
> On Mon, Sep 05, 2016 at 08:56:44PM +0200, Lluís Vilanova wrote:
> > diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
> > index 929ec2f..8973f57 100644
> > --- a/include/hw/pci/pci.h
> > +++ b/include/hw/pci/pci.h
> > @@ -80,6 +80,8 @@
> >  #define PCI_DEVICE_ID_VIRTIO_RNG         0x1005
> >  #define PCI_DEVICE_ID_VIRTIO_9P          0x1009
> >  
> > +#define PCI_DEVICE_ID_HYPERTRACE         0x10f0
> > +
> >  #define PCI_VENDOR_ID_REDHAT             0x1b36
> >  #define PCI_DEVICE_ID_REDHAT_BRIDGE      0x0001
> >  #define PCI_DEVICE_ID_REDHAT_SERIAL      0x0002
> 
> 
> There's no need to add IDs to this header.
> We should probably drop the ones we currently have in pci.h, too.

Defining the PCI IDs in public headers gives libqos test cases access to
them.  If they are scoped to only be available in device emulation code
then the test cases need to duplicate them, which is undesirable IMO.

Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

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

end of thread, other threads:[~2016-09-14 14:37 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-05 18:56 [Qemu-devel] [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel Lluís Vilanova
2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 1/6] hypertrace: Add documentation Lluís Vilanova
2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 2/6] hypertrace: Add tracing event "guest_hypertrace" Lluís Vilanova
2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 3/6] hypertrace: [*-user] Add QEMU-side proxy to "guest_hypertrace" event Lluís Vilanova
2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 4/6] hypertrace: [softmmu] " Lluís Vilanova
2016-09-06  1:43   ` Michael S. Tsirkin
2016-09-09 13:19     ` Lluís Vilanova
2016-09-14 14:37     ` Stefan Hajnoczi
2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 5/6] hypertrace: Add guest-side user-level library Lluís Vilanova
2016-09-05 18:56 ` [Qemu-devel] [PATCH v2 6/6] hypertrace: Add guest-side Linux module Lluís Vilanova
2016-09-05 19:23 ` [Qemu-devel] [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel no-reply
2016-09-06  9:11   ` [Qemu-devel] Checkpatch false positives (Was: Re: [PATCH v2 0/6] hypertrace: Lightweight guest-to-QEMU trace channel) Lluís Vilanova
2016-09-06  9:16     ` Paolo Bonzini
2016-09-06 10:19       ` [Qemu-devel] Checkpatch false positives Lluís Vilanova

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.