Deleted Added
full compact
madt.c (167247) madt.c (167814)
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

--- 14 unchanged lines hidden (view full) ---

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>
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

--- 14 unchanged lines hidden (view full) ---

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 167247 2007-03-05 20:35:17Z jhb $");
31__FBSDID("$FreeBSD: head/sys/i386/acpica/madt.c 167814 2007-03-22 18:16:43Z jkim $");
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

--- 11 unchanged lines hidden (view full) ---

51#include <contrib/dev/acpica/acpi.h>
52#include <contrib/dev/acpica/actables.h>
53#include <dev/acpica/acpivar.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
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

--- 11 unchanged lines hidden (view full) ---

51#include <contrib/dev/acpica/acpi.h>
52#include <contrib/dev/acpica/actables.h>
53#include <dev/acpica/acpivar.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);
59typedef void madt_entry_handler(ACPI_SUBTABLE_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_enabled:1;
69 u_int la_acpi_id:8;
70} lapics[NLAPICS];
71
72static int madt_found_sci_override;
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_enabled:1;
69 u_int la_acpi_id:8;
70} lapics[NLAPICS];
71
72static int madt_found_sci_override;
73static MULTIPLE_APIC_TABLE *madt;
73static ACPI_TABLE_MADT *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
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 enum intr_polarity interrupt_polarity(UINT16 Polarity, UINT8 Source);
80static enum intr_trigger interrupt_trigger(UINT16 TriggerMode, UINT8 Source);
79static enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source);
80static enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source);
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);
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(MADT_INTERRUPT_OVERRIDE *intr);
87static void madt_parse_ints(APIC_HEADER *entry, void *arg __unused);
88static void madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi);
89static void madt_parse_nmi(MADT_NMI_SOURCE *nmi);
85static void madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg);
86static void madt_parse_interrupt_override(
87 ACPI_MADT_INTERRUPT_OVERRIDE *intr);
88static void madt_parse_ints(ACPI_SUBTABLE_HEADER *entry,
89 void *arg __unused);
90static void madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi);
91static void madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi);
90static int madt_probe(void);
91static int madt_probe_cpus(void);
92static int madt_probe(void);
93static int madt_probe_cpus(void);
92static void madt_probe_cpus_handler(APIC_HEADER *entry, void *arg __unused);
94static void madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry,
95 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

--- 55 unchanged lines hidden (view full) ---

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 void *table;
162
163 header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER));
96static int madt_probe_table(vm_paddr_t address);
97static void madt_register(void *dummy);
98static int madt_setup_local(void);
99static int madt_setup_io(void);
100static void madt_unmap(void *data, vm_offset_t length);
101static void madt_unmap_table(void *table);
102static void madt_walk_table(madt_entry_handler *handler, void *arg);
103

--- 55 unchanged lines hidden (view full) ---

159static void *
160madt_map_table(vm_paddr_t pa, int offset, const char *sig)
161{
162 ACPI_TABLE_HEADER *header;
163 vm_offset_t length;
164 void *table;
165
166 header = madt_map(pa, offset, sizeof(ACPI_TABLE_HEADER));
164 if (strncmp(header->Signature, sig, 4) != 0) {
167 if (strncmp(header->Signature, sig, ACPI_NAME_SIZE) != 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 table = madt_map(pa, offset, length);
168 madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
169 return (NULL);
170 }
171 length = header->Length;
172 madt_unmap(header, sizeof(ACPI_TABLE_HEADER));
173 table = madt_map(pa, offset, length);
171 if (ACPI_FAILURE(AcpiTbVerifyTableChecksum(table))) {
174 if (ACPI_FAILURE(AcpiTbChecksum(table, length))) {
172 if (bootverbose)
173 printf("MADT: Failed checksum for table %s\n", sig);
174 madt_unmap(table, length);
175 return (NULL);
176 }
177 return (table);
178}
179

--- 7 unchanged lines hidden (view full) ---

187}
188
189/*
190 * Look for an ACPI Multiple APIC Description Table ("APIC")
191 */
192static int
193madt_probe(void)
194{
175 if (bootverbose)
176 printf("MADT: Failed checksum for table %s\n", sig);
177 madt_unmap(table, length);
178 return (NULL);
179 }
180 return (table);
181}
182

--- 7 unchanged lines hidden (view full) ---

190}
191
192/*
193 * Look for an ACPI Multiple APIC Description Table ("APIC")
194 */
195static int
196madt_probe(void)
197{
195 ACPI_POINTER rsdp_ptr;
196 RSDP_DESCRIPTOR *rsdp;
197 RSDT_DESCRIPTOR *rsdt;
198 XSDT_DESCRIPTOR *xsdt;
198 ACPI_PHYSICAL_ADDRESS rsdp_ptr;
199 ACPI_TABLE_RSDP *rsdp;
200 ACPI_TABLE_RSDT *rsdt;
201 ACPI_TABLE_XSDT *xsdt;
199 int i, count;
200
201 if (resource_disabled("acpi", 0))
202 return (ENXIO);
203
204 /*
205 * Map in the RSDP. Since ACPI uses AcpiOsMapMemory() which in turn
206 * calls pmap_mapbios() to find the RSDP, we assume that we can use
207 * pmap_mapbios() to map the RSDP.
208 */
202 int i, count;
203
204 if (resource_disabled("acpi", 0))
205 return (ENXIO);
206
207 /*
208 * Map in the RSDP. Since ACPI uses AcpiOsMapMemory() which in turn
209 * calls pmap_mapbios() to find the RSDP, we assume that we can use
210 * pmap_mapbios() to map the RSDP.
211 */
209 if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK)
212 if ((rsdp_ptr = AcpiOsGetRootPointer()) == 0)
210 return (ENXIO);
213 return (ENXIO);
211#ifdef __i386__
212 KASSERT(rsdp_ptr.Pointer.Physical < KERNLOAD, ("RSDP too high"));
213#endif
214 rsdp = pmap_mapbios(rsdp_ptr.Pointer.Physical, sizeof(RSDP_DESCRIPTOR));
214 rsdp = pmap_mapbios(rsdp_ptr, sizeof(ACPI_TABLE_RSDP));
215 if (rsdp == NULL) {
216 if (bootverbose)
217 printf("MADT: Failed to map RSDP\n");
218 return (ENXIO);
219 }
220
221 /*
222 * For ACPI >= 2.0, use the XSDT if it is available.
223 * Otherwise, use the RSDT. We map the XSDT or RSDT at page 1
224 * in the crashdump area. Page 0 is used to map in the
225 * headers of candidate ACPI tables.
226 */
227 if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) {
228 /*
229 * AcpiOsGetRootPointer only verifies the checksum for
230 * the version 1.0 portion of the RSDP. Version 2.0 has
231 * an additional checksum that we verify first.
232 */
215 if (rsdp == NULL) {
216 if (bootverbose)
217 printf("MADT: Failed to map RSDP\n");
218 return (ENXIO);
219 }
220
221 /*
222 * For ACPI >= 2.0, use the XSDT if it is available.
223 * Otherwise, use the RSDT. We map the XSDT or RSDT at page 1
224 * in the crashdump area. Page 0 is used to map in the
225 * headers of candidate ACPI tables.
226 */
227 if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) {
228 /*
229 * AcpiOsGetRootPointer only verifies the checksum for
230 * the version 1.0 portion of the RSDP. Version 2.0 has
231 * an additional checksum that we verify first.
232 */
233 if (AcpiTbGenerateChecksum(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH)) {
233 if (AcpiTbChecksum((UINT8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH)) {
234 if (bootverbose)
235 printf("MADT: RSDP failed extended checksum\n");
236 return (ENXIO);
237 }
234 if (bootverbose)
235 printf("MADT: RSDP failed extended checksum\n");
236 return (ENXIO);
237 }
238 xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1, XSDT_SIG);
238 xsdt = madt_map_table(rsdp->XsdtPhysicalAddress, 1,
239 ACPI_SIG_XSDT);
239 if (xsdt == NULL) {
240 if (bootverbose)
241 printf("MADT: Failed to map XSDT\n");
242 return (ENXIO);
243 }
240 if (xsdt == NULL) {
241 if (bootverbose)
242 printf("MADT: Failed to map XSDT\n");
243 return (ENXIO);
244 }
244 count = (xsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
245 count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) /
245 sizeof(UINT64);
246 for (i = 0; i < count; i++)
247 if (madt_probe_table(xsdt->TableOffsetEntry[i]))
248 break;
249 madt_unmap_table(xsdt);
250 } else {
246 sizeof(UINT64);
247 for (i = 0; i < count; i++)
248 if (madt_probe_table(xsdt->TableOffsetEntry[i]))
249 break;
250 madt_unmap_table(xsdt);
251 } else {
251 rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1, RSDT_SIG);
252 rsdt = madt_map_table(rsdp->RsdtPhysicalAddress, 1,
253 ACPI_SIG_RSDT);
252 if (rsdt == NULL) {
253 if (bootverbose)
254 printf("MADT: Failed to map RSDT\n");
255 return (ENXIO);
256 }
254 if (rsdt == NULL) {
255 if (bootverbose)
256 printf("MADT: Failed to map RSDT\n");
257 return (ENXIO);
258 }
257 count = (rsdt->Length - sizeof(ACPI_TABLE_HEADER)) /
259 count = (rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) /
258 sizeof(UINT32);
259 for (i = 0; i < count; i++)
260 if (madt_probe_table(rsdt->TableOffsetEntry[i]))
261 break;
262 madt_unmap_table(rsdt);
263 }
260 sizeof(UINT32);
261 for (i = 0; i < count; i++)
262 if (madt_probe_table(rsdt->TableOffsetEntry[i]))
263 break;
264 madt_unmap_table(rsdt);
265 }
264 pmap_unmapbios((vm_offset_t)rsdp, sizeof(RSDP_DESCRIPTOR));
266 pmap_unmapbios((vm_offset_t)rsdp, sizeof(ACPI_TABLE_RSDP));
265 if (madt_physaddr == 0) {
266 if (bootverbose)
267 printf("MADT: No MADT table found\n");
268 return (ENXIO);
269 }
270 if (bootverbose)
271 printf("MADT: Found table at 0x%jx\n",
272 (uintmax_t)madt_physaddr);
273
274 /*
275 * Verify that we can map the full table and that its checksum is
276 * correct, etc.
277 */
267 if (madt_physaddr == 0) {
268 if (bootverbose)
269 printf("MADT: No MADT table found\n");
270 return (ENXIO);
271 }
272 if (bootverbose)
273 printf("MADT: Found table at 0x%jx\n",
274 (uintmax_t)madt_physaddr);
275
276 /*
277 * Verify that we can map the full table and that its checksum is
278 * correct, etc.
279 */
278 madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
280 madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT);
279 if (madt == NULL)
280 return (ENXIO);
281 madt_unmap_table(madt);
282 madt = NULL;
283
284 return (0);
285}
286

--- 11 unchanged lines hidden (view full) ---

298 printf("MADT: Failed to map table at 0x%jx\n",
299 (uintmax_t)address);
300 return (0);
301 }
302 if (bootverbose)
303 printf("Table '%.4s' at 0x%jx\n", table->Signature,
304 (uintmax_t)address);
305
281 if (madt == NULL)
282 return (ENXIO);
283 madt_unmap_table(madt);
284 madt = NULL;
285
286 return (0);
287}
288

--- 11 unchanged lines hidden (view full) ---

300 printf("MADT: Failed to map table at 0x%jx\n",
301 (uintmax_t)address);
302 return (0);
303 }
304 if (bootverbose)
305 printf("Table '%.4s' at 0x%jx\n", table->Signature,
306 (uintmax_t)address);
307
306 if (strncmp(table->Signature, APIC_SIG, 4) != 0) {
308 if (strncmp(table->Signature, ACPI_SIG_MADT, ACPI_NAME_SIZE) != 0) {
307 madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
308 return (0);
309 }
310 madt_physaddr = address;
311 madt_length = table->Length;
312 madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
313 return (1);
314}
315
316/*
317 * Run through the MP table enumerating CPUs.
318 */
319static int
320madt_probe_cpus(void)
321{
322
309 madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
310 return (0);
311 }
312 madt_physaddr = address;
313 madt_length = table->Length;
314 madt_unmap(table, sizeof(ACPI_TABLE_HEADER));
315 return (1);
316}
317
318/*
319 * Run through the MP table enumerating CPUs.
320 */
321static int
322madt_probe_cpus(void)
323{
324
323 madt = madt_map_table(madt_physaddr, 0, APIC_SIG);
325 madt = madt_map_table(madt_physaddr, 0, ACPI_SIG_MADT);
324 KASSERT(madt != NULL, ("Unable to re-map MADT"));
325 madt_walk_table(madt_probe_cpus_handler, NULL);
326 madt_unmap_table(madt);
327 madt = NULL;
328 return (0);
329}
330
331/*
332 * Initialize the local APIC on the BSP.
333 */
334static int
335madt_setup_local(void)
336{
337
338 madt = pmap_mapbios(madt_physaddr, madt_length);
326 KASSERT(madt != NULL, ("Unable to re-map MADT"));
327 madt_walk_table(madt_probe_cpus_handler, NULL);
328 madt_unmap_table(madt);
329 madt = NULL;
330 return (0);
331}
332
333/*
334 * Initialize the local APIC on the BSP.
335 */
336static int
337madt_setup_local(void)
338{
339
340 madt = pmap_mapbios(madt_physaddr, madt_length);
339 lapic_init(madt->LocalApicAddress);
341 lapic_init(madt->Address);
340 printf("ACPI APIC Table: <%.*s %.*s>\n",
342 printf("ACPI APIC Table: <%.*s %.*s>\n",
341 (int)sizeof(madt->OemId), madt->OemId,
342 (int)sizeof(madt->OemTableId), madt->OemTableId);
343 (int)sizeof(madt->Header.OemId), madt->Header.OemId,
344 (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId);
343
344 /*
345 * We ignore 64-bit local APIC override entries. Should we
346 * perhaps emit a warning here if we find one?
347 */
348 return (0);
349}
350

--- 22 unchanged lines hidden (view full) ---

373 /* Second, we run through the table tweaking interrupt sources. */
374 madt_walk_table(madt_parse_ints, NULL);
375
376 /*
377 * If there was not an explicit override entry for the SCI,
378 * force it to use level trigger and active-low polarity.
379 */
380 if (!madt_found_sci_override) {
345
346 /*
347 * We ignore 64-bit local APIC override entries. Should we
348 * perhaps emit a warning here if we find one?
349 */
350 return (0);
351}
352

--- 22 unchanged lines hidden (view full) ---

375 /* Second, we run through the table tweaking interrupt sources. */
376 madt_walk_table(madt_parse_ints, NULL);
377
378 /*
379 * If there was not an explicit override entry for the SCI,
380 * force it to use level trigger and active-low polarity.
381 */
382 if (!madt_found_sci_override) {
381 if (madt_find_interrupt(AcpiGbl_FADT->SciInt, &ioapic, &pin)
382 != 0)
383 printf("MADT: Could not find APIC for SCI IRQ %d\n",
384 AcpiGbl_FADT->SciInt);
383 if (madt_find_interrupt(AcpiGbl_FADT.SciInterrupt, &ioapic,
384 &pin) != 0)
385 printf("MADT: Could not find APIC for SCI IRQ %u\n",
386 AcpiGbl_FADT.SciInterrupt);
385 else {
386 printf(
387 "MADT: Forcing active-low polarity and level trigger for SCI\n");
388 ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW);
389 ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL);
390 }
391 }
392

--- 17 unchanged lines hidden (view full) ---

410SYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, madt_register, NULL)
411
412/*
413 * Call the handler routine for each entry in the MADT table.
414 */
415static void
416madt_walk_table(madt_entry_handler *handler, void *arg)
417{
387 else {
388 printf(
389 "MADT: Forcing active-low polarity and level trigger for SCI\n");
390 ioapic_set_polarity(ioapic, pin, INTR_POLARITY_LOW);
391 ioapic_set_triggermode(ioapic, pin, INTR_TRIGGER_LEVEL);
392 }
393 }
394

--- 17 unchanged lines hidden (view full) ---

412SYSINIT(madt_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, madt_register, NULL)
413
414/*
415 * Call the handler routine for each entry in the MADT table.
416 */
417static void
418madt_walk_table(madt_entry_handler *handler, void *arg)
419{
418 APIC_HEADER *entry;
420 ACPI_SUBTABLE_HEADER *entry;
419 u_char *p, *end;
420
421 u_char *p, *end;
422
421 end = (u_char *)(madt) + madt->Length;
423 end = (u_char *)(madt) + madt->Header.Length;
422 for (p = (u_char *)(madt + 1); p < end; ) {
424 for (p = (u_char *)(madt + 1); p < end; ) {
423 entry = (APIC_HEADER *)p;
425 entry = (ACPI_SUBTABLE_HEADER *)p;
424 handler(entry, arg);
425 p += entry->Length;
426 }
427}
428
429static void
426 handler(entry, arg);
427 p += entry->Length;
428 }
429}
430
431static void
430madt_probe_cpus_handler(APIC_HEADER *entry, void *arg)
432madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
431{
433{
432 MADT_PROCESSOR_APIC *proc;
434 ACPI_MADT_LOCAL_APIC *proc;
433 struct lapic_info *la;
434
435 switch (entry->Type) {
435 struct lapic_info *la;
436
437 switch (entry->Type) {
436 case APIC_PROCESSOR:
438 case ACPI_MADT_TYPE_LOCAL_APIC:
437 /*
438 * The MADT does not include a BSP flag, so we have to
439 * let the MP code figure out which CPU is the BSP on
440 * its own.
441 */
439 /*
440 * The MADT does not include a BSP flag, so we have to
441 * let the MP code figure out which CPU is the BSP on
442 * its own.
443 */
442 proc = (MADT_PROCESSOR_APIC *)entry;
444 proc = (ACPI_MADT_LOCAL_APIC *)entry;
443 if (bootverbose)
445 if (bootverbose)
444 printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n",
445 proc->LocalApicId, proc->ProcessorId,
446 proc->ProcessorEnabled ? "enabled" : "disabled");
447 if (!proc->ProcessorEnabled)
446 printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n",
447 proc->Id, proc->ProcessorId,
448 (proc->LapicFlags & ACPI_MADT_ENABLED) ?
449 "enabled" : "disabled");
450 if (!(proc->LapicFlags & ACPI_MADT_ENABLED))
448 break;
451 break;
449 if (proc->LocalApicId >= NLAPICS)
450 panic("%s: CPU ID %d too high", __func__,
451 proc->LocalApicId);
452 la = &lapics[proc->LocalApicId];
452 if (proc->Id >= NLAPICS)
453 panic("%s: CPU ID %u too high", __func__, proc->Id);
454 la = &lapics[proc->Id];
453 KASSERT(la->la_enabled == 0,
455 KASSERT(la->la_enabled == 0,
454 ("Duplicate local APIC ID %d", proc->LocalApicId));
456 ("Duplicate local APIC ID %u", proc->Id));
455 la->la_enabled = 1;
456 la->la_acpi_id = proc->ProcessorId;
457 la->la_enabled = 1;
458 la->la_acpi_id = proc->ProcessorId;
457 lapic_create(proc->LocalApicId, 0);
459 lapic_create(proc->Id, 0);
458 break;
459 }
460}
461
462
463/*
464 * Add an I/O APIC from an entry in the table.
465 */
466static void
460 break;
461 }
462}
463
464
465/*
466 * Add an I/O APIC from an entry in the table.
467 */
468static void
467madt_parse_apics(APIC_HEADER *entry, void *arg __unused)
469madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
468{
470{
469 MADT_IO_APIC *apic;
471 ACPI_MADT_IO_APIC *apic;
470
471 switch (entry->Type) {
472
473 switch (entry->Type) {
472 case APIC_IO:
473 apic = (MADT_IO_APIC *)entry;
474 case ACPI_MADT_TYPE_IO_APIC:
475 apic = (ACPI_MADT_IO_APIC *)entry;
474 if (bootverbose)
476 if (bootverbose)
475 printf("MADT: Found IO APIC ID %d, Interrupt %d at %p\n",
476 apic->IoApicId, apic->Interrupt,
477 printf(
478 "MADT: Found IO APIC ID %u, Interrupt %u at %p\n",
479 apic->Id, apic->GlobalIrqBase,
477 (void *)(uintptr_t)apic->Address);
480 (void *)(uintptr_t)apic->Address);
478 if (apic->IoApicId >= NIOAPICS)
479 panic("%s: I/O APIC ID %d too high", __func__,
480 apic->IoApicId);
481 if (ioapics[apic->IoApicId].io_apic != NULL)
482 panic("%s: Double APIC ID %d", __func__,
483 apic->IoApicId);
484 ioapics[apic->IoApicId].io_apic = ioapic_create(apic->Address,
485 apic->IoApicId, apic->Interrupt);
486 ioapics[apic->IoApicId].io_vector = apic->Interrupt;
481 if (apic->Id >= NIOAPICS)
482 panic("%s: I/O APIC ID %u too high", __func__,
483 apic->Id);
484 if (ioapics[apic->Id].io_apic != NULL)
485 panic("%s: Double APIC ID %u", __func__, apic->Id);
486 ioapics[apic->Id].io_apic = ioapic_create(apic->Address,
487 apic->Id, apic->GlobalIrqBase);
488 ioapics[apic->Id].io_vector = apic->GlobalIrqBase;
487 break;
488 default:
489 break;
490 }
491}
492
493/*
494 * Determine properties of an interrupt source. Note that for ACPI these
495 * functions are only used for ISA interrupts, so we assume ISA bus values
496 * (Active Hi, Edge Triggered) for conforming values except for the ACPI
497 * SCI for which we use Active Lo, Level Triggered.
498 */
499static enum intr_polarity
489 break;
490 default:
491 break;
492 }
493}
494
495/*
496 * Determine properties of an interrupt source. Note that for ACPI these
497 * functions are only used for ISA interrupts, so we assume ISA bus values
498 * (Active Hi, Edge Triggered) for conforming values except for the ACPI
499 * SCI for which we use Active Lo, Level Triggered.
500 */
501static enum intr_polarity
500interrupt_polarity(UINT16 Polarity, UINT8 Source)
502interrupt_polarity(UINT16 IntiFlags, UINT8 Source)
501{
502
503{
504
503 switch (Polarity) {
504 case POLARITY_CONFORMS:
505 if (Source == AcpiGbl_FADT->SciInt)
505 switch (IntiFlags & ACPI_MADT_POLARITY_MASK) {
506 case ACPI_MADT_POLARITY_CONFORMS:
507 if (Source == AcpiGbl_FADT.SciInterrupt)
506 return (INTR_POLARITY_LOW);
507 else
508 return (INTR_POLARITY_HIGH);
508 return (INTR_POLARITY_LOW);
509 else
510 return (INTR_POLARITY_HIGH);
509 case POLARITY_ACTIVE_HIGH:
511 case ACPI_MADT_POLARITY_ACTIVE_HIGH:
510 return (INTR_POLARITY_HIGH);
512 return (INTR_POLARITY_HIGH);
511 case POLARITY_ACTIVE_LOW:
513 case ACPI_MADT_POLARITY_ACTIVE_LOW:
512 return (INTR_POLARITY_LOW);
513 default:
514 panic("Bogus Interrupt Polarity");
515 }
516}
517
518static enum intr_trigger
514 return (INTR_POLARITY_LOW);
515 default:
516 panic("Bogus Interrupt Polarity");
517 }
518}
519
520static enum intr_trigger
519interrupt_trigger(UINT16 TriggerMode, UINT8 Source)
521interrupt_trigger(UINT16 IntiFlags, UINT8 Source)
520{
521
522{
523
522 switch (TriggerMode) {
523 case TRIGGER_CONFORMS:
524 if (Source == AcpiGbl_FADT->SciInt)
524 switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) {
525 case ACPI_MADT_TRIGGER_CONFORMS:
526 if (Source == AcpiGbl_FADT.SciInterrupt)
525 return (INTR_TRIGGER_LEVEL);
526 else
527 return (INTR_TRIGGER_EDGE);
527 return (INTR_TRIGGER_LEVEL);
528 else
529 return (INTR_TRIGGER_EDGE);
528 case TRIGGER_EDGE:
530 case ACPI_MADT_TRIGGER_EDGE:
529 return (INTR_TRIGGER_EDGE);
531 return (INTR_TRIGGER_EDGE);
530 case TRIGGER_LEVEL:
532 case ACPI_MADT_TRIGGER_LEVEL:
531 return (INTR_TRIGGER_LEVEL);
532 default:
533 panic("Bogus Interrupt Trigger Mode");
534 }
535}
536
537/*
538 * Find the local APIC ID associated with a given ACPI Processor ID.

--- 41 unchanged lines hidden (view full) ---

580 intr);
581 return (0);
582}
583
584/*
585 * Parse an interrupt source override for an ISA interrupt.
586 */
587static void
533 return (INTR_TRIGGER_LEVEL);
534 default:
535 panic("Bogus Interrupt Trigger Mode");
536 }
537}
538
539/*
540 * Find the local APIC ID associated with a given ACPI Processor ID.

--- 41 unchanged lines hidden (view full) ---

582 intr);
583 return (0);
584}
585
586/*
587 * Parse an interrupt source override for an ISA interrupt.
588 */
589static void
588madt_parse_interrupt_override(MADT_INTERRUPT_OVERRIDE *intr)
590madt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr)
589{
590 void *new_ioapic, *old_ioapic;
591 u_int new_pin, old_pin;
592 enum intr_trigger trig;
593 enum intr_polarity pol;
594 char buf[64];
595
591{
592 void *new_ioapic, *old_ioapic;
593 u_int new_pin, old_pin;
594 enum intr_trigger trig;
595 enum intr_polarity pol;
596 char buf[64];
597
596 if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->Source == 0 &&
597 intr->Interrupt == 2) {
598 if (acpi_quirks & ACPI_Q_MADT_IRQ0 && intr->SourceIrq == 0 &&
599 intr->GlobalIrq == 2) {
598 if (bootverbose)
599 printf("MADT: Skipping timer override\n");
600 return;
601 }
602 if (bootverbose)
603 printf("MADT: Interrupt override: source %u, irq %u\n",
600 if (bootverbose)
601 printf("MADT: Skipping timer override\n");
602 return;
603 }
604 if (bootverbose)
605 printf("MADT: Interrupt override: source %u, irq %u\n",
604 intr->Source, intr->Interrupt);
606 intr->SourceIrq, intr->GlobalIrq);
605 KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
607 KASSERT(intr->Bus == 0, ("bus for interrupt overrides must be zero"));
606 if (madt_find_interrupt(intr->Interrupt, &new_ioapic,
607 &new_pin) != 0) {
608 printf("MADT: Could not find APIC for vector %d (IRQ %d)\n",
609 intr->Interrupt, intr->Source);
608 if (madt_find_interrupt(intr->GlobalIrq, &new_ioapic, &new_pin) != 0) {
609 printf("MADT: Could not find APIC for vector %u (IRQ %u)\n",
610 intr->GlobalIrq, intr->SourceIrq);
610 return;
611 }
612
613 /*
614 * Lookup the appropriate trigger and polarity modes for this
615 * entry.
616 */
611 return;
612 }
613
614 /*
615 * Lookup the appropriate trigger and polarity modes for this
616 * entry.
617 */
617 trig = interrupt_trigger(intr->TriggerMode, intr->Source);
618 pol = interrupt_polarity(intr->Polarity, intr->Source);
618 trig = interrupt_trigger(intr->IntiFlags, intr->SourceIrq);
619 pol = interrupt_polarity(intr->IntiFlags, intr->SourceIrq);
619
620 /*
621 * If the SCI is identity mapped but has edge trigger and
622 * active-hi polarity or the force_sci_lo tunable is set,
623 * force it to use level/lo.
624 */
620
621 /*
622 * If the SCI is identity mapped but has edge trigger and
623 * active-hi polarity or the force_sci_lo tunable is set,
624 * force it to use level/lo.
625 */
625 if (intr->Source == AcpiGbl_FADT->SciInt) {
626 if (intr->SourceIrq == AcpiGbl_FADT.SciInterrupt) {
626 madt_found_sci_override = 1;
627 if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
628 if (tolower(buf[0]) == 'e')
629 trig = INTR_TRIGGER_EDGE;
630 else if (tolower(buf[0]) == 'l')
631 trig = INTR_TRIGGER_LEVEL;
632 else
633 panic(

--- 12 unchanged lines hidden (view full) ---

646 "Invalid polarity %s: must be 'high' or 'low'",
647 buf);
648 printf("MADT: Forcing SCI to active %s polarity\n",
649 pol == INTR_POLARITY_HIGH ? "high" : "low");
650 }
651 }
652
653 /* Remap the IRQ if it is mapped to a different interrupt vector. */
627 madt_found_sci_override = 1;
628 if (getenv_string("hw.acpi.sci.trigger", buf, sizeof(buf))) {
629 if (tolower(buf[0]) == 'e')
630 trig = INTR_TRIGGER_EDGE;
631 else if (tolower(buf[0]) == 'l')
632 trig = INTR_TRIGGER_LEVEL;
633 else
634 panic(

--- 12 unchanged lines hidden (view full) ---

647 "Invalid polarity %s: must be 'high' or 'low'",
648 buf);
649 printf("MADT: Forcing SCI to active %s polarity\n",
650 pol == INTR_POLARITY_HIGH ? "high" : "low");
651 }
652 }
653
654 /* Remap the IRQ if it is mapped to a different interrupt vector. */
654 if (intr->Source != intr->Interrupt) {
655 if (intr->SourceIrq != intr->GlobalIrq) {
655 /*
656 * If the SCI is remapped to a non-ISA global interrupt,
657 * then override the vector we use to setup and allocate
658 * the interrupt.
659 */
656 /*
657 * If the SCI is remapped to a non-ISA global interrupt,
658 * then override the vector we use to setup and allocate
659 * the interrupt.
660 */
660 if (intr->Interrupt > 15 &&
661 intr->Source == AcpiGbl_FADT->SciInt)
662 acpi_OverrideInterruptLevel(intr->Interrupt);
661 if (intr->GlobalIrq > 15 &&
662 intr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
663 acpi_OverrideInterruptLevel(intr->GlobalIrq);
663 else
664 else
664 ioapic_remap_vector(new_ioapic, new_pin, intr->Source);
665 if (madt_find_interrupt(intr->Source, &old_ioapic,
665 ioapic_remap_vector(new_ioapic, new_pin,
666 intr->SourceIrq);
667 if (madt_find_interrupt(intr->SourceIrq, &old_ioapic,
666 &old_pin) != 0)
668 &old_pin) != 0)
667 printf("MADT: Could not find APIC for source IRQ %d\n",
668 intr->Source);
669 printf("MADT: Could not find APIC for source IRQ %u\n",
670 intr->SourceIrq);
669 else if (ioapic_get_vector(old_ioapic, old_pin) ==
671 else if (ioapic_get_vector(old_ioapic, old_pin) ==
670 intr->Source)
672 intr->SourceIrq)
671 ioapic_disable_pin(old_ioapic, old_pin);
672 }
673
674 /* Program the polarity and trigger mode. */
675 ioapic_set_triggermode(new_ioapic, new_pin, trig);
676 ioapic_set_polarity(new_ioapic, new_pin, pol);
677}
678
679/*
680 * Parse an entry for an NMI routed to an IO APIC.
681 */
682static void
673 ioapic_disable_pin(old_ioapic, old_pin);
674 }
675
676 /* Program the polarity and trigger mode. */
677 ioapic_set_triggermode(new_ioapic, new_pin, trig);
678 ioapic_set_polarity(new_ioapic, new_pin, pol);
679}
680
681/*
682 * Parse an entry for an NMI routed to an IO APIC.
683 */
684static void
683madt_parse_nmi(MADT_NMI_SOURCE *nmi)
685madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi)
684{
685 void *ioapic;
686 u_int pin;
687
686{
687 void *ioapic;
688 u_int pin;
689
688 if (madt_find_interrupt(nmi->Interrupt, &ioapic, &pin) != 0) {
689 printf("MADT: Could not find APIC for vector %d\n",
690 nmi->Interrupt);
690 if (madt_find_interrupt(nmi->GlobalIrq, &ioapic, &pin) != 0) {
691 printf("MADT: Could not find APIC for vector %u\n",
692 nmi->GlobalIrq);
691 return;
692 }
693
694 ioapic_set_nmi(ioapic, pin);
693 return;
694 }
695
696 ioapic_set_nmi(ioapic, pin);
695 if (nmi->TriggerMode != TRIGGER_CONFORMS)
697 if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
696 ioapic_set_triggermode(ioapic, pin,
698 ioapic_set_triggermode(ioapic, pin,
697 interrupt_trigger(nmi->TriggerMode, 0));
698 if (nmi->Polarity != TRIGGER_CONFORMS)
699 interrupt_trigger(nmi->IntiFlags, 0));
700 if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
699 ioapic_set_polarity(ioapic, pin,
701 ioapic_set_polarity(ioapic, pin,
700 interrupt_polarity(nmi->Polarity, 0));
702 interrupt_polarity(nmi->IntiFlags, 0));
701}
702
703/*
704 * Parse an entry for an NMI routed to a local APIC LVT pin.
705 */
706static void
703}
704
705/*
706 * Parse an entry for an NMI routed to a local APIC LVT pin.
707 */
708static void
707madt_parse_local_nmi(MADT_LOCAL_APIC_NMI *nmi)
709madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi)
708{
709 u_int apic_id, pin;
710
711 if (nmi->ProcessorId == 0xff)
712 apic_id = APIC_ID_ALL;
713 else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
714 if (bootverbose)
710{
711 u_int apic_id, pin;
712
713 if (nmi->ProcessorId == 0xff)
714 apic_id = APIC_ID_ALL;
715 else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
716 if (bootverbose)
715 printf("MADT: Ignoring local NMI routed to ACPI CPU %u\n",
716 nmi->ProcessorId);
717 printf("MADT: Ignoring local NMI routed to "
718 "ACPI CPU %u\n", nmi->ProcessorId);
717 return;
718 }
719 if (nmi->Lint == 0)
720 pin = LVT_LINT0;
721 else
722 pin = LVT_LINT1;
723 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
719 return;
720 }
721 if (nmi->Lint == 0)
722 pin = LVT_LINT0;
723 else
724 pin = LVT_LINT1;
725 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
724 if (nmi->TriggerMode != TRIGGER_CONFORMS)
726 if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
725 lapic_set_lvt_triggermode(apic_id, pin,
727 lapic_set_lvt_triggermode(apic_id, pin,
726 interrupt_trigger(nmi->TriggerMode, 0));
727 if (nmi->Polarity != POLARITY_CONFORMS)
728 interrupt_trigger(nmi->IntiFlags, 0));
729 if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
728 lapic_set_lvt_polarity(apic_id, pin,
730 lapic_set_lvt_polarity(apic_id, pin,
729 interrupt_polarity(nmi->Polarity, 0));
731 interrupt_polarity(nmi->IntiFlags, 0));
730}
731
732/*
733 * Parse interrupt entries.
734 */
735static void
732}
733
734/*
735 * Parse interrupt entries.
736 */
737static void
736madt_parse_ints(APIC_HEADER *entry, void *arg __unused)
738madt_parse_ints(ACPI_SUBTABLE_HEADER *entry, void *arg __unused)
737{
738
739 switch (entry->Type) {
739{
740
741 switch (entry->Type) {
740 case APIC_XRUPT_OVERRIDE:
742 case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
741 madt_parse_interrupt_override(
743 madt_parse_interrupt_override(
742 (MADT_INTERRUPT_OVERRIDE *)entry);
744 (ACPI_MADT_INTERRUPT_OVERRIDE *)entry);
743 break;
745 break;
744 case APIC_NMI:
745 madt_parse_nmi((MADT_NMI_SOURCE *)entry);
746 case ACPI_MADT_TYPE_NMI_SOURCE:
747 madt_parse_nmi((ACPI_MADT_NMI_SOURCE *)entry);
746 break;
748 break;
747 case APIC_LOCAL_NMI:
748 madt_parse_local_nmi((MADT_LOCAL_APIC_NMI *)entry);
749 case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
750 madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry);
749 break;
750 }
751}
752
753/*
754 * Setup per-CPU ACPI IDs.
755 */
756static void

--- 4 unchanged lines hidden (view full) ---

761 u_int i;
762
763 if (madt == NULL)
764 return;
765 for (i = 0; i <= mp_maxid; i++) {
766 if (CPU_ABSENT(i))
767 continue;
768 pc = pcpu_find(i);
751 break;
752 }
753}
754
755/*
756 * Setup per-CPU ACPI IDs.
757 */
758static void

--- 4 unchanged lines hidden (view full) ---

763 u_int i;
764
765 if (madt == NULL)
766 return;
767 for (i = 0; i <= mp_maxid; i++) {
768 if (CPU_ABSENT(i))
769 continue;
770 pc = pcpu_find(i);
769 KASSERT(pc != NULL, ("no pcpu data for CPU %d", i));
771 KASSERT(pc != NULL, ("no pcpu data for CPU %u", i));
770 la = &lapics[pc->pc_apic_id];
771 if (!la->la_enabled)
772 panic("APIC: CPU with APIC ID %u is not enabled",
773 pc->pc_apic_id);
774 pc->pc_acpi_id = la->la_acpi_id;
775 if (bootverbose)
776 printf("APIC: CPU %u has ACPI ID %u\n", i,
777 la->la_acpi_id);
778 }
779}
780SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL)
772 la = &lapics[pc->pc_apic_id];
773 if (!la->la_enabled)
774 panic("APIC: CPU with APIC ID %u is not enabled",
775 pc->pc_apic_id);
776 pc->pc_acpi_id = la->la_acpi_id;
777 if (bootverbose)
778 printf("APIC: CPU %u has ACPI ID %u\n", i,
779 la->la_acpi_id);
780 }
781}
782SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL)