diff options
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/bmips_vec.S | 9 | ||||
-rw-r--r-- | arch/mips/kernel/branch.c | 18 | ||||
-rw-r--r-- | arch/mips/kernel/cpu-probe.c | 5 | ||||
-rw-r--r-- | arch/mips/kernel/crash.c | 18 | ||||
-rw-r--r-- | arch/mips/kernel/machine_kexec.c | 1 | ||||
-rw-r--r-- | arch/mips/kernel/perf_event_mipsxx.c | 60 | ||||
-rw-r--r-- | arch/mips/kernel/ptrace.c | 3 | ||||
-rw-r--r-- | arch/mips/kernel/scall32-o32.S | 11 | ||||
-rw-r--r-- | arch/mips/kernel/scall64-64.S | 3 | ||||
-rw-r--r-- | arch/mips/kernel/scall64-n32.S | 14 | ||||
-rw-r--r-- | arch/mips/kernel/scall64-o32.S | 14 | ||||
-rw-r--r-- | arch/mips/kernel/setup.c | 2 | ||||
-rw-r--r-- | arch/mips/kernel/smp-bmips.c | 1 | ||||
-rw-r--r-- | arch/mips/kernel/smp-cps.c | 1 | ||||
-rw-r--r-- | arch/mips/kernel/smp.c | 2 |
15 files changed, 117 insertions, 45 deletions
diff --git a/arch/mips/kernel/bmips_vec.S b/arch/mips/kernel/bmips_vec.S index 86495072a922..d9495f3f3fad 100644 --- a/arch/mips/kernel/bmips_vec.S +++ b/arch/mips/kernel/bmips_vec.S @@ -93,7 +93,8 @@ NESTED(bmips_reset_nmi_vec, PT_SIZE, sp) #if defined(CONFIG_CPU_BMIPS5000) mfc0 k0, CP0_PRID li k1, PRID_IMP_BMIPS5000 - andi k0, 0xff00 + /* mask with PRID_IMP_BMIPS5000 to cover both variants */ + andi k0, PRID_IMP_BMIPS5000 bne k0, k1, 1f /* if we're not on core 0, this must be the SMP boot signal */ @@ -166,10 +167,12 @@ bmips_smp_entry: 2: #endif /* CONFIG_CPU_BMIPS4350 || CONFIG_CPU_BMIPS4380 */ #if defined(CONFIG_CPU_BMIPS5000) - /* set exception vector base */ + /* mask with PRID_IMP_BMIPS5000 to cover both variants */ li k1, PRID_IMP_BMIPS5000 + andi k0, PRID_IMP_BMIPS5000 bne k0, k1, 3f + /* set exception vector base */ la k0, ebase lw k0, 0(k0) mtc0 k0, $15, 1 @@ -263,6 +266,8 @@ LEAF(bmips_enable_xks01) #endif /* CONFIG_CPU_BMIPS4380 */ #if defined(CONFIG_CPU_BMIPS5000) li t1, PRID_IMP_BMIPS5000 + /* mask with PRID_IMP_BMIPS5000 to cover both variants */ + andi t2, PRID_IMP_BMIPS5000 bne t2, t1, 2f mfc0 t0, $22, 5 diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index 56f166a48fbc..fa3750b3b3a8 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -685,21 +685,9 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, } lose_fpu(1); /* Save FPU state for the emulator. */ reg = insn.i_format.rt; - bit = 0; - switch (insn.i_format.rs) { - case bc1eqz_op: - /* Test bit 0 */ - if (get_fpr32(¤t->thread.fpu.fpr[reg], 0) - & 0x1) - bit = 1; - break; - case bc1nez_op: - /* Test bit 0 */ - if (!(get_fpr32(¤t->thread.fpu.fpr[reg], 0) - & 0x1)) - bit = 1; - break; - } + bit = get_fpr32(¤t->thread.fpu.fpr[reg], 0) & 0x1; + if (insn.i_format.rs == bc1eqz_op) + bit = !bit; own_fpu(1); if (bit) epc = epc + 4 + diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index e38442d5cd6e..ee6671f0a18b 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1447,7 +1447,10 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu) case PRID_IMP_BMIPS5000: case PRID_IMP_BMIPS5200: c->cputype = CPU_BMIPS5000; - __cpu_name[cpu] = "Broadcom BMIPS5000"; + if ((c->processor_id & PRID_IMP_MASK) == PRID_IMP_BMIPS5200) + __cpu_name[cpu] = "Broadcom BMIPS5200"; + else + __cpu_name[cpu] = "Broadcom BMIPS5000"; set_elf_platform(cpu, "bmips5000"); c->options |= MIPS_CPU_ULRI; break; diff --git a/arch/mips/kernel/crash.c b/arch/mips/kernel/crash.c index 93c46c9cebb7..e757f36cea6f 100644 --- a/arch/mips/kernel/crash.c +++ b/arch/mips/kernel/crash.c @@ -50,9 +50,14 @@ static void crash_shutdown_secondary(void *passed_regs) static void crash_kexec_prepare_cpus(void) { + static int cpus_stopped; unsigned int msecs; + unsigned int ncpus; - unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */ + if (cpus_stopped) + return; + + ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */ dump_send_ipi(crash_shutdown_secondary); smp_wmb(); @@ -67,6 +72,17 @@ static void crash_kexec_prepare_cpus(void) cpu_relax(); mdelay(1); } + + cpus_stopped = 1; +} + +/* Override the weak function in kernel/panic.c */ +void crash_smp_send_stop(void) +{ + if (_crash_smp_send_stop) + _crash_smp_send_stop(); + + crash_kexec_prepare_cpus(); } #else /* !defined(CONFIG_SMP) */ diff --git a/arch/mips/kernel/machine_kexec.c b/arch/mips/kernel/machine_kexec.c index 92bc066e47a3..32b567e88b02 100644 --- a/arch/mips/kernel/machine_kexec.c +++ b/arch/mips/kernel/machine_kexec.c @@ -25,6 +25,7 @@ void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL; #ifdef CONFIG_SMP void (*relocated_kexec_smp_wait) (void *); atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0); +void (*_crash_smp_send_stop)(void) = NULL; #endif int diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index 9bc1191b1ab0..93391b0c7338 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -825,6 +825,16 @@ static const struct mips_perf_event mipsxxcore_event_map2 [PERF_COUNT_HW_BRANCH_MISSES] = { 0x27, CNTR_ODD, T }, }; +static const struct mips_perf_event i6400_event_map[PERF_COUNT_HW_MAX] = { + [PERF_COUNT_HW_CPU_CYCLES] = { 0x00, CNTR_EVEN | CNTR_ODD }, + [PERF_COUNT_HW_INSTRUCTIONS] = { 0x01, CNTR_EVEN | CNTR_ODD }, + /* These only count dcache, not icache */ + [PERF_COUNT_HW_CACHE_REFERENCES] = { 0x45, CNTR_EVEN | CNTR_ODD }, + [PERF_COUNT_HW_CACHE_MISSES] = { 0x48, CNTR_EVEN | CNTR_ODD }, + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x15, CNTR_EVEN | CNTR_ODD }, + [PERF_COUNT_HW_BRANCH_MISSES] = { 0x16, CNTR_EVEN | CNTR_ODD }, +}; + static const struct mips_perf_event loongson3_event_map[PERF_COUNT_HW_MAX] = { [PERF_COUNT_HW_CPU_CYCLES] = { 0x00, CNTR_EVEN }, [PERF_COUNT_HW_INSTRUCTIONS] = { 0x00, CNTR_ODD }, @@ -1015,6 +1025,46 @@ static const struct mips_perf_event mipsxxcore_cache_map2 }, }; +static const struct mips_perf_event i6400_cache_map + [PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX] = { +[C(L1D)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { 0x46, CNTR_EVEN | CNTR_ODD }, + [C(RESULT_MISS)] = { 0x49, CNTR_EVEN | CNTR_ODD }, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = { 0x47, CNTR_EVEN | CNTR_ODD }, + [C(RESULT_MISS)] = { 0x4a, CNTR_EVEN | CNTR_ODD }, + }, +}, +[C(L1I)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { 0x84, CNTR_EVEN | CNTR_ODD }, + [C(RESULT_MISS)] = { 0x85, CNTR_EVEN | CNTR_ODD }, + }, +}, +[C(DTLB)] = { + /* Can't distinguish read & write */ + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { 0x40, CNTR_EVEN | CNTR_ODD }, + [C(RESULT_MISS)] = { 0x41, CNTR_EVEN | CNTR_ODD }, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = { 0x40, CNTR_EVEN | CNTR_ODD }, + [C(RESULT_MISS)] = { 0x41, CNTR_EVEN | CNTR_ODD }, + }, +}, +[C(BPU)] = { + /* Conditional branches / mispredicted */ + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { 0x15, CNTR_EVEN | CNTR_ODD }, + [C(RESULT_MISS)] = { 0x16, CNTR_EVEN | CNTR_ODD }, + }, +}, +}; + static const struct mips_perf_event loongson3_cache_map [PERF_COUNT_HW_CACHE_MAX] [PERF_COUNT_HW_CACHE_OP_MAX] @@ -1556,7 +1606,6 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config) #endif break; case CPU_P5600: - case CPU_I6400: /* 8-bit event numbers */ raw_id = config & 0x1ff; base_id = raw_id & 0xff; @@ -1569,6 +1618,11 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config) raw_event.range = P; #endif break; + case CPU_I6400: + /* 8-bit event numbers */ + base_id = config & 0xff; + raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD; + break; case CPU_1004K: if (IS_BOTH_COUNTERS_1004K_EVENT(base_id)) raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD; @@ -1720,8 +1774,8 @@ init_hw_perf_events(void) break; case CPU_I6400: mipspmu.name = "mips/I6400"; - mipspmu.general_event_map = &mipsxxcore_event_map2; - mipspmu.cache_event_map = &mipsxxcore_cache_map2; + mipspmu.general_event_map = &i6400_event_map; + mipspmu.cache_event_map = &i6400_cache_map; break; case CPU_1004K: mipspmu.name = "mips/1004K"; diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 816c4b281c0f..5915bbe74929 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -670,9 +670,6 @@ static const struct pt_regs_offset regoffset_table[] = { REG_OFFSET_NAME(c0_badvaddr, cp0_badvaddr), REG_OFFSET_NAME(c0_cause, cp0_cause), REG_OFFSET_NAME(c0_epc, cp0_epc), -#ifdef CONFIG_MIPS_MT_SMTC - REG_OFFSET_NAME(c0_tcstatus, cp0_tcstatus), -#endif #ifdef CONFIG_CPU_CAVIUM_OCTEON REG_OFFSET_NAME(mpl0, mpl[0]), REG_OFFSET_NAME(mpl1, mpl[1]), diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 29b0c5f978e4..7ee8c6269b22 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -35,7 +35,6 @@ NESTED(handle_sys, PT_SIZE, sp) lw t1, PT_EPC(sp) # skip syscall on return - subu v0, v0, __NR_O32_Linux # check syscall number addiu t1, 4 # skip to next instruction sw t1, PT_EPC(sp) @@ -89,6 +88,7 @@ loads_done: and t0, t1 bnez t0, syscall_trace_entry # -> yes syscall_common: + subu v0, v0, __NR_O32_Linux # check syscall number sltiu t0, v0, __NR_O32_Linux_syscalls + 1 beqz t0, illegal_syscall @@ -118,24 +118,23 @@ o32_syscall_exit: syscall_trace_entry: SAVE_STATIC - move s0, v0 move a0, sp /* * syscall number is in v0 unless we called syscall(__NR_###) * where the real syscall number is in a0 */ - addiu a1, v0, __NR_O32_Linux - bnez v0, 1f /* __NR_syscall at offset 0 */ + move a1, v0 + subu t2, v0, __NR_O32_Linux + bnez t2, 1f /* __NR_syscall at offset 0 */ lw a1, PT_R4(sp) 1: jal syscall_trace_enter bltz v0, 1f # seccomp failed? Skip syscall - move v0, s0 # restore syscall - RESTORE_STATIC + lw v0, PT_R2(sp) # Restore syscall (maybe modified) lw a0, PT_R4(sp) # Restore argument registers lw a1, PT_R5(sp) lw a2, PT_R6(sp) diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index a6323a969919..01779c315bc6 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -82,15 +82,14 @@ n64_syscall_exit: syscall_trace_entry: SAVE_STATIC - move s0, v0 move a0, sp move a1, v0 jal syscall_trace_enter bltz v0, 1f # seccomp failed? Skip syscall - move v0, s0 RESTORE_STATIC + ld v0, PT_R2(sp) # Restore syscall (maybe modified) ld a0, PT_R4(sp) # Restore argument registers ld a1, PT_R5(sp) ld a2, PT_R6(sp) diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index e0fdca8d3abe..0d22a5cc0b8b 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -42,9 +42,6 @@ NESTED(handle_sysn32, PT_SIZE, sp) #endif beqz t0, not_n32_scall - dsll t0, v0, 3 # offset into table - ld t2, (sysn32_call_table - (__NR_N32_Linux * 8))(t0) - sd a3, PT_R26(sp) # save a3 for syscall restarting li t1, _TIF_WORK_SYSCALL_ENTRY @@ -53,6 +50,9 @@ NESTED(handle_sysn32, PT_SIZE, sp) bnez t0, n32_syscall_trace_entry syscall_common: + dsll t0, v0, 3 # offset into table + ld t2, (sysn32_call_table - (__NR_N32_Linux * 8))(t0) + jalr t2 # Do The Real Thing (TM) li t0, -EMAXERRNO - 1 # error? @@ -71,21 +71,25 @@ syscall_common: n32_syscall_trace_entry: SAVE_STATIC - move s0, t2 move a0, sp move a1, v0 jal syscall_trace_enter bltz v0, 1f # seccomp failed? Skip syscall - move t2, s0 RESTORE_STATIC + ld v0, PT_R2(sp) # Restore syscall (maybe modified) ld a0, PT_R4(sp) # Restore argument registers ld a1, PT_R5(sp) ld a2, PT_R6(sp) ld a3, PT_R7(sp) ld a4, PT_R8(sp) ld a5, PT_R9(sp) + + dsubu t2, v0, __NR_N32_Linux # check (new) syscall number + sltiu t0, t2, __NR_N32_Linux_syscalls + 1 + beqz t0, not_n32_scall + j syscall_common 1: j syscall_exit diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 4faff3e77b25..a5cc2b2823d2 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -52,9 +52,6 @@ NESTED(handle_sys, PT_SIZE, sp) sll a2, a2, 0 sll a3, a3, 0 - dsll t0, v0, 3 # offset into table - ld t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0) - sd a3, PT_R26(sp) # save a3 for syscall restarting /* @@ -88,6 +85,9 @@ loads_done: bnez t0, trace_a_syscall syscall_common: + dsll t0, v0, 3 # offset into table + ld t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0) + jalr t2 # Do The Real Thing (TM) li t0, -EMAXERRNO - 1 # error? @@ -112,7 +112,6 @@ trace_a_syscall: sd a6, PT_R10(sp) sd a7, PT_R11(sp) # For indirect syscalls - move s0, t2 # Save syscall pointer move a0, sp /* * absolute syscall number is in v0 unless we called syscall(__NR_###) @@ -133,8 +132,8 @@ trace_a_syscall: bltz v0, 1f # seccomp failed? Skip syscall - move t2, s0 RESTORE_STATIC + ld v0, PT_R2(sp) # Restore syscall (maybe modified) ld a0, PT_R4(sp) # Restore argument registers ld a1, PT_R5(sp) ld a2, PT_R6(sp) @@ -143,6 +142,11 @@ trace_a_syscall: ld a5, PT_R9(sp) ld a6, PT_R10(sp) ld a7, PT_R11(sp) # For indirect syscalls + + dsubu t0, v0, __NR_O32_Linux # check (new) syscall number + sltiu t0, t0, __NR_O32_Linux_syscalls + 1 + beqz t0, not_o32_scall + j syscall_common 1: j syscall_exit diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index ded8f4ff0cdc..5c104b13c90e 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -735,7 +735,7 @@ static void __init request_crashkernel(struct resource *res) #define USE_PROM_CMDLINE IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER) #define USE_DTB_CMDLINE IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_DTB) -#define EXTEND_WITH_PROM IS_ENABLED(CONFIG_MIPS_CMDLINE_EXTEND) +#define EXTEND_WITH_PROM IS_ENABLED(CONFIG_MIPS_CMDLINE_DTB_EXTEND) static void __init arch_mem_init(char **cmdline_p) { diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index a62d24169d75..a00c4699ca10 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -362,6 +362,7 @@ static int bmips_cpu_disable(void) pr_info("SMP: CPU%d is offline\n", cpu); set_cpu_online(cpu, false); + calculate_cpu_foreign_map(); cpumask_clear_cpu(cpu, &cpu_callin_map); clear_c0_status(IE_IRQ5); diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 1b78309fb493..1c8a5517adb7 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -392,6 +392,7 @@ static int cps_cpu_disable(void) atomic_sub(1 << cpu_vpe_id(¤t_cpu_data), &core_cfg->vpe_mask); smp_mb__after_atomic(); set_cpu_online(cpu, false); + calculate_cpu_foreign_map(); cpumask_clear_cpu(cpu, &cpu_callin_map); return 0; diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 1ef11f46db5a..91eb386c5353 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -118,7 +118,7 @@ static inline void set_cpu_core_map(int cpu) * Calculate a new cpu_foreign_map mask whenever a * new cpu appears or disappears. */ -static inline void calculate_cpu_foreign_map(void) +void calculate_cpu_foreign_map(void) { int i, k, core_present; cpumask_t temp_foreign_map; |