Skip to content

Commit 90c68c6

Browse files
committed
MIPS: cpu-probe: introduce exclusive R3k CPU probe
Running a kernel on a R3k of machine definitly will never see one of the newer CPU cores. And since R3k system usually are low on memory we could save quite some kbytes: text data bss dec hex filename 15070 88 32 15190 3b56 arch/mips/kernel/cpu-probe.o 844 4 16 864 360 arch/mips/kernel/cpu-r3k-probe.o Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
1 parent a616c06 commit 90c68c6

2 files changed

Lines changed: 178 additions & 1 deletion

File tree

arch/mips/kernel/Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@
55

66
extra-y := head.o vmlinux.lds
77

8-
obj-y += cmpxchg.o cpu-probe.o branch.o elf.o entry.o genex.o idle.o irq.o \
8+
obj-y += branch.o cmpxchg.o elf.o entry.o genex.o idle.o irq.o \
99
process.o prom.o ptrace.o reset.o setup.o signal.o \
1010
syscall.o time.o topology.o traps.o unaligned.o watch.o \
1111
vdso.o cacheinfo.o
1212

13+
ifdef CONFIG_CPU_R3K_TLB
14+
obj-y += cpu-r3k-probe.o
15+
else
16+
obj-y += cpu-probe.o
17+
endif
18+
1319
ifdef CONFIG_FUNCTION_TRACER
1420
CFLAGS_REMOVE_ftrace.o = -pg
1521
CFLAGS_REMOVE_early_printk.o = -pg

arch/mips/kernel/cpu-r3k-probe.c

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/*
3+
* Processor capabilities determination functions.
4+
*
5+
* Copyright (C) xxxx the Anonymous
6+
* Copyright (C) 1994 - 2006 Ralf Baechle
7+
* Copyright (C) 2003, 2004 Maciej W. Rozycki
8+
* Copyright (C) 2001, 2004, 2011, 2012 MIPS Technologies, Inc.
9+
*/
10+
#include <linux/init.h>
11+
#include <linux/kernel.h>
12+
#include <linux/ptrace.h>
13+
#include <linux/smp.h>
14+
#include <linux/stddef.h>
15+
#include <linux/export.h>
16+
17+
#include <asm/bugs.h>
18+
#include <asm/cpu.h>
19+
#include <asm/cpu-features.h>
20+
#include <asm/cpu-type.h>
21+
#include <asm/fpu.h>
22+
#include <asm/mipsregs.h>
23+
#include <asm/elf.h>
24+
25+
#include "fpu-probe.h"
26+
27+
/* Hardware capabilities */
28+
unsigned int elf_hwcap __read_mostly;
29+
EXPORT_SYMBOL_GPL(elf_hwcap);
30+
31+
void __init check_bugs32(void)
32+
{
33+
34+
}
35+
36+
/*
37+
* Probe whether cpu has config register by trying to play with
38+
* alternate cache bit and see whether it matters.
39+
* It's used by cpu_probe to distinguish between R3000A and R3081.
40+
*/
41+
static inline int cpu_has_confreg(void)
42+
{
43+
#ifdef CONFIG_CPU_R3000
44+
extern unsigned long r3k_cache_size(unsigned long);
45+
unsigned long size1, size2;
46+
unsigned long cfg = read_c0_conf();
47+
48+
size1 = r3k_cache_size(ST0_ISC);
49+
write_c0_conf(cfg ^ R30XX_CONF_AC);
50+
size2 = r3k_cache_size(ST0_ISC);
51+
write_c0_conf(cfg);
52+
return size1 != size2;
53+
#else
54+
return 0;
55+
#endif
56+
}
57+
58+
static inline void set_elf_platform(int cpu, const char *plat)
59+
{
60+
if (cpu == 0)
61+
__elf_platform = plat;
62+
}
63+
64+
const char *__cpu_name[NR_CPUS];
65+
const char *__elf_platform;
66+
const char *__elf_base_platform;
67+
68+
void cpu_probe(void)
69+
{
70+
struct cpuinfo_mips *c = &current_cpu_data;
71+
unsigned int cpu = smp_processor_id();
72+
73+
/*
74+
* Set a default elf platform, cpu probe may later
75+
* overwrite it with a more precise value
76+
*/
77+
set_elf_platform(cpu, "mips");
78+
79+
c->processor_id = PRID_IMP_UNKNOWN;
80+
c->fpu_id = FPIR_IMP_NONE;
81+
c->cputype = CPU_UNKNOWN;
82+
c->writecombine = _CACHE_UNCACHED;
83+
84+
c->fpu_csr31 = FPU_CSR_RN;
85+
c->fpu_msk31 = FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008 |
86+
FPU_CSR_CONDX | FPU_CSR_FS;
87+
88+
c->srsets = 1;
89+
90+
c->processor_id = read_c0_prid();
91+
switch (c->processor_id & (PRID_COMP_MASK | PRID_IMP_MASK)) {
92+
case PRID_COMP_LEGACY | PRID_IMP_R2000:
93+
c->cputype = CPU_R2000;
94+
__cpu_name[cpu] = "R2000";
95+
c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
96+
MIPS_CPU_NOFPUEX;
97+
if (__cpu_has_fpu())
98+
c->options |= MIPS_CPU_FPU;
99+
c->tlbsize = 64;
100+
break;
101+
case PRID_COMP_LEGACY | PRID_IMP_R3000:
102+
if ((c->processor_id & PRID_REV_MASK) == PRID_REV_R3000A) {
103+
if (cpu_has_confreg()) {
104+
c->cputype = CPU_R3081E;
105+
__cpu_name[cpu] = "R3081";
106+
} else {
107+
c->cputype = CPU_R3000A;
108+
__cpu_name[cpu] = "R3000A";
109+
}
110+
} else {
111+
c->cputype = CPU_R3000;
112+
__cpu_name[cpu] = "R3000";
113+
}
114+
c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
115+
MIPS_CPU_NOFPUEX;
116+
if (__cpu_has_fpu())
117+
c->options |= MIPS_CPU_FPU;
118+
c->tlbsize = 64;
119+
break;
120+
case PRID_COMP_LEGACY | PRID_IMP_TX39:
121+
c->options = MIPS_CPU_TLB | MIPS_CPU_TX39_CACHE;
122+
123+
if ((c->processor_id & 0xf0) == (PRID_REV_TX3927 & 0xf0)) {
124+
c->cputype = CPU_TX3927;
125+
__cpu_name[cpu] = "TX3927";
126+
c->tlbsize = 64;
127+
} else {
128+
switch (c->processor_id & PRID_REV_MASK) {
129+
case PRID_REV_TX3912:
130+
c->cputype = CPU_TX3912;
131+
__cpu_name[cpu] = "TX3912";
132+
c->tlbsize = 32;
133+
break;
134+
case PRID_REV_TX3922:
135+
c->cputype = CPU_TX3922;
136+
__cpu_name[cpu] = "TX3922";
137+
c->tlbsize = 64;
138+
break;
139+
}
140+
}
141+
break;
142+
}
143+
144+
BUG_ON(!__cpu_name[cpu]);
145+
BUG_ON(c->cputype == CPU_UNKNOWN);
146+
147+
/*
148+
* Platform code can force the cpu type to optimize code
149+
* generation. In that case be sure the cpu type is correctly
150+
* manually setup otherwise it could trigger some nasty bugs.
151+
*/
152+
BUG_ON(current_cpu_type() != c->cputype);
153+
154+
if (mips_fpu_disabled)
155+
c->options &= ~MIPS_CPU_FPU;
156+
157+
if (c->options & MIPS_CPU_FPU)
158+
cpu_set_fpu_opts(c);
159+
else
160+
cpu_set_nofpu_opts(c);
161+
}
162+
163+
void cpu_report(void)
164+
{
165+
struct cpuinfo_mips *c = &current_cpu_data;
166+
167+
pr_info("CPU%d revision is: %08x (%s)\n",
168+
smp_processor_id(), c->processor_id, cpu_name_string());
169+
if (c->options & MIPS_CPU_FPU)
170+
pr_info("FPU revision is: %08x\n", c->fpu_id);
171+
}

0 commit comments

Comments
 (0)