1 /*        $NetBSD: mpbios.c,v 1.72 2025/01/13 06:35:38 imil Exp $     */
2 
3 /*-
4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by RedBack Networks Inc.
9  *
10  * Author: Bill Sommerfeld
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  * Copyright (c) 1999 Stefan Grefen
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  * 3. All advertising materials mentioning features or use of this software
46  *    must display the following acknowledgement:
47  *      This product includes software developed by the NetBSD
48  *      Foundation, Inc. and its contributors.
49  * 4. Neither the name of The NetBSD Foundation nor the names of its
50  *    contributors may be used to endorse or promote products derived
51  *    from this software without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
54  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE
57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63  * SUCH DAMAGE.
64  */
65 /*
66  * Derived from FreeBSD's mp_machdep.c
67  */
68 /*
69  * Copyright (c) 1996, by Steve Passe
70  * All rights reserved.
71  *
72  * Redistribution and use in source and binary forms, with or without
73  * modification, are permitted provided that the following conditions
74  * are met:
75  * 1. Redistributions of source code must retain the above copyright
76  *    notice, this list of conditions and the following disclaimer.
77  * 2. The name of the developer may NOT be used to endorse or promote products
78  *    derived from this software without specific prior written permission.
79  *
80  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
81  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
82  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
83  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
84  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
85  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
86  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
87  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
88  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
89  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
90  * SUCH DAMAGE.
91  */
92 
93 /*
94  * The Intel MP-stuff is just one way of x86 SMP systems
95  * so only Intel MP specific stuff is here.
96  */
97 
98 #include <sys/cdefs.h>
99 __KERNEL_RCSID(0, "$NetBSD: mpbios.c,v 1.72 2025/01/13 06:35:38 imil Exp $");
100 
101 #include "acpica.h"
102 #include "lapic.h"
103 #include "ioapic.h"
104 #include "opt_acpi.h"
105 #include "opt_mpbios.h"
106 
107 #include <sys/param.h>
108 #include <sys/systm.h>
109 #include <sys/kernel.h>
110 #include <sys/device.h>
111 #include <sys/kmem.h>
112 #include <sys/bus.h>
113 #include <sys/reboot.h>
114 
115 #include <uvm/uvm_extern.h>
116 
117 #include <machine/specialreg.h>
118 #include <machine/cpuvar.h>
119 #include <machine/mpbiosvar.h>
120 #include <machine/pio.h>
121 
122 #include <machine/i82093reg.h>
123 #include <machine/i82093var.h>
124 #include <machine/i82489reg.h>
125 #include <machine/i82489var.h>
126 
127 #include <dev/isa/isareg.h>
128 
129 #ifdef X86_MPBIOS_SUPPORT_EISA
130 #include <dev/eisa/eisavar.h> /* for ELCR* def'ns */
131 #endif
132 
133 #if NACPICA > 0
134 extern int mpacpi_ncpu;
135 extern int mpacpi_nioapic;
136 #endif
137 
138 int mpbios_ncpu;
139 int mpbios_nioapic;
140 
141 #include "pci.h"
142 
143 #if NPCI > 0
144 #include <dev/pci/pcivar.h>
145 #include <dev/pci/pcireg.h>
146 #endif
147 
148 #include "locators.h"
149 
150 /* descriptions of MP basetable entries */
151 struct mpbios_baseentry {
152           uint8_t             type;
153           uint8_t             length;
154           uint16_t  count;
155           const char          *name;
156 };
157 
158 static const char *loc_where[] = {
159           "extended bios data area",
160           "last page of base memory",
161           "bios"
162 };
163 
164 struct mp_map
165 {
166           vaddr_t             baseva;
167           int                 vsize;
168           paddr_t             pa;
169           paddr_t             pg;
170           int                 psize;
171 };
172 
173 struct dflt_conf_entry {
174           const char          *bus_type[2];
175           int                 flags;
176 };
177 
178 int mp_cpuprint(void *, const char *);
179 int mp_ioapicprint(void *, const char *);
180 static const void *mpbios_search(device_t, paddr_t, int,
181     struct mp_map *);
182 static inline int mpbios_cksum(const void *,int);
183 
184 static void mp_cfg_special_intr(const struct mpbios_int *, uint32_t *);
185 static void mp_print_special_intr (int intr);
186 
187 static void mp_cfg_pci_intr(const struct mpbios_int *, uint32_t *);
188 static void mp_print_pci_intr (int intr);
189 
190 #ifdef X86_MPBIOS_SUPPORT_EISA
191 static void mp_print_eisa_intr (int intr);
192 static void mp_cfg_eisa_intr(const struct mpbios_int *, uint32_t *);
193 #endif
194 
195 static void mp_cfg_isa_intr(const struct mpbios_int *, uint32_t *);
196 static void mp_print_isa_intr(int intr);
197 
198 static void mpbios_dflt_conf_cpu(device_t);
199 static void mpbios_dflt_conf_bus(device_t, const struct dflt_conf_entry *);
200 static void mpbios_dflt_conf_ioapic(device_t);
201 static void mpbios_dflt_conf_int(device_t, const struct dflt_conf_entry *,
202                                          const int *);
203 
204 static void mpbios_cpu(const uint8_t *, device_t);
205 static void mpbios_bus(const uint8_t *, device_t);
206 static void mpbios_ioapic(const uint8_t *, device_t);
207 static void mpbios_int(const uint8_t *, int, struct mp_intr_map *);
208 
209 static const void *mpbios_map(paddr_t, int, struct mp_map *);
210 static void mpbios_unmap(struct mp_map *);
211 
212 #ifdef MPTABLE_LINUX_BUG_COMPAT
213 static uint16_t compute_entry_count(const uint8_t *, const uint8_t *);
214 #endif
215 /*
216  * globals to help us bounce our way through parsing the config table.
217  */
218 
219 static struct mp_map mp_cfg_table_map;
220 static struct mp_map mp_fp_map;
221 const struct mpbios_cth       *mp_cth;
222 const struct mpbios_fps       *mp_fps;
223 
224 int mpbios_scanned;
225 
226 int
mp_cpuprint(void * aux,const char * pnp)227 mp_cpuprint(void *aux, const char *pnp)
228 {
229           struct cpu_attach_args *caa = aux;
230 
231           if (pnp)
232                     aprint_normal("cpu at %s", pnp);
233           aprint_normal(" apid %d", caa->cpu_number);
234           return UNCONF;
235 }
236 
237 int
mp_ioapicprint(void * aux,const char * pnp)238 mp_ioapicprint(void *aux, const char *pnp)
239 {
240           struct apic_attach_args *aaa = aux;
241 
242           if (pnp)
243                     aprint_normal("ioapic at %s", pnp);
244           aprint_normal(" apid %d", aaa->apic_id);
245           return UNCONF;
246 }
247 
248 /*
249  * Map a chunk of memory read-only and return an appropriately
250  * const'ed pointer.
251  */
252 
253 static const void *
mpbios_map(paddr_t pa,int len,struct mp_map * handle)254 mpbios_map(paddr_t pa, int len, struct mp_map *handle)
255 {
256           paddr_t pgpa = x86_trunc_page(pa);
257           paddr_t endpa = x86_round_page(pa + len);
258           vaddr_t va = uvm_km_alloc(kernel_map, endpa - pgpa, 0, UVM_KMF_VAONLY);
259           vaddr_t retva = va + (pa & PGOFSET);
260 
261           handle->pa = pa;
262           handle->pg = pgpa;
263           handle->psize = len;
264           handle->baseva = va;
265           handle->vsize = endpa-pgpa;
266 
267           do {
268                     pmap_kenter_pa(va, pgpa, VM_PROT_READ, 0);
269                     va += PAGE_SIZE;
270                     pgpa += PAGE_SIZE;
271           } while (pgpa < endpa);
272           pmap_update(pmap_kernel());
273 
274           return (const void *)retva;
275 }
276 
277 inline static void
mpbios_unmap(struct mp_map * handle)278 mpbios_unmap(struct mp_map *handle)
279 {
280           pmap_kremove(handle->baseva, handle->vsize);
281           pmap_update(pmap_kernel());
282           uvm_km_free(kernel_map, handle->baseva, handle->vsize, UVM_KMF_VAONLY);
283 }
284 
285 /*
286  * Look for an Intel MP spec table, indicating SMP capable hardware.
287  */
288 int
mpbios_probe(device_t self)289 mpbios_probe(device_t self)
290 {
291           paddr_t             ebda, memtop;
292 
293           paddr_t             cthpa;
294           int                 cthlen;
295           const uint8_t       *mpbios_page;
296           int                 scan_loc;
297 
298           struct              mp_map t;
299 
300           /* If MP is disabled, don't use MPBIOS or the ioapics. */
301           if ((boothowto & RB_MD1) != 0)
302                     return 0;
303 
304           /* see if EBDA exists */
305 
306           mpbios_page = mpbios_map(0, PAGE_SIZE, &t);
307 
308           ebda = *(const uint16_t *)(&mpbios_page[0x40e]);
309           ebda <<= 4;
310 
311           memtop = *(const uint16_t *)(&mpbios_page[0x413]);
312           memtop <<= 10;
313 
314           mpbios_page = NULL;
315           mpbios_unmap(&t);
316 
317           scan_loc = 0;
318 
319           if (ebda && ebda < IOM_BEGIN ) {
320                     mp_fps = mpbios_search(self, ebda, 1024, &mp_fp_map);
321                     if (mp_fps != NULL)
322                               goto found;
323           }
324 
325           scan_loc = 1;
326 
327           if (memtop && memtop <= IOM_BEGIN ) {
328                     mp_fps = mpbios_search(self, memtop - 1024, 1024, &mp_fp_map);
329                     if (mp_fps != NULL)
330                               goto found;
331           }
332 
333           scan_loc = 2;
334 
335           mp_fps = mpbios_search(self, BIOS_BASE, BIOS_COUNT, &mp_fp_map);
336           if (mp_fps != NULL)
337                     goto found;
338 
339 #ifdef MPTABLE_LINUX_BUG_COMPAT
340           /*
341            * Linux assumes that it always has 640 kB of base memory and
342            * searches for the MP table at 639k regardless of whether that
343            * address is present in the system memory map.  Some VM systems
344            * rely on this buggy behaviour.
345            */
346           mp_fps = mpbios_search(self, 639 * 1024, 1024 / 4, &mp_fp_map);
347           if (mp_fps != NULL)
348                     goto found;
349 #endif
350 
351 
352           /* nothing found */
353           return 0;
354 
355  found:
356           if (mp_verbose)
357                     aprint_verbose_dev(self,
358                         "MP floating pointer found in %s at 0x%jx\n",
359                         loc_where[scan_loc], (uintmax_t)mp_fp_map.pa);
360 
361           if (mp_fps->pap == 0) {
362                     if (mp_fps->mpfb1 == 0) {
363                               aprint_error_dev(self, "MP fps invalid: "
364                                   "no default config and no configuration table\n");
365 
366                               goto err;
367                     }
368                     return 10;
369           }
370 
371           cthpa = mp_fps->pap;
372 
373           mp_cth = mpbios_map (cthpa, sizeof (*mp_cth), &mp_cfg_table_map);
374           cthlen = mp_cth->base_len;
375           mpbios_unmap(&mp_cfg_table_map);
376 
377           mp_cth = mpbios_map (cthpa, cthlen, &mp_cfg_table_map);
378 
379           if (mp_verbose)
380                     aprint_verbose_dev(self,
381                         "MP config table at 0x%jx, %d bytes long\n",
382                         (uintmax_t)cthpa, cthlen);
383 
384           if (mp_cth->signature != MP_CT_SIG) {
385                     aprint_error_dev(self, "MP signature mismatch (%x vs %x)\n",
386                         MP_CT_SIG, mp_cth->signature);
387                     goto err;
388           }
389 
390           if (mpbios_cksum(mp_cth, cthlen)) {
391                     aprint_error_dev(self,
392                         "MP Configuration Table checksum mismatch\n");
393                     goto err;
394           }
395           return 10;
396  err:
397           if (mp_fps) {
398                     mp_fps = NULL;
399                     mpbios_unmap(&mp_fp_map);
400           }
401           if (mp_cth) {
402                     mp_cth = NULL;
403                     mpbios_unmap(&mp_cfg_table_map);
404           }
405           return 0;
406 }
407 
408 
409 /*
410  * Simple byte checksum used on config tables.
411  */
412 
413 inline static int
mpbios_cksum(const void * start,int len)414 mpbios_cksum(const void *start, int len)
415 {
416           unsigned char res=0;
417           const char *p = start;
418           const char *end = p + len;
419 
420           while (p < end)
421                     res += *p++;
422 
423           return res;
424 }
425 
426 
427 /*
428  * Look for the MP floating pointer signature in the given physical
429  * address range.
430  *
431  * We map the memory, scan through it, and unmap it.
432  * If we find it, remap the floating pointer structure and return it.
433  */
434 
435 const void *
mpbios_search(device_t self,paddr_t start,int count,struct mp_map * map)436 mpbios_search(device_t self, paddr_t start, int count,
437                 struct mp_map *map)
438 {
439           struct mp_map t;
440 
441           int i, len;
442           const struct mpbios_fps *m;
443           int end = count - sizeof(*m);
444           const uint8_t *base = mpbios_map (start, count, &t);
445 
446           if (mp_verbose)
447                     aprint_verbose_dev(self,
448                         "scanning 0x%jx to 0x%jx for MP signature\n",
449                         (uintmax_t)start, (uintmax_t)(start+count-sizeof(*m)));
450 
451           for (i = 0; i <= end; i += 4) {
452                     m = (const struct mpbios_fps *)&base[i];
453 
454                     if ((m->signature == MP_FP_SIG) &&
455                         ((len = m->length << 4) != 0) &&
456                         mpbios_cksum(m, (m->length << 4)) == 0) {
457                               mpbios_unmap (&t);
458 
459                               return mpbios_map(start + i, len, map);
460                     }
461           }
462           mpbios_unmap(&t);
463 
464           return 0;
465 }
466 
467 /*
468  * MP configuration table parsing.
469  */
470 
471 static struct mpbios_baseentry mp_conf[] =
472 {
473           {0, 20, 0, "cpu"},
474           {1, 8, 0, "bus"},
475           {2, 8, 0, "ioapic"},
476           {3, 8, 0, "ioint"},
477           {4, 8, 0, "lint"},
478 };
479 
480 static struct mp_bus extint_bus = {
481           "ExtINT",
482           -1,
483           mp_print_special_intr,
484           mp_cfg_special_intr,
485           NULL, 0, 0, NULL, 0
486 };
487 static struct mp_bus smi_bus = {
488           "SMI",
489           -1,
490           mp_print_special_intr,
491           mp_cfg_special_intr,
492           NULL, 0, 0, NULL, 0
493 };
494 static struct mp_bus nmi_bus = {
495           "NMI",
496           -1,
497           mp_print_special_intr,
498           mp_cfg_special_intr,
499           NULL, 0, 0, NULL, 0
500 };
501 
502 /*
503  * MP default configuration tables (acc. MP Specification Version 1.4)
504  */
505 
506 /*
507  * Default configurations always feature two processors and the local APIC IDs
508  * are assigned consecutively by hardware starting from zero (sec. 5). We set
509  * I/O APIC ID to 2.
510  */
511 #define DFLT_IOAPIC_ID        2
512 
513 #define ELCR_INV    0x1
514 #define MCA_INV               0x2
515 #define IRQ_VAR               0x4
516 #define INTIN0_NC   0x8
517 
518 static const struct dflt_conf_entry dflt_conf_tab[7] = {
519           /*
520            * Assume all systems with EISA and (modern) PCI chipsets have ELCRs
521            * (to control external interrupt-level inverters). MCA systems must
522            * use fixed inverters for INTIN1-INTIN15 (table 5-1; sec. 5.3.2).
523            */
524           {{"ISA   ", NULL    }, 0                  },      /* default config 1 */
525           {{"EISA  ", NULL    }, ELCR_INV | IRQ_VAR },      /* default config 2 */
526           {{"EISA  ", NULL    }, ELCR_INV           },      /* default config 3 */
527           {{"MCA   ", NULL    }, MCA_INV            },      /* default config 4 */
528           {{"ISA   ", "PCI   "}, ELCR_INV           },      /* default config 5 */
529           {{"EISA  ", "PCI   "}, ELCR_INV           },      /* default config 6 */
530           {{"MCA   ", "PCI   "}, MCA_INV | INTIN0_NC}       /* default config 7 */
531 };
532 
533 #define _ (-1) /* INTINx not connected (to a bus interrupt) */
534 
535 static const int dflt_bus_irq_tab[2][16] = {
536           /* Default configs 1,3-7 connect INTIN1-INTIN15 to bus interrupts. */
537           {_, 1, 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
538           /*
539            * Default config 2 connects neither timer IRQ0 nor DMA chaining to
540            * INTIN2 and INTIN13 (sec. 5.3).
541            */
542           {_, 1, _, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,  _, 14, 15}
543 };
544 
545 #undef _
546 
547 static const uint8_t dflt_lint_tab[2] = {
548           MPS_INTTYPE_ExtINT, MPS_INTTYPE_NMI
549 };
550 
551 
552 #ifdef MPTABLE_LINUX_BUG_COMPAT
553 /* Compute the correct entry_count value. */
554 static uint16_t
compute_entry_count(const uint8_t * entry,const uint8_t * end)555 compute_entry_count(const uint8_t *entry, const uint8_t *end)
556 {
557           size_t nentries = 0;
558 
559           while (entry < end) {
560                     switch (*entry) {
561                     case MPS_MCT_CPU:
562                     case MPS_MCT_BUS:
563                     case MPS_MCT_IOAPIC:
564                     case MPS_MCT_IOINT:
565                     case MPS_MCT_LINT:
566                               break;
567                     default:
568                               panic("%s: Unknown MP Config Entry %d\n", __func__,
569                                         (int)*entry);
570                     }
571                     entry += mp_conf[*entry].length;;
572                     nentries++;
573           }
574           return (uint16_t)(nentries);
575 }
576 #endif
577 /*
578  * 1st pass on BIOS's Intel MP specification table.
579  *
580  * initializes:
581  *        mp_ncpus = 1
582  *
583  * determines:
584  *        cpu_apic_address (common to all CPUs)
585  *        ioapic_address[N]
586  *        mp_naps
587  *        mp_nbus
588  *        mp_napics
589  *        nintrs
590  */
591 void
mpbios_scan(device_t self,int * ncpup)592 mpbios_scan(device_t self, int *ncpup)
593 {
594           const uint8_t       *position, *end;
595           size_t          i;
596           int                 count;
597           int                 type;
598           int                 intr_cnt, cur_intr;
599 #if NLAPIC > 0
600           paddr_t             lapic_base;
601 #endif
602 #ifdef MPTABLE_LINUX_BUG_COMPAT
603           uint16_t  countfix = 0;
604 #endif
605           const struct dflt_conf_entry *dflt_conf;
606           const int *dflt_bus_irq;
607           const struct mpbios_int *iep;
608           struct mpbios_int ie;
609 
610           aprint_normal_dev(self, "Intel MP Specification ");
611 
612           switch (mp_fps->spec_rev) {
613           case 1:
614                     aprint_normal("(Version 1.1)");
615                     break;
616           case 4:
617                     aprint_normal("(Version 1.4)");
618                     break;
619           default:
620                     aprint_normal("(unrecognized rev %d)", mp_fps->spec_rev);
621           }
622 
623           /*
624            * looks like we've got a MP system.  start setting up
625            * infrastructure..
626            * XXX is this the right place??
627            */
628 
629 #if NACPICA > 0
630           if (mpacpi_ncpu == 0) {
631 #endif
632 #if NLAPIC > 0
633                     lapic_base = LAPIC_BASE;
634                     if (mp_cth != NULL)
635                               lapic_base = (paddr_t)mp_cth->apic_address;
636 
637                     lapic_boot_init(lapic_base);
638 #endif
639 #if NACPICA > 0
640           }
641 #endif
642 
643           /* check for use of 'default' configuration */
644           if (mp_fps->mpfb1 != 0) {
645 
646                     if (mp_fps->mpfb1 > __arraycount(dflt_conf_tab))
647                               panic("Unsupported MP default configuration %d\n",
648                                     mp_fps->mpfb1);
649 
650                     aprint_normal("\n");
651                     aprint_normal_dev(self, "MP default configuration %d\n",
652                         mp_fps->mpfb1);
653 
654                     dflt_conf = &dflt_conf_tab[mp_fps->mpfb1 - 1];
655                     dflt_bus_irq =
656                         dflt_bus_irq_tab[(dflt_conf->flags & IRQ_VAR) != 0];
657 
658 #if NACPICA > 0
659                     if (mpacpi_ncpu == 0)
660 #endif
661                               mpbios_dflt_conf_cpu(self);
662 
663 #if NACPICA > 0
664                     if (mpacpi_nioapic == 0)
665 #endif
666                               mpbios_dflt_conf_ioapic(self);
667 
668                     /*
669                      * Walk the table once, counting items.
670                      */
671                     mp_nbus = 0;
672                     for (i = 0; i < __arraycount(dflt_conf->bus_type); i++) {
673                               if (dflt_conf->bus_type[i] != NULL)
674                                         mp_nbus++;
675                     }
676                     KASSERT(mp_nbus != 0);
677 
678                     mp_busses = kmem_zalloc(sizeof(struct mp_bus) * mp_nbus,
679                                                   KM_SLEEP);
680                     KASSERT(mp_busses != NULL);
681 
682                     /* INTIN0 */
683                     intr_cnt = (dflt_conf->flags & INTIN0_NC) ? 0 : 1;
684                     /* INTINx */
685                     for (i = 0; i < __arraycount(dflt_bus_irq_tab[0]); i++) {
686                               if (dflt_bus_irq[i] >= 0)
687                                         intr_cnt++;
688                     }
689                     KASSERT(intr_cnt != 0);
690 
691                     /* LINTINx */
692                     for (i = 0; i < __arraycount(dflt_lint_tab); i++)
693                               intr_cnt++;
694 
695                     mp_intrs = kmem_zalloc(sizeof(struct mp_intr_map) * intr_cnt,
696                                                KM_SLEEP);
697                     KASSERT(mp_intrs != NULL);
698                     mp_nintr = intr_cnt;
699 
700                     /*
701                      * Re-walk the table, recording info of interest.
702                      */
703                     mpbios_dflt_conf_bus(self, dflt_conf);
704                     mpbios_dflt_conf_int(self, dflt_conf, dflt_bus_irq);
705           } else {
706                     /*
707                      * should not happen; mp_probe returns 0 in this case,
708                      * but..
709                      */
710                     if (mp_cth == NULL)
711                               panic ("mpbios_scan: no config (can't happen?)");
712 
713                     printf(" (%8.8s %12.12s)\n",
714                         mp_cth->oem_id, mp_cth->product_id);
715 
716                     /*
717                      * Walk the table once, counting items
718                      */
719                     position = (const uint8_t *)(mp_cth);
720                     end = position + mp_cth->base_len;
721                     position += sizeof(*mp_cth);
722 
723                     count = mp_cth->entry_count;
724 #ifdef MPTABLE_LINUX_BUG_COMPAT
725                     if (count == 0) {
726                               /* count the correct entry_count */
727                               countfix = compute_entry_count(position, end);
728                               count = countfix;
729                     }
730 #endif
731                     intr_cnt = 0;
732 
733                     while ((count--) && (position < end)) {
734                               type = *position;
735                               if (type >= MPS_MCT_NTYPES) {
736                                         aprint_error_dev(self, "unknown entry type %x"
737                                             " in MP config table\n", type);
738                                         break;
739                               }
740                               mp_conf[type].count++;
741                               if (type == MPS_MCT_BUS) {
742                                         const struct mpbios_bus *bp =
743                                             (const struct mpbios_bus *)position;
744                                         if (bp->bus_id >= mp_nbus)
745                                                   mp_nbus = bp->bus_id + 1;
746                               }
747                               /*
748                                * Count actual interrupt instances.
749                                * dst_apic_id of MPS_ALL_APICS means "wired to all
750                                * apics of this type".
751                                */
752                               if (type == MPS_MCT_IOINT) {
753                                         iep = (const struct mpbios_int *)position;
754                                         if (iep->dst_apic_id == MPS_ALL_APICS)
755                                                   intr_cnt +=
756                                                       mp_conf[MPS_MCT_IOAPIC].count;
757                                         else
758                                                   intr_cnt++;
759                               } else if (type == MPS_MCT_LINT)
760                                         intr_cnt++;
761                               position += mp_conf[type].length;
762                     }
763 
764                     mp_busses = kmem_zalloc(sizeof(struct mp_bus)*mp_nbus,
765                         KM_SLEEP);
766                     KASSERT(mp_busses != NULL);
767                     mp_intrs = kmem_zalloc(sizeof(struct mp_intr_map)*intr_cnt,
768                         KM_SLEEP);
769                     KASSERT(mp_intrs != NULL);
770                     mp_nintr = intr_cnt;
771 
772                     /* re-walk the table, recording info of interest */
773                     position = (const uint8_t *)mp_cth + sizeof(*mp_cth);
774                     count = mp_cth->entry_count;
775 #ifdef MPTABLE_LINUX_BUG_COMPAT
776                     if (count == 0)
777                               count = countfix;
778 #endif
779                     cur_intr = 0;
780 
781                     while ((count--) && (position < end)) {
782                               switch (type = *position) {
783                               case MPS_MCT_CPU:
784 #if NACPICA > 0
785                                         /* ACPI has done this for us */
786                                         if (mpacpi_ncpu)
787                                                   break;
788 #endif
789                                         mpbios_cpu(position, self);
790                                         break;
791                               case MPS_MCT_BUS:
792                                         mpbios_bus(position, self);
793                                         break;
794                               case MPS_MCT_IOAPIC:
795 #if NACPICA > 0
796                                         /* ACPI has done this for us */
797                                         if (mpacpi_nioapic)
798                                                   break;
799 #endif
800                                         mpbios_ioapic(position, self);
801                                         break;
802                               case MPS_MCT_IOINT:
803                                         iep = (const struct mpbios_int *)position;
804                                         ie = *iep;
805                                         if (iep->dst_apic_id == MPS_ALL_APICS) {
806 #if NIOAPIC > 0
807                                                   struct ioapic_softc *sc;
808                                                   for (sc = ioapics ; sc != NULL;
809                                                        sc = sc->sc_next) {
810                                                             ie.dst_apic_id = sc->sc_pic.pic_apicid;
811                                                             mpbios_int((char *)&ie, type,
812                                                                 &mp_intrs[cur_intr++]);
813                                                   }
814 #endif
815                                         } else {
816                                                   mpbios_int(position, type,
817                                                       &mp_intrs[cur_intr++]);
818                                         }
819                                         break;
820                               case MPS_MCT_LINT:
821                                         mpbios_int(position, type,
822                                             &mp_intrs[cur_intr]);
823                                         cur_intr++;
824                                         break;
825                               default:
826                                         aprint_error_dev(self, "unknown entry type %x"
827                                             " in MP config table\n", type);
828                                         /* NOTREACHED */
829                                         return;
830                               }
831 
832                               position += mp_conf[type].length;
833                     }
834                     if (mp_verbose && mp_cth->ext_len)
835                               aprint_verbose_dev(self, "MP WARNING: %d bytes of"
836                                   " extended entries not examined\n",
837                                   mp_cth->ext_len);
838           }
839           /* Clean up. */
840           mp_fps = NULL;
841           mpbios_unmap (&mp_fp_map);
842           if (mp_cth != NULL) {
843                     mp_cth = NULL;
844                     mpbios_unmap (&mp_cfg_table_map);
845           }
846           mpbios_scanned = 1;
847 
848           *ncpup = mpbios_ncpu;
849 }
850 
851 static void
mpbios_cpu(const uint8_t * ent,device_t self)852 mpbios_cpu(const uint8_t *ent, device_t self)
853 {
854           const struct mpbios_proc *entry = (const struct mpbios_proc *)ent;
855           struct cpu_attach_args caa;
856           int locs[CPUBUSCF_NLOCS];
857 
858           /* XXX move this into the CPU attachment goo. */
859           /* check for usability */
860           if (!(entry->cpu_flags & PROCENTRY_FLAG_EN))
861                     return;
862 
863           mpbios_ncpu++;
864 
865           /* check for BSP flag */
866           if (entry->cpu_flags & PROCENTRY_FLAG_BP)
867                     caa.cpu_role = CPU_ROLE_BP;
868           else
869                     caa.cpu_role = CPU_ROLE_AP;
870 
871           caa.cpu_id = entry->apic_id;
872           caa.cpu_number = entry->apic_id;
873           caa.cpu_func = &mp_cpu_funcs;
874           locs[CPUBUSCF_APID] = caa.cpu_number;
875 
876           config_found(self, &caa, mp_cpuprint,
877               CFARGS(.submatch = config_stdsubmatch,
878                        .iattr = "cpubus",
879                        .locators = locs));
880 }
881 
882 static void
mpbios_dflt_conf_cpu(device_t self)883 mpbios_dflt_conf_cpu(device_t self)
884 {
885           struct mpbios_proc mpp;
886 
887           /* mpp.type and mpp.apic_version are irrelevant for mpbios_cpu(). */
888           /*
889            * Default configurations always feature two processors and the local
890            * APIC IDs are assigned consecutively by hardware starting from zero
891            * (sec. 5). Just determine the BSP (APIC ID).
892            */
893           mpp.apic_id = cpu_info_primary.ci_cpuid;
894           mpp.cpu_flags = PROCENTRY_FLAG_EN | PROCENTRY_FLAG_BP;
895           mpbios_cpu((uint8_t *)&mpp, self);
896 
897           mpp.apic_id = 1 - cpu_info_primary.ci_cpuid;
898           mpp.cpu_flags = PROCENTRY_FLAG_EN;
899           mpbios_cpu((uint8_t *)&mpp, self);
900 }
901 
902 static void
mpbios_dflt_conf_bus(device_t self,const struct dflt_conf_entry * dflt_conf)903 mpbios_dflt_conf_bus(device_t self, const struct dflt_conf_entry *dflt_conf)
904 {
905           struct mpbios_bus mpb;
906           size_t i;
907 
908           /* mpb.type is irrelevant for mpbios_bus(). */
909           mpb.bus_id = 0;
910           for (i = 0; i < __arraycount(dflt_conf->bus_type); i++) {
911                     if (dflt_conf->bus_type[i] != NULL) {
912                               memcpy(mpb.bus_type, dflt_conf->bus_type[i], 6);
913                               mpbios_bus((u_int8_t *)&mpb, self);
914                               mpb.bus_id++;
915                     }
916           }
917 }
918 
919 static void
mpbios_dflt_conf_ioapic(device_t self)920 mpbios_dflt_conf_ioapic(device_t self)
921 {
922           struct mpbios_ioapic mpio;
923 
924           /* mpio.type is irrelevant for mpbios_ioapic(). */
925           mpio.apic_id = DFLT_IOAPIC_ID;
926           /* XXX Let ioapic driver read real APIC version... */
927           mpio.apic_version = 0;
928           mpio.apic_flags = IOAPICENTRY_FLAG_EN;
929           mpio.apic_address = (uint32_t)IOAPIC_BASE_DEFAULT;
930           mpbios_ioapic((uint8_t *)&mpio, self);
931 }
932 
933 static void
mpbios_dflt_conf_int(device_t self,const struct dflt_conf_entry * dflt_conf,const int * dflt_bus_irq)934 mpbios_dflt_conf_int(device_t self, const struct dflt_conf_entry *dflt_conf,
935                          const int *dflt_bus_irq)
936 {
937           struct   mpbios_int mpi;
938           size_t   i;
939           int      cur_intr;
940           uint16_t level_inv;
941 
942           cur_intr = 0;
943           /*
944            * INTIN0
945            */
946           /*
947            * 8259A INTR is connected to INTIN0 for default configs 1-6, but not
948            * for default config 7 (sec. 5.3).
949            */
950           if ((dflt_conf->flags & INTIN0_NC) == 0) {
951                     /* mpi.type is irrelevant for mpbios_int(). */
952                     mpi.int_type = MPS_INTTYPE_ExtINT;
953                     mpi.int_flags = 0;
954                     mpi.src_bus_id = 0;
955                     mpi.src_bus_irq = 0;
956                     mpi.dst_apic_id = DFLT_IOAPIC_ID;
957                     mpi.dst_apic_int = 0;
958                     mpbios_int((u_int8_t *)&mpi, MPS_MCT_IOINT,
959                                  &mp_intrs[cur_intr++]);
960           }
961 
962           /*
963            * INTINx
964            */
965           /* mpi.type is irrelevant for mpbios_int(). */
966           mpi.int_type = MPS_INTTYPE_INT;
967           /*
968            * PCI interrupt lines appear as (E)ISA interrupt lines/on bus 0
969            * (sec. 5.2).
970            */
971           mpi.src_bus_id = 0;
972           mpi.dst_apic_id = DFLT_IOAPIC_ID;
973           /*
974            * Compliant systems must convert active-low, level-triggered
975            * interrupts to active-high by external inverters before INTINx
976            *(table 5-1; sec. 5.3.2).
977            */
978           if (dflt_conf->flags & ELCR_INV) {
979 #ifdef X86_MPBIOS_SUPPORT_EISA
980                     /* Systems with ELCRs use them to control the inverters. */
981                     level_inv = ((uint16_t)inb(ELCR1) << 8) | inb(ELCR0);
982 #else
983                     level_inv = 0;
984 #endif
985           } else if (dflt_conf->flags & MCA_INV) {
986                     /* MCA systems have fixed inverters. */
987                     level_inv = 0xffffU;
988           } else
989                     level_inv = 0;
990 
991           for (i = 0; i < __arraycount(dflt_bus_irq_tab[0]); i++) {
992                     if (dflt_bus_irq[i] >= 0) {
993                               mpi.src_bus_irq = (uint8_t)dflt_bus_irq[i];
994                               if (level_inv & (1U << mpi.src_bus_irq))
995                                         mpi.int_flags = (MPS_INTTR_LEVEL << 2)
996                                                             | MPS_INTPO_ACTHI;
997                               else
998                                         mpi.int_flags = 0; /* conforms to bus spec. */
999                               mpi.dst_apic_int = (uint8_t)i;
1000                               mpbios_int((u_int8_t *)&mpi, MPS_MCT_IOINT,
1001                                            &mp_intrs[cur_intr++]);
1002                     }
1003           }
1004 
1005           /*
1006            * LINTINx
1007            */
1008           /* mpi.type is irrelevant for mpbios_int(). */
1009           mpi.int_flags = 0;
1010           mpi.src_bus_id = 0;
1011           mpi.src_bus_irq = 0;
1012           mpi.dst_apic_id = MPS_ALL_APICS;
1013           for (i = 0; i < __arraycount(dflt_lint_tab); i++) {
1014                     mpi.int_type = dflt_lint_tab[i];
1015                     mpi.dst_apic_int = (uint8_t)i;
1016                     mpbios_int((u_int8_t *)&mpi, MPS_MCT_LINT,
1017                                  &mp_intrs[cur_intr++]);
1018           }
1019 }
1020 
1021 /*
1022  * The following functions conspire to compute base ioapic redirection
1023  * table entry for a given interrupt line.
1024  *
1025  * Fill in: trigger mode, polarity, and possibly delivery mode.
1026  */
1027 static void
mp_cfg_special_intr(const struct mpbios_int * entry,uint32_t * redir)1028 mp_cfg_special_intr(const struct mpbios_int *entry, uint32_t *redir)
1029 {
1030 
1031           /*
1032            * All of these require edge triggered, zero vector,
1033            * appropriate delivery mode.
1034            * see page 13 of the 82093AA datasheet.
1035            */
1036           *redir &= ~IOAPIC_REDLO_DEL_MASK;
1037           *redir &= ~IOAPIC_REDLO_VECTOR_MASK;
1038           *redir &= ~IOAPIC_REDLO_LEVEL;
1039 
1040           switch (entry->int_type) {
1041           case MPS_INTTYPE_NMI:
1042                     *redir |= (IOAPIC_REDLO_DEL_NMI<<IOAPIC_REDLO_DEL_SHIFT);
1043                     break;
1044 
1045           case MPS_INTTYPE_SMI:
1046                     *redir |= (IOAPIC_REDLO_DEL_SMI<<IOAPIC_REDLO_DEL_SHIFT);
1047                     break;
1048 
1049           case MPS_INTTYPE_ExtINT:
1050                     /*
1051                      * We are using the ioapic in "native" mode.
1052                      * This indicates where the 8259 is wired to the ioapic
1053                      * and/or local apic..
1054                      */
1055                     *redir |= (IOAPIC_REDLO_DEL_EXTINT<<IOAPIC_REDLO_DEL_SHIFT);
1056                     *redir |= (IOAPIC_REDLO_MASK);
1057                     break;
1058           }
1059 }
1060 
1061 /* XXX too much duplicated code here. */
1062 
1063 static void
mp_cfg_pci_intr(const struct mpbios_int * entry,uint32_t * redir)1064 mp_cfg_pci_intr(const struct mpbios_int *entry, uint32_t *redir)
1065 {
1066           int mpspo = entry->int_flags & 0x03; /* XXX magic */
1067           int mpstrig = (entry->int_flags >> 2) & 0x03; /* XXX magic */
1068 
1069           *redir &= ~IOAPIC_REDLO_DEL_MASK;
1070           switch (mpspo) {
1071           case MPS_INTPO_ACTHI:
1072                     *redir &= ~IOAPIC_REDLO_ACTLO;
1073                     break;
1074           case MPS_INTPO_DEF:
1075           case MPS_INTPO_ACTLO:
1076                     *redir |= IOAPIC_REDLO_ACTLO;
1077                     break;
1078           default:
1079                     panic("unknown MPS interrupt polarity %d", mpspo);
1080           }
1081 
1082           if (entry->int_type != MPS_INTTYPE_INT) {
1083                     mp_cfg_special_intr(entry, redir);
1084                     return;
1085           }
1086           *redir |= (IOAPIC_REDLO_DEL_FIXED<<IOAPIC_REDLO_DEL_SHIFT);
1087 
1088           switch (mpstrig) {
1089           case MPS_INTTR_DEF:
1090           case MPS_INTTR_LEVEL:
1091                     *redir |= IOAPIC_REDLO_LEVEL;
1092                     break;
1093           case MPS_INTTR_EDGE:
1094                     *redir &= ~IOAPIC_REDLO_LEVEL;
1095                     break;
1096           default:
1097                     panic("unknown MPS interrupt trigger %d", mpstrig);
1098           }
1099 }
1100 
1101 #ifdef X86_MPBIOS_SUPPORT_EISA
1102 static void
mp_cfg_eisa_intr(const struct mpbios_int * entry,uint32_t * redir)1103 mp_cfg_eisa_intr(const struct mpbios_int *entry, uint32_t *redir)
1104 {
1105           int mpspo = entry->int_flags & 0x03; /* XXX magic */
1106           int mpstrig = (entry->int_flags >> 2) & 0x03; /* XXX magic */
1107 
1108           *redir &= ~IOAPIC_REDLO_DEL_MASK;
1109           switch (mpspo) {
1110           case MPS_INTPO_DEF:
1111           case MPS_INTPO_ACTHI:
1112                     *redir &= ~IOAPIC_REDLO_ACTLO;
1113                     break;
1114           case MPS_INTPO_ACTLO:
1115                     *redir |= IOAPIC_REDLO_ACTLO;
1116                     break;
1117           default:
1118                     panic("unknown MPS interrupt polarity %d", mpspo);
1119           }
1120 
1121           if (entry->int_type != MPS_INTTYPE_INT) {
1122                     mp_cfg_special_intr(entry, redir);
1123                     return;
1124           }
1125           *redir |= (IOAPIC_REDLO_DEL_FIXED << IOAPIC_REDLO_DEL_SHIFT);
1126 
1127           switch (mpstrig) {
1128           case MPS_INTTR_LEVEL:
1129                     *redir |= IOAPIC_REDLO_LEVEL;
1130                     break;
1131           case MPS_INTTR_EDGE:
1132                     *redir &= ~IOAPIC_REDLO_LEVEL;
1133                     break;
1134           case MPS_INTTR_DEF:
1135                     /*
1136                      * Set "default" setting based on ELCR value snagged
1137                      * earlier.
1138                      */
1139                     if (mp_busses[entry->src_bus_id].mb_data &
1140                         (1 << entry->src_bus_irq)) {
1141                               *redir |= IOAPIC_REDLO_LEVEL;
1142                     } else {
1143                               *redir &= ~IOAPIC_REDLO_LEVEL;
1144                     }
1145                     break;
1146           default:
1147                     panic("unknown MPS interrupt trigger %d", mpstrig);
1148           }
1149 }
1150 #endif
1151 
1152 
1153 static void
mp_cfg_isa_intr(const struct mpbios_int * entry,uint32_t * redir)1154 mp_cfg_isa_intr(const struct mpbios_int *entry, uint32_t *redir)
1155 {
1156           int mpspo = entry->int_flags & 0x03; /* XXX magic */
1157           int mpstrig = (entry->int_flags >> 2) & 0x03; /* XXX magic */
1158 
1159           *redir &= ~IOAPIC_REDLO_DEL_MASK;
1160           switch (mpspo) {
1161           case MPS_INTPO_DEF:
1162           case MPS_INTPO_ACTHI:
1163                     *redir &= ~IOAPIC_REDLO_ACTLO;
1164                     break;
1165           case MPS_INTPO_ACTLO:
1166                     *redir |= IOAPIC_REDLO_ACTLO;
1167                     break;
1168           default:
1169                     panic("unknown MPS interrupt polarity %d", mpspo);
1170           }
1171 
1172           if (entry->int_type != MPS_INTTYPE_INT) {
1173                     mp_cfg_special_intr(entry, redir);
1174                     return;
1175           }
1176           *redir |= (IOAPIC_REDLO_DEL_FIXED << IOAPIC_REDLO_DEL_SHIFT);
1177 
1178           switch (mpstrig) {
1179           case MPS_INTTR_LEVEL:
1180                     *redir |= IOAPIC_REDLO_LEVEL;
1181                     break;
1182           case MPS_INTTR_DEF:
1183           case MPS_INTTR_EDGE:
1184                     *redir &= ~IOAPIC_REDLO_LEVEL;
1185                     break;
1186           default:
1187                     panic("unknown MPS interrupt trigger %d", mpstrig);
1188           }
1189 }
1190 
1191 
1192 static void
mp_print_special_intr(int intr)1193 mp_print_special_intr(int intr)
1194 {
1195 }
1196 
1197 static void
mp_print_pci_intr(int intr)1198 mp_print_pci_intr(int intr)
1199 {
1200           printf(" device %d INT_%c", (intr>>2)&0x1f, 'A' + (intr & 0x3));
1201 }
1202 
1203 static void
mp_print_isa_intr(int intr)1204 mp_print_isa_intr(int intr)
1205 {
1206           printf(" irq %d", intr);
1207 }
1208 
1209 #ifdef X86_MPBIOS_SUPPORT_EISA
1210 static void
mp_print_eisa_intr(int intr)1211 mp_print_eisa_intr(int intr)
1212 {
1213           printf(" EISA irq %d", intr);
1214 }
1215 #endif
1216 
1217 
1218 
1219 #define TAB_UNIT    4
1220 #define TAB_ROUND(a)          _TAB_ROUND(a, TAB_UNIT)
1221 
1222 #define _TAB_ROUND(a,u)       (((a) + (u - 1)) & ~(u-1))
1223 #define EXTEND_TAB(a,u)       (!(_TAB_ROUND(a,u) == _TAB_ROUND((a+1),u)))
1224 
1225 static void
mpbios_bus(const uint8_t * ent,device_t self)1226 mpbios_bus(const uint8_t *ent, device_t self)
1227 {
1228           const struct mpbios_bus *entry = (const struct mpbios_bus *)ent;
1229           int bus_id = entry->bus_id;
1230 
1231           aprint_verbose("mpbios: bus %d is type %6.6s\n", bus_id,
1232               entry->bus_type);
1233 
1234 #ifdef DIAGNOSTIC
1235           /*
1236            * This "should not happen" unless the table changes out
1237            * from underneath us
1238            */
1239           if (bus_id >= mp_nbus) {
1240                     panic("mpbios: bus number %d out of range?? (type %6.6s)\n",
1241                         bus_id, entry->bus_type);
1242           }
1243 #endif
1244 
1245           mp_busses[bus_id].mb_intrs = NULL;
1246 
1247           if (memcmp(entry->bus_type, "PCI   ", 6) == 0) {
1248                     mp_busses[bus_id].mb_name = "pci";
1249                     mp_busses[bus_id].mb_idx = bus_id;
1250                     mp_busses[bus_id].mb_intr_print = mp_print_pci_intr;
1251                     mp_busses[bus_id].mb_intr_cfg = mp_cfg_pci_intr;
1252 #ifdef X86_MPBIOS_SUPPORT_EISA
1253           } else if (memcmp(entry->bus_type, "EISA  ", 6) == 0) {
1254                     mp_busses[bus_id].mb_name = "eisa";
1255                     mp_busses[bus_id].mb_idx = bus_id;
1256                     mp_busses[bus_id].mb_intr_print = mp_print_eisa_intr;
1257                     mp_busses[bus_id].mb_intr_cfg = mp_cfg_eisa_intr;
1258 
1259                     mp_busses[bus_id].mb_data = inb(ELCR0) | (inb(ELCR1) << 8);
1260 
1261                     if (mp_eisa_bus != -1)
1262                               aprint_error("oops: multiple isa busses?\n");
1263                     else
1264                               mp_eisa_bus = bus_id;
1265 #endif
1266 
1267           } else if (memcmp(entry->bus_type, "ISA   ", 6) == 0) {
1268                     mp_busses[bus_id].mb_name = "isa";
1269                     mp_busses[bus_id].mb_idx = 0; /* XXX */
1270                     mp_busses[bus_id].mb_intr_print = mp_print_isa_intr;
1271                     mp_busses[bus_id].mb_intr_cfg = mp_cfg_isa_intr;
1272                     if (mp_isa_bus != -1)
1273                               printf("oops: multiple isa busses?\n");
1274                     else
1275                               mp_isa_bus = bus_id;
1276           } else
1277                     aprint_error_dev(self, "unsupported bus type %6.6s\n",
1278                         entry->bus_type);
1279 }
1280 
1281 
1282 static void
mpbios_ioapic(const uint8_t * ent,device_t self)1283 mpbios_ioapic(const uint8_t *ent, device_t self)
1284 {
1285           const struct mpbios_ioapic *entry = (const struct mpbios_ioapic *)ent;
1286 
1287           /* XXX let flags checking happen in ioapic driver.. */
1288           if (!(entry->apic_flags & IOAPICENTRY_FLAG_EN))
1289                     return;
1290 
1291           mpbios_nioapic++;
1292 
1293 #if NIOAPIC > 0
1294           {
1295           int locs[IOAPICBUSCF_NLOCS];
1296           struct apic_attach_args aaa;
1297 
1298           aaa.apic_id = entry->apic_id;
1299           aaa.apic_version = entry->apic_version;
1300           aaa.apic_address = (paddr_t)entry->apic_address;
1301           aaa.apic_vecbase = -1;
1302           aaa.flags = (mp_fps->mpfb2 & 0x80) ? IOAPIC_PICMODE : IOAPIC_VWIRE;
1303           locs[IOAPICBUSCF_APID] = aaa.apic_id;
1304 
1305           config_found(self, &aaa, mp_ioapicprint,
1306               CFARGS(.submatch = config_stdsubmatch,
1307                        .iattr = "ioapicbus",
1308                        .locators = locs));
1309           }
1310 #endif
1311 }
1312 
1313 static const char inttype_fmt[] = "\177\020"
1314                     "f\0\2type\0" "=\1NMI\0" "=\2SMI\0" "=\3ExtINT\0";
1315 
1316 static const char flagtype_fmt[] = "\177\020"
1317                     "f\0\2pol\0" "=\1Act Hi\0" "=\3Act Lo\0"
1318                     "f\2\2trig\0" "=\1Edge\0" "=\3Level\0";
1319 
1320 static void
mpbios_int(const uint8_t * ent,int enttype,struct mp_intr_map * mpi)1321 mpbios_int(const uint8_t *ent, int enttype, struct mp_intr_map *mpi)
1322 {
1323           const struct mpbios_int *entry = (const struct mpbios_int *)ent;
1324           struct ioapic_softc *sc = NULL;
1325           struct pic *sc2;
1326 
1327           struct mp_intr_map *altmpi;
1328           struct mp_bus *mpb;
1329 
1330           uint32_t id = entry->dst_apic_id;
1331           uint32_t pin = entry->dst_apic_int;
1332           uint32_t bus = entry->src_bus_id;
1333           uint32_t dev = entry->src_bus_irq;
1334           uint32_t type = entry->int_type;
1335           uint32_t flags = entry->int_flags;
1336 
1337           switch (type) {
1338           case MPS_INTTYPE_INT:
1339                     mpb = &(mp_busses[bus]);
1340                     break;
1341           case MPS_INTTYPE_ExtINT:
1342                     mpb = &extint_bus;
1343                     break;
1344           case MPS_INTTYPE_SMI:
1345                     mpb = &smi_bus;
1346                     break;
1347           case MPS_INTTYPE_NMI:
1348                     mpb = &nmi_bus;
1349                     break;
1350           default:
1351                     panic("unknown MPS interrupt type %d", entry->int_type);
1352           }
1353 
1354           mpi->next = mpb->mb_intrs;
1355           mpb->mb_intrs = mpi;
1356           mpi->bus = mpb;
1357           mpi->bus_pin = dev;
1358           mpi->global_int = -1;
1359 
1360           mpi->type = type;
1361           mpi->flags = flags;
1362           mpi->redir = 0;
1363           if (mpb->mb_intr_cfg == NULL) {
1364                     printf("mpbios: can't find bus %d for apic %d pin %d\n",
1365                         bus, id, pin);
1366                     return;
1367           }
1368 
1369           (*mpb->mb_intr_cfg)(entry, &mpi->redir);
1370 
1371           if (enttype == MPS_MCT_IOINT) {
1372 #if NIOAPIC > 0
1373                     sc = ioapic_find(id);
1374 #else
1375                     sc = NULL;
1376 #endif
1377                     if (sc == NULL) {
1378 #if NIOAPIC > 0
1379                               /*
1380                                * If we couldn't find an ioapic by given id, retry to
1381                                * get it by a pin number.
1382                                */
1383                               sc = ioapic_find_bybase(pin);
1384                               if (sc == NULL) {
1385                                         aprint_error("mpbios: can't find ioapic by"
1386                                             " neither apid(%d) nor pin number(%d)\n",
1387                                             id, pin);
1388                                         return;
1389                               }
1390                               aprint_verbose("mpbios: use apid %d instead of %d\n",
1391                                   sc->sc_pic.pic_apicid, id);
1392                               id = sc->sc_pic.pic_apicid;
1393 #else
1394                               aprint_error("mpbios: can't find ioapic %d\n", id);
1395                               return;
1396 #endif
1397                     }
1398 
1399                     /*
1400                      * XXX workaround for broken BIOSs that put the ACPI global
1401                      * interrupt number in the entry, not the pin number.
1402                      */
1403                     if (pin >= sc->sc_apic_sz) {
1404                               sc2 = intr_findpic(pin);
1405                               if (sc2 && sc2->pic_ioapic != sc) {
1406                                         printf("mpbios: bad pin %d for apic %d\n",
1407                                             pin, id);
1408                                         return;
1409                               }
1410                               printf("mpbios: WARNING: pin %d for apic %d too high; "
1411                                      "assuming ACPI global int value\n", pin, id);
1412                               pin -= sc->sc_apic_vecbase;
1413                     }
1414 
1415                     mpi->ioapic = (struct pic *)sc;
1416                     mpi->ioapic_pin = pin;
1417 
1418                     altmpi = sc->sc_pins[pin].ip_map;
1419 
1420                     if (altmpi != NULL) {
1421                               if ((altmpi->type != type) ||
1422                                   (altmpi->flags != flags)) {
1423                                         printf("%s: conflicting map entries for pin %d\n",
1424                                             device_xname(sc->sc_dev), pin);
1425                               }
1426                     } else
1427                               sc->sc_pins[pin].ip_map = mpi;
1428           } else {
1429                     if (pin >= 2)
1430                               printf("pin %d of local apic doesn't exist!\n", pin);
1431                     else {
1432                               mpi->ioapic = NULL;
1433                               mpi->ioapic_pin = pin;
1434                               mpi->cpu_id = id;
1435                     }
1436           }
1437 
1438           mpi->ioapic_ih = APIC_INT_VIA_APIC |
1439               ((id << APIC_INT_APIC_SHIFT) | (pin << APIC_INT_PIN_SHIFT));
1440 
1441           if (mp_verbose) {
1442                     char buf[256];
1443 
1444                     printf("%s: int%d attached to %s",
1445                         sc ? device_xname(sc->sc_dev) : "local apic",
1446                         pin, mpb->mb_name);
1447 
1448                     if (mpb->mb_idx != -1)
1449                               printf("%d", mpb->mb_idx);
1450 
1451                     (*(mpb->mb_intr_print))(dev);
1452 
1453                     snprintb(buf, sizeof(buf), inttype_fmt, type);
1454                     printf(" (type %s", buf);
1455 
1456                     snprintb(buf, sizeof(buf), flagtype_fmt, flags);
1457                     printf(" flags %s)\n", buf);
1458           }
1459 }
1460 
1461 #if NPCI > 0
1462 int
mpbios_pci_attach_hook(device_t parent,device_t self,struct pcibus_attach_args * pba)1463 mpbios_pci_attach_hook(device_t parent, device_t self,
1464                            struct pcibus_attach_args *pba)
1465 {
1466           struct mp_bus *mpb;
1467 
1468           if (mpbios_scanned == 0)
1469                     return ENOENT;
1470 
1471           if (pba->pba_bus >= mp_isa_bus) {
1472                     intr_add_pcibus(pba);
1473                     return 0;
1474           }
1475 
1476           mpb = &mp_busses[pba->pba_bus];
1477           if (mpb->mb_name != NULL) {
1478                     if (strcmp(mpb->mb_name, "pci"))
1479                               return EINVAL;
1480           } else
1481                     mpb->mb_name = "pci";
1482 
1483           if (mp_verbose)
1484                     printf("\n%s: added to list as bus %d", device_xname(parent),
1485                         pba->pba_bus);
1486 
1487           mpb->mb_dev = self;
1488           mpb->mb_pci_bridge_tag = pba->pba_bridgetag;
1489           mpb->mb_pci_chipset_tag = pba->pba_pc;
1490           return 0;
1491 }
1492 #endif
1493