powerpc: Add ABIv2 support to ppc_function_entry
Skip over the well known global entry point code for ABIv2. Signed-off-by: Anton Blanchard <anton@samba.org>
This commit is contained in:
parent
814e4cd98f
commit
c71b7eff42
|
@ -42,15 +42,47 @@ void __patch_exception(int exc, unsigned long addr);
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define OP_RT_RA_MASK 0xffff0000UL
|
||||||
|
#define LIS_R2 0x3c020000UL
|
||||||
|
#define ADDIS_R2_R12 0x3c4c0000UL
|
||||||
|
#define ADDI_R2_R2 0x38420000UL
|
||||||
|
|
||||||
static inline unsigned long ppc_function_entry(void *func)
|
static inline unsigned long ppc_function_entry(void *func)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_PPC64
|
#if defined(CONFIG_PPC64)
|
||||||
|
#if defined(_CALL_ELF) && _CALL_ELF == 2
|
||||||
|
u32 *insn = func;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On PPC64 the function pointer actually points to the function's
|
* A PPC64 ABIv2 function may have a local and a global entry
|
||||||
* descriptor. The first entry in the descriptor is the address
|
* point. We need to use the local entry point when patching
|
||||||
* of the function text.
|
* functions, so identify and step over the global entry point
|
||||||
|
* sequence.
|
||||||
|
*
|
||||||
|
* The global entry point sequence is always of the form:
|
||||||
|
*
|
||||||
|
* addis r2,r12,XXXX
|
||||||
|
* addi r2,r2,XXXX
|
||||||
|
*
|
||||||
|
* A linker optimisation may convert the addis to lis:
|
||||||
|
*
|
||||||
|
* lis r2,XXXX
|
||||||
|
* addi r2,r2,XXXX
|
||||||
|
*/
|
||||||
|
if ((((*insn & OP_RT_RA_MASK) == ADDIS_R2_R12) ||
|
||||||
|
((*insn & OP_RT_RA_MASK) == LIS_R2)) &&
|
||||||
|
((*(insn+1) & OP_RT_RA_MASK) == ADDI_R2_R2))
|
||||||
|
return (unsigned long)(insn + 2);
|
||||||
|
else
|
||||||
|
return (unsigned long)func;
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* On PPC64 ABIv1 the function pointer actually points to the
|
||||||
|
* function's descriptor. The first entry in the descriptor is the
|
||||||
|
* address of the function text.
|
||||||
*/
|
*/
|
||||||
return ((func_descr_t *)func)->entry;
|
return ((func_descr_t *)func)->entry;
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
return (unsigned long)func;
|
return (unsigned long)func;
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user