Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/x86/x86 Use the default mp definition tables for an...



details:   https://anonhg.NetBSD.org/src/rev/435a6e01a701
branches:  trunk
changeset: 789538:435a6e01a701
user:      christos <christos%NetBSD.org@localhost>
date:      Wed Aug 21 16:37:31 2013 +0000

description:
Use the default mp definition tables for ancient machines. From Felix
Deichmann.

diffstat:

 sys/arch/x86/x86/mpbios.c |  272 +++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 243 insertions(+), 29 deletions(-)

diffs (truncated from 363 to 300 lines):

diff -r b5611bd50863 -r 435a6e01a701 sys/arch/x86/x86/mpbios.c
--- a/sys/arch/x86/x86/mpbios.c Wed Aug 21 15:26:44 2013 +0000
+++ b/sys/arch/x86/x86/mpbios.c Wed Aug 21 16:37:31 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mpbios.c,v 1.60 2012/11/27 20:32:58 jakllsch Exp $     */
+/*     $NetBSD: mpbios.c,v 1.61 2013/08/21 16:37:31 christos Exp $     */
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -96,7 +96,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mpbios.c,v 1.60 2012/11/27 20:32:58 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mpbios.c,v 1.61 2013/08/21 16:37:31 christos Exp $");
 
 #include "acpica.h"
 #include "lapic.h"
@@ -147,10 +147,6 @@
 
 #include "locators.h"
 
-static struct mpbios_ioapic default_ioapic = {
-    2,0,1,IOAPICENTRY_FLAG_EN,(uint32_t)IOAPIC_BASE_DEFAULT
-};
-
 /* descriptions of MP basetable entries */
 struct mpbios_baseentry {
        uint8_t         type;
@@ -174,6 +170,11 @@
        int             psize;
 };
 
+struct dflt_conf_entry {
+       const char      *bus_type[2];
+       int             flags;
+};
+
 int mp_cpuprint(void *, const char *);
 int mp_ioapicprint(void *, const char *);
 static const void *mpbios_search(device_t, paddr_t, int,
@@ -194,7 +195,12 @@
 static void mp_cfg_isa_intr(const struct mpbios_int *, uint32_t *);
 static void mp_print_isa_intr(int intr);
 
-static void mpbios_cpus(device_t);
+static void mpbios_dflt_conf_cpu(device_t);
+static void mpbios_dflt_conf_bus(device_t, const struct dflt_conf_entry *);
+static void mpbios_dflt_conf_ioapic(device_t);
+static void mpbios_dflt_conf_int(device_t, const struct dflt_conf_entry *,
+                                 const int *);
+
 static void mpbios_cpu(const uint8_t *, device_t);
 static void mpbios_bus(const uint8_t *, device_t);
 static void mpbios_ioapic(const uint8_t *, device_t);
@@ -342,8 +348,6 @@
 
                        goto err;
                }
-               aprint_normal_dev(self, "MP default configuration %d\n",
-                   mp_fps->mpfb1);
                return 10;
        }
 
@@ -476,6 +480,55 @@
        NULL, 0, 0, NULL, 0
 };
 
+/*
+ * MP default configuration tables (acc. MP Specification Version 1.4)
+ */
+
+/*
+ * Default configurations always feature two processors and the local APIC IDs
+ * are assigned consecutively by hardware starting from zero (sec. 5). We set
+ * I/O APIC ID to 2.
+ */
+#define DFLT_IOAPIC_ID 2
+
+#define ELCR_INV       0x1
+#define MCA_INV                0x2
+#define IRQ_VAR                0x4
+#define INTIN0_NC      0x8
+
+static const struct dflt_conf_entry dflt_conf_tab[7] = {
+       /*
+        * Assume all systems with EISA and (modern) PCI chipsets have ELCRs
+        * (to control external interrupt-level inverters). MCA systems must
+        * use fixed inverters for INTIN1-INTIN15 (table 5-1; sec. 5.3.2).
+        */
+       {{"ISA   ", NULL    }, 0                  },    /* default config 1 */
+       {{"EISA  ", NULL    }, ELCR_INV | IRQ_VAR },    /* default config 2 */
+       {{"EISA  ", NULL    }, ELCR_INV           },    /* default config 3 */
+       {{"MCA   ", NULL    }, MCA_INV            },    /* default config 4 */
+       {{"ISA   ", "PCI   "}, ELCR_INV           },    /* default config 5 */
+       {{"EISA  ", "PCI   "}, ELCR_INV           },    /* default config 6 */
+       {{"MCA   ", "PCI   "}, MCA_INV | INTIN0_NC}     /* default config 7 */
+};
+
+#define _ (-1) /* INTINx not connected (to a bus interrupt) */
+
+static const int dflt_bus_irq_tab[2][16] = {
+       /* Default configs 1,3-7 connect INTIN1-INTIN15 to bus interrupts. */
+       {_, 1, 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
+       /*
+        * Default config 2 connects neither timer IRQ0 nor DMA chaining to
+        * INTIN2 and INTIN13 (sec. 5.3).
+        */
+       {_, 1, _, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,  _, 14, 15}
+};
+
+#undef _
+
+static const uint8_t dflt_lint_tab[2] = {
+       MPS_INTTYPE_ExtINT, MPS_INTTYPE_NMI
+};
+
 
 /*
  * 1st pass on BIOS's Intel MP specification table.
@@ -495,10 +548,13 @@
 mpbios_scan(device_t self, int *ncpup)
 {
        const uint8_t   *position, *end;
+       size_t          i;
        int             count;
        int             type;
        int             intr_cnt, cur_intr;
        paddr_t         lapic_base;
+       const struct dflt_conf_entry *dflt_conf;
+       const int *dflt_bus_irq;
        const struct mpbios_int *iep;
        struct mpbios_int ie;
 
@@ -538,30 +594,65 @@
        /* check for use of 'default' configuration */
        if (mp_fps->mpfb1 != 0) {
 
+               if (mp_fps->mpfb1 > __arraycount(dflt_conf_tab))
+                       panic("Unsupported MP default configuration %d\n",
+                             mp_fps->mpfb1);
+
                aprint_normal("\n");
                aprint_normal_dev(self, "MP default configuration %d\n",
                    mp_fps->mpfb1);
+
+               dflt_conf = &dflt_conf_tab[mp_fps->mpfb1 - 1];
+               dflt_bus_irq =
+                   dflt_bus_irq_tab[(dflt_conf->flags & IRQ_VAR) != 0];
+
 #if NACPICA > 0
                if (mpacpi_ncpu == 0)
 #endif
-                       mpbios_cpus(self);
+                       mpbios_dflt_conf_cpu(self);
 
 #if NACPICA > 0
                if (mpacpi_nioapic == 0)
 #endif
-                       mpbios_ioapic((uint8_t *)&default_ioapic, self);
-
-               /* XXX */
-               aprint_verbose_dev(self, "WARNING: interrupts not configured\n");
+                       mpbios_dflt_conf_ioapic(self);
 
                /*
-                * XXX rpaulo: I have a machine that can boot, so I
-                * commented this (for now).
+                * Walk the table once, counting items.
                 */
-#if 0
-               panic("lazy bum");
-               return;
-#endif
+               mp_nbus = 0;
+               for (i = 0; i < __arraycount(dflt_conf->bus_type); i++) {
+                       if (dflt_conf->bus_type[i] != NULL)
+                               mp_nbus++;
+               }
+               KASSERT(mp_nbus != 0);
+
+               mp_busses = kmem_zalloc(sizeof(struct mp_bus) * mp_nbus,
+                                       KM_SLEEP);
+               KASSERT(mp_busses != NULL);
+
+               /* INTIN0 */
+               intr_cnt = (dflt_conf->flags & INTIN0_NC) ? 0 : 1;
+               /* INTINx */
+               for (i = 0; i < __arraycount(dflt_bus_irq_tab[0]); i++) {
+                       if (dflt_bus_irq[i] >= 0)
+                               intr_cnt++;
+               }
+               KASSERT(intr_cnt != 0);
+
+               /* LINTINx */
+               for (i = 0; i < __arraycount(dflt_lint_tab); i++)
+                       intr_cnt++;
+
+               mp_intrs = kmem_zalloc(sizeof(struct mp_intr_map) * intr_cnt,
+                                      KM_SLEEP);
+               KASSERT(mp_intrs != NULL);
+               mp_nintr = intr_cnt;
+
+               /*
+                * Re-walk the table, recording info of interest.
+                */
+               mpbios_dflt_conf_bus(self, dflt_conf);
+               mpbios_dflt_conf_int(self, dflt_conf, dflt_bus_irq);
        } else {
                /*
                 * should not happen; mp_probe returns 0 in this case,
@@ -727,19 +818,142 @@
 }
 
 static void
-mpbios_cpus(device_t self)
+mpbios_dflt_conf_cpu(device_t self)
+{
+       struct mpbios_proc mpp;
+
+       /* mpp.type and mpp.apic_version are irrelevant for mpbios_cpu(). */
+       /*
+        * Default configurations always feature two processors and the local
+        * APIC IDs are assigned consecutively by hardware starting from zero
+        * (sec. 5). Just determine the BSP (APIC ID).
+        */
+       mpp.apic_id = cpu_info_primary.ci_cpuid;
+       mpp.cpu_flags = PROCENTRY_FLAG_EN | PROCENTRY_FLAG_BP;
+       mpbios_cpu((uint8_t *)&mpp, self);
+
+       mpp.apic_id = 1 - cpu_info_primary.ci_cpuid;
+       mpp.cpu_flags = PROCENTRY_FLAG_EN;
+       mpbios_cpu((uint8_t *)&mpp, self);
+}
+
+static void
+mpbios_dflt_conf_bus(device_t self, const struct dflt_conf_entry *dflt_conf)
 {
-       struct mpbios_proc pe;
-       /* use default addresses */
-       pe.apic_id = lapic_cpu_number();
-       pe.cpu_flags = PROCENTRY_FLAG_EN|PROCENTRY_FLAG_BP;
+       struct mpbios_bus mpb;
+       size_t i;
+
+       /* mpb.type is irrelevant for mpbios_bus(). */
+       mpb.bus_id = 0;
+       for (i = 0; i < __arraycount(dflt_conf->bus_type); i++) {
+               if (dflt_conf->bus_type[i] != NULL) {
+                       memcpy(mpb.bus_type, dflt_conf->bus_type[i], 6);
+                       mpbios_bus((u_int8_t *)&mpb, self);
+                       mpb.bus_id++;
+               }
+       }
+}
+
+static void
+mpbios_dflt_conf_ioapic(device_t self)
+{
+       struct mpbios_ioapic mpio;
+
+       /* mpio.type is irrelevant for mpbios_ioapic(). */
+       mpio.apic_id = DFLT_IOAPIC_ID;
+       /* XXX Let ioapic driver read real APIC version... */
+       mpio.apic_version = 0;
+       mpio.apic_flags = IOAPICENTRY_FLAG_EN;
+       mpio.apic_address = (uint32_t)IOAPIC_BASE_DEFAULT;
+       mpbios_ioapic((uint8_t *)&mpio, self);
+}
+
+static void
+mpbios_dflt_conf_int(device_t self, const struct dflt_conf_entry *dflt_conf,
+                     const int *dflt_bus_irq)
+{
+       struct   mpbios_int mpi;
+       size_t   i;
+       int      cur_intr;
+       uint16_t level_inv;
 
-       mpbios_cpu((uint8_t *)&pe, self);
+       cur_intr = 0;
+       /*
+        * INTIN0
+        */
+       /*
+        * 8259A INTR is connected to INTIN0 for default configs 1-6, but not
+        * for default config 7 (sec. 5.3).
+        */
+       if ((dflt_conf->flags & INTIN0_NC) == 0) {
+               /* mpi.type is irrelevant for mpbios_int(). */
+               mpi.int_type = MPS_INTTYPE_ExtINT;
+               mpi.int_flags = 0;
+               mpi.src_bus_id = 0;
+               mpi.src_bus_irq = 0;
+               mpi.dst_apic_id = DFLT_IOAPIC_ID;
+               mpi.dst_apic_int = 0;
+               mpbios_int((u_int8_t *)&mpi, MPS_MCT_IOINT,
+                          &mp_intrs[cur_intr++]);
+       }
 



Home | Main Index | Thread Index | Old Index