summaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/Makefile14
-rw-r--r--arch/mips/kernel/cps-vec.S4
-rw-r--r--arch/mips/kernel/cpu-probe.c59
-rw-r--r--arch/mips/kernel/genex.S13
-rw-r--r--arch/mips/kernel/idle.c1
-rw-r--r--arch/mips/kernel/mips-cm.c94
-rw-r--r--arch/mips/kernel/mips-cpc.c17
-rw-r--r--arch/mips/kernel/mips-r2-to-r6-emul.c16
-rw-r--r--arch/mips/kernel/octeon_switch.S11
-rw-r--r--arch/mips/kernel/pm-cps.c17
-rw-r--r--arch/mips/kernel/proc.c6
-rw-r--r--arch/mips/kernel/process.c102
-rw-r--r--arch/mips/kernel/r2300_fpu.S80
-rw-r--r--arch/mips/kernel/r2300_switch.S81
-rw-r--r--arch/mips/kernel/r4k_fpu.S196
-rw-r--r--arch/mips/kernel/r4k_switch.S203
-rw-r--r--arch/mips/kernel/r6000_fpu.S99
-rw-r--r--arch/mips/kernel/smp-bmips.c10
-rw-r--r--arch/mips/kernel/smp-cmp.c6
-rw-r--r--arch/mips/kernel/smp-cps.c152
-rw-r--r--arch/mips/kernel/smp-mt.c14
-rw-r--r--arch/mips/kernel/smp-up.c5
-rw-r--r--arch/mips/kernel/smp.c24
-rw-r--r--arch/mips/kernel/time.c14
-rw-r--r--arch/mips/kernel/traps.c29
-rw-r--r--arch/mips/kernel/unaligned.c2
-rw-r--r--arch/mips/kernel/vdso.c15
27 files changed, 605 insertions, 679 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 46c0581256f1..07f0f4a4b562 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -35,11 +35,15 @@ obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o
-obj-$(CONFIG_CPU_R4K_FPU) += r4k_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o
-obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o
-obj-$(CONFIG_CPU_CAVIUM_OCTEON) += r4k_fpu.o octeon_switch.o
+sw-y := r4k_switch.o
+sw-$(CONFIG_CPU_R3000) := r2300_switch.o
+sw-$(CONFIG_CPU_TX39XX) := r2300_switch.o
+sw-$(CONFIG_CPU_CAVIUM_OCTEON) := octeon_switch.o
+obj-y += $(sw-y)
+
+obj-$(CONFIG_CPU_R4K_FPU) += r4k_fpu.o
+obj-$(CONFIG_CPU_R3000) += r2300_fpu.o
+obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_SMP_UP) += smp-up.o
diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S
index b849fe6aad94..d173b49f212d 100644
--- a/arch/mips/kernel/cps-vec.S
+++ b/arch/mips/kernel/cps-vec.S
@@ -327,8 +327,8 @@ LEAF(mips_cps_get_bootcfg)
* to handle contiguous VP numbering, but no such systems yet
* exist.
*/
- mfc0 t9, $3, 1
- andi t9, t9, 0xff
+ mfc0 t9, CP0_GLOBALNUMBER
+ andi t9, t9, MIPS_GLOBALNUMBER_VP
#elif defined(CONFIG_MIPS_MT_SMP)
has_mt ta2, 1f
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index d08afc7dc507..cf3fd549e16d 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -326,7 +326,7 @@ static int __init fpu_disable(char *s)
__setup("nofpu", fpu_disable);
-int mips_dsp_disabled;
+static int mips_dsp_disabled;
static int __init dsp_disable(char *s)
{
@@ -919,9 +919,12 @@ static void decode_configs(struct cpuinfo_mips *c)
#ifndef CONFIG_MIPS_CPS
if (cpu_has_mips_r2_r6) {
- c->core = get_ebase_cpunum();
+ unsigned int core;
+
+ core = get_ebase_cpunum();
if (cpu_has_mipsmt)
- c->core >>= fls(core_nvpes()) - 1;
+ core >>= fls(core_nvpes()) - 1;
+ cpu_set_core(c, core);
}
#endif
}
@@ -1394,24 +1397,6 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
MIPS_CPU_DIVEC | MIPS_CPU_LLSC;
c->tlbsize = 48;
break;
- case PRID_IMP_R6000:
- c->cputype = CPU_R6000;
- __cpu_name[cpu] = "R6000";
- set_isa(c, MIPS_CPU_ISA_II);
- c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
- c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
- MIPS_CPU_LLSC;
- c->tlbsize = 32;
- break;
- case PRID_IMP_R6000A:
- c->cputype = CPU_R6000A;
- __cpu_name[cpu] = "R6000A";
- set_isa(c, MIPS_CPU_ISA_II);
- c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
- c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
- MIPS_CPU_LLSC;
- c->tlbsize = 32;
- break;
case PRID_IMP_RM7000:
c->cputype = CPU_RM7000;
__cpu_name[cpu] = "RM7000";
@@ -2113,3 +2098,35 @@ void cpu_report(void)
if (cpu_has_msa)
pr_info("MSA revision is: %08x\n", c->msa_id);
}
+
+void cpu_set_cluster(struct cpuinfo_mips *cpuinfo, unsigned int cluster)
+{
+ /* Ensure the core number fits in the field */
+ WARN_ON(cluster > (MIPS_GLOBALNUMBER_CLUSTER >>
+ MIPS_GLOBALNUMBER_CLUSTER_SHF));
+
+ cpuinfo->globalnumber &= ~MIPS_GLOBALNUMBER_CLUSTER;
+ cpuinfo->globalnumber |= cluster << MIPS_GLOBALNUMBER_CLUSTER_SHF;
+}
+
+void cpu_set_core(struct cpuinfo_mips *cpuinfo, unsigned int core)
+{
+ /* Ensure the core number fits in the field */
+ WARN_ON(core > (MIPS_GLOBALNUMBER_CORE >> MIPS_GLOBALNUMBER_CORE_SHF));
+
+ cpuinfo->globalnumber &= ~MIPS_GLOBALNUMBER_CORE;
+ cpuinfo->globalnumber |= core << MIPS_GLOBALNUMBER_CORE_SHF;
+}
+
+void cpu_set_vpe_id(struct cpuinfo_mips *cpuinfo, unsigned int vpe)
+{
+ /* Ensure the VP(E) ID fits in the field */
+ WARN_ON(vpe > (MIPS_GLOBALNUMBER_VP >> MIPS_GLOBALNUMBER_VP_SHF));
+
+ /* Ensure we're not using VP(E)s without support */
+ WARN_ON(vpe && !IS_ENABLED(CONFIG_MIPS_MT_SMP) &&
+ !IS_ENABLED(CONFIG_CPU_MIPSR6));
+
+ cpuinfo->globalnumber &= ~MIPS_GLOBALNUMBER_VP;
+ cpuinfo->globalnumber |= vpe << MIPS_GLOBALNUMBER_VP_SHF;
+}
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index ae810da4d499..37b9383eacd3 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -150,6 +150,7 @@ LEAF(__r4k_wait)
.align 5
BUILD_ROLLBACK_PROLOGUE handle_int
NESTED(handle_int, PT_SIZE, sp)
+ .cfi_signal_frame
#ifdef CONFIG_TRACE_IRQFLAGS
/*
* Check to see if the interrupted code has just disabled
@@ -181,7 +182,7 @@ NESTED(handle_int, PT_SIZE, sp)
1:
.set pop
#endif
- SAVE_ALL
+ SAVE_ALL docfi=1
CLI
TRACE_IRQS_OFF
@@ -269,8 +270,8 @@ NESTED(except_vec_ejtag_debug, 0, sp)
*/
BUILD_ROLLBACK_PROLOGUE except_vec_vi
NESTED(except_vec_vi, 0, sp)
- SAVE_SOME
- SAVE_AT
+ SAVE_SOME docfi=1
+ SAVE_AT docfi=1
.set push
.set noreorder
PTR_LA v1, except_vec_vi_handler
@@ -396,6 +397,7 @@ NESTED(except_vec_nmi, 0, sp)
__FINIT
NESTED(nmi_handler, PT_SIZE, sp)
+ .cfi_signal_frame
.set push
.set noat
/*
@@ -478,6 +480,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
.macro __BUILD_HANDLER exception handler clear verbose ext
.align 5
NESTED(handle_\exception, PT_SIZE, sp)
+ .cfi_signal_frame
.set noat
SAVE_ALL
FEXPORT(handle_\exception\ext)
@@ -485,8 +488,8 @@ NESTED(nmi_handler, PT_SIZE, sp)
.set at
__BUILD_\verbose \exception
move a0, sp
- PTR_LA ra, ret_from_exception
- j do_\handler
+ jal do_\handler
+ j ret_from_exception
END(handle_\exception)
.endm
diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c
index 60ab4c44d305..7c246b69c545 100644
--- a/arch/mips/kernel/idle.c
+++ b/arch/mips/kernel/idle.c
@@ -11,6 +11,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/cpu.h>
#include <linux/export.h>
#include <linux/init.h>
#include <linux/irqflags.h>
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index cb0c57f860d4..e91c8c4e2eb5 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -12,10 +12,10 @@
#include <linux/percpu.h>
#include <linux/spinlock.h>
-#include <asm/mips-cm.h>
+#include <asm/mips-cps.h>
#include <asm/mipsregs.h>
-void __iomem *mips_cm_base;
+void __iomem *mips_gcr_base;
void __iomem *mips_cm_l2sync_base;
int mips_cm_is64;
@@ -167,8 +167,8 @@ phys_addr_t __mips_cm_l2sync_phys_base(void)
* current location.
*/
base_reg = read_gcr_l2_only_sync_base();
- if (base_reg & CM_GCR_L2_ONLY_SYNC_BASE_SYNCEN_MSK)
- return base_reg & CM_GCR_L2_ONLY_SYNC_BASE_SYNCBASE_MSK;
+ if (base_reg & CM_GCR_L2_ONLY_SYNC_BASE_SYNCEN)
+ return base_reg & CM_GCR_L2_ONLY_SYNC_BASE_SYNCBASE;
/* Default to following the CM */
return mips_cm_phys_base() + MIPS_CM_GCR_SIZE;
@@ -183,19 +183,19 @@ static void mips_cm_probe_l2sync(void)
phys_addr_t addr;
/* L2-only sync was introduced with CM major revision 6 */
- major_rev = (read_gcr_rev() & CM_GCR_REV_MAJOR_MSK) >>
- CM_GCR_REV_MAJOR_SHF;
+ major_rev = (read_gcr_rev() & CM_GCR_REV_MAJOR) >>
+ __ffs(CM_GCR_REV_MAJOR);
if (major_rev < 6)
return;
/* Find a location for the L2 sync region */
addr = mips_cm_l2sync_phys_base();
- BUG_ON((addr & CM_GCR_L2_ONLY_SYNC_BASE_SYNCBASE_MSK) != addr);
+ BUG_ON((addr & CM_GCR_L2_ONLY_SYNC_BASE_SYNCBASE) != addr);
if (!addr)
return;
/* Set the region base address & enable it */
- write_gcr_l2_only_sync_base(addr | CM_GCR_L2_ONLY_SYNC_BASE_SYNCEN_MSK);
+ write_gcr_l2_only_sync_base(addr | CM_GCR_L2_ONLY_SYNC_BASE_SYNCEN);
/* Map the region */
mips_cm_l2sync_base = ioremap_nocache(addr, MIPS_CM_L2SYNC_SIZE);
@@ -211,41 +211,39 @@ int mips_cm_probe(void)
* No need to probe again if we have already been
* here before.
*/
- if (mips_cm_base)
+ if (mips_gcr_base)
return 0;
addr = mips_cm_phys_base();
- BUG_ON((addr & CM_GCR_BASE_GCRBASE_MSK) != addr);
+ BUG_ON((addr & CM_GCR_BASE_GCRBASE) != addr);
if (!addr)
return -ENODEV;
- mips_cm_base = ioremap_nocache(addr, MIPS_CM_GCR_SIZE);
- if (!mips_cm_base)
+ mips_gcr_base = ioremap_nocache(addr, MIPS_CM_GCR_SIZE);
+ if (!mips_gcr_base)
return -ENXIO;
/* sanity check that we're looking at a CM */
base_reg = read_gcr_base();
- if ((base_reg & CM_GCR_BASE_GCRBASE_MSK) != addr) {
+ if ((base_reg & CM_GCR_BASE_GCRBASE) != addr) {
pr_err("GCRs appear to have been moved (expected them at 0x%08lx)!\n",
(unsigned long)addr);
- mips_cm_base = NULL;
+ mips_gcr_base = NULL;
return -ENODEV;
}
/* set default target to memory */
- base_reg &= ~CM_GCR_BASE_CMDEFTGT_MSK;
- base_reg |= CM_GCR_BASE_CMDEFTGT_MEM;
- write_gcr_base(base_reg);
+ change_gcr_base(CM_GCR_BASE_CMDEFTGT, CM_GCR_BASE_CMDEFTGT_MEM);
/* disable CM regions */
- write_gcr_reg0_base(CM_GCR_REGn_BASE_BASEADDR_MSK);
- write_gcr_reg0_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK);
- write_gcr_reg1_base(CM_GCR_REGn_BASE_BASEADDR_MSK);
- write_gcr_reg1_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK);
- write_gcr_reg2_base(CM_GCR_REGn_BASE_BASEADDR_MSK);
- write_gcr_reg2_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK);
- write_gcr_reg3_base(CM_GCR_REGn_BASE_BASEADDR_MSK);
- write_gcr_reg3_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK);
+ write_gcr_reg0_base(CM_GCR_REGn_BASE_BASEADDR);
+ write_gcr_reg0_mask(CM_GCR_REGn_MASK_ADDRMASK);
+ write_gcr_reg1_base(CM_GCR_REGn_BASE_BASEADDR);
+ write_gcr_reg1_mask(CM_GCR_REGn_MASK_ADDRMASK);
+ write_gcr_reg2_base(CM_GCR_REGn_BASE_BASEADDR);
+ write_gcr_reg2_mask(CM_GCR_REGn_MASK_ADDRMASK);
+ write_gcr_reg3_base(CM_GCR_REGn_BASE_BASEADDR);
+ write_gcr_reg3_mask(CM_GCR_REGn_MASK_ADDRMASK);
/* probe for an L2-only sync region */
mips_cm_probe_l2sync();
@@ -259,16 +257,27 @@ int mips_cm_probe(void)
return 0;
}
-void mips_cm_lock_other(unsigned int core, unsigned int vp)
+void mips_cm_lock_other(unsigned int cluster, unsigned int core,
+ unsigned int vp, unsigned int block)
{
- unsigned curr_core;
+ unsigned int curr_core, cm_rev;
u32 val;
+ cm_rev = mips_cm_revision();
preempt_disable();
- if (mips_cm_revision() >= CM_REV_CM3) {
- val = core << CM3_GCR_Cx_OTHER_CORE_SHF;
- val |= vp << CM3_GCR_Cx_OTHER_VP_SHF;
+ if (cm_rev >= CM_REV_CM3) {
+ val = core << __ffs(CM3_GCR_Cx_OTHER_CORE);
+ val |= vp << __ffs(CM3_GCR_Cx_OTHER_VP);
+
+ if (cm_rev >= CM_REV_CM3_5) {
+ val |= CM_GCR_Cx_OTHER_CLUSTER_EN;
+ val |= cluster << __ffs(CM_GCR_Cx_OTHER_CLUSTER);
+ val |= block << __ffs(CM_GCR_Cx_OTHER_BLOCK);
+ } else {
+ WARN_ON(cluster != 0);
+ WARN_ON(block != CM_GCR_Cx_OTHER_BLOCK_LOCAL);
+ }
/*
* We need to disable interrupts in SMP systems in order to
@@ -282,18 +291,20 @@ void mips_cm_lock_other(unsigned int core, unsigned int vp)
spin_lock_irqsave(this_cpu_ptr(&cm_core_lock),
*this_cpu_ptr(&cm_core_lock_flags));
} else {
+ WARN_ON(cluster != 0);
WARN_ON(vp != 0);
+ WARN_ON(block != CM_GCR_Cx_OTHER_BLOCK_LOCAL);
/*
* We only have a GCR_CL_OTHER per core in systems with
* CM 2.5 & older, so have to ensure other VP(E)s don't
* race with us.
*/
- curr_core = current_cpu_data.core;
+ curr_core = cpu_core(&current_cpu_data);
spin_lock_irqsave(&per_cpu(cm_core_lock, curr_core),
per_cpu(cm_core_lock_flags, curr_core));
- val = core << CM_GCR_Cx_OTHER_CORENUM_SHF;
+ val = core << __ffs(CM_GCR_Cx_OTHER_CORENUM);
}
write_gcr_cl_other(val);
@@ -310,7 +321,7 @@ void mips_cm_unlock_other(void)
unsigned int curr_core;
if (mips_cm_revision() < CM_REV_CM3) {
- curr_core = current_cpu_data.core;
+ curr_core = cpu_core(&current_cpu_data);
spin_unlock_irqrestore(&per_cpu(cm_core_lock, curr_core),
per_cpu(cm_core_lock_flags, curr_core));
} else {
@@ -332,13 +343,13 @@ void mips_cm_error_report(void)
return;
revision = mips_cm_revision();
+ cm_error = read_gcr_error_cause();
+ cm_addr = read_gcr_error_addr();
+ cm_other = read_gcr_error_mult();
if (revision < CM_REV_CM3) { /* CM2 */
- cm_error = read_gcr_error_cause();
- cm_addr = read_gcr_error_addr();
- cm_other = read_gcr_error_mult();
- cause = cm_error >> CM_GCR_ERROR_CAUSE_ERRTYPE_SHF;
- ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF;
+ cause = cm_error >> __ffs(CM_GCR_ERROR_CAUSE_ERRTYPE);
+ ocause = cm_other >> __ffs(CM_GCR_ERROR_MULT_ERR2ND);
if (!cause)
return;
@@ -380,11 +391,8 @@ void mips_cm_error_report(void)
ulong core_id_bits, vp_id_bits, cmd_bits, cmd_group_bits;
ulong cm3_cca_bits, mcp_bits, cm3_tr_bits, sched_bit;
- cm_error = read64_gcr_error_cause();
- cm_addr = read64_gcr_error_addr();
- cm_other = read64_gcr_error_mult();
- cause = cm_error >> CM3_GCR_ERROR_CAUSE_ERRTYPE_SHF;
- ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF;
+ cause = cm_error >> __ffs64(CM3_GCR_ERROR_CAUSE_ERRTYPE);
+ ocause = cm_other >> __ffs(CM_GCR_ERROR_MULT_ERR2ND);
if (!cause)
return;
diff --git a/arch/mips/kernel/mips-cpc.c b/arch/mips/kernel/mips-cpc.c
index a4964c334cab..f66b05ebf637 100644
--- a/arch/mips/kernel/mips-cpc.c
+++ b/arch/mips/kernel/mips-cpc.c
@@ -12,8 +12,7 @@
#include <linux/percpu.h>
#include <linux/spinlock.h>
-#include <asm/mips-cm.h>
-#include <asm/mips-cpc.h>
+#include <asm/mips-cps.h>
void __iomem *mips_cpc_base;
@@ -40,13 +39,13 @@ static phys_addr_t mips_cpc_phys_base(void)
if (!mips_cm_present())
return 0;
- if (!(read_gcr_cpc_status() & CM_GCR_CPC_STATUS_EX_MSK))
+ if (!(read_gcr_cpc_status() & CM_GCR_CPC_STATUS_EX))
return 0;
/* If the CPC is already enabled, leave it so */
cpc_base = read_gcr_cpc_base();
- if (cpc_base & CM_GCR_CPC_BASE_CPCEN_MSK)
- return cpc_base & CM_GCR_CPC_BASE_CPCBASE_MSK;
+ if (cpc_base & CM_GCR_CPC_BASE_CPCEN)
+ return cpc_base & CM_GCR_CPC_BASE_CPCBASE;
/* Otherwise, use the default address */
cpc_base = mips_cpc_default_phys_base();
@@ -54,7 +53,7 @@ static phys_addr_t mips_cpc_phys_base(void)
return cpc_base;
/* Enable the CPC, mapped at the default address */
- write_gcr_cpc_base(cpc_base | CM_GCR_CPC_BASE_CPCEN_MSK);
+ write_gcr_cpc_base(cpc_base | CM_GCR_CPC_BASE_CPCEN);
return cpc_base;
}
@@ -86,10 +85,10 @@ void mips_cpc_lock_other(unsigned int core)
return;
preempt_disable();
- curr_core = current_cpu_data.core;
+ curr_core = cpu_core(&current_cpu_data);
spin_lock_irqsave(&per_cpu(cpc_core_lock, curr_core),
per_cpu(cpc_core_lock_flags, curr_core));
- write_cpc_cl_other(core << CPC_Cx_OTHER_CORENUM_SHF);
+ write_cpc_cl_other(core << __ffs(CPC_Cx_OTHER_CORENUM));
/*
* Ensure the core-other region reflects the appropriate core &
@@ -106,7 +105,7 @@ void mips_cpc_unlock_other(void)
/* Systems with CM >= 3 lock the CPC via mips_cm_lock_other */
return;
- curr_core = current_cpu_data.core;
+ curr_core = cpu_core(&current_cpu_data);
spin_unlock_irqrestore(&per_cpu(cpc_core_lock, curr_core),
per_cpu(cpc_core_lock_flags, curr_core));
preempt_enable();
diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c
index ae64c8f56a8c..eb18b186e858 100644
--- a/arch/mips/kernel/mips-r2-to-r6-emul.c
+++ b/arch/mips/kernel/mips-r2-to-r6-emul.c
@@ -46,9 +46,11 @@
#define LL "ll "
#define SC "sc "
-DEFINE_PER_CPU(struct mips_r2_emulator_stats, mipsr2emustats);
-DEFINE_PER_CPU(struct mips_r2_emulator_stats, mipsr2bdemustats);
-DEFINE_PER_CPU(struct mips_r2br_emulator_stats, mipsr2bremustats);
+#ifdef CONFIG_DEBUG_FS
+static DEFINE_PER_CPU(struct mips_r2_emulator_stats, mipsr2emustats);
+static DEFINE_PER_CPU(struct mips_r2_emulator_stats, mipsr2bdemustats);
+static DEFINE_PER_CPU(struct mips_r2br_emulator_stats, mipsr2bremustats);
+#endif
extern const unsigned int fpucondbit[8];
@@ -600,7 +602,7 @@ static int ddivu_func(struct pt_regs *regs, u32 ir)
}
/* R6 removed instructions for the SPECIAL opcode */
-static struct r2_decoder_table spec_op_table[] = {
+static const struct r2_decoder_table spec_op_table[] = {
{ 0xfc1ff83f, 0x00000008, jr_func },
{ 0xfc00ffff, 0x00000018, mult_func },
{ 0xfc00ffff, 0x00000019, multu_func },
@@ -867,7 +869,7 @@ static int dclo_func(struct pt_regs *regs, u32 ir)
}
/* R6 removed instructions for the SPECIAL2 opcode */
-static struct r2_decoder_table spec2_op_table[] = {
+static const struct r2_decoder_table spec2_op_table[] = {
{ 0xfc00ffff, 0x70000000, madd_func },
{ 0xfc00ffff, 0x70000001, maddu_func },
{ 0xfc0007ff, 0x70000002, mul_func },
@@ -881,9 +883,9 @@ static struct r2_decoder_table spec2_op_table[] = {
};
static inline int mipsr2_find_op_func(struct pt_regs *regs, u32 inst,
- struct r2_decoder_table *table)
+ const struct r2_decoder_table *table)
{
- struct r2_decoder_table *p;
+ const struct r2_decoder_table *p;
int err;
for (p = table; p->func; p++) {
diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S
index 3375745b9198..e42113fe2762 100644
--- a/arch/mips/kernel/octeon_switch.S
+++ b/arch/mips/kernel/octeon_switch.S
@@ -10,12 +10,13 @@
* Copyright (C) 2000 MIPS Technologies, Inc.
* written by Carsten Langgaard, carstenl@mips.com
*/
+#include <asm/asm.h>
+#include <asm/export.h>
+#include <asm/asm-offsets.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
-#define USE_ALTERNATE_RESUME_IMPL 1
- .set push
- .set arch=mips64r2
-#include "r4k_switch.S"
- .set pop
/*
* task_struct *resume(task_struct *prev, task_struct *next,
* struct thread_info *next_ti)
diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c
index d99416094ba9..4655017f2377 100644
--- a/arch/mips/kernel/pm-cps.c
+++ b/arch/mips/kernel/pm-cps.c
@@ -17,8 +17,7 @@
#include <asm/cacheflush.h>
#include <asm/cacheops.h>
#include <asm/idle.h>
-#include <asm/mips-cm.h>
-#include <asm/mips-cpc.h>
+#include <asm/mips-cps.h>
#include <asm/mipsmtregs.h>
#include <asm/pm.h>
#include <asm/pm-cps.h>
@@ -49,7 +48,7 @@ static DEFINE_PER_CPU_READ_MOSTLY(cps_nc_entry_fn[CPS_PM_STATE_COUNT],
nc_asm_enter);
/* Bitmap indicating which states are supported by the system */
-DECLARE_BITMAP(state_support, CPS_PM_STATE_COUNT);
+static DECLARE_BITMAP(state_support, CPS_PM_STATE_COUNT);
/*
* Indicates the number of coupled VPEs ready to operate in a non-coherent
@@ -114,7 +113,7 @@ static void coupled_barrier(atomic_t *a, unsigned online)
int cps_pm_enter_state(enum cps_pm_state state)
{
unsigned cpu = smp_processor_id();
- unsigned core = current_cpu_data.core;
+ unsigned core = cpu_core(&current_cpu_data);
unsigned online, left;
cpumask_t *coupled_mask = this_cpu_ptr(&online_coupled);
u32 *core_ready_count, *nc_core_ready_count;
@@ -486,7 +485,7 @@ static void *cps_gen_entry_code(unsigned cpu, enum cps_pm_state state)
* defined by the interAptiv & proAptiv SUMs as ensuring that the
* operation resulting from the preceding store is complete.
*/
- uasm_i_addiu(&p, t0, zero, 1 << cpu_data[cpu].core);
+ uasm_i_addiu(&p, t0, zero, 1 << cpu_core(&cpu_data[cpu]));
uasm_i_sw(&p, t0, 0, r_pcohctl);
uasm_i_lw(&p, t0, 0, r_pcohctl);
@@ -569,8 +568,8 @@ static void *cps_gen_entry_code(unsigned cpu, enum cps_pm_state state)
* rest will just be performing a rather unusual nop.
*/
uasm_i_addiu(&p, t0, zero, mips_cm_revision() < CM_REV_CM3
- ? CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK
- : CM3_GCR_Cx_COHERENCE_COHEN_MSK);
+ ? CM_GCR_Cx_COHERENCE_COHDOMAINEN
+ : CM3_GCR_Cx_COHERENCE_COHEN);
uasm_i_sw(&p, t0, 0, r_pcohctl);
uasm_i_lw(&p, t0, 0, r_pcohctl);
@@ -640,7 +639,7 @@ out_err:
static int cps_pm_online_cpu(unsigned int cpu)
{
enum cps_pm_state state;
- unsigned core = cpu_data[cpu].core;
+ unsigned core = cpu_core(&cpu_data[cpu]);
void *entry_fn, *core_rc;
for (state = CPS_PM_NC_WAIT; state < CPS_PM_STATE_COUNT; state++) {
@@ -692,7 +691,7 @@ static int __init cps_pm_init(void)
/* Detect whether a CPC is present */
if (mips_cpc_present()) {
/* Detect whether clock gating is implemented */
- if (read_cpc_cl_stat_conf() & CPC_Cx_STAT_CONF_CLKGAT_IMPL_MSK)
+ if (read_cpc_cl_stat_conf() & CPC_Cx_STAT_CONF_CLKGAT_IMPL)
set_bit(CPS_PM_CLOCK_GATED, state_support);
else
pr_warn("pm-cps: CPC does not support clock gating\n");
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 70604c753aa4..bd9bf528f19b 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -134,13 +134,13 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "kscratch registers\t: %d\n",
hweight8(cpu_data[n].kscratch_mask));
seq_printf(m, "package\t\t\t: %d\n", cpu_data[n].package);
- seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core);
+ seq_printf(m, "core\t\t\t: %d\n", cpu_core(&cpu_data[n]));
#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6)
if (cpu_has_mipsmt)
- seq_printf(m, "VPE\t\t\t: %d\n", cpu_data[n].vpe_id);
+ seq_printf(m, "VPE\t\t\t: %d\n", cpu_vpe_id(&cpu_data[n]));
else if (cpu_has_vp)
- seq_printf(m, "VP\t\t\t: %d\n", cpu_data[n].vpe_id);
+ seq_printf(m, "VP\t\t\t: %d\n", cpu_vpe_id(&cpu_data[n]));
#endif
sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 5351e1f3950d..c5ff6bfe2825 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -208,13 +208,13 @@ static inline int is_ra_save_ins(union mips_instruction *ip, int *poff)
*
* microMIPS is way more fun...
*/
- if (mm_insn_16bit(ip->halfword[1])) {
+ if (mm_insn_16bit(ip->word >> 16)) {
switch (ip->mm16_r5_format.opcode) {
case mm_swsp16_op:
if (ip->mm16_r5_format.rt != 31)
return 0;
- *poff = ip->mm16_r5_format.simmediate;
+ *poff = ip->mm16_r5_format.imm;
*poff = (*poff << 2) / sizeof(ulong);
return 1;
@@ -287,7 +287,7 @@ static inline int is_jump_ins(union mips_instruction *ip)
*
* microMIPS is kind of more fun...
*/
- if (mm_insn_16bit(ip->halfword[1])) {
+ if (mm_insn_16bit(ip->word >> 16)) {
if ((ip->mm16_r5_format.opcode == mm_pool16c_op &&
(ip->mm16_r5_format.rt & mm_jr16_op) == mm_jr16_op))
return 1;
@@ -313,9 +313,11 @@ static inline int is_jump_ins(union mips_instruction *ip)
#endif
}
-static inline int is_sp_move_ins(union mips_instruction *ip)
+static inline int is_sp_move_ins(union mips_instruction *ip, int *frame_size)
{
#ifdef CONFIG_CPU_MICROMIPS
+ unsigned short tmp;
+
/*
* addiusp -imm
* addius5 sp,-imm
@@ -324,21 +326,40 @@ static inline int is_sp_move_ins(union mips_instruction *ip)
*
* microMIPS is not more fun...
*/
- if (mm_insn_16bit(ip->halfword[1])) {
- return (ip->mm16_r3_format.opcode == mm_pool16d_op &&
- ip->mm16_r3_format.simmediate && mm_addiusp_func) ||
- (ip->mm16_r5_format.opcode == mm_pool16d_op &&
- ip->mm16_r5_format.rt == 29);
+ if (mm_insn_16bit(ip->word >> 16)) {
+ if (ip->mm16_r3_format.opcode == mm_pool16d_op &&
+ ip->mm16_r3_format.simmediate & mm_addiusp_func) {
+ tmp = ip->mm_b0_format.simmediate >> 1;
+ tmp = ((tmp & 0x1ff) ^ 0x100) - 0x100;
+ if ((tmp + 2) < 4) /* 0x0,0x1,0x1fe,0x1ff are special */
+ tmp ^= 0x100;
+ *frame_size = -(signed short)(tmp << 2);
+ return 1;
+ }
+ if (ip->mm16_r5_format.opcode == mm_pool16d_op &&
+ ip->mm16_r5_format.rt == 29) {
+ tmp = ip->mm16_r5_format.imm >> 1;
+ *frame_size = -(signed short)(tmp & 0xf);
+ return 1;
+ }
+ return 0;
}
- return ip->mm_i_format.opcode == mm_addiu32_op &&
- ip->mm_i_format.rt == 29 && ip->mm_i_format.rs == 29;
+ if (ip->mm_i_format.opcode == mm_addiu32_op &&
+ ip->mm_i_format.rt == 29 && ip->mm_i_format.rs == 29) {
+ *frame_size = -ip->i_format.simmediate;
+ return 1;
+ }
#else
/* addiu/daddiu sp,sp,-imm */
if (ip->i_format.rs != 29 || ip->i_format.rt != 29)
return 0;
- if (ip->i_format.opcode == addiu_op || ip->i_format.opcode == daddiu_op)
+
+ if (ip->i_format.opcode == addiu_op ||
+ ip->i_format.opcode == daddiu_op) {
+ *frame_size = -ip->i_format.simmediate;
return 1;
+ }
#endif
return 0;
}
@@ -348,7 +369,9 @@ static int get_frame_info(struct mips_frame_info *info)
bool is_mmips = IS_ENABLED(CONFIG_CPU_MICROMIPS);
union mips_instruction insn, *ip, *ip_end;
const unsigned int max_insns = 128;
+ unsigned int last_insn_size = 0;
unsigned int i;
+ bool saw_jump = false;
info->pc_offset = -1;
info->frame_size = 0;
@@ -359,47 +382,44 @@ static int get_frame_info(struct mips_frame_info *info)
ip_end = (void *)ip + info->func_size;
- for (i = 0; i < max_insns && ip < ip_end; i++, ip++) {
+ for (i = 0; i < max_insns && ip < ip_end; i++) {
+ ip = (void *)ip + last_insn_size;
if (is_mmips && mm_insn_16bit(ip->halfword[0])) {
- insn.halfword[0] = 0;
- insn.halfword[1] = ip->halfword[0];
+ insn.word = ip->halfword[0] << 16;
+ last_insn_size = 2;
} else if (is_mmips) {
- insn.halfword[0] = ip->halfword[1];
- insn.halfword[1] = ip->halfword[0];
+ insn.word = ip->halfword[0] << 16 | ip->halfword[1];
+ last_insn_size = 4;
} else {
insn.word = ip->word;
+ last_insn_size = 4;
}
- if (is_jump_ins(&insn))
- break;
-
if (!info->frame_size) {
- if (is_sp_move_ins(&insn))
- {
-#ifdef CONFIG_CPU_MICROMIPS
- if (mm_insn_16bit(ip->halfword[0]))
- {
- unsigned short tmp;
-
- if (ip->halfword[0] & mm_addiusp_func)
- {
- tmp = (((ip->halfword[0] >> 1) & 0x1ff) << 2);
- info->frame_size = -(signed short)(tmp | ((tmp & 0x100) ? 0xfe00 : 0));
- } else {
- tmp = (ip->halfword[0] >> 1);
- info->frame_size = -(signed short)(tmp & 0xf);
- }
- ip = (void *) &ip->halfword[1];
- ip--;
- } else
-#endif
- info->frame_size = - ip->i_format.simmediate;
- }
+ is_sp_move_ins(&insn, &info->frame_size);
+ continue;
+ } else if (!saw_jump && is_jump_ins(ip)) {
+ /*
+ * If we see a jump instruction, we are finished
+ * with the frame save.
+ *
+ * Some functions can have a shortcut return at
+ * the beginning of the function, so don't start
+ * looking for jump instruction until we see the
+ * frame setup.
+ *
+ * The RA save instruction can get put into the
+ * delay slot of the jump instruction, so look
+ * at the next instruction, too.
+ */
+ saw_jump = true;
continue;
}
if (info->pc_offset == -1 &&
is_ra_save_ins(&insn, &info->pc_offset))
break;
+ if (saw_jump)
+ break;
}
if (info->frame_size && info->pc_offset >= 0) /* nested */
return 0;
diff --git a/arch/mips/kernel/r2300_fpu.S b/arch/mips/kernel/r2300_fpu.S
index 918f2f6d3861..3062ba66c563 100644
--- a/arch/mips/kernel/r2300_fpu.S
+++ b/arch/mips/kernel/r2300_fpu.S
@@ -12,7 +12,9 @@
* Copyright (c) 1998 Harald Koerfgen
*/
#include <asm/asm.h>
+#include <asm/asmmacro.h>
#include <asm/errno.h>
+#include <asm/export.h>
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
#include <asm/asm-offsets.h>
@@ -31,9 +33,85 @@
PTR 9b+4,bad_stack; \
.previous
- .set noreorder
.set mips1
+/*
+ * Save a thread's fp context.
+ */
+LEAF(_save_fp)
+EXPORT_SYMBOL(_save_fp)
+ fpu_save_single a0, t1 # clobbers t1
+ jr ra
+ END(_save_fp)
+
+/*
+ * Restore a thread's fp context.
+ */
+LEAF(_restore_fp)
+ fpu_restore_single a0, t1 # clobbers t1
+ jr ra
+ END(_restore_fp)
+
+/*
+ * Load the FPU with signalling NANS. This bit pattern we're using has
+ * the property that no matter whether considered as single or as double
+ * precision represents signaling NANS.
+ *
+ * The value to initialize fcr31 to comes in $a0.
+ */
+
+ .set push
+ SET_HARDFLOAT
+
+LEAF(_init_fpu)
+ mfc0 t0, CP0_STATUS
+ li t1, ST0_CU1
+ or t0, t1
+ mtc0 t0, CP0_STATUS
+
+ ctc1 a0, fcr31
+
+ li t0, -1
+
+ mtc1 t0, $f0
+ mtc1 t0, $f1
+ mtc1 t0, $f2
+ mtc1 t0, $f3
+ mtc1 t0, $f4
+ mtc1 t0, $f5
+ mtc1 t0, $f6
+ mtc1 t0, $f7
+ mtc1 t0, $f8
+ mtc1 t0, $f9
+ mtc1 t0, $f10
+ mtc1 t0, $f11
+ mtc1 t0, $f12
+ mtc1 t0, $f13
+ mtc1 t0, $f14
+ mtc1 t0, $f15
+ mtc1 t0, $f16
+ mtc1 t0, $f17
+ mtc1 t0, $f18
+ mtc1 t0, $f19
+ mtc1 t0, $f20
+ mtc1 t0, $f21
+ mtc1 t0, $f22
+ mtc1 t0, $f23
+ mtc1 t0, $f24
+ mtc1 t0, $f25
+ mtc1 t0, $f26
+ mtc1 t0, $f27
+ mtc1 t0, $f28
+ mtc1 t0, $f29
+ mtc1 t0, $f30
+ mtc1 t0, $f31
+ jr ra
+ END(_init_fpu)
+
+ .set pop
+
+ .set noreorder
+
/**
* _save_fp_context() - save FP context from the FPU
* @a0 - pointer to fpregs field of sigcontext
diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S
index 1049eeafd97d..e57703b1de50 100644
--- a/arch/mips/kernel/r2300_switch.S
+++ b/arch/mips/kernel/r2300_switch.S
@@ -26,12 +26,6 @@
.align 5
/*
- * 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)
-
-/*
* task_struct *resume(task_struct *prev, task_struct *next,
* struct thread_info *next_ti)
*/
@@ -68,78 +62,3 @@ LEAF(resume)
move v0, a0
jr ra
END(resume)
-
-/*
- * Save a thread's fp context.
- */
-LEAF(_save_fp)
-EXPORT_SYMBOL(_save_fp)
- fpu_save_single a0, t1 # clobbers t1
- jr ra
- END(_save_fp)
-
-/*
- * Restore a thread's fp context.
- */
-LEAF(_restore_fp)
- fpu_restore_single a0, t1 # clobbers t1
- jr ra
- END(_restore_fp)
-
-/*
- * Load the FPU with signalling NANS. This bit pattern we're using has
- * the property that no matter whether considered as single or as double
- * precision represents signaling NANS.
- *
- * The value to initialize fcr31 to comes in $a0.
- */
-
- .set push
- SET_HARDFLOAT
-
-LEAF(_init_fpu)
- mfc0 t0, CP0_STATUS
- li t1, ST0_CU1
- or t0, t1
- mtc0 t0, CP0_STATUS
-
- ctc1 a0, fcr31
-
- li t0, -1
-
- mtc1 t0, $f0
- mtc1 t0, $f1
- mtc1 t0, $f2
- mtc1 t0, $f3
- mtc1 t0, $f4
- mtc1 t0, $f5
- mtc1 t0, $f6
- mtc1 t0, $f7
- mtc1 t0, $f8
- mtc1 t0, $f9
- mtc1 t0, $f10
- mtc1 t0, $f11
- mtc1 t0, $f12
- mtc1 t0, $f13
- mtc1 t0, $f14
- mtc1 t0, $f15
- mtc1 t0, $f16
- mtc1 t0, $f17
- mtc1 t0, $f18
- mtc1 t0, $f19
- mtc1 t0, $f20
- mtc1 t0, $f21
- mtc1 t0, $f22
- mtc1 t0, $f23
- mtc1 t0, $f24
- mtc1 t0, $f25
- mtc1 t0, $f26
- mtc1 t0, $f27
- mtc1 t0, $f28
- mtc1 t0, $f29
- mtc1 t0, $f30
- mtc1 t0, $f31
- jr ra
- END(_init_fpu)
-
- .set pop
diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
index 56d86b09c917..0a83b1708b3c 100644
--- a/arch/mips/kernel/r4k_fpu.S
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -15,6 +15,7 @@
#include <asm/asm.h>
#include <asm/asmmacro.h>
#include <asm/errno.h>
+#include <asm/export.h>
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
#include <asm/asm-offsets.h>
@@ -34,6 +35,201 @@
.previous
.endm
+/*
+ * Save a thread's fp context.
+ */
+LEAF(_save_fp)
+EXPORT_SYMBOL(_save_fp)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
+ defined(CONFIG_CPU_MIPS32_R6)
+ mfc0 t0, CP0_STATUS
+#endif
+ fpu_save_double a0 t0 t1 # clobbers t1
+ jr ra
+ END(_save_fp)
+
+/*
+ * Restore a thread's fp context.
+ */
+LEAF(_restore_fp)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
+ defined(CONFIG_CPU_MIPS32_R6)
+ mfc0 t0, CP0_STATUS
+#endif
+ fpu_restore_double a0 t0 t1 # clobbers t1
+ jr ra
+ END(_restore_fp)
+
+#ifdef CONFIG_CPU_HAS_MSA
+
+/*
+ * Save a thread's MSA vector context.
+ */
+LEAF(_save_msa)
+EXPORT_SYMBOL(_save_msa)
+ msa_save_all a0
+ jr ra
+ END(_save_msa)
+
+/*
+ * Restore a thread's MSA vector context.
+ */
+LEAF(_restore_msa)
+ msa_restore_all a0
+ jr ra
+ END(_restore_msa)
+
+LEAF(_init_msa_upper)
+ msa_init_all_upper
+ jr ra
+ END(_init_msa_upper)
+
+#endif
+
+/*
+ * Load the FPU with signalling NANS. This bit pattern we're using has
+ * the property that no matter whether considered as single or as double
+ * precision represents signaling NANS.
+ *
+ * The value to initialize fcr31 to comes in $a0.
+ */
+
+ .set push
+ SET_HARDFLOAT
+
+LEAF(_init_fpu)
+ mfc0 t0, CP0_STATUS
+ li t1, ST0_CU1
+ or t0, t1
+ mtc0 t0, CP0_STATUS
+ enable_fpu_hazard
+
+ ctc1 a0, fcr31
+
+ li t1, -1 # SNaN
+
+#ifdef CONFIG_64BIT
+ sll t0, t0, 5
+ bgez t0, 1f # 16 / 32 register mode?
+
+ dmtc1 t1, $f1
+ dmtc1 t1, $f3
+ dmtc1 t1, $f5
+ dmtc1 t1, $f7
+ dmtc1 t1, $f9
+ dmtc1 t1, $f11
+ dmtc1 t1, $f13
+ dmtc1 t1, $f15
+ dmtc1 t1, $f17
+ dmtc1 t1, $f19
+ dmtc1 t1, $f21
+ dmtc1 t1, $f23
+ dmtc1 t1, $f25
+ dmtc1 t1, $f27
+ dmtc1 t1, $f29
+ dmtc1 t1, $f31
+1:
+#endif
+
+#ifdef CONFIG_CPU_MIPS32
+ mtc1 t1, $f0
+ mtc1 t1, $f1
+ mtc1 t1, $f2
+ mtc1 t1, $f3
+ mtc1 t1, $f4
+ mtc1 t1, $f5
+ mtc1 t1, $f6
+ mtc1 t1, $f7
+ mtc1 t1, $f8
+ mtc1 t1, $f9
+ mtc1 t1, $f10
+ mtc1 t1, $f11
+ mtc1 t1, $f12
+ mtc1 t1, $f13
+ mtc1 t1, $f14
+ mtc1 t1, $f15
+ mtc1 t1, $f16
+ mtc1 t1, $f17
+ mtc1 t1, $f18
+ mtc1 t1, $f19
+ mtc1 t1, $f20
+ mtc1 t1, $f21
+ mtc1 t1, $f22
+ mtc1 t1, $f23
+ mtc1 t1, $f24
+ mtc1 t1, $f25
+ mtc1 t1, $f26
+ mtc1 t1, $f27
+ mtc1 t1, $f28
+ mtc1 t1, $f29
+ mtc1 t1, $f30
+ mtc1 t1, $f31
+
+#if defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS32_R6)
+ .set push
+ .set MIPS_ISA_LEVEL_RAW
+ .set fp=64
+ sll t0, t0, 5 # is Status.FR set?
+ bgez t0, 1f # no: skip setting upper 32b
+
+ mthc1 t1, $f0
+ mthc1 t1, $f1
+ mthc1 t1, $f2
+ mthc1 t1, $f3
+ mthc1 t1, $f4
+ mthc1 t1, $f5
+ mthc1 t1, $f6
+ mthc1 t1, $f7
+ mthc1 t1, $f8
+ mthc1 t1, $f9
+ mthc1 t1, $f10
+ mthc1 t1, $f11
+ mthc1 t1, $f12
+ mthc1 t1, $f13
+ mthc1 t1, $f14
+ mthc1 t1, $f15
+ mthc1 t1, $f16
+ mthc1 t1, $f17
+ mthc1 t1, $f18
+ mthc1 t1, $f19
+ mthc1 t1, $f20
+ mthc1 t1, $f21
+ mthc1 t1, $f22
+ mthc1 t1, $f23
+ mthc1 t1, $f24
+ mthc1 t1, $f25
+ mthc1 t1, $f26
+ mthc1 t1, $f27
+ mthc1 t1, $f28
+ mthc1 t1, $f29
+ mthc1 t1, $f30
+ mthc1 t1, $f31
+1: .set pop
+#endif /* CONFIG_CPU_MIPS32_R2 || CONFIG_CPU_MIPS32_R6 */
+#else
+ .set MIPS_ISA_ARCH_LEVEL_RAW
+ dmtc1 t1, $f0
+ dmtc1 t1, $f2
+ dmtc1 t1, $f4
+ dmtc1 t1, $f6
+ dmtc1 t1, $f8
+ dmtc1 t1, $f10
+ dmtc1 t1, $f12
+ dmtc1 t1, $f14
+ dmtc1 t1, $f16
+ dmtc1 t1, $f18
+ dmtc1 t1, $f20
+ dmtc1 t1, $f22
+ dmtc1 t1, $f24
+ dmtc1 t1, $f26
+ dmtc1 t1, $f28
+ dmtc1 t1, $f30
+#endif
+ jr ra
+ END(_init_fpu)
+
+ .set pop /* SET_HARDFLOAT */
+
.set noreorder
/**
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 7b386d54fd65..17cf9341c1cf 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -12,8 +12,6 @@
*/
#include <asm/asm.h>
#include <asm/cachectl.h>
-#include <asm/export.h>
-#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
#include <asm/asm-offsets.h>
#include <asm/regdef.h>
@@ -22,10 +20,6 @@
#include <asm/asmmacro.h>
-/* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */
-#undef fp
-
-#ifndef USE_ALTERNATE_RESUME_IMPL
/*
* task_struct *resume(task_struct *prev, task_struct *next,
* struct thread_info *next_ti)
@@ -63,200 +57,3 @@
move v0, a0
jr ra
END(resume)
-
-#endif /* USE_ALTERNATE_RESUME_IMPL */
-
-/*
- * Save a thread's fp context.
- */
-LEAF(_save_fp)
-EXPORT_SYMBOL(_save_fp)
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
- defined(CONFIG_CPU_MIPS32_R6)
- mfc0 t0, CP0_STATUS
-#endif
- fpu_save_double a0 t0 t1 # clobbers t1
- jr ra
- END(_save_fp)
-
-/*
- * Restore a thread's fp context.
- */
-LEAF(_restore_fp)
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
- defined(CONFIG_CPU_MIPS32_R6)
- mfc0 t0, CP0_STATUS
-#endif
- fpu_restore_double a0 t0 t1 # clobbers t1
- jr ra
- END(_restore_fp)
-
-#ifdef CONFIG_CPU_HAS_MSA
-
-/*
- * Save a thread's MSA vector context.
- */
-LEAF(_save_msa)
-EXPORT_SYMBOL(_save_msa)
- msa_save_all a0
- jr ra
- END(_save_msa)
-
-/*
- * Restore a thread's MSA vector context.
- */
-LEAF(_restore_msa)
- msa_restore_all a0
- jr ra
- END(_restore_msa)
-
-LEAF(_init_msa_upper)
- msa_init_all_upper
- jr ra
- END(_init_msa_upper)
-
-#endif
-
-/*
- * Load the FPU with signalling NANS. This bit pattern we're using has
- * the property that no matter whether considered as single or as double
- * precision represents signaling NANS.
- *
- * The value to initialize fcr31 to comes in $a0.
- */
-
- .set push
- SET_HARDFLOAT
-
-LEAF(_init_fpu)
- mfc0 t0, CP0_STATUS
- li t1, ST0_CU1
- or t0, t1
- mtc0 t0, CP0_STATUS
- enable_fpu_hazard
-
- ctc1 a0, fcr31
-
- li t1, -1 # SNaN
-
-#ifdef CONFIG_64BIT
- sll t0, t0, 5
- bgez t0, 1f # 16 / 32 register mode?
-
- dmtc1 t1, $f1
- dmtc1 t1, $f3
- dmtc1 t1, $f5
- dmtc1 t1, $f7
- dmtc1 t1, $f9
- dmtc1 t1, $f11
- dmtc1 t1, $f13
- dmtc1 t1, $f15
- dmtc1 t1, $f17
- dmtc1 t1, $f19
- dmtc1 t1, $f21
- dmtc1 t1, $f23
- dmtc1 t1, $f25
- dmtc1 t1, $f27
- dmtc1 t1, $f29
- dmtc1 t1, $f31
-1:
-#endif
-
-#ifdef CONFIG_CPU_MIPS32
- mtc1 t1, $f0
- mtc1 t1, $f1
- mtc1 t1, $f2
- mtc1 t1, $f3
- mtc1 t1, $f4
- mtc1 t1, $f5
- mtc1 t1, $f6
- mtc1 t1, $f7
- mtc1 t1, $f8
- mtc1 t1, $f9
- mtc1 t1, $f10
- mtc1 t1, $f11
- mtc1 t1, $f12
- mtc1 t1, $f13
- mtc1 t1, $f14
- mtc1 t1, $f15
- mtc1 t1, $f16
- mtc1 t1, $f17
- mtc1 t1, $f18
- mtc1 t1, $f19
- mtc1 t1, $f20
- mtc1 t1, $f21
- mtc1 t1, $f22
- mtc1 t1, $f23
- mtc1 t1, $f24
- mtc1 t1, $f25
- mtc1 t1, $f26
- mtc1 t1, $f27
- mtc1 t1, $f28
- mtc1 t1, $f29
- mtc1 t1, $f30
- mtc1 t1, $f31
-
-#if defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS32_R6)
- .set push
- .set MIPS_ISA_LEVEL_RAW
- .set fp=64
- sll t0, t0, 5 # is Status.FR set?
- bgez t0, 1f # no: skip setting upper 32b
-
- mthc1 t1, $f0
- mthc1 t1, $f1
- mthc1 t1, $f2
- mthc1 t1, $f3
- mthc1 t1, $f4
- mthc1 t1, $f5
- mthc1 t1, $f6
- mthc1 t1, $f7
- mthc1 t1, $f8
- mthc1 t1, $f9
- mthc1 t1, $f10
- mthc1 t1, $f11
- mthc1 t1, $f12
- mthc1 t1, $f13
- mthc1 t1, $f14
- mthc1 t1, $f15
- mthc1 t1, $f16
- mthc1 t1, $f17
- mthc1 t1, $f18
- mthc1 t1, $f19
- mthc1 t1, $f20
- mthc1 t1, $f21
- mthc1 t1, $f22
- mthc1 t1, $f23
- mthc1 t1, $f24
- mthc1 t1, $f25
- mthc1 t1, $f26
- mthc1 t1, $f27
- mthc1 t1, $f28
- mthc1 t1, $f29
- mthc1 t1, $f30
- mthc1 t1, $f31
-1: .set pop
-#endif /* CONFIG_CPU_MIPS32_R2 || CONFIG_CPU_MIPS32_R6 */
-#else
- .set MIPS_ISA_ARCH_LEVEL_RAW
- dmtc1 t1, $f0
- dmtc1 t1, $f2
- dmtc1 t1, $f4
- dmtc1 t1, $f6
- dmtc1 t1, $f8
- dmtc1 t1, $f10
- dmtc1 t1, $f12
- dmtc1 t1, $f14
- dmtc1 t1, $f16
- dmtc1 t1, $f18
- dmtc1 t1, $f20
- dmtc1 t1, $f22
- dmtc1 t1, $f24
- dmtc1 t1, $f26
- dmtc1 t1, $f28
- dmtc1 t1, $f30
-#endif
- jr ra
- END(_init_fpu)
-
- .set pop /* SET_HARDFLOAT */
diff --git a/arch/mips/kernel/r6000_fpu.S b/arch/mips/kernel/r6000_fpu.S
deleted file mode 100644
index 9cc7bfab3419..000000000000
--- a/arch/mips/kernel/r6000_fpu.S
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * r6000_fpu.S: Save/restore floating point context for signal handlers.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1996 by Ralf Baechle
- *
- * Multi-arch abstraction and asm macros for easier reading:
- * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
- */
-#include <asm/asm.h>
-#include <asm/fpregdef.h>
-#include <asm/mipsregs.h>
-#include <asm/asm-offsets.h>
-#include <asm/regdef.h>
-
- .set noreorder
- .set mips2
- .set push
- SET_HARDFLOAT
-
-/**
- * _save_fp_context() - save FP context from the FPU
- * @a0 - pointer to fpregs field of sigcontext
- * @a1 - pointer to fpc_csr field of sigcontext
- *
- * Save FP context, including the 32 FP data registers and the FP
- * control & status register, from the FPU to signal context.
- */
- LEAF(_save_fp_context)
- mfc0 t0,CP0_STATUS
- sll t0,t0,2
- bgez t0,1f
- nop
-
- cfc1 t1,fcr31
- /* Store the 16 double precision registers */
- sdc1 $f0,0(a0)
- sdc1 $f2,16(a0)
- sdc1 $f4,32(a0)
- sdc1 $f6,48(a0)
- sdc1 $f8,64(a0)
- sdc1 $f10,80(a0)
- sdc1 $f12,96(a0)
- sdc1 $f14,112(a0)
- sdc1 $f16,128(a0)
- sdc1 $f18,144(a0)
- sdc1 $f20,160(a0)
- sdc1 $f22,176(a0)
- sdc1 $f24,192(a0)
- sdc1 $f26,208(a0)
- sdc1 $f28,224(a0)
- sdc1 $f30,240(a0)
- jr ra
- sw t0,(a1)
-1: jr ra
- nop
- END(_save_fp_context)
-
-/**
- * _restore_fp_context() - restore FP context to the FPU
- * @a0 - pointer to fpregs field of sigcontext
- * @a1 - pointer to fpc_csr field of sigcontext
- *
- * Restore FP context, including the 32 FP data registers and the FP
- * control & status register, from signal context to the FPU.
- */
- LEAF(_restore_fp_context)
- mfc0 t0,CP0_STATUS
- sll t0,t0,2
-
- bgez t0,1f
- lw t0,(a1)
- /* Restore the 16 double precision registers */
- ldc1 $f0,0(a0)
- ldc1 $f2,16(a0)
- ldc1 $f4,32(a0)
- ldc1 $f6,48(a0)
- ldc1 $f8,64(a0)
- ldc1 $f10,80(a0)
- ldc1 $f12,96(a0)
- ldc1 $f14,112(a0)
- ldc1 $f16,128(a0)
- ldc1 $f18,144(a0)
- ldc1 $f20,160(a0)
- ldc1 $f22,176(a0)
- ldc1 $f24,192(a0)
- ldc1 $f26,208(a0)
- ldc1 $f28,224(a0)
- ldc1 $f30,240(a0)
- jr ra
- ctc1 t0,fcr31
-1: jr ra
- nop
- END(_restore_fp_context)
-
- .set pop /* SET_HARDFLOAT */
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c
index 1b070a76fcdd..406072e26752 100644
--- a/arch/mips/kernel/smp-bmips.c
+++ b/arch/mips/kernel/smp-bmips.c
@@ -179,7 +179,7 @@ static void bmips_prepare_cpus(unsigned int max_cpus)
/*
* Tell the hardware to boot CPUx - runs on CPU0
*/
-static void bmips_boot_secondary(int cpu, struct task_struct *idle)
+static int bmips_boot_secondary(int cpu, struct task_struct *idle)
{
bmips_smp_boot_sp = __KSTK_TOS(idle);
bmips_smp_boot_gp = (unsigned long)task_thread_info(idle);
@@ -231,6 +231,8 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle)
}
cpumask_set_cpu(cpu, &bmips_booted_mask);
}
+
+ return 0;
}
/*
@@ -245,7 +247,7 @@ static void bmips_init_secondary(void)
break;
case CPU_BMIPS5000:
write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
- current_cpu_data.core = (read_c0_brcm_config() >> 25) & 3;
+ cpu_set_core(&current_cpu_data, (read_c0_brcm_config() >> 25) & 3);
break;
}
}
@@ -409,7 +411,7 @@ void __ref play_dead(void)
#endif /* CONFIG_HOTPLUG_CPU */
-struct plat_smp_ops bmips43xx_smp_ops = {
+const struct plat_smp_ops bmips43xx_smp_ops = {
.smp_setup = bmips_smp_setup,
.prepare_cpus = bmips_prepare_cpus,
.boot_secondary = bmips_boot_secondary,
@@ -423,7 +425,7 @@ struct plat_smp_ops bmips43xx_smp_ops = {
#endif
};
-struct plat_smp_ops bmips5000_smp_ops = {
+const struct plat_smp_ops bmips5000_smp_ops = {
.smp_setup = bmips_smp_setup,
.prepare_cpus = bmips_prepare_cpus,
.boot_secondary = bmips_boot_secondary,
diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c
index 76923349b4fe..05295a4909f1 100644
--- a/arch/mips/kernel/smp-cmp.c
+++ b/arch/mips/kernel/smp-cmp.c
@@ -24,7 +24,6 @@
#include <linux/cpumask.h>
#include <linux/interrupt.h>
#include <linux/compiler.h>
-#include <linux/irqchip/mips-gic.h>
#include <linux/atomic.h>
#include <asm/cacheflush.h>
@@ -78,7 +77,7 @@ static void cmp_smp_finish(void)
* __KSTK_TOS(idle) is apparently the stack pointer
* (unsigned long)idle->thread_info the gp
*/
-static void cmp_boot_secondary(int cpu, struct task_struct *idle)
+static int cmp_boot_secondary(int cpu, struct task_struct *idle)
{
struct thread_info *gp = task_thread_info(idle);
unsigned long sp = __KSTK_TOS(idle);
@@ -95,6 +94,7 @@ static void cmp_boot_secondary(int cpu, struct task_struct *idle)
#endif
amon_cpu_start(cpu, pc, sp, (unsigned long)gp, a0);
+ return 0;
}
/*
@@ -148,7 +148,7 @@ void __init cmp_prepare_cpus(unsigned int max_cpus)
}
-struct plat_smp_ops cmp_smp_ops = {
+const struct plat_smp_ops cmp_smp_ops = {
.send_ipi_single = mips_smp_send_ipi_single,
.send_ipi_mask = mips_smp_send_ipi_mask,
.init_secondary = cmp_init_secondary,
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
index f832e99ad4c3..0063122c85da 100644
--- a/arch/mips/kernel/smp-cps.c
+++ b/arch/mips/kernel/smp-cps.c
@@ -11,7 +11,6 @@
#include <linux/cpu.h>
#include <linux/delay.h>
#include <linux/io.h>
-#include <linux/irqchip/mips-gic.h>
#include <linux/sched/task_stack.h>
#include <linux/sched/hotplug.h>
#include <linux/slab.h>
@@ -19,8 +18,7 @@
#include <linux/types.h>
#include <asm/bcache.h>
-#include <asm/mips-cm.h>
-#include <asm/mips-cpc.h>
+#include <asm/mips-cps.h>
#include <asm/mips_mt.h>
#include <asm/mipsregs.h>
#include <asm/pm-cps.h>
@@ -41,55 +39,58 @@ static int __init setup_nothreads(char *s)
}
early_param("nothreads", setup_nothreads);
-static unsigned core_vpe_count(unsigned core)
+static unsigned core_vpe_count(unsigned int cluster, unsigned core)
{
- unsigned cfg;
-
if (threads_disabled)
return 1;
- if ((!IS_ENABLED(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
- && (!IS_ENABLED(CONFIG_CPU_MIPSR6) || !cpu_has_vp))
- return 1;
-
- mips_cm_lock_other(core, 0);
- cfg = read_gcr_co_config() & CM_GCR_Cx_CONFIG_PVPE_MSK;
- mips_cm_unlock_other();
- return (cfg >> CM_GCR_Cx_CONFIG_PVPE_SHF) + 1;
+ return mips_cps_numvps(cluster, core);
}
static void __init cps_smp_setup(void)
{
- unsigned int ncores, nvpes, core_vpes;
+ unsigned int nclusters, ncores, nvpes, core_vpes;
unsigned long core_entry;
- int c, v;
+ int cl, c, v;
/* Detect & record VPE topology */
- ncores = mips_cm_numcores();
+ nvpes = 0;
+ nclusters = mips_cps_numclusters();
pr_info("%s topology ", cpu_has_mips_r6 ? "VP" : "VPE");
- for (c = nvpes = 0; c < ncores; c++) {
- core_vpes = core_vpe_count(c);
- pr_cont("%c%u", c ? ',' : '{', core_vpes);
-
- /* Use the number of VPEs in core 0 for smp_num_siblings */
- if (!c)
- smp_num_siblings = core_vpes;
-
- for (v = 0; v < min_t(int, core_vpes, NR_CPUS - nvpes); v++) {
- cpu_data[nvpes + v].core = c;
-#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6)
- cpu_data[nvpes + v].vpe_id = v;
-#endif
+ for (cl = 0; cl < nclusters; cl++) {
+ if (cl > 0)
+ pr_cont(",");
+ pr_cont("{");
+
+ ncores = mips_cps_numcores(cl);
+ for (c = 0; c < ncores; c++) {
+ core_vpes = core_vpe_count(cl, c);
+
+ if (c > 0)
+ pr_cont(",");
+ pr_cont("%u", core_vpes);
+
+ /* Use the number of VPEs in cluster 0 core 0 for smp_num_siblings */
+ if (!cl && !c)
+ smp_num_siblings = core_vpes;
+
+ for (v = 0; v < min_t(int, core_vpes, NR_CPUS - nvpes); v++) {
+ cpu_set_cluster(&cpu_data[nvpes + v], cl);
+ cpu_set_core(&cpu_data[nvpes + v], c);
+ cpu_set_vpe_id(&cpu_data[nvpes + v], v);
+ }
+
+ nvpes += core_vpes;
}
- nvpes += core_vpes;
+ pr_cont("}");
}
- pr_cont("} total %u\n", nvpes);
+ pr_cont(" total %u\n", nvpes);
/* Indicate present CPUs (CPU being synonymous with VPE) */
for (v = 0; v < min_t(unsigned, nvpes, NR_CPUS); v++) {
- set_cpu_possible(v, true);
- set_cpu_present(v, true);
+ set_cpu_possible(v, cpu_cluster(&cpu_data[v]) == 0);
+ set_cpu_present(v, cpu_cluster(&cpu_data[v]) == 0);
__cpu_number_map[v] = v;
__cpu_logical_map[v] = v;
}
@@ -121,7 +122,7 @@ static void __init cps_smp_setup(void)
static void __init cps_prepare_cpus(unsigned int max_cpus)
{
unsigned ncores, core_vpes, c, cca;
- bool cca_unsuitable;
+ bool cca_unsuitable, cores_limited;
u32 *entry_code;
mips_mt_set_cpuoptions();
@@ -141,19 +142,22 @@ static void __init cps_prepare_cpus(unsigned int max_cpus)
}
/* Warn the user if the CCA prevents multi-core */
- ncores = mips_cm_numcores();
- if ((cca_unsuitable || cpu_has_dc_aliases) && ncores > 1) {
+ cores_limited = false;
+ if (cca_unsuitable || cpu_has_dc_aliases) {
+ for_each_present_cpu(c) {
+ if (cpus_are_siblings(smp_processor_id(), c))
+ continue;
+
+ set_cpu_present(c, false);
+ cores_limited = true;
+ }
+ }
+ if (cores_limited)
pr_warn("Using only one core due to %s%s%s\n",
cca_unsuitable ? "unsuitable CCA" : "",
(cca_unsuitable && cpu_has_dc_aliases) ? " & " : "",
cpu_has_dc_aliases ? "dcache aliasing" : "");
- for_each_present_cpu(c) {
- if (cpu_data[c].core)
- set_cpu_present(c, false);
- }
- }
-
/*
* Patch the start of mips_cps_core_entry to provide:
*
@@ -168,6 +172,7 @@ static void __init cps_prepare_cpus(unsigned int max_cpus)
__sync();
/* Allocate core boot configuration structs */
+ ncores = mips_cps_numcores(0);
mips_cps_core_bootcfg = kcalloc(ncores, sizeof(*mips_cps_core_bootcfg),
GFP_KERNEL);
if (!mips_cps_core_bootcfg) {
@@ -177,7 +182,7 @@ static void __init cps_prepare_cpus(unsigned int max_cpus)
/* Allocate VPE boot configuration structs */
for (c = 0; c < ncores; c++) {
- core_vpes = core_vpe_count(c);
+ core_vpes = core_vpe_count(0, c);
mips_cps_core_bootcfg[c].vpe_config = kcalloc(core_vpes,
sizeof(*mips_cps_core_bootcfg[c].vpe_config),
GFP_KERNEL);
@@ -189,7 +194,7 @@ static void __init cps_prepare_cpus(unsigned int max_cpus)
}
/* Mark this CPU as booted */
- atomic_set(&mips_cps_core_bootcfg[current_cpu_data.core].vpe_mask,
+ atomic_set(&mips_cps_core_bootcfg[cpu_core(&current_cpu_data)].vpe_mask,
1 << cpu_vpe_id(&current_cpu_data));
return;
@@ -212,11 +217,11 @@ err_out:
static void boot_core(unsigned int core, unsigned int vpe_id)
{
- u32 access, stat, seq_state;
+ u32 stat, seq_state;
unsigned timeout;
/* Select the appropriate core */
- mips_cm_lock_other(core, 0);
+ mips_cm_lock_other(0, core, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
/* Set its reset vector */
write_gcr_co_reset_base(CKSEG1ADDR((unsigned long)mips_cps_core_entry));
@@ -225,12 +230,10 @@ static void boot_core(unsigned int core, unsigned int vpe_id)
write_gcr_co_coherence(0);
/* Start it with the legacy memory map and exception base */
- write_gcr_co_reset_ext_base(CM_GCR_RESET_EXT_BASE_UEB);
+ write_gcr_co_reset_ext_base(CM_GCR_Cx_RESET_EXT_BASE_UEB);
/* Ensure the core can access the GCRs */
- access = read_gcr_access();
- access |= 1 << (CM_GCR_ACCESS_ACCESSEN_SHF + core);
- write_gcr_access(access);
+ set_gcr_access(1 << core);
if (mips_cpc_present()) {
/* Reset the core */
@@ -253,7 +256,8 @@ static void boot_core(unsigned int core, unsigned int vpe_id)
timeout = 100;
while (true) {
stat = read_cpc_co_stat_conf();
- seq_state = stat & CPC_Cx_STAT_CONF_SEQSTATE_MSK;
+ seq_state = stat & CPC_Cx_STAT_CONF_SEQSTATE;
+ seq_state >>= __ffs(CPC_Cx_STAT_CONF_SEQSTATE);
/* U6 == coherent execution, ie. the core is up */
if (seq_state == CPC_Cx_STAT_CONF_SEQSTATE_U6)
@@ -285,15 +289,15 @@ static void boot_core(unsigned int core, unsigned int vpe_id)
static void remote_vpe_boot(void *dummy)
{
- unsigned core = current_cpu_data.core;
+ unsigned core = cpu_core(&current_cpu_data);
struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core];
mips_cps_boot_vpes(core_cfg, cpu_vpe_id(&current_cpu_data));
}
-static void cps_boot_secondary(int cpu, struct task_struct *idle)
+static int cps_boot_secondary(int cpu, struct task_struct *idle)
{
- unsigned core = cpu_data[cpu].core;
+ unsigned core = cpu_core(&cpu_data[cpu]);
unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]);
struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core];
struct vpe_boot_config *vpe_cfg = &core_cfg->vpe_config[vpe_id];
@@ -301,6 +305,10 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle)
unsigned int remote;
int err;
+ /* We don't yet support booting CPUs in other clusters */
+ if (cpu_cluster(&cpu_data[cpu]) != cpu_cluster(&current_cpu_data))
+ return -ENOSYS;
+
vpe_cfg->pc = (unsigned long)&smp_bootstrap;
vpe_cfg->sp = __KSTK_TOS(idle);
vpe_cfg->gp = (unsigned long)task_thread_info(idle);
@@ -316,16 +324,16 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle)
}
if (cpu_has_vp) {
- mips_cm_lock_other(core, vpe_id);
+ mips_cm_lock_other(0, core, vpe_id, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
core_entry = CKSEG1ADDR((unsigned long)mips_cps_core_entry);
write_gcr_co_reset_base(core_entry);
mips_cm_unlock_other();
}
- if (core != current_cpu_data.core) {
+ if (!cpus_are_siblings(cpu, smp_processor_id())) {
/* Boot a VPE on another powered up core */
for (remote = 0; remote < NR_CPUS; remote++) {
- if (cpu_data[remote].core != core)
+ if (!cpus_are_siblings(cpu, remote))
continue;
if (cpu_online(remote))
break;
@@ -349,6 +357,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle)
mips_cps_boot_vpes(core_cfg, vpe_id);
out:
preempt_enable();
+ return 0;
}
static void cps_init_secondary(void)
@@ -358,7 +367,7 @@ static void cps_init_secondary(void)
dmt();
if (mips_cm_revision() >= CM_REV_CM3) {
- unsigned ident = gic_read_local_vp_id();
+ unsigned int ident = read_gic_vl_ident();
/*
* Ensure that our calculation of the VP ID matches up with
@@ -402,7 +411,7 @@ static int cps_cpu_disable(void)
if (!cps_pm_support_state(CPS_PM_POWER_GATED))
return -EINVAL;
- core_cfg = &mips_cps_core_bootcfg[current_cpu_data.core];
+ core_cfg = &mips_cps_core_bootcfg[cpu_core(&current_cpu_data)];
atomic_sub(1 << cpu_vpe_id(&current_cpu_data), &core_cfg->vpe_mask);
smp_mb__after_atomic();
set_cpu_online(cpu, false);
@@ -424,15 +433,17 @@ void play_dead(void)
local_irq_disable();
idle_task_exit();
cpu = smp_processor_id();
- core = cpu_data[cpu].core;
+ core = cpu_core(&cpu_data[cpu]);
cpu_death = CPU_DEATH_POWER;
pr_debug("CPU%d going offline\n", cpu);
if (cpu_has_mipsmt || cpu_has_vp) {
+ core = cpu_core(&cpu_data[cpu]);
+
/* Look for another online VPE within the core */
for_each_online_cpu(cpu_death_sibling) {
- if (cpu_data[cpu_death_sibling].core != core)
+ if (!cpus_are_siblings(cpu, cpu_death_sibling))
continue;
/*
@@ -488,7 +499,7 @@ static void wait_for_sibling_halt(void *ptr_cpu)
static void cps_cpu_die(unsigned int cpu)
{
- unsigned core = cpu_data[cpu].core;
+ unsigned core = cpu_core(&cpu_data[cpu]);
unsigned int vpe_id = cpu_vpe_id(&cpu_data[cpu]);
ktime_t fail_time;
unsigned stat;
@@ -519,10 +530,11 @@ static void cps_cpu_die(unsigned int cpu)
*/
fail_time = ktime_add_ms(ktime_get(), 2000);
do {
- mips_cm_lock_other(core, 0);
+ mips_cm_lock_other(0, core, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
mips_cpc_lock_other(core);
stat = read_cpc_co_stat_conf();
- stat &= CPC_Cx_STAT_CONF_SEQSTATE_MSK;
+ stat &= CPC_Cx_STAT_CONF_SEQSTATE;
+ stat >>= __ffs(CPC_Cx_STAT_CONF_SEQSTATE);
mips_cpc_unlock_other();
mips_cm_unlock_other();
@@ -544,7 +556,7 @@ static void cps_cpu_die(unsigned int cpu)
*/
if (WARN(ktime_after(ktime_get(), fail_time),
"CPU%u hasn't powered down, seq. state %u\n",
- cpu, stat >> CPC_Cx_STAT_CONF_SEQSTATE_SHF))
+ cpu, stat))
break;
} while (1);
@@ -562,7 +574,7 @@ static void cps_cpu_die(unsigned int cpu)
panic("Failed to call remote sibling CPU\n");
} else if (cpu_has_vp) {
do {
- mips_cm_lock_other(core, vpe_id);
+ mips_cm_lock_other(0, core, vpe_id, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
stat = read_cpc_co_vp_running();
mips_cm_unlock_other();
} while (stat & (1 << vpe_id));
@@ -571,7 +583,7 @@ static void cps_cpu_die(unsigned int cpu)
#endif /* CONFIG_HOTPLUG_CPU */
-static struct plat_smp_ops cps_smp_ops = {
+static const struct plat_smp_ops cps_smp_ops = {
.smp_setup = cps_smp_setup,
.prepare_cpus = cps_prepare_cpus,
.boot_secondary = cps_boot_secondary,
@@ -587,7 +599,7 @@ static struct plat_smp_ops cps_smp_ops = {
bool mips_cps_smp_in_use(void)
{
- extern struct plat_smp_ops *mp_ops;
+ extern const struct plat_smp_ops *mp_ops;
return mp_ops == &cps_smp_ops;
}
@@ -599,7 +611,7 @@ int register_cps_smp_ops(void)
}
/* check we have a GIC - we need one for IPIs */
- if (!(read_gcr_gic_status() & CM_GCR_GIC_STATUS_EX_MSK)) {
+ if (!(read_gcr_gic_status() & CM_GCR_GIC_STATUS_EX)) {
pr_warn("MIPS CPS SMP unable to proceed without a GIC\n");
return -ENODEV;
}
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index ed6b4df583ea..94ab3276b48c 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -21,7 +21,6 @@
#include <linux/sched.h>
#include <linux/cpumask.h>
#include <linux/interrupt.h>
-#include <linux/irqchip/mips-gic.h>
#include <linux/compiler.h>
#include <linux/sched/task_stack.h>
#include <linux/smp.h>
@@ -36,6 +35,7 @@
#include <asm/mipsregs.h>
#include <asm/mipsmtregs.h>
#include <asm/mips_mt.h>
+#include <asm/mips-cps.h>
static void __init smvp_copy_vpe_config(void)
{
@@ -83,7 +83,7 @@ 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;
+ cpu_set_vpe_id(&cpu_data[ncpu], tc);
return ncpu;
}
@@ -118,14 +118,12 @@ static void __init smvp_tc_init(unsigned int tc, unsigned int mvpconf0)
static void vsmp_init_secondary(void)
{
-#ifdef CONFIG_MIPS_GIC
/* This is Malta specific: IPI,performance and timer interrupts */
- if (gic_present)
+ if (mips_gic_present())
change_c0_status(ST0_IM, STATUSF_IP2 | STATUSF_IP3 |
STATUSF_IP4 | STATUSF_IP5 |
STATUSF_IP6 | STATUSF_IP7);
else
-#endif
change_c0_status(ST0_IM, STATUSF_IP0 | STATUSF_IP1 |
STATUSF_IP6 | STATUSF_IP7);
}
@@ -152,7 +150,7 @@ static void vsmp_smp_finish(void)
* (unsigned long)idle->thread_info the gp
* assumes a 1:1 mapping of TC => VPE
*/
-static void vsmp_boot_secondary(int cpu, struct task_struct *idle)
+static int vsmp_boot_secondary(int cpu, struct task_struct *idle)
{
struct thread_info *gp = task_thread_info(idle);
dvpe();
@@ -184,6 +182,8 @@ static void vsmp_boot_secondary(int cpu, struct task_struct *idle)
clear_c0_mvpcontrol(MVPCONTROL_VPC);
evpe(EVPE_ENABLE);
+
+ return 0;
}
/*
@@ -239,7 +239,7 @@ static void __init vsmp_prepare_cpus(unsigned int max_cpus)
mips_mt_set_cpuoptions();
}
-struct plat_smp_ops vsmp_smp_ops = {
+const struct plat_smp_ops vsmp_smp_ops = {
.send_ipi_single = mips_smp_send_ipi_single,
.send_ipi_mask = mips_smp_send_ipi_mask,
.init_secondary = vsmp_init_secondary,
diff --git a/arch/mips/kernel/smp-up.c b/arch/mips/kernel/smp-up.c
index 17878d71ef2b..525d3196f793 100644
--- a/arch/mips/kernel/smp-up.c
+++ b/arch/mips/kernel/smp-up.c
@@ -39,8 +39,9 @@ static void up_smp_finish(void)
/*
* Firmware CPU startup hook
*/
-static void up_boot_secondary(int cpu, struct task_struct *idle)
+static int up_boot_secondary(int cpu, struct task_struct *idle)
{
+ return 0;
}
static void __init up_smp_setup(void)
@@ -63,7 +64,7 @@ static void up_cpu_die(unsigned int cpu)
}
#endif
-struct plat_smp_ops up_smp_ops = {
+const struct plat_smp_ops up_smp_ops = {
.send_ipi_single = up_send_ipi_single,
.send_ipi_mask = up_send_ipi_mask,
.init_secondary = up_init_secondary,
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index c7cbddfcdc3b..bbe19b64def5 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -96,8 +96,7 @@ static inline void set_cpu_sibling_map(int cpu)
if (smp_num_siblings > 1) {
for_each_cpu(i, &cpu_sibling_setup_map) {
- if (cpu_data[cpu].package == cpu_data[i].package &&
- cpu_data[cpu].core == cpu_data[i].core) {
+ if (cpus_are_siblings(cpu, i)) {
cpumask_set_cpu(i, &cpu_sibling_map[cpu]);
cpumask_set_cpu(cpu, &cpu_sibling_map[i]);
}
@@ -134,8 +133,7 @@ void calculate_cpu_foreign_map(void)
for_each_online_cpu(i) {
core_present = 0;
for_each_cpu(k, &temp_foreign_map)
- if (cpu_data[i].package == cpu_data[k].package &&
- cpu_data[i].core == cpu_data[k].core)
+ if (cpus_are_siblings(i, k))
core_present = 1;
if (!core_present)
cpumask_set_cpu(i, &temp_foreign_map);
@@ -146,10 +144,10 @@ void calculate_cpu_foreign_map(void)
&temp_foreign_map, &cpu_sibling_map[i]);
}
-struct plat_smp_ops *mp_ops;
+const struct plat_smp_ops *mp_ops;
EXPORT_SYMBOL(mp_ops);
-void register_smp_ops(struct plat_smp_ops *ops)
+void register_smp_ops(const struct plat_smp_ops *ops)
{
if (mp_ops)
printk(KERN_WARNING "Overriding previously set SMP ops\n");
@@ -186,13 +184,13 @@ void mips_smp_send_ipi_mask(const struct cpumask *mask, unsigned int action)
if (mips_cpc_present()) {
for_each_cpu(cpu, mask) {
- core = cpu_data[cpu].core;
-
- if (core == current_cpu_data.core)
+ if (cpus_are_siblings(cpu, smp_processor_id()))
continue;
+ core = cpu_core(&cpu_data[cpu]);
+
while (!cpumask_test_cpu(cpu, &cpu_coherent_mask)) {
- mips_cm_lock_other(core, 0);
+ mips_cm_lock_other_cpu(cpu, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
mips_cpc_lock_other(core);
write_cpc_co_cmd(CPC_Cx_CMD_PWRUP);
mips_cpc_unlock_other();
@@ -441,7 +439,11 @@ void smp_prepare_boot_cpu(void)
int __cpu_up(unsigned int cpu, struct task_struct *tidle)
{
- mp_ops->boot_secondary(cpu, tidle);
+ int err;
+
+ err = mp_ops->boot_secondary(cpu, tidle);
+ if (err)
+ return err;
/*
* We must check for timeout here, as the CPU will not be marked
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index c036157fb891..a6ebc8135112 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -72,20 +72,6 @@ EXPORT_SYMBOL(perf_irq);
unsigned int mips_hpt_frequency;
EXPORT_SYMBOL_GPL(mips_hpt_frequency);
-/*
- * This function exists in order to cause an error due to a duplicate
- * definition if platform code should have its own implementation. The hook
- * to use instead is plat_time_init. plat_time_init does not receive the
- * irqaction pointer argument anymore. This is because any function which
- * initializes an interrupt timer now takes care of its own request_irq rsp.
- * setup_irq calls and each clock_event_device should use its own
- * struct irqrequest.
- */
-void __init plat_timer_setup(void)
-{
- BUG();
-}
-
static __init int cpu_has_mfc0_count_bug(void)
{
switch (current_cpu_type()) {
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 2bf414993347..5669d3b8bd38 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -50,9 +50,8 @@
#include <asm/fpu.h>
#include <asm/fpu_emulator.h>
#include <asm/idle.h>
-#include <asm/mips-cm.h>
+#include <asm/mips-cps.h>
#include <asm/mips-r2-to-r6-emul.h>
-#include <asm/mips-cm.h>
#include <asm/mipsregs.h>
#include <asm/mipsmtregs.h>
#include <asm/module.h>
@@ -734,8 +733,7 @@ void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr,
si.si_code = FPE_FLTUND;
else if (fcr31 & FPU_CSR_INE_X)
si.si_code = FPE_FLTRES;
- else
- return; /* Broken hardware? */
+
force_sig_info(SIGFPE, &si, tsk);
}
@@ -1673,7 +1671,7 @@ static inline void parity_protection_init(void)
/* Probe L2 ECC support */
gcr_ectl = read_gcr_err_control();
- if (!(gcr_ectl & CM_GCR_ERR_CONTROL_L2_ECC_SUPPORT_MSK) ||
+ if (!(gcr_ectl & CM_GCR_ERR_CONTROL_L2_ECC_SUPPORT) ||
!(cp0_ectl & ERRCTL_PE)) {
/*
* One of L1 or L2 ECC checking isn't supported,
@@ -1693,12 +1691,12 @@ static inline void parity_protection_init(void)
/* Configure L2 ECC checking */
if (l2parity)
- gcr_ectl |= CM_GCR_ERR_CONTROL_L2_ECC_EN_MSK;
+ gcr_ectl |= CM_GCR_ERR_CONTROL_L2_ECC_EN;
else
- gcr_ectl &= ~CM_GCR_ERR_CONTROL_L2_ECC_EN_MSK;
+ gcr_ectl &= ~CM_GCR_ERR_CONTROL_L2_ECC_EN;
write_gcr_err_control(gcr_ectl);
gcr_ectl = read_gcr_err_control();
- gcr_ectl &= CM_GCR_ERR_CONTROL_L2_ECC_EN_MSK;
+ gcr_ectl &= CM_GCR_ERR_CONTROL_L2_ECC_EN;
WARN_ON(!!gcr_ectl != l2parity);
pr_info("Cache parity protection %sabled\n",
@@ -2428,21 +2426,6 @@ void __init trap_init(void)
set_except_vector(EXCCODE_TR, handle_tr);
set_except_vector(EXCCODE_MSAFPE, handle_msa_fpe);
- if (current_cpu_type() == CPU_R6000 ||
- current_cpu_type() == CPU_R6000A) {
- /*
- * The R6000 is the only R-series CPU that features a machine
- * check exception (similar to the R4000 cache error) and
- * unaligned ldc1/sdc1 exception. The handlers have not been
- * written yet. Well, anyway there is no R6000 machine on the
- * current list of targets for Linux/MIPS.
- * (Duh, crap, there is someone with a triple R6k machine)
- */
- //set_except_vector(14, handle_mc);
- //set_except_vector(15, handle_ndc);
- }
-
-
if (board_nmi_handler_setup)
board_nmi_handler_setup();
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 5eaf2578ac04..2d0b912f9e3e 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -1378,7 +1378,7 @@ sigill:
const int reg16to32[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
/* Recode table from 16-bit STORE register notation to 32-bit GPR. */
-const int reg16to32st[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
+static const int reg16to32st[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
static void emulate_load_store_microMIPS(struct pt_regs *regs,
void __user *addr)
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
index 093517e85a6c..019035d7225c 100644
--- a/arch/mips/kernel/vdso.c
+++ b/arch/mips/kernel/vdso.c
@@ -13,13 +13,13 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/ioport.h>
-#include <linux/irqchip/mips-gic.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/timekeeper_internal.h>
#include <asm/abi.h>
+#include <asm/mips-cps.h>
#include <asm/vdso.h>
/* Kernel-provided data used by the VDSO. */
@@ -99,9 +99,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
{
struct mips_vdso_image *image = current->thread.abi->vdso;
struct mm_struct *mm = current->mm;
- unsigned long gic_size, vvar_size, size, base, data_addr, vdso_addr;
+ unsigned long gic_size, vvar_size, size, base, data_addr, vdso_addr, gic_pfn;
struct vm_area_struct *vma;
- struct resource gic_res;
int ret;
if (down_write_killable(&mm->mmap_sem))
@@ -125,7 +124,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
* only map a page even though the total area is 64K, as we only need
* the counter registers at the start.
*/
- gic_size = gic_present ? PAGE_SIZE : 0;
+ gic_size = mips_gic_present() ? PAGE_SIZE : 0;
vvar_size = gic_size + PAGE_SIZE;
size = vvar_size + image->size;
@@ -148,13 +147,9 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
/* Map GIC user page. */
if (gic_size) {
- ret = gic_get_usm_range(&gic_res);
- if (ret)
- goto out;
+ gic_pfn = virt_to_phys(mips_gic_base + MIPS_GIC_USER_OFS) >> PAGE_SHIFT;
- ret = io_remap_pfn_range(vma, base,
- gic_res.start >> PAGE_SHIFT,
- gic_size,
+ ret = io_remap_pfn_range(vma, base, gic_pfn, gic_size,
pgprot_noncached(PAGE_READONLY));
if (ret)
goto out;