Skip to content

Commit

Permalink
powerpc: Add ABIv2 support to ppc_function_entry
Browse files Browse the repository at this point in the history
Skip over the well known global entry point code for ABIv2.

Signed-off-by: Anton Blanchard <anton@samba.org>
  • Loading branch information
antonblanchard committed Apr 23, 2014
1 parent 814e4cd commit c71b7ef
Showing 1 changed file with 36 additions and 4 deletions.
40 changes: 36 additions & 4 deletions arch/powerpc/include/asm/code-patching.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,47 @@ void __patch_exception(int exc, unsigned long addr);
} while (0)
#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)
{
#ifdef CONFIG_PPC64
#if defined(CONFIG_PPC64)
#if defined(_CALL_ELF) && _CALL_ELF == 2
u32 *insn = func;

/*
* A PPC64 ABIv2 function may have a local and a global entry
* point. We need to use the local entry point when patching
* 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 the function pointer actually points to the function's
* descriptor. The first entry in the descriptor is the address
* of the function text.
* 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;
#endif
#else
return (unsigned long)func;
#endif
Expand Down

0 comments on commit c71b7ef

Please sign in to comment.