summaryrefslogtreecommitdiff
path: root/sys/arch/i386
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/i386')
-rw-r--r--sys/arch/i386/i386/apic.c3
-rw-r--r--sys/arch/i386/i386/ioapic.c162
-rw-r--r--sys/arch/i386/i386/mpbios.c6
-rw-r--r--sys/arch/i386/i386/mpbios_intr_fixup.c4
-rw-r--r--sys/arch/i386/include/cpufunc.h5
-rw-r--r--sys/arch/i386/include/i82093var.h4
-rw-r--r--sys/arch/i386/include/intr.h4
-rw-r--r--sys/arch/i386/include/pic.h43
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