Skip to content

Commit c71b7ef

Browse files
powerpc: Add ABIv2 support to ppc_function_entry
Skip over the well known global entry point code for ABIv2. Signed-off-by: Anton Blanchard <[email protected]>
1 parent 814e4cd commit c71b7ef

File tree

1 file changed

+36
-4
lines changed

1 file changed

+36
-4
lines changed

arch/powerpc/include/asm/code-patching.h

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,47 @@ void __patch_exception(int exc, unsigned long addr);
4242
} while (0)
4343
#endif
4444

45+
#define OP_RT_RA_MASK 0xffff0000UL
46+
#define LIS_R2 0x3c020000UL
47+
#define ADDIS_R2_R12 0x3c4c0000UL
48+
#define ADDI_R2_R2 0x38420000UL
49+
4550
static inline unsigned long ppc_function_entry(void *func)
4651
{
47-
#ifdef CONFIG_PPC64
52+
#if defined(CONFIG_PPC64)
53+
#if defined(_CALL_ELF) && _CALL_ELF == 2
54+
u32 *insn = func;
55+
56+
/*
57+
* A PPC64 ABIv2 function may have a local and a global entry
58+
* point. We need to use the local entry point when patching
59+
* functions, so identify and step over the global entry point
60+
* sequence.
61+
*
62+
* The global entry point sequence is always of the form:
63+
*
64+
* addis r2,r12,XXXX
65+
* addi r2,r2,XXXX
66+
*
67+
* A linker optimisation may convert the addis to lis:
68+
*
69+
* lis r2,XXXX
70+
* addi r2,r2,XXXX
71+
*/
72+
if ((((*insn & OP_RT_RA_MASK) == ADDIS_R2_R12) ||
73+
((*insn & OP_RT_RA_MASK) == LIS_R2)) &&
74+
((*(insn+1) & OP_RT_RA_MASK) == ADDI_R2_R2))
75+
return (unsigned long)(insn + 2);
76+
else
77+
return (unsigned long)func;
78+
#else
4879
/*
49-
* On PPC64 the function pointer actually points to the function's
50-
* descriptor. The first entry in the descriptor is the address
51-
* of the function text.
80+
* On PPC64 ABIv1 the function pointer actually points to the
81+
* function's descriptor. The first entry in the descriptor is the
82+
* address of the function text.
5283
*/
5384
return ((func_descr_t *)func)->entry;
85+
#endif
5486
#else
5587
return (unsigned long)func;
5688
#endif

0 commit comments

Comments
 (0)