aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorTony Wu <tung7970@gmail.com>2013-05-12 11:05:34 -0400
committerRalf Baechle <ralf@linux-mips.org>2013-05-17 14:59:35 -0400
commit5000653e923de49aa282fd7d172eb6528c3ec5c7 (patch)
tree8281f7a92a93c4b44af76b47c159c136905130e6 /arch/mips
parente7438c4b893e87311d2fb0facb3e6a0df17abe01 (diff)
MIPS: Extract schedule_mfi info from __schedule
schedule_mfi is supposed to be extracted from schedule(), and is used in thread_saved_pc and get_wchan. But, after optimization, schedule() is reduced to a sibling call to __schedule(), and no real frame info can be extracted. One solution is to compile schedule() with -fno-omit-frame-pointer and -fno-optimize-sibling-calls, but that will incur performance degradation. Another solution is to extract info from the real scheduler, __schedule, and this is the approache adopted here. This patch reads the __schedule address by either following the 'j' call in schedule if KALLSYMS is disabled or by using kallsyms_lookup_name to lookup __schedule if KALLSYMS is available, then, extracts schedule_mfi from __schedule frame info. This patch also fixes the "Can't analyze schedule() prologue" warning at boot time. Signed-off-by: Tony Wu <tung7970@gmail.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5237/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/kernel/process.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 785bf2a4129a..a682a87bcc04 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -224,6 +224,9 @@ struct mips_frame_info {
224 int pc_offset; 224 int pc_offset;
225}; 225};
226 226
227#define J_TARGET(pc,target) \
228 (((unsigned long)(pc) & 0xf0000000) | ((target) << 2))
229
227static inline int is_ra_save_ins(union mips_instruction *ip) 230static inline int is_ra_save_ins(union mips_instruction *ip)
228{ 231{
229#ifdef CONFIG_CPU_MICROMIPS 232#ifdef CONFIG_CPU_MICROMIPS
@@ -395,15 +398,42 @@ err:
395 398
396static struct mips_frame_info schedule_mfi __read_mostly; 399static struct mips_frame_info schedule_mfi __read_mostly;
397 400
401#ifdef CONFIG_KALLSYMS
402static unsigned long get___schedule_addr(void)
403{
404 return kallsyms_lookup_name("__schedule");
405}
406#else
407static unsigned long get___schedule_addr(void)
408{
409 union mips_instruction *ip = (void *)schedule;
410 int max_insns = 8;
411 int i;
412
413 for (i = 0; i < max_insns; i++, ip++) {
414 if (ip->j_format.opcode == j_op)
415 return J_TARGET(ip, ip->j_format.target);
416 }
417 return 0;
418}
419#endif
420
398static int __init frame_info_init(void) 421static int __init frame_info_init(void)
399{ 422{
400 unsigned long size = 0; 423 unsigned long size = 0;
401#ifdef CONFIG_KALLSYMS 424#ifdef CONFIG_KALLSYMS
402 unsigned long ofs; 425 unsigned long ofs;
426#endif
427 unsigned long addr;
403 428
404 kallsyms_lookup_size_offset((unsigned long)schedule, &size, &ofs); 429 addr = get___schedule_addr();
430 if (!addr)
431 addr = (unsigned long)schedule;
432
433#ifdef CONFIG_KALLSYMS
434 kallsyms_lookup_size_offset(addr, &size, &ofs);
405#endif 435#endif
406 schedule_mfi.func = schedule; 436 schedule_mfi.func = (void *)addr;
407 schedule_mfi.func_size = size; 437 schedule_mfi.func_size = size;
408 438
409 get_frame_info(&schedule_mfi); 439 get_frame_info(&schedule_mfi);