|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v4 33/34] 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.
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>
v2: Add Copyright
---
---
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 9b7fac7..200a544 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -62,6 +62,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..4196a0a
--- /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 256
+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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |