aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis R. Rodriguez <mcgrof@kernel.org>2016-06-28 11:19:52 -0700
committerLuis R. Rodriguez <mcgrof@kernel.org>2016-06-29 17:29:05 -0700
commit923a4eb88b45bc947812a394d3acb92dd4f4bbf3 (patch)
tree4700cb2a70cbba307c29cd9c52c5e45abd93c0d2
parent3adf023d2a05a89f4851bd49fd6a3be78bb7f77f (diff)
downloadlinker-tables-923a4eb88b45bc947812a394d3acb92dd4f4bbf3.tar.gz
synth: add partially static shift right demo
This demos the use of "partially static" variables, they like consts, however we modify them early in boot time and provide functions that do the handy work for us. The handy work of processing them is accomplished through kernel's alternatives. To this end we add an example simple alternatives processing mechanism, its architecture is rather simple given it simply relies on the linker table with structural data, and updates it as needed. We demo a partially static function which shifts a variable to the right by certain amount of times, the amount of times we shift is determined through a function passed early in boot, and as such can be dynamic. Without alternatives processed you'd get: Synthetics: ps_shr(0XDEADBEEF) returns: 0xDEADBEEF After alternatives is processed you get: Synthetics: ps_shr(0XDEADBEEF) returns: 0x0000DEAD Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
-rw-r--r--Makefile1
-rw-r--r--arch/x86/kernel/alternative.c31
-rw-r--r--drivers/synth/main.c13
-rw-r--r--include/linux/ps_const.h42
4 files changed, 87 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 33f91a6..08115d6 100644
--- a/Makefile
+++ b/Makefile
@@ -42,6 +42,7 @@ OBJS = \
arch/x86/kernel/head64.c \
kasan.o\
memory.o \
+ arch/x86/kernel/alternative.o \
arch/x86/kernel/init.o \
kernel/locking/mutex.o \
kernel/locking/spinlock.o \
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
new file mode 100644
index 0000000..ed80a82
--- /dev/null
+++ b/arch/x86/kernel/alternative.c
@@ -0,0 +1,31 @@
+#include <asm/x86_init_fn.h>
+
+#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
+void apply_alternatives_linker_tables(void)
+{
+ unsigned int num_consts = LINUX_SECTION_SIZE(ps_set_const_table);
+ struct ps_set_const *ps_const;
+
+ if (!num_consts)
+ return;
+
+ pr_debug("Number of init entries: %d\n", num_consts);
+
+ LINKTABLE_FOR_EACH(ps_const, ps_set_const_table) {
+ switch(ps_const->type) {
+ case SET_CONST_U8:
+ *ps_const->count = (__u8) ps_const->func();
+ break;
+ case SET_CONST_U16:
+ *ps_const->count = (__u16) ps_const->func();
+ break;
+ case SET_CONST_U32:
+ *ps_const->count = (__u16) ps_const->func();
+ break;
+ }
+ }
+}
+
+x86_init_early_pc(apply_alternatives_linker_tables);
diff --git a/drivers/synth/main.c b/drivers/synth/main.c
index 4899e67..e776f6f 100644
--- a/drivers/synth/main.c
+++ b/drivers/synth/main.c
@@ -2,17 +2,30 @@
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
#include "common.h"
#include "synth.h"
+DEFINE_LINKTABLE_INIT_DATA(struct ps_set_const, ps_set_const_table);
+
+unsigned int get_demo_shr(void)
+{
+ return 16;
+}
+
static int synth_init(void)
{
int synth_or;
int val = 2;
+ unsigned int reg;
synth_or = synth_init_or(val);
pr_info("synth_init_or(%d) returns: 0x%08X\n", val, synth_or);
+ reg = ps_shr(0xDEADBEEF, get_demo_shr);
+ pr_info("ps_shr(0x%08X, get_demo_shr) returns: 0x%08X\n", 0xDEADBEEF, reg);
+
return 0;
}
module_init(synth_init);
diff --git a/include/linux/ps_const.h b/include/linux/ps_const.h
new file mode 100644
index 0000000..1747421
--- /dev/null
+++ b/include/linux/ps_const.h
@@ -0,0 +1,42 @@
+#ifndef __PS_CONST
+#define __PS_CONST
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/tables.h>
+
+/* Helpers for partially static settings */
+
+enum ps_static_type {
+ SET_CONST_U8 = 0,
+ SET_CONST_U16,
+ SET_CONST_U32,
+};
+
+struct ps_set_const {
+ unsigned int *count;
+ enum ps_static_type type;
+ unsigned int (*func)(void);
+};
+
+DECLARE_LINKTABLE(struct ps_set_const, ps_set_const_table);
+
+/*
+ * ps_ stands for "partially static", so we "partialloy static shift right"
+ * You can optimize this for your architecture.
+ *
+ * ps_shr(unsigned int in, unsigned char (*func)(void))
+ */
+#ifndef ps_shr
+#define ps_shr(_in, _func) \
+({ \
+ static unsigned int _count; \
+ static LINKTABLE_INIT_DATA(ps_set_const_table, 01) \
+ __ps_shr##__func = \
+ { &_count, SET_CONST_U8, (_func) }; \
+ \
+ (_in) >> _count; \
+})
+#endif /* ps_shr */
+
+#endif /* __PS_CONST */