All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Lluís Vilanova" <vilanova@ac.upc.edu>
To: qemu-devel@nongnu.org
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Subject: [Qemu-devel] [PATCH 5/6] hypertrace: Add guest-side user-level library
Date: Fri,  5 Aug 2016 18:59:50 +0200	[thread overview]
Message-ID: <147041639047.2523.7352313284957186583.stgit@fimbulvetr.bsc.es> (raw)
In-Reply-To: <147041636348.2523.2954972609232949598.stgit@fimbulvetr.bsc.es>

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          |   28 ++++
 hypertrace/guest/user/common.c          |  221 +++++++++++++++++++++++++++++++
 hypertrace/guest/user/qemu-hypertrace.h |   77 +++++++++++
 5 files changed, 333 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 0d7647f..bebd6e6 100644
--- a/Makefile
+++ b/Makefile
@@ -459,9 +459,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 e80fde4..076eb8b 100755
--- a/configure
+++ b/configure
@@ -5780,6 +5780,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..bcc9dc9
--- /dev/null
+++ b/hypertrace/guest/user/Makefile
@@ -0,0 +1,28 @@
+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
+
+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..1429b2a
--- /dev/null
+++ b/hypertrace/guest/user/common.c
@@ -0,0 +1,221 @@
+/*
+ * 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 <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
+
+
+static char *data_path = NULL;
+static char *control_path = NULL;
+static int data_fd = -1;
+static int control_fd = -1;
+
+static uint64_t *data_addr = NULL;
+static uint64_t *control_addr = NULL;
+
+
+static int init_channel_file(const char *base, const char *suffix, size_t size,
+                             char ** path, int *fd, uint64_t **addr)
+{
+    *path = malloc(strlen(base) + strlen(suffix) + 1);
+    sprintf(*path, "%s%s", base, suffix);
+
+    *fd = open(*path, O_RDWR);
+    if (*fd == -1) {
+        return -1;
+    }
+
+    *addr = mmap(NULL, size, PROT_READ | PROT_WRITE, 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 *control_suff = "-control";
+    const size_t control_size = getpagesize() * 2;
+    const char *data_suff = "-data";
+#elif defined(__linux__)
+    const char *control_suff = "/resource0";
+    const size_t control_size = getpagesize();
+    const char *data_suff = "/resource1";
+#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
+
+    int res;
+    res = init_channel_file(base, control_suff, control_size,
+                            &control_path, &control_fd, &control_addr);
+    if (res != 0) {
+        return res;
+    }
+
+    size_t data_size = qemu_hypertrace_num_args() * sizeof(uint64_t);
+    data_size *= qemu_hypertrace_max_offset() + 1;
+    res = init_channel_file(base, data_suff, data_size,
+                            &data_path, &data_fd, &data_addr);
+    if (res != 0) {
+        return res;
+    }
+    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_num_args(void)
+{
+    return CONFIG_HYPERTRACE_ARGS;
+}
+
+uint64_t qemu_hypertrace_max_offset(void)
+{
+    return control_addr[0];
+}
+
+uint64_t *qemu_hypertrace_data(uint64_t data_offset)
+{
+    return &data_addr[data_offset * CONFIG_HYPERTRACE_ARGS * sizeof(uint64_t)];
+}
+
+void qemu_hypertrace (uint64_t data_offset)
+{
+    uint64_t *ctrl;
+    ctrl = control_addr;
+    ctrl[1] = data_offset;
+#if defined(CONFIG_USER_ONLY)
+    /* QEMU in 'user' mode uses two faulting pages to detect invocations */
+    ctrl = (uint64_t*)((char*)control_addr + getpagesize());
+    ctrl[1] = data_offset;
+#endif
+}
diff --git a/hypertrace/guest/user/qemu-hypertrace.h b/hypertrace/guest/user/qemu-hypertrace.h
new file mode 100644
index 0000000..ba58e49
--- /dev/null
+++ b/hypertrace/guest/user/qemu-hypertrace.h
@@ -0,0 +1,77 @@
+/*
+ * 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 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_num_args:
+ *
+ * Number of uint64_t values read by each call to qemu_hypertrace().
+ */
+uint64_t qemu_hypertrace_num_args(void);
+
+/**
+ * qemu_hypertrace_data_size:
+ *
+ * Maximum data offset value accepted by other calls.
+ */
+uint64_t qemu_hypertrace_max_offset(void);
+
+/**
+ * qemu_hypertrace_data:
+ * @data_offset: Offset in multiples of argument packs.
+ *
+ * Pointer to the start of the data channel.
+ */
+uint64_t *qemu_hypertrace_data(uint64_t data_offset);
+
+/**
+ * qemu_hypertrace:
+ * @data_offset: Offset in multiples of argument packs.
+ *
+ * Invoke the control channel.
+ *
+ * Each of the users (e.g., thread) of the hypertrace channel can use a
+ * different data offset 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 data_offset);

  parent reply	other threads:[~2016-08-05 16:59 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-05 16:59 [Qemu-devel] [PATCH 0/6] hypertrace: Lightweight guest-to-QEMU trace channel Lluís Vilanova
2016-08-05 16:59 ` [Qemu-devel] [PATCH 1/6] hypertrace: Add documentation Lluís Vilanova
2016-08-05 17:17   ` Eric Blake
2016-08-08 13:02     ` Lluís Vilanova
2016-08-05 16:59 ` [Qemu-devel] [PATCH 2/6] hypertrace: Add tracing event "guest_hypertrace" Lluís Vilanova
2016-08-18  9:59   ` Stefan Hajnoczi
2016-08-18 10:32     ` Lluís Vilanova
2016-08-05 16:59 ` [Qemu-devel] [PATCH 3/6] hypertrace: [*-user] Add QEMU-side proxy to "guest_hypertrace" event Lluís Vilanova
2016-08-05 17:23   ` Eric Blake
2016-08-08 13:08     ` Lluís Vilanova
2016-08-18 10:17   ` Stefan Hajnoczi
2016-08-21 12:15     ` Lluís Vilanova
2016-08-23 15:52       ` Stefan Hajnoczi
2016-08-05 16:59 ` [Qemu-devel] [PATCH 4/6] hypertrace: [softmmu] " Lluís Vilanova
2016-08-05 16:59 ` Lluís Vilanova [this message]
2016-08-05 16:59 ` [Qemu-devel] [PATCH 6/6] hypertrace: Add guest-side Linux module Lluís Vilanova
2016-08-18  9:47 ` [Qemu-devel] [PATCH 0/6] hypertrace: Lightweight guest-to-QEMU trace channel Stefan Hajnoczi
2016-08-18  9:47   ` Stefan Hajnoczi
2016-08-18 10:22   ` [Qemu-devel] " Lluís Vilanova
2016-08-18 13:53     ` Stefan Hajnoczi
2016-08-18 14:21       ` Luiz Capitulino
2016-08-21 12:17         ` Lluís Vilanova
2016-08-21 12:17         ` Lluís Vilanova
2016-08-18 14:21       ` Luiz Capitulino
2016-08-18 13:53     ` Stefan Hajnoczi
2016-08-18 10:22   ` Lluís Vilanova
2016-08-18 10:54 ` Stefan Hajnoczi
2016-08-18 10:54   ` Stefan Hajnoczi
2016-08-18 13:37   ` [Qemu-devel] " Luiz Capitulino
2016-08-19  4:45     ` Masami Hiramatsu
2016-08-19  4:45       ` Masami Hiramatsu
2016-08-18 13:37   ` [Qemu-devel] " Luiz Capitulino
2016-08-18 16:19   ` Steven Rostedt
2016-08-19 10:02     ` Stefan Hajnoczi
2016-08-19 13:30       ` Steven Rostedt
2016-08-19 13:30       ` Steven Rostedt
2016-08-19 10:02     ` Stefan Hajnoczi
2016-08-18 16:19   ` Steven Rostedt
2016-08-21 12:32   ` Lluís Vilanova
2016-08-23 15:54     ` Stefan Hajnoczi
2016-08-23 15:54     ` Stefan Hajnoczi
2016-08-24 10:25       ` Lluís Vilanova
2016-08-29 13:45         ` Stefan Hajnoczi
2016-08-29 13:45           ` Stefan Hajnoczi
2016-08-29 18:46           ` [Qemu-devel] " Lluís Vilanova
2016-08-29 18:46           ` Lluís Vilanova
2016-08-31 16:35             ` Stefan Hajnoczi
2016-08-31 16:35             ` Stefan Hajnoczi
2016-09-05 14:37               ` Lluís Vilanova
2016-09-05 14:37               ` Lluís Vilanova
2016-09-05 19:20                 ` Masami Hiramatsu
2016-09-05 19:20                   ` Masami Hiramatsu
2016-09-06 12:59                   ` [Qemu-devel] " Lluís Vilanova
2016-09-06 12:59                   ` Lluís Vilanova
2016-09-13 13:52                 ` Stefan Hajnoczi
2016-09-13 13:52                   ` Stefan Hajnoczi
2016-09-13 16:50                   ` [Qemu-devel] " Lluís Vilanova
2016-09-13 16:50                   ` Lluís Vilanova
2016-09-05 14:59             ` Daniel P. Berrange
2016-09-05 14:59               ` Daniel P. Berrange
2016-09-05 18:29               ` [Qemu-devel] " Lluís Vilanova
2016-09-05 18:59                 ` Daniel P. Berrange
2016-09-06  8:54                   ` Lluís Vilanova
2016-09-06  8:54                   ` Lluís Vilanova
2016-09-05 18:59                 ` Daniel P. Berrange
2016-09-05 18:29               ` Lluís Vilanova
2016-08-24 10:25       ` Lluís Vilanova
2016-08-21 12:32   ` Lluís Vilanova

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=147041639047.2523.7352313284957186583.stgit@fimbulvetr.bsc.es \
    --to=vilanova@ac.upc.edu \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

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

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