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