diff options
-rw-r--r-- | arch/mips/kernel/process.c | 34 |
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 | |||
227 | static inline int is_ra_save_ins(union mips_instruction *ip) | 230 | static 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 | ||
396 | static struct mips_frame_info schedule_mfi __read_mostly; | 399 | static struct mips_frame_info schedule_mfi __read_mostly; |
397 | 400 | ||
401 | #ifdef CONFIG_KALLSYMS | ||
402 | static unsigned long get___schedule_addr(void) | ||
403 | { | ||
404 | return kallsyms_lookup_name("__schedule"); | ||
405 | } | ||
406 | #else | ||
407 | static 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 | |||
398 | static int __init frame_info_init(void) | 421 | static 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); |