2005-04-17 00:20:36 +02:00
|
|
|
/*
|
|
|
|
* Processor capabilities determination functions.
|
|
|
|
*
|
|
|
|
* Copyright (C) xxxx the Anonymous
|
2006-01-29 19:42:08 +01:00
|
|
|
* Copyright (C) 1994 - 2006 Ralf Baechle
|
2005-05-05 18:45:59 +02:00
|
|
|
* Copyright (C) 2003, 2004 Maciej W. Rozycki
|
2013-01-22 12:59:30 +01:00
|
|
|
* Copyright (C) 2001, 2004, 2011, 2012 MIPS Technologies, Inc.
|
2005-04-17 00:20:36 +02:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version
|
|
|
|
* 2 of the License, or (at your option) any later version.
|
|
|
|
*/
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/ptrace.h>
|
2009-06-19 15:05:26 +02:00
|
|
|
#include <linux/smp.h>
|
2005-04-17 00:20:36 +02:00
|
|
|
#include <linux/stddef.h>
|
2011-07-23 22:30:40 +02:00
|
|
|
#include <linux/export.h>
|
2005-04-17 00:20:36 +02:00
|
|
|
|
2007-02-18 20:07:31 +01:00
|
|
|
#include <asm/bugs.h>
|
2005-04-17 00:20:36 +02:00
|
|
|
#include <asm/cpu.h>
|
2015-04-04 00:27:26 +02:00
|
|
|
#include <asm/cpu-features.h>
|
2013-09-17 10:25:47 +02:00
|
|
|
#include <asm/cpu-type.h>
|
2005-04-17 00:20:36 +02:00
|
|
|
#include <asm/fpu.h>
|
|
|
|
#include <asm/mipsregs.h>
|
2014-03-27 11:57:30 +01:00
|
|
|
#include <asm/mipsmtregs.h>
|
2014-01-27 16:23:10 +01:00
|
|
|
#include <asm/msa.h>
|
2008-09-23 09:07:16 +02:00
|
|
|
#include <asm/watch.h>
|
2011-07-23 22:26:41 +02:00
|
|
|
#include <asm/elf.h>
|
2014-07-18 11:51:32 +02:00
|
|
|
#include <asm/pgtable-bits.h>
|
2009-07-10 10:51:27 +02:00
|
|
|
#include <asm/spram.h>
|
2010-10-14 20:32:33 +02:00
|
|
|
#include <asm/uaccess.h>
|
|
|
|
|
2015-07-27 21:58:23 +02:00
|
|
|
/* Hardware capabilities */
|
|
|
|
unsigned int elf_hwcap __read_mostly;
|
|
|
|
|
2015-04-04 00:27:54 +02:00
|
|
|
/*
|
|
|
|
* Get the FPU Implementation/Revision.
|
|
|
|
*/
|
|
|
|
static inline unsigned long cpu_get_fpu_id(void)
|
|
|
|
{
|
|
|
|
unsigned long tmp, fpu_id;
|
|
|
|
|
|
|
|
tmp = read_c0_status();
|
|
|
|
__enable_fpu(FPU_AS_IS);
|
|
|
|
fpu_id = read_32bit_cp1_register(CP1_REVISION);
|
|
|
|
write_c0_status(tmp);
|
|
|
|
return fpu_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if the CPU has an external FPU.
|
|
|
|
*/
|
|
|
|
static inline int __cpu_has_fpu(void)
|
|
|
|
{
|
|
|
|
return (cpu_get_fpu_id() & FPIR_IMP_MASK) != FPIR_IMP_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned long cpu_get_msa_id(void)
|
|
|
|
{
|
|
|
|
unsigned long status, msa_id;
|
|
|
|
|
|
|
|
status = read_c0_status();
|
|
|
|
__enable_fpu(FPU_64BIT);
|
|
|
|
enable_msa();
|
|
|
|
msa_id = read_msa_ir();
|
|
|
|
disable_msa();
|
|
|
|
write_c0_status(status);
|
|
|
|
return msa_id;
|
|
|
|
}
|
|
|
|
|
2015-04-04 00:27:48 +02:00
|
|
|
/*
|
|
|
|
* Determine the FCSR mask for FPU hardware.
|
|
|
|
*/
|
|
|
|
static inline void cpu_set_fpu_fcsr_mask(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
unsigned long sr, mask, fcsr, fcsr0, fcsr1;
|
|
|
|
|
2015-06-02 18:50:59 +02:00
|
|
|
fcsr = c->fpu_csr31;
|
2015-04-04 00:27:48 +02:00
|
|
|
mask = FPU_CSR_ALL_X | FPU_CSR_ALL_E | FPU_CSR_ALL_S | FPU_CSR_RM;
|
|
|
|
|
|
|
|
sr = read_c0_status();
|
|
|
|
__enable_fpu(FPU_AS_IS);
|
|
|
|
|
|
|
|
fcsr0 = fcsr & mask;
|
|
|
|
write_32bit_cp1_register(CP1_STATUS, fcsr0);
|
|
|
|
fcsr0 = read_32bit_cp1_register(CP1_STATUS);
|
|
|
|
|
|
|
|
fcsr1 = fcsr | ~mask;
|
|
|
|
write_32bit_cp1_register(CP1_STATUS, fcsr1);
|
|
|
|
fcsr1 = read_32bit_cp1_register(CP1_STATUS);
|
|
|
|
|
|
|
|
write_32bit_cp1_register(CP1_STATUS, fcsr);
|
|
|
|
|
|
|
|
write_c0_status(sr);
|
|
|
|
|
|
|
|
c->fpu_msk31 = ~(fcsr0 ^ fcsr1) & ~mask;
|
|
|
|
}
|
|
|
|
|
2015-11-13 01:48:15 +01:00
|
|
|
/*
|
|
|
|
* Determine the IEEE 754 NaN encodings and ABS.fmt/NEG.fmt execution modes
|
|
|
|
* supported by FPU hardware.
|
|
|
|
*/
|
|
|
|
static void cpu_set_fpu_2008(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
|
|
|
|
MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
|
|
|
|
MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) {
|
|
|
|
unsigned long sr, fir, fcsr, fcsr0, fcsr1;
|
|
|
|
|
|
|
|
sr = read_c0_status();
|
|
|
|
__enable_fpu(FPU_AS_IS);
|
|
|
|
|
|
|
|
fir = read_32bit_cp1_register(CP1_REVISION);
|
|
|
|
if (fir & MIPS_FPIR_HAS2008) {
|
|
|
|
fcsr = read_32bit_cp1_register(CP1_STATUS);
|
|
|
|
|
|
|
|
fcsr0 = fcsr & ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008);
|
|
|
|
write_32bit_cp1_register(CP1_STATUS, fcsr0);
|
|
|
|
fcsr0 = read_32bit_cp1_register(CP1_STATUS);
|
|
|
|
|
|
|
|
fcsr1 = fcsr | FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
|
|
|
|
write_32bit_cp1_register(CP1_STATUS, fcsr1);
|
|
|
|
fcsr1 = read_32bit_cp1_register(CP1_STATUS);
|
|
|
|
|
|
|
|
write_32bit_cp1_register(CP1_STATUS, fcsr);
|
|
|
|
|
|
|
|
if (!(fcsr0 & FPU_CSR_NAN2008))
|
|
|
|
c->options |= MIPS_CPU_NAN_LEGACY;
|
|
|
|
if (fcsr1 & FPU_CSR_NAN2008)
|
|
|
|
c->options |= MIPS_CPU_NAN_2008;
|
|
|
|
|
|
|
|
if ((fcsr0 ^ fcsr1) & FPU_CSR_ABS2008)
|
|
|
|
c->fpu_msk31 &= ~FPU_CSR_ABS2008;
|
|
|
|
else
|
|
|
|
c->fpu_csr31 |= fcsr & FPU_CSR_ABS2008;
|
|
|
|
|
|
|
|
if ((fcsr0 ^ fcsr1) & FPU_CSR_NAN2008)
|
|
|
|
c->fpu_msk31 &= ~FPU_CSR_NAN2008;
|
|
|
|
else
|
|
|
|
c->fpu_csr31 |= fcsr & FPU_CSR_NAN2008;
|
|
|
|
} else {
|
|
|
|
c->options |= MIPS_CPU_NAN_LEGACY;
|
|
|
|
}
|
|
|
|
|
|
|
|
write_c0_status(sr);
|
|
|
|
} else {
|
|
|
|
c->options |= MIPS_CPU_NAN_LEGACY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2015-11-13 01:48:29 +01:00
|
|
|
* IEEE 754 conformance mode to use. Affects the NaN encoding and the
|
|
|
|
* ABS.fmt/NEG.fmt execution mode.
|
|
|
|
*/
|
|
|
|
static enum { STRICT, LEGACY, STD2008, RELAXED } ieee754 = STRICT;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the IEEE 754 NaN encodings and the ABS.fmt/NEG.fmt execution modes
|
|
|
|
* to support by the FPU emulator according to the IEEE 754 conformance
|
|
|
|
* mode selected. Note that "relaxed" straps the emulator so that it
|
|
|
|
* allows 2008-NaN binaries even for legacy processors.
|
2015-11-13 01:48:15 +01:00
|
|
|
*/
|
|
|
|
static void cpu_set_nofpu_2008(struct cpuinfo_mips *c)
|
|
|
|
{
|
2015-11-13 01:48:29 +01:00
|
|
|
c->options &= ~(MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY);
|
2015-11-13 01:48:15 +01:00
|
|
|
c->fpu_csr31 &= ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008);
|
2015-11-13 01:48:29 +01:00
|
|
|
c->fpu_msk31 &= ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008);
|
|
|
|
|
|
|
|
switch (ieee754) {
|
|
|
|
case STRICT:
|
|
|
|
if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
|
|
|
|
MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
|
|
|
|
MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) {
|
|
|
|
c->options |= MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY;
|
|
|
|
} else {
|
|
|
|
c->options |= MIPS_CPU_NAN_LEGACY;
|
|
|
|
c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LEGACY:
|
2015-11-13 01:48:15 +01:00
|
|
|
c->options |= MIPS_CPU_NAN_LEGACY;
|
|
|
|
c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
|
2015-11-13 01:48:29 +01:00
|
|
|
break;
|
|
|
|
case STD2008:
|
|
|
|
c->options |= MIPS_CPU_NAN_2008;
|
|
|
|
c->fpu_csr31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
|
|
|
|
c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
|
|
|
|
break;
|
|
|
|
case RELAXED:
|
|
|
|
c->options |= MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY;
|
|
|
|
break;
|
2015-11-13 01:48:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-13 01:48:29 +01:00
|
|
|
/*
|
|
|
|
* Override the IEEE 754 NaN encoding and ABS.fmt/NEG.fmt execution mode
|
|
|
|
* according to the "ieee754=" parameter.
|
|
|
|
*/
|
|
|
|
static void cpu_set_nan_2008(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
switch (ieee754) {
|
|
|
|
case STRICT:
|
|
|
|
mips_use_nan_legacy = !!cpu_has_nan_legacy;
|
|
|
|
mips_use_nan_2008 = !!cpu_has_nan_2008;
|
|
|
|
break;
|
|
|
|
case LEGACY:
|
|
|
|
mips_use_nan_legacy = !!cpu_has_nan_legacy;
|
|
|
|
mips_use_nan_2008 = !cpu_has_nan_legacy;
|
|
|
|
break;
|
|
|
|
case STD2008:
|
|
|
|
mips_use_nan_legacy = !cpu_has_nan_2008;
|
|
|
|
mips_use_nan_2008 = !!cpu_has_nan_2008;
|
|
|
|
break;
|
|
|
|
case RELAXED:
|
|
|
|
mips_use_nan_legacy = true;
|
|
|
|
mips_use_nan_2008 = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* IEEE 754 NaN encoding and ABS.fmt/NEG.fmt execution mode override
|
|
|
|
* settings:
|
|
|
|
*
|
|
|
|
* strict: accept binaries that request a NaN encoding supported by the FPU
|
|
|
|
* legacy: only accept legacy-NaN binaries
|
|
|
|
* 2008: only accept 2008-NaN binaries
|
|
|
|
* relaxed: accept any binaries regardless of whether supported by the FPU
|
|
|
|
*/
|
|
|
|
static int __init ieee754_setup(char *s)
|
|
|
|
{
|
|
|
|
if (!s)
|
|
|
|
return -1;
|
|
|
|
else if (!strcmp(s, "strict"))
|
|
|
|
ieee754 = STRICT;
|
|
|
|
else if (!strcmp(s, "legacy"))
|
|
|
|
ieee754 = LEGACY;
|
|
|
|
else if (!strcmp(s, "2008"))
|
|
|
|
ieee754 = STD2008;
|
|
|
|
else if (!strcmp(s, "relaxed"))
|
|
|
|
ieee754 = RELAXED;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!(boot_cpu_data.options & MIPS_CPU_FPU))
|
|
|
|
cpu_set_nofpu_2008(&boot_cpu_data);
|
|
|
|
cpu_set_nan_2008(&boot_cpu_data);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
early_param("ieee754", ieee754_setup);
|
|
|
|
|
2015-04-04 00:27:26 +02:00
|
|
|
/*
|
|
|
|
* Set the FIR feature flags for the FPU emulator.
|
|
|
|
*/
|
|
|
|
static void cpu_set_nofpu_id(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
u32 value;
|
|
|
|
|
|
|
|
value = 0;
|
|
|
|
if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
|
|
|
|
MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
|
|
|
|
MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6))
|
|
|
|
value |= MIPS_FPIR_D | MIPS_FPIR_S;
|
|
|
|
if (c->isa_level & (MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
|
|
|
|
MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6))
|
|
|
|
value |= MIPS_FPIR_F64 | MIPS_FPIR_L | MIPS_FPIR_W;
|
2015-11-13 01:47:28 +01:00
|
|
|
if (c->options & MIPS_CPU_NAN_2008)
|
|
|
|
value |= MIPS_FPIR_HAS2008;
|
2015-04-04 00:27:26 +02:00
|
|
|
c->fpu_id = value;
|
|
|
|
}
|
|
|
|
|
2015-04-04 00:27:48 +02:00
|
|
|
/* Determined FPU emulator mask to use for the boot CPU with "nofpu". */
|
|
|
|
static unsigned int mips_nofpu_msk31;
|
|
|
|
|
2015-04-04 00:27:54 +02:00
|
|
|
/*
|
|
|
|
* Set options for FPU hardware.
|
|
|
|
*/
|
|
|
|
static void cpu_set_fpu_opts(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
c->fpu_id = cpu_get_fpu_id();
|
|
|
|
mips_nofpu_msk31 = c->fpu_msk31;
|
|
|
|
|
|
|
|
if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
|
|
|
|
MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
|
|
|
|
MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) {
|
|
|
|
if (c->fpu_id & MIPS_FPIR_3D)
|
|
|
|
c->ases |= MIPS_ASE_MIPS3D;
|
|
|
|
if (c->fpu_id & MIPS_FPIR_FREP)
|
|
|
|
c->options |= MIPS_CPU_FRE;
|
|
|
|
}
|
|
|
|
|
|
|
|
cpu_set_fpu_fcsr_mask(c);
|
2015-11-13 01:48:15 +01:00
|
|
|
cpu_set_fpu_2008(c);
|
2015-11-13 01:48:29 +01:00
|
|
|
cpu_set_nan_2008(c);
|
2015-04-04 00:27:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set options for the FPU emulator.
|
|
|
|
*/
|
|
|
|
static void cpu_set_nofpu_opts(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
c->options &= ~MIPS_CPU_FPU;
|
|
|
|
c->fpu_msk31 = mips_nofpu_msk31;
|
|
|
|
|
2015-11-13 01:48:15 +01:00
|
|
|
cpu_set_nofpu_2008(c);
|
2015-11-13 01:48:29 +01:00
|
|
|
cpu_set_nan_2008(c);
|
2015-04-04 00:27:54 +02:00
|
|
|
cpu_set_nofpu_id(c);
|
|
|
|
}
|
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 15:38:59 +02:00
|
|
|
static int mips_fpu_disabled;
|
2010-05-02 23:43:52 +02:00
|
|
|
|
|
|
|
static int __init fpu_disable(char *s)
|
|
|
|
{
|
2015-04-04 00:27:54 +02:00
|
|
|
cpu_set_nofpu_opts(&boot_cpu_data);
|
2010-05-02 23:43:52 +02:00
|
|
|
mips_fpu_disabled = 1;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
__setup("nofpu", fpu_disable);
|
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 15:38:59 +02:00
|
|
|
int mips_dsp_disabled;
|
2010-05-02 23:43:52 +02:00
|
|
|
|
|
|
|
static int __init dsp_disable(char *s)
|
|
|
|
{
|
2012-08-03 17:26:04 +02:00
|
|
|
cpu_data[0].ases &= ~(MIPS_ASE_DSP | MIPS_ASE_DSP2P);
|
2010-05-02 23:43:52 +02:00
|
|
|
mips_dsp_disabled = 1;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
__setup("nodsp", dsp_disable);
|
|
|
|
|
2014-07-14 13:46:13 +02:00
|
|
|
static int mips_htw_disabled;
|
|
|
|
|
|
|
|
static int __init htw_disable(char *s)
|
|
|
|
{
|
|
|
|
mips_htw_disabled = 1;
|
|
|
|
cpu_data[0].options &= ~MIPS_CPU_HTW;
|
|
|
|
write_c0_pwctl(read_c0_pwctl() &
|
|
|
|
~(1 << MIPS_PWCTL_PWEN_SHIFT));
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
__setup("nohtw", htw_disable);
|
|
|
|
|
2014-08-29 10:37:26 +02:00
|
|
|
static int mips_ftlb_disabled;
|
|
|
|
static int mips_has_ftlb_configured;
|
|
|
|
|
2016-08-19 19:18:27 +02:00
|
|
|
enum ftlb_flags {
|
|
|
|
FTLB_EN = 1 << 0,
|
|
|
|
FTLB_SET_PROB = 1 << 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int set_ftlb_enable(struct cpuinfo_mips *c, enum ftlb_flags flags);
|
2014-08-29 10:37:26 +02:00
|
|
|
|
|
|
|
static int __init ftlb_disable(char *s)
|
|
|
|
{
|
|
|
|
unsigned int config4, mmuextdef;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the core hasn't done any FTLB configuration, there is nothing
|
|
|
|
* for us to do here.
|
|
|
|
*/
|
|
|
|
if (!mips_has_ftlb_configured)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* Disable it in the boot cpu */
|
2015-07-09 11:40:51 +02:00
|
|
|
if (set_ftlb_enable(&cpu_data[0], 0)) {
|
|
|
|
pr_warn("Can't turn FTLB off\n");
|
|
|
|
return 1;
|
|
|
|
}
|
2014-08-29 10:37:26 +02:00
|
|
|
|
|
|
|
config4 = read_c0_config4();
|
|
|
|
|
|
|
|
/* Check that FTLB has been disabled */
|
|
|
|
mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
|
|
|
|
/* MMUSIZEEXT == VTLB ON, FTLB OFF */
|
|
|
|
if (mmuextdef == MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT) {
|
|
|
|
/* This should never happen */
|
|
|
|
pr_warn("FTLB could not be disabled!\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
mips_ftlb_disabled = 1;
|
|
|
|
mips_has_ftlb_configured = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* noftlb is mainly used for debug purposes so print
|
|
|
|
* an informative message instead of using pr_debug()
|
|
|
|
*/
|
|
|
|
pr_info("FTLB has been disabled\n");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Some of these bits are duplicated in the decode_config4.
|
|
|
|
* MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT is the only possible case
|
|
|
|
* once FTLB has been disabled so undo what decode_config4 did.
|
|
|
|
*/
|
|
|
|
cpu_data[0].tlbsize -= cpu_data[0].tlbsizeftlbways *
|
|
|
|
cpu_data[0].tlbsizeftlbsets;
|
|
|
|
cpu_data[0].tlbsizeftlbsets = 0;
|
|
|
|
cpu_data[0].tlbsizeftlbways = 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
__setup("noftlb", ftlb_disable);
|
|
|
|
|
|
|
|
|
2007-06-14 23:55:31 +02:00
|
|
|
static inline void check_errata(void)
|
|
|
|
{
|
|
|
|
struct cpuinfo_mips *c = ¤t_cpu_data;
|
|
|
|
|
2013-09-17 10:25:47 +02:00
|
|
|
switch (current_cpu_type()) {
|
2007-06-14 23:55:31 +02:00
|
|
|
case CPU_34K:
|
|
|
|
/*
|
|
|
|
* Erratum "RPS May Cause Incorrect Instruction Execution"
|
2014-05-23 16:29:44 +02:00
|
|
|
* This code only handles VPE0, any SMP/RTOS code
|
2007-06-14 23:55:31 +02:00
|
|
|
* making use of VPE1 will be responsable for that VPE.
|
|
|
|
*/
|
|
|
|
if ((c->processor_id & PRID_REV_MASK) <= PRID_REV_34K_V1_0_2)
|
|
|
|
write_c0_config7(read_c0_config7() | MIPS_CONF7_RPS);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-17 00:20:36 +02:00
|
|
|
void __init check_bugs32(void)
|
|
|
|
{
|
2007-06-14 23:55:31 +02:00
|
|
|
check_errata();
|
2005-04-17 00:20:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Probe whether cpu has config register by trying to play with
|
|
|
|
* alternate cache bit and see whether it matters.
|
|
|
|
* It's used by cpu_probe to distinguish between R3000A and R3081.
|
|
|
|
*/
|
|
|
|
static inline int cpu_has_confreg(void)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_CPU_R3000
|
|
|
|
extern unsigned long r3k_cache_size(unsigned long);
|
|
|
|
unsigned long size1, size2;
|
|
|
|
unsigned long cfg = read_c0_conf();
|
|
|
|
|
|
|
|
size1 = r3k_cache_size(ST0_ISC);
|
|
|
|
write_c0_conf(cfg ^ R30XX_CONF_AC);
|
|
|
|
size2 = r3k_cache_size(ST0_ISC);
|
|
|
|
write_c0_conf(cfg);
|
|
|
|
return size1 != size2;
|
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2011-04-18 20:37:55 +02:00
|
|
|
static inline void set_elf_platform(int cpu, const char *plat)
|
|
|
|
{
|
|
|
|
if (cpu == 0)
|
|
|
|
__elf_platform = plat;
|
|
|
|
}
|
|
|
|
|
2010-02-02 17:52:20 +01:00
|
|
|
static inline void cpu_probe_vmbits(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
#ifdef __NEED_VMBITS_PROBE
|
2010-02-08 21:27:00 +01:00
|
|
|
write_c0_entryhi(0x3fffffffffffe000ULL);
|
2010-02-02 17:52:20 +01:00
|
|
|
back_to_back_c0_hazard();
|
2010-02-08 21:27:00 +01:00
|
|
|
c->vmbits = fls64(read_c0_entryhi() & 0x3fffffffffffe000ULL);
|
2010-02-02 17:52:20 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 15:38:59 +02:00
|
|
|
static void set_isa(struct cpuinfo_mips *c, unsigned int isa)
|
2012-12-07 05:31:36 +01:00
|
|
|
{
|
|
|
|
switch (isa) {
|
|
|
|
case MIPS_CPU_ISA_M64R2:
|
|
|
|
c->isa_level |= MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2;
|
|
|
|
case MIPS_CPU_ISA_M64R1:
|
|
|
|
c->isa_level |= MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1;
|
|
|
|
case MIPS_CPU_ISA_V:
|
|
|
|
c->isa_level |= MIPS_CPU_ISA_V;
|
|
|
|
case MIPS_CPU_ISA_IV:
|
|
|
|
c->isa_level |= MIPS_CPU_ISA_IV;
|
|
|
|
case MIPS_CPU_ISA_III:
|
2013-06-26 17:06:34 +02:00
|
|
|
c->isa_level |= MIPS_CPU_ISA_II | MIPS_CPU_ISA_III;
|
2012-12-07 05:31:36 +01:00
|
|
|
break;
|
|
|
|
|
2014-11-13 14:51:51 +01:00
|
|
|
/* R6 incompatible with everything else */
|
|
|
|
case MIPS_CPU_ISA_M64R6:
|
|
|
|
c->isa_level |= MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6;
|
|
|
|
case MIPS_CPU_ISA_M32R6:
|
|
|
|
c->isa_level |= MIPS_CPU_ISA_M32R6;
|
|
|
|
/* Break here so we don't add incompatible ISAs */
|
|
|
|
break;
|
2012-12-07 05:31:36 +01:00
|
|
|
case MIPS_CPU_ISA_M32R2:
|
|
|
|
c->isa_level |= MIPS_CPU_ISA_M32R2;
|
|
|
|
case MIPS_CPU_ISA_M32R1:
|
|
|
|
c->isa_level |= MIPS_CPU_ISA_M32R1;
|
|
|
|
case MIPS_CPU_ISA_II:
|
|
|
|
c->isa_level |= MIPS_CPU_ISA_II;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 15:38:59 +02:00
|
|
|
static char unknown_isa[] = KERN_ERR \
|
2012-06-20 21:05:32 +02:00
|
|
|
"Unsupported ISA type, c0.config0: %d.";
|
|
|
|
|
2014-11-10 13:25:34 +01:00
|
|
|
static unsigned int calculate_ftlb_probability(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
|
|
|
|
unsigned int probability = c->tlbsize / c->tlbsizevtlb;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 0 = All TLBWR instructions go to FTLB
|
|
|
|
* 1 = 15:1: For every 16 TBLWR instructions, 15 go to the
|
|
|
|
* FTLB and 1 goes to the VTLB.
|
|
|
|
* 2 = 7:1: As above with 7:1 ratio.
|
|
|
|
* 3 = 3:1: As above with 3:1 ratio.
|
|
|
|
*
|
|
|
|
* Use the linear midpoint as the probability threshold.
|
|
|
|
*/
|
|
|
|
if (probability >= 12)
|
|
|
|
return 1;
|
|
|
|
else if (probability >= 6)
|
|
|
|
return 2;
|
|
|
|
else
|
|
|
|
/*
|
|
|
|
* So FTLB is less than 4 times bigger than VTLB.
|
|
|
|
* A 3:1 ratio can still be useful though.
|
|
|
|
*/
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
|
2016-08-19 19:18:27 +02:00
|
|
|
static int set_ftlb_enable(struct cpuinfo_mips *c, enum ftlb_flags flags)
|
2013-11-14 17:12:31 +01:00
|
|
|
{
|
2015-07-09 11:40:53 +02:00
|
|
|
unsigned int config;
|
2014-01-22 17:19:40 +01:00
|
|
|
|
|
|
|
/* It's implementation dependent how the FTLB can be enabled */
|
|
|
|
switch (c->cputype) {
|
|
|
|
case CPU_PROAPTIV:
|
|
|
|
case CPU_P5600:
|
2016-02-03 04:26:38 +01:00
|
|
|
case CPU_P6600:
|
2014-01-22 17:19:40 +01:00
|
|
|
/* proAptiv & related cores use Config6 to enable the FTLB */
|
2015-07-09 11:40:53 +02:00
|
|
|
config = read_c0_config6();
|
2016-08-19 19:18:27 +02:00
|
|
|
|
|
|
|
if (flags & FTLB_EN)
|
|
|
|
config |= MIPS_CONF6_FTLBEN;
|
2013-11-14 17:12:31 +01:00
|
|
|
else
|
2016-08-19 19:18:27 +02:00
|
|
|
config &= ~MIPS_CONF6_FTLBEN;
|
|
|
|
|
|
|
|
if (flags & FTLB_SET_PROB) {
|
|
|
|
config &= ~(3 << MIPS_CONF6_FTLBP_SHIFT);
|
|
|
|
config |= calculate_ftlb_probability(c)
|
|
|
|
<< MIPS_CONF6_FTLBP_SHIFT;
|
|
|
|
}
|
|
|
|
|
|
|
|
write_c0_config6(config);
|
2016-08-19 19:18:28 +02:00
|
|
|
back_to_back_c0_hazard();
|
2015-07-09 11:40:53 +02:00
|
|
|
break;
|
|
|
|
case CPU_I6400:
|
2016-08-19 19:18:26 +02:00
|
|
|
/* There's no way to disable the FTLB */
|
2016-08-19 19:18:27 +02:00
|
|
|
if (!(flags & FTLB_EN))
|
|
|
|
return 1;
|
|
|
|
return 0;
|
2016-03-03 02:45:09 +01:00
|
|
|
case CPU_LOONGSON3:
|
2016-03-03 02:45:11 +01:00
|
|
|
/* Flush ITLB, DTLB, VTLB and FTLB */
|
|
|
|
write_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB |
|
|
|
|
LOONGSON_DIAG_VTLB | LOONGSON_DIAG_FTLB);
|
2016-03-03 02:45:09 +01:00
|
|
|
/* Loongson-3 cores use Config6 to enable the FTLB */
|
|
|
|
config = read_c0_config6();
|
2016-08-19 19:18:27 +02:00
|
|
|
if (flags & FTLB_EN)
|
2016-03-03 02:45:09 +01:00
|
|
|
/* Enable FTLB */
|
|
|
|
write_c0_config6(config & ~MIPS_CONF6_FTLBDIS);
|
|
|
|
else
|
|
|
|
/* Disable FTLB */
|
|
|
|
write_c0_config6(config | MIPS_CONF6_FTLBDIS);
|
|
|
|
break;
|
2015-07-09 11:40:51 +02:00
|
|
|
default:
|
|
|
|
return 1;
|
2013-11-14 17:12:31 +01:00
|
|
|
}
|
2015-07-09 11:40:51 +02:00
|
|
|
|
|
|
|
return 0;
|
2013-11-14 17:12:31 +01:00
|
|
|
}
|
|
|
|
|
2012-06-20 21:05:32 +02:00
|
|
|
static inline unsigned int decode_config0(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
unsigned int config0;
|
2015-09-17 18:49:20 +02:00
|
|
|
int isa, mt;
|
2012-06-20 21:05:32 +02:00
|
|
|
|
|
|
|
config0 = read_c0_config();
|
|
|
|
|
2013-11-14 17:12:31 +01:00
|
|
|
/*
|
|
|
|
* Look for Standard TLB or Dual VTLB and FTLB
|
|
|
|
*/
|
2015-09-17 18:49:20 +02:00
|
|
|
mt = config0 & MIPS_CONF_MT;
|
|
|
|
if (mt == MIPS_CONF_MT_TLB)
|
2012-06-20 21:05:32 +02:00
|
|
|
c->options |= MIPS_CPU_TLB;
|
2015-09-17 18:49:20 +02:00
|
|
|
else if (mt == MIPS_CONF_MT_FTLB)
|
|
|
|
c->options |= MIPS_CPU_TLB | MIPS_CPU_FTLB;
|
2013-11-14 17:12:31 +01:00
|
|
|
|
2012-06-20 21:05:32 +02:00
|
|
|
isa = (config0 & MIPS_CONF_AT) >> 13;
|
|
|
|
switch (isa) {
|
|
|
|
case 0:
|
|
|
|
switch ((config0 & MIPS_CONF_AR) >> 10) {
|
|
|
|
case 0:
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_M32R1);
|
2012-06-20 21:05:32 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_M32R2);
|
2012-06-20 21:05:32 +02:00
|
|
|
break;
|
2014-11-13 14:51:51 +01:00
|
|
|
case 2:
|
|
|
|
set_isa(c, MIPS_CPU_ISA_M32R6);
|
|
|
|
break;
|
2012-06-20 21:05:32 +02:00
|
|
|
default:
|
|
|
|
goto unknown;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
switch ((config0 & MIPS_CONF_AR) >> 10) {
|
|
|
|
case 0:
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_M64R1);
|
2012-06-20 21:05:32 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_M64R2);
|
2012-06-20 21:05:32 +02:00
|
|
|
break;
|
2014-11-13 14:51:51 +01:00
|
|
|
case 2:
|
|
|
|
set_isa(c, MIPS_CPU_ISA_M64R6);
|
|
|
|
break;
|
2012-06-20 21:05:32 +02:00
|
|
|
default:
|
|
|
|
goto unknown;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto unknown;
|
|
|
|
}
|
|
|
|
|
|
|
|
return config0 & MIPS_CONF_M;
|
|
|
|
|
|
|
|
unknown:
|
|
|
|
panic(unknown_isa, config0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned int decode_config1(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
unsigned int config1;
|
|
|
|
|
|
|
|
config1 = read_c0_config1();
|
|
|
|
|
|
|
|
if (config1 & MIPS_CONF1_MD)
|
|
|
|
c->ases |= MIPS_ASE_MDMX;
|
2016-05-11 14:50:53 +02:00
|
|
|
if (config1 & MIPS_CONF1_PC)
|
|
|
|
c->options |= MIPS_CPU_PERF;
|
2012-06-20 21:05:32 +02:00
|
|
|
if (config1 & MIPS_CONF1_WR)
|
|
|
|
c->options |= MIPS_CPU_WATCH;
|
|
|
|
if (config1 & MIPS_CONF1_CA)
|
|
|
|
c->ases |= MIPS_ASE_MIPS16;
|
|
|
|
if (config1 & MIPS_CONF1_EP)
|
|
|
|
c->options |= MIPS_CPU_EJTAG;
|
|
|
|
if (config1 & MIPS_CONF1_FP) {
|
|
|
|
c->options |= MIPS_CPU_FPU;
|
|
|
|
c->options |= MIPS_CPU_32FPR;
|
|
|
|
}
|
2013-11-14 17:12:31 +01:00
|
|
|
if (cpu_has_tlb) {
|
2012-06-20 21:05:32 +02:00
|
|
|
c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1;
|
2013-11-14 17:12:31 +01:00
|
|
|
c->tlbsizevtlb = c->tlbsize;
|
|
|
|
c->tlbsizeftlbsets = 0;
|
|
|
|
}
|
2012-06-20 21:05:32 +02:00
|
|
|
|
|
|
|
return config1 & MIPS_CONF_M;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned int decode_config2(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
unsigned int config2;
|
|
|
|
|
|
|
|
config2 = read_c0_config2();
|
|
|
|
|
|
|
|
if (config2 & MIPS_CONF2_SL)
|
|
|
|
c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
|
|
|
|
|
|
|
|
return config2 & MIPS_CONF_M;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned int decode_config3(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
unsigned int config3;
|
|
|
|
|
|
|
|
config3 = read_c0_config3();
|
|
|
|
|
2012-09-13 23:47:58 +02:00
|
|
|
if (config3 & MIPS_CONF3_SM) {
|
2012-06-20 21:05:32 +02:00
|
|
|
c->ases |= MIPS_ASE_SMARTMIPS;
|
2016-05-11 14:50:52 +02:00
|
|
|
c->options |= MIPS_CPU_RIXI | MIPS_CPU_CTXTC;
|
2012-09-13 23:47:58 +02:00
|
|
|
}
|
|
|
|
if (config3 & MIPS_CONF3_RXI)
|
|
|
|
c->options |= MIPS_CPU_RIXI;
|
2016-05-11 14:50:52 +02:00
|
|
|
if (config3 & MIPS_CONF3_CTXTC)
|
|
|
|
c->options |= MIPS_CPU_CTXTC;
|
2012-06-20 21:05:32 +02:00
|
|
|
if (config3 & MIPS_CONF3_DSP)
|
|
|
|
c->ases |= MIPS_ASE_DSP;
|
2016-03-29 16:50:25 +02:00
|
|
|
if (config3 & MIPS_CONF3_DSP2P) {
|
2012-08-03 17:26:04 +02:00
|
|
|
c->ases |= MIPS_ASE_DSP2P;
|
2016-03-29 16:50:25 +02:00
|
|
|
if (cpu_has_mips_r6)
|
|
|
|
c->ases |= MIPS_ASE_DSP3;
|
|
|
|
}
|
2012-06-20 21:05:32 +02:00
|
|
|
if (config3 & MIPS_CONF3_VINT)
|
|
|
|
c->options |= MIPS_CPU_VINT;
|
|
|
|
if (config3 & MIPS_CONF3_VEIC)
|
|
|
|
c->options |= MIPS_CPU_VEIC;
|
2016-04-19 10:24:59 +02:00
|
|
|
if (config3 & MIPS_CONF3_LPA)
|
|
|
|
c->options |= MIPS_CPU_LPA;
|
2012-06-20 21:05:32 +02:00
|
|
|
if (config3 & MIPS_CONF3_MT)
|
|
|
|
c->ases |= MIPS_ASE_MIPSMT;
|
|
|
|
if (config3 & MIPS_CONF3_ULRI)
|
|
|
|
c->options |= MIPS_CPU_ULRI;
|
2012-12-07 04:51:35 +01:00
|
|
|
if (config3 & MIPS_CONF3_ISA)
|
|
|
|
c->options |= MIPS_CPU_MICROMIPS;
|
2013-02-16 23:42:43 +01:00
|
|
|
if (config3 & MIPS_CONF3_VZ)
|
|
|
|
c->ases |= MIPS_ASE_VZ;
|
2013-11-14 17:12:24 +01:00
|
|
|
if (config3 & MIPS_CONF3_SC)
|
|
|
|
c->options |= MIPS_CPU_SEGMENTS;
|
2016-05-11 14:50:51 +02:00
|
|
|
if (config3 & MIPS_CONF3_BI)
|
|
|
|
c->options |= MIPS_CPU_BADINSTR;
|
|
|
|
if (config3 & MIPS_CONF3_BP)
|
|
|
|
c->options |= MIPS_CPU_BADINSTRP;
|
2014-01-27 16:23:10 +01:00
|
|
|
if (config3 & MIPS_CONF3_MSA)
|
|
|
|
c->ases |= MIPS_ASE_MSA;
|
2015-09-22 21:03:37 +02:00
|
|
|
if (config3 & MIPS_CONF3_PW) {
|
2015-01-26 14:04:33 +01:00
|
|
|
c->htw_seq = 0;
|
2014-07-14 13:46:13 +02:00
|
|
|
c->options |= MIPS_CPU_HTW;
|
2015-01-26 14:04:33 +01:00
|
|
|
}
|
2015-02-02 12:45:08 +01:00
|
|
|
if (config3 & MIPS_CONF3_CDMM)
|
|
|
|
c->options |= MIPS_CPU_CDMM;
|
2015-07-15 17:17:44 +02:00
|
|
|
if (config3 & MIPS_CONF3_SP)
|
|
|
|
c->options |= MIPS_CPU_SP;
|
2012-06-20 21:05:32 +02:00
|
|
|
|
|
|
|
return config3 & MIPS_CONF_M;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned int decode_config4(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
unsigned int config4;
|
2013-11-14 17:12:31 +01:00
|
|
|
unsigned int newcf4;
|
|
|
|
unsigned int mmuextdef;
|
|
|
|
unsigned int ftlb_page = MIPS_CONF4_FTLBPAGESIZE;
|
2016-05-06 15:36:24 +02:00
|
|
|
unsigned long asid_mask;
|
2012-06-20 21:05:32 +02:00
|
|
|
|
|
|
|
config4 = read_c0_config4();
|
|
|
|
|
2013-11-14 17:12:23 +01:00
|
|
|
if (cpu_has_tlb) {
|
|
|
|
if (((config4 & MIPS_CONF4_IE) >> 29) == 2)
|
|
|
|
c->options |= MIPS_CPU_TLBINV;
|
2015-09-17 18:49:21 +02:00
|
|
|
|
2015-07-09 11:40:52 +02:00
|
|
|
/*
|
2015-09-17 18:49:21 +02:00
|
|
|
* R6 has dropped the MMUExtDef field from config4.
|
|
|
|
* On R6 the fields always describe the FTLB, and only if it is
|
|
|
|
* present according to Config.MT.
|
2015-07-09 11:40:52 +02:00
|
|
|
*/
|
2015-09-17 18:49:21 +02:00
|
|
|
if (!cpu_has_mips_r6)
|
|
|
|
mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
|
|
|
|
else if (cpu_has_ftlb)
|
2015-07-09 11:40:52 +02:00
|
|
|
mmuextdef = MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT;
|
|
|
|
else
|
2015-09-17 18:49:21 +02:00
|
|
|
mmuextdef = 0;
|
2015-07-09 11:40:52 +02:00
|
|
|
|
2013-11-14 17:12:31 +01:00
|
|
|
switch (mmuextdef) {
|
|
|
|
case MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT:
|
|
|
|
c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;
|
|
|
|
c->tlbsizevtlb = c->tlbsize;
|
|
|
|
break;
|
|
|
|
case MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT:
|
|
|
|
c->tlbsizevtlb +=
|
|
|
|
((config4 & MIPS_CONF4_VTLBSIZEEXT) >>
|
|
|
|
MIPS_CONF4_VTLBSIZEEXT_SHIFT) * 0x40;
|
|
|
|
c->tlbsize = c->tlbsizevtlb;
|
|
|
|
ftlb_page = MIPS_CONF4_VFTLBPAGESIZE;
|
|
|
|
/* fall through */
|
|
|
|
case MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT:
|
2014-08-29 10:37:26 +02:00
|
|
|
if (mips_ftlb_disabled)
|
|
|
|
break;
|
2013-11-14 17:12:31 +01:00
|
|
|
newcf4 = (config4 & ~ftlb_page) |
|
|
|
|
(page_size_ftlb(mmuextdef) <<
|
|
|
|
MIPS_CONF4_FTLBPAGESIZE_SHIFT);
|
|
|
|
write_c0_config4(newcf4);
|
|
|
|
back_to_back_c0_hazard();
|
|
|
|
config4 = read_c0_config4();
|
|
|
|
if (config4 != newcf4) {
|
|
|
|
pr_err("PAGE_SIZE 0x%lx is not supported by FTLB (config4=0x%x)\n",
|
|
|
|
PAGE_SIZE, config4);
|
|
|
|
/* Switch FTLB off */
|
|
|
|
set_ftlb_enable(c, 0);
|
2016-08-19 19:18:27 +02:00
|
|
|
mips_ftlb_disabled = 1;
|
2013-11-14 17:12:31 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
c->tlbsizeftlbsets = 1 <<
|
|
|
|
((config4 & MIPS_CONF4_FTLBSETS) >>
|
|
|
|
MIPS_CONF4_FTLBSETS_SHIFT);
|
|
|
|
c->tlbsizeftlbways = ((config4 & MIPS_CONF4_FTLBWAYS) >>
|
|
|
|
MIPS_CONF4_FTLBWAYS_SHIFT) + 2;
|
|
|
|
c->tlbsize += c->tlbsizeftlbways * c->tlbsizeftlbsets;
|
2014-08-29 10:37:26 +02:00
|
|
|
mips_has_ftlb_configured = 1;
|
2013-11-14 17:12:31 +01:00
|
|
|
break;
|
|
|
|
}
|
2013-11-14 17:12:23 +01:00
|
|
|
}
|
|
|
|
|
2016-05-11 16:50:27 +02:00
|
|
|
c->kscratch_mask = (config4 & MIPS_CONF4_KSCREXIST)
|
|
|
|
>> MIPS_CONF4_KSCREXIST_SHIFT;
|
2012-06-20 21:05:32 +02:00
|
|
|
|
2016-05-06 15:36:24 +02:00
|
|
|
asid_mask = MIPS_ENTRYHI_ASID;
|
|
|
|
if (config4 & MIPS_CONF4_AE)
|
|
|
|
asid_mask |= MIPS_ENTRYHI_ASIDX;
|
|
|
|
set_cpu_asid_mask(c, asid_mask);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Warn if the computed ASID mask doesn't match the mask the kernel
|
|
|
|
* is built for. This may indicate either a serious problem or an
|
|
|
|
* easy optimisation opportunity, but either way should be addressed.
|
|
|
|
*/
|
|
|
|
WARN_ON(asid_mask != cpu_asid_mask(c));
|
|
|
|
|
2012-06-20 21:05:32 +02:00
|
|
|
return config4 & MIPS_CONF_M;
|
|
|
|
}
|
|
|
|
|
2013-09-19 11:15:49 +02:00
|
|
|
static inline unsigned int decode_config5(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
unsigned int config5;
|
|
|
|
|
|
|
|
config5 = read_c0_config5();
|
2014-09-11 09:30:19 +02:00
|
|
|
config5 &= ~(MIPS_CONF5_UFR | MIPS_CONF5_UFE);
|
2013-09-19 11:15:49 +02:00
|
|
|
write_c0_config5(config5);
|
|
|
|
|
2014-01-09 17:04:51 +01:00
|
|
|
if (config5 & MIPS_CONF5_EVA)
|
|
|
|
c->options |= MIPS_CPU_EVA;
|
2014-07-14 11:32:14 +02:00
|
|
|
if (config5 & MIPS_CONF5_MRP)
|
|
|
|
c->options |= MIPS_CPU_MAAR;
|
2014-12-02 10:46:19 +01:00
|
|
|
if (config5 & MIPS_CONF5_LLB)
|
|
|
|
c->options |= MIPS_CPU_RW_LLB;
|
2015-02-27 01:16:38 +01:00
|
|
|
if (config5 & MIPS_CONF5_MVH)
|
2016-05-18 01:08:49 +02:00
|
|
|
c->options |= MIPS_CPU_MVH;
|
2016-02-03 04:15:21 +01:00
|
|
|
if (cpu_has_mips_r6 && (config5 & MIPS_CONF5_VP))
|
|
|
|
c->options |= MIPS_CPU_VP;
|
2014-01-09 17:04:51 +01:00
|
|
|
|
2013-09-19 11:15:49 +02:00
|
|
|
return config5 & MIPS_CONF_M;
|
|
|
|
}
|
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 15:38:59 +02:00
|
|
|
static void decode_configs(struct cpuinfo_mips *c)
|
2012-06-20 21:05:32 +02:00
|
|
|
{
|
|
|
|
int ok;
|
|
|
|
|
|
|
|
/* MIPS32 or MIPS64 compliant CPU. */
|
|
|
|
c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER |
|
|
|
|
MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK;
|
|
|
|
|
|
|
|
c->scache.flags = MIPS_CACHE_NOT_PRESENT;
|
|
|
|
|
2014-08-29 10:37:26 +02:00
|
|
|
/* Enable FTLB if present and not disabled */
|
2016-08-19 19:18:27 +02:00
|
|
|
set_ftlb_enable(c, mips_ftlb_disabled ? 0 : FTLB_EN);
|
2013-11-14 17:12:31 +01:00
|
|
|
|
2012-06-20 21:05:32 +02:00
|
|
|
ok = decode_config0(c); /* Read Config registers. */
|
2013-01-22 12:59:30 +01:00
|
|
|
BUG_ON(!ok); /* Arch spec violation! */
|
2012-06-20 21:05:32 +02:00
|
|
|
if (ok)
|
|
|
|
ok = decode_config1(c);
|
|
|
|
if (ok)
|
|
|
|
ok = decode_config2(c);
|
|
|
|
if (ok)
|
|
|
|
ok = decode_config3(c);
|
|
|
|
if (ok)
|
|
|
|
ok = decode_config4(c);
|
2013-09-19 11:15:49 +02:00
|
|
|
if (ok)
|
|
|
|
ok = decode_config5(c);
|
2012-06-20 21:05:32 +02:00
|
|
|
|
2016-05-11 14:50:50 +02:00
|
|
|
/* Probe the EBase.WG bit */
|
|
|
|
if (cpu_has_mips_r2_r6) {
|
|
|
|
u64 ebase;
|
|
|
|
unsigned int status;
|
|
|
|
|
|
|
|
/* {read,write}_c0_ebase_64() may be UNDEFINED prior to r6 */
|
|
|
|
ebase = cpu_has_mips64r6 ? read_c0_ebase_64()
|
|
|
|
: (s32)read_c0_ebase();
|
|
|
|
if (ebase & MIPS_EBASE_WG) {
|
|
|
|
/* WG bit already set, we can avoid the clumsy probe */
|
|
|
|
c->options |= MIPS_CPU_EBASE_WG;
|
|
|
|
} else {
|
|
|
|
/* Its UNDEFINED to change EBase while BEV=0 */
|
|
|
|
status = read_c0_status();
|
|
|
|
write_c0_status(status | ST0_BEV);
|
|
|
|
irq_enable_hazard();
|
|
|
|
/*
|
|
|
|
* On pre-r6 cores, this may well clobber the upper bits
|
|
|
|
* of EBase. This is hard to avoid without potentially
|
|
|
|
* hitting UNDEFINED dm*c0 behaviour if EBase is 32-bit.
|
|
|
|
*/
|
|
|
|
if (cpu_has_mips64r6)
|
|
|
|
write_c0_ebase_64(ebase | MIPS_EBASE_WG);
|
|
|
|
else
|
|
|
|
write_c0_ebase(ebase | MIPS_EBASE_WG);
|
|
|
|
back_to_back_c0_hazard();
|
|
|
|
/* Restore BEV */
|
|
|
|
write_c0_status(status);
|
|
|
|
if (read_c0_ebase() & MIPS_EBASE_WG) {
|
|
|
|
c->options |= MIPS_CPU_EBASE_WG;
|
|
|
|
write_c0_ebase(ebase);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-19 19:18:27 +02:00
|
|
|
/* configure the FTLB write probability */
|
|
|
|
set_ftlb_enable(c, (mips_ftlb_disabled ? 0 : FTLB_EN) | FTLB_SET_PROB);
|
|
|
|
|
2012-06-20 21:05:32 +02:00
|
|
|
mips_probe_watch_registers(c);
|
|
|
|
|
2014-01-15 11:31:53 +01:00
|
|
|
#ifndef CONFIG_MIPS_CPS
|
2014-11-13 14:51:51 +01:00
|
|
|
if (cpu_has_mips_r2_r6) {
|
2014-05-28 23:52:10 +02:00
|
|
|
c->core = get_ebase_cpunum();
|
2014-03-27 11:57:30 +01:00
|
|
|
if (cpu_has_mipsmt)
|
|
|
|
c->core >>= fls(core_nvpes()) - 1;
|
|
|
|
}
|
2014-01-15 11:31:53 +01:00
|
|
|
#endif
|
2012-06-20 21:05:32 +02:00
|
|
|
}
|
|
|
|
|
MIPS: Add probing & defs for VZ & guest features
Add a few new cpu-features.h definitions for VZ sub-features, namely the
existence of the CP0_GuestCtl0Ext, CP0_GuestCtl1, and CP0_GuestCtl2
registers, and support for GuestID to dialias TLB entries belonging to
different guests.
Also add certain features present in the guest, with the naming scheme
cpu_guest_has_*. These are added separately to the main options bitfield
since they generally parallel similar features in the root context. A
few of these (FPU, MSA, watchpoints, perf counters, CP0_[X]ContextConfig
registers, MAAR registers, and probably others in future) can be
dynamically configured in the guest context, for which the
cpu_guest_has_dyn_* macros are added.
[ralf@linux-mips.org: Resolve merge conflict.]
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/13231/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2016-05-11 16:50:30 +02:00
|
|
|
/*
|
|
|
|
* Probe for certain guest capabilities by writing config bits and reading back.
|
|
|
|
* Finally write back the original value.
|
|
|
|
*/
|
|
|
|
#define probe_gc0_config(name, maxconf, bits) \
|
|
|
|
do { \
|
|
|
|
unsigned int tmp; \
|
|
|
|
tmp = read_gc0_##name(); \
|
|
|
|
write_gc0_##name(tmp | (bits)); \
|
|
|
|
back_to_back_c0_hazard(); \
|
|
|
|
maxconf = read_gc0_##name(); \
|
|
|
|
write_gc0_##name(tmp); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Probe for dynamic guest capabilities by changing certain config bits and
|
|
|
|
* reading back to see if they change. Finally write back the original value.
|
|
|
|
*/
|
|
|
|
#define probe_gc0_config_dyn(name, maxconf, dynconf, bits) \
|
|
|
|
do { \
|
|
|
|
maxconf = read_gc0_##name(); \
|
|
|
|
write_gc0_##name(maxconf ^ (bits)); \
|
|
|
|
back_to_back_c0_hazard(); \
|
|
|
|
dynconf = maxconf ^ read_gc0_##name(); \
|
|
|
|
write_gc0_##name(maxconf); \
|
|
|
|
maxconf |= dynconf; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
static inline unsigned int decode_guest_config0(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
unsigned int config0;
|
|
|
|
|
|
|
|
probe_gc0_config(config, config0, MIPS_CONF_M);
|
|
|
|
|
|
|
|
if (config0 & MIPS_CONF_M)
|
|
|
|
c->guest.conf |= BIT(1);
|
|
|
|
return config0 & MIPS_CONF_M;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned int decode_guest_config1(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
unsigned int config1, config1_dyn;
|
|
|
|
|
|
|
|
probe_gc0_config_dyn(config1, config1, config1_dyn,
|
|
|
|
MIPS_CONF_M | MIPS_CONF1_PC | MIPS_CONF1_WR |
|
|
|
|
MIPS_CONF1_FP);
|
|
|
|
|
|
|
|
if (config1 & MIPS_CONF1_FP)
|
|
|
|
c->guest.options |= MIPS_CPU_FPU;
|
|
|
|
if (config1_dyn & MIPS_CONF1_FP)
|
|
|
|
c->guest.options_dyn |= MIPS_CPU_FPU;
|
|
|
|
|
|
|
|
if (config1 & MIPS_CONF1_WR)
|
|
|
|
c->guest.options |= MIPS_CPU_WATCH;
|
|
|
|
if (config1_dyn & MIPS_CONF1_WR)
|
|
|
|
c->guest.options_dyn |= MIPS_CPU_WATCH;
|
|
|
|
|
|
|
|
if (config1 & MIPS_CONF1_PC)
|
|
|
|
c->guest.options |= MIPS_CPU_PERF;
|
|
|
|
if (config1_dyn & MIPS_CONF1_PC)
|
|
|
|
c->guest.options_dyn |= MIPS_CPU_PERF;
|
|
|
|
|
|
|
|
if (config1 & MIPS_CONF_M)
|
|
|
|
c->guest.conf |= BIT(2);
|
|
|
|
return config1 & MIPS_CONF_M;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned int decode_guest_config2(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
unsigned int config2;
|
|
|
|
|
|
|
|
probe_gc0_config(config2, config2, MIPS_CONF_M);
|
|
|
|
|
|
|
|
if (config2 & MIPS_CONF_M)
|
|
|
|
c->guest.conf |= BIT(3);
|
|
|
|
return config2 & MIPS_CONF_M;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned int decode_guest_config3(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
unsigned int config3, config3_dyn;
|
|
|
|
|
|
|
|
probe_gc0_config_dyn(config3, config3, config3_dyn,
|
|
|
|
MIPS_CONF_M | MIPS_CONF3_MSA | MIPS_CONF3_CTXTC);
|
|
|
|
|
|
|
|
if (config3 & MIPS_CONF3_CTXTC)
|
|
|
|
c->guest.options |= MIPS_CPU_CTXTC;
|
|
|
|
if (config3_dyn & MIPS_CONF3_CTXTC)
|
|
|
|
c->guest.options_dyn |= MIPS_CPU_CTXTC;
|
|
|
|
|
|
|
|
if (config3 & MIPS_CONF3_PW)
|
|
|
|
c->guest.options |= MIPS_CPU_HTW;
|
|
|
|
|
|
|
|
if (config3 & MIPS_CONF3_SC)
|
|
|
|
c->guest.options |= MIPS_CPU_SEGMENTS;
|
|
|
|
|
|
|
|
if (config3 & MIPS_CONF3_BI)
|
|
|
|
c->guest.options |= MIPS_CPU_BADINSTR;
|
|
|
|
if (config3 & MIPS_CONF3_BP)
|
|
|
|
c->guest.options |= MIPS_CPU_BADINSTRP;
|
|
|
|
|
|
|
|
if (config3 & MIPS_CONF3_MSA)
|
|
|
|
c->guest.ases |= MIPS_ASE_MSA;
|
|
|
|
if (config3_dyn & MIPS_CONF3_MSA)
|
|
|
|
c->guest.ases_dyn |= MIPS_ASE_MSA;
|
|
|
|
|
|
|
|
if (config3 & MIPS_CONF_M)
|
|
|
|
c->guest.conf |= BIT(4);
|
|
|
|
return config3 & MIPS_CONF_M;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned int decode_guest_config4(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
unsigned int config4;
|
|
|
|
|
|
|
|
probe_gc0_config(config4, config4,
|
|
|
|
MIPS_CONF_M | MIPS_CONF4_KSCREXIST);
|
|
|
|
|
|
|
|
c->guest.kscratch_mask = (config4 & MIPS_CONF4_KSCREXIST)
|
|
|
|
>> MIPS_CONF4_KSCREXIST_SHIFT;
|
|
|
|
|
|
|
|
if (config4 & MIPS_CONF_M)
|
|
|
|
c->guest.conf |= BIT(5);
|
|
|
|
return config4 & MIPS_CONF_M;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned int decode_guest_config5(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
unsigned int config5, config5_dyn;
|
|
|
|
|
|
|
|
probe_gc0_config_dyn(config5, config5, config5_dyn,
|
|
|
|
MIPS_CONF_M | MIPS_CONF5_MRP);
|
|
|
|
|
|
|
|
if (config5 & MIPS_CONF5_MRP)
|
|
|
|
c->guest.options |= MIPS_CPU_MAAR;
|
|
|
|
if (config5_dyn & MIPS_CONF5_MRP)
|
|
|
|
c->guest.options_dyn |= MIPS_CPU_MAAR;
|
|
|
|
|
|
|
|
if (config5 & MIPS_CONF5_LLB)
|
|
|
|
c->guest.options |= MIPS_CPU_RW_LLB;
|
|
|
|
|
|
|
|
if (config5 & MIPS_CONF_M)
|
|
|
|
c->guest.conf |= BIT(6);
|
|
|
|
return config5 & MIPS_CONF_M;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void decode_guest_configs(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
unsigned int ok;
|
|
|
|
|
|
|
|
ok = decode_guest_config0(c);
|
|
|
|
if (ok)
|
|
|
|
ok = decode_guest_config1(c);
|
|
|
|
if (ok)
|
|
|
|
ok = decode_guest_config2(c);
|
|
|
|
if (ok)
|
|
|
|
ok = decode_guest_config3(c);
|
|
|
|
if (ok)
|
|
|
|
ok = decode_guest_config4(c);
|
|
|
|
if (ok)
|
|
|
|
decode_guest_config5(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void cpu_probe_guestctl0(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
unsigned int guestctl0, temp;
|
|
|
|
|
|
|
|
guestctl0 = read_c0_guestctl0();
|
|
|
|
|
|
|
|
if (guestctl0 & MIPS_GCTL0_G0E)
|
|
|
|
c->options |= MIPS_CPU_GUESTCTL0EXT;
|
|
|
|
if (guestctl0 & MIPS_GCTL0_G1)
|
|
|
|
c->options |= MIPS_CPU_GUESTCTL1;
|
|
|
|
if (guestctl0 & MIPS_GCTL0_G2)
|
|
|
|
c->options |= MIPS_CPU_GUESTCTL2;
|
|
|
|
if (!(guestctl0 & MIPS_GCTL0_RAD)) {
|
|
|
|
c->options |= MIPS_CPU_GUESTID;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Probe for Direct Root to Guest (DRG). Set GuestCtl1.RID = 0
|
|
|
|
* first, otherwise all data accesses will be fully virtualised
|
|
|
|
* as if they were performed by guest mode.
|
|
|
|
*/
|
|
|
|
write_c0_guestctl1(0);
|
|
|
|
tlbw_use_hazard();
|
|
|
|
|
|
|
|
write_c0_guestctl0(guestctl0 | MIPS_GCTL0_DRG);
|
|
|
|
back_to_back_c0_hazard();
|
|
|
|
temp = read_c0_guestctl0();
|
|
|
|
|
|
|
|
if (temp & MIPS_GCTL0_DRG) {
|
|
|
|
write_c0_guestctl0(guestctl0);
|
|
|
|
c->options |= MIPS_CPU_DRG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void cpu_probe_guestctl1(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
if (cpu_has_guestid) {
|
|
|
|
/* determine the number of bits of GuestID available */
|
|
|
|
write_c0_guestctl1(MIPS_GCTL1_ID);
|
|
|
|
back_to_back_c0_hazard();
|
|
|
|
c->guestid_mask = (read_c0_guestctl1() & MIPS_GCTL1_ID)
|
|
|
|
>> MIPS_GCTL1_ID_SHIFT;
|
|
|
|
write_c0_guestctl1(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void cpu_probe_gtoffset(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
/* determine the number of bits of GTOffset available */
|
|
|
|
write_c0_gtoffset(0xffffffff);
|
|
|
|
back_to_back_c0_hazard();
|
|
|
|
c->gtoffset_mask = read_c0_gtoffset();
|
|
|
|
write_c0_gtoffset(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void cpu_probe_vz(struct cpuinfo_mips *c)
|
|
|
|
{
|
|
|
|
cpu_probe_guestctl0(c);
|
|
|
|
if (cpu_has_guestctl1)
|
|
|
|
cpu_probe_guestctl1(c);
|
|
|
|
|
|
|
|
cpu_probe_gtoffset(c);
|
|
|
|
|
|
|
|
decode_guest_configs(c);
|
|
|
|
}
|
|
|
|
|
2005-10-01 14:06:32 +02:00
|
|
|
#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
|
2005-04-17 00:20:36 +02:00
|
|
|
| MIPS_CPU_COUNTER)
|
|
|
|
|
2008-10-30 14:38:45 +01:00
|
|
|
static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
|
2005-04-17 00:20:36 +02:00
|
|
|
{
|
2013-09-17 17:58:10 +02:00
|
|
|
switch (c->processor_id & PRID_IMP_MASK) {
|
2005-04-17 00:20:36 +02:00
|
|
|
case PRID_IMP_R2000:
|
|
|
|
c->cputype = CPU_R2000;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R2000";
|
2015-04-04 00:27:48 +02:00
|
|
|
c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
|
2005-10-01 14:06:32 +02:00
|
|
|
c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
|
2012-05-11 06:21:18 +02:00
|
|
|
MIPS_CPU_NOFPUEX;
|
2005-04-17 00:20:36 +02:00
|
|
|
if (__cpu_has_fpu())
|
|
|
|
c->options |= MIPS_CPU_FPU;
|
|
|
|
c->tlbsize = 64;
|
|
|
|
break;
|
|
|
|
case PRID_IMP_R3000:
|
2013-09-17 17:58:10 +02:00
|
|
|
if ((c->processor_id & PRID_REV_MASK) == PRID_REV_R3000A) {
|
2008-10-30 14:38:45 +01:00
|
|
|
if (cpu_has_confreg()) {
|
2005-04-17 00:20:36 +02:00
|
|
|
c->cputype = CPU_R3081E;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R3081";
|
|
|
|
} else {
|
2005-04-17 00:20:36 +02:00
|
|
|
c->cputype = CPU_R3000A;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R3000A";
|
|
|
|
}
|
|
|
|
} else {
|
2005-04-17 00:20:36 +02:00
|
|
|
c->cputype = CPU_R3000;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R3000";
|
|
|
|
}
|
2015-04-04 00:27:48 +02:00
|
|
|
c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
|
2005-10-01 14:06:32 +02:00
|
|
|
c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
|
2012-05-11 06:21:18 +02:00
|
|
|
MIPS_CPU_NOFPUEX;
|
2005-04-17 00:20:36 +02:00
|
|
|
if (__cpu_has_fpu())
|
|
|
|
c->options |= MIPS_CPU_FPU;
|
|
|
|
c->tlbsize = 64;
|
|
|
|
break;
|
|
|
|
case PRID_IMP_R4000:
|
|
|
|
if (read_c0_config() & CONF_SC) {
|
2013-09-17 17:58:10 +02:00
|
|
|
if ((c->processor_id & PRID_REV_MASK) >=
|
|
|
|
PRID_REV_R4400) {
|
2005-04-17 00:20:36 +02:00
|
|
|
c->cputype = CPU_R4400PC;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R4400PC";
|
|
|
|
} else {
|
2005-04-17 00:20:36 +02:00
|
|
|
c->cputype = CPU_R4000PC;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R4000PC";
|
|
|
|
}
|
2005-04-17 00:20:36 +02:00
|
|
|
} else {
|
2013-09-23 15:01:53 +02:00
|
|
|
int cca = read_c0_config() & CONF_CM_CMASK;
|
|
|
|
int mc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SC and MC versions can't be reliably told apart,
|
|
|
|
* but only the latter support coherent caching
|
|
|
|
* modes so assume the firmware has set the KSEG0
|
|
|
|
* coherency attribute reasonably (if uncached, we
|
|
|
|
* assume SC).
|
|
|
|
*/
|
|
|
|
switch (cca) {
|
|
|
|
case CONF_CM_CACHABLE_CE:
|
|
|
|
case CONF_CM_CACHABLE_COW:
|
|
|
|
case CONF_CM_CACHABLE_CUW:
|
|
|
|
mc = 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
mc = 0;
|
|
|
|
break;
|
|
|
|
}
|
2013-09-17 17:58:10 +02:00
|
|
|
if ((c->processor_id & PRID_REV_MASK) >=
|
|
|
|
PRID_REV_R4400) {
|
2013-09-23 15:01:53 +02:00
|
|
|
c->cputype = mc ? CPU_R4400MC : CPU_R4400SC;
|
|
|
|
__cpu_name[cpu] = mc ? "R4400MC" : "R4400SC";
|
2008-10-30 14:38:45 +01:00
|
|
|
} else {
|
2013-09-23 15:01:53 +02:00
|
|
|
c->cputype = mc ? CPU_R4000MC : CPU_R4000SC;
|
|
|
|
__cpu_name[cpu] = mc ? "R4000MC" : "R4000SC";
|
2008-10-30 14:38:45 +01:00
|
|
|
}
|
2005-04-17 00:20:36 +02:00
|
|
|
}
|
|
|
|
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_III);
|
2015-04-04 00:27:48 +02:00
|
|
|
c->fpu_msk31 |= FPU_CSR_CONDX;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
|
2012-05-11 06:21:18 +02:00
|
|
|
MIPS_CPU_WATCH | MIPS_CPU_VCE |
|
|
|
|
MIPS_CPU_LLSC;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->tlbsize = 48;
|
|
|
|
break;
|
|
|
|
case PRID_IMP_VR41XX:
|
2013-02-21 07:38:19 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_III);
|
2015-04-04 00:27:48 +02:00
|
|
|
c->fpu_msk31 |= FPU_CSR_CONDX;
|
2013-02-21 07:38:19 +01:00
|
|
|
c->options = R4K_OPTS;
|
|
|
|
c->tlbsize = 32;
|
2005-04-17 00:20:36 +02:00
|
|
|
switch (c->processor_id & 0xf0) {
|
|
|
|
case PRID_REV_VR4111:
|
|
|
|
c->cputype = CPU_VR4111;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "NEC VR4111";
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
|
|
|
case PRID_REV_VR4121:
|
|
|
|
c->cputype = CPU_VR4121;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "NEC VR4121";
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
|
|
|
case PRID_REV_VR4122:
|
2008-10-30 14:38:45 +01:00
|
|
|
if ((c->processor_id & 0xf) < 0x3) {
|
2005-04-17 00:20:36 +02:00
|
|
|
c->cputype = CPU_VR4122;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "NEC VR4122";
|
|
|
|
} else {
|
2005-04-17 00:20:36 +02:00
|
|
|
c->cputype = CPU_VR4181A;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "NEC VR4181A";
|
|
|
|
}
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
|
|
|
case PRID_REV_VR4130:
|
2008-10-30 14:38:45 +01:00
|
|
|
if ((c->processor_id & 0xf) < 0x4) {
|
2005-04-17 00:20:36 +02:00
|
|
|
c->cputype = CPU_VR4131;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "NEC VR4131";
|
|
|
|
} else {
|
2005-04-17 00:20:36 +02:00
|
|
|
c->cputype = CPU_VR4133;
|
2013-02-21 07:38:19 +01:00
|
|
|
c->options |= MIPS_CPU_LLSC;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "NEC VR4133";
|
|
|
|
}
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
|
|
|
|
c->cputype = CPU_VR41XX;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "NEC Vr41xx";
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PRID_IMP_R4300:
|
|
|
|
c->cputype = CPU_R4300;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R4300";
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_III);
|
2015-04-04 00:27:48 +02:00
|
|
|
c->fpu_msk31 |= FPU_CSR_CONDX;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
|
2012-05-11 06:21:18 +02:00
|
|
|
MIPS_CPU_LLSC;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->tlbsize = 32;
|
|
|
|
break;
|
|
|
|
case PRID_IMP_R4600:
|
|
|
|
c->cputype = CPU_R4600;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R4600";
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_III);
|
2015-04-04 00:27:48 +02:00
|
|
|
c->fpu_msk31 |= FPU_CSR_CONDX;
|
2005-07-27 23:48:12 +02:00
|
|
|
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
|
|
|
|
MIPS_CPU_LLSC;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->tlbsize = 48;
|
|
|
|
break;
|
|
|
|
#if 0
|
2012-05-11 06:21:18 +02:00
|
|
|
case PRID_IMP_R4650:
|
2005-04-17 00:20:36 +02:00
|
|
|
/*
|
|
|
|
* This processor doesn't have an MMU, so it's not
|
|
|
|
* "real easy" to run Linux on it. It is left purely
|
|
|
|
* for documentation. Commented out because it shares
|
|
|
|
* it's c0_prid id number with the TX3900.
|
|
|
|
*/
|
2006-03-11 09:18:41 +01:00
|
|
|
c->cputype = CPU_R4650;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R4650";
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_III);
|
2015-04-04 00:27:48 +02:00
|
|
|
c->fpu_msk31 |= FPU_CSR_CONDX;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC;
|
2012-05-11 06:21:18 +02:00
|
|
|
c->tlbsize = 48;
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case PRID_IMP_TX39:
|
2015-04-04 00:27:48 +02:00
|
|
|
c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
|
2005-10-01 14:06:32 +02:00
|
|
|
c->options = MIPS_CPU_TLB | MIPS_CPU_TX39_CACHE;
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
if ((c->processor_id & 0xf0) == (PRID_REV_TX3927 & 0xf0)) {
|
|
|
|
c->cputype = CPU_TX3927;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "TX3927";
|
2005-04-17 00:20:36 +02:00
|
|
|
c->tlbsize = 64;
|
|
|
|
} else {
|
2013-09-17 17:58:10 +02:00
|
|
|
switch (c->processor_id & PRID_REV_MASK) {
|
2005-04-17 00:20:36 +02:00
|
|
|
case PRID_REV_TX3912:
|
|
|
|
c->cputype = CPU_TX3912;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "TX3912";
|
2005-04-17 00:20:36 +02:00
|
|
|
c->tlbsize = 32;
|
|
|
|
break;
|
|
|
|
case PRID_REV_TX3922:
|
|
|
|
c->cputype = CPU_TX3922;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "TX3922";
|
2005-04-17 00:20:36 +02:00
|
|
|
c->tlbsize = 64;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PRID_IMP_R4700:
|
|
|
|
c->cputype = CPU_R4700;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R4700";
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_III);
|
2015-04-04 00:27:48 +02:00
|
|
|
c->fpu_msk31 |= FPU_CSR_CONDX;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
|
2012-05-11 06:21:18 +02:00
|
|
|
MIPS_CPU_LLSC;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->tlbsize = 48;
|
|
|
|
break;
|
|
|
|
case PRID_IMP_TX49:
|
|
|
|
c->cputype = CPU_TX49XX;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R49XX";
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_III);
|
2015-04-04 00:27:48 +02:00
|
|
|
c->fpu_msk31 |= FPU_CSR_CONDX;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->options = R4K_OPTS | MIPS_CPU_LLSC;
|
|
|
|
if (!(c->processor_id & 0x08))
|
|
|
|
c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR;
|
|
|
|
c->tlbsize = 48;
|
|
|
|
break;
|
|
|
|
case PRID_IMP_R5000:
|
|
|
|
c->cputype = CPU_R5000;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R5000";
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_IV);
|
2005-04-17 00:20:36 +02:00
|
|
|
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
|
2012-05-11 06:21:18 +02:00
|
|
|
MIPS_CPU_LLSC;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->tlbsize = 48;
|
|
|
|
break;
|
|
|
|
case PRID_IMP_R5432:
|
|
|
|
c->cputype = CPU_R5432;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R5432";
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_IV);
|
2005-04-17 00:20:36 +02:00
|
|
|
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
|
2012-05-11 06:21:18 +02:00
|
|
|
MIPS_CPU_WATCH | MIPS_CPU_LLSC;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->tlbsize = 48;
|
|
|
|
break;
|
|
|
|
case PRID_IMP_R5500:
|
|
|
|
c->cputype = CPU_R5500;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R5500";
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_IV);
|
2005-04-17 00:20:36 +02:00
|
|
|
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
|
2012-05-11 06:21:18 +02:00
|
|
|
MIPS_CPU_WATCH | MIPS_CPU_LLSC;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->tlbsize = 48;
|
|
|
|
break;
|
|
|
|
case PRID_IMP_NEVADA:
|
|
|
|
c->cputype = CPU_NEVADA;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "Nevada";
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_IV);
|
2005-04-17 00:20:36 +02:00
|
|
|
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
|
2012-05-11 06:21:18 +02:00
|
|
|
MIPS_CPU_DIVEC | MIPS_CPU_LLSC;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->tlbsize = 48;
|
|
|
|
break;
|
|
|
|
case PRID_IMP_R6000:
|
|
|
|
c->cputype = CPU_R6000;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R6000";
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_II);
|
2015-04-04 00:27:48 +02:00
|
|
|
c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
|
2012-05-11 06:21:18 +02:00
|
|
|
MIPS_CPU_LLSC;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->tlbsize = 32;
|
|
|
|
break;
|
|
|
|
case PRID_IMP_R6000A:
|
|
|
|
c->cputype = CPU_R6000A;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R6000A";
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_II);
|
2015-04-04 00:27:48 +02:00
|
|
|
c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
|
2012-05-11 06:21:18 +02:00
|
|
|
MIPS_CPU_LLSC;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->tlbsize = 32;
|
|
|
|
break;
|
|
|
|
case PRID_IMP_RM7000:
|
|
|
|
c->cputype = CPU_RM7000;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "RM7000";
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_IV);
|
2005-04-17 00:20:36 +02:00
|
|
|
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
|
2012-05-11 06:21:18 +02:00
|
|
|
MIPS_CPU_LLSC;
|
2005-04-17 00:20:36 +02:00
|
|
|
/*
|
2013-01-22 12:59:30 +01:00
|
|
|
* Undocumented RM7000: Bit 29 in the info register of
|
2005-04-17 00:20:36 +02:00
|
|
|
* the RM7000 v2.0 indicates if the TLB has 48 or 64
|
|
|
|
* entries.
|
|
|
|
*
|
2013-01-22 12:59:30 +01:00
|
|
|
* 29 1 => 64 entry JTLB
|
|
|
|
* 0 => 48 entry JTLB
|
2005-04-17 00:20:36 +02:00
|
|
|
*/
|
|
|
|
c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48;
|
|
|
|
break;
|
|
|
|
case PRID_IMP_R8000:
|
|
|
|
c->cputype = CPU_R8000;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "RM8000";
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_IV);
|
2005-04-17 00:20:36 +02:00
|
|
|
c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
|
2012-05-11 06:21:18 +02:00
|
|
|
MIPS_CPU_FPU | MIPS_CPU_32FPR |
|
|
|
|
MIPS_CPU_LLSC;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->tlbsize = 384; /* has weird TLB: 3-way x 128 */
|
|
|
|
break;
|
|
|
|
case PRID_IMP_R10000:
|
|
|
|
c->cputype = CPU_R10000;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R10000";
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_IV);
|
2005-11-22 18:53:59 +01:00
|
|
|
c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
|
2012-05-11 06:21:18 +02:00
|
|
|
MIPS_CPU_FPU | MIPS_CPU_32FPR |
|
2005-04-17 00:20:36 +02:00
|
|
|
MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
|
2012-05-11 06:21:18 +02:00
|
|
|
MIPS_CPU_LLSC;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->tlbsize = 64;
|
|
|
|
break;
|
|
|
|
case PRID_IMP_R12000:
|
|
|
|
c->cputype = CPU_R12000;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "R12000";
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_IV);
|
2005-11-22 18:53:59 +01:00
|
|
|
c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
|
2012-05-11 06:21:18 +02:00
|
|
|
MIPS_CPU_FPU | MIPS_CPU_32FPR |
|
2005-04-17 00:20:36 +02:00
|
|
|
MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
|
2015-06-03 00:21:33 +02:00
|
|
|
MIPS_CPU_LLSC | MIPS_CPU_BP_GHIST;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->tlbsize = 64;
|
|
|
|
break;
|
2006-05-17 04:23:59 +02:00
|
|
|
case PRID_IMP_R14000:
|
2015-01-21 13:59:45 +01:00
|
|
|
if (((c->processor_id >> 4) & 0x0f) > 2) {
|
|
|
|
c->cputype = CPU_R16000;
|
|
|
|
__cpu_name[cpu] = "R16000";
|
|
|
|
} else {
|
|
|
|
c->cputype = CPU_R14000;
|
|
|
|
__cpu_name[cpu] = "R14000";
|
|
|
|
}
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_IV);
|
2006-05-17 04:23:59 +02:00
|
|
|
c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
|
2012-05-11 06:21:18 +02:00
|
|
|
MIPS_CPU_FPU | MIPS_CPU_32FPR |
|
2006-05-17 04:23:59 +02:00
|
|
|
MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
|
2015-06-03 00:21:33 +02:00
|
|
|
MIPS_CPU_LLSC | MIPS_CPU_BP_GHIST;
|
2006-05-17 04:23:59 +02:00
|
|
|
c->tlbsize = 64;
|
|
|
|
break;
|
2014-02-16 09:01:18 +01:00
|
|
|
case PRID_IMP_LOONGSON_64: /* Loongson-2/3 */
|
2011-04-16 20:29:29 +02:00
|
|
|
switch (c->processor_id & PRID_REV_MASK) {
|
|
|
|
case PRID_REV_LOONGSON2E:
|
2014-03-21 11:44:00 +01:00
|
|
|
c->cputype = CPU_LOONGSON2;
|
|
|
|
__cpu_name[cpu] = "ICT Loongson-2";
|
2011-04-16 20:29:29 +02:00
|
|
|
set_elf_platform(cpu, "loongson2e");
|
2014-11-04 07:13:23 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_III);
|
2015-04-04 00:27:48 +02:00
|
|
|
c->fpu_msk31 |= FPU_CSR_CONDX;
|
2011-04-16 20:29:29 +02:00
|
|
|
break;
|
|
|
|
case PRID_REV_LOONGSON2F:
|
2014-03-21 11:44:00 +01:00
|
|
|
c->cputype = CPU_LOONGSON2;
|
|
|
|
__cpu_name[cpu] = "ICT Loongson-2";
|
2011-04-16 20:29:29 +02:00
|
|
|
set_elf_platform(cpu, "loongson2f");
|
2014-11-04 07:13:23 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_III);
|
2015-04-04 00:27:48 +02:00
|
|
|
c->fpu_msk31 |= FPU_CSR_CONDX;
|
2011-04-16 20:29:29 +02:00
|
|
|
break;
|
2016-03-03 02:45:09 +01:00
|
|
|
case PRID_REV_LOONGSON3A_R1:
|
2014-03-21 11:44:00 +01:00
|
|
|
c->cputype = CPU_LOONGSON3;
|
|
|
|
__cpu_name[cpu] = "ICT Loongson-3";
|
|
|
|
set_elf_platform(cpu, "loongson3a");
|
2014-11-04 07:13:23 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_M64R1);
|
2014-03-21 11:44:00 +01:00
|
|
|
break;
|
2014-06-26 05:41:30 +02:00
|
|
|
case PRID_REV_LOONGSON3B_R1:
|
|
|
|
case PRID_REV_LOONGSON3B_R2:
|
|
|
|
c->cputype = CPU_LOONGSON3;
|
|
|
|
__cpu_name[cpu] = "ICT Loongson-3";
|
|
|
|
set_elf_platform(cpu, "loongson3b");
|
2014-11-04 07:13:23 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_M64R1);
|
2014-06-26 05:41:30 +02:00
|
|
|
break;
|
2011-04-16 20:29:29 +02:00
|
|
|
}
|
|
|
|
|
2007-06-06 08:52:43 +02:00
|
|
|
c->options = R4K_OPTS |
|
|
|
|
MIPS_CPU_FPU | MIPS_CPU_LLSC |
|
|
|
|
MIPS_CPU_32FPR;
|
|
|
|
c->tlbsize = 64;
|
2014-11-04 07:13:22 +01:00
|
|
|
c->writecombine = _CACHE_UNCACHED_ACCELERATED;
|
2007-06-06 08:52:43 +02:00
|
|
|
break;
|
2014-02-16 09:01:18 +01:00
|
|
|
case PRID_IMP_LOONGSON_32: /* Loongson-1 */
|
2012-06-20 21:05:32 +02:00
|
|
|
decode_configs(c);
|
2005-12-08 15:04:24 +01:00
|
|
|
|
2012-06-20 21:05:32 +02:00
|
|
|
c->cputype = CPU_LOONGSON1;
|
2005-04-17 00:20:36 +02:00
|
|
|
|
2012-06-20 21:05:32 +02:00
|
|
|
switch (c->processor_id & PRID_REV_MASK) {
|
|
|
|
case PRID_REV_LOONGSON1B:
|
|
|
|
__cpu_name[cpu] = "Loongson 1B";
|
2005-12-08 15:04:24 +01:00
|
|
|
break;
|
|
|
|
}
|
2005-05-05 18:45:59 +02:00
|
|
|
|
2012-06-20 21:05:32 +02:00
|
|
|
break;
|
2005-04-17 00:20:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-30 14:38:45 +01:00
|
|
|
static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
|
2005-04-17 00:20:36 +02:00
|
|
|
{
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED_ACCELERATED;
|
2013-09-17 17:58:10 +02:00
|
|
|
switch (c->processor_id & PRID_IMP_MASK) {
|
2014-11-24 13:59:44 +01:00
|
|
|
case PRID_IMP_QEMU_GENERIC:
|
|
|
|
c->writecombine = _CACHE_UNCACHED;
|
|
|
|
c->cputype = CPU_QEMU_GENERIC;
|
|
|
|
__cpu_name[cpu] = "MIPS GENERIC QEMU";
|
|
|
|
break;
|
2005-04-17 00:20:36 +02:00
|
|
|
case PRID_IMP_4KC:
|
|
|
|
c->cputype = CPU_4KC;
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "MIPS 4Kc";
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
|
|
|
case PRID_IMP_4KEC:
|
2005-04-08 22:36:05 +02:00
|
|
|
case PRID_IMP_4KECR2:
|
|
|
|
c->cputype = CPU_4KEC;
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "MIPS 4KEc";
|
2005-04-08 22:36:05 +02:00
|
|
|
break;
|
2005-04-17 00:20:36 +02:00
|
|
|
case PRID_IMP_4KSC:
|
2005-10-04 16:01:26 +02:00
|
|
|
case PRID_IMP_4KSD:
|
2005-04-17 00:20:36 +02:00
|
|
|
c->cputype = CPU_4KSC;
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "MIPS 4KSc";
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
|
|
|
case PRID_IMP_5KC:
|
|
|
|
c->cputype = CPU_5KC;
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "MIPS 5Kc";
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
2012-07-06 21:56:01 +02:00
|
|
|
case PRID_IMP_5KE:
|
|
|
|
c->cputype = CPU_5KE;
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED;
|
2012-07-06 21:56:01 +02:00
|
|
|
__cpu_name[cpu] = "MIPS 5KE";
|
|
|
|
break;
|
2005-04-17 00:20:36 +02:00
|
|
|
case PRID_IMP_20KC:
|
|
|
|
c->cputype = CPU_20KC;
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "MIPS 20Kc";
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
|
|
|
case PRID_IMP_24K:
|
|
|
|
c->cputype = CPU_24K;
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "MIPS 24Kc";
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
2013-01-11 22:44:10 +01:00
|
|
|
case PRID_IMP_24KE:
|
|
|
|
c->cputype = CPU_24K;
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED;
|
2013-01-11 22:44:10 +01:00
|
|
|
__cpu_name[cpu] = "MIPS 24KEc";
|
|
|
|
break;
|
2005-04-17 00:20:36 +02:00
|
|
|
case PRID_IMP_25KF:
|
|
|
|
c->cputype = CPU_25KF;
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "MIPS 25Kc";
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
2005-07-12 18:12:05 +02:00
|
|
|
case PRID_IMP_34K:
|
|
|
|
c->cputype = CPU_34K;
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "MIPS 34Kc";
|
2005-07-12 18:12:05 +02:00
|
|
|
break;
|
2006-05-02 15:08:46 +02:00
|
|
|
case PRID_IMP_74K:
|
|
|
|
c->cputype = CPU_74K;
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "MIPS 74Kc";
|
2006-05-02 15:08:46 +02:00
|
|
|
break;
|
2012-07-06 23:56:00 +02:00
|
|
|
case PRID_IMP_M14KC:
|
|
|
|
c->cputype = CPU_M14KC;
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED;
|
2012-07-06 23:56:00 +02:00
|
|
|
__cpu_name[cpu] = "MIPS M14Kc";
|
|
|
|
break;
|
2012-12-07 04:51:35 +01:00
|
|
|
case PRID_IMP_M14KEC:
|
|
|
|
c->cputype = CPU_M14KEC;
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED;
|
2012-12-07 04:51:35 +01:00
|
|
|
__cpu_name[cpu] = "MIPS M14KEc";
|
|
|
|
break;
|
2008-04-28 18:14:26 +02:00
|
|
|
case PRID_IMP_1004K:
|
|
|
|
c->cputype = CPU_1004K;
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "MIPS 1004Kc";
|
2008-04-28 18:14:26 +02:00
|
|
|
break;
|
2012-06-26 06:11:03 +02:00
|
|
|
case PRID_IMP_1074K:
|
2014-01-17 22:03:50 +01:00
|
|
|
c->cputype = CPU_1074K;
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED;
|
2012-06-26 06:11:03 +02:00
|
|
|
__cpu_name[cpu] = "MIPS 1074Kc";
|
|
|
|
break;
|
2013-11-20 11:46:02 +01:00
|
|
|
case PRID_IMP_INTERAPTIV_UP:
|
|
|
|
c->cputype = CPU_INTERAPTIV;
|
|
|
|
__cpu_name[cpu] = "MIPS interAptiv";
|
|
|
|
break;
|
|
|
|
case PRID_IMP_INTERAPTIV_MP:
|
|
|
|
c->cputype = CPU_INTERAPTIV;
|
|
|
|
__cpu_name[cpu] = "MIPS interAptiv (multi)";
|
|
|
|
break;
|
2013-11-14 17:12:28 +01:00
|
|
|
case PRID_IMP_PROAPTIV_UP:
|
|
|
|
c->cputype = CPU_PROAPTIV;
|
|
|
|
__cpu_name[cpu] = "MIPS proAptiv";
|
|
|
|
break;
|
|
|
|
case PRID_IMP_PROAPTIV_MP:
|
|
|
|
c->cputype = CPU_PROAPTIV;
|
|
|
|
__cpu_name[cpu] = "MIPS proAptiv (multi)";
|
|
|
|
break;
|
2014-01-22 17:19:39 +01:00
|
|
|
case PRID_IMP_P5600:
|
|
|
|
c->cputype = CPU_P5600;
|
|
|
|
__cpu_name[cpu] = "MIPS P5600";
|
|
|
|
break;
|
2016-02-03 04:26:39 +01:00
|
|
|
case PRID_IMP_P6600:
|
|
|
|
c->cputype = CPU_P6600;
|
|
|
|
__cpu_name[cpu] = "MIPS P6600";
|
|
|
|
break;
|
2015-07-09 11:40:37 +02:00
|
|
|
case PRID_IMP_I6400:
|
|
|
|
c->cputype = CPU_I6400;
|
|
|
|
__cpu_name[cpu] = "MIPS I6400";
|
|
|
|
break;
|
2014-03-04 14:34:44 +01:00
|
|
|
case PRID_IMP_M5150:
|
|
|
|
c->cputype = CPU_M5150;
|
|
|
|
__cpu_name[cpu] = "MIPS M5150";
|
|
|
|
break;
|
2016-02-03 17:17:30 +01:00
|
|
|
case PRID_IMP_M6250:
|
|
|
|
c->cputype = CPU_M6250;
|
|
|
|
__cpu_name[cpu] = "MIPS M6250";
|
|
|
|
break;
|
2005-04-17 00:20:36 +02:00
|
|
|
}
|
2007-09-13 13:32:02 +02:00
|
|
|
|
2013-11-14 17:12:31 +01:00
|
|
|
decode_configs(c);
|
|
|
|
|
2007-09-13 13:32:02 +02:00
|
|
|
spram_config();
|
2005-04-17 00:20:36 +02:00
|
|
|
}
|
|
|
|
|
2008-10-30 14:38:45 +01:00
|
|
|
static inline void cpu_probe_alchemy(struct cpuinfo_mips *c, unsigned int cpu)
|
2005-04-17 00:20:36 +02:00
|
|
|
{
|
2005-05-05 18:45:59 +02:00
|
|
|
decode_configs(c);
|
2013-09-17 17:58:10 +02:00
|
|
|
switch (c->processor_id & PRID_IMP_MASK) {
|
2005-04-17 00:20:36 +02:00
|
|
|
case PRID_IMP_AU1_REV1:
|
|
|
|
case PRID_IMP_AU1_REV2:
|
2009-03-25 17:49:28 +01:00
|
|
|
c->cputype = CPU_ALCHEMY;
|
2005-04-17 00:20:36 +02:00
|
|
|
switch ((c->processor_id >> 24) & 0xff) {
|
|
|
|
case 0:
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "Au1000";
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "Au1500";
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "Au1100";
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
|
|
|
case 3:
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "Au1550";
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
2005-03-01 07:33:16 +01:00
|
|
|
case 4:
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "Au1200";
|
2013-09-17 17:58:10 +02:00
|
|
|
if ((c->processor_id & PRID_REV_MASK) == 2)
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "Au1250";
|
2007-12-06 09:07:55 +01:00
|
|
|
break;
|
|
|
|
case 5:
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "Au1210";
|
2005-03-01 07:33:16 +01:00
|
|
|
break;
|
2005-04-17 00:20:36 +02:00
|
|
|
default:
|
2009-03-25 17:49:28 +01:00
|
|
|
__cpu_name[cpu] = "Au1xxx";
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-30 14:38:45 +01:00
|
|
|
static inline void cpu_probe_sibyte(struct cpuinfo_mips *c, unsigned int cpu)
|
2005-04-17 00:20:36 +02:00
|
|
|
{
|
2005-05-05 18:45:59 +02:00
|
|
|
decode_configs(c);
|
2005-10-01 14:06:32 +02:00
|
|
|
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED_ACCELERATED;
|
2013-09-17 17:58:10 +02:00
|
|
|
switch (c->processor_id & PRID_IMP_MASK) {
|
2005-04-17 00:20:36 +02:00
|
|
|
case PRID_IMP_SB1:
|
|
|
|
c->cputype = CPU_SB1;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "SiByte SB1";
|
2005-04-17 00:20:36 +02:00
|
|
|
/* FPU in pass1 is known to have issues. */
|
2013-09-17 17:58:10 +02:00
|
|
|
if ((c->processor_id & PRID_REV_MASK) < 0x02)
|
2006-01-29 19:42:08 +01:00
|
|
|
c->options &= ~(MIPS_CPU_FPU | MIPS_CPU_32FPR);
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
2005-10-20 08:56:20 +02:00
|
|
|
case PRID_IMP_SB1A:
|
|
|
|
c->cputype = CPU_SB1A;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "SiByte SB1A";
|
2005-10-20 08:56:20 +02:00
|
|
|
break;
|
2005-04-17 00:20:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-30 14:38:45 +01:00
|
|
|
static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c, unsigned int cpu)
|
2005-04-17 00:20:36 +02:00
|
|
|
{
|
2005-05-05 18:45:59 +02:00
|
|
|
decode_configs(c);
|
2013-09-17 17:58:10 +02:00
|
|
|
switch (c->processor_id & PRID_IMP_MASK) {
|
2005-04-17 00:20:36 +02:00
|
|
|
case PRID_IMP_SR71000:
|
|
|
|
c->cputype = CPU_SR71000;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "Sandcraft SR71000";
|
2005-04-17 00:20:36 +02:00
|
|
|
c->scache.ways = 8;
|
|
|
|
c->tlbsize = 64;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-30 14:38:45 +01:00
|
|
|
static inline void cpu_probe_nxp(struct cpuinfo_mips *c, unsigned int cpu)
|
2005-07-14 19:47:57 +02:00
|
|
|
{
|
|
|
|
decode_configs(c);
|
2013-09-17 17:58:10 +02:00
|
|
|
switch (c->processor_id & PRID_IMP_MASK) {
|
2005-07-14 19:47:57 +02:00
|
|
|
case PRID_IMP_PR4450:
|
|
|
|
c->cputype = CPU_PR4450;
|
2008-10-30 14:38:45 +01:00
|
|
|
__cpu_name[cpu] = "Philips PR4450";
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_M32R1);
|
2005-07-14 19:47:57 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-30 14:38:45 +01:00
|
|
|
static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
|
2007-09-25 15:40:12 +02:00
|
|
|
{
|
|
|
|
decode_configs(c);
|
2013-09-17 17:58:10 +02:00
|
|
|
switch (c->processor_id & PRID_IMP_MASK) {
|
2010-11-23 19:26:45 +01:00
|
|
|
case PRID_IMP_BMIPS32_REV4:
|
|
|
|
case PRID_IMP_BMIPS32_REV8:
|
2010-10-16 23:22:30 +02:00
|
|
|
c->cputype = CPU_BMIPS32;
|
|
|
|
__cpu_name[cpu] = "Broadcom BMIPS32";
|
2011-04-16 20:29:28 +02:00
|
|
|
set_elf_platform(cpu, "bmips32");
|
2010-10-16 23:22:30 +02:00
|
|
|
break;
|
|
|
|
case PRID_IMP_BMIPS3300:
|
|
|
|
case PRID_IMP_BMIPS3300_ALT:
|
|
|
|
case PRID_IMP_BMIPS3300_BUG:
|
|
|
|
c->cputype = CPU_BMIPS3300;
|
|
|
|
__cpu_name[cpu] = "Broadcom BMIPS3300";
|
2011-04-16 20:29:28 +02:00
|
|
|
set_elf_platform(cpu, "bmips3300");
|
2010-10-16 23:22:30 +02:00
|
|
|
break;
|
|
|
|
case PRID_IMP_BMIPS43XX: {
|
2013-09-17 17:58:10 +02:00
|
|
|
int rev = c->processor_id & PRID_REV_MASK;
|
2010-10-16 23:22:30 +02:00
|
|
|
|
|
|
|
if (rev >= PRID_REV_BMIPS4380_LO &&
|
|
|
|
rev <= PRID_REV_BMIPS4380_HI) {
|
|
|
|
c->cputype = CPU_BMIPS4380;
|
|
|
|
__cpu_name[cpu] = "Broadcom BMIPS4380";
|
2011-04-16 20:29:28 +02:00
|
|
|
set_elf_platform(cpu, "bmips4380");
|
2016-02-09 21:55:53 +01:00
|
|
|
c->options |= MIPS_CPU_RIXI;
|
2010-10-16 23:22:30 +02:00
|
|
|
} else {
|
|
|
|
c->cputype = CPU_BMIPS4350;
|
|
|
|
__cpu_name[cpu] = "Broadcom BMIPS4350";
|
2011-04-16 20:29:28 +02:00
|
|
|
set_elf_platform(cpu, "bmips4350");
|
2010-10-16 23:22:30 +02:00
|
|
|
}
|
2009-08-18 14:23:37 +02:00
|
|
|
break;
|
2010-10-16 23:22:30 +02:00
|
|
|
}
|
|
|
|
case PRID_IMP_BMIPS5000:
|
2014-10-21 06:28:01 +02:00
|
|
|
case PRID_IMP_BMIPS5200:
|
2010-10-16 23:22:30 +02:00
|
|
|
c->cputype = CPU_BMIPS5000;
|
2016-04-04 19:55:38 +02:00
|
|
|
if ((c->processor_id & PRID_IMP_MASK) == PRID_IMP_BMIPS5200)
|
|
|
|
__cpu_name[cpu] = "Broadcom BMIPS5200";
|
|
|
|
else
|
|
|
|
__cpu_name[cpu] = "Broadcom BMIPS5000";
|
2011-04-16 20:29:28 +02:00
|
|
|
set_elf_platform(cpu, "bmips5000");
|
2016-02-09 21:55:53 +01:00
|
|
|
c->options |= MIPS_CPU_ULRI | MIPS_CPU_RIXI;
|
2009-08-18 14:23:37 +02:00
|
|
|
break;
|
2007-09-25 15:40:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-12 00:33:26 +01:00
|
|
|
static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu)
|
|
|
|
{
|
|
|
|
decode_configs(c);
|
2013-09-17 17:58:10 +02:00
|
|
|
switch (c->processor_id & PRID_IMP_MASK) {
|
2008-12-12 00:33:26 +01:00
|
|
|
case PRID_IMP_CAVIUM_CN38XX:
|
|
|
|
case PRID_IMP_CAVIUM_CN31XX:
|
|
|
|
case PRID_IMP_CAVIUM_CN30XX:
|
2010-02-11 00:12:48 +01:00
|
|
|
c->cputype = CPU_CAVIUM_OCTEON;
|
|
|
|
__cpu_name[cpu] = "Cavium Octeon";
|
|
|
|
goto platform;
|
2008-12-12 00:33:26 +01:00
|
|
|
case PRID_IMP_CAVIUM_CN58XX:
|
|
|
|
case PRID_IMP_CAVIUM_CN56XX:
|
|
|
|
case PRID_IMP_CAVIUM_CN50XX:
|
|
|
|
case PRID_IMP_CAVIUM_CN52XX:
|
2010-02-11 00:12:48 +01:00
|
|
|
c->cputype = CPU_CAVIUM_OCTEON_PLUS;
|
|
|
|
__cpu_name[cpu] = "Cavium Octeon+";
|
|
|
|
platform:
|
2011-04-18 20:37:55 +02:00
|
|
|
set_elf_platform(cpu, "octeon");
|
2008-12-12 00:33:26 +01:00
|
|
|
break;
|
2011-09-24 02:29:54 +02:00
|
|
|
case PRID_IMP_CAVIUM_CN61XX:
|
2010-10-08 01:03:45 +02:00
|
|
|
case PRID_IMP_CAVIUM_CN63XX:
|
2011-09-24 02:29:54 +02:00
|
|
|
case PRID_IMP_CAVIUM_CN66XX:
|
|
|
|
case PRID_IMP_CAVIUM_CN68XX:
|
2013-07-30 00:07:01 +02:00
|
|
|
case PRID_IMP_CAVIUM_CNF71XX:
|
2010-10-08 01:03:45 +02:00
|
|
|
c->cputype = CPU_CAVIUM_OCTEON2;
|
|
|
|
__cpu_name[cpu] = "Cavium Octeon II";
|
2011-04-18 20:37:55 +02:00
|
|
|
set_elf_platform(cpu, "octeon2");
|
2010-10-08 01:03:45 +02:00
|
|
|
break;
|
2013-07-30 00:07:01 +02:00
|
|
|
case PRID_IMP_CAVIUM_CN70XX:
|
2016-02-01 23:43:41 +01:00
|
|
|
case PRID_IMP_CAVIUM_CN73XX:
|
|
|
|
case PRID_IMP_CAVIUM_CNF75XX:
|
2013-07-30 00:07:01 +02:00
|
|
|
case PRID_IMP_CAVIUM_CN78XX:
|
|
|
|
c->cputype = CPU_CAVIUM_OCTEON3;
|
|
|
|
__cpu_name[cpu] = "Cavium Octeon III";
|
|
|
|
set_elf_platform(cpu, "octeon3");
|
|
|
|
break;
|
2008-12-12 00:33:26 +01:00
|
|
|
default:
|
|
|
|
printk(KERN_INFO "Unknown Octeon chip!\n");
|
|
|
|
c->cputype = CPU_UNKNOWN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-03 02:45:09 +01:00
|
|
|
static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
|
|
|
|
{
|
|
|
|
switch (c->processor_id & PRID_IMP_MASK) {
|
|
|
|
case PRID_IMP_LOONGSON_64: /* Loongson-2/3 */
|
|
|
|
switch (c->processor_id & PRID_REV_MASK) {
|
|
|
|
case PRID_REV_LOONGSON3A_R2:
|
|
|
|
c->cputype = CPU_LOONGSON3;
|
|
|
|
__cpu_name[cpu] = "ICT Loongson-3";
|
|
|
|
set_elf_platform(cpu, "loongson3a");
|
|
|
|
set_isa(c, MIPS_CPU_ISA_M64R2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
decode_configs(c);
|
2016-03-03 02:45:12 +01:00
|
|
|
c->options |= MIPS_CPU_TLBINV | MIPS_CPU_LDPTE;
|
2016-03-03 02:45:09 +01:00
|
|
|
c->writecombine = _CACHE_UNCACHED_ACCELERATED;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
panic("Unknown Loongson Processor ID!");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-17 13:07:51 +02:00
|
|
|
static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu)
|
|
|
|
{
|
|
|
|
decode_configs(c);
|
|
|
|
/* JZRISC does not implement the CP0 counter. */
|
|
|
|
c->options &= ~MIPS_CPU_COUNTER;
|
MIPS: Implement random_get_entropy with CP0 Random
Update to commit 9c9b415c50bc298ac61412dff856eae2f54889ee [MIPS:
Reimplement get_cycles().]
On systems were for whatever reasons we can't use the cycle counter, fall
back to the c0_random register as an entropy source. It has however a
very small range that makes it suitable for random_get_entropy only and
not get_cycles.
This optimised version compiles to 8 instructions in the fast path even in
the worst case of all the conditions to check being variable (including a
MFC0 move delay slot that is only required for very old processors):
828: 8cf90000 lw t9,0(a3)
828: R_MIPS_LO16 jiffies
82c: 40057800 mfc0 a1,c0_prid
830: 3c0200ff lui v0,0xff
834: 00a21024 and v0,a1,v0
838: 1040007d beqz v0,a30 <add_interrupt_randomness+0x22c>
83c: 3c030000 lui v1,0x0
83c: R_MIPS_HI16 cpu_data
840: 40024800 mfc0 v0,c0_count
844: 00000000 nop
848: 00409021 move s2,v0
84c: 8ce20000 lw v0,0(a3)
84c: R_MIPS_LO16 jiffies
On most targets the sequence will be shorter and on some it will reduce to
a single `MFC0 <reg>,c0_count', as all MIPS architecture (i.e. non-legacy
MIPS) processors require the CP0 Count register to be present.
The only known exception that reports MIPS architecture compliance, but
contrary to that lacks CP0 Count is the Ingenic JZ4740 thingy. For broken
platforms like that this code requires cpu_has_counter to be hardcoded to
0 (i.e. no variable setting is permitted) so as not to penalise all the
other good platforms out there.
The asm barrier is required so that the compiler does not pull any
potentially costly (cold cache!) `cpu_data' variable access into the fast
path.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Cc: Theodore Ts'o <tytso@mit.edu>
Cc: John Crispin <blogic@openwrt.org>
Cc: Andrew McGregor <andrewmcgr@gmail.com>
Cc: Dave Taht <dave.taht@bufferbloat.net>
Cc: Felix Fietkau <nbd@nbd.name>
Cc: Simon Kelley <simon@thekelleys.org.uk>
Cc: Jim Gettys <jg@freedesktop.org>
Cc: David Daney <ddaney@caviumnetworks.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/6702/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2014-04-06 22:31:29 +02:00
|
|
|
BUG_ON(!__builtin_constant_p(cpu_has_counter) || cpu_has_counter);
|
2013-09-17 17:58:10 +02:00
|
|
|
switch (c->processor_id & PRID_IMP_MASK) {
|
2010-07-17 13:07:51 +02:00
|
|
|
case PRID_IMP_JZRISC:
|
|
|
|
c->cputype = CPU_JZRISC;
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED_ACCELERATED;
|
2010-07-17 13:07:51 +02:00
|
|
|
__cpu_name[cpu] = "Ingenic JZRISC";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
panic("Unknown Ingenic Processor ID!");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-11 08:34:58 +02:00
|
|
|
static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu)
|
|
|
|
{
|
|
|
|
decode_configs(c);
|
|
|
|
|
2013-09-17 17:58:10 +02:00
|
|
|
if ((c->processor_id & PRID_IMP_MASK) == PRID_IMP_NETLOGIC_AU13XX) {
|
2011-11-01 20:03:30 +01:00
|
|
|
c->cputype = CPU_ALCHEMY;
|
|
|
|
__cpu_name[cpu] = "Au1300";
|
|
|
|
/* following stuff is not for Alchemy */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-01-22 12:59:30 +01:00
|
|
|
c->options = (MIPS_CPU_TLB |
|
|
|
|
MIPS_CPU_4KEX |
|
2011-05-11 08:34:58 +02:00
|
|
|
MIPS_CPU_COUNTER |
|
2013-01-22 12:59:30 +01:00
|
|
|
MIPS_CPU_DIVEC |
|
|
|
|
MIPS_CPU_WATCH |
|
|
|
|
MIPS_CPU_EJTAG |
|
2011-05-11 08:34:58 +02:00
|
|
|
MIPS_CPU_LLSC);
|
|
|
|
|
2013-09-17 17:58:10 +02:00
|
|
|
switch (c->processor_id & PRID_IMP_MASK) {
|
2013-08-11 11:13:54 +02:00
|
|
|
case PRID_IMP_NETLOGIC_XLP2XX:
|
2013-12-21 12:22:20 +01:00
|
|
|
case PRID_IMP_NETLOGIC_XLP9XX:
|
2014-04-29 16:37:53 +02:00
|
|
|
case PRID_IMP_NETLOGIC_XLP5XX:
|
2013-08-11 11:13:54 +02:00
|
|
|
c->cputype = CPU_XLP;
|
|
|
|
__cpu_name[cpu] = "Broadcom XLPII";
|
|
|
|
break;
|
|
|
|
|
2011-11-16 01:21:29 +01:00
|
|
|
case PRID_IMP_NETLOGIC_XLP8XX:
|
|
|
|
case PRID_IMP_NETLOGIC_XLP3XX:
|
2011-11-16 01:21:20 +01:00
|
|
|
c->cputype = CPU_XLP;
|
|
|
|
__cpu_name[cpu] = "Netlogic XLP";
|
|
|
|
break;
|
|
|
|
|
2011-05-11 08:34:58 +02:00
|
|
|
case PRID_IMP_NETLOGIC_XLR732:
|
|
|
|
case PRID_IMP_NETLOGIC_XLR716:
|
|
|
|
case PRID_IMP_NETLOGIC_XLR532:
|
|
|
|
case PRID_IMP_NETLOGIC_XLR308:
|
|
|
|
case PRID_IMP_NETLOGIC_XLR532C:
|
|
|
|
case PRID_IMP_NETLOGIC_XLR516C:
|
|
|
|
case PRID_IMP_NETLOGIC_XLR508C:
|
|
|
|
case PRID_IMP_NETLOGIC_XLR308C:
|
|
|
|
c->cputype = CPU_XLR;
|
|
|
|
__cpu_name[cpu] = "Netlogic XLR";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PRID_IMP_NETLOGIC_XLS608:
|
|
|
|
case PRID_IMP_NETLOGIC_XLS408:
|
|
|
|
case PRID_IMP_NETLOGIC_XLS404:
|
|
|
|
case PRID_IMP_NETLOGIC_XLS208:
|
|
|
|
case PRID_IMP_NETLOGIC_XLS204:
|
|
|
|
case PRID_IMP_NETLOGIC_XLS108:
|
|
|
|
case PRID_IMP_NETLOGIC_XLS104:
|
|
|
|
case PRID_IMP_NETLOGIC_XLS616B:
|
|
|
|
case PRID_IMP_NETLOGIC_XLS608B:
|
|
|
|
case PRID_IMP_NETLOGIC_XLS416B:
|
|
|
|
case PRID_IMP_NETLOGIC_XLS412B:
|
|
|
|
case PRID_IMP_NETLOGIC_XLS408B:
|
|
|
|
case PRID_IMP_NETLOGIC_XLS404B:
|
|
|
|
c->cputype = CPU_XLR;
|
|
|
|
__cpu_name[cpu] = "Netlogic XLS";
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2011-11-16 01:21:20 +01:00
|
|
|
pr_info("Unknown Netlogic chip id [%02x]!\n",
|
2011-05-11 08:34:58 +02:00
|
|
|
c->processor_id);
|
|
|
|
c->cputype = CPU_XLR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-11-16 01:21:20 +01:00
|
|
|
if (c->cputype == CPU_XLP) {
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_M64R2);
|
2011-11-16 01:21:20 +01:00
|
|
|
c->options |= (MIPS_CPU_FPU | MIPS_CPU_ULRI | MIPS_CPU_MCHECK);
|
|
|
|
/* This will be updated again after all threads are woken up */
|
|
|
|
c->tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1;
|
|
|
|
} else {
|
2012-12-07 05:31:36 +01:00
|
|
|
set_isa(c, MIPS_CPU_ISA_M64R1);
|
2011-11-16 01:21:20 +01:00
|
|
|
c->tlbsize = ((read_c0_config1() >> 25) & 0x3f) + 1;
|
|
|
|
}
|
2013-06-11 16:41:35 +02:00
|
|
|
c->kscratch_mask = 0xf;
|
2011-05-11 08:34:58 +02:00
|
|
|
}
|
|
|
|
|
2010-10-14 20:32:33 +02:00
|
|
|
#ifdef CONFIG_64BIT
|
|
|
|
/* For use by uaccess.h */
|
|
|
|
u64 __ua_limit;
|
|
|
|
EXPORT_SYMBOL(__ua_limit);
|
|
|
|
#endif
|
|
|
|
|
2007-10-12 00:46:17 +02:00
|
|
|
const char *__cpu_name[NR_CPUS];
|
2010-01-29 01:52:12 +01:00
|
|
|
const char *__elf_platform;
|
2007-10-12 00:46:17 +02:00
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 15:38:59 +02:00
|
|
|
void cpu_probe(void)
|
2005-04-17 00:20:36 +02:00
|
|
|
{
|
|
|
|
struct cpuinfo_mips *c = ¤t_cpu_data;
|
2007-10-12 00:46:17 +02:00
|
|
|
unsigned int cpu = smp_processor_id();
|
2005-04-17 00:20:36 +02:00
|
|
|
|
2013-01-22 12:59:30 +01:00
|
|
|
c->processor_id = PRID_IMP_UNKNOWN;
|
2005-04-17 00:20:36 +02:00
|
|
|
c->fpu_id = FPIR_IMP_NONE;
|
|
|
|
c->cputype = CPU_UNKNOWN;
|
2014-07-18 11:51:32 +02:00
|
|
|
c->writecombine = _CACHE_UNCACHED;
|
2005-04-17 00:20:36 +02:00
|
|
|
|
2015-04-04 00:27:48 +02:00
|
|
|
c->fpu_csr31 = FPU_CSR_RN;
|
|
|
|
c->fpu_msk31 = FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
|
|
|
|
|
2005-04-17 00:20:36 +02:00
|
|
|
c->processor_id = read_c0_prid();
|
2013-09-17 17:58:10 +02:00
|
|
|
switch (c->processor_id & PRID_COMP_MASK) {
|
2005-04-17 00:20:36 +02:00
|
|
|
case PRID_COMP_LEGACY:
|
2008-10-30 14:38:45 +01:00
|
|
|
cpu_probe_legacy(c, cpu);
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
|
|
|
case PRID_COMP_MIPS:
|
2008-10-30 14:38:45 +01:00
|
|
|
cpu_probe_mips(c, cpu);
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
|
|
|
case PRID_COMP_ALCHEMY:
|
2008-10-30 14:38:45 +01:00
|
|
|
cpu_probe_alchemy(c, cpu);
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
|
|
|
case PRID_COMP_SIBYTE:
|
2008-10-30 14:38:45 +01:00
|
|
|
cpu_probe_sibyte(c, cpu);
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
2007-09-25 15:40:12 +02:00
|
|
|
case PRID_COMP_BROADCOM:
|
2008-10-30 14:38:45 +01:00
|
|
|
cpu_probe_broadcom(c, cpu);
|
2007-09-25 15:40:12 +02:00
|
|
|
break;
|
2005-04-17 00:20:36 +02:00
|
|
|
case PRID_COMP_SANDCRAFT:
|
2008-10-30 14:38:45 +01:00
|
|
|
cpu_probe_sandcraft(c, cpu);
|
2005-04-17 00:20:36 +02:00
|
|
|
break;
|
2008-03-06 10:07:18 +01:00
|
|
|
case PRID_COMP_NXP:
|
2008-10-30 14:38:45 +01:00
|
|
|
cpu_probe_nxp(c, cpu);
|
2006-03-11 09:18:41 +01:00
|
|
|
break;
|
2008-12-12 00:33:26 +01:00
|
|
|
case PRID_COMP_CAVIUM:
|
|
|
|
cpu_probe_cavium(c, cpu);
|
|
|
|
break;
|
2016-03-03 02:45:09 +01:00
|
|
|
case PRID_COMP_LOONGSON:
|
|
|
|
cpu_probe_loongson(c, cpu);
|
|
|
|
break;
|
2015-05-24 17:11:14 +02:00
|
|
|
case PRID_COMP_INGENIC_D0:
|
|
|
|
case PRID_COMP_INGENIC_D1:
|
|
|
|
case PRID_COMP_INGENIC_E1:
|
2010-07-17 13:07:51 +02:00
|
|
|
cpu_probe_ingenic(c, cpu);
|
|
|
|
break;
|
2011-05-11 08:34:58 +02:00
|
|
|
case PRID_COMP_NETLOGIC:
|
|
|
|
cpu_probe_netlogic(c, cpu);
|
|
|
|
break;
|
2005-04-17 00:20:36 +02:00
|
|
|
}
|
2007-10-08 16:11:51 +02:00
|
|
|
|
2008-10-30 14:38:45 +01:00
|
|
|
BUG_ON(!__cpu_name[cpu]);
|
|
|
|
BUG_ON(c->cputype == CPU_UNKNOWN);
|
|
|
|
|
2007-10-08 16:11:51 +02:00
|
|
|
/*
|
|
|
|
* Platform code can force the cpu type to optimize code
|
|
|
|
* generation. In that case be sure the cpu type is correctly
|
|
|
|
* manually setup otherwise it could trigger some nasty bugs.
|
|
|
|
*/
|
|
|
|
BUG_ON(current_cpu_type() != c->cputype);
|
|
|
|
|
2016-02-09 21:55:52 +01:00
|
|
|
if (cpu_has_rixi) {
|
|
|
|
/* Enable the RIXI exceptions */
|
|
|
|
set_c0_pagegrain(PG_IEC);
|
|
|
|
back_to_back_c0_hazard();
|
|
|
|
/* Verify the IEC bit is set */
|
|
|
|
if (read_c0_pagegrain() & PG_IEC)
|
|
|
|
c->options |= MIPS_CPU_RIXIEX;
|
|
|
|
}
|
|
|
|
|
2010-05-02 23:43:52 +02:00
|
|
|
if (mips_fpu_disabled)
|
|
|
|
c->options &= ~MIPS_CPU_FPU;
|
|
|
|
|
|
|
|
if (mips_dsp_disabled)
|
2012-08-03 17:26:04 +02:00
|
|
|
c->ases &= ~(MIPS_ASE_DSP | MIPS_ASE_DSP2P);
|
2010-05-02 23:43:52 +02:00
|
|
|
|
2014-07-14 13:46:13 +02:00
|
|
|
if (mips_htw_disabled) {
|
|
|
|
c->options &= ~MIPS_CPU_HTW;
|
|
|
|
write_c0_pwctl(read_c0_pwctl() &
|
|
|
|
~(1 << MIPS_PWCTL_PWEN_SHIFT));
|
|
|
|
}
|
|
|
|
|
2015-04-04 00:27:54 +02:00
|
|
|
if (c->options & MIPS_CPU_FPU)
|
|
|
|
cpu_set_fpu_opts(c);
|
|
|
|
else
|
|
|
|
cpu_set_nofpu_opts(c);
|
2007-10-12 00:46:17 +02:00
|
|
|
|
2015-06-03 00:21:33 +02:00
|
|
|
if (cpu_has_bp_ghist)
|
|
|
|
write_c0_r10k_diag(read_c0_r10k_diag() |
|
|
|
|
R10K_DIAG_E_GHIST);
|
|
|
|
|
2014-11-13 14:51:51 +01:00
|
|
|
if (cpu_has_mips_r2_r6) {
|
2007-11-08 19:02:29 +01:00
|
|
|
c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
|
2012-07-13 22:44:51 +02:00
|
|
|
/* R2 has Performance Counter Interrupt indicator */
|
|
|
|
c->options |= MIPS_CPU_PCI;
|
|
|
|
}
|
2007-11-08 19:02:29 +01:00
|
|
|
else
|
|
|
|
c->srsets = 1;
|
2010-02-02 17:52:20 +01:00
|
|
|
|
2015-07-27 21:58:24 +02:00
|
|
|
if (cpu_has_mips_r6)
|
|
|
|
elf_hwcap |= HWCAP_MIPS_R6;
|
|
|
|
|
2014-01-28 15:28:43 +01:00
|
|
|
if (cpu_has_msa) {
|
2014-01-27 16:23:10 +01:00
|
|
|
c->msa_id = cpu_get_msa_id();
|
2014-01-28 15:28:43 +01:00
|
|
|
WARN(c->msa_id & MSA_IR_WRPF,
|
|
|
|
"Vector register partitioning unimplemented!");
|
2015-07-27 21:58:25 +02:00
|
|
|
elf_hwcap |= HWCAP_MIPS_MSA;
|
2014-01-28 15:28:43 +01:00
|
|
|
}
|
2014-01-27 16:23:10 +01:00
|
|
|
|
MIPS: Add probing & defs for VZ & guest features
Add a few new cpu-features.h definitions for VZ sub-features, namely the
existence of the CP0_GuestCtl0Ext, CP0_GuestCtl1, and CP0_GuestCtl2
registers, and support for GuestID to dialias TLB entries belonging to
different guests.
Also add certain features present in the guest, with the naming scheme
cpu_guest_has_*. These are added separately to the main options bitfield
since they generally parallel similar features in the root context. A
few of these (FPU, MSA, watchpoints, perf counters, CP0_[X]ContextConfig
registers, MAAR registers, and probably others in future) can be
dynamically configured in the guest context, for which the
cpu_guest_has_dyn_* macros are added.
[ralf@linux-mips.org: Resolve merge conflict.]
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/13231/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2016-05-11 16:50:30 +02:00
|
|
|
if (cpu_has_vz)
|
|
|
|
cpu_probe_vz(c);
|
|
|
|
|
2010-02-02 17:52:20 +01:00
|
|
|
cpu_probe_vmbits(c);
|
2010-10-14 20:32:33 +02:00
|
|
|
|
|
|
|
#ifdef CONFIG_64BIT
|
|
|
|
if (cpu == 0)
|
|
|
|
__ua_limit = ~((1ull << cpu_vmbits) - 1);
|
|
|
|
#endif
|
2005-04-17 00:20:36 +02:00
|
|
|
}
|
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 15:38:59 +02:00
|
|
|
void cpu_report(void)
|
2005-04-17 00:20:36 +02:00
|
|
|
{
|
|
|
|
struct cpuinfo_mips *c = ¤t_cpu_data;
|
|
|
|
|
2013-10-07 11:43:32 +02:00
|
|
|
pr_info("CPU%d revision is: %08x (%s)\n",
|
|
|
|
smp_processor_id(), c->processor_id, cpu_name_string());
|
2005-04-17 00:20:36 +02:00
|
|
|
if (c->options & MIPS_CPU_FPU)
|
2007-10-12 00:46:17 +02:00
|
|
|
printk(KERN_INFO "FPU revision is: %08x\n", c->fpu_id);
|
2014-01-27 16:23:10 +01:00
|
|
|
if (cpu_has_msa)
|
|
|
|
pr_info("MSA revision is: %08x\n", c->msa_id);
|
2005-04-17 00:20:36 +02:00
|
|
|
}
|