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