aboutsummaryrefslogtreecommitdiff
path: root/arch/mips/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/process.c')
-rw-r--r--arch/mips/kernel/process.c98
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, &current->thread.fpu, sizeof(current->thread.fpu));
+ int i;
+
+ for (i = 0; i < NUM_FPU_REGS; i++)
+ memcpy(&r[i], &current->thread.fpu.fpr[i], sizeof(*r));
+
+ memcpy(&r[NUM_FPU_REGS], &current->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);