#include <machine/apm_bios.h>
#include <machine/pc/bios.h>
#include <machine_base/apm/apm.h>
+#include <machine/smp.h>
uint32_t acpi_reset_video = 1;
TUNABLE_INT("hw.acpi.reset_video", &acpi_reset_video);
-#ifdef APIC_IO
-static int intr_model = ACPI_INTR_APIC;
+/*
+ * -1 == unset. Use acpi_GetDefaultIntrModel()
+ */
+#ifdef SMP /* APIC-IO */
+static int intr_model = -1;
#else
static int intr_model = ACPI_INTR_PIC;
#endif
+
static struct apm_softc apm_softc;
static d_open_t apmopen;
kprintf("Warning: ACPI is disabling APM's device. You can't run both\n");
}
+/*
+ * Lazy initialize intr_model
+ */
+static int
+acpi_GetDefaultIntrModel(void)
+{
+ if (intr_model == -1) {
+#ifdef SMP /* APIC-IO */
+ if (apic_io_enable)
+ intr_model = ACPI_INTR_APIC;
+ else
+ intr_model = ACPI_INTR_PIC;
+#else
+ intr_model = ACPI_INTR_PIC;
+#endif
+ }
+ return intr_model;
+}
+
int
acpi_machdep_init(device_t dev)
{
acpi_install_wakeup_handler(sc);
- if (intr_model == ACPI_INTR_PIC)
+ if (acpi_GetDefaultIntrModel() == ACPI_INTR_PIC)
BUS_CONFIG_INTR(dev, dev, AcpiGbl_FADT.SciInterrupt,
INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW);
else
- acpi_SetIntrModel(intr_model);
+ acpi_SetIntrModel(acpi_GetDefaultIntrModel());
SYSCTL_ADD_UINT(&sc->acpi_sysctl_ctx,
SYSCTL_CHILDREN(sc->acpi_sysctl_tree), OID_AUTO,
#include "apic_ipl.h"
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
extern void APIC_INTREN(int);
extern void APIC_INTRDIS(int);
static int apic_imcr_present;
-struct machintr_abi MachIntrABI = {
+struct machintr_abi MachIntrABI_APIC = {
MACHINTR_APIC,
.intrdis = APIC_INTRDIS,
.intren = APIC_INTREN,
#ifndef _ARCH_APIC_IPL_H_
#define _ARCH_APIC_IPL_H_
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
/* IDT vector base for regular (aka. slow) and fast interrupts */
#define TPR_FAST_INTS 0x60
#include "apic_ipl.h"
#include "assym.s"
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
.text
SUPERALIGN_TEXT
APIC_IMASK_UNLOCK ; \
8: ; \
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
/*
* Fast interrupt call handlers run in the following sequence:
POP_FRAME
iret
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
MCOUNT_LABEL(bintr)
FAST_INTR(0,apic_fastintr0)
*/
temp = lapic.tpr;
temp &= ~APIC_TPR_PRIO; /* clear priority field */
-#ifndef APIC_IO
+#ifdef SMP /* APIC-IO */
+if (!apic_io_enable) {
+#endif
/*
* If we are NOT running the IO APICs, the LAPIC will only be used
* for IPIs. Set the TPR to prevent any unintentional interrupts.
*/
temp |= TPR_IPI_ONLY;
+#ifdef SMP /* APIC-IO */
+}
#endif
lapic.tpr = temp;
}
-#if defined(APIC_IO)
+#ifdef SMP /* APIC-IO */
/*
* IO APIC code,
* Inter Processor Interrupt functions.
*/
-#endif /* APIC_IO */
+#endif /* SMP APIC-IO */
/*
* Send APIC IPI 'vector' to 'destType' via 'deliveryMode'.
*/
#define CPU_TO_ID(CPU) (cpu_num_to_apic_id[CPU])
#define ID_TO_CPU(ID) (apic_id_to_logical[ID])
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
#define IO_TO_ID(IO) (io_num_to_apic_id[IO])
#define ID_TO_IO(ID) (apic_id_to_logical[ID])
#endif
bus/pci/i386/pci_bus.c optional pci
bus/pci/i386/pci_cfgreg.c optional pci
bus/pci/i386/pci_pir.c optional pci
-bus/pci/i386/mptable_pci.c optional pci smp apic_io
+bus/pci/i386/mptable_pci.c optional pci smp
platform/pc32/isa/pmtimer.c optional pmtimer acpi
# XXX drhodus
platform/pc32/isa/prof_machdep.c optional profiling-routine
LINPROCFS opt_dontuse.h #Linux compatible procfs
# i386 SMP options
-APIC_IO opt_global.h
# Change KVM size. Changes things all over the kernel.
KVA_PAGES opt_global.h
cninit_finish();
if (bootverbose) {
-#ifdef APIC_IO
- imen_dump();
-#endif /* APIC_IO */
+#ifdef SMP /* APIC-IO */
+ if (apic_io_enable)
+ imen_dump();
+#endif
/*
* Print out the BIOS's idea of the disk geometries.
#include <sys/ptrace.h>
#include <machine/sigframe.h>
+#include <sys/machintr.h>
+
#define PHYSMAP_ENTRIES 10
extern void init386(int first);
avail_end = phys_avail[pa_indx];
}
+#ifdef SMP
+int apic_io_enable = 1; /* Enabled by default */
+TUNABLE_INT("hw.apic_io_enable", &apic_io_enable);
+extern struct machintr_abi MachIntrABI_APIC;
+#endif
+
+extern struct machintr_abi MachIntrABI_ICU;
+struct machintr_abi MachIntrABI;
+
/*
* IDT VECTORS:
* 0 Divide by zero
kern_envp = (caddr_t)bootinfo.bi_envp + KERNBASE;
/*
+ * Setup MachIntrABI
+ * XXX: Where is the correct place for it?
+ */
+ MachIntrABI = MachIntrABI_ICU;
+#ifdef SMP
+ TUNABLE_INT_FETCH("hw.apic_io_enable", &apic_io_enable);
+ if (apic_io_enable)
+ MachIntrABI = MachIntrABI_APIC;
+#endif
+
+ /*
* start with one cpu. Note: with one cpu, ncpus2_shift, ncpus2_mask,
* and ncpus_fit_mask remain 0.
*/
extern struct region_descriptor r_gdt, r_idt;
int mp_naps; /* # of Applications processors */
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
static int mp_nbusses; /* # of busses */
int mp_napics; /* # of IO APICs */
-#endif
-#ifdef APIC_IO
vm_offset_t io_apic_address[NAPICID]; /* NAPICID is more than enough */
u_int32_t *io_apic_versions;
#endif
extern u_long ebda_addr;
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
struct apic_intmapinfo int_to_apicintpin[APIC_INTMAPSIZE];
#endif
* We oversize these to simplify boot-time config.
*/
int cpu_num_to_apic_id[NAPICID];
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
int io_num_to_apic_id[NAPICID];
#endif
int apic_id_to_logical[NAPICID];
static int mptable_check(vm_paddr_t);
static int mptable_search_sig(u_int32_t target, int count);
static int mptable_hyperthread_fixup(u_int, int);
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
static void mptable_pass1(struct mptable_pos *);
static void mptable_pass2(struct mptable_pos *);
static void mptable_default(int type);
static void mptable_lapic_enumerate(struct lapic_enumerator *);
static void mptable_lapic_default(void);
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
static void setup_apic_irq_mapping(void);
static int apic_int_is_bus_type(int intr, int bus_type);
#endif
kprintf(", version: 0x%08x\n", cpu_apic_versions[x]);
}
-#if defined(APIC_IO)
+if (apic_io_enable) {
for (x = 0; x < mp_napics; ++x) {
kprintf(" io%d (APIC): apic id: %2d", x, IO_TO_ID(x));
kprintf(", version: 0x%08x", io_apic_versions[x]);
kprintf(", at 0x%08lx\n", io_apic_address[x]);
}
-#else
+} else {
kprintf(" Warning: APIC I/O disabled\n");
-#endif /* APIC_IO */
+}
}
/*
static void
mp_enable(u_int boot_addr)
{
-#if defined(APIC_IO)
int apic;
u_int ux;
-#endif /* APIC_IO */
vm_paddr_t mpfps_paddr;
struct mptable_pos mpt;
mptable_imcr(&mpt);
mptable_unmap(&mpt);
}
-#if defined(APIC_IO)
+if (apic_io_enable) {
if (!mpfps_paddr)
- panic("no MP table, disable APIC_IO!\n");
+ panic("no MP table, disable APIC_IO! (set hw.apic_io_enable=0)\n");
mptable_map(&mpt, mpfps_paddr);
if (io_apic_setup(apic) < 0)
panic("IO APIC setup failure");
-#endif /* APIC_IO */
+}
/*
* These are required for SMP operation
char name[7];
} bus_type_name;
-#ifdef APIC_IO
-
static bus_type_name bus_type_table[] =
{
{CBUS, "CBUS"},
static io_int *io_apic_ints;
static int nintrs;
-#endif
-
static int processor_entry (const struct PROCENTRY *entry, int cpu);
-#ifdef APIC_IO
static int bus_entry (const struct BUSENTRY *entry, int bus);
static int io_apic_entry (const struct IOAPICENTRY *entry, int apic);
static int int_entry (const struct INTENTRY *entry, int intr);
static int lookup_bus_type (char *name);
-#endif
-
-#ifdef APIC_IO
static int
mptable_ioapic_pass1_callback(void *xarg, const void *pos, int type)
panic("mptable_iterate_entries(ioapic_pass2) failed\n");
}
-#endif /* APIC_IO */
-
/*
* Check if we should perform a hyperthreading "fix-up" to
* enumerate any logical CPU's that aren't already listed
}
}
-#ifdef APIC_IO
-
void
assign_apic_irq(int apic, int intpin, int irq)
{
/* PCI interrupt assignment is deferred */
}
-#endif
-
void
mp_set_cpuids(int cpu_id, int apic_id)
{
return 0;
}
-#ifdef APIC_IO
-
static int
bus_entry(const struct BUSENTRY *entry, int bus)
{
#undef INTAPIC
#undef INTTYPE
-#endif
-
/*
* Reprogram the MB chipset to NOT redirect an ISA INTerrupt.
*
}
-#ifdef APIC_IO
-
/*
* given a bus ID, return:
* the bus type if found
io_apic_ints[0].int_type = 3; /* vectored 8259 */
}
-#endif /* APIC_IO */
-
/*
* Map a physical memory address representing I/O into KVA. The I/O
* block is assumed not to cross a page boundary.
irq_rman.rm_start = 0;
irq_rman.rm_type = RMAN_ARRAY;
irq_rman.rm_descr = "Interrupt request lines";
-#ifdef APIC_IO
+
+#if SMP /* APIC-IO */
+if (apic_io_enable) {
irq_rman.rm_end = APIC_INTMAPSIZE - 1;
if (rman_init(&irq_rman)
|| rman_manage_region(&irq_rman,
irq_rman.rm_start, irq_rman.rm_end))
panic("nexus_probe irq_rman");
-#else
+} else {
+#endif
irq_rman.rm_end = 15;
if (rman_init(&irq_rman)
|| rman_manage_region(&irq_rman, irq_rman.rm_start, 1)
|| rman_manage_region(&irq_rman, 3, irq_rman.rm_end))
panic("nexus_probe irq_rman");
+#if SMP /* APIC-IO */
+}
#endif
-
/*
* ISA DMA on PCI systems is implemented in the ISA part of each
* PCI->ISA bridge and the channels can be duplicated if there are
nexus_config_intr(device_t dev, device_t child, int irq, enum intr_trigger trig,
enum intr_polarity pol)
{
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
+if (apic_io_enable) {
int line;
int slot = pci_get_slot(child);
int bus = pci_get_bus(child);
return line;
return PCI_INVALID_IRQ;
-#else
- return irq;
+}
#endif
+ return irq;
}
/*
#include "icu.h"
#include "icu_ipl.h"
-#ifndef APIC_IO
-
extern void ICU_INTREN(int);
extern void ICU_INTRDIS(int);
&IDTVEC(icu_fastintr14), &IDTVEC(icu_fastintr15)
};
-struct machintr_abi MachIntrABI = {
+struct machintr_abi MachIntrABI_ICU = {
MACHINTR_ICU,
.intrdis = ICU_INTRDIS,
.intren = ICU_INTREN,
write_eflags(ef);
return (error);
}
-
-#endif
* WARNING! SMP builds can use the ICU now so this code must be MP safe.
*/
-#ifndef APIC_IO
-
.data
ALIGN_DATA
outb %al,$IO_ICU2+ICU_IMR_OFFSET
ICU_IMASK_UNLOCK
ret
-
-#endif
#include "assym.s"
#include "icu_ipl.h"
-#ifndef APIC_IO
-
#define ICU_IMR_OFFSET 1 /* IO_ICU{1,2} + 1 */
#define ICU_EOI 0x20 /* XXX - define elsewhere */
.data
.text
-
-#endif
extern int64_t tsc_frequency;
extern int tsc_is_broken;
extern int wall_cmos_clock;
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
extern int apic_8254_intr;
#endif
int ext_int_setup (int, int);
void lapic_config(void);
void lapic_enumerator_register(struct lapic_enumerator *);
+extern int apic_io_enable;
#if defined(READY)
void clr_io_apic_mask24 (int, u_int32_t);
#include <machine_base/isa/intr_machdep.h>
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
/* The interrupt triggered by the 8254 (timer) chip */
int apic_8254_intr;
static void setup_8254_mixed_mode (void);
i8254_intr_initclock(struct cputimer_intr *cti, boolean_t selected)
{
int diag;
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
int apic_8254_trial;
void *clkdesc;
-#endif /* APIC_IO */
+#endif
callout_init(&sysbeepstop_ch);
}
/* Finish initializing 8253 timer 0. */
-#ifdef APIC_IO
-
+#ifdef SMP /* APIC-IO */
+if (apic_io_enable) {
apic_8254_intr = isa_apic_irq(0);
apic_8254_trial = 0;
if (apic_8254_intr >= 0 ) {
INTR_NOPOLL | INTR_MPSAFE |
INTR_NOENTROPY);
machintr_intren(apic_8254_intr);
-
-#else /* APIC_IO */
-
+} else {
+#endif
register_int(0, clkintr, NULL, "clk", NULL,
INTR_EXCL | INTR_CLOCK |
INTR_NOPOLL | INTR_MPSAFE |
INTR_NOENTROPY);
machintr_intren(ICU_IRQ0);
-
-#endif /* APIC_IO */
+#ifdef SMP /* APIC-IO */
+}
+#endif
/* Initialize RTC. */
writertc(RTC_STATUSA, rtc_statusa);
if (diag != 0)
kprintf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
+if (apic_io_enable) {
if (isa_apic_irq(8) != 8)
panic("APIC RTC != 8");
-#endif /* APIC_IO */
+}
+#endif
register_int(8, (inthand2_t *)rtcintr, NULL, "rtc", NULL,
INTR_EXCL | INTR_CLOCK | INTR_NOPOLL |
writertc(RTC_STATUSB, rtc_statusb);
}
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
+if (apic_io_enable) {
if (apic_8254_trial) {
sysclock_t base;
long lastcnt;
kprintf("APIC_IO: "
"routing 8254 via 8259 and IOAPIC #0 intpin 0\n");
}
+}
#endif
}
-#ifdef APIC_IO
+#ifdef SMP /* APIC-IO */
static void
setup_8254_mixed_mode(void)
/* XXX should be in suitable include files */
#define ICU_IMR_OFFSET 1 /* IO_ICU{1,2} + 1 */
-#ifdef APIC_IO
-/*
- * This is to accommodate "mixed-mode" programming for
- * motherboards that don't connect the 8254 to the IO APIC.
- */
-#define AUTO_EOI_1 1
-#endif
-
static void init_i8259(void);
#define NMI_PARITY (1 << 7)
outb(IO_ICU1+ICU_IMR_OFFSET, IDT_OFFSET); /* starting at this vector index */
outb(IO_ICU1+ICU_IMR_OFFSET, 1 << ICU_IRQ_SLAVE); /* slave on line 2 */
#ifdef AUTO_EOI_1
- outb(IO_ICU1+ICU_IMR_OFFSET, 2 | 1); /* auto EOI, 8086 mode */
+ int auto_eoi = 2; /* auto EOI, 8086 mode */
#else
- outb(IO_ICU1+ICU_IMR_OFFSET, 1); /* 8086 mode */
+ int auto_eoi = 0; /* 8086 mode */
#endif
+#ifdef SMP
+ if (apic_io_enable)
+ auto_eoi = 2; /* auto EOI, 8086 mode */
+#endif
+ outb(IO_ICU1+ICU_IMR_OFFSET, auto_eoi | 1);
+
outb(IO_ICU1+ICU_IMR_OFFSET, 0xff); /* leave interrupts masked */
outb(IO_ICU1, 0x0a); /* default to IRR on read */
outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */