diff options
Diffstat (limited to 'arch/mips/kernel/process.c')
| -rw-r--r-- | arch/mips/kernel/process.c | 98 |
1 files changed, 63 insertions, 35 deletions
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index eb902c1f0ca..0a1ec0f3bef 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -32,6 +32,7 @@ #include <asm/cpu.h> #include <asm/dsp.h> #include <asm/fpu.h> +#include <asm/msa.h> #include <asm/pgtable.h> #include <asm/mipsregs.h> #include <asm/processor.h> @@ -51,19 +52,6 @@ void arch_cpu_idle_dead(void) } #endif -void arch_cpu_idle(void) -{ -#ifdef CONFIG_MIPS_MT_SMTC - extern void smtc_idle_loop_hook(void); - - smtc_idle_loop_hook(); -#endif - if (cpu_wait) - (*cpu_wait)(); - else - local_irq_enable(); -} - asmlinkage void ret_from_fork(void); asmlinkage void ret_from_kernel_thread(void); @@ -73,15 +61,13 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) /* New thread loses kernel privileges. */ status = regs->cp0_status & ~(ST0_CU0|ST0_CU1|ST0_FR|KU_MASK); -#ifdef CONFIG_64BIT - status |= test_thread_flag(TIF_32BIT_REGS) ? 0 : ST0_FR; -#endif status |= KU_USER; regs->cp0_status = status; clear_used_math(); clear_fpu_owner(); - if (cpu_has_dsp) - __init_dsp(); + init_dsp(); + clear_thread_flag(TIF_MSA_CTX_LIVE); + disable_msa(); regs->cp0_epc = pc; regs->regs[29] = sp; } @@ -106,7 +92,9 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, preempt_disable(); - if (is_fpu_owner()) + if (is_msa_enabled()) + save_msa(p); + else if (is_fpu_owner()) save_fp(p); if (cpu_has_dsp) @@ -152,13 +140,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, */ childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); -#ifdef CONFIG_MIPS_MT_SMTC - /* - * SMTC restores TCStatus after Status, and the CU bits - * are aliased there. - */ - childregs->cp0_tcstatus &= ~(ST0_CU2|ST0_CU1); -#endif clear_tsk_thread_flag(p, TIF_USEDFPU); #ifdef CONFIG_MIPS_MT_FPAFF @@ -174,7 +155,13 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, /* Fill in the fpu structure for a core dump.. */ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) { - memcpy(r, ¤t->thread.fpu, sizeof(current->thread.fpu)); + int i; + + for (i = 0; i < NUM_FPU_REGS; i++) + memcpy(&r[i], ¤t->thread.fpu.fpr[i], sizeof(*r)); + + memcpy(&r[NUM_FPU_REGS], ¤t->thread.fpu.fcr31, + sizeof(current->thread.fpu.fcr31)); return 1; } @@ -209,14 +196,23 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr) { - memcpy(fpr, &t->thread.fpu, sizeof(current->thread.fpu)); + int i; + + for (i = 0; i < NUM_FPU_REGS; i++) + memcpy(&fpr[i], &t->thread.fpu.fpr[i], sizeof(*fpr)); + + memcpy(&fpr[NUM_FPU_REGS], &t->thread.fpu.fcr31, + sizeof(t->thread.fpu.fcr31)); return 1; } -/* - * - */ +#ifdef CONFIG_CC_STACKPROTECTOR +#include <linux/stackprotector.h> +unsigned long __stack_chk_guard __read_mostly; +EXPORT_SYMBOL(__stack_chk_guard); +#endif + struct mips_frame_info { void *func; unsigned long func_size; @@ -224,6 +220,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 +263,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 +287,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 +351,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 +394,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); |
