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