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