@@ -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) \
@@ -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]'
new file mode 100644
@@ -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
new file mode 100644
@@ -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 $< $@
new file mode 100644
@@ -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;
+}
new file mode 100644
@@ -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 */
new file mode 100644
@@ -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);
+}
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