xref: /netbsd-src/sys/arch/arm/arm32/cpu.c (revision 23c8222edbfb0f0932d88a8351d3a0cf817dfb9e)
1 /*	$NetBSD: cpu.c,v 1.56 2004/04/14 04:01:49 bsh 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.56 2004/04/14 04:01:49 bsh 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_SA1,
174 	CPU_CLASS_XSCALE
175 };
176 
177 static const char * const generic_steppings[16] = {
178 	"rev 0",	"rev 1",	"rev 2",	"rev 3",
179 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
180 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
181 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
182 };
183 
184 static const char * const sa110_steppings[16] = {
185 	"rev 0",	"step J",	"step K",	"step S",
186 	"step T",	"rev 5",	"rev 6",	"rev 7",
187 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
188 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
189 };
190 
191 static const char * const sa1100_steppings[16] = {
192 	"rev 0",	"step B",	"step C",	"rev 3",
193 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
194 	"step D",	"step E",	"rev 10"	"step G",
195 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
196 };
197 
198 static const char * const sa1110_steppings[16] = {
199 	"step A-0",	"rev 1",	"rev 2",	"rev 3",
200 	"step B-0",	"step B-1",	"step B-2",	"step B-3",
201 	"step B-4",	"step B-5",	"rev 10",	"rev 11",
202 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
203 };
204 
205 static const char * const ixp12x0_steppings[16] = {
206 	"(IXP1200 step A)",		"(IXP1200 step B)",
207 	"rev 2",			"(IXP1200 step C)",
208 	"(IXP1200 step D)",		"(IXP1240/1250 step A)",
209 	"(IXP1240 step B)",		"(IXP1250 step B)",
210 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
211 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
212 };
213 
214 static const char * const xscale_steppings[16] = {
215 	"step A-0",	"step A-1",	"step B-0",	"step C-0",
216 	"step D-0",	"rev 5",	"rev 6",	"rev 7",
217 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
218 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
219 };
220 
221 static const char * const i80321_steppings[16] = {
222 	"step A-0",	"step B-0",	"rev 2",	"rev 3",
223 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
224 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
225 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
226 };
227 
228 /* Steppings for PXA2[15]0 */
229 static const char * const pxa2x0_steppings[16] = {
230 	"step A-0",	"step A-1",	"step B-0",	"step B-1",
231 	"step B-2",	"step C-0",	"rev 6",	"rev 7",
232 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
233 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
234 };
235 
236 /* Steppings for PXA255/26x.
237  * rev 5: PXA26x B0, rev 6: PXA255 A0
238  */
239 static const char * const pxa255_steppings[16] = {
240 	"rev 0",	"rev 1",	"rev 2",	"step A-0",
241 	"rev 4",	"step B-0",	"step A-0",	"rev 7",
242 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
243 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
244 };
245 
246 static const char * const ixp425_steppings[16] = {
247 	"step 0",	"rev 1",	"rev 2",	"rev 3",
248 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
249 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
250 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
251 };
252 
253 struct cpuidtab {
254 	u_int32_t	cpuid;
255 	enum		cpu_class cpu_class;
256 	const char	*cpu_name;
257 	const char * const *cpu_steppings;
258 };
259 
260 const struct cpuidtab cpuids[] = {
261 	{ CPU_ID_ARM2,		CPU_CLASS_ARM2,		"ARM2",
262 	  generic_steppings },
263 	{ CPU_ID_ARM250,	CPU_CLASS_ARM2AS,	"ARM250",
264 	  generic_steppings },
265 
266 	{ CPU_ID_ARM3,		CPU_CLASS_ARM3,		"ARM3",
267 	  generic_steppings },
268 
269 	{ CPU_ID_ARM600,	CPU_CLASS_ARM6,		"ARM600",
270 	  generic_steppings },
271 	{ CPU_ID_ARM610,	CPU_CLASS_ARM6,		"ARM610",
272 	  generic_steppings },
273 	{ CPU_ID_ARM620,	CPU_CLASS_ARM6,		"ARM620",
274 	  generic_steppings },
275 
276 	{ CPU_ID_ARM700,	CPU_CLASS_ARM7,		"ARM700",
277 	  generic_steppings },
278 	{ CPU_ID_ARM710,	CPU_CLASS_ARM7,		"ARM710",
279 	  generic_steppings },
280 	{ CPU_ID_ARM7500,	CPU_CLASS_ARM7,		"ARM7500",
281 	  generic_steppings },
282 	{ CPU_ID_ARM710A,	CPU_CLASS_ARM7,		"ARM710a",
283 	  generic_steppings },
284 	{ CPU_ID_ARM7500FE,	CPU_CLASS_ARM7,		"ARM7500FE",
285 	  generic_steppings },
286 	{ CPU_ID_ARM710T,	CPU_CLASS_ARM7TDMI,	"ARM710T",
287 	  generic_steppings },
288 	{ CPU_ID_ARM720T,	CPU_CLASS_ARM7TDMI,	"ARM720T",
289 	  generic_steppings },
290 	{ CPU_ID_ARM740T8K,	CPU_CLASS_ARM7TDMI, "ARM740T (8 KB cache)",
291 	  generic_steppings },
292 	{ CPU_ID_ARM740T4K,	CPU_CLASS_ARM7TDMI, "ARM740T (4 KB cache)",
293 	  generic_steppings },
294 
295 	{ CPU_ID_ARM810,	CPU_CLASS_ARM8,		"ARM810",
296 	  generic_steppings },
297 
298 	{ CPU_ID_ARM920T,	CPU_CLASS_ARM9TDMI,	"ARM920T",
299 	  generic_steppings },
300 	{ CPU_ID_ARM922T,	CPU_CLASS_ARM9TDMI,	"ARM922T",
301 	  generic_steppings },
302 	{ CPU_ID_ARM940T,	CPU_CLASS_ARM9TDMI,	"ARM940T",
303 	  generic_steppings },
304 	{ CPU_ID_ARM946ES,	CPU_CLASS_ARM9ES,	"ARM946E-S",
305 	  generic_steppings },
306 	{ CPU_ID_ARM966ES,	CPU_CLASS_ARM9ES,	"ARM966E-S",
307 	  generic_steppings },
308 	{ CPU_ID_ARM966ESR1,	CPU_CLASS_ARM9ES,	"ARM966E-S",
309 	  generic_steppings },
310 	{ CPU_ID_TI925T,	CPU_CLASS_ARM9TDMI,	"TI ARM925T",
311 	  generic_steppings },
312 
313 	{ CPU_ID_ARM1020E,	CPU_CLASS_ARM10E,	"ARM1020E",
314 	  generic_steppings },
315 	{ CPU_ID_ARM1022ES,	CPU_CLASS_ARM10E,	"ARM1022E-S",
316 	  generic_steppings },
317 
318 	{ CPU_ID_SA110,		CPU_CLASS_SA1,		"SA-110",
319 	  sa110_steppings },
320 	{ CPU_ID_SA1100,	CPU_CLASS_SA1,		"SA-1100",
321 	  sa1100_steppings },
322 	{ CPU_ID_SA1110,	CPU_CLASS_SA1,		"SA-1110",
323 	  sa1110_steppings },
324 
325 	{ CPU_ID_IXP1200,	CPU_CLASS_SA1,		"IXP1200",
326 	  ixp12x0_steppings },
327 
328 	{ CPU_ID_80200,		CPU_CLASS_XSCALE,	"i80200",
329 	  xscale_steppings },
330 
331 	{ CPU_ID_80321_400,	CPU_CLASS_XSCALE,	"i80321 400MHz",
332 	  i80321_steppings },
333 	{ CPU_ID_80321_600,	CPU_CLASS_XSCALE,	"i80321 600MHz",
334 	  i80321_steppings },
335 	{ CPU_ID_80321_400_B0,	CPU_CLASS_XSCALE,	"i80321 400MHz",
336 	  i80321_steppings },
337 	{ CPU_ID_80321_600_B0,	CPU_CLASS_XSCALE,	"i80321 600MHz",
338 	  i80321_steppings },
339 
340 	{ CPU_ID_PXA250A,	CPU_CLASS_XSCALE,	"PXA250",
341 	  pxa2x0_steppings },
342 	{ CPU_ID_PXA210A,	CPU_CLASS_XSCALE,	"PXA210",
343 	  pxa2x0_steppings },
344 	{ CPU_ID_PXA250B,	CPU_CLASS_XSCALE,	"PXA250",
345 	  pxa2x0_steppings },
346 	{ CPU_ID_PXA210B,	CPU_CLASS_XSCALE,	"PXA210",
347 	  pxa2x0_steppings },
348 	{ CPU_ID_PXA250C, 	CPU_CLASS_XSCALE,	"PXA255/26x",
349 	  pxa255_steppings },
350 	{ CPU_ID_PXA210C, 	CPU_CLASS_XSCALE,	"PXA210",
351 	  pxa2x0_steppings },
352 
353 	{ CPU_ID_IXP425_533,	CPU_CLASS_XSCALE,	"IXP425 533MHz",
354 	  ixp425_steppings },
355 	{ CPU_ID_IXP425_400,	CPU_CLASS_XSCALE,	"IXP425 400MHz",
356 	  ixp425_steppings },
357 	{ CPU_ID_IXP425_266,	CPU_CLASS_XSCALE,	"IXP425 266MHz",
358 	  ixp425_steppings },
359 
360 	{ 0, CPU_CLASS_NONE, NULL, NULL }
361 };
362 
363 struct cpu_classtab {
364 	const char	*class_name;
365 	const char	*class_option;
366 };
367 
368 const struct cpu_classtab cpu_classes[] = {
369 	{ "unknown",	NULL },			/* CPU_CLASS_NONE */
370 	{ "ARM2",	"CPU_ARM2" },		/* CPU_CLASS_ARM2 */
371 	{ "ARM2as",	"CPU_ARM250" },		/* CPU_CLASS_ARM2AS */
372 	{ "ARM3",	"CPU_ARM3" },		/* CPU_CLASS_ARM3 */
373 	{ "ARM6",	"CPU_ARM6" },		/* CPU_CLASS_ARM6 */
374 	{ "ARM7",	"CPU_ARM7" },		/* CPU_CLASS_ARM7 */
375 	{ "ARM7TDMI",	"CPU_ARM7TDMI" },	/* CPU_CLASS_ARM7TDMI */
376 	{ "ARM8",	"CPU_ARM8" },		/* CPU_CLASS_ARM8 */
377 	{ "ARM9TDMI",	NULL },			/* CPU_CLASS_ARM9TDMI */
378 	{ "ARM9E-S",	NULL },			/* CPU_CLASS_ARM9ES */
379 	{ "ARM10E",	"CPU_ARM10" },		/* CPU_CLASS_ARM10E */
380 	{ "SA-1",	"CPU_SA110" },		/* CPU_CLASS_SA1 */
381 	{ "XScale",	"CPU_XSCALE_..." },	/* CPU_CLASS_XSCALE */
382 };
383 
384 /*
385  * Report the type of the specified arm processor. This uses the generic and
386  * arm specific information in the CPU structure to identify the processor.
387  * The remaining fields in the CPU structure are filled in appropriately.
388  */
389 
390 static const char * const wtnames[] = {
391 	"write-through",
392 	"write-back",
393 	"write-back",
394 	"**unknown 3**",
395 	"**unknown 4**",
396 	"write-back-locking",		/* XXX XScale-specific? */
397 	"write-back-locking-A",
398 	"write-back-locking-B",
399 	"**unknown 8**",
400 	"**unknown 9**",
401 	"**unknown 10**",
402 	"**unknown 11**",
403 	"**unknown 12**",
404 	"**unknown 13**",
405 	"**unknown 14**",
406 	"**unknown 15**",
407 };
408 
409 void
410 identify_arm_cpu(struct device *dv, struct cpu_info *ci)
411 {
412 	u_int cpuid;
413 	enum cpu_class cpu_class = CPU_CLASS_NONE;
414 	int i;
415 
416 	cpuid = ci->ci_arm_cpuid;
417 
418 	if (cpuid == 0) {
419 		aprint_error("Processor failed probe - no CPU ID\n");
420 		return;
421 	}
422 
423 	for (i = 0; cpuids[i].cpuid != 0; i++)
424 		if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
425 			cpu_class = cpuids[i].cpu_class;
426 			sprintf(cpu_model, "%s %s (%s core)",
427 			    cpuids[i].cpu_name,
428 			    cpuids[i].cpu_steppings[cpuid &
429 						    CPU_ID_REVISION_MASK],
430 			    cpu_classes[cpu_class].class_name);
431 			break;
432 		}
433 
434 	if (cpuids[i].cpuid == 0)
435 		sprintf(cpu_model, "unknown CPU (ID = 0x%x)", cpuid);
436 
437 	aprint_naive(": %s\n", cpu_model);
438 	aprint_normal(": %s\n", cpu_model);
439 
440 	aprint_normal("%s:", dv->dv_xname);
441 
442 	switch (cpu_class) {
443 	case CPU_CLASS_ARM6:
444 	case CPU_CLASS_ARM7:
445 	case CPU_CLASS_ARM7TDMI:
446 	case CPU_CLASS_ARM8:
447 		if ((ci->ci_ctrl & CPU_CONTROL_IDC_ENABLE) == 0)
448 			aprint_normal(" IDC disabled");
449 		else
450 			aprint_normal(" IDC enabled");
451 		break;
452 	case CPU_CLASS_ARM9TDMI:
453 	case CPU_CLASS_ARM10E:
454 	case CPU_CLASS_SA1:
455 	case CPU_CLASS_XSCALE:
456 		if ((ci->ci_ctrl & CPU_CONTROL_DC_ENABLE) == 0)
457 			aprint_normal(" DC disabled");
458 		else
459 			aprint_normal(" DC enabled");
460 		if ((ci->ci_ctrl & CPU_CONTROL_IC_ENABLE) == 0)
461 			aprint_normal(" IC disabled");
462 		else
463 			aprint_normal(" IC enabled");
464 		break;
465 	default:
466 		break;
467 	}
468 	if ((ci->ci_ctrl & CPU_CONTROL_WBUF_ENABLE) == 0)
469 		aprint_normal(" WB disabled");
470 	else
471 		aprint_normal(" WB enabled");
472 
473 	if (ci->ci_ctrl & CPU_CONTROL_LABT_ENABLE)
474 		aprint_normal(" LABT");
475 	else
476 		aprint_normal(" EABT");
477 
478 	if (ci->ci_ctrl & CPU_CONTROL_BPRD_ENABLE)
479 		aprint_normal(" branch prediction enabled");
480 
481 	aprint_normal("\n");
482 
483 	/* Print cache info. */
484 	if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0)
485 		goto skip_pcache;
486 
487 	if (arm_pcache_unified) {
488 		aprint_normal("%s: %dKB/%dB %d-way %s unified cache\n",
489 		    dv->dv_xname, arm_pdcache_size / 1024,
490 		    arm_pdcache_line_size, arm_pdcache_ways,
491 		    wtnames[arm_pcache_type]);
492 	} else {
493 		aprint_normal("%s: %dKB/%dB %d-way Instruction cache\n",
494 		    dv->dv_xname, arm_picache_size / 1024,
495 		    arm_picache_line_size, arm_picache_ways);
496 		aprint_normal("%s: %dKB/%dB %d-way %s Data cache\n",
497 		    dv->dv_xname, arm_pdcache_size / 1024,
498 		    arm_pdcache_line_size, arm_pdcache_ways,
499 		    wtnames[arm_pcache_type]);
500 	}
501 
502  skip_pcache:
503 
504 	switch (cpu_class) {
505 #ifdef CPU_ARM2
506 	case CPU_CLASS_ARM2:
507 #endif
508 #ifdef CPU_ARM250
509 	case CPU_CLASS_ARM2AS:
510 #endif
511 #ifdef CPU_ARM3
512 	case CPU_CLASS_ARM3:
513 #endif
514 #ifdef CPU_ARM6
515 	case CPU_CLASS_ARM6:
516 #endif
517 #ifdef CPU_ARM7
518 	case CPU_CLASS_ARM7:
519 #endif
520 #ifdef CPU_ARM7TDMI
521 	case CPU_CLASS_ARM7TDMI:
522 #endif
523 #ifdef CPU_ARM8
524 	case CPU_CLASS_ARM8:
525 #endif
526 #ifdef CPU_ARM9
527 	case CPU_CLASS_ARM9TDMI:
528 #endif
529 #ifdef CPU_ARM10
530 	case CPU_CLASS_ARM10E:
531 #endif
532 #if defined(CPU_SA110) || defined(CPU_SA1100) || \
533     defined(CPU_SA1110) || defined(CPU_IXP12X0)
534 	case CPU_CLASS_SA1:
535 #endif
536 #if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
537     defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425)
538 	case CPU_CLASS_XSCALE:
539 #endif
540 		break;
541 	default:
542 		if (cpu_classes[cpu_class].class_option != NULL)
543 			aprint_error("%s: %s does not fully support this CPU."
544 			       "\n", dv->dv_xname, ostype);
545 		else {
546 			aprint_error("%s: This kernel does not fully support "
547 			       "this CPU.\n", dv->dv_xname);
548 			aprint_normal("%s: Recompile with \"options %s\" to "
549 			       "correct this.\n", dv->dv_xname,
550 			       cpu_classes[cpu_class].class_option);
551 		}
552 		break;
553 	}
554 
555 }
556 #ifdef MULTIPROCESSOR
557 int
558 cpu_alloc_idlepcb(struct cpu_info *ci)
559 {
560 	vaddr_t uaddr;
561 	struct pcb *pcb;
562 	struct trapframe *tf;
563 	int error;
564 
565 	/*
566 	 * Generate a kernel stack and PCB (in essence, a u-area) for the
567 	 * new CPU.
568 	 */
569 	if (uvm_uarea_alloc(&uaddr)) {
570 		error = uvm_fault_wire(kernel_map, uaddr, uaddr + USPACE,
571 		    VM_FAULT_WIRE, VM_PROT_READ | VM_PROT_WRITE);
572 		if (error)
573 			return error;
574 	}
575 	ci->ci_idlepcb = pcb = (struct pcb *)uaddr;
576 
577 	/*
578 	 * This code is largely derived from cpu_fork(), with which it
579 	 * should perhaps be shared.
580 	 */
581 
582 	/* Copy the pcb */
583 	*pcb = proc0.p_addr->u_pcb;
584 
585 	/* Set up the undefined stack for the process. */
586 	pcb->pcb_un.un_32.pcb32_und_sp = uaddr + USPACE_UNDEF_STACK_TOP;
587 	pcb->pcb_un.un_32.pcb32_sp = uaddr + USPACE_SVC_STACK_TOP;
588 
589 #ifdef STACKCHECKS
590 	/* Fill the undefined stack with a known pattern */
591 	memset(((u_char *)uaddr) + USPACE_UNDEF_STACK_BOTTOM, 0xdd,
592 	    (USPACE_UNDEF_STACK_TOP - USPACE_UNDEF_STACK_BOTTOM));
593 	/* Fill the kernel stack with a known pattern */
594 	memset(((u_char *)uaddr) + USPACE_SVC_STACK_BOTTOM, 0xdd,
595 	    (USPACE_SVC_STACK_TOP - USPACE_SVC_STACK_BOTTOM));
596 #endif	/* STACKCHECKS */
597 
598 	pcb->pcb_tf = tf =
599 	    (struct trapframe *)pcb->pcb_un.un_32.pcb32_sp - 1;
600 	*tf = *proc0.p_addr->u_pcb.pcb_tf;
601 	return 0;
602 }
603 #endif /* MULTIPROCESSOR */
604 
605 /* End of cpu.c */
606