diff options
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/asm-offsets.c | 14 | ||||
-rw-r--r-- | arch/mips/kernel/setup.c | 13 | ||||
-rw-r--r-- | arch/mips/kernel/smp-bmips.c | 1 | ||||
-rw-r--r-- | arch/mips/kernel/smp-cps.c | 29 | ||||
-rw-r--r-- | arch/mips/kernel/smp-mt.c | 3 | ||||
-rw-r--r-- | arch/mips/kernel/smp.c | 26 | ||||
-rw-r--r-- | arch/mips/kernel/syscalls/syscall_n32.tbl | 1 | ||||
-rw-r--r-- | arch/mips/kernel/syscalls/syscall_n64.tbl | 1 | ||||
-rw-r--r-- | arch/mips/kernel/syscalls/syscall_o32.tbl | 1 | ||||
-rw-r--r-- | arch/mips/kernel/unaligned.c | 41 |
10 files changed, 107 insertions, 23 deletions
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index 40fd4051bb3d..d1b11f66f748 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -23,6 +23,7 @@ #include <linux/kvm_host.h> +void output_ptreg_defines(void); void output_ptreg_defines(void) { COMMENT("MIPS pt_regs offsets."); @@ -75,6 +76,7 @@ void output_ptreg_defines(void) BLANK(); } +void output_task_defines(void); void output_task_defines(void) { COMMENT("MIPS task_struct offsets."); @@ -89,6 +91,7 @@ void output_task_defines(void) BLANK(); } +void output_thread_info_defines(void); void output_thread_info_defines(void) { COMMENT("MIPS thread_info offsets."); @@ -105,6 +108,7 @@ void output_thread_info_defines(void) BLANK(); } +void output_thread_defines(void); void output_thread_defines(void) { COMMENT("MIPS specific thread_struct offsets."); @@ -133,6 +137,7 @@ void output_thread_defines(void) } #ifdef CONFIG_MIPS_FP_SUPPORT +void output_thread_fpu_defines(void); void output_thread_fpu_defines(void) { OFFSET(THREAD_FPU, task_struct, thread.fpu); @@ -176,6 +181,7 @@ void output_thread_fpu_defines(void) } #endif +void output_mm_defines(void); void output_mm_defines(void) { COMMENT("Size of struct page"); @@ -210,6 +216,7 @@ void output_mm_defines(void) } #ifdef CONFIG_32BIT +void output_sc_defines(void); void output_sc_defines(void) { COMMENT("Linux sigcontext offsets."); @@ -232,6 +239,7 @@ void output_sc_defines(void) #endif #ifdef CONFIG_64BIT +void output_sc_defines(void); void output_sc_defines(void) { COMMENT("Linux sigcontext offsets."); @@ -245,6 +253,7 @@ void output_sc_defines(void) } #endif +void output_signal_defined(void); void output_signal_defined(void) { COMMENT("Linux signal numbers."); @@ -284,6 +293,7 @@ void output_signal_defined(void) } #ifdef CONFIG_CPU_CAVIUM_OCTEON +void output_octeon_cop2_state_defines(void); void output_octeon_cop2_state_defines(void) { COMMENT("Octeon specific octeon_cop2_state offsets."); @@ -315,6 +325,7 @@ void output_octeon_cop2_state_defines(void) #endif #ifdef CONFIG_HIBERNATION +void output_pbe_defines(void); void output_pbe_defines(void) { COMMENT(" Linux struct pbe offsets. "); @@ -327,6 +338,7 @@ void output_pbe_defines(void) #endif #ifdef CONFIG_CPU_PM +void output_pm_defines(void); void output_pm_defines(void) { COMMENT(" PM offsets. "); @@ -341,6 +353,7 @@ void output_pm_defines(void) #endif #ifdef CONFIG_MIPS_FP_SUPPORT +void output_kvm_defines(void); void output_kvm_defines(void) { COMMENT(" KVM/MIPS Specific offsets. "); @@ -385,6 +398,7 @@ void output_kvm_defines(void) #endif #ifdef CONFIG_MIPS_CPS +void output_cps_defines(void); void output_cps_defines(void) { COMMENT(" MIPS CPS offsets. "); diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index c0e65135481b..cb871eb784a7 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -11,6 +11,8 @@ * Copyright (C) 2000, 2001, 2002, 2007 Maciej W. Rozycki */ #include <linux/init.h> +#include <linux/cpu.h> +#include <linux/delay.h> #include <linux/ioport.h> #include <linux/export.h> #include <linux/screen_info.h> @@ -841,3 +843,14 @@ static int __init setnocoherentio(char *str) } early_param("nocoherentio", setnocoherentio); #endif + +void __init arch_cpu_finalize_init(void) +{ + unsigned int cpu = smp_processor_id(); + + cpu_data[cpu].udelay_val = loops_per_jiffy; + check_bugs32(); + + if (IS_ENABLED(CONFIG_CPU_R4X00_BUGS64)) + check_bugs64(); +} diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index 15466d4cf4a0..c074ecce3fbf 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -392,6 +392,7 @@ static void bmips_cpu_die(unsigned int cpu) void __ref play_dead(void) { idle_task_exit(); + cpuhp_ap_report_dead(); /* flush data cache */ _dma_cache_wback_inv(0, ~0); diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 62f677b2306f..dd55d59b88db 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -25,24 +25,13 @@ #include <asm/time.h> #include <asm/uasm.h> -static bool threads_disabled; static DECLARE_BITMAP(core_power, NR_CPUS); struct core_boot_config *mips_cps_core_bootcfg; -static int __init setup_nothreads(char *s) +static unsigned __init core_vpe_count(unsigned int cluster, unsigned core) { - threads_disabled = true; - return 0; -} -early_param("nothreads", setup_nothreads); - -static unsigned core_vpe_count(unsigned int cluster, unsigned core) -{ - if (threads_disabled) - return 1; - - return mips_cps_numvps(cluster, core); + return min(smp_max_threads, mips_cps_numvps(cluster, core)); } static void __init cps_smp_setup(void) @@ -503,8 +492,7 @@ void play_dead(void) } } - /* This CPU has chosen its way out */ - (void)cpu_report_death(); + cpuhp_ap_report_dead(); cps_shutdown_this_cpu(cpu_death); @@ -527,7 +515,9 @@ static void wait_for_sibling_halt(void *ptr_cpu) } while (!(halted & TCHALT_H)); } -static void cps_cpu_die(unsigned int cpu) +static void cps_cpu_die(unsigned int cpu) { } + +static void cps_cleanup_dead_cpu(unsigned cpu) { unsigned core = cpu_core(&cpu_data[cpu]); unsigned int vpe_id = cpu_vpe_id(&cpu_data[cpu]); @@ -535,12 +525,6 @@ static void cps_cpu_die(unsigned int cpu) unsigned stat; int err; - /* Wait for the cpu to choose its way out */ - if (!cpu_wait_death(cpu, 5)) { - pr_err("CPU%u: didn't offline\n", cpu); - return; - } - /* * Now wait for the CPU to actually offline. Without doing this that * offlining may race with one or more of: @@ -624,6 +608,7 @@ static const struct plat_smp_ops cps_smp_ops = { #ifdef CONFIG_HOTPLUG_CPU .cpu_disable = cps_cpu_disable, .cpu_die = cps_cpu_die, + .cleanup_dead_cpu = cps_cleanup_dead_cpu, #endif #ifdef CONFIG_KEXEC .kexec_nonboot_cpu = cps_kexec_nonboot_cpu, diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 5f04a0141068..7729cc733421 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -46,7 +46,8 @@ static void __init smvp_copy_vpe_config(void) static unsigned int __init smvp_vpe_init(unsigned int tc, unsigned int mvpconf0, unsigned int ncpu) { - if (tc > ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)) + if (tc >= smp_max_threads || + (tc > ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT))) return ncpu; /* Deactivate all but VPE 0 */ diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 1d93b85271ba..8fbef537fb88 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -73,6 +73,24 @@ static cpumask_t cpu_core_setup_map; cpumask_t cpu_coherent_mask; +unsigned int smp_max_threads __initdata = UINT_MAX; + +static int __init early_nosmt(char *s) +{ + smp_max_threads = 1; + return 0; +} +early_param("nosmt", early_nosmt); + +static int __init early_smt(char *s) +{ + get_option(&s, &smp_max_threads); + /* Ensure at least one thread is available */ + smp_max_threads = clamp_val(smp_max_threads, 1U, UINT_MAX); + return 0; +} +early_param("smt", early_smt); + #ifdef CONFIG_GENERIC_IRQ_IPI static struct irq_desc *call_desc; static struct irq_desc *sched_desc; @@ -690,6 +708,14 @@ void flush_tlb_one(unsigned long vaddr) EXPORT_SYMBOL(flush_tlb_page); EXPORT_SYMBOL(flush_tlb_one); +#ifdef CONFIG_HOTPLUG_CORE_SYNC_DEAD +void arch_cpuhp_cleanup_dead_cpu(unsigned int cpu) +{ + if (mp_ops->cleanup_dead_cpu) + mp_ops->cleanup_dead_cpu(cpu); +} +#endif + #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST static void tick_broadcast_callee(void *info) diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl index 253ff994ed2e..1976317d4e8b 100644 --- a/arch/mips/kernel/syscalls/syscall_n32.tbl +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl @@ -389,3 +389,4 @@ 448 n32 process_mrelease sys_process_mrelease 449 n32 futex_waitv sys_futex_waitv 450 n32 set_mempolicy_home_node sys_set_mempolicy_home_node +451 n32 cachestat sys_cachestat diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl index 3f1886ad9d80..cfda2511badf 100644 --- a/arch/mips/kernel/syscalls/syscall_n64.tbl +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl @@ -365,3 +365,4 @@ 448 n64 process_mrelease sys_process_mrelease 449 n64 futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node +451 n64 cachestat sys_cachestat diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl index 8f243e35a7b2..7692234c3768 100644 --- a/arch/mips/kernel/syscalls/syscall_o32.tbl +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl @@ -438,3 +438,4 @@ 448 o32 process_mrelease sys_process_mrelease 449 o32 futex_waitv sys_futex_waitv 450 o32 set_mempolicy_home_node sys_set_mempolicy_home_node +451 o32 cachestat sys_cachestat diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 7b5aba5df02e..f4cf94e92ec3 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -160,6 +160,47 @@ static void emulate_load_store_insn(struct pt_regs *regs, * The remaining opcodes are the ones that are really of * interest. */ +#ifdef CONFIG_MACH_INGENIC + case spec2_op: + if (insn.mxu_lx_format.func != mxu_lx_op) + goto sigbus; /* other MXU instructions we don't care */ + + switch (insn.mxu_lx_format.op) { + case mxu_lxw_op: + if (user && !access_ok(addr, 4)) + goto sigbus; + LoadW(addr, value, res); + if (res) + goto fault; + compute_return_epc(regs); + regs->regs[insn.mxu_lx_format.rd] = value; + break; + case mxu_lxh_op: + if (user && !access_ok(addr, 2)) + goto sigbus; + LoadHW(addr, value, res); + if (res) + goto fault; + compute_return_epc(regs); + regs->regs[insn.dsp_format.rd] = value; + break; + case mxu_lxhu_op: + if (user && !access_ok(addr, 2)) + goto sigbus; + LoadHWU(addr, value, res); + if (res) + goto fault; + compute_return_epc(regs); + regs->regs[insn.dsp_format.rd] = value; + break; + case mxu_lxb_op: + case mxu_lxbu_op: + goto sigbus; + default: + goto sigill; + } + break; +#endif case spec3_op: if (insn.dsp_format.func == lx_op) { switch (insn.dsp_format.op) { |