diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-05-21 11:39:21 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-05-21 11:39:21 -0500 |
commit | 4510dbe324876f2f2f3dc9931e97ec0e98f1ee26 (patch) | |
tree | d42a8ff24b82e0c6b01756b3f2c33756fc30fc17 /arch/mips/kernel/process.c | |
parent | b296263398f08d21e68d5d7b2afc43228c208b71 (diff) | |
parent | c7788792a5e7b0d5d7f96d0766b4cb6112d47d75 (diff) | |
download | blackbird-op-linux-4510dbe324876f2f2f3dc9931e97ec0e98f1ee26.tar.gz blackbird-op-linux-4510dbe324876f2f2f3dc9931e97ec0e98f1ee26.zip |
Merge tag 'v3.10-rc2' into asoc-ux500
Linux 3.10-rc2
Diffstat (limited to 'arch/mips/kernel/process.c')
-rw-r--r-- | arch/mips/kernel/process.c | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index eb902c1f0cad..a682a87bcc04 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -224,6 +224,9 @@ struct mips_frame_info { int pc_offset; }; +#define J_TARGET(pc,target) \ + (((unsigned long)(pc) & 0xf0000000) | ((target) << 2)) + static inline int is_ra_save_ins(union mips_instruction *ip) { #ifdef CONFIG_CPU_MICROMIPS @@ -264,7 +267,7 @@ static inline int is_ra_save_ins(union mips_instruction *ip) #endif } -static inline int is_jal_jalr_jr_ins(union mips_instruction *ip) +static inline int is_jump_ins(union mips_instruction *ip) { #ifdef CONFIG_CPU_MICROMIPS /* @@ -288,6 +291,8 @@ static inline int is_jal_jalr_jr_ins(union mips_instruction *ip) return 0; return (((ip->u_format.uimmediate >> 6) & mm_jalr_op) == mm_jalr_op); #else + if (ip->j_format.opcode == j_op) + return 1; if (ip->j_format.opcode == jal_op) return 1; if (ip->r_format.opcode != spec_op) @@ -350,7 +355,7 @@ static int get_frame_info(struct mips_frame_info *info) for (i = 0; i < max_insns; i++, ip++) { - if (is_jal_jalr_jr_ins(ip)) + if (is_jump_ins(ip)) break; if (!info->frame_size) { if (is_sp_move_ins(ip)) @@ -393,15 +398,42 @@ err: static struct mips_frame_info schedule_mfi __read_mostly; +#ifdef CONFIG_KALLSYMS +static unsigned long get___schedule_addr(void) +{ + return kallsyms_lookup_name("__schedule"); +} +#else +static unsigned long get___schedule_addr(void) +{ + union mips_instruction *ip = (void *)schedule; + int max_insns = 8; + int i; + + for (i = 0; i < max_insns; i++, ip++) { + if (ip->j_format.opcode == j_op) + return J_TARGET(ip, ip->j_format.target); + } + return 0; +} +#endif + static int __init frame_info_init(void) { unsigned long size = 0; #ifdef CONFIG_KALLSYMS unsigned long ofs; +#endif + unsigned long addr; - kallsyms_lookup_size_offset((unsigned long)schedule, &size, &ofs); + addr = get___schedule_addr(); + if (!addr) + addr = (unsigned long)schedule; + +#ifdef CONFIG_KALLSYMS + kallsyms_lookup_size_offset(addr, &size, &ofs); #endif - schedule_mfi.func = schedule; + schedule_mfi.func = (void *)addr; schedule_mfi.func_size = size; get_frame_info(&schedule_mfi); |