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>