xref: /netbsd-src/sys/arch/arm/arm32/cpu.c (revision bf1e9b32e27832f0c493206710fb8b58a980838a)
1 /*	$NetBSD: cpu.c,v 1.58 2005/06/03 15:55:55 rearnsha Exp $	*/
2 
3 /*
4  * Copyright (c) 1995 Mark Brinicombe.
5  * Copyright (c) 1995 Brini.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by Brini.
19  * 4. The name of the company nor the name of the author may be used to
20  *    endorse or promote products derived from this software without specific
21  *    prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
24  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  * RiscBSD kernel project
36  *
37  * cpu.c
38  *
39  * Probing and configuration for the master CPU
40  *
41  * Created      : 10/10/95
42  */
43 
44 #include "opt_armfpe.h"
45 #include "opt_multiprocessor.h"
46 
47 #include <sys/param.h>
48 
49 __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.58 2005/06/03 15:55:55 rearnsha Exp $");
50 
51 #include <sys/systm.h>
52 #include <sys/malloc.h>
53 #include <sys/device.h>
54 #include <sys/proc.h>
55 #include <sys/conf.h>
56 #include <uvm/uvm_extern.h>
57 #include <machine/cpu.h>
58 
59 #include <arm/cpuconf.h>
60 #include <arm/undefined.h>
61 
62 #ifdef ARMFPE
63 #include <machine/bootconfig.h> /* For boot args */
64 #include <arm/fpe-arm/armfpe.h>
65 #endif
66 
67 char cpu_model[256];
68 
69 /* Prototypes */
70 void identify_arm_cpu(struct device *dv, struct cpu_info *);
71 
72 /*
73  * Identify the master (boot) CPU
74  */
75 
76 void
77 cpu_attach(struct device *dv)
78 {
79 	int usearmfpe;
80 
81 	usearmfpe = 1;	/* when compiled in, its enabled by default */
82 
83 	curcpu()->ci_dev = dv;
84 
85 	evcnt_attach_dynamic(&curcpu()->ci_arm700bugcount, EVCNT_TYPE_MISC,
86 	    NULL, dv->dv_xname, "arm700swibug");
87 
88 	/* Get the CPU ID from coprocessor 15 */
89 
90 	curcpu()->ci_arm_cpuid = cpu_id();
91 	curcpu()->ci_arm_cputype = curcpu()->ci_arm_cpuid & CPU_ID_CPU_MASK;
92 	curcpu()->ci_arm_cpurev =
93 	    curcpu()->ci_arm_cpuid & CPU_ID_REVISION_MASK;
94 
95 	identify_arm_cpu(dv, curcpu());
96 
97 	if (curcpu()->ci_arm_cputype == CPU_ID_SA110 &&
98 	    curcpu()->ci_arm_cpurev < 3) {
99 		aprint_normal("%s: SA-110 with bugged STM^ instruction\n",
100 		       dv->dv_xname);
101 	}
102 
103 #ifdef CPU_ARM8
104 	if ((curcpu()->ci_arm_cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM810) {
105 		int clock = arm8_clock_config(0, 0);
106 		char *fclk;
107 		aprint_normal("%s: ARM810 cp15=%02x", dv->dv_xname, clock);
108 		aprint_normal(" clock:%s", (clock & 1) ? " dynamic" : "");
109 		aprint_normal("%s", (clock & 2) ? " sync" : "");
110 		switch ((clock >> 2) & 3) {
111 		case 0:
112 			fclk = "bus clock";
113 			break;
114 		case 1:
115 			fclk = "ref clock";
116 			break;
117 		case 3:
118 			fclk = "pll";
119 			break;
120 		default:
121 			fclk = "illegal";
122 			break;
123 		}
124 		aprint_normal(" fclk source=%s\n", fclk);
125  	}
126 #endif
127 
128 #ifdef ARMFPE
129 	/*
130 	 * Ok now we test for an FPA
131 	 * At this point no floating point emulator has been installed.
132 	 * This means any FP instruction will cause undefined exception.
133 	 * We install a temporay coproc 1 handler which will modify
134 	 * undefined_test if it is called.
135 	 * We then try to read the FP status register. If undefined_test
136 	 * has been decremented then the instruction was not handled by
137 	 * an FPA so we know the FPA is missing. If undefined_test is
138 	 * still 1 then we know the instruction was handled by an FPA.
139 	 * We then remove our test handler and look at the
140 	 * FP status register for identification.
141 	 */
142 
143 	/*
144 	 * Ok if ARMFPE is defined and the boot options request the
145 	 * ARM FPE then it will be installed as the FPE.
146 	 * This is just while I work on integrating the new FPE.
147 	 * It means the new FPE gets installed if compiled int (ARMFPE
148 	 * defined) and also gives me a on/off option when I boot in
149 	 * case the new FPE is causing panics.
150 	 */
151 
152 
153 	if (boot_args)
154 		get_bootconf_option(boot_args, "armfpe",
155 		    BOOTOPT_TYPE_BOOLEAN, &usearmfpe);
156 	if (usearmfpe)
157 		initialise_arm_fpe();
158 #endif
159 }
160 
161 enum cpu_class {
162 	CPU_CLASS_NONE,
163 	CPU_CLASS_ARM2,
164 	CPU_CLASS_ARM2AS,
165 	CPU_CLASS_ARM3,
166 	CPU_CLASS_ARM6,
167 	CPU_CLASS_ARM7,
168 	CPU_CLASS_ARM7TDMI,
169 	CPU_CLASS_ARM8,
170 	CPU_CLASS_ARM9TDMI,
171 	CPU_CLASS_ARM9ES,
172 	CPU_CLASS_ARM10E,
173 	CPU_CLASS_ARM10EJ,
174 	CPU_CLASS_SA1,
175 	CPU_CLASS_XSCALE,
176 	CPU_CLASS_ARM11J
177 };
178 
179 static const char * const generic_steppings[16] = {
180 	"rev 0",	"rev 1",	"rev 2",	"rev 3",
181 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
182 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
183 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
184 };
185 
186 static const char * const sa110_steppings[16] = {
187 	"rev 0",	"step J",	"step K",	"step S",
188 	"step T",	"rev 5",	"rev 6",	"rev 7",
189 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
190 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
191 };
192 
193 static const char * const sa1100_steppings[16] = {
194 	"rev 0",	"step B",	"step C",	"rev 3",
195 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
196 	"step D",	"step E",	"rev 10"	"step G",
197 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
198 };
199 
200 static const char * const sa1110_steppings[16] = {
201 	"step A-0",	"rev 1",	"rev 2",	"rev 3",
202 	"step B-0",	"step B-1",	"step B-2",	"step B-3",
203 	"step B-4",	"step B-5",	"rev 10",	"rev 11",
204 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
205 };
206 
207 static const char * const ixp12x0_steppings[16] = {
208 	"(IXP1200 step A)",		"(IXP1200 step B)",
209 	"rev 2",			"(IXP1200 step C)",
210 	"(IXP1200 step D)",		"(IXP1240/1250 step A)",
211 	"(IXP1240 step B)",		"(IXP1250 step B)",
212 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
213 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
214 };
215 
216 static const char * const xscale_steppings[16] = {
217 	"step A-0",	"step A-1",	"step B-0",	"step C-0",
218 	"step D-0",	"rev 5",	"rev 6",	"rev 7",
219 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
220 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
221 };
222 
223 static const char * const i80321_steppings[16] = {
224 	"step A-0",	"step B-0",	"rev 2",	"rev 3",
225 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
226 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
227 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
228 };
229 
230 /* Steppings for PXA2[15]0 */
231 static const char * const pxa2x0_steppings[16] = {
232 	"step A-0",	"step A-1",	"step B-0",	"step B-1",
233 	"step B-2",	"step C-0",	"rev 6",	"rev 7",
234 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
235 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
236 };
237 
238 /* Steppings for PXA255/26x.
239  * rev 5: PXA26x B0, rev 6: PXA255 A0
240  */
241 static const char * const pxa255_steppings[16] = {
242 	"rev 0",	"rev 1",	"rev 2",	"step A-0",
243 	"rev 4",	"step B-0",	"step A-0",	"rev 7",
244 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
245 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
246 };
247 
248 static const char * const ixp425_steppings[16] = {
249 	"step 0",	"rev 1",	"rev 2",	"rev 3",
250 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
251 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
252 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
253 };
254 
255 struct cpuidtab {
256 	u_int32_t	cpuid;
257 	enum		cpu_class cpu_class;
258 	const char	*cpu_name;
259 	const char * const *cpu_steppings;
260 };
261 
262 const struct cpuidtab cpuids[] = {
263 	{ CPU_ID_ARM2,		CPU_CLASS_ARM2,		"ARM2",
264 	  generic_steppings },
265 	{ CPU_ID_ARM250,	CPU_CLASS_ARM2AS,	"ARM250",
266 	  generic_steppings },
267 
268 	{ CPU_ID_ARM3,		CPU_CLASS_ARM3,		"ARM3",
269 	  generic_steppings },
270 
271 	{ CPU_ID_ARM600,	CPU_CLASS_ARM6,		"ARM600",
272 	  generic_steppings },
273 	{ CPU_ID_ARM610,	CPU_CLASS_ARM6,		"ARM610",
274 	  generic_steppings },
275 	{ CPU_ID_ARM620,	CPU_CLASS_ARM6,		"ARM620",
276 	  generic_steppings },
277 
278 	{ CPU_ID_ARM700,	CPU_CLASS_ARM7,		"ARM700",
279 	  generic_steppings },
280 	{ CPU_ID_ARM710,	CPU_CLASS_ARM7,		"ARM710",
281 	  generic_steppings },
282 	{ CPU_ID_ARM7500,	CPU_CLASS_ARM7,		"ARM7500",
283 	  generic_steppings },
284 	{ CPU_ID_ARM710A,	CPU_CLASS_ARM7,		"ARM710a",
285 	  generic_steppings },
286 	{ CPU_ID_ARM7500FE,	CPU_CLASS_ARM7,		"ARM7500FE",
287 	  generic_steppings },
288 	{ CPU_ID_ARM710T,	CPU_CLASS_ARM7TDMI,	"ARM710T",
289 	  generic_steppings },
290 	{ CPU_ID_ARM720T,	CPU_CLASS_ARM7TDMI,	"ARM720T",
291 	  generic_steppings },
292 	{ CPU_ID_ARM740T8K,	CPU_CLASS_ARM7TDMI, "ARM740T (8 KB cache)",
293 	  generic_steppings },
294 	{ CPU_ID_ARM740T4K,	CPU_CLASS_ARM7TDMI, "ARM740T (4 KB cache)",
295 	  generic_steppings },
296 
297 	{ CPU_ID_ARM810,	CPU_CLASS_ARM8,		"ARM810",
298 	  generic_steppings },
299 
300 	{ CPU_ID_ARM920T,	CPU_CLASS_ARM9TDMI,	"ARM920T",
301 	  generic_steppings },
302 	{ CPU_ID_ARM922T,	CPU_CLASS_ARM9TDMI,	"ARM922T",
303 	  generic_steppings },
304 	{ CPU_ID_ARM940T,	CPU_CLASS_ARM9TDMI,	"ARM940T",
305 	  generic_steppings },
306 	{ CPU_ID_ARM946ES,	CPU_CLASS_ARM9ES,	"ARM946E-S",
307 	  generic_steppings },
308 	{ CPU_ID_ARM966ES,	CPU_CLASS_ARM9ES,	"ARM966E-S",
309 	  generic_steppings },
310 	{ CPU_ID_ARM966ESR1,	CPU_CLASS_ARM9ES,	"ARM966E-S",
311 	  generic_steppings },
312 	{ CPU_ID_TI925T,	CPU_CLASS_ARM9TDMI,	"TI ARM925T",
313 	  generic_steppings },
314 
315 	{ CPU_ID_ARM1020E,	CPU_CLASS_ARM10E,	"ARM1020E",
316 	  generic_steppings },
317 	{ CPU_ID_ARM1022ES,	CPU_CLASS_ARM10E,	"ARM1022E-S",
318 	  generic_steppings },
319 	{ CPU_ID_ARM1026EJS,	CPU_CLASS_ARM10EJ,	"ARM1026EJ-S",
320 	  generic_steppings },
321 
322 	{ CPU_ID_SA110,		CPU_CLASS_SA1,		"SA-110",
323 	  sa110_steppings },
324 	{ CPU_ID_SA1100,	CPU_CLASS_SA1,		"SA-1100",
325 	  sa1100_steppings },
326 	{ CPU_ID_SA1110,	CPU_CLASS_SA1,		"SA-1110",
327 	  sa1110_steppings },
328 
329 	{ CPU_ID_IXP1200,	CPU_CLASS_SA1,		"IXP1200",
330 	  ixp12x0_steppings },
331 
332 	{ CPU_ID_80200,		CPU_CLASS_XSCALE,	"i80200",
333 	  xscale_steppings },
334 
335 	{ CPU_ID_80321_400,	CPU_CLASS_XSCALE,	"i80321 400MHz",
336 	  i80321_steppings },
337 	{ CPU_ID_80321_600,	CPU_CLASS_XSCALE,	"i80321 600MHz",
338 	  i80321_steppings },
339 	{ CPU_ID_80321_400_B0,	CPU_CLASS_XSCALE,	"i80321 400MHz",
340 	  i80321_steppings },
341 	{ CPU_ID_80321_600_B0,	CPU_CLASS_XSCALE,	"i80321 600MHz",
342 	  i80321_steppings },
343 
344 	{ CPU_ID_PXA250A,	CPU_CLASS_XSCALE,	"PXA250",
345 	  pxa2x0_steppings },
346 	{ CPU_ID_PXA210A,	CPU_CLASS_XSCALE,	"PXA210",
347 	  pxa2x0_steppings },
348 	{ CPU_ID_PXA250B,	CPU_CLASS_XSCALE,	"PXA250",
349 	  pxa2x0_steppings },
350 	{ CPU_ID_PXA210B,	CPU_CLASS_XSCALE,	"PXA210",
351 	  pxa2x0_steppings },
352 	{ CPU_ID_PXA250C, 	CPU_CLASS_XSCALE,	"PXA255/26x",
353 	  pxa255_steppings },
354 	{ CPU_ID_PXA210C, 	CPU_CLASS_XSCALE,	"PXA210",
355 	  pxa2x0_steppings },
356 
357 	{ CPU_ID_IXP425_533,	CPU_CLASS_XSCALE,	"IXP425 533MHz",
358 	  ixp425_steppings },
359 	{ CPU_ID_IXP425_400,	CPU_CLASS_XSCALE,	"IXP425 400MHz",
360 	  ixp425_steppings },
361 	{ CPU_ID_IXP425_266,	CPU_CLASS_XSCALE,	"IXP425 266MHz",
362 	  ixp425_steppings },
363 
364 	{ CPU_ID_ARM1136JS,	CPU_CLASS_ARM11J,	"ARM1136J-S",
365 	  generic_steppings },
366 	{ CPU_ID_ARM1136JSR1,	CPU_CLASS_ARM11J,	"ARM1136J-S R1",
367 	  generic_steppings },
368 
369 	{ 0, CPU_CLASS_NONE, NULL, NULL }
370 };
371 
372 struct cpu_classtab {
373 	const char	*class_name;
374 	const char	*class_option;
375 };
376 
377 const struct cpu_classtab cpu_classes[] = {
378 	{ "unknown",	NULL },			/* CPU_CLASS_NONE */
379 	{ "ARM2",	"CPU_ARM2" },		/* CPU_CLASS_ARM2 */
380 	{ "ARM2as",	"CPU_ARM250" },		/* CPU_CLASS_ARM2AS */
381 	{ "ARM3",	"CPU_ARM3" },		/* CPU_CLASS_ARM3 */
382 	{ "ARM6",	"CPU_ARM6" },		/* CPU_CLASS_ARM6 */
383 	{ "ARM7",	"CPU_ARM7" },		/* CPU_CLASS_ARM7 */
384 	{ "ARM7TDMI",	"CPU_ARM7TDMI" },	/* CPU_CLASS_ARM7TDMI */
385 	{ "ARM8",	"CPU_ARM8" },		/* CPU_CLASS_ARM8 */
386 	{ "ARM9TDMI",	NULL },			/* CPU_CLASS_ARM9TDMI */
387 	{ "ARM9E-S",	NULL },			/* CPU_CLASS_ARM9ES */
388 	{ "ARM10E",	"CPU_ARM10" },		/* CPU_CLASS_ARM10E */
389 	{ "ARM10EJ",	"CPU_ARM10" },		/* CPU_CLASS_ARM10EJ */
390 	{ "SA-1",	"CPU_SA110" },		/* CPU_CLASS_SA1 */
391 	{ "XScale",	"CPU_XSCALE_..." },	/* CPU_CLASS_XSCALE */
392 	{ "ARM11J",	"CPU_ARM11" },		/* CPU_CLASS_ARM11J */
393 };
394 
395 /*
396  * Report the type of the specified arm processor. This uses the generic and
397  * arm specific information in the CPU structure to identify the processor.
398  * The remaining fields in the CPU structure are filled in appropriately.
399  */
400 
401 static const char * const wtnames[] = {
402 	"write-through",
403 	"write-back",
404 	"write-back",
405 	"**unknown 3**",
406 	"**unknown 4**",
407 	"write-back-locking",		/* XXX XScale-specific? */
408 	"write-back-locking-A",
409 	"write-back-locking-B",
410 	"**unknown 8**",
411 	"**unknown 9**",
412 	"**unknown 10**",
413 	"**unknown 11**",
414 	"**unknown 12**",
415 	"**unknown 13**",
416 	"write-back-locking-C",
417 	"**unknown 15**",
418 };
419 
420 void
421 identify_arm_cpu(struct device *dv, struct cpu_info *ci)
422 {
423 	u_int cpuid;
424 	enum cpu_class cpu_class = CPU_CLASS_NONE;
425 	int i;
426 
427 	cpuid = ci->ci_arm_cpuid;
428 
429 	if (cpuid == 0) {
430 		aprint_error("Processor failed probe - no CPU ID\n");
431 		return;
432 	}
433 
434 	for (i = 0; cpuids[i].cpuid != 0; i++)
435 		if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
436 			cpu_class = cpuids[i].cpu_class;
437 			sprintf(cpu_model, "%s %s (%s core)",
438 			    cpuids[i].cpu_name,
439 			    cpuids[i].cpu_steppings[cpuid &
440 						    CPU_ID_REVISION_MASK],
441 			    cpu_classes[cpu_class].class_name);
442 			break;
443 		}
444 
445 	if (cpuids[i].cpuid == 0)
446 		sprintf(cpu_model, "unknown CPU (ID = 0x%x)", cpuid);
447 
448 	aprint_naive(": %s\n", cpu_model);
449 	aprint_normal(": %s\n", cpu_model);
450 
451 	aprint_normal("%s:", dv->dv_xname);
452 
453 	switch (cpu_class) {
454 	case CPU_CLASS_ARM6:
455 	case CPU_CLASS_ARM7:
456 	case CPU_CLASS_ARM7TDMI:
457 	case CPU_CLASS_ARM8:
458 		if ((ci->ci_ctrl & CPU_CONTROL_IDC_ENABLE) == 0)
459 			aprint_normal(" IDC disabled");
460 		else
461 			aprint_normal(" IDC enabled");
462 		break;
463 	case CPU_CLASS_ARM9TDMI:
464 	case CPU_CLASS_ARM10E:
465 	case CPU_CLASS_ARM10EJ:
466 	case CPU_CLASS_SA1:
467 	case CPU_CLASS_XSCALE:
468 	case CPU_CLASS_ARM11J:
469 		if ((ci->ci_ctrl & CPU_CONTROL_DC_ENABLE) == 0)
470 			aprint_normal(" DC disabled");
471 		else
472 			aprint_normal(" DC enabled");
473 		if ((ci->ci_ctrl & CPU_CONTROL_IC_ENABLE) == 0)
474 			aprint_normal(" IC disabled");
475 		else
476 			aprint_normal(" IC enabled");
477 		break;
478 	default:
479 		break;
480 	}
481 	if ((ci->ci_ctrl & CPU_CONTROL_WBUF_ENABLE) == 0)
482 		aprint_normal(" WB disabled");
483 	else
484 		aprint_normal(" WB enabled");
485 
486 	if (ci->ci_ctrl & CPU_CONTROL_LABT_ENABLE)
487 		aprint_normal(" LABT");
488 	else
489 		aprint_normal(" EABT");
490 
491 	if (ci->ci_ctrl & CPU_CONTROL_BPRD_ENABLE)
492 		aprint_normal(" branch prediction enabled");
493 
494 	aprint_normal("\n");
495 
496 	/* Print cache info. */
497 	if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0)
498 		goto skip_pcache;
499 
500 	if (arm_pcache_unified) {
501 		aprint_normal("%s: %dKB/%dB %d-way %s unified cache\n",
502 		    dv->dv_xname, arm_pdcache_size / 1024,
503 		    arm_pdcache_line_size, arm_pdcache_ways,
504 		    wtnames[arm_pcache_type]);
505 	} else {
506 		aprint_normal("%s: %dKB/%dB %d-way Instruction cache\n",
507 		    dv->dv_xname, arm_picache_size / 1024,
508 		    arm_picache_line_size, arm_picache_ways);
509 		aprint_normal("%s: %dKB/%dB %d-way %s Data cache\n",
510 		    dv->dv_xname, arm_pdcache_size / 1024,
511 		    arm_pdcache_line_size, arm_pdcache_ways,
512 		    wtnames[arm_pcache_type]);
513 	}
514 
515  skip_pcache:
516 
517 	switch (cpu_class) {
518 #ifdef CPU_ARM2
519 	case CPU_CLASS_ARM2:
520 #endif
521 #ifdef CPU_ARM250
522 	case CPU_CLASS_ARM2AS:
523 #endif
524 #ifdef CPU_ARM3
525 	case CPU_CLASS_ARM3:
526 #endif
527 #ifdef CPU_ARM6
528 	case CPU_CLASS_ARM6:
529 #endif
530 #ifdef CPU_ARM7
531 	case CPU_CLASS_ARM7:
532 #endif
533 #ifdef CPU_ARM7TDMI
534 	case CPU_CLASS_ARM7TDMI:
535 #endif
536 #ifdef CPU_ARM8
537 	case CPU_CLASS_ARM8:
538 #endif
539 #ifdef CPU_ARM9
540 	case CPU_CLASS_ARM9TDMI:
541 #endif
542 #ifdef CPU_ARM10
543 	case CPU_CLASS_ARM10E:
544 	case CPU_CLASS_ARM10EJ:
545 #endif
546 #if defined(CPU_SA110) || defined(CPU_SA1100) || \
547     defined(CPU_SA1110) || defined(CPU_IXP12X0)
548 	case CPU_CLASS_SA1:
549 #endif
550 #if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
551     defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425)
552 	case CPU_CLASS_XSCALE:
553 #endif
554 #ifdef CPU_ARM11
555 	case CPU_CLASS_ARM11J:
556 #endif
557 		break;
558 	default:
559 		if (cpu_classes[cpu_class].class_option != NULL)
560 			aprint_error("%s: %s does not fully support this CPU."
561 			       "\n", dv->dv_xname, ostype);
562 		else {
563 			aprint_error("%s: This kernel does not fully support "
564 			       "this CPU.\n", dv->dv_xname);
565 			aprint_normal("%s: Recompile with \"options %s\" to "
566 			       "correct this.\n", dv->dv_xname,
567 			       cpu_classes[cpu_class].class_option);
568 		}
569 		break;
570 	}
571 
572 }
573 #ifdef MULTIPROCESSOR
574 int
575 cpu_alloc_idlepcb(struct cpu_info *ci)
576 {
577 	vaddr_t uaddr;
578 	struct pcb *pcb;
579 	struct trapframe *tf;
580 	int error;
581 
582 	/*
583 	 * Generate a kernel stack and PCB (in essence, a u-area) for the
584 	 * new CPU.
585 	 */
586 	if (uvm_uarea_alloc(&uaddr)) {
587 		error = uvm_fault_wire(kernel_map, uaddr, uaddr + USPACE,
588 		    VM_FAULT_WIRE, VM_PROT_READ | VM_PROT_WRITE);
589 		if (error)
590 			return error;
591 	}
592 	ci->ci_idlepcb = pcb = (struct pcb *)uaddr;
593 
594 	/*
595 	 * This code is largely derived from cpu_fork(), with which it
596 	 * should perhaps be shared.
597 	 */
598 
599 	/* Copy the pcb */
600 	*pcb = proc0.p_addr->u_pcb;
601 
602 	/* Set up the undefined stack for the process. */
603 	pcb->pcb_un.un_32.pcb32_und_sp = uaddr + USPACE_UNDEF_STACK_TOP;
604 	pcb->pcb_un.un_32.pcb32_sp = uaddr + USPACE_SVC_STACK_TOP;
605 
606 #ifdef STACKCHECKS
607 	/* Fill the undefined stack with a known pattern */
608 	memset(((u_char *)uaddr) + USPACE_UNDEF_STACK_BOTTOM, 0xdd,
609 	    (USPACE_UNDEF_STACK_TOP - USPACE_UNDEF_STACK_BOTTOM));
610 	/* Fill the kernel stack with a known pattern */
611 	memset(((u_char *)uaddr) + USPACE_SVC_STACK_BOTTOM, 0xdd,
612 	    (USPACE_SVC_STACK_TOP - USPACE_SVC_STACK_BOTTOM));
613 #endif	/* STACKCHECKS */
614 
615 	pcb->pcb_tf = tf =
616 	    (struct trapframe *)pcb->pcb_un.un_32.pcb32_sp - 1;
617 	*tf = *proc0.p_addr->u_pcb.pcb_tf;
618 	return 0;
619 }
620 #endif /* MULTIPROCESSOR */
621 
622 /* End of cpu.c */
623