madt.c revision 128329
1/*-
2 * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
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. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of any co-contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sys/i386/acpica/madt.c 128329 2004-04-16 19:46:30Z jhb $");
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/bus.h>
36#include <sys/kernel.h>
37#include <sys/malloc.h>
38#include <sys/smp.h>
39
40#include <vm/vm.h>
41#include <vm/vm_param.h>
42#include <vm/pmap.h>
43
44#include <machine/apicreg.h>
45#include <machine/frame.h>
46#include <machine/intr_machdep.h>
47#include <machine/apicvar.h>
48#include <machine/md_var.h>
49#include <machine/specialreg.h>
50
51#include "acpi.h"
52#include <dev/acpica/acpivar.h>
53#include <dev/pci/pcivar.h>
54
55#define	NIOAPICS		32	/* Max number of I/O APICs */
56#define	NLAPICS			32	/* Max number of local APICs */
57
58typedef	void madt_entry_handler(APIC_HEADER *entry, void *arg);
59
60/* These two arrays are indexed by APIC IDs. */
61struct ioapic_info {
62	void *io_apic;
63	UINT32 io_vector;
64} ioapics[NIOAPICS];
65
66struct lapic_info {
67	u_int la_present:1;
68	u_int la_enabled:1;
69	u_int la_apic_id:8;
70} lapics[NLAPICS + 1];
71
72static int force_sci_lo;
73TUNABLE_INT("hw.acpi.force_sci_lo", &force_sci_lo);
74static MULTIPLE_APIC_TABLE *madt;
75static vm_paddr_t madt_physaddr;
76static vm_offset_t madt_length;
77
78MALLOC_DEFINE(M_MADT, "MADT Table", "ACPI MADT Table Items");
79
80static u_char	interrupt_polarity(UINT16 Polarity);
81static u_char	interrupt_trigger(UINT16 TriggerMode);
82static int	madt_find_cpu(u_int acpi_id, u_int *apic_id);
83static int	madt_find_interrupt(int intr, void **apic, u_int *pin);
84static void	*madt_map(vm_paddr_t pa, int offset, vm_offset_t length);
85static void	*madt_map_table(vm_paddr_t pa, int offset, const char *sig);
86static void	madt_parse_apics(APIC_HEADER *entry, void *arg);
87static void	madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr);
88static void	madt_parse_ints(APIC_HEADER *entry, void *arg __unused);
89static void	madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi);
90static void	madt_parse_nmi(MADT_NMI_SOURCE *nmi);
91static int	madt_probe(void);
92static int	madt_probe_cpus(void);
93static void	madt_probe_cpus_handler(APIC_HEADER *entry, void *arg __unused);
94static int	madt_probe_table(vm_paddr_t address);
95static void	madt_register(void *dummy);
96static int	madt_setup_local(void);
97static int	madt_setup_io(void);
98static void	madt_unmap(void *data, vm_offset_t length);
99static void	madt_unmap_table(void *table);
100static void	madt_walk_table(madt_entry_handler *handler, void *arg);
101
102static struct apic_enumerator madt_enumerator = {
103	"MADT",
104	madt_probe,
105	madt_probe_cpus,
106	madt_setup_local,
107	madt_setup_io
108};
109
110/*
111 * Code to abuse the crashdump map to map in the tables for the early
112 * probe.  We cheat and make the following assumptions about how we
113 * use this KVA: page 0 is used to map in the first page of each table
114 * found via the RSDT or XSDT and pages 1 to n are used to map in the
115 * RSDT or XSDT.  The offset is in pages; the length is in bytes.
116 */
117static void *
118madt_map(vm_paddr_t pa, int offset, vm_offset_t length)
119{
120	vm_offset_t va, off;
121	void *data;
122
123	off = pa & PAGE_MASK;
124	length = roundup(length + off, PAGE_SIZE);
125	pa = pa & PG_FRAME;
126	va = (vm_offset_t)pmap_kenter_temporary(pa, offset) +
127	    (offset * PAGE_SIZE);
128	data = (void *)(va + off);
129	length -= PAGE_SIZE;
130	while (length > 0) {
131		va += PAGE_SIZE;
132		pa += PAGE_SIZE;
133		length -= PAGE_SIZE;
134		pmap_kenter(va, pa);
135		invlpg(va);
136	}
137	return (data);
138}
139
140static void
141madt_unmap(void *data, vm_offset_t length)
142{
143	vm_offset_t va, off;
144
145	va = (vm_offset_t)data;
146	off = va & PAGE_MASK;
147	length = roundup(length + off, PAGE_SIZE);
148	va &= ~PAGE_MASK;
149	while (length > 0) {
150		pmap_kremove(va);
151		invlpg(va);
152		va += PAGE_SIZE;
153		length -= PAGE_SIZE;
154	}
155}
156
157static void *
158madt_map_table(vm_paddr_t pa, int offset, const char *sig)
159{
160	ACPI_TABLE_HEADER *header;
161	vm_offset_t length;
162
163	header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER));
164	if (strncmp(header->Signature, sig, 4) != 0) {
165		madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
166		return (NULL);
167	}
168	length = header->Length;
169	madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
170	return (madt_map(pa, offset, length));
171}
172
173static void
174madt_unmap_table(void *table)
175{
176	ACPI_TABLE_HEADER *header;
177
178	header = (ACPI_TABLE_HEADER *)table;
179	madt_unmap(table, header->Length);
180}
181
182/*
183 * Look for an ACPI Multiple APIC Description Table ("APIC")
184 */
185static int
186madt_probe(void)
187{
188	ACPI_POINTER rsdp_ptr;
189	RSDP_DESCRIPTOR *rsdp;
190	RSDT_DESCRIPTOR *rsdt;
191	XSDT_DESCRIPTOR *xsdt;
192	int i, count;
193
194	if (resource_disabled("acpi", 0))
195		return (ENXIO);
196
197	/*
198	 * Map in the RSDP.  Since ACPI uses AcpiOsMapMemory() which in turn
199	 * calls pmap_mapdev() to find the RSDP, we assume that we can use
200	 * pmap_mapdev() to map the RSDP.
201	 */
202	if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK)
203		return (ENXIO);
204#ifdef __i386__
205	KASSERT(rsdp_ptr.Pointer.Physical < KERNLOAD, ("RSDP too high"));
206#endif
207	rsdp = pmap_mapdev(rsdp_ptr.Pointer.Physical, sizeof(RSDP_DESCRIPTOR));
208	if (rsdp == NULL) {
209		if (bootverbose)
210			printf("MADT: Failed to map RSDP\n");
211		return (ENXIO);
212	}
213
214	/*
215	 * For ACPI < 2.0, use the RSDT.  For ACPI >= 2.0, use the XSDT.
216	 * We map the XSDT and RSDT at page 1 in the crashdump area.
217	 * Page 0 is used to map in the headers of candidate ACPI tables.
218	 */
219	if (rsdp->Revision >= 2) {
220		xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, XSDT_SIG);
221		if (xsdt == NULL) {
222			if (bootverbose)
223				printf("MADT: Failed to map XSDT\n");
224			return (ENXIO);
225		}
226		count = (xsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
227		    sizeof(UINT64);
228		for (i = 0; i < count; i++)
229			if (madt_probe_table(xsdt->TableOffsetEntry[i]))
230				break;
231		madt_unmap_table(xsdt);
232	} else {
233		rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, RSDT_SIG);
234		if (rsdt == NULL) {
235			if (bootverbose)
236				printf("MADT: Failed to map RSDT\n");
237			return (ENXIO);
238		}
239		count = (rsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
240		    sizeof(UINT32);
241		for (i = 0; i < count; i++)
242			if (madt_probe_table(rsdt->TableOffsetEntry[i]))
243				break;
244		madt_unmap_table(rsdt);
245	}
246	pmap_unmapdev((vm_offset_t)rsdp, sizeof(RSDP_DESCRIPTOR));
247	if (madt_physaddr == 0) {
248		if (bootverbose)
249			printf("MADT: No MADT table found\n");
250		return (ENXIO);
251	}
252	if (bootverbose)
253		printf("MADT: Found table at 0x%jx\n",
254		    (uintmax_t)madt_physaddr);
255
256	return (0);
257}
258
259/*
260 * See if a given ACPI table is the MADT.
261 */
262static int
263madt_probe_table(vm_paddr_t address)
264{
265	ACPI_TABLE_HEADER *table;
266
267	table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER));
268	if (table == NULL) {
269		if (bootverbose)
270			printf("MADT: Failed to map table at 0x%jx\n",
271			    (uintmax_t)address);
272		return (0);
273	}
274	if (bootverbose)
275		printf("Table '%.4s' at 0x%jx\n", table->Signature,
276		    (uintmax_t)address);
277
278	/* XXX: Verify checksum? */
279	if (strncmp(table->Signature, APIC_SIG, 4) != 0) {
280		madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
281		return (0);
282	}
283	madt_physaddr = address;
284	madt_length = table->Length;
285	madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
286	return (1);
287}
288
289/*
290 * Run through the MP table enumerating CPUs.
291 */
292static int
293madt_probe_cpus(void)
294{
295
296	madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
297	KASSERT(madt != NULL, ("Unable to re-map MADT"));
298	madt_walk_table(madt_probe_cpus_handler, NULL);
299	madt_unmap_table(madt);
300	madt = NULL;
301	return (0);
302}
303
304/*
305 * Initialize the local APIC on the BSP.
306 */
307static int
308madt_setup_local(void)
309{
310
311	madt = pmap_mapdev(madt_physaddr, madt_length);
312	lapic_init((uintptr_t)madt->LocalApicAddress);
313	printf("ACPI APIC Table: <%.*s %.*s>\n",
314	    (int)sizeof(madt->OemId), madt->OemId,
315	    (int)sizeof(madt->OemTableId), madt->OemTableId);
316
317	/*
318	 * We ignore 64-bit local APIC override entries.  Should we
319	 * perhaps emit a warning here if we find one?
320	 */
321	return (0);
322}
323
324/*
325 * Enumerate I/O APICs and setup interrupt sources.
326 */
327static int
328madt_setup_io(void)
329{
330	int i;
331
332	/* Try to initialize ACPI so that we can access the FADT. */
333	i = acpi_Startup();
334	if (ACPI_FAILURE(i)) {
335		printf("MADT: ACPI Startup failed with %s\n",
336		    AcpiFormatException(i));
337		printf("Try disabling either ACPI or apic support.\n");
338		panic("Using MADT but ACPI doesn't work");
339	}
340
341	/* First, we run through adding I/O APIC's. */
342	madt_walk_table(madt_parse_apics, NULL);
343
344	/* Second, we run through the table tweaking interrupt sources. */
345	madt_walk_table(madt_parse_ints, NULL);
346
347	/* Third, we register all the I/O APIC's. */
348	for (i = 0; i < NIOAPICS; i++)
349		if (ioapics[i].io_apic != NULL)
350			ioapic_register(ioapics[i].io_apic);
351
352	/* Finally, we throw the switch to enable the I/O APIC's. */
353	acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
354
355	return (0);
356}
357
358static void
359madt_register(void *dummy __unused)
360{
361
362	apic_register_enumerator(&madt_enumerator);
363}
364SYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, madt_register, NULL)
365
366/*
367 * Call the handler routine for each entry in the MADT table.
368 */
369static void
370madt_walk_table(madt_entry_handler *handler, void *arg)
371{
372	APIC_HEADER *entry;
373	u_char *p, *end;
374
375	end = (u_char *)(madt) + madt->Length;
376	for (p = (u_char *)(madt + 1); p < end; ) {
377		entry = (APIC_HEADER *)p;
378		handler(entry, arg);
379		p += entry->Length;
380	}
381}
382
383static void
384madt_probe_cpus_handler(APIC_HEADER *entry, void *arg)
385{
386	MADT_PROCESSOR_APIC *proc;
387	struct lapic_info *la;
388
389	switch (entry->Type) {
390	case APIC_PROCESSOR:
391		/*
392		 * The MADT does not include a BSP flag, so we have to
393		 * let the MP code figure out which CPU is the BSP on
394		 * its own.
395		 */
396		proc = (MADT_PROCESSOR_APIC *)entry;
397		if (bootverbose)
398			printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n",
399			    proc->LocalApicId, proc->ProcessorId,
400			    proc->ProcessorEnabled ? "enabled" : "disabled");
401		if (proc->ProcessorId > NLAPICS)
402			panic("%s: CPU ID %d too high", __func__,
403			    proc->ProcessorId);
404		la = &lapics[proc->ProcessorId];
405		KASSERT(la->la_present == 0,
406		    ("Duplicate local ACPI ID %d", proc->ProcessorId));
407		la->la_present = 1;
408		la->la_apic_id = proc->LocalApicId;
409		if (proc->ProcessorEnabled) {
410			la->la_enabled = 1;
411			lapic_create(proc->LocalApicId, 0);
412		}
413		break;
414	}
415}
416
417
418/*
419 * Add an I/O APIC from an entry in the table.
420 */
421static void
422madt_parse_apics(APIC_HEADER *entry, void *arg __unused)
423{
424	MADT_IO_APIC *apic;
425
426	switch (entry->Type) {
427	case APIC_IO:
428		apic = (MADT_IO_APIC *)entry;
429		if (bootverbose)
430			printf("MADT: Found IO APIC ID %d, Interrupt %d at %p\n",
431			    apic->IoApicId, apic->Interrupt,
432			    (void *)(uintptr_t)apic->Address);
433		if (apic->IoApicId >= NIOAPICS)
434			panic("%s: I/O APIC ID %d too high", __func__,
435			    apic->IoApicId);
436		if (ioapics[apic->IoApicId].io_apic != NULL)
437			panic("%s: Double APIC ID %d", __func__,
438			    apic->IoApicId);
439		ioapics[apic->IoApicId].io_apic = ioapic_create(
440			(uintptr_t)apic->Address, apic->IoApicId,
441			    apic->Interrupt);
442		ioapics[apic->IoApicId].io_vector = apic->Interrupt;
443		break;
444	default:
445		break;
446	}
447}
448
449/*
450 * Determine properties of an interrupt source.  Note that for ACPI,
451 * these are only used for ISA interrupts, so we assume ISA bus values
452 * (Active Hi, Edge Triggered) for conforming values.
453 */
454static u_char
455interrupt_polarity(UINT16 Polarity)
456{
457
458	switch (Polarity) {
459	case POLARITY_CONFORMS:
460	case POLARITY_ACTIVE_HIGH:
461		return (1);
462	case POLARITY_ACTIVE_LOW:
463		return (0);
464	default:
465		panic("Bogus Interrupt Polarity");
466	}
467}
468
469static u_char
470interrupt_trigger(UINT16 TriggerMode)
471{
472
473	switch (TriggerMode) {
474	case TRIGGER_CONFORMS:
475	case TRIGGER_EDGE:
476		return (1);
477	case TRIGGER_LEVEL:
478		return (0);
479	default:
480		panic("Bogus Interrupt Trigger Mode");
481	}
482}
483
484/*
485 * Find the local APIC ID associated with a given ACPI Processor ID.
486 */
487static int
488madt_find_cpu(u_int acpi_id, u_int *apic_id)
489{
490
491	if (!lapics[acpi_id].la_present)
492		return (ENOENT);
493	*apic_id = lapics[acpi_id].la_apic_id;
494	if (lapics[acpi_id].la_enabled)
495		return (0);
496	else
497		return (ENXIO);
498}
499
500/*
501 * Find the IO APIC and pin on that APIC associated with a given global
502 * interrupt.
503 */
504static int
505madt_find_interrupt(int intr, void **apic, u_int *pin)
506{
507	int i, best;
508
509	best = -1;
510	for (i = 0; i < NIOAPICS; i++) {
511		if (ioapics[i].io_apic == NULL ||
512		    ioapics[i].io_vector > intr)
513			continue;
514		if (best == -1 ||
515		    ioapics[best].io_vector < ioapics[i].io_vector)
516			best = i;
517	}
518	if (best == -1)
519		return (ENOENT);
520	*apic = ioapics[best].io_apic;
521	*pin = intr - ioapics[best].io_vector;
522	if (*pin > 32)
523		printf("WARNING: Found intpin of %u for vector %d\n", *pin,
524		    intr);
525	return (0);
526}
527
528/*
529 * Parse an interrupt source override for an ISA interrupt.
530 */
531static void
532madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr)
533{
534	void *new_ioapic, *old_ioapic;
535	u_int new_pin, old_pin;
536	int force_lo;
537
538	if (bootverbose)
539		printf("MADT: intr override: source %u, irq %u\n",
540		    intr->Source, intr->Interrupt);
541	KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
542	if (madt_find_interrupt(intr->Interrupt, &new_ioapic,
543	    &new_pin) != 0) {
544		printf("MADT: Could not find APIC for vector %d (IRQ %d)\n",
545		    intr->Interrupt, intr->Source);
546		return;
547	}
548
549	/*
550	 * If the SCI is identity mapped but has edge trigger and
551	 * active-hi polarity or the force_sci_lo tunable is set,
552	 * force it to use level/lo.
553	 */
554	force_lo = 0;
555	if (intr->Source == AcpiGbl_FADT->SciInt)
556		if (force_sci_lo || (intr->Interrupt == intr->Source &&
557		    intr->TriggerMode == TRIGGER_EDGE &&
558		    intr->Polarity == POLARITY_ACTIVE_HIGH))
559			force_lo = 1;
560
561	if (intr->Source != intr->Interrupt) {
562		/*
563		 * If the SCI is remapped to a non-ISA global interrupt,
564		 * then override the vector we use to setup and allocate
565		 * the interrupt.
566		 */
567		if (intr->Interrupt > 15 &&
568		    intr->Source == AcpiGbl_FADT->SciInt)
569			acpi_OverrideInterruptLevel(intr->Interrupt);
570		else
571			ioapic_remap_vector(new_ioapic, new_pin, intr->Source);
572		if (madt_find_interrupt(intr->Source, &old_ioapic,
573		    &old_pin) != 0)
574			printf("MADT: Could not find APIC for source IRQ %d\n",
575			    intr->Source);
576		else if (ioapic_get_vector(old_ioapic, old_pin) ==
577		    intr->Source)
578			ioapic_disable_pin(old_ioapic, old_pin);
579	}
580	if (force_lo) {
581		printf(
582	"MADT: Forcing active-lo polarity and level trigger for IRQ %d\n",
583		    intr->Source);
584		ioapic_set_polarity(new_ioapic, new_pin, 0);
585		ioapic_set_triggermode(new_ioapic, new_pin, 0);
586	} else {
587		ioapic_set_polarity(new_ioapic, new_pin,
588		    interrupt_polarity(intr->Polarity));
589		ioapic_set_triggermode(new_ioapic, new_pin,
590		    interrupt_trigger(intr->TriggerMode));
591	}
592}
593
594/*
595 * Parse an entry for an NMI routed to an IO APIC.
596 */
597static void
598madt_parse_nmi(MADT_NMI_SOURCE *nmi)
599{
600	void *ioapic;
601	u_int pin;
602
603	if (madt_find_interrupt(nmi->Interrupt, &ioapic, &pin) != 0) {
604		printf("MADT: Could not find APIC for vector %d\n",
605		    nmi->Interrupt);
606		return;
607	}
608
609	ioapic_set_nmi(ioapic, pin);
610	if (nmi->TriggerMode != TRIGGER_CONFORMS)
611		ioapic_set_triggermode(ioapic, pin,
612		    interrupt_trigger(nmi->TriggerMode));
613	if (nmi->Polarity != TRIGGER_CONFORMS)
614		ioapic_set_polarity(ioapic, pin,
615		    interrupt_polarity(nmi->Polarity));
616}
617
618/*
619 * Parse an entry for an NMI routed to a local APIC LVT pin.
620 */
621static void
622madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi)
623{
624	u_int apic_id, pin;
625
626	if (nmi->ProcessorId == 0xff)
627		apic_id = APIC_ID_ALL;
628	else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
629		if (bootverbose)
630			printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n",
631			    nmi->ProcessorId);
632		return;
633	}
634	if (nmi->Lint == 0)
635		pin = LVT_LINT0;
636	else
637		pin = LVT_LINT1;
638	lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
639	if (nmi->TriggerMode != TRIGGER_CONFORMS)
640		lapic_set_lvt_triggermode(apic_id, pin,
641		    interrupt_trigger(nmi->TriggerMode));
642	if (nmi->Polarity != POLARITY_CONFORMS)
643		lapic_set_lvt_polarity(apic_id, pin,
644		    interrupt_polarity(nmi->Polarity));
645}
646
647/*
648 * Parse interrupt entries.
649 */
650static void
651madt_parse_ints(APIC_HEADER *entry, void *arg __unused)
652{
653
654	switch (entry->Type) {
655	case APIC_XRUPT_OVERRIDE:
656		madt_parse_interrupt_override(
657			(MADT_INTERRUPT_OVERRIDE *)entry);
658		break;
659	case APIC_NMI:
660		madt_parse_nmi((MADT_NMI_SOURCE *)entry);
661		break;
662	case APIC_LOCAL_NMI:
663		madt_parse_local_nmi((MADT_LOCAL_APIC_NMI *)entry);
664		break;
665	}
666}
667
668/*
669 * Setup per-CPU ACPI IDs.
670 */
671static void
672madt_set_ids(void *dummy)
673{
674	struct pcpu *pc;
675	u_int i, j;
676
677	if (madt == NULL)
678		return;
679	for (i = 0; i <= mp_maxid; i++) {
680		if (CPU_ABSENT(i))
681			continue;
682		pc = pcpu_find(i);
683		KASSERT(pc != NULL, ("no pcpu data for CPU %d", i));
684		for (j = 0; j < NLAPICS + 1; j++) {
685			if (!lapics[j].la_present || !lapics[j].la_enabled)
686				continue;
687			if (lapics[j].la_apic_id == pc->pc_apic_id) {
688				pc->pc_acpi_id = j;
689				if (bootverbose)
690					printf("APIC: CPU %u has ACPI ID %u\n",
691					    i, j);
692				break;
693			}
694		}
695		if (j == NLAPICS + 1)
696			panic("Unable to find ACPI ID for CPU %d", i);
697	}
698}
699SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL)
700