[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 6/6] hypertrace: Add guest-side Linux module
From: |
Lluís Vilanova |
Subject: |
[Qemu-devel] [PATCH 6/6] hypertrace: Add guest-side Linux module |
Date: |
Fri, 5 Aug 2016 18:59:56 +0200 |
User-agent: |
StGit/0.17.1-dirty |
Provides guest Linux kernel module "qemu-hypertrace.ko" to abstract
access to the hypertrace channel.
Signed-off-by: Lluís Vilanova <address@hidden>
---
Makefile | 4 -
configure | 4 +
hypertrace/guest/linux-module/Kbuild.in | 5 +
hypertrace/guest/linux-module/Makefile | 24 ++++
.../include/linux/qemu-hypertrace-internal.h | 46 +++++++
.../linux-module/include/linux/qemu-hypertrace.h | 71 +++++++++++
hypertrace/guest/linux-module/qemu-hypertrace.c | 133 ++++++++++++++++++++
7 files changed, 286 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 bebd6e6..26fb418 100644
--- a/Makefile
+++ b/Makefile
@@ -460,8 +460,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 076eb8b..b809f69 100755
--- a/configure
+++ b/configure
@@ -5782,6 +5782,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..87656d4
--- /dev/null
+++ b/hypertrace/guest/linux-module/Kbuild.in
@@ -0,0 +1,5 @@
+# -*- mode: makefile -*-
+
+src = $(MOD_SRC_PATH)
+ccflags-y := -I$(src)/include/ -DHYPERTRACE_NUM_ARGS=$(HYPERTRACE_NUM_ARGS)
+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..d9247a0
--- /dev/null
+++ b/hypertrace/guest/linux-module/Makefile
@@ -0,0 +1,24 @@
+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) \
+ HYPERTRACE_NUM_ARGS=$(CONFIG_HYPERTRACE_ARGS) \
+ 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..465c003
--- /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 <address@hidden>
+ *
+ * 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_num_args;
+extern uint64_t _qemu_hypertrace_channel_max_offset;
+extern uint64_t *_qemu_hypertrace_channel_data;
+extern uint64_t *_qemu_hypertrace_channel_control;
+
+static inline uint64_t qemu_hypertrace_num_args(void)
+{
+ return _qemu_hypertrace_channel_num_args;
+}
+
+static inline uint64_t qemu_hypertrace_max_offset(void)
+{
+ return _qemu_hypertrace_channel_max_offset;
+}
+
+static inline uint64_t *qemu_hypertrace_data(uint64_t data_offset)
+{
+ size_t args_size = qemu_hypertrace_num_args() * sizeof(uint64_t);
+ return &_qemu_hypertrace_channel_data[data_offset * args_size];
+}
+
+static inline void qemu_hypertrace (uint64_t data_offset)
+{
+ uint64_t *ctrlp = _qemu_hypertrace_channel_control;
+ ctrlp[1] = data_offset;
+}
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..bb6ad7f
--- /dev/null
+++ b/hypertrace/guest/linux-module/include/linux/qemu-hypertrace.h
@@ -0,0 +1,71 @@
+/* -*- C -*-
+ *
+ * Guest-side management of hypertrace.
+ *
+ * Copyright (C) 2016 Lluís Vilanova <address@hidden>
+ *
+ * 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_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_size:
+ *
+ * Maximum data offset value accepted by other calls.
+ */
+static 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.
+ */
+static 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., CPU) 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).
+ *
+ * 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 data_offset);
+
+
+#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..43d35d7
--- /dev/null
+++ b/hypertrace/guest/linux-module/qemu-hypertrace.c
@@ -0,0 +1,133 @@
+/*
+ * Guest-side management of hypertrace.
+ *
+ * Copyright (C) 2016 Lluís Vilanova <address@hidden>
+ *
+ * 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 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_num_args = HYPERTRACE_NUM_ARGS;
+uint64_t _qemu_hypertrace_channel_max_offset = 0;
+uint64_t *_qemu_hypertrace_channel_control = NULL;
+uint64_t *_qemu_hypertrace_channel_data = NULL;
+
+EXPORT_SYMBOL(_qemu_hypertrace_channel_num_args);
+EXPORT_SYMBOL(_qemu_hypertrace_channel_max_offset);
+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;
+ size_t args_size;
+ size_t data_size;
+
+ 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_control, dev, 0);
+ if (res != 0) {
+ printk(KERN_ERR "Unable to find hypertrace control channel\n");
+ goto error;
+ }
+
+ res = init_channel(&_qemu_hypertrace_channel_data, dev, 1);
+ if (res != 0) {
+ printk(KERN_ERR "Unable to find hypertrace data channel\n");
+ goto error_data;
+ }
+
+ args_size = _qemu_hypertrace_channel_num_args * sizeof(uint64_t);
+ data_size = pci_resource_len(dev, 1);
+ _qemu_hypertrace_channel_max_offset = data_size / args_size;
+
+ goto ok;
+
+error_data:
+ iounmap(_qemu_hypertrace_channel_control);
+
+error:
+ _qemu_hypertrace_channel_control = NULL;
+ _qemu_hypertrace_channel_data = NULL;
+
+ok:
+ return res;
+}
+
+void cleanup_module(void)
+{
+ printk(KERN_NOTICE "Unloading QEMU hypertrace module\n");
+
+ iounmap(_qemu_hypertrace_channel_control);
+ iounmap(_qemu_hypertrace_channel_data);
+}
Re: [Qemu-devel] [PATCH 0/6] hypertrace: Lightweight guest-to-QEMU trace channel, Stefan Hajnoczi, 2016/08/18