Patchwork [5/5] backdoor: Add guest-side library

login
register
mail settings
Submitter Lluís Vilanova
Date Sept. 29, 2011, 1:47 p.m.
Message ID <20110929134754.19559.6821.stgit@ginnungagap.bsc.es>
Download mbox | patch
Permalink /patch/116960/
State New
Headers show

Comments

Lluís Vilanova - Sept. 29, 2011, 1:47 p.m.
Guest applications can link against "libqemu-backdoor-guest.a" to use the
backdoor communication channel.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 backdoor/guest/Makefile        |   18 ++++++
 backdoor/guest/common.c        |  130 ++++++++++++++++++++++++++++++++++++++++
 backdoor/guest/qemu-backdoor.h |   50 +++++++++++++++
 configure                      |    2 +
 4 files changed, 200 insertions(+), 0 deletions(-)
 create mode 100644 backdoor/guest/Makefile
 create mode 100644 backdoor/guest/common.c
 create mode 100644 backdoor/guest/qemu-backdoor.h

Patch

diff --git a/backdoor/guest/Makefile b/backdoor/guest/Makefile
new file mode 100644
index 0000000..200ee3b
--- /dev/null
+++ b/backdoor/guest/Makefile
@@ -0,0 +1,18 @@ 
+include ../../../config-host.mak
+include ../../config-target.mak
+include $(SRC_PATH)/rules.mak
+
+vpath % $(SRC_PATH)/backdoor/guest
+
+QEMU_CFLAGS += $(GLIB_CFLAGS)
+QEMU_CFLAGS += -I../../../
+QEMU_CFLAGS += -I../../
+
+obj-y = common.o
+
+libqemu-backdoor-guest.a: $(obj-y)
+
+all: libqemu-backdoor-guest.a
+
+clean:
+	rm -f $(obj-y) libqemu-backdoor-guest.a
diff --git a/backdoor/guest/common.c b/backdoor/guest/common.c
new file mode 100644
index 0000000..7b4354f
--- /dev/null
+++ b/backdoor/guest/common.c
@@ -0,0 +1,130 @@ 
+/*
+ * Guest-side management of backdoor channels.
+ *
+ * Copyright (C) 2011 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-backdoor.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 "config-target.h"
+
+
+static char *data_path = NULL;
+static char *control_path = NULL;
+static int data_fd = -1;
+static int control_fd = -1;
+
+static void *data_addr = NULL;
+static void *control_addr = NULL;
+
+
+static int init_channel_file(const char *base, const char *suffix, size_t size,
+                             char ** path, int *fd, void **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;
+}
+
+int qemu_backdoor_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
+
+    int res;
+    res = init_channel_file(base, control_suff, control_size,
+                            &control_path, &control_fd, &control_addr);
+    if (res != 0) {
+        return res;
+    }
+
+    res = init_channel_file(base, data_suff, qemu_backdoor_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_backdoor_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_backdoor_data_size(void)
+{
+    return *(uint64_t*)control_addr;
+}
+
+void *qemu_backdoor_data(void)
+{
+    return data_addr;
+}
+
+void qemu_backdoor (uint64_t cmd)
+{
+    uint64_t *ctrl;
+    ctrl = control_addr;
+    ctrl[1] = cmd;
+#if defined(CONFIG_USER_ONLY)
+    /* QEMU in 'user' mode uses two faulting pages to detect invocations */
+    ctrl = control_addr + getpagesize();
+    ctrl[1] = cmd;
+#endif
+}
diff --git a/backdoor/guest/qemu-backdoor.h b/backdoor/guest/qemu-backdoor.h
new file mode 100644
index 0000000..99d4cb2
--- /dev/null
+++ b/backdoor/guest/qemu-backdoor.h
@@ -0,0 +1,50 @@ 
+/*
+ * Guest-side management of backdoor channels.
+ *
+ * Copyright (C) 2011 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>
+
+
+/** Initialize the backdoor channel.
+ *
+ * The base path to the backdoor channel is dependant on the type of QEMU
+ * target:
+ *
+ * - User (single-application)
+ *   The base path provided when starting QEMU ("-backdoor" commandline option).
+ *
+ * - Softmmu (full-system); OS-dependant
+ *   - Linux: The base path to the backdoor channel virtual device ("-device
+ *     backdoor" commandline option).
+ *
+ * @param base Base path to the backdoor channel.
+ * @return Zero on success.
+ */
+int qemu_backdoor_init(const char *base);
+
+/** Deinitialize the backdoor channel.
+ *
+ * @return Zero on success.
+ */
+int qemu_backdoor_fini(void);
+
+/** The amount of data that can be passed through the data channel. */
+uint64_t qemu_backdoor_data_size(void);
+/** Pointer to the start of the data channel. */
+void *qemu_backdoor_data(void);
+
+/** Invoke the control channel.
+ *
+ * The command in the control channel can be used to, e.g., differentiate
+ * between multiple users of the backdoor channel without resorting to the data
+ * channel for deambiguation.
+ *
+ * @param cmd Integral number passed out-of-band w.r.t the data channel.
+ */
+void qemu_backdoor(uint64_t cmd);
diff --git a/configure b/configure
index 74a6f5a..e982787 100755
--- a/configure
+++ b/configure
@@ -3217,6 +3217,8 @@  if test -n "$backdoor"; then
     mkdir -p $target_dir/libbackdoor
     symlink $backdoor/Makefile $target_dir/libbackdoor/Makefile
     mkdir -p $target_dir/backdoor/qemu
+    mkdir -p $target_dir/backdoor/guest
+    symlink $source_path/backdoor/guest/Makefile $target_dir/backdoor/guest/Makefile
 fi