PERFORCE change 38458 for review
Peter Wemm
peter at FreeBSD.org
Mon Sep 22 19:42:27 PDT 2003
http://perforce.freebsd.org/chv.cgi?CH=38458
Change 38458 by peter at peter_daintree on 2003/09/22 19:42:20
p4 integ -I to pick up jhb's latest changes
Affected files ...
.. //depot/projects/hammer/sys/amd64/amd64/io_apic.c#4 integrate
.. //depot/projects/hammer/sys/amd64/amd64/local_apic.c#2 integrate
.. //depot/projects/hammer/sys/amd64/include/apicvar.h#3 integrate
.. //depot/projects/hammer/sys/amd64/include/intr_machdep.h#2 integrate
.. //depot/projects/hammer/sys/amd64/isa/atpic.c#3 integrate
.. //depot/projects/hammer/sys/jhb_notes#2 integrate
Differences ...
==== //depot/projects/hammer/sys/amd64/amd64/io_apic.c#4 (text+ko) ====
@@ -29,6 +29,8 @@
* $FreeBSD$
*/
+#include "opt_isa.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
@@ -55,6 +57,10 @@
#endif
#include <machine/segments.h>
+#ifdef DEV_ISA
+#define MIXED_MODE
+#endif
+
#define IOAPIC_ISA_INTS 16
#define IOAPIC_MEM_REGION 32
#define IOAPIC_REDTBL_LO(i) (IOAPIC_REDTBL + (i) * 2)
@@ -65,6 +71,10 @@
#define VECTOR_SMI -3
#define VECTOR_DISABLED -4
+#define DEST_NONE -1
+#define DEST_EXTINT -2
+#define DEST_EXTINT_ENABLED -3
+
#define TODO printf("%s: not implemented!\n", __func__)
MALLOC_DEFINE(M_IOAPIC, "I/O APIC", "I/O APIC structures");
@@ -112,17 +122,21 @@
static void ioapic_write(volatile ioapic_t *apic, int reg, u_int val);
static void ioapic_enable_source(struct intsrc *isrc);
static void ioapic_disable_source(struct intsrc *isrc);
+static void ioapic_eoi_source(struct intsrc *isrc);
static void ioapic_enable_intr(struct intsrc *isrc);
static int ioapic_vector(struct intsrc *isrc);
static int ioapic_source_pending(struct intsrc *isrc);
static void ioapic_suspend(struct intsrc *isrc);
static void ioapic_resume(struct intsrc *isrc);
static void ioapic_program_destination(struct ioapic_intsrc *intpin);
+#ifdef MIXED_MODE
+static struct intsrc *mixedpic_create_source(struct ioapic_intsrc *intpin);
+#endif
struct pic ioapic_template = { ioapic_enable_source, ioapic_disable_source,
- ioapic_enable_intr, ioapic_vector,
- ioapic_source_pending, ioapic_suspend,
- ioapic_resume };
+ ioapic_eoi_source, ioapic_enable_intr,
+ ioapic_vector, ioapic_source_pending,
+ ioapic_suspend, ioapic_resume };
static int next_ioapic_base, logical_clusters, current_cluster;
@@ -182,6 +196,13 @@
mtx_unlock_spin(&icu_lock);
}
+static void
+ioapic_eoi_source(struct intsrc *isrc)
+{
+ TODO;
+ /* lapic_eoi(); */
+}
+
/*
* Program an individual intpin's logical destination.
*/
@@ -191,10 +212,18 @@
struct ioapic *io = (struct ioapic *)intpin->io_intsrc.is_pic;
uint32_t value;
- KASSERT(intpin->io_dest != -1, ("intpin not assigned to a cluster"));
+ KASSERT(intpin->io_dest != DEST_NONE,
+ ("intpin not assigned to a cluster"));
+ KASSERT(intpin->io_dest != DEST_EXTINT &&
+ intpin->io_dest != DEST_EXTINT_ENABLED,
+ ("intpin routed via ExtINT"));
/* XXXTEST */
- printf("ioapic%u: routing intpin %u (IRQ %u) to cluster %u\n",
- io->io_id, intpin->io_intpin, intpin->io_vector, intpin->io_dest);
+ printf("ioapic%u: routing intpin %u (", io->io_id, intpin->io_intpin);
+ if (intpin->io_vector == VECTOR_EXTINT)
+ printf("ExtINT");
+ else
+ printf("IRQ %u", intpin->io_vector);
+ printf(") to cluster %u\n", intpin->io_dest);
mtx_lock_spin(&icu_lock);
value = ioapic_read(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin));
value &= ~IOART_DESTMOD;
@@ -209,18 +238,8 @@
}
static void
-ioapic_enable_intr(struct intsrc *isrc)
+ioapic_assign_cluster(struct ioapic_intsrc *intpin)
{
- struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc;
-
- if (intpin->io_vector == IDT_SYSCALL - NRSVIDT) {
- printf("WARNING: IRQ %d is not routed!\n",
- IDT_SYSCALL - NRSVIDT);
- return;
- }
- if (intpin->io_dest != -1)
- return;
-
/*
* Assign this intpin to a logical APIC cluster in a
* round-robin fashion. We don't actually use the logical
@@ -236,6 +255,38 @@
current_cluster = 0;
if (program_logical_dest)
ioapic_program_destination(intpin);
+}
+
+static void
+ioapic_enable_intr(struct intsrc *isrc)
+{
+ struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc;
+ struct ioapic_intsrc *extint;
+ struct ioapic *io;
+
+ if (intpin->io_vector == IDT_TO_IRQ(IDT_SYSCALL)) {
+ printf("WARNING: IRQ %d is not routed!\n",
+ IDT_TO_IRQ(IDT_SYSCALL));
+ return;
+ }
+ switch (intpin->io_dest) {
+ case DEST_NONE:
+ ioapic_assign_cluster(intpin);
+ break;
+ case DEST_EXTINT:
+ io = (struct ioapic *)isrc->is_pic;
+ extint = &io->io_pins[0];
+ if (extint->io_vector != VECTOR_EXTINT)
+ panic("Can't find ExtINT pin to route through!");
+ if (extint->io_dest == DEST_NONE) {
+ ioapic_assign_cluster(extint);
+ ioapic_enable_source(&extint->io_intsrc);
+ }
+ intpin->io_dest = DEST_EXTINT_ENABLED;
+ break;
+ default:
+ return;
+ }
lapic_enable_intr(intpin->io_vector);
}
@@ -527,6 +578,7 @@
void
ioapic_register(void *cookie)
{
+ struct ioapic_intsrc *pin;
struct ioapic *io;
volatile ioapic_t *apic;
uint32_t flags;
@@ -540,43 +592,43 @@
mtx_unlock_spin(&icu_lock);
printf("ioapic%u <Version %u> irqs %u-%u on motherboard\n", io->io_id,
flags, io->io_intbase, io->io_intbase + io->io_numintr - 1);
- for (i = 0; i < io->io_numintr; i++) {
+ for (i = 0, pin = io->io_pins; i < io->io_numintr; i++, pin++) {
/*
* Finish initializing the pins by programming the vectors
* and delivery mode. XXX this may not be all right yet
*/
- if (io->io_pins[i].io_vector == VECTOR_DISABLED)
+ if (pin->io_vector == VECTOR_DISABLED)
continue;
flags = IOART_DESTPHY;
- if (io->io_pins[i].io_edgetrigger)
+ if (pin->io_edgetrigger)
flags |= IOART_TRGREDG;
else
flags |= IOART_TRGRLVL;
- if (io->io_pins[i].io_activehi)
+ if (pin->io_activehi)
flags |= IOART_INTAHI;
else
flags |= IOART_INTALO;
- if (io->io_pins[i].io_masked)
+ if (pin->io_masked)
flags |= IOART_INTMSET;
- switch (io->io_pins[i].io_vector) {
+ switch (pin->io_vector) {
case VECTOR_EXTINT:
- KASSERT(io->io_pins[i].io_edgetrigger,
+ KASSERT(pin->io_edgetrigger,
("EXTINT not edge triggered"));
flags |= IOART_DELEXINT;
break;
case VECTOR_NMI:
- KASSERT(io->io_pins[i].io_edgetrigger,
+ KASSERT(pin->io_edgetrigger,
("NMI not edge triggered"));
flags |= IOART_DELNMI;
break;
case VECTOR_SMI:
- KASSERT(io->io_pins[i].io_edgetrigger,
+ KASSERT(pin->io_edgetrigger,
("SMI not edge triggered"));
flags |= IOART_DELSMI;
break;
default:
flags |= IOART_DELLOPRI |
- (io->io_pins[i].io_vector + NRSVIDT);
+ IRQ_TO_IDT(pin->io_vector);
}
mtx_lock_spin(&icu_lock);
ioapic_write(apic, IOAPIC_REDTBL_LO(i), flags);
@@ -591,8 +643,17 @@
flags |= IOART_DEST;
ioapic_write(apic, IOAPIC_REDTBL_HI(i), flags);
mtx_unlock_spin(&icu_lock);
- if (io->io_pins[i].io_vector >= 0)
- intr_register_source(&io->io_pins[i].io_intsrc);
+ if (pin->io_vector >= 0) {
+ struct intsrc *isrc;
+#ifdef MIXED_MODE
+ /* Route IRQ0 via the 8259A using mixed mode. */
+ if (pin->io_vector == 0)
+ isrc = mixedpic_create_source(pin);
+ else
+#endif
+ isrc = &pin->io_intsrc;
+ intr_register_source(isrc);
+ }
}
}
@@ -609,24 +670,13 @@
program_logical_dest = 1;
STAILQ_FOREACH(io, &ioapic_list, io_next)
for (i = 0; i < io->io_numintr; i++)
- if (io->io_pins[i].io_dest != -1)
+ if (io->io_pins[i].io_dest != DEST_NONE)
ioapic_program_destination(&io->io_pins[i]);
}
SYSINIT(ioapic_destinations, SI_SUB_SMP, SI_ORDER_SECOND,
ioapic_set_logical_destinations, NULL)
-
-#ifdef MIXED_MODE_notyet
-/*
- * Hmm, so we have the problem that we may need to EOI both the local APIC
- * and the 8259's in mixed mode. Also, the mapping of vectors to intpins
- * is more cmplicated with IO APICs, so perhaps instead we should add another
- * PIC-independent layer for the actual low-level interrupt code to register
- * handlers in IDT and then use intsrc pointers to handle EOI and
- * block/unblock. Not too happy about adding extra overhead to the critical
- * path however. Maybe I can talk about this with Peter this week. Bah.
- */
-#endif
+#ifdef MIXED_MODE
/*
* Support for mixed-mode interrupt sources. These sources route an ISA
* IRQ through the 8259A's via the ExtINT on pin 0 of the I/O APIC that
@@ -642,17 +692,17 @@
static void mixedpic_enable_source(struct intsrc *isrc);
static void mixedpic_disable_source(struct intsrc *isrc);
+static void mixedpic_eoi_source(struct intsrc *isrc);
static void mixedpic_enable_intr(struct intsrc *isrc);
static int mixedpic_vector(struct intsrc *isrc);
static int mixedpic_source_pending(struct intsrc *isrc);
static void mixedpic_suspend(struct intsrc *isrc);
static void mixedpic_resume(struct intsrc *isrc);
-static struct intsrc *mixedpic_create_source(struct ioapic_intsrc *intpin);
struct pic mixedpic = { mixedpic_enable_source, mixedpic_disable_source,
- mixedpic_enable_intr, mixedpic_vector,
- mixedpic_source_pending, mixedpic_suspend,
- mixedpic_resume };
+ mixedpic_eoi_source, mixedpic_enable_intr,
+ mixedpic_vector, mixedpic_source_pending,
+ mixedpic_suspend, mixedpic_resume };
static void
mixedpic_enable_source(struct intsrc *isrc)
@@ -668,16 +718,43 @@
mixedpic_disable_source(struct intsrc *isrc)
{
struct mixedpic_intsrc *mpsrc;
+ struct intsrc *intpin;
mpsrc = (struct mixedpic_intsrc *)isrc;
+ intpin = mpsrc->mp_apicpin;
isrc = mpsrc->mp_atpicsrc;
isrc->is_pic->pic_disable_source(isrc);
+
+ /*
+ * If the interrupt is pending in the local APIC, assume that
+ * we have been called just before the local APIC gets its
+ * EOI and send an EOI out to the 8259As.
+ */
+ if (intpin->is_pic->pic_source_pending(intpin))
+ isrc->is_pic->pic_eoi_source(isrc);
+}
+
+static void
+mixedpic_eoi_source(struct intsrc *isrc)
+{
+ struct mixedpic_intsrc *mpsrc;
+ struct intsrc *intpin;
+
+ mpsrc = (struct mixedpic_intsrc *)isrc;
+ intpin = mpsrc->mp_apicpin;
+ isrc = mpsrc->mp_atpicsrc;
+ isrc->is_pic->pic_eoi_source(isrc);
+ intpin->is_pic->pic_eoi_source(intpin);
}
static void
mixedpic_enable_intr(struct intsrc *isrc)
{
- /* here be dragons */
+ struct mixedpic_intsrc *mpsrc;
+
+ mpsrc = (struct mixedpic_intsrc *)isrc;
+ isrc = mpsrc->mp_apicpin;
+ isrc->is_pic->pic_enable_intr(isrc);
}
static int
@@ -720,10 +797,15 @@
struct mixedpic_intsrc *mpsrc;
int vector;
+ KASSERT(intpin->io_dest == DEST_NONE, ("%s: intpin already enabled",
+ __func__));
mpsrc = malloc(sizeof(struct mixedpic_intsrc), M_IOAPIC, M_WAITOK);
mpsrc->mp_intsrc.is_pic = &mixedpic;
mpsrc->mp_apicpin = (struct intsrc *)intpin;
vector = intpin->io_intsrc.is_pic->pic_vector(&intpin->io_intsrc);
mpsrc->mp_atpicsrc = atpic_lookup_source(vector);
+ intpin->io_dest = DEST_EXTINT; /* XXX */
return (&mpsrc->mp_intsrc);
}
+
+#endif /* MIXED_MODE */
==== //depot/projects/hammer/sys/amd64/amd64/local_apic.c#2 (text+ko) ====
@@ -241,10 +241,10 @@
{
/* Convert to IDT vector. */
- vector += NRSVIDT;
- KASSERT(vector != 0x80, ("Attempt to overwrite syscall entry"));
+ vector = IRQ_TO_IDT(vector);
+ KASSERT(vector != IDT_SYSCALL, ("Attempt to overwrite syscall entry"));
KASSERT(ioint_handlers[vector / 32] != NULL,
- ("No ISR handler for IRQ %d", vector - NRSVIDT));
+ ("No ISR handler for IRQ %d", IDT_TO_IRQ(vector)));
setidt(vector, ioint_handlers[vector / 32], SDT_SYS386IGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
}
==== //depot/projects/hammer/sys/amd64/include/apicvar.h#3 (text+ko) ====
@@ -82,7 +82,7 @@
#define APIC_ID_ALL 0xff
#define APIC_NUM_IOINTS 160
-#define APIC_LOCAL_INTS (NRSVIDT + APIC_NUM_IOINTS)
+#define APIC_LOCAL_INTS (IDT_IO_INTS + APIC_NUM_IOINTS)
#define APIC_TIMER_INT APIC_LOCAL_INTS
#define APIC_ERROR_INT (APIC_LOCAL_INTS + 1)
#define APIC_THERMAL_INT (APIC_LOCAL_INTS + 2)
==== //depot/projects/hammer/sys/amd64/include/intr_machdep.h#2 (text+ko) ====
@@ -51,6 +51,7 @@
struct pic {
void (*pic_enable_source)(struct intsrc *);
void (*pic_disable_source)(struct intsrc *);
+ void (*pic_eoi_source)(struct intsrc *);
void (*pic_enable_intr)(struct intsrc *);
int (*pic_vector)(struct intsrc *);
int (*pic_source_pending)(struct intsrc *);
@@ -77,7 +78,7 @@
extern struct mtx icu_lock;
void atpic_startup(void);
-void atpic_lookup_source(int vector);
+struct intsrc *atpic_lookup_source(int vector);
int intr_add_handler(const char *name, int vector, driver_intr_t handler,
void *arg, enum intr_type flags, void **cookiep);
==== //depot/projects/hammer/sys/amd64/isa/atpic.c#3 (text+ko) ====
@@ -54,6 +54,10 @@
#ifdef DEV_ISA
#include <isa/isavar.h>
+
+#define MASTER 0
+#define SLAVE 1
+
#endif
static void atpic_init(void *dummy);
@@ -80,10 +84,10 @@
#define IRQ(ap, ai) ((ap)->at_irqbase + (ai)->at_irq)
-#define ATPIC(io, base, intbase, imenptr) \
- { { atpic_enable_source, atpic_disable_source, atpic_enable_intr, \
- atpic_vector, atpic_source_pending, NULL, atpic_resume }, \
- (io), (base), (intbase), (imenptr) }
+#define ATPIC(io, base, eoi, imenptr) \
+ { { atpic_enable_source, atpic_disable_source, (eoi), \
+ atpic_enable_intr, atpic_vector, atpic_source_pending, NULL, \
+ atpic_resume }, (io), (base), IRQ_TO_IDT(base), (imenptr) }
#define INTSRC(irq) \
{ { (struct pic *)(&atpics[(irq) / 8]) }, (irq) % 8, \
@@ -113,6 +117,8 @@
static void atpic_enable_source(struct intsrc *isrc);
static void atpic_disable_source(struct intsrc *isrc);
+static void atpic_eoi_master(struct intsrc *isrc);
+static void atpic_eoi_slave(struct intsrc *isrc);
static void atpic_enable_intr(struct intsrc *isrc);
static int atpic_vector(struct intsrc *isrc);
static void atpic_resume(struct intsrc *isrc);
@@ -120,8 +126,8 @@
static void i8259_init(struct atpic *pic, int slave);
static struct atpic atpics[] = {
- ATPIC(IO_ICU1, 0, NRSVIDT, (uint8_t *)&imen),
- ATPIC(IO_ICU2, 8, NRSVIDT+8, ((uint8_t *)&imen) + 1)
+ ATPIC(IO_ICU1, 0, atpic_eoi_master, (uint8_t *)&imen),
+ ATPIC(IO_ICU2, 8, atpic_eoi_slave, ((uint8_t *)&imen) + 1)
};
static struct atpic_intsrc atintrs[] = {
@@ -168,6 +174,35 @@
}
static void
+atpic_eoi_master(struct intsrc *isrc)
+{
+
+ KASSERT(isrc->is_pic == &atpics[MASTER].at_pic,
+ ("%s: mismatched pic", __func__));
+#ifndef AUTO_EOI_1
+ mtx_lock_spin(&icu_lock);
+ outb(atpics[MASTER].at_ioaddr, ICU_EOI);
+ mtx_unlock_spin(&icu_lock);
+#endif
+}
+
+static void
+atpic_eoi_slave(struct intsrc *isrc)
+{
+
+ KASSERT(isrc->is_pic == &atpics[SLAVE].at_pic,
+ ("%s: mismatched pic", __func__));
+#ifndef AUTO_EOI_2
+ mtx_lock_spin(&icu_lock);
+ outb(atpics[SLAVE].at_ioaddr, ICU_EOI);
+#ifndef AUTO_EOI_1
+ outb(atpics[MASTER].at_ioaddr, ICU_EOI);
+#endif
+ mtx_unlock_spin(&icu_lock);
+#endif
+}
+
+static void
atpic_enable_intr(struct intsrc *isrc)
{
struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
@@ -223,7 +258,7 @@
struct atpic *ap = (struct atpic *)isrc->is_pic;
if (ai->at_irq == 0)
- i8259_init(ap, !(ap == &atpics[0]));
+ i8259_init(ap, ap == &atpics[SLAVE]);
}
static void
@@ -283,8 +318,8 @@
/* Start off with all interrupts disabled. */
imen = 0xffff;
- i8259_init(&atpics[0], 0);
- i8259_init(&atpics[1], 1);
+ i8259_init(&atpics[MASTER], 0);
+ i8259_init(&atpics[SLAVE], 1);
atpic_enable_source((struct intsrc *)&atintrs[ICU_SLAVEID]);
}
@@ -317,14 +352,14 @@
intr_execute_handlers(&atintrs[iframe.if_vec].at_intsrc, &iframe);
}
-void
+struct intsrc *
atpic_lookup_source(int vector)
{
KASSERT(vector >= 0 && vector != ICU_SLAVEID &&
vector < sizeof(atintrs) / sizeof(struct atpic_intsrc),
("%s: invalid vector %d", __func__, vector));
- return (&atintrs[vector]);
+ return (&atintrs[vector].at_intsrc);
}
/*
==== //depot/projects/hammer/sys/jhb_notes#2 (text+ko) ====
@@ -27,13 +27,10 @@
- isa/vector.s
Todo:
-- Add ICU locking
- - atpic low-level asm still dinks with pic w/o lock - XXX (should be ok)
+- Fix IDT_SYSCALL mapping in APIC case
+- Test mixed mode
- Kill isa_irq_pending() (maybe, is this an MI function?)
-- Use mixed-mode by default for rtc and clk or add back in a runtime test.
- Add ACPI MADT APIC enumerator.
- + UP works
- + SMP works
- solve ACPI module problem where madt wants APIC symbols :(
- Implement mixed-mode and use it for IRQ0 unless no ExtINT pin or
NO_MIXED_MODE
@@ -51,8 +48,8 @@
- Suspend/resume support for I/O APICs
- check XXX and XXXTEST in new code
- reimplement lazy masking of interrupts for critical sections w/o bitmasks??
-- Revisit cpu_add, make call #ifdef SMP?
- Enhance acpi_cpu(4) driver to grok SMP at all?
+- Rip out CPU halting stuff perhaps and maybe disable MPTable HTT fixup?
Unrelated to this branch:
- Work on cleaning up nested includes in sys/* headers. According to Bruce,
More information about the p4-projects
mailing list