xref: /freebsd/sys/x86/acpica/madt.c (revision fcb560670601b2a4d87bb31d7531c8dcc37ee71b)
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  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/bus.h>
33 #include <sys/kernel.h>
34 #include <sys/malloc.h>
35 #include <sys/smp.h>
36 #include <vm/vm.h>
37 #include <vm/pmap.h>
38 
39 #include <x86/apicreg.h>
40 #include <machine/intr_machdep.h>
41 #include <x86/apicvar.h>
42 #include <machine/md_var.h>
43 
44 #include <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/actables.h>
46 
47 #include <dev/acpica/acpivar.h>
48 #include <dev/pci/pcivar.h>
49 
50 /* These two arrays are indexed by APIC IDs. */
51 static struct {
52 	void *io_apic;
53 	UINT32 io_vector;
54 } *ioapics;
55 
56 static struct lapic_info {
57 	u_int la_enabled:1;
58 	u_int la_acpi_id:8;
59 } lapics[MAX_APIC_ID + 1];
60 
61 int madt_found_sci_override;
62 static ACPI_TABLE_MADT *madt;
63 static vm_paddr_t madt_physaddr;
64 static vm_offset_t madt_length;
65 
66 static MALLOC_DEFINE(M_MADT, "madt_table", "ACPI MADT Table Items");
67 
68 static enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source);
69 static enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source);
70 static int	madt_find_cpu(u_int acpi_id, u_int *apic_id);
71 static int	madt_find_interrupt(int intr, void **apic, u_int *pin);
72 static void	madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg);
73 static void	madt_parse_interrupt_override(
74 		    ACPI_MADT_INTERRUPT_OVERRIDE *intr);
75 static void	madt_parse_ints(ACPI_SUBTABLE_HEADER *entry,
76 		    void *arg __unused);
77 static void	madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi);
78 static void	madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi);
79 static int	madt_probe(void);
80 static int	madt_probe_cpus(void);
81 static void	madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry,
82 		    void *arg __unused);
83 static void	madt_register(void *dummy);
84 static int	madt_setup_local(void);
85 static int	madt_setup_io(void);
86 static void	madt_walk_table(acpi_subtable_handler *handler, void *arg);
87 
88 static struct apic_enumerator madt_enumerator = {
89 	"MADT",
90 	madt_probe,
91 	madt_probe_cpus,
92 	madt_setup_local,
93 	madt_setup_io
94 };
95 
96 /*
97  * Look for an ACPI Multiple APIC Description Table ("APIC")
98  */
99 static int
100 madt_probe(void)
101 {
102 
103 	madt_physaddr = acpi_find_table(ACPI_SIG_MADT);
104 	if (madt_physaddr == 0)
105 		return (ENXIO);
106 	return (-50);
107 }
108 
109 /*
110  * Run through the MP table enumerating CPUs.
111  */
112 static int
113 madt_probe_cpus(void)
114 {
115 
116 	madt = acpi_map_table(madt_physaddr, ACPI_SIG_MADT);
117 	madt_length = madt->Header.Length;
118 	KASSERT(madt != NULL, ("Unable to re-map MADT"));
119 	madt_walk_table(madt_probe_cpus_handler, NULL);
120 	acpi_unmap_table(madt);
121 	madt = NULL;
122 	return (0);
123 }
124 
125 /*
126  * Initialize the local APIC on the BSP.
127  */
128 static int
129 madt_setup_local(void)
130 {
131 	ACPI_TABLE_DMAR *dmartbl;
132 	vm_paddr_t dmartbl_physaddr;
133 
134 	madt = pmap_mapbios(madt_physaddr, madt_length);
135 	if ((cpu_feature2 & CPUID2_X2APIC) != 0) {
136 		x2apic_mode = 1;
137 		dmartbl_physaddr = acpi_find_table(ACPI_SIG_DMAR);
138 		if (dmartbl_physaddr != 0) {
139 			dmartbl = acpi_map_table(dmartbl_physaddr,
140 			    ACPI_SIG_DMAR);
141 			if ((dmartbl->Flags & ACPI_DMAR_X2APIC_OPT_OUT) != 0) {
142 				x2apic_mode = 0;
143 				if (bootverbose)
144 					printf(
145 		"x2APIC available but disabled by DMAR table\n");
146 			}
147 			acpi_unmap_table(dmartbl);
148 		}
149 		TUNABLE_INT_FETCH("hw.x2apic_enable", &x2apic_mode);
150 	}
151 
152 	lapic_init(madt->Address);
153 	printf("ACPI APIC Table: <%.*s %.*s>\n",
154 	    (int)sizeof(madt->Header.OemId), madt->Header.OemId,
155 	    (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId);
156 
157 	/*
158 	 * We ignore 64-bit local APIC override entries.  Should we
159 	 * perhaps emit a warning here if we find one?
160 	 */
161 	return (0);
162 }
163 
164 /*
165  * Enumerate I/O APICs and setup interrupt sources.
166  */
167 static int
168 madt_setup_io(void)
169 {
170 	void *ioapic;
171 	u_int pin;
172 	int i;
173 
174 	/* Try to initialize ACPI so that we can access the FADT. */
175 	i = acpi_Startup();
176 	if (ACPI_FAILURE(i)) {
177 		printf("MADT: ACPI Startup failed with %s\n",
178 		    AcpiFormatException(i));
179 		printf("Try disabling either ACPI or apic support.\n");
180 		panic("Using MADT but ACPI doesn't work");
181 	}
182 
183 	ioapics = malloc(sizeof(*ioapics) * (MAX_APIC_ID + 1), M_MADT,
184 	    M_WAITOK | M_ZERO);
185 
186 	/* First, we run through adding I/O APIC's. */
187 	madt_walk_table(madt_parse_apics, NULL);
188 
189 	/* Second, we run through the table tweaking interrupt sources. */
190 	madt_walk_table(madt_parse_ints, NULL);
191 
192 	/*
193 	 * If there was not an explicit override entry for the SCI,
194 	 * force it to use level trigger and active-low polarity.
195 	 */
196 	if (!madt_found_sci_override) {
197 		if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic,
198 		    &pin) != 0)
199 			printf("MADT: Could not find APIC for SCI IRQ %u\n",
200 			    AcpiGbl_FADT.SciInterrupt);
201 		else {
202 			printf(
203 	"MADT: Forcing active-low polarity and level trigger for SCI\n");
204 			ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW);
205 			ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL);
206 		}
207 	}
208 
209 	/* Third, we register all the I/O APIC's. */
210 	for (i = 0; i <= MAX_APIC_ID; i++)
211 		if (ioapics[i].io_apic != NULL)
212 			ioapic_register(ioapics[i].io_apic);
213 
214 	/* Finally, we throw the switch to enable the I/O APIC's. */
215 	acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
216 
217 	free(ioapics, M_MADT);
218 	ioapics = NULL;
219 
220 	return (0);
221 }
222 
223 static void
224 madt_register(void *dummy __unused)
225 {
226 
227 	apic_register_enumerator(&madt_enumerator);
228 }
229 SYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, madt_register, NULL);
230 
231 /*
232  * Call the handler routine for each entry in the MADT table.
233  */
234 static void
235 madt_walk_table(acpi_subtable_handler *handler, void *arg)
236 {
237 
238 	acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
239 	    handler, arg);
240 }
241 
242 static void
243 madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
244 {
245 	ACPI_MADT_LOCAL_APIC *proc;
246 	struct lapic_info *la;
247 
248 	switch (entry->Type) {
249 	case ACPI_MADT_TYPE_LOCAL_APIC:
250 		/*
251 		 * The MADT does not include a BSP flag, so we have to
252 		 * let the MP code figure out which CPU is the BSP on
253 		 * its own.
254 		 */
255 		proc = (ACPI_MADT_LOCAL_APIC *)entry;
256 		if (bootverbose)
257 			printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n",
258 			    proc->Id, proc->ProcessorId,
259 			    (proc->LapicFlags & ACPI_MADT_ENABLED) ?
260 			    "enabled" : "disabled");
261 		if (!(proc->LapicFlags & ACPI_MADT_ENABLED))
262 			break;
263 		if (proc->Id > MAX_APIC_ID)
264 			panic("%s: CPU ID %u too high", __func__, proc->Id);
265 		la = &lapics[proc->Id];
266 		KASSERT(la->la_enabled == 0,
267 		    ("Duplicate local APIC ID %u", proc->Id));
268 		la->la_enabled = 1;
269 		la->la_acpi_id = proc->ProcessorId;
270 		lapic_create(proc->Id, 0);
271 		break;
272 	}
273 }
274 
275 
276 /*
277  * Add an I/O APIC from an entry in the table.
278  */
279 static void
280 madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
281 {
282 	ACPI_MADT_IO_APIC *apic;
283 
284 	switch (entry->Type) {
285 	case ACPI_MADT_TYPE_IO_APIC:
286 		apic = (ACPI_MADT_IO_APIC *)entry;
287 		if (bootverbose)
288 			printf(
289 			    "MADT: Found IO APIC ID %u, Interrupt %u at %p\n",
290 			    apic->Id, apic->GlobalIrqBase,
291 			    (void *)(uintptr_t)apic->Address);
292 		if (apic->Id > MAX_APIC_ID)
293 			panic("%s: I/O APIC ID %u too high", __func__,
294 			    apic->Id);
295 		if (ioapics[apic->Id].io_apic != NULL)
296 			panic("%s: Double APIC ID %u", __func__, apic->Id);
297 		if (apic->GlobalIrqBase >= FIRST_MSI_INT) {
298 			printf("MADT: Ignoring bogus I/O APIC ID %u", apic->Id);
299 			break;
300 		}
301 		ioapics[apic->Id].io_apic = ioapic_create(apic->Address,
302 		    apic->Id, apic->GlobalIrqBase);
303 		ioapics[apic->Id].io_vector = apic->GlobalIrqBase;
304 		break;
305 	default:
306 		break;
307 	}
308 }
309 
310 /*
311  * Determine properties of an interrupt source.  Note that for ACPI these
312  * functions are only used for ISA interrupts, so we assume ISA bus values
313  * (Active Hi, Edge Triggered) for conforming values except for the ACPI
314  * SCI for which we use Active Lo, Level Triggered.
315  */
316 static enum intr_polarity
317 interrupt_polarity(UINT16 IntiFlags, UINT8 Source)
318 {
319 
320 	switch (IntiFlags & ACPI_MADT_POLARITY_MASK) {
321 	default:
322 		printf("WARNING: Bogus Interrupt Polarity. Assume CONFORMS\n");
323 		/* FALLTHROUGH*/
324 	case ACPI_MADT_POLARITY_CONFORMS:
325 		if (Source == AcpiGbl_FADT.SciInterrupt)
326 			return (INTR_POLARITY_LOW);
327 		else
328 			return (INTR_POLARITY_HIGH);
329 	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
330 		return (INTR_POLARITY_HIGH);
331 	case ACPI_MADT_POLARITY_ACTIVE_LOW:
332 		return (INTR_POLARITY_LOW);
333 	}
334 }
335 
336 static enum intr_trigger
337 interrupt_trigger(UINT16 IntiFlags, UINT8 Source)
338 {
339 
340 	switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) {
341 	default:
342 		printf("WARNING: Bogus Interrupt Trigger Mode. Assume CONFORMS.\n");
343 		/*FALLTHROUGH*/
344 	case ACPI_MADT_TRIGGER_CONFORMS:
345 		if (Source == AcpiGbl_FADT.SciInterrupt)
346 			return (INTR_TRIGGER_LEVEL);
347 		else
348 			return (INTR_TRIGGER_EDGE);
349 	case ACPI_MADT_TRIGGER_EDGE:
350 		return (INTR_TRIGGER_EDGE);
351 	case ACPI_MADT_TRIGGER_LEVEL:
352 		return (INTR_TRIGGER_LEVEL);
353 	}
354 }
355 
356 /*
357  * Find the local APIC ID associated with a given ACPI Processor ID.
358  */
359 static int
360 madt_find_cpu(u_int acpi_id, u_int *apic_id)
361 {
362 	int i;
363 
364 	for (i = 0; i <= MAX_APIC_ID; i++) {
365 		if (!lapics[i].la_enabled)
366 			continue;
367 		if (lapics[i].la_acpi_id != acpi_id)
368 			continue;
369 		*apic_id = i;
370 		return (0);
371 	}
372 	return (ENOENT);
373 }
374 
375 /*
376  * Find the IO APIC and pin on that APIC associated with a given global
377  * interrupt.
378  */
379 static int
380 madt_find_interrupt(int intr, void **apic, u_int *pin)
381 {
382 	int i, best;
383 
384 	best = -1;
385 	for (i = 0; i <= MAX_APIC_ID; i++) {
386 		if (ioapics[i].io_apic == NULL ||
387 		    ioapics[i].io_vector > intr)
388 			continue;
389 		if (best == -1 ||
390 		    ioapics[best].io_vector < ioapics[i].io_vector)
391 			best = i;
392 	}
393 	if (best == -1)
394 		return (ENOENT);
395 	*apic = ioapics[best].io_apic;
396 	*pin = intr - ioapics[best].io_vector;
397 	if (*pin > 32)
398 		printf("WARNING: Found intpin of %u for vector %d\n", *pin,
399 		    intr);
400 	return (0);
401 }
402 
403 void
404 madt_parse_interrupt_values(void *entry,
405     enum intr_trigger *trig, enum intr_polarity *pol)
406 {
407 	ACPI_MADT_INTERRUPT_OVERRIDE *intr;
408 	char buf[64];
409 
410 	intr = entry;
411 
412 	if (bootverbose)
413 		printf("MADT: Interrupt override: source %u, irq %u\n",
414 		    intr->SourceIrq, intr->GlobalIrq);
415 	KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
416 
417 	/*
418 	 * Lookup the appropriate trigger and polarity modes for this
419 	 * entry.
420 	 */
421 	*trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq);
422 	*pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq);
423 
424 	/*
425 	 * If the SCI is identity mapped but has edge trigger and
426 	 * active-hi polarity or the force_sci_lo tunable is set,
427 	 * force it to use level/lo.
428 	 */
429 	if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) {
430 		madt_found_sci_override = 1;
431 		if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
432 			if (tolower(buf[0]) == 'e')
433 				*trig = INTR_TRIGGER_EDGE;
434 			else if (tolower(buf[0]) == 'l')
435 				*trig = INTR_TRIGGER_LEVEL;
436 			else
437 				panic(
438 				"Invalid trigger %s: must be 'edge' or 'level'",
439 				    buf);
440 			printf("MADT: Forcing SCI to %s trigger\n",
441 			    *trig == INTR_TRIGGER_EDGE ? "edge" : "level");
442 		}
443 		if (getenv_string("hw.acpi.sci.polarity", buf, sizeof(buf))) {
444 			if (tolower(buf[0]) == 'h')
445 				*pol = INTR_POLARITY_HIGH;
446 			else if (tolower(buf[0]) == 'l')
447 				*pol = INTR_POLARITY_LOW;
448 			else
449 				panic(
450 				"Invalid polarity %s: must be 'high' or 'low'",
451 				    buf);
452 			printf("MADT: Forcing SCI to active %s polarity\n",
453 			    *pol == INTR_POLARITY_HIGH ? "high" : "low");
454 		}
455 	}
456 }
457 
458 /*
459  * Parse an interrupt source override for an ISA interrupt.
460  */
461 static void
462 madt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr)
463 {
464 	void *new_ioapic, *old_ioapic;
465 	u_int new_pin, old_pin;
466 	enum intr_trigger trig;
467 	enum intr_polarity pol;
468 
469 	if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 &&
470 	    intr->GlobalIrq == 2) {
471 		if (bootverbose)
472 			printf("MADT: Skipping timer override\n");
473 		return;
474 	}
475 
476 	if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) {
477 		printf("MADT: Could not find APIC for vector %u (IRQ %u)\n",
478 		    intr->GlobalIrq, intr->SourceIrq);
479 		return;
480 	}
481 
482 	madt_parse_interrupt_values(intr, &trig, &pol);
483 
484 	/* Remap the IRQ if it is mapped to a different interrupt vector. */
485 	if (intr->SourceIrq != intr->GlobalIrq) {
486 		/*
487 		 * If the SCI is remapped to a non-ISA global interrupt,
488 		 * then override the vector we use to setup and allocate
489 		 * the interrupt.
490 		 */
491 		if (intr->GlobalIrq > 15 &&
492 		    intr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
493 			acpi_OverrideInterruptLevel(intr->GlobalIrq);
494 		else
495 			ioapic_remap_vector(new_ioapic, new_pin,
496 			    intr->SourceIrq);
497 		if (madt_find_interrupt(intr->SourceIrq, &old_ioapic,
498 		    &old_pin) != 0)
499 			printf("MADT: Could not find APIC for source IRQ %u\n",
500 			    intr->SourceIrq);
501 		else if (ioapic_get_vector(old_ioapic, old_pin) ==
502 		    intr->SourceIrq)
503 			ioapic_disable_pin(old_ioapic, old_pin);
504 	}
505 
506 	/* Program the polarity and trigger mode. */
507 	ioapic_set_triggermode(new_ioapic, new_pin, trig);
508 	ioapic_set_polarity(new_ioapic, new_pin, pol);
509 }
510 
511 /*
512  * Parse an entry for an NMI routed to an IO APIC.
513  */
514 static void
515 madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi)
516 {
517 	void *ioapic;
518 	u_int pin;
519 
520 	if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) {
521 		printf("MADT: Could not find APIC for vector %u\n",
522 		    nmi->GlobalIrq);
523 		return;
524 	}
525 
526 	ioapic_set_nmi(ioapic, pin);
527 	if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
528 		ioapic_set_triggermode(ioapic, pin,
529 		    interrupt_trigger(nmi->IntiFlags, 0));
530 	if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
531 		ioapic_set_polarity(ioapic, pin,
532 		    interrupt_polarity(nmi->IntiFlags, 0));
533 }
534 
535 /*
536  * Parse an entry for an NMI routed to a local APIC LVT pin.
537  */
538 static void
539 madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi)
540 {
541 	u_int apic_id, pin;
542 
543 	if (nmi->ProcessorId == 0xff)
544 		apic_id = APIC_ID_ALL;
545 	else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
546 		if (bootverbose)
547 			printf("MADT: Ignoring local NMI routed to "
548 			    "ACPI CPU %u\n", nmi->ProcessorId);
549 		return;
550 	}
551 	if (nmi->Lint == 0)
552 		pin = APIC_LVT_LINT0;
553 	else
554 		pin = APIC_LVT_LINT1;
555 	lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
556 	if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
557 		lapic_set_lvt_triggermode(apic_id, pin,
558 		    interrupt_trigger(nmi->IntiFlags, 0));
559 	if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
560 		lapic_set_lvt_polarity(apic_id, pin,
561 		    interrupt_polarity(nmi->IntiFlags, 0));
562 }
563 
564 /*
565  * Parse interrupt entries.
566  */
567 static void
568 madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
569 {
570 
571 	switch (entry->Type) {
572 	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
573 		madt_parse_interrupt_override(
574 			(ACPI_MADT_INTERRUPT_OVERRIDE *)entry);
575 		break;
576 	case ACPI_MADT_TYPE_NMI_SOURCE:
577 		madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry);
578 		break;
579 	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
580 		madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry);
581 		break;
582 	}
583 }
584 
585 /*
586  * Setup per-CPU ACPI IDs.
587  */
588 static void
589 madt_set_ids(void *dummy)
590 {
591 	struct lapic_info *la;
592 	struct pcpu *pc;
593 	u_int i;
594 
595 	if (madt == NULL)
596 		return;
597 	CPU_FOREACH(i) {
598 		pc = pcpu_find(i);
599 		KASSERT(pc != NULL, ("no pcpu data for CPU %u", i));
600 		la = &lapics[pc->pc_apic_id];
601 		if (!la->la_enabled)
602 			panic("APIC: CPU with APIC ID %u is not enabled",
603 			    pc->pc_apic_id);
604 		pc->pc_acpi_id = la->la_acpi_id;
605 		if (bootverbose)
606 			printf("APIC: CPU %u has ACPI ID %u\n", i,
607 			    la->la_acpi_id);
608 	}
609 }
610 SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_MIDDLE, madt_set_ids, NULL);
611