aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/cputable.c72
-rw-r--r--arch/powerpc/kernel/head_64.S19
-rw-r--r--arch/powerpc/kernel/misc_32.S74
-rw-r--r--arch/powerpc/kernel/misc_64.S124
-rw-r--r--arch/powerpc/kernel/setup_32.c8
-rw-r--r--arch/powerpc/kernel/setup_64.c11
6 files changed, 88 insertions, 220 deletions
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index f23aad66a79e..6fdfaa4a82b8 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -18,6 +18,7 @@
18 18
19#include <asm/oprofile_impl.h> 19#include <asm/oprofile_impl.h>
20#include <asm/cputable.h> 20#include <asm/cputable.h>
21#include <asm/prom.h> /* for PTRRELOC on ARCH=ppc */
21 22
22struct cpu_spec* cur_cpu_spec = NULL; 23struct cpu_spec* cur_cpu_spec = NULL;
23EXPORT_SYMBOL(cur_cpu_spec); 24EXPORT_SYMBOL(cur_cpu_spec);
@@ -73,7 +74,7 @@ extern void __restore_cpu_ppc970(void);
73#define PPC_FEATURE_SPE_COMP 0 74#define PPC_FEATURE_SPE_COMP 0
74#endif 75#endif
75 76
76struct cpu_spec cpu_specs[] = { 77static struct cpu_spec cpu_specs[] = {
77#ifdef CONFIG_PPC64 78#ifdef CONFIG_PPC64
78 { /* Power3 */ 79 { /* Power3 */
79 .pvr_mask = 0xffff0000, 80 .pvr_mask = 0xffff0000,
@@ -1167,3 +1168,72 @@ struct cpu_spec cpu_specs[] = {
1167#endif /* !CLASSIC_PPC */ 1168#endif /* !CLASSIC_PPC */
1168#endif /* CONFIG_PPC32 */ 1169#endif /* CONFIG_PPC32 */
1169}; 1170};
1171
1172struct cpu_spec *identify_cpu(unsigned long offset)
1173{
1174 struct cpu_spec *s = cpu_specs;
1175 struct cpu_spec **cur = &cur_cpu_spec;
1176 unsigned int pvr = mfspr(SPRN_PVR);
1177 int i;
1178
1179 s = PTRRELOC(s);
1180 cur = PTRRELOC(cur);
1181
1182 if (*cur != NULL)
1183 return PTRRELOC(*cur);
1184
1185 for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++)
1186 if ((pvr & s->pvr_mask) == s->pvr_value) {
1187 *cur = cpu_specs + i;
1188#ifdef CONFIG_PPC64
1189 /* ppc64 expects identify_cpu to also call setup_cpu
1190 * for that processor. I will consolidate that at a
1191 * later time, for now, just use our friend #ifdef.
1192 * we also don't need to PTRRELOC the function pointer
1193 * on ppc64 as we are running at 0 in real mode.
1194 */
1195 if (s->cpu_setup) {
1196 s->cpu_setup(offset, s);
1197 }
1198#endif /* CONFIG_PPC64 */
1199 return s;
1200 }
1201 BUG();
1202 return NULL;
1203}
1204
1205void do_feature_fixups(unsigned long offset, unsigned long value,
1206 void *fixup_start, void *fixup_end)
1207{
1208 struct fixup_entry {
1209 unsigned long mask;
1210 unsigned long value;
1211 unsigned int *start;
1212 unsigned int *end;
1213 } *fcur, *fend;
1214
1215 fcur = fixup_start;
1216 fend = fixup_end;
1217
1218 for (; fcur < fend; fcur++) {
1219 unsigned int *pstart, *pend, *p;
1220
1221 if ((value & fcur->mask) == fcur->value)
1222 continue;
1223
1224 /* These PTRRELOCs will disappear once the new scheme for
1225 * modules and vdso is implemented
1226 */
1227 pstart = PTRRELOC(fcur->start);
1228 pend = PTRRELOC(fcur->end);
1229
1230 for (p = pstart; p < pend; p++) {
1231 *p = 0x60000000u;
1232 asm volatile ("dcbst 0, %0" : : "r" (p));
1233 }
1234 asm volatile ("sync" : : : "memory");
1235 for (p = pstart; p < pend; p++)
1236 asm volatile ("icbi 0,%0" : : "r" (p));
1237 asm volatile ("sync; isync" : : : "memory");
1238 }
1239}
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 645c7f10fb28..f12e3c55520d 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -1580,11 +1580,6 @@ _STATIC(__start_initialization_iSeries)
1580 li r0,0 1580 li r0,0
1581 stdu r0,-STACK_FRAME_OVERHEAD(r1) 1581 stdu r0,-STACK_FRAME_OVERHEAD(r1)
1582 1582
1583 LOAD_REG_IMMEDIATE(r3,cpu_specs)
1584 LOAD_REG_IMMEDIATE(r4,cur_cpu_spec)
1585 li r5,0
1586 bl .identify_cpu
1587
1588 LOAD_REG_IMMEDIATE(r2,__toc_start) 1583 LOAD_REG_IMMEDIATE(r2,__toc_start)
1589 addi r2,r2,0x4000 1584 addi r2,r2,0x4000
1590 addi r2,r2,0x4000 1585 addi r2,r2,0x4000
@@ -1964,13 +1959,6 @@ _STATIC(start_here_multiplatform)
1964 addi r2,r2,0x4000 1959 addi r2,r2,0x4000
1965 add r2,r2,r26 1960 add r2,r2,r26
1966 1961
1967 LOAD_REG_IMMEDIATE(r3, cpu_specs)
1968 add r3,r3,r26
1969 LOAD_REG_IMMEDIATE(r4,cur_cpu_spec)
1970 add r4,r4,r26
1971 mr r5,r26
1972 bl .identify_cpu
1973
1974 /* Do very early kernel initializations, including initial hash table, 1962 /* Do very early kernel initializations, including initial hash table,
1975 * stab and slb setup before we turn on relocation. */ 1963 * stab and slb setup before we turn on relocation. */
1976 1964
@@ -2000,13 +1988,6 @@ _STATIC(start_here_common)
2000 li r0,0 1988 li r0,0
2001 stdu r0,-STACK_FRAME_OVERHEAD(r1) 1989 stdu r0,-STACK_FRAME_OVERHEAD(r1)
2002 1990
2003 /* Apply the CPUs-specific fixups (nop out sections not relevant
2004 * to this CPU
2005 */
2006 li r3,0
2007 bl .do_cpu_ftr_fixups
2008 bl .do_fw_ftr_fixups
2009
2010 /* ptr to current */ 1991 /* ptr to current */
2011 LOAD_REG_IMMEDIATE(r4, init_task) 1992 LOAD_REG_IMMEDIATE(r4, init_task)
2012 std r4,PACACURRENT(r13) 1993 std r4,PACACURRENT(r13)
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 88fd73fdf048..412bea3cf813 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -102,80 +102,6 @@ _GLOBAL(reloc_got2)
102 blr 102 blr
103 103
104/* 104/*
105 * identify_cpu,
106 * called with r3 = data offset and r4 = CPU number
107 * doesn't change r3
108 */
109_GLOBAL(identify_cpu)
110 addis r8,r3,cpu_specs@ha
111 addi r8,r8,cpu_specs@l
112 mfpvr r7
1131:
114 lwz r5,CPU_SPEC_PVR_MASK(r8)
115 and r5,r5,r7
116 lwz r6,CPU_SPEC_PVR_VALUE(r8)
117 cmplw 0,r6,r5
118 beq 1f
119 addi r8,r8,CPU_SPEC_ENTRY_SIZE
120 b 1b
1211:
122 addis r6,r3,cur_cpu_spec@ha
123 addi r6,r6,cur_cpu_spec@l
124 sub r8,r8,r3
125 stw r8,0(r6)
126 blr
127
128/*
129 * do_cpu_ftr_fixups - goes through the list of CPU feature fixups
130 * and writes nop's over sections of code that don't apply for this cpu.
131 * r3 = data offset (not changed)
132 */
133_GLOBAL(do_cpu_ftr_fixups)
134 /* Get CPU 0 features */
135 addis r6,r3,cur_cpu_spec@ha
136 addi r6,r6,cur_cpu_spec@l
137 lwz r4,0(r6)
138 add r4,r4,r3
139 lwz r4,CPU_SPEC_FEATURES(r4)
140
141 /* Get the fixup table */
142 addis r6,r3,__start___ftr_fixup@ha
143 addi r6,r6,__start___ftr_fixup@l
144 addis r7,r3,__stop___ftr_fixup@ha
145 addi r7,r7,__stop___ftr_fixup@l
146
147 /* Do the fixup */
1481: cmplw 0,r6,r7
149 bgelr
150 addi r6,r6,16
151 lwz r8,-16(r6) /* mask */
152 and r8,r8,r4
153 lwz r9,-12(r6) /* value */
154 cmplw 0,r8,r9
155 beq 1b
156 lwz r8,-8(r6) /* section begin */
157 lwz r9,-4(r6) /* section end */
158 subf. r9,r8,r9
159 beq 1b
160 /* write nops over the section of code */
161 /* todo: if large section, add a branch at the start of it */
162 srwi r9,r9,2
163 mtctr r9
164 add r8,r8,r3
165 lis r0,0x60000000@h /* nop */
1663: stw r0,0(r8)
167 andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l
168 beq 2f
169 dcbst 0,r8 /* suboptimal, but simpler */
170 sync
171 icbi 0,r8
1722: addi r8,r8,4
173 bdnz 3b
174 sync /* additional sync needed on g4 */
175 isync
176 b 1b
177
178/*
179 * call_setup_cpu - call the setup_cpu function for this cpu 105 * call_setup_cpu - call the setup_cpu function for this cpu
180 * r3 = data offset, r24 = cpu number 106 * r3 = data offset, r24 = cpu number
181 * 107 *
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index c70e20708a1f..21fd2c662a99 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -246,130 +246,6 @@ _GLOBAL(__flush_dcache_icache)
246 isync 246 isync
247 blr 247 blr
248 248
249/*
250 * identify_cpu and calls setup_cpu
251 * In: r3 = base of the cpu_specs array
252 * r4 = address of cur_cpu_spec
253 * r5 = relocation offset
254 */
255_GLOBAL(identify_cpu)
256 mfpvr r7
2571:
258 lwz r8,CPU_SPEC_PVR_MASK(r3)
259 and r8,r8,r7
260 lwz r9,CPU_SPEC_PVR_VALUE(r3)
261 cmplw 0,r9,r8
262 beq 1f
263 addi r3,r3,CPU_SPEC_ENTRY_SIZE
264 b 1b
2651:
266 sub r0,r3,r5
267 std r0,0(r4)
268 ld r4,CPU_SPEC_SETUP(r3)
269 cmpdi 0,r4,0
270 add r4,r4,r5
271 beqlr
272 ld r4,0(r4)
273 add r4,r4,r5
274 mtctr r4
275 /* Calling convention for cpu setup is r3=offset, r4=cur_cpu_spec */
276 mr r4,r3
277 mr r3,r5
278 bctr
279
280/*
281 * do_cpu_ftr_fixups - goes through the list of CPU feature fixups
282 * and writes nop's over sections of code that don't apply for this cpu.
283 * r3 = data offset (not changed)
284 */
285_GLOBAL(do_cpu_ftr_fixups)
286 /* Get CPU 0 features */
287 LOAD_REG_IMMEDIATE(r6,cur_cpu_spec)
288 sub r6,r6,r3
289 ld r4,0(r6)
290 sub r4,r4,r3
291 ld r4,CPU_SPEC_FEATURES(r4)
292 /* Get the fixup table */
293 LOAD_REG_IMMEDIATE(r6,__start___ftr_fixup)
294 sub r6,r6,r3
295 LOAD_REG_IMMEDIATE(r7,__stop___ftr_fixup)
296 sub r7,r7,r3
297 /* Do the fixup */
2981: cmpld r6,r7
299 bgelr
300 addi r6,r6,32
301 ld r8,-32(r6) /* mask */
302 and r8,r8,r4
303 ld r9,-24(r6) /* value */
304 cmpld r8,r9
305 beq 1b
306 ld r8,-16(r6) /* section begin */
307 ld r9,-8(r6) /* section end */
308 subf. r9,r8,r9
309 beq 1b
310 /* write nops over the section of code */
311 /* todo: if large section, add a branch at the start of it */
312 srwi r9,r9,2
313 mtctr r9
314 sub r8,r8,r3
315 lis r0,0x60000000@h /* nop */
3163: stw r0,0(r8)
317 andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l
318 beq 2f
319 dcbst 0,r8 /* suboptimal, but simpler */
320 sync
321 icbi 0,r8
3222: addi r8,r8,4
323 bdnz 3b
324 sync /* additional sync needed on g4 */
325 isync
326 b 1b
327
328/*
329 * do_fw_ftr_fixups - goes through the list of firmware feature fixups
330 * and writes nop's over sections of code that don't apply for this firmware.
331 * r3 = data offset (not changed)
332 */
333_GLOBAL(do_fw_ftr_fixups)
334 /* Get firmware features */
335 LOAD_REG_IMMEDIATE(r6,powerpc_firmware_features)
336 sub r6,r6,r3
337 ld r4,0(r6)
338 /* Get the fixup table */
339 LOAD_REG_IMMEDIATE(r6,__start___fw_ftr_fixup)
340 sub r6,r6,r3
341 LOAD_REG_IMMEDIATE(r7,__stop___fw_ftr_fixup)
342 sub r7,r7,r3
343 /* Do the fixup */
3441: cmpld r6,r7
345 bgelr
346 addi r6,r6,32
347 ld r8,-32(r6) /* mask */
348 and r8,r8,r4
349 ld r9,-24(r6) /* value */
350 cmpld r8,r9
351 beq 1b
352 ld r8,-16(r6) /* section begin */
353 ld r9,-8(r6) /* section end */
354 subf. r9,r8,r9
355 beq 1b
356 /* write nops over the section of code */
357 /* todo: if large section, add a branch at the start of it */
358 srwi r9,r9,2
359 mtctr r9
360 sub r8,r8,r3
361 lis r0,0x60000000@h /* nop */
3623: stw r0,0(r8)
363BEGIN_FTR_SECTION
364 dcbst 0,r8 /* suboptimal, but simpler */
365 sync
366 icbi 0,r8
367END_FTR_SECTION_IFSET(CPU_FTR_SPLIT_ID_CACHE)
368 addi r8,r8,4
369 bdnz 3b
370 sync /* additional sync needed on g4 */
371 isync
372 b 1b
373 249
374#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) 250#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
375/* 251/*
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 191d0ab09222..769e511783b0 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -91,6 +91,7 @@ int ucache_bsize;
91unsigned long __init early_init(unsigned long dt_ptr) 91unsigned long __init early_init(unsigned long dt_ptr)
92{ 92{
93 unsigned long offset = reloc_offset(); 93 unsigned long offset = reloc_offset();
94 struct cpu_spec *spec;
94 95
95 /* First zero the BSS -- use memset_io, some platforms don't have 96 /* First zero the BSS -- use memset_io, some platforms don't have
96 * caches on yet */ 97 * caches on yet */
@@ -100,8 +101,11 @@ unsigned long __init early_init(unsigned long dt_ptr)
100 * Identify the CPU type and fix up code sections 101 * Identify the CPU type and fix up code sections
101 * that depend on which cpu we have. 102 * that depend on which cpu we have.
102 */ 103 */
103 identify_cpu(offset, 0); 104 spec = identify_cpu(offset);
104 do_cpu_ftr_fixups(offset); 105
106 do_feature_fixups(offset, spec->cpu_features,
107 PTRRELOC(&__start___ftr_fixup),
108 PTRRELOC(&__stop___ftr_fixup));
105 109
106 return KERNELBASE + offset; 110 return KERNELBASE + offset;
107} 111}
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 4b2e32eab9dc..1969b5686eee 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -170,6 +170,9 @@ void __init setup_paca(int cpu)
170 170
171void __init early_setup(unsigned long dt_ptr) 171void __init early_setup(unsigned long dt_ptr)
172{ 172{
173 /* Identify CPU type */
174 identify_cpu(0);
175
173 /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ 176 /* Assume we're on cpu 0 for now. Don't write to the paca yet! */
174 setup_paca(0); 177 setup_paca(0);
175 178
@@ -348,6 +351,14 @@ void __init setup_system(void)
348{ 351{
349 DBG(" -> setup_system()\n"); 352 DBG(" -> setup_system()\n");
350 353
354 /* Apply the CPUs-specific and firmware specific fixups to kernel
355 * text (nop out sections not relevant to this CPU or this firmware)
356 */
357 do_feature_fixups(0, cur_cpu_spec->cpu_features,
358 &__start___ftr_fixup, &__stop___ftr_fixup);
359 do_feature_fixups(0, powerpc_firmware_features,
360 &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
361
351 /* 362 /*
352 * Unflatten the device-tree passed by prom_init or kexec 363 * Unflatten the device-tree passed by prom_init or kexec
353 */ 364 */