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:
parent
e19e4ab415
commit
c87ef1171d
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user