powerpc: Add helper functions for synthesising instructions at runtime

There's a few places already, and soon will be more, where we synthesise
branch instructions at runtime. Rather than doing it by hand in each case,
it would make sense to have one implementation.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h
index 5b2ecbc..b5da0b8 100644
--- a/include/asm-powerpc/system.h
+++ b/include/asm-powerpc/system.h
@@ -359,5 +359,53 @@
 
 #define PTRRELOC(x)	((typeof(x)) add_reloc_offset((unsigned long)(x)))
 
+static inline void create_instruction(unsigned long addr, unsigned int instr)
+{
+	unsigned int *p;
+	p  = (unsigned int *)addr;
+	*p = instr;
+	asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (p));
+}
+
+/* Flags for create_branch:
+ * "b"   == create_branch(addr, target, 0);
+ * "ba"  == create_branch(addr, target, BRANCH_ABSOLUTE);
+ * "bl"  == create_branch(addr, target, BRANCH_SET_LINK);
+ * "bla" == create_branch(addr, target, BRANCH_ABSOLUTE | BRANCH_SET_LINK);
+ */
+#define BRANCH_SET_LINK	0x1
+#define BRANCH_ABSOLUTE	0x2
+
+static inline void create_branch(unsigned long addr,
+		unsigned long target, int flags)
+{
+	unsigned int instruction;
+
+	if (! (flags & BRANCH_ABSOLUTE))
+		target = target - addr;
+
+	/* Mask out the flags and target, so they don't step on each other. */
+	instruction = 0x48000000 | (flags & 0x3) | (target & 0x03FFFFFC);
+
+	create_instruction(addr, instruction);
+}
+
+static inline void create_function_call(unsigned long addr, void * func)
+{
+	unsigned long func_addr;
+
+#ifdef CONFIG_PPC64
+	/*
+	 * On PPC64 the function pointer actually points to the function's
+	 * descriptor. The first entry in the descriptor is the address
+	 * of the function text.
+	 */
+	func_addr = *(unsigned long *)func;
+#else
+	func_addr = (unsigned long)func;
+#endif
+	create_branch(addr, func_addr, BRANCH_SET_LINK);
+}
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_SYSTEM_H */