madt.c revision 122502
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 122502 2003-11-11 18:20:10Z 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/acpica/madt.h>
54#include <dev/pci/pcivar.h>
55
56#define	NIOAPICS		32	/* Max number of I/O APICs */
57#define	NLAPICS			32	/* Max number of local APICs */
58
59typedef	void madt_entry_handler(APIC_HEADER *entry, void *arg);
60
61/* These two arrays are indexed by APIC IDs. */
62struct ioapic_info {
63	void *io_apic;
64	UINT32 io_vector;
65} ioapics[NIOAPICS];
66
67struct lapic_info {
68	u_int la_present:1;
69	u_int la_enabled:1;
70	u_int la_apic_id:8;
71} lapics[NLAPICS + 1];
72
73static APIC_TABLE *madt;
74static vm_paddr_t madt_physaddr;
75static vm_offset_t madt_length;
76
77MALLOC_DEFINE(M_MADT, "MADT Table", "ACPI MADT Table Items");
78
79static u_char	interrupt_polarity(UINT16 Polarity);
80static u_char	interrupt_trigger(UINT16 TriggerMode);
81static int	madt_find_cpu(u_int acpi_id, u_int *apic_id);
82static int	madt_find_interrupt(int intr, void **apic, u_int *pin);
83static void	*madt_map(vm_paddr_t pa, int offset, vm_offset_t length);
84static void	*madt_map_table(vm_paddr_t pa, int offset, const char *sig);
85static void	madt_parse_apics(APIC_HEADER *entry, void *arg);
86static void	madt_parse_interrupt_override(INTERRUPT_SOURCE_OVERRIDE *intr);
87static void	madt_parse_ints(APIC_HEADER *entry, void *arg __unused);
88static void	madt_parse_local_nmi(LAPIC_NMI *nmi);
89static void	madt_parse_nmi(NMI *nmi);
90static int	madt_probe(void);
91static int	madt_probe_cpus(void);
92static void	madt_probe_cpus_handler(APIC_HEADER *entry, void *arg __unused);
93static int	madt_probe_table(vm_paddr_t address);
94static void	madt_register(void *dummy);
95static int	madt_setup_local(void);
96static int	madt_setup_io(void);
97static void	madt_unmap(void *data, vm_offset_t length);
98static void	madt_unmap_table(void *table);
99static void	madt_walk_table(madt_entry_handler *handler, void *arg);
100
101static struct apic_enumerator madt_enumerator = {
102	"MADT",
103	madt_probe,
104	madt_probe_cpus,
105	madt_setup_local,
106	madt_setup_io
107};
108
109/*
110 * Code to abuse the crashdump map to map in the tables for the early
111 * probe.  We cheat and make the following assumptions about how we
112 * use this KVA: page 0 is used to map in the first page of each table
113 * found via the RSDT or XSDT and pages 1 to n are used to map in the
114 * RSDT or XSDT.  The offset is in pages; the length is in bytes.
115 */
116static void *
117madt_map(vm_paddr_t pa, int offset, vm_offset_t length)
118{
119	vm_offset_t va, off;
120	void *data;
121
122	off = pa & PAGE_MASK;
123	length = roundup(length + off, PAGE_SIZE);
124	pa = pa & PG_FRAME;
125	va = (vm_offset_t)pmap_kenter_temporary(pa, offset) +
126	    (offset * PAGE_SIZE);
127	data = (void *)(va + off);
128	length -= PAGE_SIZE;
129	while (length > 0) {
130		va += PAGE_SIZE;
131		pa += PAGE_SIZE;
132		length -= PAGE_SIZE;
133		pmap_kenter(va, pa);
134		invlpg(va);
135	}
136	return (data);
137}
138
139static void
140madt_unmap(void *data, vm_offset_t length)
141{
142	vm_offset_t va, off;
143
144	va = (vm_offset_t)data;
145	off = va & PAGE_MASK;
146	length = roundup(length + off, PAGE_SIZE);
147	va &= ~PAGE_MASK;
148	while (length > 0) {
149		pmap_kremove(va);
150		invlpg(va);
151		va += PAGE_SIZE;
152		length -= PAGE_SIZE;
153	}
154}
155
156static void *
157madt_map_table(vm_paddr_t pa, int offset, const char *sig)
158{
159	ACPI_TABLE_HEADER *header;
160	vm_offset_t length;
161
162	header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER));
163	if (strncmp(header->Signature, sig, 4) != 0) {
164		madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
165		return (NULL);
166	}
167	length = header->Length;
168	madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
169	return (madt_map(pa, offset, length));
170}
171
172static void
173madt_unmap_table(void *table)
174{
175	ACPI_TABLE_HEADER *header;
176
177	header = (ACPI_TABLE_HEADER *)table;
178	madt_unmap(table, header->Length);
179}
180
181/*
182 * Look for an ACPI Multiple APIC Description Table ("APIC")
183 */
184static int
185madt_probe(void)
186{
187	ACPI_POINTER rsdp_ptr;
188	RSDP_DESCRIPTOR *rsdp;
189	RSDT_DESCRIPTOR *rsdt;
190	XSDT_DESCRIPTOR *xsdt;
191	int i, count;
192
193	if (resource_disabled("acpi", 0))
194		return (ENXIO);
195
196	/*
197	 * Map in the RSDP.  Since ACPI uses AcpiOsMapMemory() which in turn
198	 * calls pmap_mapdev() to find the RSDP, we assume that we can use
199	 * pmap_mapdev() to map the RSDP.
200	 */
201	if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK)
202		return (ENXIO);
203	KASSERT(rsdp_ptr.Pointer.Physical < KERNLOAD, ("RSDP too high"));
204	rsdp = pmap_mapdev(rsdp_ptr.Pointer.Physical, sizeof(RSDP_DESCRIPTOR));
205	if (rsdp == NULL) {
206		if (bootverbose)
207			printf("MADT: Failed to map RSDP\n");
208		return (ENXIO);
209	}
210
211	/*
212	 * For ACPI < 2.0, use the RSDT.  For ACPI >= 2.0, use the XSDT.
213	 * We map the XSDT and RSDT at page 1 in the crashdump area.
214	 * Page 0 is used to map in the headers of candidate ACPI tables.
215	 */
216	if (rsdp->Revision >= 2) {
217		xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, XSDT_SIG);
218		if (xsdt == NULL) {
219			if (bootverbose)
220				printf("MADT: Failed to map XSDT\n");
221			return (ENXIO);
222		}
223		count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) /
224		    sizeof(UINT64);
225		for (i = 0; i < count; i++)
226			if (madt_probe_table(xsdt->TableOffsetEntry[i]))
227				break;
228		madt_unmap_table(xsdt);
229	} else {
230		rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, RSDT_SIG);
231		if (rsdt == NULL) {
232			if (bootverbose)
233				printf("MADT: Failed to map RSDT\n");
234			return (ENXIO);
235		}
236		count = (rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) /
237		    sizeof(UINT32);
238		for (i = 0; i < count; i++)
239			if (madt_probe_table(rsdt->TableOffsetEntry[i]))
240				break;
241		madt_unmap_table(rsdt);
242	}
243	pmap_unmapdev((vm_offset_t)rsdp, sizeof(RSDP_DESCRIPTOR));
244	if (madt_physaddr == 0) {
245		if (bootverbose)
246			printf("MADT: No MADT table found\n");
247		return (ENXIO);
248	}
249	if (bootverbose)
250		printf("MADT: Found table at 0x%jx\n",
251		    (uintmax_t)madt_physaddr);
252
253	return (0);
254}
255
256/*
257 * See if a given ACPI table is the MADT.
258 */
259static int
260madt_probe_table(vm_paddr_t address)
261{
262	ACPI_TABLE_HEADER *table;
263
264	table = madt_map(address, 0, sizeof(ACPI_TABLE_HEADER));
265	if (table == NULL) {
266		if (bootverbose)
267			printf("MADT: Failed to map table at 0x%jx\n",
268			    (uintmax_t)address);
269		return (0);
270	}
271	if (bootverbose)
272		printf("Table '%.4s' at 0x%jx\n", table->Signature,
273		    (uintmax_t)address);
274
275	/* XXX: Verify checksum? */
276	if (strncmp(table->Signature, APIC_SIG, 4) != 0) {
277		madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
278		return (0);
279	}
280	madt_physaddr = address;
281	madt_length = table->Length;
282	madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
283	return (1);
284}
285
286/*
287 * Run through the MP table enumerating CPUs.
288 */
289static int
290madt_probe_cpus(void)
291{
292
293	madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
294	KASSERT(madt != NULL, ("Unable to re-map MADT"));
295	madt_walk_table(madt_probe_cpus_handler, NULL);
296	madt_unmap_table(madt);
297	madt = NULL;
298	return (0);
299}
300
301/*
302 * Initialize the local APIC on the BSP.
303 */
304static int
305madt_setup_local(void)
306{
307
308	madt = pmap_mapdev(madt_physaddr, madt_length);
309	lapic_init((uintptr_t)madt->LocalApicAddress);
310	printf("ACPI APIC Table: <%.*s %.*s>\n",
311	    sizeof(madt->Header.OemId), madt->Header.OemId,
312	    sizeof(madt->Header.OemTableId), madt->Header.OemTableId);
313
314	/*
315	 * We ignore 64-bit local APIC override entries.  Should we
316	 * perhaps emit a warning here if we find one?
317	 */
318	return (0);
319}
320
321/*
322 * Run through the MP table enumerating I/O APICs.
323 */
324static int
325madt_setup_io(void)
326{
327	int i;
328
329	/* First, we run through adding I/O APIC's. */
330	madt_walk_table(madt_parse_apics, NULL);
331
332	/* Second, we run through the table tweaking interrupt sources. */
333	madt_walk_table(madt_parse_ints, NULL);
334
335	/* Third, we register all the I/O APIC's. */
336	for (i = 0; i < NIOAPICS; i++)
337		if (ioapics[i].io_apic != NULL)
338			ioapic_register(ioapics[i].io_apic);
339
340	/* Finally, we throw the switch to enable the I/O APIC's. */
341	acpi_SetDefaultIntrModel(ACPI_INTR_APIC);
342
343	return (0);
344}
345
346static void
347madt_register(void *dummy __unused)
348{
349
350	apic_register_enumerator(&madt_enumerator);
351}
352SYSINIT(madt_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST,
353    madt_register, NULL)
354
355/*
356 * Call the handler routine for each entry in the MADT table.
357 */
358static void
359madt_walk_table(madt_entry_handler *handler, void *arg)
360{
361	APIC_HEADER *entry;
362	u_char *p, *end;
363
364	end = (u_char *)(madt) + madt->Header.Length;
365	for (p = (u_char *)(madt + 1); p < end; ) {
366		entry = (APIC_HEADER *)p;
367		handler(entry, arg);
368		p += entry->Length;
369	}
370}
371
372static void
373madt_probe_cpus_handler(APIC_HEADER *entry, void *arg)
374{
375	PROCESSOR_APIC *proc;
376	struct lapic_info *la;
377
378	switch (entry->Type) {
379	case APIC_PROC:
380		/*
381		 * The MADT does not include a BSP flag, so we have to
382		 * let the MP code figure out which CPU is the BSP on
383		 * its own.
384		 */
385		proc = (PROCESSOR_APIC *)entry;
386		if (bootverbose)
387			printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n",
388			    proc->LocalApicId, proc->ProcessorApicId,
389			    proc->ProcessorEnabled ? "enabled" : "disabled");
390		if (proc->ProcessorApicId > NLAPICS)
391			panic("%s: CPU ID %d too high", __func__,
392			    proc->ProcessorApicId);
393		la = &lapics[proc->ProcessorApicId];
394		KASSERT(la->la_present == 0,
395		    ("Duplicate local ACPI ID %d", proc->ProcessorApicId));
396		la->la_present = 1;
397		la->la_apic_id = proc->LocalApicId;
398		if (proc->ProcessorEnabled) {
399			la->la_enabled = 1;
400			lapic_create(proc->LocalApicId, 0);
401		}
402		break;
403	}
404}
405
406
407/*
408 * Add an I/O APIC from an entry in the table.
409 */
410static void
411madt_parse_apics(APIC_HEADER *entry, void *arg __unused)
412{
413	IO_APIC *apic;
414
415
416	switch (entry->Type) {
417	case APIC_IO:
418		apic = (IO_APIC *)entry;
419		if (bootverbose)
420			printf("MADT: Found IO APIC ID %d, Vector %d at %p\n",
421			    apic->IoApicId, apic->Vector,
422			    (void *)apic->IoApicAddress);
423		if (apic->IoApicId >= NIOAPICS)
424			panic("%s: I/O APIC ID %d too high", __func__,
425			    apic->IoApicId);
426		if (ioapics[apic->IoApicId].io_apic != NULL)
427			panic("%s: Double APIC ID %d", __func__,
428			    apic->IoApicId);
429		ioapics[apic->IoApicId].io_apic = ioapic_create(
430			(uintptr_t)apic->IoApicAddress, apic->IoApicId,
431			    apic->Vector);
432		ioapics[apic->IoApicId].io_vector = apic->Vector;
433		break;
434	default:
435		break;
436	}
437}
438
439/*
440 * Determine properties of an interrupt source.  Note that for ACPI,
441 * these are only used for ISA interrupts, so we assume ISA bus values
442 * (Active Hi, Edge Triggered) for conforming values.
443 */
444static u_char
445interrupt_polarity(UINT16 Polarity)
446{
447
448	switch (Polarity) {
449	case APIC_POLARITY_CONFORM:
450	case APIC_POLARITY_ACTIVEHI:
451		return (1);
452	case APIC_POLARITY_ACTIVELO:
453		return (0);
454	default:
455		panic("Bogus Interrupt Polarity");
456	}
457}
458
459static u_char
460interrupt_trigger(UINT16 TriggerMode)
461{
462
463	switch (TriggerMode) {
464	case APIC_TRIGGER_CONFORM:
465	case APIC_TRIGGER_EDGE:
466		return (1);
467	case APIC_TRIGGER_LEVEL:
468		return (0);
469	default:
470		panic("Bogus Interrupt Trigger Mode");
471	}
472}
473
474/*
475 * Find the local APIC ID associated with a given ACPI Processor ID.
476 */
477static int
478madt_find_cpu(u_int acpi_id, u_int *apic_id)
479{
480
481	if (!lapics[acpi_id].la_present)
482		return (ENOENT);
483	*apic_id = lapics[acpi_id].la_apic_id;
484	if (lapics[acpi_id].la_enabled)
485		return (0);
486	else
487		return (ENXIO);
488}
489
490/*
491 * Find the IO APIC and pin on that APIC associated with a given global
492 * interrupt.
493 */
494static int
495madt_find_interrupt(int intr, void **apic, u_int *pin)
496{
497	int i, best;
498
499	best = -1;
500	for (i = 0; i < NIOAPICS; i++) {
501		if (ioapics[i].io_apic == NULL ||
502		    ioapics[i].io_vector > intr)
503			continue;
504		if (best == -1 ||
505		    ioapics[best].io_vector < ioapics[i].io_vector)
506			best = i;
507	}
508	if (best == -1)
509		return (ENOENT);
510	*apic = ioapics[best].io_apic;
511	*pin = intr - ioapics[best].io_vector;
512	if (*pin > 32)
513		printf("WARNING: Found intpin of %u for vector %d\n", *pin,
514		    intr);
515	return (0);
516}
517
518/*
519 * Parse an interrupt source override for an ISA interrupt.
520 */
521static void
522madt_parse_interrupt_override(INTERRUPT_SOURCE_OVERRIDE *intr)
523{
524	void *new_ioapic, *old_ioapic;
525	u_int new_pin, old_pin;
526
527	if (bootverbose)
528		printf("MADT: intr override: source %u, irq %u\n",
529		    intr->Source, intr->GlobalSystemInterrupt);
530	KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
531	if (madt_find_interrupt(intr->GlobalSystemInterrupt, &new_ioapic,
532	    &new_pin) != 0) {
533		printf("MADT: Could not find APIC for vector %d (IRQ %d)\n",
534		    intr->GlobalSystemInterrupt, intr->Source);
535		return;
536	}
537
538	if (intr->Source != intr->GlobalSystemInterrupt) {
539		/* XXX: This assumes that the SCI uses IRQ 9. */
540		if (intr->GlobalSystemInterrupt > 15 && intr->Source == 9)
541			acpi_OverrideInterruptLevel(
542				intr->GlobalSystemInterrupt);
543		else
544			ioapic_remap_vector(new_ioapic, new_pin, intr->Source);
545		if (madt_find_interrupt(intr->Source, &old_ioapic,
546		    &old_pin) != 0)
547			printf("MADT: Could not find APIC for source IRQ %d\n",
548			    intr->Source);
549		else if (ioapic_get_vector(old_ioapic, old_pin) ==
550		    intr->Source)
551			ioapic_disable_pin(old_ioapic, old_pin);
552	}
553	ioapic_set_triggermode(new_ioapic, new_pin,
554	    interrupt_trigger(intr->TriggerMode));
555	ioapic_set_polarity(new_ioapic, new_pin,
556	    interrupt_polarity(intr->Polarity));
557}
558
559/*
560 * Parse an entry for an NMI routed to an IO APIC.
561 */
562static void
563madt_parse_nmi(NMI *nmi)
564{
565	void *ioapic;
566	u_int pin;
567
568	if (madt_find_interrupt(nmi->GlobalSystemInterrupt,
569	    &ioapic, &pin) != 0) {
570		printf("MADT: Could not find APIC for vector %d\n",
571		    nmi->GlobalSystemInterrupt);
572		return;
573	}
574
575	ioapic_set_nmi(ioapic, pin);
576	if (nmi->TriggerMode != APIC_TRIGGER_CONFORM)
577		ioapic_set_triggermode(ioapic, pin,
578		    interrupt_trigger(nmi->TriggerMode));
579	if (nmi->Polarity != APIC_TRIGGER_CONFORM)
580		ioapic_set_polarity(ioapic, pin,
581		    interrupt_polarity(nmi->Polarity));
582}
583
584/*
585 * Parse an entry for an NMI routed to a local APIC LVT pin.
586 */
587static void
588madt_parse_local_nmi(LAPIC_NMI *nmi)
589{
590	u_int apic_id, pin;
591
592	if (nmi->ProcessorApicId == 0xff)
593		apic_id = APIC_ID_ALL;
594	else if (madt_find_cpu(nmi->ProcessorApicId, &apic_id) != 0) {
595		if (bootverbose)
596			printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n",
597			    nmi->ProcessorApicId);
598		return;
599	}
600	if (nmi->LINTPin == 0)
601		pin = LVT_LINT0;
602	else
603		pin = LVT_LINT1;
604	lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
605	if (nmi->TriggerMode != APIC_TRIGGER_CONFORM)
606		lapic_set_lvt_triggermode(apic_id, pin,
607		    interrupt_trigger(nmi->TriggerMode));
608	if (nmi->Polarity != APIC_POLARITY_CONFORM)
609		lapic_set_lvt_polarity(apic_id, pin,
610		    interrupt_polarity(nmi->Polarity));
611}
612
613/*
614 * Parse interrupt entries.
615 */
616static void
617madt_parse_ints(APIC_HEADER *entry, void *arg __unused)
618{
619
620	switch (entry->Type) {
621	case APIC_INTERRUPT_SOURCE_OVERRIDE:
622		madt_parse_interrupt_override(
623			(INTERRUPT_SOURCE_OVERRIDE *)entry);
624		break;
625	case APIC_NMI:
626		madt_parse_nmi((NMI *)entry);
627		break;
628	case APIC_LOCAL_APIC_NMI:
629		madt_parse_local_nmi((LAPIC_NMI *)entry);
630		break;
631	}
632}
633
634/*
635 * Setup per-CPU ACPI IDs.
636 */
637static void
638madt_set_ids(void *dummy)
639{
640	struct pcpu *pc;
641	u_int i, j;
642
643	if (madt == NULL)
644		return;
645	for (i = 0; i < MAXCPU; i++) {
646		if (CPU_ABSENT(i))
647			continue;
648		pc = pcpu_find(i);
649		KASSERT(pc != NULL, ("no pcpu data for CPU %d", i));
650		for (j = 0; j < NLAPICS + 1; j++) {
651			if (!lapics[j].la_present || !lapics[j].la_enabled)
652				continue;
653			if (lapics[j].la_apic_id == pc->pc_apic_id) {
654				pc->pc_acpi_id = j;
655				if (bootverbose)
656					printf("APIC: CPU %u has ACPI ID %u\n",
657					    i, j);
658				break;
659			}
660		}
661		if (j == NLAPICS + 1)
662			panic("Unable to find ACPI ID for CPU %d", i);
663	}
664}
665SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL)
666