diff options
Diffstat (limited to 'arch/powerpc/kernel/module_64.c')
| -rw-r--r-- | arch/powerpc/kernel/module_64.c | 48 | 
1 files changed, 32 insertions, 16 deletions
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index a2636c250b7b..b8d61e019d06 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c @@ -280,6 +280,10 @@ static unsigned long get_stubs_size(const Elf64_Ehdr *hdr,  #ifdef CONFIG_DYNAMIC_FTRACE  	/* make the trampoline to the ftrace_caller */  	relocs++; +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS +	/* an additional one for ftrace_regs_caller */ +	relocs++; +#endif  #endif  	pr_debug("Looks like a total of %lu stubs, max\n", relocs); @@ -462,9 +466,12 @@ static unsigned long stub_for_addr(const Elf64_Shdr *sechdrs,  	return (unsigned long)&stubs[i];  } -#ifdef CC_USING_MPROFILE_KERNEL -static bool is_early_mcount_callsite(u32 *instruction) +#ifdef CONFIG_MPROFILE_KERNEL +static bool is_mprofile_mcount_callsite(const char *name, u32 *instruction)  { +	if (strcmp("_mcount", name)) +		return false; +  	/*  	 * Check if this is one of the -mprofile-kernel sequences.  	 */ @@ -496,8 +503,7 @@ static void squash_toc_save_inst(const char *name, unsigned long addr)  #else  static void squash_toc_save_inst(const char *name, unsigned long addr) { } -/* without -mprofile-kernel, mcount calls are never early */ -static bool is_early_mcount_callsite(u32 *instruction) +static bool is_mprofile_mcount_callsite(const char *name, u32 *instruction)  {  	return false;  } @@ -505,11 +511,11 @@ static bool is_early_mcount_callsite(u32 *instruction)  /* We expect a noop next: if it is, replace it with instruction to     restore r2. */ -static int restore_r2(u32 *instruction, struct module *me) +static int restore_r2(const char *name, u32 *instruction, struct module *me)  {  	u32 *prev_insn = instruction - 1; -	if (is_early_mcount_callsite(prev_insn)) +	if (is_mprofile_mcount_callsite(name, prev_insn))  		return 1;  	/* @@ -650,7 +656,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,  				value = stub_for_addr(sechdrs, value, me);  				if (!value)  					return -ENOENT; -				if (!restore_r2((u32 *)location + 1, me)) +				if (!restore_r2(strtab + sym->st_name, +							(u32 *)location + 1, me))  					return -ENOEXEC;  				squash_toc_save_inst(strtab + sym->st_name, value); @@ -746,7 +753,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,  #ifdef CONFIG_DYNAMIC_FTRACE -#ifdef CC_USING_MPROFILE_KERNEL +#ifdef CONFIG_MPROFILE_KERNEL  #define PACATOC offsetof(struct paca_struct, kernel_toc) @@ -762,7 +769,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,   * via the paca (in r13). The target (ftrace_caller()) is responsible for   * saving and restoring the toc before returning.   */ -static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, struct module *me) +static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, +				struct module *me, unsigned long addr)  {  	struct ppc64_stub_entry *entry;  	unsigned int i, num_stubs; @@ -789,9 +797,10 @@ static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, struct module  	memcpy(entry->jump, stub_insns, sizeof(stub_insns));  	/* Stub uses address relative to kernel toc (from the paca) */ -	reladdr = (unsigned long)ftrace_caller - kernel_toc_addr(); +	reladdr = addr - kernel_toc_addr();  	if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) { -		pr_err("%s: Address of ftrace_caller out of range of kernel_toc.\n", me->name); +		pr_err("%s: Address of %ps out of range of kernel_toc.\n", +							me->name, (void *)addr);  		return 0;  	} @@ -799,22 +808,29 @@ static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, struct module  	entry->jump[2] |= PPC_LO(reladdr);  	/* Eventhough we don't use funcdata in the stub, it's needed elsewhere. */ -	entry->funcdata = func_desc((unsigned long)ftrace_caller); +	entry->funcdata = func_desc(addr);  	entry->magic = STUB_MAGIC;  	return (unsigned long)entry;  }  #else -static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, struct module *me) +static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, +				struct module *me, unsigned long addr)  { -	return stub_for_addr(sechdrs, (unsigned long)ftrace_caller, me); +	return stub_for_addr(sechdrs, addr, me);  }  #endif  int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs)  { -	mod->arch.toc = my_r2(sechdrs, mod); -	mod->arch.tramp = create_ftrace_stub(sechdrs, mod); +	mod->arch.tramp = create_ftrace_stub(sechdrs, mod, +					(unsigned long)ftrace_caller); +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS +	mod->arch.tramp_regs = create_ftrace_stub(sechdrs, mod, +					(unsigned long)ftrace_regs_caller); +	if (!mod->arch.tramp_regs) +		return -ENOENT; +#endif  	if (!mod->arch.tramp)  		return -ENOENT;  |