drivers/synth: add initial synthetic "or" function using section ranges

This demos building a synthetic "or" function using section
ranges in asm. The file or.S consists of completely unordered pieces of
code, each doing different things and each also pegged onto separate
the same section, however specified with a specific order level.

The different pieces of unordered code illustrates how we'd expect code to
be gathered and compiled, each piece of code could realiastically be in
separate files. We add some #ifdefs with CONFIG_* options, we could also
expect that some of the code might be present and some of it might not
while it all still works together.

We'll later add support for building these pieces of code separately.

The linker stiches these pieces of code for us using the levels for
order, in the end it builds a single concise function which then runs
orderly.

Upon running this we get a series of variables OR'd together:

Synthetics: synth_init_or(2) returns: 0xDEADBEEF

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
diff --git a/Makefile b/Makefile
index b69ba24..33f91a6 100644
--- a/Makefile
+++ b/Makefile
@@ -53,6 +53,9 @@
 	beta.o \
 	alpha.o \
 	drivers/acme.o \
+	drivers/synth/main.o \
+	drivers/synth/common.o \
+	drivers/synth/or.S \
 	xen.o \
 	xen-driver.o \
 	main.o
diff --git a/drivers/synth/common.c b/drivers/synth/common.c
new file mode 100644
index 0000000..b44d9fc
--- /dev/null
+++ b/drivers/synth/common.c
@@ -0,0 +1,16 @@
+int demo_or_1(int arg)
+{
+	switch (arg) {
+	case 1:
+		return 0xDEA00000;
+	case 2:
+		return 0X000D0000;
+	default:
+		return arg * 2;
+	}
+}
+
+int demo_or_2(void)
+{
+	return 0x0000BEEF;
+}
diff --git a/drivers/synth/common.h b/drivers/synth/common.h
new file mode 100644
index 0000000..9282700
--- /dev/null
+++ b/drivers/synth/common.h
@@ -0,0 +1,2 @@
+int demo_or_1(int arg);
+int demo_or_2(void);
diff --git a/drivers/synth/main.c b/drivers/synth/main.c
new file mode 100644
index 0000000..4899e67
--- /dev/null
+++ b/drivers/synth/main.c
@@ -0,0 +1,23 @@
+#define pr_fmt(fmt) "Synthetics: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include "common.h"
+#include "synth.h"
+
+static int synth_init(void)
+{
+	int synth_or;
+	int val = 2;
+
+	synth_or = synth_init_or(val);
+	pr_info("synth_init_or(%d) returns: 0x%08X\n", val, synth_or);
+
+	return 0;
+}
+module_init(synth_init);
+
+static void synth_exit(void)
+{
+}
+module_exit(synth_exit);
diff --git a/drivers/synth/or.S b/drivers/synth/or.S
new file mode 100644
index 0000000..5a80526
--- /dev/null
+++ b/drivers/synth/or.S
@@ -0,0 +1,43 @@
+	.pushsection .init.text.rng.synth_init_or.
+	.globl synth_init_or
+synth_init_or:
+	.popsection
+
+	.pushsection .init.text.rng.synth_init_or.01
+	/* err = 0; */
+	pushq %rbp
+	movq %rsp,%rbp
+	pushq %rbx
+	xorq %rbx,%rbx
+	.popsection
+
+	.pushsection .init.text.rng.synth_init_or.~
+	.popsection
+
+	.pushsection .init.text.rng.synth_init_or.99
+	/* return err; */
+	movq %rbx,%rax
+	popq %rbx
+	popq %rbp
+	retq
+	.popsection
+
+	.pushsection .init.text.rng.synth_init_or.50
+	/* err |= demo_or_1(1); */
+	movl $1,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	.pushsection .init.text.rng.synth_init_or.50
+	/* err |= demo_or_1(2); */
+	movl $2,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	.pushsection .init.text.rng.synth_init_or.50
+	/* err |= demo_or_2(); */
+	call demo_or_2
+	orq %rax,%rbx
+	.popsection
diff --git a/drivers/synth/synth.h b/drivers/synth/synth.h
new file mode 100644
index 0000000..abbb9af
--- /dev/null
+++ b/drivers/synth/synth.h
@@ -0,0 +1,2 @@
+/* Synthetic demos go here */
+int synth_init_or(int arg);