diff options
Diffstat (limited to 'sys/arch/i386')
-rw-r--r-- | sys/arch/i386/i386/apic.c | 3 | ||||
-rw-r--r-- | sys/arch/i386/i386/ioapic.c | 162 | ||||
-rw-r--r-- | sys/arch/i386/i386/mpbios.c | 6 | ||||
-rw-r--r-- | sys/arch/i386/i386/mpbios_intr_fixup.c | 4 | ||||
-rw-r--r-- | sys/arch/i386/include/cpufunc.h | 5 | ||||
-rw-r--r-- | sys/arch/i386/include/i82093var.h | 4 | ||||
-rw-r--r-- | sys/arch/i386/include/intr.h | 4 | ||||
-rw-r--r-- | sys/arch/i386/include/pic.h | 43 |
8 files changed, 173 insertions, 58 deletions
diff --git a/sys/arch/i386/i386/apic.c b/sys/arch/i386/i386/apic.c index 8aaee1613da..a0ae3e9754b 100644 --- a/sys/arch/i386/i386/apic.c +++ b/sys/arch/i386/i386/apic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: apic.c,v 1.5 2008/06/26 05:42:10 ray Exp $ */ +/* $OpenBSD: apic.c,v 1.6 2009/08/13 13:24:48 kettenis Exp $ */ /* $NetBSD: apic.c,v 1.1.2.2 2000/02/21 18:51:00 sommerfeld Exp $ */ /*- @@ -50,4 +50,3 @@ apic_format_redir(char *where1, char *where2, int idx, u_int32_t redirhi, printf("\n"); } - diff --git a/sys/arch/i386/i386/ioapic.c b/sys/arch/i386/i386/ioapic.c index cea19a78fcb..60b08698845 100644 --- a/sys/arch/i386/i386/ioapic.c +++ b/sys/arch/i386/i386/ioapic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ioapic.c,v 1.20 2009/01/09 18:53:16 kettenis Exp $ */ +/* $OpenBSD: ioapic.c,v 1.21 2009/08/13 13:24:48 kettenis Exp $ */ /* $NetBSD: ioapic.c,v 1.7 2003/07/14 22:32:40 lukem Exp $ */ /*- @@ -64,6 +64,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ + #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> @@ -97,6 +98,8 @@ void ioapic_attach(struct device *, struct device *, void *); extern int bus_mem_add_mapping(bus_addr_t, bus_size_t, int, bus_space_handle_t *); +void ioapic_hwmask(struct pic *, int); +void ioapic_hwunmask(struct pic *, int); void apic_set_redir(struct ioapic_softc *, int); void apic_vectorset(struct ioapic_softc *, int, int, int); @@ -113,34 +116,71 @@ static int ioapic_vecbase; void ioapic_set_id(struct ioapic_softc *); +static __inline u_long +ioapic_lock(struct ioapic_softc *sc) +{ + u_long flags; + + flags = read_psl(); + disable_intr(); +#ifdef MULTIPROCESSOR + mtx_enter(&sc->sc_pic.pic_mutex); +#endif + return flags; +} + +static __inline void +ioapic_unlock(struct ioapic_softc *sc, u_long flags) +{ +#ifdef MULTIPROCESSOR + mtx_leave(&sc->sc_pic.pic_mutex); +#endif + write_psl(flags); +} + /* * Register read/write routines. */ static __inline u_int32_t -ioapic_read(struct ioapic_softc *sc, int regid) +ioapic_read_ul(struct ioapic_softc *sc,int regid) { u_int32_t val; - - /* - * XXX lock apic - */ + *(sc->sc_reg) = regid; val = *sc->sc_data; return (val); - } static __inline void -ioapic_write(struct ioapic_softc *sc, int regid, int val) +ioapic_write_ul(struct ioapic_softc *sc,int regid, u_int32_t val) { - /* - * XXX lock apic - */ *(sc->sc_reg) = regid; *(sc->sc_data) = val; } +static __inline u_int32_t +ioapic_read(struct ioapic_softc *sc, int regid) +{ + u_int32_t val; + u_long flags; + + flags = ioapic_lock(sc); + val = ioapic_read_ul(sc, regid); + ioapic_unlock(sc, flags); + return val; +} + +static __inline void +ioapic_write(struct ioapic_softc *sc,int regid, int val) +{ + u_long flags; + + flags = ioapic_lock(sc); + ioapic_write_ul(sc, regid, val); + ioapic_unlock(sc, flags); +} + struct ioapic_softc * ioapic_find(int apicid) { @@ -195,7 +235,7 @@ ioapic_print_redir(struct ioapic_softc *sc, char *why, int pin) u_int32_t redirlo = ioapic_read(sc, IOAPIC_REDLO(pin)); u_int32_t redirhi = ioapic_read(sc, IOAPIC_REDHI(pin)); - apic_format_redir(sc->sc_dev.dv_xname, why, pin, redirhi, redirlo); + apic_format_redir(sc->sc_pic.pic_name, why, pin, redirhi, redirlo); } struct cfattach ioapic_ca = { @@ -203,14 +243,14 @@ struct cfattach ioapic_ca = { }; struct cfdriver ioapic_cd = { - NULL, "ioapic", DV_DULL /* XXX DV_CPU ? */ + NULL, "ioapic", DV_DULL }; int -ioapic_match(struct device *parent, void *matchv, void *aux) +ioapic_match(struct device *parent, void *v, void *aux) { - struct cfdata *match = (struct cfdata *)matchv; - struct apic_attach_args * aaa = (struct apic_attach_args *)aux; + struct apic_attach_args *aaa = (struct apic_attach_args *)aux; + struct cfdata *match = v; if (strcmp(aaa->aaa_name, match->cf_driver->cd_name) == 0) return (1); @@ -305,7 +345,7 @@ ioapic_attach(struct device *parent, struct device *self, void *aux) sc->sc_pins[i].ip_vector = 0; sc->sc_pins[i].ip_type = 0; sc->sc_pins[i].ip_minlevel = 0xff; /* XXX magic*/ - sc->sc_pins[i].ip_maxlevel = 0; /* XXX magic */ + sc->sc_pins[i].ip_maxlevel = 0; /* XXX magic */ } /* @@ -313,8 +353,8 @@ ioapic_attach(struct device *parent, struct device *self, void *aux) * do it now. */ if (apic_id != sc->sc_apicid) { - printf("%s: misconfigured as apic %d", sc->sc_dev.dv_xname, - apic_id); + printf("%s: misconfigured as apic %d", + sc->sc_pic.pic_name, apic_id); ioapic_set_id(sc); } #if 0 @@ -446,7 +486,7 @@ apic_vectorset(struct ioapic_softc *sc, int pin, int minlevel, int maxlevel) #ifdef MPVERBOSE if (minlevel != maxlevel) printf("%s: pin %d shares different IPL interrupts " - "(%x..%x)\n", sc->sc_dev.dv_xname, pin, + "(%x..%x)\n", sc->sc_pic.pic_name, pin, minlevel, maxlevel); #endif @@ -465,7 +505,7 @@ apic_vectorset(struct ioapic_softc *sc, int pin, int minlevel, int maxlevel) * and install a slightly different handler. */ panic("%s: can't alloc vector for pin %d at level %x", - sc->sc_dev.dv_xname, pin, maxlevel); + sc->sc_pic.pic_name, pin, maxlevel); } idt_vec_set(nvector, apichandler[nvector & 0xf]); @@ -524,7 +564,7 @@ ioapic_enable(void) if (ioapics->sc_flags & IOAPIC_PICMODE) { printf("%s: writing to IMCR to disable pics\n", - ioapics->sc_dev.dv_xname); + ioapics->sc_pic.pic_name); outb(IMCR_ADDR, IMCR_REGISTER); outb(IMCR_DATA, IMCR_APIC); } @@ -535,7 +575,7 @@ ioapic_enable(void) for (sc = ioapics; sc != NULL; sc = sc->sc_next) { if (mp_verbose) - printf("%s: enabling\n", sc->sc_dev.dv_xname); + printf("%s: enabling\n", sc->sc_pic.pic_name); for (p = 0; p < sc->sc_apic_sz; p++) { maxlevel = 0; /* magic */ @@ -553,6 +593,38 @@ ioapic_enable(void) } } +void +ioapic_hwmask(struct pic *pic, int pin) +{ + u_int32_t redlo; + struct ioapic_softc *sc = (struct ioapic_softc *)pic; + u_long flags; + + if (ioapic_cold) + return; + flags = ioapic_lock(sc); + redlo = ioapic_read_ul(sc, IOAPIC_REDLO(pin)); + redlo |= IOAPIC_REDLO_MASK; + ioapic_write_ul(sc, IOAPIC_REDLO(pin), redlo); + ioapic_unlock(sc, flags); +} + +void +ioapic_hwunmask(struct pic *pic, int pin) +{ + u_int32_t redlo; + struct ioapic_softc *sc = (struct ioapic_softc *)pic; + u_long flags; + + if (ioapic_cold) + return; + flags = ioapic_lock(sc); + redlo = ioapic_read_ul(sc, IOAPIC_REDLO(pin)); + redlo &= ~IOAPIC_REDLO_MASK; + ioapic_write_ul(sc, IOAPIC_REDLO(pin), redlo); + ioapic_unlock(sc, flags); +} + /* * Interrupt handler management with the apic is radically different from the * good old 8259. @@ -582,9 +654,9 @@ apic_intr_establish(int irq, int type, int level, int (*ih_fun)(void *), struct ioapic_softc *sc = ioapic_find(ioapic); struct ioapic_pin *pin; struct intrhand **p, *q, *ih; - static struct intrhand fakehand = {fakeintr}; extern int cold; int minlevel, maxlevel; + extern void intr_calculatemasks(void); /* XXX */ if (sc == NULL) panic("apic_intr_establish: unknown ioapic %d", ioapic); @@ -620,6 +692,9 @@ apic_intr_establish(int irq, int type, int level, int (*ih_fun)(void *), break; } + if (!cold) + ioapic_hwmask(&sc->sc_pic, intr); + /* * Figure out where to put the handler. * This is O(N^2) to establish N interrupts, but we want to @@ -634,13 +709,17 @@ apic_intr_establish(int irq, int type, int level, int (*ih_fun)(void *), minlevel = q->ih_level; } - /* - * Actually install a fake handler momentarily, since we might be doing - * this with interrupts enabled and don't want the real routine called - * until masking is set up. - */ - fakehand.ih_level = level; - *p = &fakehand; + ih->ih_fun = ih_fun; + ih->ih_arg = ih_arg; + ih->ih_next = NULL; + ih->ih_level = level; + ih->ih_irq = irq; + evcount_attach(&ih->ih_count, ih_what, (void *)&pin->ip_vector, + &evcount_intr); + + *p = ih; + + intr_calculatemasks(); /* * Fix up the vector for this pin. @@ -651,21 +730,8 @@ apic_intr_establish(int irq, int type, int level, int (*ih_fun)(void *), if (!ioapic_cold) apic_vectorset(sc, intr, minlevel, maxlevel); -#if 0 - apic_calculatemasks(); -#endif - - /* - * Poke the real handler in now. - */ - ih->ih_fun = ih_fun; - ih->ih_arg = ih_arg; - ih->ih_next = NULL; - ih->ih_level = level; - ih->ih_irq = irq; - evcount_attach(&ih->ih_count, ih_what, (void *)&pin->ip_vector, - &evcount_intr); - *p = ih; + if (!cold) + ioapic_hwunmask(&sc->sc_pic, intr); return (ih); } @@ -697,6 +763,7 @@ apic_intr_disestablish(void *arg) struct ioapic_pin *pin = &sc->sc_pins[intr]; struct intrhand **p, *q; int minlevel, maxlevel; + extern void intr_calculatemasks(void); /* XXX */ if (sc == NULL) panic("apic_intr_disestablish: unknown ioapic %d", ioapic); @@ -729,6 +796,7 @@ apic_intr_disestablish(void *arg) minlevel = q->ih_level; } + intr_calculatemasks(); if (!ioapic_cold) apic_vectorset(sc, intr, minlevel, maxlevel); @@ -745,7 +813,7 @@ apic_stray(int irqnum) { sc = ioapic_find(apicid); if (sc == NULL) return; - printf("%s: stray interrupt %d\n", sc->sc_dev.dv_xname, irqnum); + printf("%s: stray interrupt %d\n", sc->sc_pic.pic_name, irqnum); } #ifdef DDB diff --git a/sys/arch/i386/i386/mpbios.c b/sys/arch/i386/i386/mpbios.c index 0367c66de2c..b1e3d10d5a8 100644 --- a/sys/arch/i386/i386/mpbios.c +++ b/sys/arch/i386/i386/mpbios.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpbios.c,v 1.32 2009/04/19 18:02:57 deraadt Exp $ */ +/* $OpenBSD: mpbios.c,v 1.33 2009/08/13 13:24:48 kettenis Exp $ */ /* $NetBSD: mpbios.c,v 1.2 2002/10/01 12:56:57 fvdl Exp $ */ /*- @@ -1140,7 +1140,7 @@ mpbios_int(const u_int8_t *ent, struct mp_intr_map *mpi) (altmpi->flags != flags)) { printf( "%s: conflicting map entries for pin %d\n", - sc->sc_dev.dv_xname, pin); + sc->sc_pic.pic_dev.dv_xname, pin); } } else { sc->sc_pins[pin].ip_map = mpi; @@ -1157,7 +1157,7 @@ mpbios_int(const u_int8_t *ent, struct mp_intr_map *mpi) if (mp_verbose) { printf("%s: int%d attached to %s", - sc ? sc->sc_dev.dv_xname : "local apic", pin, + sc ? sc->sc_pic.pic_dev.dv_xname : "local apic", pin, mpb->mb_name); if (mpb->mb_idx != -1) printf("%d", mpb->mb_idx); diff --git a/sys/arch/i386/i386/mpbios_intr_fixup.c b/sys/arch/i386/i386/mpbios_intr_fixup.c index f5d4a5a6663..cb8341a6f99 100644 --- a/sys/arch/i386/i386/mpbios_intr_fixup.c +++ b/sys/arch/i386/i386/mpbios_intr_fixup.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpbios_intr_fixup.c,v 1.4 2008/09/17 16:54:32 brad Exp $ */ +/* $OpenBSD: mpbios_intr_fixup.c,v 1.5 2009/08/13 13:24:48 kettenis Exp $ */ /* * Copyright (c) 2006 Mark Kettenis @@ -156,7 +156,7 @@ mpbios_pin_fixup(int bus, int dev, int rawpin, int pin) if (mp_verbose) { printf("%s: int%d attached to %s", - mip->ioapic->sc_dev.dv_xname, + mip->ioapic->sc_pic.pic_name, pin, mpb->mb_name); if (mpb->mb_idx != -1) diff --git a/sys/arch/i386/include/cpufunc.h b/sys/arch/i386/include/cpufunc.h index 7813ce64ad6..cd66ef4dde4 100644 --- a/sys/arch/i386/include/cpufunc.h +++ b/sys/arch/i386/include/cpufunc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpufunc.h,v 1.14 2007/11/28 17:05:09 tedu Exp $ */ +/* $OpenBSD: cpufunc.h,v 1.15 2009/08/13 13:24:48 kettenis Exp $ */ /* $NetBSD: cpufunc.h,v 1.8 1994/10/27 04:15:59 cgd Exp $ */ /* @@ -269,6 +269,9 @@ breakpoint(void) __asm __volatile("int $3"); } +#define read_psl() read_eflags() +#define write_psl(x) write_eflags(x) + void amd64_errata(struct cpu_info *); #endif /* _KERNEL */ diff --git a/sys/arch/i386/include/i82093var.h b/sys/arch/i386/include/i82093var.h index 4bd7659fb95..42b2d72a39b 100644 --- a/sys/arch/i386/include/i82093var.h +++ b/sys/arch/i386/include/i82093var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: i82093var.h,v 1.7 2008/10/05 16:57:36 kettenis Exp $ */ +/* $OpenBSD: i82093var.h,v 1.8 2009/08/13 13:24:48 kettenis Exp $ */ /* $NetBSD: i82093var.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */ /*- @@ -49,7 +49,7 @@ struct ioapic_pin }; struct ioapic_softc { - struct device sc_dev; /* generic device glue */ + struct pic sc_pic; struct ioapic_softc *sc_next; int sc_apicid; int sc_apic_vers; diff --git a/sys/arch/i386/include/intr.h b/sys/arch/i386/include/intr.h index fd5f02fa4af..bfba600f8de 100644 --- a/sys/arch/i386/include/intr.h +++ b/sys/arch/i386/include/intr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.h,v 1.38 2009/04/19 17:50:18 oga Exp $ */ +/* $OpenBSD: intr.h,v 1.39 2009/08/13 13:24:48 kettenis Exp $ */ /* $NetBSD: intr.h,v 1.5 1996/05/13 06:11:28 mycroft Exp $ */ /* @@ -129,6 +129,8 @@ void splassert_check(int, const char *); #define setsoftnet() softintr(SIR_NET) #define setsofttty() softintr(SIR_TTY) +#include <machine/pic.h> + struct cpu_info; #ifdef MULTIPROCESSOR diff --git a/sys/arch/i386/include/pic.h b/sys/arch/i386/include/pic.h new file mode 100644 index 00000000000..ce95cc48e45 --- /dev/null +++ b/sys/arch/i386/include/pic.h @@ -0,0 +1,43 @@ +/* $OpenBSD: pic.h,v 1.1 2009/08/13 13:24:48 kettenis Exp $ */ +/* $NetBSD: pic.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */ + +#ifndef _X86_PIC_H +#define _X86_PIC_H + +#include <sys/device.h> +#include <sys/mutex.h> +#include <sys/lock.h> + +struct cpu_info; + +/* + * Structure common to all PIC softcs + */ +struct pic { + struct device pic_dev; + int pic_type; +#ifdef MULTIPROCESSOR + struct mutex pic_mutex; +#endif + void (*pic_hwmask)(struct pic *, int); + void (*pic_hwunmask)(struct pic *, int); + void (*pic_addroute)(struct pic *, struct cpu_info *, int, int, int); + void (*pic_delroute)(struct pic *, struct cpu_info *, int, int, int); + struct intrstub *pic_level_stubs; + struct intrstub *pic_edge_stubs; +}; + +#define pic_name pic_dev.dv_xname + +/* + * PIC types. + */ +#define PIC_I8259 0 +#define PIC_IOAPIC 1 +#define PIC_LAPIC 2 +#define PIC_SOFT 3 + +extern struct pic i8259_pic; +extern struct pic local_pic; +extern struct pic softintr_pic; +#endif |