forked from mirrors/linux
		
	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
					
				
					 1 changed files with 36 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -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;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * 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.
 | 
			
		||||
	 * 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 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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue