diff options
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/cpu-probe.c | 7 | ||||
-rw-r--r-- | arch/mips/kernel/mips-r2-to-r6-emul.c | 16 | ||||
-rw-r--r-- | arch/mips/kernel/process.c | 6 | ||||
-rw-r--r-- | arch/mips/kernel/r4k_switch.S | 6 | ||||
-rw-r--r-- | arch/mips/kernel/smp-cps.c | 7 | ||||
-rw-r--r-- | arch/mips/kernel/smp-mt.c | 49 | ||||
-rw-r--r-- | arch/mips/kernel/smp.c | 20 |
7 files changed, 43 insertions, 68 deletions
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 3382892544f0..1aba27786bd5 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -34,6 +34,7 @@ /* Hardware capabilities */ unsigned int elf_hwcap __read_mostly; +EXPORT_SYMBOL_GPL(elf_hwcap); /* * Get the FPU Implementation/Revision. @@ -1955,6 +1956,12 @@ void cpu_probe(void) struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int cpu = smp_processor_id(); + /* + * Set a default elf platform, cpu probe may later + * overwrite it with a more precise value + */ + set_elf_platform(cpu, "mips"); + c->processor_id = PRID_IMP_UNKNOWN; c->fpu_id = FPIR_IMP_NONE; c->cputype = CPU_UNKNOWN; diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c index 550e7d03090a..ae64c8f56a8c 100644 --- a/arch/mips/kernel/mips-r2-to-r6-emul.c +++ b/arch/mips/kernel/mips-r2-to-r6-emul.c @@ -1096,10 +1096,20 @@ repeat: } break; - case beql_op: - case bnel_op: case blezl_op: case bgtzl_op: + /* + * For BLEZL and BGTZL, rt field must be set to 0. If this + * is not the case, this may be an encoding of a MIPS R6 + * instruction, so return to CPU execution if this occurs + */ + if (MIPSInst_RT(inst)) { + err = SIGILL; + break; + } + /* fall through */ + case beql_op: + case bnel_op: if (delay_slot(regs)) { err = SIGILL; break; @@ -2329,6 +2339,8 @@ static int mipsr2_stats_clear_show(struct seq_file *s, void *unused) __this_cpu_write((mipsr2bremustats).bgezl, 0); __this_cpu_write((mipsr2bremustats).bltzll, 0); __this_cpu_write((mipsr2bremustats).bgezll, 0); + __this_cpu_write((mipsr2bremustats).bltzall, 0); + __this_cpu_write((mipsr2bremustats).bgezall, 0); __this_cpu_write((mipsr2bremustats).bltzal, 0); __this_cpu_write((mipsr2bremustats).bgezal, 0); __this_cpu_write((mipsr2bremustats).beql, 0); diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index b68e10fc453d..918d4c73e951 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -114,8 +114,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) /* * Copy architecture-specific thread state */ -int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long kthread_arg, struct task_struct *p) +int copy_thread_tls(unsigned long clone_flags, unsigned long usp, + unsigned long kthread_arg, struct task_struct *p, unsigned long tls) { struct thread_info *ti = task_thread_info(p); struct pt_regs *childregs, *regs = current_pt_regs(); @@ -176,7 +176,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, atomic_set(&p->thread.bd_emu_frame, BD_EMUFRAME_NONE); if (clone_flags & CLONE_SETTLS) - ti->tp_value = regs->regs[7]; + ti->tp_value = tls; return 0; } diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index 758577861523..7b386d54fd65 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S @@ -25,12 +25,6 @@ /* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */ #undef fp -/* - * Offset to the current process status flags, the first 32 bytes of the - * stack are not used. - */ -#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS) - #ifndef USE_ALTERNATE_RESUME_IMPL /* * task_struct *resume(task_struct *prev, task_struct *next, diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 795b4aaf8927..36954ddd0b9f 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -8,6 +8,7 @@ * option) any later version. */ +#include <linux/cpu.h> #include <linux/delay.h> #include <linux/io.h> #include <linux/irqchip/mips-gic.h> @@ -408,7 +409,6 @@ static int cps_cpu_disable(void) return 0; } -static DECLARE_COMPLETION(cpu_death_chosen); static unsigned cpu_death_sibling; static enum { CPU_DEATH_HALT, @@ -443,7 +443,7 @@ void play_dead(void) } /* This CPU has chosen its way out */ - complete(&cpu_death_chosen); + (void)cpu_report_death(); if (cpu_death == CPU_DEATH_HALT) { vpe_id = cpu_vpe_id(&cpu_data[cpu]); @@ -492,8 +492,7 @@ static void cps_cpu_die(unsigned int cpu) int err; /* Wait for the cpu to choose its way out */ - if (!wait_for_completion_timeout(&cpu_death_chosen, - msecs_to_jiffies(5000))) { + if (!cpu_wait_death(cpu, 5)) { pr_err("CPU%u: didn't offline\n", cpu); return; } diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index e398cbc3d776..ed6b4df583ea 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -83,6 +83,8 @@ static unsigned int __init smvp_vpe_init(unsigned int tc, unsigned int mvpconf0, if (tc != 0) smvp_copy_vpe_config(); + cpu_data[ncpu].vpe_id = tc; + return ncpu; } @@ -114,49 +116,6 @@ static void __init smvp_tc_init(unsigned int tc, unsigned int mvpconf0) write_tc_c0_tchalt(TCHALT_H); } -static void vsmp_send_ipi_single(int cpu, unsigned int action) -{ - int i; - unsigned long flags; - int vpflags; - -#ifdef CONFIG_MIPS_GIC - if (gic_present) { - mips_smp_send_ipi_single(cpu, action); - return; - } -#endif - local_irq_save(flags); - - vpflags = dvpe(); /* can't access the other CPU's registers whilst MVPE enabled */ - - switch (action) { - case SMP_CALL_FUNCTION: - i = C_SW1; - break; - - case SMP_RESCHEDULE_YOURSELF: - default: - i = C_SW0; - break; - } - - /* 1:1 mapping of vpe and tc... */ - settc(cpu); - write_vpe_c0_cause(read_vpe_c0_cause() | i); - evpe(vpflags); - - local_irq_restore(flags); -} - -static void vsmp_send_ipi_mask(const struct cpumask *mask, unsigned int action) -{ - unsigned int i; - - for_each_cpu(i, mask) - vsmp_send_ipi_single(i, action); -} - static void vsmp_init_secondary(void) { #ifdef CONFIG_MIPS_GIC @@ -281,8 +240,8 @@ static void __init vsmp_prepare_cpus(unsigned int max_cpus) } struct plat_smp_ops vsmp_smp_ops = { - .send_ipi_single = vsmp_send_ipi_single, - .send_ipi_mask = vsmp_send_ipi_mask, + .send_ipi_single = mips_smp_send_ipi_single, + .send_ipi_mask = mips_smp_send_ipi_mask, .init_secondary = vsmp_init_secondary, .smp_finish = vsmp_smp_finish, .boot_secondary = vsmp_boot_secondary, diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 6e71130549ea..aba1afb64b62 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -261,16 +261,20 @@ int mips_smp_ipi_allocate(const struct cpumask *mask) ipidomain = irq_find_matching_host(NULL, DOMAIN_BUS_IPI); /* - * There are systems which only use IPI domains some of the time, - * depending upon configuration we don't know until runtime. An - * example is Malta where we may compile in support for GIC & the - * MT ASE, but run on a system which has multiple VPEs in a single - * core and doesn't include a GIC. Until all IPI implementations - * have been converted to use IPI domains the best we can do here - * is to return & hope some other code sets up the IPIs. + * There are systems which use IPI IRQ domains, but only have one + * registered when some runtime condition is met. For example a Malta + * kernel may include support for GIC & CPU interrupt controller IPI + * IRQ domains, but if run on a system with no GIC & no MT ASE then + * neither will be supported or registered. + * + * We only have a problem if we're actually using multiple CPUs so fail + * loudly if that is the case. Otherwise simply return, skipping IPI + * setup, if we're running with only a single CPU. */ - if (!ipidomain) + if (!ipidomain) { + BUG_ON(num_present_cpus() > 1); return 0; + } virq = irq_reserve_ipi(ipidomain, mask); BUG_ON(!virq); |