xref: /freebsd/sys/kern/subr_smp.c (revision ce834215a70ff69e7e222827437116eee2f9ac6f)
1 /*
2  * Copyright (c) 1996, by Steve Passe
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. The name of the developer may NOT be used to endorse or promote products
11  *    derived from this software without specific prior written permission.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  *	$Id: mp_machdep.c,v 1.14 1997/07/13 00:42:14 smp Exp smp $
26  */
27 
28 #include "opt_smp.h"
29 
30 #include <sys/param.h>		/* for KERNBASE */
31 #include <sys/types.h>
32 #include <sys/sysproto.h>
33 #include <sys/time.h>
34 #include <sys/systm.h>
35 
36 #include <vm/vm.h>		/* for KERNBASE */
37 #include <vm/vm_param.h>	/* for KERNBASE */
38 #include <vm/pmap.h>		/* for KERNBASE */
39 #include <machine/pmap.h>	/* for KERNBASE */
40 #include <vm/vm_kern.h>
41 #include <vm/vm_extern.h>
42 
43 #include <machine/smp.h>
44 #include <machine/apic.h>
45 #include <machine/mpapic.h>
46 #include <machine/cpufunc.h>
47 #include <machine/segments.h>
48 #include <machine/smptests.h>	/** TEST_DEFAULT_CONFIG, TEST_CPUSTOP _TEST1 */
49 #include <machine/tss.h>
50 #include <machine/specialreg.h>
51 
52 #include <i386/i386/cons.h>	/* cngetc() */
53 
54 #if defined(APIC_IO)
55 #include <machine/md_var.h>		/* setidt() */
56 #include <i386/isa/icu.h>		/* IPIs */
57 #include <i386/isa/intr_machdep.h>	/* IPIs */
58 #endif	/* APIC_IO */
59 
60 #define WARMBOOT_TARGET		0
61 #define WARMBOOT_OFF		(KERNBASE + 0x0467)
62 #define WARMBOOT_SEG		(KERNBASE + 0x0469)
63 
64 #define BIOS_BASE		(0xf0000)
65 #define BIOS_SIZE		(0x10000)
66 #define BIOS_COUNT		(BIOS_SIZE/4)
67 
68 #define CMOS_REG		(0x70)
69 #define CMOS_DATA		(0x71)
70 #define BIOS_RESET		(0x0f)
71 #define BIOS_WARM		(0x0a)
72 
73 #define PROCENTRY_FLAG_EN	0x01
74 #define PROCENTRY_FLAG_BP	0x02
75 #define IOAPICENTRY_FLAG_EN	0x01
76 
77 
78 /* MP Floating Pointer Structure */
79 typedef struct MPFPS {
80 	char    signature[4];
81 	void   *pap;
82 	u_char  length;
83 	u_char  spec_rev;
84 	u_char  checksum;
85 	u_char  mpfb1;
86 	u_char  mpfb2;
87 	u_char  mpfb3;
88 	u_char  mpfb4;
89 	u_char  mpfb5;
90 }      *mpfps_t;
91 
92 /* MP Configuration Table Header */
93 typedef struct MPCTH {
94 	char    signature[4];
95 	u_short base_table_length;
96 	u_char  spec_rev;
97 	u_char  checksum;
98 	u_char  oem_id[8];
99 	u_char  product_id[12];
100 	void   *oem_table_pointer;
101 	u_short oem_table_size;
102 	u_short entry_count;
103 	void   *apic_address;
104 	u_short extended_table_length;
105 	u_char  extended_table_checksum;
106 	u_char  reserved;
107 }      *mpcth_t;
108 
109 
110 typedef struct PROCENTRY {
111 	u_char  type;
112 	u_char  apic_id;
113 	u_char  apic_version;
114 	u_char  cpu_flags;
115 	u_long  cpu_signature;
116 	u_long  feature_flags;
117 	u_long  reserved1;
118 	u_long  reserved2;
119 }      *proc_entry_ptr;
120 
121 typedef struct BUSENTRY {
122 	u_char  type;
123 	u_char  bus_id;
124 	char    bus_type[6];
125 }      *bus_entry_ptr;
126 
127 typedef struct IOAPICENTRY {
128 	u_char  type;
129 	u_char  apic_id;
130 	u_char  apic_version;
131 	u_char  apic_flags;
132 	void   *apic_address;
133 }      *io_apic_entry_ptr;
134 
135 typedef struct INTENTRY {
136 	u_char  type;
137 	u_char  int_type;
138 	u_short int_flags;
139 	u_char  src_bus_id;
140 	u_char  src_bus_irq;
141 	u_char  dst_apic_id;
142 	u_char  dst_apic_int;
143 }      *int_entry_ptr;
144 
145 /* descriptions of MP basetable entries */
146 typedef struct BASETABLE_ENTRY {
147 	u_char  type;
148 	u_char  length;
149 	char    name[16];
150 }       basetable_entry;
151 
152 /*
153  * this code MUST be enabled here and in mpboot.s.
154  * it follows the very early stages of AP boot by placing values in CMOS ram.
155  * it NORMALLY will never be needed and thus the primitive method for enabling.
156  *
157 #define CHECK_POINTS
158  */
159 
160 #if defined(CHECK_POINTS)
161 #define CHECK_READ(A)	 (outb(CMOS_REG, (A)), inb(CMOS_DATA))
162 #define CHECK_WRITE(A,D) (outb(CMOS_REG, (A)), outb(CMOS_DATA, (D)))
163 
164 #define CHECK_INIT(D);				\
165 	CHECK_WRITE(0x34, (D));			\
166 	CHECK_WRITE(0x35, (D));			\
167 	CHECK_WRITE(0x36, (D));			\
168 	CHECK_WRITE(0x37, (D));			\
169 	CHECK_WRITE(0x38, (D));			\
170 	CHECK_WRITE(0x39, (D));
171 
172 #define CHECK_PRINT(S);				\
173 	printf("%s: %d, %d, %d, %d, %d, %d\n",	\
174 	   (S),					\
175 	   CHECK_READ(0x34),			\
176 	   CHECK_READ(0x35),			\
177 	   CHECK_READ(0x36),			\
178 	   CHECK_READ(0x37),			\
179 	   CHECK_READ(0x38),			\
180 	   CHECK_READ(0x39));
181 
182 #else				/* CHECK_POINTS */
183 
184 #define CHECK_INIT(D)
185 #define CHECK_PRINT(S)
186 
187 #endif				/* CHECK_POINTS */
188 
189 /*
190  * Values to send to the POST hardware.
191  */
192 #define MP_BOOTADDRESS_POST	0x10
193 #define MP_PROBE_POST		0x11
194 #define MP_START_POST		0x12
195 #define MP_ANNOUNCE_POST	0x13
196 #define MPTABLE_PASS1_POST	0x14
197 #define MPTABLE_PASS2_POST	0x15
198 #define MP_ENABLE_POST		0x16
199 #define START_ALL_APS_POST	0x17
200 #define INSTALL_AP_TRAMP_POST	0x18
201 #define START_AP_POST		0x19
202 
203 /** XXX FIXME: where does this really belong, isa.h/isa.c perhaps? */
204 int	current_postcode;
205 
206 /** XXX FIXME: what system files declare these??? */
207 extern struct region_descriptor r_gdt, r_idt;
208 
209 int	mp_ncpus;		/* # of CPUs, including BSP */
210 int	mp_naps;		/* # of Applications processors */
211 int	mp_nbusses;		/* # of busses */
212 int	mp_napics;		/* # of IO APICs */
213 int	boot_cpu_id;		/* designated BSP */
214 vm_offset_t cpu_apic_address;
215 vm_offset_t io_apic_address[NAPICID];	/* NAPICID is more than enough */
216 
217 u_int32_t cpu_apic_versions[NCPU];
218 u_int32_t io_apic_versions[NAPIC];
219 
220 /*
221  * APIC ID logical/physical mapping structures.
222  * We oversize these to simplify boot-time config.
223  */
224 int     cpu_num_to_apic_id[NAPICID];
225 int     io_num_to_apic_id[NAPICID];
226 int     apic_id_to_logical[NAPICID];
227 
228 /* Bitmap of all available CPUs */
229 u_int	all_cpus;
230 
231 /* Boot of AP uses this PTD */
232 u_int *bootPTD;
233 
234 /* Hotwire a 0->4MB V==P mapping */
235 extern pt_entry_t KPTphys;
236 
237 /* Virtual address of per-cpu common_tss */
238 extern struct i386tss common_tss;
239 
240 /*
241  * Local data and functions.
242  */
243 
244 static int	mp_capable;
245 static u_int	boot_address;
246 static u_int	base_memory;
247 
248 static int	picmode;		/* 0: virtual wire mode, 1: PIC mode */
249 static mpfps_t	mpfps;
250 static int	search_for_sig(u_int32_t target, int count);
251 static void	mp_enable(u_int boot_addr);
252 
253 static int	mptable_pass1(void);
254 static int	mptable_pass2(void);
255 static void	default_mp_table(int type);
256 static int	start_all_aps(u_int boot_addr);
257 static void	install_ap_tramp(u_int boot_addr);
258 static int	start_ap(int logicalCpu, u_int boot_addr);
259 
260 
261 /*
262  * Calculate usable address in base memory for AP trampoline code.
263  */
264 u_int
265 mp_bootaddress(u_int basemem)
266 {
267 	POSTCODE(MP_BOOTADDRESS_POST);
268 
269 	base_memory = basemem * 1024;	/* convert to bytes */
270 
271 	boot_address = base_memory & ~0xfff;	/* round down to 4k boundary */
272 	if ((base_memory - boot_address) < bootMP_size)
273 		boot_address -= 4096;	/* not enough, lower by 4k */
274 
275 	return boot_address;
276 }
277 
278 
279 /*
280  * Look for an Intel MP spec table (ie, SMP capable hardware).
281  */
282 int
283 mp_probe(void)
284 {
285 	int     x;
286 	u_long  segment;
287 	u_int32_t target;
288 
289 	POSTCODE(MP_PROBE_POST);
290 
291 	/* see if EBDA exists */
292 	if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
293 		/* search first 1K of EBDA */
294 		target = (u_int32_t) (segment << 4);
295 		if ((x = search_for_sig(target, 1024 / 4)) >= 0)
296 			goto found;
297 	} else {
298 		/* last 1K of base memory, effective 'top of base' passed in */
299 		target = (u_int32_t) (base_memory - 0x400);
300 		if ((x = search_for_sig(target, 1024 / 4)) >= 0)
301 			goto found;
302 	}
303 
304 	/* search the BIOS */
305 	target = (u_int32_t) BIOS_BASE;
306 	if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
307 		goto found;
308 
309 	/* nothing found */
310 	mpfps = (mpfps_t)0;
311 	mp_capable = 0;
312 	return 0;
313 
314 found:
315 	/* calculate needed resources */
316 	mpfps = (mpfps_t)x;
317 	if (mptable_pass1())
318 		panic("you must reconfigure your kernel");
319 
320 	/* flag fact that we are running multiple processors */
321 	mp_capable = 1;
322 	return 1;
323 }
324 
325 
326 /*
327  * Startup the SMP processors.
328  */
329 void
330 mp_start(void)
331 {
332 	POSTCODE(MP_START_POST);
333 
334 	/* look for MP capable motherboard */
335 	if (mp_capable)
336 		mp_enable(boot_address);
337 	else
338 		panic("MP hardware not found!");
339 }
340 
341 
342 /*
343  * Print various information about the SMP system hardware and setup.
344  */
345 void
346 mp_announce(void)
347 {
348 	int     x;
349 
350 	POSTCODE(MP_ANNOUNCE_POST);
351 
352 	printf("FreeBSD/SMP: Multiprocessor motherboard\n");
353 	printf(" cpu0 (BSP): apic id: %d", CPU_TO_ID(0));
354 	printf(", version: 0x%08x", cpu_apic_versions[0]);
355 	printf(", at 0x%08x\n", cpu_apic_address);
356 	for (x = 1; x <= mp_naps; ++x) {
357 		printf(" cpu%d (AP):  apic id: %d", x, CPU_TO_ID(x));
358 		printf(", version: 0x%08x", cpu_apic_versions[x]);
359 		printf(", at 0x%08x\n", cpu_apic_address);
360 	}
361 
362 #if defined(APIC_IO)
363 	for (x = 0; x < mp_napics; ++x) {
364 		printf(" io%d (APIC): apic id: %d", x, IO_TO_ID(x));
365 		printf(", version: 0x%08x", io_apic_versions[x]);
366 		printf(", at 0x%08x\n", io_apic_address[x]);
367 	}
368 #else
369 	printf(" Warning: APIC I/O disabled\n");
370 #endif	/* APIC_IO */
371 }
372 
373 /*
374  * AP cpu's call this to sync up protected mode.
375  */
376 void
377 init_secondary(void)
378 {
379 	int     gsel_tss, slot;
380 
381 	r_gdt.rd_limit = sizeof(gdt[0]) * (NGDT + NCPU) - 1;
382 	r_gdt.rd_base = (int) gdt;
383 	lgdt(&r_gdt);			/* does magic intra-segment return */
384 	lidt(&r_idt);
385 	lldt(_default_ldt);
386 
387 	slot = NGDT + cpuid;
388 	gsel_tss = GSEL(slot, SEL_KPL);
389 	gdt[slot].sd.sd_type = SDT_SYS386TSS;
390 	common_tss.tss_esp0 = 0;	/* not used until after switch */
391 	common_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL);
392 	common_tss.tss_ioopt = (sizeof common_tss) << 16;
393 	ltr(gsel_tss);
394 
395 	load_cr0(0x8005003b);		/* XXX! */
396 
397 	PTD[0] = 0;
398 	invltlb();
399 }
400 
401 
402 #if defined(APIC_IO)
403 /*
404  * Final configuration of the BSP's local APIC:
405  *  - disable 'pic mode'.
406  *  - disable 'virtual wire mode'.
407  *  - enable NMI.
408  */
409 void
410 bsp_apic_configure(void)
411 {
412 	u_char		byte;
413 	u_int32_t	temp;
414 
415 	/* leave 'pic mode' if necessary */
416 	if (picmode) {
417 		outb(0x22, 0x70);	/* select IMCR */
418 		byte = inb(0x23);	/* current contents */
419 		byte |= 0x01;		/* mask external INTR */
420 		outb(0x23, byte);	/* disconnect 8259s/NMI */
421 	}
422 
423 	/* mask lint0 (the 8259 'virtual wire' connection) */
424 	temp = lapic.lvt_lint0;
425 	temp |= APIC_LVT_M;		/* set the mask */
426 	lapic.lvt_lint0 = temp;
427 
428         /* setup lint1 to handle NMI */
429         temp = lapic.lvt_lint1;
430         temp &= ~APIC_LVT_M;		/* clear the mask */
431         lapic.lvt_lint1 = temp;
432 
433 	if (bootverbose)
434 		apic_dump();
435 }
436 #endif  /* APIC_IO */
437 
438 
439 /*******************************************************************
440  * local functions and data
441  */
442 
443 /*
444  * start the SMP system
445  */
446 static void
447 mp_enable(u_int boot_addr)
448 {
449 	int     x;
450 #if defined(APIC_IO)
451 	int     apic;
452 	u_int   ux;
453 #endif	/* APIC_IO */
454 
455 	POSTCODE(MP_ENABLE_POST);
456 
457 	/* turn on 4MB of V == P addressing so we can get to MP table */
458 	*(int *)PTD = PG_V | PG_RW | ((u_long)KPTphys & PG_FRAME);
459 	invltlb();
460 
461 	/* examine the MP table for needed info, uses physical addresses */
462 	x = mptable_pass2();
463 
464 	*(int *)PTD = 0;
465 	invltlb();
466 
467 	/* can't process default configs till the CPU APIC is pmapped */
468 	if (x)
469 		default_mp_table(x);
470 
471 #if defined(APIC_IO)
472 
473 	/* fill the LOGICAL io_apic_versions table */
474 	for (apic = 0; apic < mp_napics; ++apic) {
475 		ux = io_apic_read(apic, IOAPIC_VER);
476 		io_apic_versions[apic] = ux;
477 	}
478 
479 	/* program each IO APIC in the system */
480 	for (apic = 0; apic < mp_napics; ++apic)
481 		if (io_apic_setup(apic) < 0)
482 			panic("IO APIC setup failure");
483 
484 	/* install a 'Spurious INTerrupt' vector */
485 	setidt(XSPURIOUSINT_OFFSET, Xspuriousint,
486 	       SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
487 
488 	/* install an inter-CPU IPI for TLB invalidation */
489 	setidt(XINVLTLB_OFFSET, Xinvltlb,
490 	       SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
491 
492 #if defined(TEST_CPUSTOP)
493 	/* install an inter-CPU IPI for CPU stop/restart */
494 	setidt(XCPUSTOP_OFFSET, Xcpustop,
495 	       SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
496 #endif  /** TEST_CPUSTOP */
497 
498 #if defined(TEST_TEST1)
499 	/* install a 'Spurious INTerrupt' vector */
500 	setidt(XTEST1_OFFSET, Xtest1,
501 	       SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
502 #endif  /** TEST_TEST1 */
503 
504 #endif	/* APIC_IO */
505 
506 	/* start each Application Processor */
507 	start_all_aps(boot_addr);
508 
509 	/*
510 	 * The init process might be started on a different CPU now,
511 	 * and the boot CPU might not call prepare_usermode to get
512 	 * cr0 correctly configured. Thus we initialize cr0 here.
513 	 */
514 	load_cr0(rcr0() | CR0_WP | CR0_AM);
515 }
516 
517 
518 /*
519  * look for the MP spec signature
520  */
521 
522 /* string defined by the Intel MP Spec as identifying the MP table */
523 #define MP_SIG		0x5f504d5f	/* _MP_ */
524 #define NEXT(X)		((X) += 4)
525 static int
526 search_for_sig(u_int32_t target, int count)
527 {
528 	int     x;
529 	u_int32_t *addr = (u_int32_t *) (KERNBASE + target);
530 
531 	for (x = 0; x < count; NEXT(x))
532 		if (addr[x] == MP_SIG)
533 			/* make array index a byte index */
534 			return (target + (x * sizeof(u_int32_t)));
535 
536 	return -1;
537 }
538 
539 
540 static basetable_entry basetable_entry_types[] =
541 {
542 	{0, 20, "Processor"},
543 	{1, 8, "Bus"},
544 	{2, 8, "I/O APIC"},
545 	{3, 8, "I/O INT"},
546 	{4, 8, "Local INT"}
547 };
548 
549 typedef struct BUSDATA {
550 	u_char  bus_id;
551 	enum busTypes bus_type;
552 }       bus_datum;
553 
554 typedef struct INTDATA {
555 	u_char  int_type;
556 	u_short int_flags;
557 	u_char  src_bus_id;
558 	u_char  src_bus_irq;
559 	u_char  dst_apic_id;
560 	u_char  dst_apic_int;
561 }       io_int, local_int;
562 
563 typedef struct BUSTYPENAME {
564 	u_char  type;
565 	char    name[7];
566 }       bus_type_name;
567 
568 static bus_type_name bus_type_table[] =
569 {
570 	{CBUS, "CBUS"},
571 	{CBUSII, "CBUSII"},
572 	{EISA, "EISA"},
573 	{UNKNOWN_BUSTYPE, "---"},
574 	{UNKNOWN_BUSTYPE, "---"},
575 	{ISA, "ISA"},
576 	{UNKNOWN_BUSTYPE, "---"},
577 	{UNKNOWN_BUSTYPE, "---"},
578 	{UNKNOWN_BUSTYPE, "---"},
579 	{UNKNOWN_BUSTYPE, "---"},
580 	{UNKNOWN_BUSTYPE, "---"},
581 	{UNKNOWN_BUSTYPE, "---"},
582 	{PCI, "PCI"},
583 	{UNKNOWN_BUSTYPE, "---"},
584 	{UNKNOWN_BUSTYPE, "---"},
585 	{UNKNOWN_BUSTYPE, "---"},
586 	{UNKNOWN_BUSTYPE, "---"},
587 	{XPRESS, "XPRESS"},
588 	{UNKNOWN_BUSTYPE, "---"}
589 };
590 /* from MP spec v1.4, table 5-1 */
591 static int default_data[7][5] =
592 {
593 /*   nbus, id0, type0, id1, type1 */
594 	{1, 0, ISA, 255, 255},
595 	{1, 0, EISA, 255, 255},
596 	{1, 0, EISA, 255, 255},
597 	{0, 255, 255, 255, 255},/* MCA not supported */
598 	{2, 0, ISA, 1, PCI},
599 	{2, 0, EISA, 1, PCI},
600 	{0, 255, 255, 255, 255}	/* MCA not supported */
601 };
602 
603 
604 /* the bus data */
605 bus_datum bus_data[NBUS];
606 
607 /* the IO INT data, one entry per possible APIC INTerrupt */
608 io_int  io_apic_ints[NINTR];
609 
610 static int nintrs;
611 
612 static void fix_mp_table	__P((void));
613 static int processor_entry	__P((proc_entry_ptr entry, int cpu));
614 static int bus_entry		__P((bus_entry_ptr entry, int bus));
615 static int io_apic_entry	__P((io_apic_entry_ptr entry, int apic));
616 static int int_entry		__P((int_entry_ptr entry, int intr));
617 static int lookup_bus_type	__P((char *name));
618 
619 
620 /*
621  * 1st pass on motherboard's Intel MP specification table.
622  *
623  * initializes:
624  *	mp_ncpus = 1
625  *
626  * determines:
627  *	cpu_apic_address (common to all CPUs)
628  *	io_apic_address[N]
629  *	mp_naps
630  *	mp_nbusses
631  *	mp_napics
632  *	nintrs
633  */
634 static int
635 mptable_pass1(void)
636 {
637 	int	x;
638 	mpcth_t	cth;
639 	int	totalSize;
640 	void*	position;
641 	int	count;
642 	int	type;
643 	int	mustpanic;
644 
645 	POSTCODE(MPTABLE_PASS1_POST);
646 
647 	mustpanic = 0;
648 
649 	/* clear various tables */
650 	for (x = 0; x < NAPICID; ++x) {
651 		io_apic_address[x] = ~0;	/* IO APIC address table */
652 	}
653 
654 	/* init everything to empty */
655 	mp_naps = 0;
656 	mp_nbusses = 0;
657 	mp_napics = 0;
658 	nintrs = 0;
659 
660 	/* check for use of 'default' configuration */
661 	if (mpfps->mpfb1 != 0) {
662 		/* use default addresses */
663 		cpu_apic_address = DEFAULT_APIC_BASE;
664 		io_apic_address[0] = DEFAULT_IO_APIC_BASE;
665 
666 		/* fill in with defaults */
667 		mp_naps = 2;		/* includes BSP */
668 		mp_nbusses = default_data[mpfps->mpfb1 - 1][0];
669 #if defined(APIC_IO)
670 		mp_napics = 1;
671 		nintrs = 16;
672 #endif	/* APIC_IO */
673 	}
674 	else {
675 		if ((cth = mpfps->pap) == 0)
676 			panic("MP Configuration Table Header MISSING!");
677 
678 		cpu_apic_address = (vm_offset_t) cth->apic_address;
679 
680 		/* walk the table, recording info of interest */
681 		totalSize = cth->base_table_length - sizeof(struct MPCTH);
682 		position = (u_char *) cth + sizeof(struct MPCTH);
683 		count = cth->entry_count;
684 
685 		while (count--) {
686 			switch (type = *(u_char *) position) {
687 			case 0: /* processor_entry */
688 				if (((proc_entry_ptr)position)->cpu_flags
689 					& PROCENTRY_FLAG_EN)
690 					++mp_naps;
691 				break;
692 			case 1: /* bus_entry */
693 				++mp_nbusses;
694 				break;
695 			case 2: /* io_apic_entry */
696 				if (((io_apic_entry_ptr)position)->apic_flags
697 					& IOAPICENTRY_FLAG_EN)
698 					io_apic_address[mp_napics++] =
699 					    (vm_offset_t)((io_apic_entry_ptr)
700 						position)->apic_address;
701 				break;
702 			case 3: /* int_entry */
703 				++nintrs;
704 				break;
705 			case 4:	/* int_entry */
706 				break;
707 			default:
708 				panic("mpfps Base Table HOSED!");
709 				/* NOTREACHED */
710 			}
711 
712 			totalSize -= basetable_entry_types[type].length;
713 			(u_char*)position += basetable_entry_types[type].length;
714 		}
715 	}
716 
717 	/* qualify the numbers */
718 	if (mp_naps > NCPU)
719 		printf("Warning: only using %d of %d available CPUs!\n",
720 			NCPU, mp_naps);
721 #if 0
722 		/** XXX we consider this legal now (but should we?) */
723 		mustpanic = 1;
724 #endif
725 	if (mp_nbusses > NBUS) {
726 		printf("found %d busses, increase NBUS\n", mp_nbusses);
727 		mustpanic = 1;
728 	}
729 	if (mp_napics > NAPIC) {
730 		printf("found %d apics, increase NAPIC\n", mp_napics);
731 		mustpanic = 1;
732 	}
733 	if (nintrs > NINTR) {
734 		printf("found %d intrs, increase NINTR\n", nintrs);
735 		mustpanic = 1;
736 	}
737 
738 	/*
739 	 * Count the BSP.
740 	 * This is also used as a counter while starting the APs.
741 	 */
742 	mp_ncpus = 1;
743 
744 	--mp_naps;	/* subtract the BSP */
745 
746 	return mustpanic;
747 }
748 
749 
750 /*
751  * 2nd pass on motherboard's Intel MP specification table.
752  *
753  * sets:
754  *	boot_cpu_id
755  *	ID_TO_IO(N), phy APIC ID to log CPU/IO table
756  *	CPU_TO_ID(N), logical CPU to APIC ID table
757  *	IO_TO_ID(N), logical IO to APIC ID table
758  *	bus_data[N]
759  *	io_apic_ints[N]
760  */
761 static int
762 mptable_pass2(void)
763 {
764 	int     x;
765 	mpcth_t cth;
766 	int     totalSize;
767 	void*   position;
768 	int     count;
769 	int     type;
770 	int     apic, bus, cpu, intr;
771 
772 	POSTCODE(MPTABLE_PASS2_POST);
773 
774 	/* clear various tables */
775 	for (x = 0; x < NAPICID; ++x) {
776 		ID_TO_IO(x) = -1;	/* phy APIC ID to log CPU/IO table */
777 		CPU_TO_ID(x) = -1;	/* logical CPU to APIC ID table */
778 		IO_TO_ID(x) = -1;	/* logical IO to APIC ID table */
779 	}
780 
781 	/* clear bus data table */
782 	for (x = 0; x < NBUS; ++x)
783 		bus_data[x].bus_id = 0xff;
784 
785 	/* clear IO APIC INT table */
786 	for (x = 0; x < NINTR; ++x)
787 		io_apic_ints[x].int_type = 0xff;
788 
789 	/* setup the cpu/apic mapping arrays */
790 	boot_cpu_id = -1;
791 
792 	/* record whether PIC or virtual-wire mode */
793 	picmode = (mpfps->mpfb2 & 0x80) ? 1 : 0;
794 
795 	/* check for use of 'default' configuration */
796 #if defined(TEST_DEFAULT_CONFIG)
797 	return TEST_DEFAULT_CONFIG;
798 #else
799 	if (mpfps->mpfb1 != 0)
800 		return mpfps->mpfb1;	/* return default configuration type */
801 #endif	/* TEST_DEFAULT_CONFIG */
802 
803 	if ((cth = mpfps->pap) == 0)
804 		panic("MP Configuration Table Header MISSING!");
805 
806 	/* walk the table, recording info of interest */
807 	totalSize = cth->base_table_length - sizeof(struct MPCTH);
808 	position = (u_char *) cth + sizeof(struct MPCTH);
809 	count = cth->entry_count;
810 	apic = bus = intr = 0;
811 	cpu = 1;				/* pre-count the BSP */
812 
813 	while (count--) {
814 		switch (type = *(u_char *) position) {
815 		case 0:
816 			if (processor_entry(position, cpu))
817 				++cpu;
818 			break;
819 		case 1:
820 			if (bus_entry(position, bus))
821 				++bus;
822 			break;
823 		case 2:
824 			if (io_apic_entry(position, apic))
825 				++apic;
826 			break;
827 		case 3:
828 			if (int_entry(position, intr))
829 				++intr;
830 			break;
831 		case 4:
832 			/* int_entry(position); */
833 			break;
834 		default:
835 			panic("mpfps Base Table HOSED!");
836 			/* NOTREACHED */
837 		}
838 
839 		totalSize -= basetable_entry_types[type].length;
840 		(u_char *) position += basetable_entry_types[type].length;
841 	}
842 
843 	if (boot_cpu_id == -1)
844 		panic("NO BSP found!");
845 
846 	/* post scan cleanup */
847 	fix_mp_table();
848 
849 	/* report fact that its NOT a default configuration */
850 	return 0;
851 }
852 
853 
854 /*
855  * parse an Intel MP specification table
856  */
857 static void
858 fix_mp_table(void)
859 {
860 	int	x;
861 	int	id;
862 	int	bus_0;
863 	int	bus_pci;
864 	int	num_pci_bus;
865 
866 	/*
867 	 * Fix mis-numbering of the PCI bus and its INT entries if the BIOS
868 	 * did it wrong.  The MP spec says that when more than 1 PCI bus
869 	 * exists the BIOS must begin with bus entries for the PCI bus and use
870 	 * actual PCI bus numbering.  This implies that when only 1 PCI bus
871 	 * exists the BIOS can choose to ignore this ordering, and indeed many
872 	 * MP motherboards do ignore it.  This causes a problem when the PCI
873 	 * sub-system makes requests of the MP sub-system based on PCI bus
874 	 * numbers.	So here we look for the situation and renumber the
875 	 * busses and associated INTs in an effort to "make it right".
876 	 */
877 
878 	/* find bus 0, PCI bus, count the number of PCI busses */
879 	for (num_pci_bus = 0, x = 0; x < mp_nbusses; ++x) {
880 		if (bus_data[x].bus_id == 0) {
881 			bus_0 = x;
882 		}
883 		if (bus_data[x].bus_type == PCI) {
884 			++num_pci_bus;
885 			bus_pci = x;
886 		}
887 	}
888 	/*
889 	 * bus_0 == slot of bus with ID of 0
890 	 * bus_pci == slot of last PCI bus encountered
891 	 */
892 
893 	/* check the 1 PCI bus case for sanity */
894 	if (num_pci_bus == 1) {
895 
896 		/* if it is number 0 all is well */
897 		if (bus_data[bus_pci].bus_id == 0)
898 			return;
899 
900 		/* mis-numbered, swap with whichever bus uses slot 0 */
901 
902 		/* swap the bus entry types */
903 		bus_data[bus_pci].bus_type = bus_data[bus_0].bus_type;
904 		bus_data[bus_0].bus_type = PCI;
905 
906 		/* swap each relavant INTerrupt entry */
907 		id = bus_data[bus_pci].bus_id;
908 		for (x = 0; x < nintrs; ++x) {
909 			if (io_apic_ints[x].src_bus_id == id) {
910 				io_apic_ints[x].src_bus_id = 0;
911 			}
912 			else if (io_apic_ints[x].src_bus_id == 0) {
913 				io_apic_ints[x].src_bus_id = id;
914 			}
915 		}
916 	}
917 	/* sanity check if more than 1 PCI bus */
918 	else if (num_pci_bus > 1) {
919 		for (x = 0; x < mp_nbusses; ++x) {
920 			if (bus_data[x].bus_type != PCI)
921 				continue;
922 			if (bus_data[x].bus_id >= num_pci_bus)
923 				panic("bad PCI bus numbering");
924 		}
925 	}
926 }
927 
928 
929 static int
930 processor_entry(proc_entry_ptr entry, int cpu)
931 {
932 	/* check for usability */
933 	if ((cpu >= NCPU) || !(entry->cpu_flags & PROCENTRY_FLAG_EN))
934 		return 0;
935 
936 	/* check for BSP flag */
937 	if (entry->cpu_flags & PROCENTRY_FLAG_BP) {
938 		boot_cpu_id = entry->apic_id;
939 		CPU_TO_ID(0) = entry->apic_id;
940 		ID_TO_CPU(entry->apic_id) = 0;
941 		return 0;	/* its already been counted */
942 	}
943 
944 	/* add another AP to list, if less than max number of CPUs */
945 	else {
946 		CPU_TO_ID(cpu) = entry->apic_id;
947 		ID_TO_CPU(entry->apic_id) = cpu;
948 		return 1;
949 	}
950 }
951 
952 
953 static int
954 bus_entry(bus_entry_ptr entry, int bus)
955 {
956 	int     x;
957 	char    c, name[8];
958 
959 	/* encode the name into an index */
960 	for (x = 0; x < 6; ++x) {
961 		if ((c = entry->bus_type[x]) == ' ')
962 			break;
963 		name[x] = c;
964 	}
965 	name[x] = '\0';
966 
967 	if ((x = lookup_bus_type(name)) == UNKNOWN_BUSTYPE)
968 		panic("unknown bus type: '%s'", name);
969 
970 	bus_data[bus].bus_id = entry->bus_id;
971 	bus_data[bus].bus_type = x;
972 
973 	return 1;
974 }
975 
976 
977 static int
978 io_apic_entry(io_apic_entry_ptr entry, int apic)
979 {
980 	if (!(entry->apic_flags & IOAPICENTRY_FLAG_EN))
981 		return 0;
982 
983 	IO_TO_ID(apic) = entry->apic_id;
984 	ID_TO_IO(entry->apic_id) = apic;
985 
986 	return 1;
987 }
988 
989 
990 static int
991 lookup_bus_type(char *name)
992 {
993 	int     x;
994 
995 	for (x = 0; x < MAX_BUSTYPE; ++x)
996 		if (strcmp(bus_type_table[x].name, name) == 0)
997 			return bus_type_table[x].type;
998 
999 	return UNKNOWN_BUSTYPE;
1000 }
1001 
1002 
1003 static int
1004 int_entry(int_entry_ptr entry, int intr)
1005 {
1006 	io_apic_ints[intr].int_type = entry->int_type;
1007 	io_apic_ints[intr].int_flags = entry->int_flags;
1008 	io_apic_ints[intr].src_bus_id = entry->src_bus_id;
1009 	io_apic_ints[intr].src_bus_irq = entry->src_bus_irq;
1010 	io_apic_ints[intr].dst_apic_id = entry->dst_apic_id;
1011 	io_apic_ints[intr].dst_apic_int = entry->dst_apic_int;
1012 
1013 	return 1;
1014 }
1015 
1016 
1017 static int
1018 apic_int_is_bus_type(int intr, int bus_type)
1019 {
1020 	int     bus;
1021 
1022 	for (bus = 0; bus < mp_nbusses; ++bus)
1023 		if ((bus_data[bus].bus_id == io_apic_ints[intr].src_bus_id)
1024 		    && ((int) bus_data[bus].bus_type == bus_type))
1025 			return 1;
1026 
1027 	return 0;
1028 }
1029 
1030 
1031 /*
1032  * Given a traditional ISA INT mask, return an APIC mask.
1033  */
1034 u_int
1035 isa_apic_mask(u_int isa_mask)
1036 {
1037 	int isa_irq;
1038 	int apic_pin;
1039 
1040 #if defined(SKIP_IRQ15_REDIRECT)
1041 	if (isa_mask == (1 << 15)) {
1042 		printf("skipping ISA IRQ15 redirect\n");
1043 		return isa_mask;
1044 	}
1045 #endif  /* SKIP_IRQ15_REDIRECT */
1046 
1047 	isa_irq = ffs(isa_mask);		/* find its bit position */
1048 	if (isa_irq == 0)			/* doesn't exist */
1049 		return 0;
1050 	--isa_irq;				/* make it zero based */
1051 
1052 	apic_pin = isa_apic_pin(isa_irq);	/* look for APIC connection */
1053 	if (apic_pin == -1)
1054 		return 0;
1055 
1056 	return (1 << apic_pin);			/* convert pin# to a mask */
1057 }
1058 
1059 
1060 /*
1061  * Determine which APIC pin an ISA/EISA INT is attached to.
1062  */
1063 #define INTTYPE(I)	(io_apic_ints[(I)].int_type)
1064 #define INTPIN(I)	(io_apic_ints[(I)].dst_apic_int)
1065 
1066 #define SRCBUSIRQ(I)	(io_apic_ints[(I)].src_bus_irq)
1067 int
1068 isa_apic_pin(int isa_irq)
1069 {
1070 	int     intr;
1071 
1072 #if defined(SMP_TIMER_NC)
1073 	if (isa_irq == 0)
1074 		return -1;
1075 #endif	/* SMP_TIMER_NC */
1076 
1077 	for (intr = 0; intr < nintrs; ++intr) {		/* check each record */
1078 		if (INTTYPE(intr) == 0) {		/* standard INT */
1079 			if (SRCBUSIRQ(intr) == isa_irq) {
1080 				if (apic_int_is_bus_type(intr, ISA) ||
1081 			            apic_int_is_bus_type(intr, EISA))
1082 					return INTPIN(intr);	/* found */
1083 			}
1084 		}
1085 	}
1086 	return -1;					/* NOT found */
1087 }
1088 #undef SRCBUSIRQ
1089 
1090 
1091 /*
1092  * Determine which APIC pin a PCI INT is attached to.
1093  */
1094 #define SRCBUSID(I)	(io_apic_ints[(I)].src_bus_id)
1095 #define SRCBUSDEVICE(I)	((io_apic_ints[(I)].src_bus_irq >> 2) & 0x1f)
1096 #define SRCBUSLINE(I)	(io_apic_ints[(I)].src_bus_irq & 0x03)
1097 int
1098 pci_apic_pin(int pciBus, int pciDevice, int pciInt)
1099 {
1100 	int     intr;
1101 
1102 	--pciInt;					/* zero based */
1103 
1104 	for (intr = 0; intr < nintrs; ++intr)		/* check each record */
1105 		if ((INTTYPE(intr) == 0)		/* standard INT */
1106 		    && (SRCBUSID(intr) == pciBus)
1107 		    && (SRCBUSDEVICE(intr) == pciDevice)
1108 		    && (SRCBUSLINE(intr) == pciInt))	/* a candidate IRQ */
1109 			if (apic_int_is_bus_type(intr, PCI))
1110 				return INTPIN(intr);	/* exact match */
1111 
1112 	return -1;					/* NOT found */
1113 }
1114 #undef SRCBUSLINE
1115 #undef SRCBUSDEVICE
1116 #undef SRCBUSID
1117 
1118 #undef INTPIN
1119 #undef INTTYPE
1120 
1121 
1122 /*
1123  * Reprogram the MB chipset to NOT redirect an ISA INTerrupt.
1124  *
1125  * XXX FIXME:
1126  *  Exactly what this means is unclear at this point.  It is a solution
1127  *  for motherboards that redirect the MBIRQ0 pin.  Generically a motherboard
1128  *  could route any of the ISA INTs to upper (>15) IRQ values.  But most would
1129  *  NOT be redirected via MBIRQ0, thus "undirect()ing" them would NOT be an
1130  *  option.
1131  */
1132 int
1133 undirect_isa_irq(int rirq)
1134 {
1135 #if defined(READY)
1136 	printf("Freeing redirected ISA irq %d.\n", rirq);
1137 	/** FIXME: tickle the MB redirector chip */
1138 	return ???;
1139 #else
1140 	printf("Freeing (NOT implemented) redirected ISA irq %d.\n", rirq);
1141 	return 0;
1142 #endif  /* READY */
1143 }
1144 
1145 
1146 /*
1147  * Reprogram the MB chipset to NOT redirect a PCI INTerrupt
1148  */
1149 int
1150 undirect_pci_irq(int rirq)
1151 {
1152 #if defined(READY)
1153 	if (bootverbose)
1154 		printf("Freeing redirected PCI irq %d.\n", rirq);
1155 
1156 	/** FIXME: tickle the MB redirector chip */
1157 	return ???;
1158 #else
1159 	if (bootverbose)
1160 		printf("Freeing (NOT implemented) redirected PCI irq %d.\n",
1161 		       rirq);
1162 	return 0;
1163 #endif  /* READY */
1164 }
1165 
1166 
1167 /*
1168  * given a bus ID, return:
1169  *  the bus type if found
1170  *  -1 if NOT found
1171  */
1172 int
1173 apic_bus_type(int id)
1174 {
1175 	int     x;
1176 
1177 	for (x = 0; x < mp_nbusses; ++x)
1178 		if (bus_data[x].bus_id == id)
1179 			return bus_data[x].bus_type;
1180 
1181 	return -1;
1182 }
1183 
1184 
1185 /*
1186  * given a LOGICAL APIC# and pin#, return:
1187  *  the associated src bus ID if found
1188  *  -1 if NOT found
1189  */
1190 int
1191 apic_src_bus_id(int apic, int pin)
1192 {
1193 	int     x;
1194 
1195 	/* search each of the possible INTerrupt sources */
1196 	for (x = 0; x < nintrs; ++x)
1197 		if ((apic == ID_TO_IO(io_apic_ints[x].dst_apic_id)) &&
1198 		    (pin == io_apic_ints[x].dst_apic_int))
1199 			return (io_apic_ints[x].src_bus_id);
1200 
1201 	return -1;		/* NOT found */
1202 }
1203 
1204 
1205 /*
1206  * given a LOGICAL APIC# and pin#, return:
1207  *  the associated src bus IRQ if found
1208  *  -1 if NOT found
1209  */
1210 int
1211 apic_src_bus_irq(int apic, int pin)
1212 {
1213 	int     x;
1214 
1215 	for (x = 0; x < nintrs; x++)
1216 		if ((apic == ID_TO_IO(io_apic_ints[x].dst_apic_id)) &&
1217 		    (pin == io_apic_ints[x].dst_apic_int))
1218 			return (io_apic_ints[x].src_bus_irq);
1219 
1220 	return -1;		/* NOT found */
1221 }
1222 
1223 
1224 /*
1225  * given a LOGICAL APIC# and pin#, return:
1226  *  the associated INTerrupt type if found
1227  *  -1 if NOT found
1228  */
1229 int
1230 apic_int_type(int apic, int pin)
1231 {
1232 	int     x;
1233 
1234 	/* search each of the possible INTerrupt sources */
1235 	for (x = 0; x < nintrs; ++x)
1236 		if ((apic == ID_TO_IO(io_apic_ints[x].dst_apic_id)) &&
1237 		    (pin == io_apic_ints[x].dst_apic_int))
1238 			return (io_apic_ints[x].int_type);
1239 
1240 	return -1;		/* NOT found */
1241 }
1242 
1243 
1244 /*
1245  * given a LOGICAL APIC# and pin#, return:
1246  *  the associated trigger mode if found
1247  *  -1 if NOT found
1248  */
1249 int
1250 apic_trigger(int apic, int pin)
1251 {
1252 	int     x;
1253 
1254 	/* search each of the possible INTerrupt sources */
1255 	for (x = 0; x < nintrs; ++x)
1256 		if ((apic == ID_TO_IO(io_apic_ints[x].dst_apic_id)) &&
1257 		    (pin == io_apic_ints[x].dst_apic_int))
1258 			return ((io_apic_ints[x].int_flags >> 2) & 0x03);
1259 
1260 	return -1;		/* NOT found */
1261 }
1262 
1263 
1264 /*
1265  * given a LOGICAL APIC# and pin#, return:
1266  *  the associated 'active' level if found
1267  *  -1 if NOT found
1268  */
1269 int
1270 apic_polarity(int apic, int pin)
1271 {
1272 	int     x;
1273 
1274 	/* search each of the possible INTerrupt sources */
1275 	for (x = 0; x < nintrs; ++x)
1276 		if ((apic == ID_TO_IO(io_apic_ints[x].dst_apic_id)) &&
1277 		    (pin == io_apic_ints[x].dst_apic_int))
1278 			return (io_apic_ints[x].int_flags & 0x03);
1279 
1280 	return -1;		/* NOT found */
1281 }
1282 
1283 
1284 /*
1285  * set data according to MP defaults
1286  * FIXME: probably not complete yet...
1287  */
1288 static void
1289 default_mp_table(int type)
1290 {
1291 	int     ap_cpu_id;
1292 #if defined(APIC_IO)
1293 	u_int32_t ux;
1294 	int     io_apic_id;
1295 	int     pin;
1296 #endif	/* APIC_IO */
1297 
1298 #if 0
1299 	printf("  MP default config type: %d\n", type);
1300 	switch (type) {
1301 	case 1:
1302 		printf("   bus: ISA, APIC: 82489DX\n");
1303 		break;
1304 	case 2:
1305 		printf("   bus: EISA, APIC: 82489DX\n");
1306 		break;
1307 	case 3:
1308 		printf("   bus: EISA, APIC: 82489DX\n");
1309 		break;
1310 	case 4:
1311 		printf("   bus: MCA, APIC: 82489DX\n");
1312 		break;
1313 	case 5:
1314 		printf("   bus: ISA+PCI, APIC: Integrated\n");
1315 		break;
1316 	case 6:
1317 		printf("   bus: EISA+PCI, APIC: Integrated\n");
1318 		break;
1319 	case 7:
1320 		printf("   bus: MCA+PCI, APIC: Integrated\n");
1321 		break;
1322 	default:
1323 		printf("   future type\n");
1324 		break;
1325 		/* NOTREACHED */
1326 	}
1327 #endif	/* 0 */
1328 
1329 	boot_cpu_id = (lapic.id & APIC_ID_MASK) >> 24;
1330 	ap_cpu_id = (boot_cpu_id == 0) ? 1 : 0;
1331 
1332 	/* BSP */
1333 	CPU_TO_ID(0) = boot_cpu_id;
1334 	ID_TO_CPU(boot_cpu_id) = 0;
1335 
1336 	/* one and only AP */
1337 	CPU_TO_ID(1) = ap_cpu_id;
1338 	ID_TO_CPU(ap_cpu_id) = 1;
1339 
1340 #if defined(APIC_IO)
1341 	/* one and only IO APIC */
1342 	io_apic_id = (io_apic_read(0, IOAPIC_ID) & APIC_ID_MASK) >> 24;
1343 
1344 	/*
1345 	 * sanity check, refer to MP spec section 3.6.6, last paragraph
1346 	 * necessary as some hardware isn't properly setting up the IO APIC
1347 	 */
1348 #if defined(REALLY_ANAL_IOAPICID_VALUE)
1349 	if (io_apic_id != 2) {
1350 #else
1351 	if ((io_apic_id == 0) || (io_apic_id == 1) || (io_apic_id == 15)) {
1352 #endif	/* REALLY_ANAL_IOAPICID_VALUE */
1353 		ux = io_apic_read(0, IOAPIC_ID);	/* get current contents */
1354 		ux &= ~APIC_ID_MASK;	/* clear the ID field */
1355 		ux |= 0x02000000;	/* set it to '2' */
1356 		io_apic_write(0, IOAPIC_ID, ux);	/* write new value */
1357 		ux = io_apic_read(0, IOAPIC_ID);	/* re-read && test */
1358 		if ((ux & APIC_ID_MASK) != 0x02000000)
1359 			panic("can't control IO APIC ID, reg: 0x%08x", ux);
1360 		io_apic_id = 2;
1361 	}
1362 	IO_TO_ID(0) = io_apic_id;
1363 	ID_TO_IO(io_apic_id) = 0;
1364 #endif	/* APIC_IO */
1365 
1366 	/* fill out bus entries */
1367 	switch (type) {
1368 	case 1:
1369 	case 2:
1370 	case 3:
1371 	case 5:
1372 	case 6:
1373 		bus_data[0].bus_id = default_data[type - 1][1];
1374 		bus_data[0].bus_type = default_data[type - 1][2];
1375 		bus_data[1].bus_id = default_data[type - 1][3];
1376 		bus_data[1].bus_type = default_data[type - 1][4];
1377 		break;
1378 
1379 	/* case 4: case 7:		   MCA NOT supported */
1380 	default:		/* illegal/reserved */
1381 		panic("BAD default MP config: %d", type);
1382 		/* NOTREACHED */
1383 	}
1384 
1385 #if defined(APIC_IO)
1386 	/* general cases from MP v1.4, table 5-2 */
1387 	for (pin = 0; pin < 16; ++pin) {
1388 		io_apic_ints[pin].int_type = 0;
1389 		io_apic_ints[pin].int_flags = 0x05;	/* edge-triggered/active-hi */
1390 		io_apic_ints[pin].src_bus_id = 0;
1391 		io_apic_ints[pin].src_bus_irq = pin;	/* IRQ2 is caught below */
1392 		io_apic_ints[pin].dst_apic_id = io_apic_id;
1393 		io_apic_ints[pin].dst_apic_int = pin;	/* 1-to-1 correspondence */
1394 	}
1395 
1396 	/* special cases from MP v1.4, table 5-2 */
1397 	if (type == 2) {
1398 		io_apic_ints[2].int_type = 0xff;	/* N/C */
1399 		io_apic_ints[13].int_type = 0xff;	/* N/C */
1400 #if !defined(APIC_MIXED_MODE)
1401 		/** FIXME: ??? */
1402 		panic("sorry, can't support type 2 default yet");
1403 #endif	/* APIC_MIXED_MODE */
1404 	}
1405 	else
1406 		io_apic_ints[2].src_bus_irq = 0;	/* ISA IRQ0 is on APIC INT 2 */
1407 
1408 	if (type == 7)
1409 		io_apic_ints[0].int_type = 0xff;	/* N/C */
1410 	else
1411 		io_apic_ints[0].int_type = 3;	/* vectored 8259 */
1412 #endif	/* APIC_IO */
1413 }
1414 
1415 
1416 /*
1417  * start each AP in our list
1418  */
1419 static int
1420 start_all_aps(u_int boot_addr)
1421 {
1422 	int     x, i;
1423 	u_char  mpbiosreason;
1424 	u_long  mpbioswarmvec;
1425 	pd_entry_t newptd;
1426 	pt_entry_t newpt;
1427 	int *newpp;
1428 
1429 	POSTCODE(START_ALL_APS_POST);
1430 
1431 	/**
1432          * NOTE: this needs further thought:
1433          *        where does it get released?
1434          *        should it be set to empy?
1435          *
1436          * get the initial mp_lock with a count of 1 for the BSP
1437          */
1438 	mp_lock = 1;	/* this uses a LOGICAL cpu ID, ie BSP == 0 */
1439 
1440 	/* initialize BSP's local APIC */
1441 	apic_initialize();
1442 
1443 	/* install the AP 1st level boot code */
1444 	install_ap_tramp(boot_addr);
1445 
1446 
1447 	/* save the current value of the warm-start vector */
1448 	mpbioswarmvec = *((u_long *) WARMBOOT_OFF);
1449 	outb(CMOS_REG, BIOS_RESET);
1450 	mpbiosreason = inb(CMOS_DATA);
1451 
1452 	/* record BSP in CPU map */
1453 	all_cpus = 1;
1454 
1455 	/* start each AP */
1456 	for (x = 1; x <= mp_naps; ++x) {
1457 
1458 		/* HACK HACK HACK !!! */
1459 
1460 		/* alloc new page table directory */
1461 		newptd = (pd_entry_t)(kmem_alloc(kernel_map, PAGE_SIZE));
1462 
1463 		/* clone currently active one (ie: IdlePTD) */
1464 		bcopy(PTD, newptd, PAGE_SIZE);	/* inc prv page pde */
1465 
1466 		/* set up 0 -> 4MB P==V mapping for AP boot */
1467 		newptd[0] = PG_V | PG_RW | ((u_long)KPTphys & PG_FRAME);
1468 
1469 		/* store PTD for this AP */
1470 		bootPTD = (pd_entry_t)vtophys(newptd);
1471 
1472 		/* alloc new page table page */
1473 		newpt = (pt_entry_t)(kmem_alloc(kernel_map, PAGE_SIZE));
1474 
1475 		/* set the new PTD's private page to point there */
1476 		newptd[MPPTDI] = PG_V | PG_RW | vtophys(newpt);
1477 
1478 		/* install self referential entry */
1479 		newptd[PTDPTDI] = PG_V | PG_RW | vtophys(newptd);
1480 
1481 		/* get a new private data page */
1482 		newpp = (int *)kmem_alloc(kernel_map, PAGE_SIZE);
1483 
1484 		/* wire it into the private page table page */
1485 		newpt[0] = PG_V | PG_RW | vtophys(newpp);
1486 
1487 		/* wire the ptp into itself for access */
1488 		newpt[1] = PG_V | PG_RW | vtophys(newpt);
1489 
1490 		/* and the local apic */
1491 		newpt[2] = SMP_prvpt[2];
1492 
1493 		/* and the IO apic mapping[s] */
1494 		for (i = 16; i < 32; i++)
1495 			newpt[i] = SMP_prvpt[i];
1496 
1497 		/* prime data page for it to use */
1498 		newpp[0] = x;		/* cpuid */
1499 		newpp[1] = 0;		/* curproc */
1500 		newpp[2] = 0;		/* curpcb */
1501 		newpp[3] = 0;		/* npxproc */
1502 		newpp[4] = 0;		/* runtime.tv_sec */
1503 		newpp[5] = 0;		/* runtime.tv_usec */
1504 		newpp[6] = x << 24;	/* cpu_lockid */
1505 
1506 		/* XXX NOTE: ABANDON bootPTD for now!!!! */
1507 
1508 		/* END REVOLTING HACKERY */
1509 
1510 		/* setup a vector to our boot code */
1511 		*((volatile u_short *) WARMBOOT_OFF) = WARMBOOT_TARGET;
1512 		*((volatile u_short *) WARMBOOT_SEG) = (boot_addr >> 4);
1513 		outb(CMOS_REG, BIOS_RESET);
1514 		outb(CMOS_DATA, BIOS_WARM);	/* 'warm-start' */
1515 
1516 		/* attempt to start the Application Processor */
1517 		CHECK_INIT(99);	/* setup checkpoints */
1518 		if (!start_ap(x, boot_addr)) {
1519 			printf("AP #%d (PHY# %d) failed!\n", x, CPU_TO_ID(x));
1520 			CHECK_PRINT("trace");	/* show checkpoints */
1521 			/* better panic as the AP may be running loose */
1522 			printf("panic y/n? [y] ");
1523 			if (cngetc() != 'n')
1524 				panic("bye-bye");
1525 		}
1526 		CHECK_PRINT("trace");		/* show checkpoints */
1527 
1528 		/* record its version info */
1529 		cpu_apic_versions[x] = cpu_apic_versions[0];
1530 
1531 		all_cpus |= (1 << x);		/* record AP in CPU map */
1532 	}
1533 
1534 	/* build our map of 'other' CPUs */
1535 	other_cpus = all_cpus & ~(1 << cpuid);
1536 
1537 	/* fill in our (BSP) APIC version */
1538 	cpu_apic_versions[0] = lapic.version;
1539 
1540 	/* restore the warmstart vector */
1541 	*(u_long *) WARMBOOT_OFF = mpbioswarmvec;
1542 	outb(CMOS_REG, BIOS_RESET);
1543 	outb(CMOS_DATA, mpbiosreason);
1544 
1545 	/* number of APs actually started */
1546 	return mp_ncpus - 1;
1547 }
1548 
1549 
1550 /*
1551  * load the 1st level AP boot code into base memory.
1552  */
1553 
1554 /* targets for relocation */
1555 extern void bigJump(void);
1556 extern void bootCodeSeg(void);
1557 extern void bootDataSeg(void);
1558 extern void MPentry(void);
1559 extern u_int MP_GDT;
1560 extern u_int mp_gdtbase;
1561 
1562 static void
1563 install_ap_tramp(u_int boot_addr)
1564 {
1565 	int     x;
1566 	int     size = *(int *) ((u_long) & bootMP_size);
1567 	u_char *src = (u_char *) ((u_long) bootMP);
1568 	u_char *dst = (u_char *) boot_addr + KERNBASE;
1569 	u_int   boot_base = (u_int) bootMP;
1570 	u_int8_t *dst8;
1571 	u_int16_t *dst16;
1572 	u_int32_t *dst32;
1573 
1574 	POSTCODE(INSTALL_AP_TRAMP_POST);
1575 
1576 	for (x = 0; x < size; ++x)
1577 		*dst++ = *src++;
1578 
1579 	/*
1580 	 * modify addresses in code we just moved to basemem. unfortunately we
1581 	 * need fairly detailed info about mpboot.s for this to work.  changes
1582 	 * to mpboot.s might require changes here.
1583 	 */
1584 
1585 	/* boot code is located in KERNEL space */
1586 	dst = (u_char *) boot_addr + KERNBASE;
1587 
1588 	/* modify the lgdt arg */
1589 	dst32 = (u_int32_t *) (dst + ((u_int) & mp_gdtbase - boot_base));
1590 	*dst32 = boot_addr + ((u_int) & MP_GDT - boot_base);
1591 
1592 	/* modify the ljmp target for MPentry() */
1593 	dst32 = (u_int32_t *) (dst + ((u_int) bigJump - boot_base) + 1);
1594 	*dst32 = ((u_int) MPentry - KERNBASE);
1595 
1596 	/* modify the target for boot code segment */
1597 	dst16 = (u_int16_t *) (dst + ((u_int) bootCodeSeg - boot_base));
1598 	dst8 = (u_int8_t *) (dst16 + 1);
1599 	*dst16 = (u_int) boot_addr & 0xffff;
1600 	*dst8 = ((u_int) boot_addr >> 16) & 0xff;
1601 
1602 	/* modify the target for boot data segment */
1603 	dst16 = (u_int16_t *) (dst + ((u_int) bootDataSeg - boot_base));
1604 	dst8 = (u_int8_t *) (dst16 + 1);
1605 	*dst16 = (u_int) boot_addr & 0xffff;
1606 	*dst8 = ((u_int) boot_addr >> 16) & 0xff;
1607 }
1608 
1609 
1610 /*
1611  * this function starts the AP (application processor) identified
1612  * by the APIC ID 'physicalCpu'.  It does quite a "song and dance"
1613  * to accomplish this.  This is necessary because of the nuances
1614  * of the different hardware we might encounter.  It ain't pretty,
1615  * but it seems to work.
1616  */
1617 static int
1618 start_ap(int logical_cpu, u_int boot_addr)
1619 {
1620 	int     physical_cpu;
1621 	int     vector;
1622 	int     cpus;
1623 	u_long  icr_lo, icr_hi;
1624 
1625 	POSTCODE(START_AP_POST);
1626 
1627 	/* get the PHYSICAL APIC ID# */
1628 	physical_cpu = CPU_TO_ID(logical_cpu);
1629 
1630 	/* calculate the vector */
1631 	vector = (boot_addr >> 12) & 0xff;
1632 
1633 	/* used as a watchpoint to signal AP startup */
1634 	cpus = mp_ncpus;
1635 
1636 	/*
1637 	 * first we do an INIT/RESET IPI this INIT IPI might be run, reseting
1638 	 * and running the target CPU. OR this INIT IPI might be latched (P5
1639 	 * bug), CPU waiting for STARTUP IPI. OR this INIT IPI might be
1640 	 * ignored.
1641 	 */
1642 
1643 	/* setup the address for the target AP */
1644 	icr_hi = lapic.icr_hi & ~APIC_ID_MASK;
1645 	icr_hi |= (physical_cpu << 24);
1646 	lapic.icr_hi = icr_hi;
1647 
1648 	/* do an INIT IPI: assert RESET */
1649 	icr_lo = lapic.icr_lo & 0xfff00000;
1650 	lapic.icr_lo = icr_lo | 0x0000c500;
1651 
1652 	/* wait for pending status end */
1653 	while (lapic.icr_lo & APIC_DELSTAT_MASK)
1654 		 /* spin */ ;
1655 
1656 	/* do an INIT IPI: deassert RESET */
1657 	lapic.icr_lo = icr_lo | 0x00008500;
1658 
1659 	/* wait for pending status end */
1660 	u_sleep(10000);		/* wait ~10mS */
1661 	while (lapic.icr_lo & APIC_DELSTAT_MASK)
1662 		 /* spin */ ;
1663 
1664 	/*
1665 	 * next we do a STARTUP IPI: the previous INIT IPI might still be
1666 	 * latched, (P5 bug) this 1st STARTUP would then terminate
1667 	 * immediately, and the previously started INIT IPI would continue. OR
1668 	 * the previous INIT IPI has already run. and this STARTUP IPI will
1669 	 * run. OR the previous INIT IPI was ignored. and this STARTUP IPI
1670 	 * will run.
1671 	 */
1672 
1673 	/* do a STARTUP IPI */
1674 	lapic.icr_lo = icr_lo | 0x00000600 | vector;
1675 	while (lapic.icr_lo & APIC_DELSTAT_MASK)
1676 		 /* spin */ ;
1677 	u_sleep(200);		/* wait ~200uS */
1678 
1679 	/*
1680 	 * finally we do a 2nd STARTUP IPI: this 2nd STARTUP IPI should run IF
1681 	 * the previous STARTUP IPI was cancelled by a latched INIT IPI. OR
1682 	 * this STARTUP IPI will be ignored, as only ONE STARTUP IPI is
1683 	 * recognized after hardware RESET or INIT IPI.
1684 	 */
1685 
1686 	lapic.icr_lo = icr_lo | 0x00000600 | vector;
1687 	while (lapic.icr_lo & APIC_DELSTAT_MASK)
1688 		 /* spin */ ;
1689 	u_sleep(200);		/* wait ~200uS */
1690 
1691 	/* wait for it to start */
1692 	set_apic_timer(5000000);/* == 5 seconds */
1693 	while (read_apic_timer())
1694 		if (mp_ncpus > cpus)
1695 			return 1;	/* return SUCCESS */
1696 
1697 	return 0;		/* return FAILURE */
1698 }
1699 
1700 
1701 /*
1702  * Flush the TLB on all other CPU's
1703  *
1704  * XXX: Needs to handshake and wait for completion before proceding.
1705  */
1706 void
1707 smp_invltlb(void)
1708 {
1709 #if defined(APIC_IO)
1710 	if (smp_active && invltlb_ok)
1711 		all_but_self_ipi(XINVLTLB_OFFSET);
1712 #endif  /* APIC_IO */
1713 }
1714 
1715 void
1716 invlpg(u_int addr)
1717 {
1718 	__asm   __volatile("invlpg (%0)"::"r"(addr):"memory");
1719 
1720 	/* send a message to the other CPUs */
1721 	smp_invltlb();
1722 }
1723 
1724 void
1725 invltlb(void)
1726 {
1727 	u_long  temp;
1728 
1729 	/*
1730 	 * This should be implemented as load_cr3(rcr3()) when load_cr3() is
1731 	 * inlined.
1732 	 */
1733 	__asm __volatile("movl %%cr3, %0; movl %0, %%cr3":"=r"(temp) :: "memory");
1734 
1735 	/* send a message to the other CPUs */
1736 	smp_invltlb();
1737 }
1738 
1739 
1740 #if defined(TEST_CPUSTOP)
1741 
1742 #if defined(DEBUG_CPUSTOP)
1743 void	db_printf __P((const char *fmt, ...));
1744 #endif /* DEBUG_CPUSTOP */
1745 
1746 /*
1747  * When called the executing CPU will send an IPI to all other CPUs
1748  *  requesting that they halt execution.
1749  *
1750  * Usually (but not necessarily) called with 'other_cpus' as its arg.
1751  *
1752  *  - Signals all CPUs in map to stop.
1753  *  - Waits for each to stop.
1754  *
1755  * Returns:
1756  *  -1: error
1757  *   0: NA
1758  *   1: ok
1759  *
1760  * XXX FIXME: this is not MP-safe, needs a lock to prevent multiple CPUs
1761  *            from executing at same time.
1762  */
1763 int
1764 stop_cpus( u_int map )
1765 {
1766 	if (!smp_active)
1767 		return 0;
1768 
1769 	/* send IPI to all CPUs in map */
1770 #if defined(DEBUG_CPUSTOP)
1771 	db_printf("\nCPU%d stopping CPUs: 0x%08x\n", cpuid, map);
1772 #endif /* DEBUG_CPUSTOP */
1773 
1774 	stopped_cpus = 0;
1775 
1776 	/* send the Xcpustop IPI to all CPUs in map */
1777 	selected_apic_ipi(map, XCPUSTOP_OFFSET, APIC_DELMODE_FIXED);
1778 
1779 #if defined(DEBUG_CPUSTOP)
1780 	db_printf("  spin\n");
1781 #endif /* DEBUG_CPUSTOP */
1782 
1783 	while (stopped_cpus != map)
1784 		/* spin */ ;
1785 
1786 #if defined(DEBUG_CPUSTOP)
1787 	db_printf("  spun\nstopped\n");
1788 #endif /* DEBUG_CPUSTOP */
1789 
1790 	return 1;
1791 }
1792 
1793 
1794 /*
1795  * Called by a CPU to restart stopped CPUs.
1796  *
1797  * Usually (but not necessarily) called with 'stopped_cpus' as its arg.
1798  *
1799  *  - Signals all CPUs in map to restart.
1800  *  - Waits for each to restart.
1801  *
1802  * Returns:
1803  *  -1: error
1804  *   0: NA
1805  *   1: ok
1806  */
1807 int
1808 restart_cpus( u_int map )
1809 {
1810 	if (!smp_active)
1811 		return 0;
1812 
1813 #if defined(DEBUG_CPUSTOP)
1814 	db_printf("\nCPU%d restarting CPUs: 0x%08x (0x%08x)\n",
1815 	       cpuid, map, stopped_cpus);
1816 #endif /* DEBUG_CPUSTOP */
1817 
1818 	started_cpus = map;		/* signal other cpus to restart */
1819 
1820 	while (started_cpus)		/* wait for each to clear its bit */
1821 		/* spin */ ;
1822 
1823 #if defined(DEBUG_CPUSTOP)
1824 	db_printf(" restarted\n");
1825 #endif /* DEBUG_CPUSTOP */
1826 
1827 	return 1;
1828 }
1829 
1830 #endif  /** TEST_CPUSTOP */
1831