[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v3 6/6] hypertrace: Add guest-side Linux module
From: |
Lluís Vilanova |
Subject: |
[Qemu-devel] [PATCH v3 6/6] hypertrace: Add guest-side Linux module |
Date: |
Wed, 28 Sep 2016 15:06:03 +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 | 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 | 149 ++++++++++++++++++++
7 files changed, 305 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 45c5c05..4bb31f7 100644
--- a/Makefile
+++ b/Makefile
@@ -464,8 +464,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 710bc91..f6d4ed7 100755
--- a/configure
+++ b/configure
@@ -5772,6 +5772,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..c439107
--- /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_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 <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_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..5f16ef0
--- /dev/null
+++ b/hypertrace/guest/linux-module/qemu-hypertrace.c
@@ -0,0 +1,149 @@
+/*
+ * 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 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, 2);
+ 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);
+}
- [Qemu-devel] [PATCH v3 0/6] hypertrace: Lightweight guest-to-QEMU trace channel, Lluís Vilanova, 2016/09/28
- [Qemu-devel] [PATCH v3 1/6] hypertrace: Add documentation, Lluís Vilanova, 2016/09/28
- [Qemu-devel] [PATCH v3 2/6] hypertrace: Add tracing event "guest_hypertrace", Lluís Vilanova, 2016/09/28
- [Qemu-devel] [PATCH v3 5/6] hypertrace: Add guest-side user-level library, Lluís Vilanova, 2016/09/28
- [Qemu-devel] [PATCH v3 3/6] hypertrace: [*-user] Add QEMU-side proxy to "guest_hypertrace" event, Lluís Vilanova, 2016/09/28
- [Qemu-devel] [PATCH v3 4/6] hypertrace: [softmmu] Add QEMU-side proxy to "guest_hypertrace" event, Lluís Vilanova, 2016/09/28
- [Qemu-devel] [PATCH v3 6/6] hypertrace: Add guest-side Linux module,
Lluís Vilanova <=
- Re: [Qemu-devel] [PATCH v3 0/6] hypertrace: Lightweight guest-to-QEMU trace channel, no-reply, 2016/09/28