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>
This commit is contained in:
Michael Ellerman 2005-11-03 17:57:53 +11:00
parent e19e4ab415
commit c87ef1171d

View File

@ -359,5 +359,53 @@ extern void reloc_got2(unsigned long);
#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 */