Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Sep 2003 19:42:23 -0700 (PDT)
From:      Peter Wemm <peter@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 38458 for review
Message-ID:  <200309230242.h8N2gNaI076263@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=38458

Change 38458 by peter@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,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200309230242.h8N2gNaI076263>