[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v5 27/28] xsplice: Add support for shadow variables.



From: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>

Shadow variables are a piece of infrastructure to be used by xsplice
modules. They are used to attach a new piece of data to an existing
structure in memory.

Martin Pohlack also mentions that using the SHADOW_SLOTS of small
prime numbers has the advantage of having a simple hash function.
Using round numbers (such as 256) will give "lot's of hash collisions
at the price of very fast hash computations as compilers, linkers, and
memory allocators tend to align starting addresses." (Martin)

Signed-off-by: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
---
Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Cc: Jan Beulich <jbeulich@xxxxxxxx>
Cc: Keir Fraser <keir@xxxxxxx>
Cc: Tim Deegan <tim@xxxxxxx>

v4: Add Copyright
v5: Change SHADOW_SLOTS to 257 per Martin's suggestion.
---
---
 xen/common/Makefile             |   1 +
 xen/common/xsplice_shadow.c     | 109 ++++++++++++++++++++++++++++++++++++++++
 xen/include/xen/xsplice_patch.h |  36 +++++++++++++
 3 files changed, 146 insertions(+)
 create mode 100644 xen/common/xsplice_shadow.c

diff --git a/xen/common/Makefile b/xen/common/Makefile
index afd84b6..8371e2c 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_XENOPROF) += xenoprof.o
 obj-y += xmalloc_tlsf.o
 obj-$(CONFIG_XSPLICE) += xsplice.o
 obj-$(CONFIG_XSPLICE) += xsplice_elf.o
+obj-$(CONFIG_XSPLICE) += xsplice_shadow.o
 
 obj-bin-$(CONFIG_X86) += $(foreach n,decompress bunzip2 unxz unlzma unlzo 
unlz4 earlycpio,$(n).init.o)
 
diff --git a/xen/common/xsplice_shadow.c b/xen/common/xsplice_shadow.c
new file mode 100644
index 0000000..8c63d62
--- /dev/null
+++ b/xen/common/xsplice_shadow.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 Citrix Systems R&D Ltd.
+ */
+
+#include <xen/init.h>
+#include <xen/kernel.h>
+#include <xen/lib.h>
+#include <xen/list.h>
+#include <xen/spinlock.h>
+#include <xen/xsplice_patch.h>
+
+#define SHADOW_SLOTS 257
+struct hlist_head shadow_tbl[SHADOW_SLOTS];
+static DEFINE_SPINLOCK(shadow_lock);
+
+struct shadow_var {
+    struct hlist_node list;         /* Linked to 'shadow_tbl' */
+    void *data;
+    const void *obj;
+    char var[16];
+};
+
+void *xsplice_shadow_alloc(const void *obj, const char *var, size_t size)
+{
+    struct shadow_var *shadow;
+    unsigned int slot;
+
+    shadow = xmalloc(struct shadow_var);
+    if ( !shadow )
+        return NULL;
+
+    shadow->obj = obj;
+    strlcpy(shadow->var, var, sizeof shadow->var);
+    shadow->data = xmalloc_bytes(size);
+    if ( !shadow->data )
+    {
+        xfree(shadow);
+        return NULL;
+    }
+
+    slot = (unsigned long)obj % SHADOW_SLOTS;
+    spin_lock(&shadow_lock);
+    hlist_add_head(&shadow->list, &shadow_tbl[slot]);
+    spin_unlock(&shadow_lock);
+
+    return shadow->data;
+}
+
+void xsplice_shadow_free(const void *obj, const char *var)
+{
+    struct shadow_var *entry, *shadow = NULL;
+    unsigned int slot;
+    struct hlist_node *next;
+
+    slot = (unsigned long)obj % SHADOW_SLOTS;
+
+    spin_lock(&shadow_lock);
+    hlist_for_each_entry(entry, next, &shadow_tbl[slot], list)
+    {
+        if ( entry->obj == obj &&
+             !strcmp(entry->var, var) )
+        {
+            shadow = entry;
+            break;
+        }
+    }
+    if (shadow)
+    {
+        hlist_del(&shadow->list);
+        xfree(shadow->data);
+        xfree(shadow);
+    }
+    spin_unlock(&shadow_lock);
+}
+
+void *xsplice_shadow_get(const void *obj, const char *var)
+{
+    struct shadow_var *entry;
+    unsigned int slot;
+    struct hlist_node *next;
+    void *ret = NULL;
+
+    slot = (unsigned long)obj % SHADOW_SLOTS;
+
+    spin_lock(&shadow_lock);
+    hlist_for_each_entry(entry, next, &shadow_tbl[slot], list)
+    {
+        if ( entry->obj == obj &&
+             !strcmp(entry->var, var) )
+        {
+            ret = entry->data;
+            break;
+        }
+    }
+
+    spin_unlock(&shadow_lock);
+    return ret;
+}
+
+static int __init xsplice_shadow_init(void)
+{
+    int i;
+
+    for ( i = 0; i < SHADOW_SLOTS; i++ )
+        INIT_HLIST_HEAD(&shadow_tbl[i]);
+
+    return 0;
+}
+__initcall(xsplice_shadow_init);
diff --git a/xen/include/xen/xsplice_patch.h b/xen/include/xen/xsplice_patch.h
index 19d3f76..e297fe1 100644
--- a/xen/include/xen/xsplice_patch.h
+++ b/xen/include/xen/xsplice_patch.h
@@ -56,4 +56,40 @@ typedef void (*xsplice_unloadcall_t)(void);
 #define XSPLICE_UNLOAD_HOOK(_fn) \
        xsplice_unloadcall_t __attribute__((weak)) xsplice_unload_data 
__section(".xsplice.hooks.unload") = _fn;
 
+
+/*
+ * The following definitions are to be used in patches. They are taken
+ * from kpatch.
+ */
+
+/*
+ * xsplice shadow variables
+ *
+ * These functions can be used to add new "shadow" fields to existing data
+ * structures.  For example, to allocate a "newpid" variable associated with an
+ * instance of task_struct, and assign it a value of 1000:
+ *
+ * struct task_struct *tsk = current;
+ * int *newpid;
+ * newpid = xsplice_shadow_alloc(tsk, "newpid", sizeof(int));
+ * if (newpid)
+ *     *newpid = 1000;
+ *
+ * To retrieve a pointer to the variable:
+ *
+ * struct task_struct *tsk = current;
+ * int *newpid;
+ * newpid = xsplice_shadow_get(tsk, "newpid");
+ * if (newpid)
+ *     printk("task newpid = %d\n", *newpid); // prints "task newpid = 1000"
+ *
+ * To free it:
+ *
+ * xsplice_shadow_free(tsk, "newpid");
+ */
+
+void *xsplice_shadow_alloc(const void *obj, const char *var, size_t size);
+void xsplice_shadow_free(const void *obj, const char *var);
+void *xsplice_shadow_get(const void *obj, const char *var);
+
 #endif /* __XEN_XSPLICE_PATCH_H__ */
-- 
2.5.0


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.