1 /*
2 * Copyright (c) 2009 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Sepherosa Ziehau <sepherosa@gmail.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include <sys/param.h>
36 #include <sys/bus.h>
37 #include <sys/kernel.h>
38 #include <sys/systm.h>
39
40 #include <machine_base/isa/isa_intr.h>
41 #include <machine_base/apic/lapic.h>
42 #include <machine_base/apic/ioapic.h>
43 #include <machine_base/apic/apicvar.h>
44 #include <machine_base/acpica/acpi_md_cpu.h>
45 #include <machine/specialreg.h>
46
47 #include <contrib/dev/acpica/source/include/acpi.h>
48
49 #include "acpi_sdt_var.h"
50 #include "acpi_sci_var.h"
51
52 extern int naps;
53
54 #define MADT_VPRINTF(fmt, arg...) \
55 do { \
56 if (bootverbose) \
57 kprintf("ACPI MADT: " fmt , ##arg); \
58 } while (0)
59
60 #define MADT_INT_BUS_ISA 0
61
62 typedef int (*madt_iter_t)(void *,
63 const ACPI_SUBTABLE_HEADER *);
64
65 static int madt_check(vm_paddr_t);
66 static int madt_iterate_entries(ACPI_TABLE_MADT *,
67 madt_iter_t, void *);
68
69 static vm_paddr_t madt_lapic_pass1(void);
70 static int madt_lapic_pass2(int);
71
72 static int madt_lapic_enumerate(struct lapic_enumerator *);
73 static int madt_lapic_probe(struct lapic_enumerator *);
74
75 static void madt_ioapic_enumerate(
76 struct ioapic_enumerator *);
77 static int madt_ioapic_probe(struct ioapic_enumerator *);
78
79 static vm_paddr_t madt_phyaddr;
80
81 static boolean_t madt_use_x2apic = FALSE;
82
83 u_int cpu_id_to_acpi_id[NAPICID];
84
85 static void
madt_probe(void)86 madt_probe(void)
87 {
88 vm_paddr_t madt_paddr;
89 int i;
90
91 for (i = 0; i < NAPICID; ++i)
92 CPUID_TO_ACPIID(i) = (u_int)-1;
93
94 KKASSERT(madt_phyaddr == 0);
95
96 madt_paddr = sdt_search(ACPI_SIG_MADT);
97 if (madt_paddr == 0) {
98 kprintf("madt_probe: can't locate MADT\n");
99 return;
100 }
101
102 /* Preliminary checks */
103 if (madt_check(madt_paddr)) {
104 kprintf("madt_probe: madt_check failed\n");
105 return;
106 }
107
108 madt_phyaddr = madt_paddr;
109 }
110 SYSINIT(madt_probe, SI_BOOT2_PRESMP, SI_ORDER_SECOND, madt_probe, 0);
111
112 static int
madt_check(vm_paddr_t madt_paddr)113 madt_check(vm_paddr_t madt_paddr)
114 {
115 ACPI_TABLE_MADT *madt;
116 int error = 0;
117
118 KKASSERT(madt_paddr != 0);
119
120 madt = sdt_sdth_map(madt_paddr);
121 KKASSERT(madt != NULL);
122
123 /*
124 * MADT in ACPI specification 1.0 - 6.4
125 */
126 if (madt->Header.Revision < 1 || madt->Header.Revision > 5) {
127 kprintf("madt_check: unknown MADT revision %d\n",
128 madt->Header.Revision);
129 }
130
131 if (madt->Header.Length < sizeof(*madt)) {
132 kprintf("madt_check: invalid MADT length %u\n",
133 madt->Header.Length);
134 error = EINVAL;
135 goto back;
136 }
137 back:
138 sdt_sdth_unmap(&madt->Header);
139 return error;
140 }
141
142 static int
madt_iterate_entries(ACPI_TABLE_MADT * madt,madt_iter_t func,void * arg)143 madt_iterate_entries(ACPI_TABLE_MADT *madt, madt_iter_t func, void *arg)
144 {
145 int size, cur, error;
146
147 size = madt->Header.Length - sizeof(*madt);
148 cur = 0;
149 error = 0;
150
151 while (size - cur > sizeof(ACPI_SUBTABLE_HEADER)) {
152 const ACPI_SUBTABLE_HEADER *ent;
153
154 ent = (const ACPI_SUBTABLE_HEADER *)
155 ((char *)madt + sizeof(*madt) + cur);
156 if (ent->Length < sizeof(*ent)) {
157 kprintf("madt_iterate_entries: invalid MADT "
158 "entry len %d\n", ent->Length);
159 error = EINVAL;
160 break;
161 }
162 if (ent->Length > (size - cur)) {
163 kprintf("madt_iterate_entries: invalid MADT "
164 "entry len %d, > table length\n", ent->Length);
165 error = EINVAL;
166 break;
167 }
168
169 cur += ent->Length;
170
171 /*
172 * Only Local APIC, I/O APIC and Interrupt Source Override
173 * are defined in ACPI specification 1.0 - 5.0
174 */
175 switch (ent->Type) {
176 case ACPI_MADT_TYPE_LOCAL_APIC:
177 if (ent->Length < sizeof(ACPI_MADT_LOCAL_APIC)) {
178 kprintf("madt_iterate_entries: invalid MADT "
179 "lapic entry len %d\n", ent->Length);
180 error = EINVAL;
181 }
182 break;
183
184 case ACPI_MADT_TYPE_LOCAL_X2APIC:
185 if (ent->Length < sizeof(ACPI_MADT_LOCAL_X2APIC)) {
186 kprintf("madt_iterate_entries: invalid MADT "
187 "x2apic entry len %d\n", ent->Length);
188 error = EINVAL;
189 }
190 break;
191
192 case ACPI_MADT_TYPE_IO_APIC:
193 if (ent->Length < sizeof(ACPI_MADT_IO_APIC)) {
194 kprintf("madt_iterate_entries: invalid MADT "
195 "ioapic entry len %d\n", ent->Length);
196 error = EINVAL;
197 }
198 break;
199
200 case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
201 if (ent->Length < sizeof(ACPI_MADT_INTERRUPT_OVERRIDE)) {
202 kprintf("madt_iterate_entries: invalid MADT "
203 "intsrc entry len %d\n",
204 ent->Length);
205 error = EINVAL;
206 }
207 break;
208 }
209 if (error)
210 break;
211
212 error = func(arg, ent);
213 if (error)
214 break;
215
216 ent = ACPI_ADD_PTR(ACPI_SUBTABLE_HEADER, ent, ent->Length);
217 }
218 return error;
219 }
220
221 static int
madt_lapic_pass1_callback(void * xarg,const ACPI_SUBTABLE_HEADER * ent)222 madt_lapic_pass1_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent)
223 {
224 const ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_addr_ent;
225 uint64_t *addr64 = xarg;
226
227 if (ent->Type != ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE)
228 return 0;
229 if (ent->Length < sizeof(*lapic_addr_ent)) {
230 kprintf("madt_lapic_pass1: "
231 "invalid LAPIC address override length\n");
232 return 0;
233 }
234 lapic_addr_ent = (const ACPI_MADT_LOCAL_APIC_OVERRIDE *)ent;
235
236 *addr64 = lapic_addr_ent->Address;
237 return 0;
238 }
239
240 static vm_paddr_t
madt_lapic_pass1(void)241 madt_lapic_pass1(void)
242 {
243 ACPI_TABLE_MADT *madt;
244 vm_paddr_t lapic_addr;
245 uint64_t lapic_addr64;
246 int error;
247
248 KKASSERT(madt_phyaddr != 0);
249
250 madt = sdt_sdth_map(madt_phyaddr);
251 KKASSERT(madt != NULL);
252
253 MADT_VPRINTF("LAPIC address 0x%x, flags %#x\n",
254 madt->Address, madt->Flags);
255 lapic_addr = madt->Address;
256
257 lapic_addr64 = 0;
258 error = madt_iterate_entries(madt, madt_lapic_pass1_callback,
259 &lapic_addr64);
260 if (error)
261 panic("madt_iterate_entries(pass1) failed");
262
263 if (lapic_addr64 != 0) {
264 kprintf("ACPI MADT: 64bits lapic address 0x%lx\n",
265 lapic_addr64);
266 lapic_addr = lapic_addr64;
267 }
268
269 sdt_sdth_unmap(&madt->Header);
270
271 return lapic_addr;
272 }
273
274 struct madt_lapic_pass2_cbarg {
275 int cpu;
276 int bsp_found;
277 int bsp_apic_id;
278 };
279
280 static int
madt_lapic_pass2_callback(void * xarg,const ACPI_SUBTABLE_HEADER * ent)281 madt_lapic_pass2_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent)
282 {
283 const ACPI_MADT_LOCAL_APIC *lapic_ent;
284 struct madt_lapic_pass2_cbarg *arg = xarg;
285
286 if (ent->Type != ACPI_MADT_TYPE_LOCAL_APIC)
287 return 0;
288
289 lapic_ent = (const ACPI_MADT_LOCAL_APIC *)ent;
290 if (lapic_ent->LapicFlags & ACPI_MADT_ENABLED) {
291 int cpu;
292
293 if (lapic_ent->Id == arg->bsp_apic_id) {
294 cpu = 0;
295 if (arg->bsp_found) {
296 kprintf("cpu id %d, duplicate BSP found\n",
297 arg->cpu);
298 }
299 arg->bsp_found = 1;
300 } else {
301 cpu = arg->cpu;
302 arg->cpu++;
303 }
304 MADT_VPRINTF("cpu id %d, acpi id %d, apic id %d\n",
305 cpu, lapic_ent->ProcessorId, lapic_ent->Id);
306 if (lapic_ent->Id >= 255) {
307 kprintf("cpu id %d, WARNING acpi id %d\n",
308 cpu, lapic_ent->Id);
309 }
310 if (lapic_ent->ProcessorId >= 255) {
311 kprintf("cpu id %d, WARNING acpi processorid %d\n",
312 cpu, lapic_ent->ProcessorId);
313 }
314 lapic_set_cpuid(cpu, lapic_ent->Id);
315 CPUID_TO_ACPIID(cpu) = lapic_ent->ProcessorId;
316 }
317 return 0;
318 }
319
320 static int
madt_x2apic_pass2_callback(void * xarg,const ACPI_SUBTABLE_HEADER * ent)321 madt_x2apic_pass2_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent)
322 {
323 const ACPI_MADT_LOCAL_X2APIC *x2apic_ent;
324 struct madt_lapic_pass2_cbarg *arg = xarg;
325
326 if (ent->Type != ACPI_MADT_TYPE_LOCAL_X2APIC)
327 return 0;
328
329 x2apic_ent = (const ACPI_MADT_LOCAL_X2APIC *)ent;
330 if (x2apic_ent->LapicFlags & ACPI_MADT_ENABLED) {
331 int cpu;
332
333 if (x2apic_ent->LocalApicId == arg->bsp_apic_id) {
334 cpu = 0;
335 arg->bsp_found = 1;
336 } else {
337 cpu = arg->cpu;
338 arg->cpu++;
339 }
340 MADT_VPRINTF("cpu id %d, acpi uid %u, apic id %d\n",
341 cpu, x2apic_ent->Uid, x2apic_ent->LocalApicId);
342 lapic_set_cpuid(cpu, x2apic_ent->LocalApicId);
343 CPUID_TO_ACPIID(cpu) = x2apic_ent->Uid;
344 }
345 return 0;
346 }
347
348 static int
madt_lapic_pass2(int bsp_apic_id)349 madt_lapic_pass2(int bsp_apic_id)
350 {
351 ACPI_TABLE_MADT *madt;
352 struct madt_lapic_pass2_cbarg arg;
353 madt_iter_t func;
354 int error;
355
356 MADT_VPRINTF("BSP apic id %d\n", bsp_apic_id);
357
358 KKASSERT(madt_phyaddr != 0);
359
360 madt = sdt_sdth_map(madt_phyaddr);
361 KKASSERT(madt != NULL);
362
363 bzero(&arg, sizeof(arg));
364 arg.cpu = 1;
365 arg.bsp_apic_id = bsp_apic_id;
366
367 if (madt_use_x2apic)
368 func = madt_x2apic_pass2_callback;
369 else
370 func = madt_lapic_pass2_callback;
371 error = madt_iterate_entries(madt, func, &arg);
372 if (error)
373 panic("madt_iterate_entries(pass2) failed");
374
375 KKASSERT(arg.bsp_found);
376 naps = arg.cpu - 1; /* exclude BSP */
377 kprintf("ACPI CPUS = %d\n", arg.cpu);
378
379 sdt_sdth_unmap(&madt->Header);
380
381 return 0;
382 }
383
384 struct madt_lapic_probe_cbarg {
385 int x2apic_count;
386 int lapic_count;
387 vm_paddr_t lapic_addr;
388 };
389
390 static int
madt_lapic_probe_callback(void * xarg,const ACPI_SUBTABLE_HEADER * ent)391 madt_lapic_probe_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent)
392 {
393 struct madt_lapic_probe_cbarg *arg = xarg;
394
395 if (ent->Type == ACPI_MADT_TYPE_LOCAL_APIC) {
396 const ACPI_MADT_LOCAL_APIC *lapic_ent;
397
398 lapic_ent = (const ACPI_MADT_LOCAL_APIC *)ent;
399 if (lapic_ent->LapicFlags & ACPI_MADT_ENABLED) {
400 arg->lapic_count++;
401 if (lapic_ent->Id == APICID_MAX) {
402 kprintf("madt_lapic_probe: "
403 "invalid LAPIC apic id %d\n",
404 lapic_ent->Id);
405 return EINVAL;
406 }
407 }
408 } else if (ent->Type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
409 const ACPI_MADT_LOCAL_X2APIC *x2apic_ent;
410
411 x2apic_ent = (const ACPI_MADT_LOCAL_X2APIC *)ent;
412 if (x2apic_ent->LapicFlags & ACPI_MADT_ENABLED) {
413 if (x2apic_ent->LocalApicId < APICID_MAX) {
414 /*
415 * XXX we only support APIC ID 0~254 at
416 * the moment.
417 */
418 arg->x2apic_count++;
419 }
420 }
421 } else if (ent->Type == ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE) {
422 const ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_addr_ent;
423
424 if (ent->Length < sizeof(*lapic_addr_ent)) {
425 kprintf("madt_lapic_probe: "
426 "invalid LAPIC address override length\n");
427 return 0;
428 }
429 lapic_addr_ent = (const ACPI_MADT_LOCAL_APIC_OVERRIDE *)ent;
430
431 if (lapic_addr_ent->Address != 0)
432 arg->lapic_addr = lapic_addr_ent->Address;
433 }
434 return 0;
435 }
436
437 static int
madt_lapic_probe(struct lapic_enumerator * e)438 madt_lapic_probe(struct lapic_enumerator *e)
439 {
440 struct madt_lapic_probe_cbarg arg;
441 ACPI_TABLE_MADT *madt;
442 int error;
443
444 if (madt_phyaddr == 0)
445 return ENXIO;
446
447 madt = sdt_sdth_map(madt_phyaddr);
448 KKASSERT(madt != NULL);
449
450 bzero(&arg, sizeof(arg));
451 arg.lapic_addr = madt->Address;
452
453 error = madt_iterate_entries(madt, madt_lapic_probe_callback, &arg);
454 if (!error) {
455 kprintf("madt_lapic_probe: lapic_count=%d x2apic_count=%d\n",
456 arg.lapic_count, arg.x2apic_count);
457 if (arg.lapic_count == 0 && arg.x2apic_count == 0) {
458 kprintf("madt_lapic_probe: no CPU is found\n");
459 error = EOPNOTSUPP;
460 } else if (arg.lapic_count == 0) {
461 /*
462 * ACPI 5.1 says that LOCAL_X2APIC entry should
463 * be used only if APIC ID > 255. While ACPI 6.2
464 * removes that constraint, which means that
465 * LOCAL_X2APIC entry could be used for any APIC
466 * ID.
467 *
468 * XXX
469 * In DragonFlyBSD, we don't support APIC ID >=
470 * 255, so LOCAL_X2APIC entries should be ignored,
471 * if LOCAL_X2APIC entries are mixed with
472 * LOCAL_APIC entries. LOCAL_X2APIC entries are
473 * used, iff only LOCAL_X2APIC entries exist.
474 */
475 madt_use_x2apic = TRUE;
476 kprintf("MADT: use X2APIC entries\n");
477 }
478
479 if (arg.lapic_addr == 0) {
480 /*
481 * The LAPIC address does not matter in X2APIC mode.
482 */
483 if ((cpu_feature2 & CPUID2_X2APIC) == 0) {
484 kprintf("madt_lapic_probe: zero LAPIC address\n");
485 error = EOPNOTSUPP;
486 }
487 }
488 }
489
490 sdt_sdth_unmap(&madt->Header);
491 return error;
492 }
493
494 static int
madt_lapic_enumerate(struct lapic_enumerator * e)495 madt_lapic_enumerate(struct lapic_enumerator *e)
496 {
497 vm_paddr_t lapic_addr = 0;
498 int bsp_apic_id;
499
500 KKASSERT(madt_phyaddr != 0);
501
502 if (!x2apic_enable) {
503 lapic_addr = madt_lapic_pass1();
504 if (lapic_addr == 0) {
505 /*
506 * No LAPIC address.
507 */
508 if (cpu_feature2 & CPUID2_X2APIC) {
509 /*
510 * X2APIC mode is not enabled, but the CPU supports
511 * it. Forcefully enable X2APIC mode, which nullifies
512 * the requirement of the LAPIC address.
513 */
514 kprintf("MADT: no LAPIC address, force X2APIC mode\n");
515 KKASSERT(!x2apic_enable);
516 x2apic_enable = 1;
517 lapic_x2apic_enter(TRUE);
518 } else {
519 /*
520 * We should not reach here, madt_lapic_probe() must
521 * have failed.
522 */
523 panic("madt_lapic_enumerate: no local apic");
524 }
525 }
526 }
527
528 if (!x2apic_enable) {
529 KASSERT(lapic_addr != 0, ("madt_lapic_enumerate: zero LAPIC address"));
530 lapic_map(lapic_addr);
531 }
532
533 bsp_apic_id = LAPIC_READID;
534 if (bsp_apic_id == APICID_MAX) {
535 /*
536 * XXX
537 * Some old brain dead BIOS will set BSP's LAPIC apic id
538 * to 255, though all LAPIC entries in MADT are valid.
539 */
540 kprintf("%s invalid BSP LAPIC apic id %d\n", __func__,
541 bsp_apic_id);
542 return EINVAL;
543 }
544
545 if (madt_lapic_pass2(bsp_apic_id))
546 panic("madt_lapic_enumerate: madt_lapic_pass2 failed");
547
548 return 0;
549 }
550
551 static struct lapic_enumerator madt_lapic_enumerator = {
552 .lapic_prio = LAPIC_ENUM_PRIO_MADT,
553 .lapic_probe = madt_lapic_probe,
554 .lapic_enumerate = madt_lapic_enumerate
555 };
556
557 static void
madt_lapic_enum_register(void)558 madt_lapic_enum_register(void)
559 {
560 int prio;
561
562 prio = LAPIC_ENUM_PRIO_MADT;
563 kgetenv_int("hw.madt_lapic_prio", &prio);
564 madt_lapic_enumerator.lapic_prio = prio;
565
566 lapic_enumerator_register(&madt_lapic_enumerator);
567 }
568 SYSINIT(madt_lapic, SI_BOOT2_PRESMP, SI_ORDER_ANY, madt_lapic_enum_register, 0);
569
570 struct madt_ioapic_probe_cbarg {
571 int ioapic_cnt;
572 int gsi_base0;
573 };
574
575 static int
madt_ioapic_probe_callback(void * xarg,const ACPI_SUBTABLE_HEADER * ent)576 madt_ioapic_probe_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent)
577 {
578 struct madt_ioapic_probe_cbarg *arg = xarg;
579
580 if (ent->Type == ACPI_MADT_TYPE_INTERRUPT_OVERRIDE) {
581 const ACPI_MADT_INTERRUPT_OVERRIDE *intsrc_ent;
582 int trig, pola;
583
584 intsrc_ent = (const ACPI_MADT_INTERRUPT_OVERRIDE *)ent;
585
586 if (intsrc_ent->SourceIrq >= ISA_IRQ_CNT) {
587 kprintf("madt_ioapic_probe: invalid intsrc irq (%d)\n",
588 intsrc_ent->SourceIrq);
589 return EINVAL;
590 }
591
592 if (intsrc_ent->Bus != MADT_INT_BUS_ISA) {
593 kprintf("ACPI MADT: warning intsrc irq %d "
594 "bus is not ISA (%d)\n",
595 intsrc_ent->SourceIrq, intsrc_ent->Bus);
596 }
597
598 trig = intsrc_ent->IntiFlags & ACPI_MADT_TRIGGER_MASK;
599 if (trig == ACPI_MADT_TRIGGER_RESERVED) {
600 kprintf("ACPI MADT: warning invalid intsrc irq %d "
601 "trig, reserved\n", intsrc_ent->SourceIrq);
602 } else if (trig == ACPI_MADT_TRIGGER_LEVEL) {
603 MADT_VPRINTF("warning invalid intsrc irq %d "
604 "trig, level\n", intsrc_ent->SourceIrq);
605 }
606
607 pola = intsrc_ent->IntiFlags & ACPI_MADT_POLARITY_MASK;
608 if (pola == ACPI_MADT_POLARITY_RESERVED) {
609 kprintf("ACPI MADT: warning invalid intsrc irq %d "
610 "pola, reserved\n", intsrc_ent->SourceIrq);
611 } else if (pola == ACPI_MADT_POLARITY_ACTIVE_LOW) {
612 MADT_VPRINTF("warning invalid intsrc irq %d "
613 "pola, low\n", intsrc_ent->SourceIrq);
614 }
615 } else if (ent->Type == ACPI_MADT_TYPE_IO_APIC) {
616 const ACPI_MADT_IO_APIC *ioapic_ent;
617
618 ioapic_ent = (const ACPI_MADT_IO_APIC *)ent;
619 if (ioapic_ent->Address == 0) {
620 kprintf("madt_ioapic_probe: zero IOAPIC address\n");
621 return EINVAL;
622 }
623 if (ioapic_ent->Id == APICID_MAX) {
624 kprintf("madt_ioapic_probe: "
625 "invalid IOAPIC apic id %d\n",
626 ioapic_ent->Id);
627 return EINVAL;
628 }
629
630 arg->ioapic_cnt++;
631 if (ioapic_ent->GlobalIrqBase == 0)
632 arg->gsi_base0 = 1;
633 }
634 return 0;
635 }
636
637 static int
madt_ioapic_probe(struct ioapic_enumerator * e)638 madt_ioapic_probe(struct ioapic_enumerator *e)
639 {
640 struct madt_ioapic_probe_cbarg arg;
641 ACPI_TABLE_MADT *madt;
642 int error;
643
644 if (madt_phyaddr == 0)
645 return ENXIO;
646
647 madt = sdt_sdth_map(madt_phyaddr);
648 KKASSERT(madt != NULL);
649
650 bzero(&arg, sizeof(arg));
651
652 error = madt_iterate_entries(madt, madt_ioapic_probe_callback, &arg);
653 if (!error) {
654 if (arg.ioapic_cnt == 0) {
655 kprintf("madt_ioapic_probe: no IOAPIC\n");
656 error = ENXIO;
657 }
658 if (!arg.gsi_base0) {
659 kprintf("madt_ioapic_probe: no GSI base 0\n");
660 error = EINVAL;
661 }
662 }
663
664 sdt_sdth_unmap(&madt->Header);
665 return error;
666 }
667
668 static int
madt_ioapic_enum_callback(void * xarg,const ACPI_SUBTABLE_HEADER * ent)669 madt_ioapic_enum_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent)
670 {
671 if (ent->Type == ACPI_MADT_TYPE_INTERRUPT_OVERRIDE) {
672 const ACPI_MADT_INTERRUPT_OVERRIDE *intsrc_ent;
673 enum intr_trigger trig;
674 enum intr_polarity pola;
675 int ent_trig, ent_pola;
676
677 intsrc_ent = (const ACPI_MADT_INTERRUPT_OVERRIDE *)ent;
678
679 KKASSERT(intsrc_ent->SourceIrq < ISA_IRQ_CNT);
680 if (intsrc_ent->Bus != MADT_INT_BUS_ISA)
681 return 0;
682
683 ent_trig = intsrc_ent->IntiFlags & ACPI_MADT_TRIGGER_MASK;
684 if (ent_trig == ACPI_MADT_TRIGGER_RESERVED)
685 return 0;
686 else if (ent_trig == ACPI_MADT_TRIGGER_LEVEL)
687 trig = INTR_TRIGGER_LEVEL;
688 else
689 trig = INTR_TRIGGER_EDGE;
690
691 ent_pola = intsrc_ent->IntiFlags & ACPI_MADT_POLARITY_MASK;
692 if (ent_pola == ACPI_MADT_POLARITY_RESERVED)
693 return 0;
694 else if (ent_pola == ACPI_MADT_POLARITY_ACTIVE_LOW)
695 pola = INTR_POLARITY_LOW;
696 else
697 pola = INTR_POLARITY_HIGH;
698
699 if (intsrc_ent->SourceIrq == acpi_sci_irqno()) {
700 acpi_sci_setmode1(trig, pola);
701 MADT_VPRINTF("SCI irq %d, first test %s/%s\n",
702 intsrc_ent->SourceIrq,
703 intr_str_trigger(trig), intr_str_polarity(pola));
704 }
705
706 /*
707 * We ignore the polarity and trigger changes, since
708 * most of them are wrong or useless at best.
709 */
710 if (intsrc_ent->SourceIrq == intsrc_ent->GlobalIrq) {
711 /* Nothing changed */
712 return 0;
713 }
714 trig = INTR_TRIGGER_EDGE;
715 pola = INTR_POLARITY_HIGH;
716
717 MADT_VPRINTF("INTSRC irq %d -> gsi %u %s/%s\n",
718 intsrc_ent->SourceIrq, intsrc_ent->GlobalIrq,
719 intr_str_trigger(trig), intr_str_polarity(pola));
720 ioapic_intsrc(intsrc_ent->SourceIrq, intsrc_ent->GlobalIrq,
721 trig, pola);
722 } else if (ent->Type == ACPI_MADT_TYPE_IO_APIC) {
723 const ACPI_MADT_IO_APIC *ioapic_ent;
724 uint32_t ver;
725 void *addr;
726 int npin;
727
728 ioapic_ent = (const ACPI_MADT_IO_APIC *)ent;
729 MADT_VPRINTF("IOAPIC addr 0x%08x, apic id %d, gsi base %u\n",
730 ioapic_ent->Address, ioapic_ent->Id,
731 ioapic_ent->GlobalIrqBase);
732
733 addr = ioapic_map(ioapic_ent->Address);
734
735 ver = ioapic_read(addr, IOAPIC_VER);
736 npin = ((ver & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1;
737
738 ioapic_add(addr, ioapic_ent->GlobalIrqBase, npin);
739 }
740 return 0;
741 }
742
743 static void
madt_ioapic_enumerate(struct ioapic_enumerator * e)744 madt_ioapic_enumerate(struct ioapic_enumerator *e)
745 {
746 ACPI_TABLE_MADT *madt;
747 int error;
748
749 KKASSERT(madt_phyaddr != 0);
750
751 madt = sdt_sdth_map(madt_phyaddr);
752 KKASSERT(madt != NULL);
753
754 error = madt_iterate_entries(madt, madt_ioapic_enum_callback, NULL);
755 if (error)
756 panic("madt_ioapic_enumerate failed");
757
758 sdt_sdth_unmap(&madt->Header);
759 }
760
761 static struct ioapic_enumerator madt_ioapic_enumerator = {
762 .ioapic_prio = IOAPIC_ENUM_PRIO_MADT,
763 .ioapic_probe = madt_ioapic_probe,
764 .ioapic_enumerate = madt_ioapic_enumerate
765 };
766
767 static void
madt_ioapic_enum_register(void)768 madt_ioapic_enum_register(void)
769 {
770 int prio;
771
772 prio = IOAPIC_ENUM_PRIO_MADT;
773 kgetenv_int("hw.madt_ioapic_prio", &prio);
774 madt_ioapic_enumerator.ioapic_prio = prio;
775
776 ioapic_enumerator_register(&madt_ioapic_enumerator);
777 }
778 SYSINIT(madt_ioapic, SI_BOOT2_PRESMP, SI_ORDER_ANY,
779 madt_ioapic_enum_register, 0);
780