summaryrefslogtreecommitdiff
path: root/sys/arch/amd64
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r--sys/arch/amd64/amd64/apic.c79
-rw-r--r--sys/arch/amd64/amd64/cpu.c48
-rw-r--r--sys/arch/amd64/amd64/fpu.c4
-rw-r--r--sys/arch/amd64/amd64/gdt.c10
-rw-r--r--sys/arch/amd64/amd64/genassym.cf9
-rw-r--r--sys/arch/amd64/amd64/i8259.c6
-rw-r--r--sys/arch/amd64/amd64/identcpu.c7
-rw-r--r--sys/arch/amd64/amd64/intr.c20
-rw-r--r--sys/arch/amd64/amd64/ioapic.c549
-rw-r--r--sys/arch/amd64/amd64/ipi.c142
-rw-r--r--sys/arch/amd64/amd64/ipifuncs.c135
-rw-r--r--sys/arch/amd64/amd64/lapic.c491
-rw-r--r--sys/arch/amd64/amd64/locore.S206
-rw-r--r--sys/arch/amd64/amd64/machdep.c32
-rw-r--r--sys/arch/amd64/amd64/microtime.S4
-rw-r--r--sys/arch/amd64/amd64/mpbios.c1108
-rw-r--r--sys/arch/amd64/amd64/mptramp.S239
-rw-r--r--sys/arch/amd64/amd64/pmap.c42
-rw-r--r--sys/arch/amd64/amd64/spl.S1
-rw-r--r--sys/arch/amd64/amd64/vector.S8
-rw-r--r--sys/arch/amd64/amd64/vm_machdep.c3
-rw-r--r--sys/arch/amd64/compile/.cvsignore1
-rw-r--r--sys/arch/amd64/conf/GENERIC4
-rw-r--r--sys/arch/amd64/conf/GENERIC.MP9
-rw-r--r--sys/arch/amd64/conf/RAMDISK4
-rw-r--r--sys/arch/amd64/conf/RAMDISK_CD4
-rw-r--r--sys/arch/amd64/conf/files.amd6415
-rw-r--r--sys/arch/amd64/include/cpu.h21
-rw-r--r--sys/arch/amd64/include/frame.h3
-rw-r--r--sys/arch/amd64/include/i82093reg.h64
-rw-r--r--sys/arch/amd64/include/i82489var.h122
-rw-r--r--sys/arch/amd64/include/intr.h5
-rw-r--r--sys/arch/amd64/include/lock.h119
-rw-r--r--sys/arch/amd64/include/mpconfig.h3
-rw-r--r--sys/arch/amd64/include/pic.h10
-rw-r--r--sys/arch/amd64/isa/clock.c31
-rw-r--r--sys/arch/amd64/pci/pci_machdep.c4
37 files changed, 3332 insertions, 230 deletions
diff --git a/sys/arch/amd64/amd64/apic.c b/sys/arch/amd64/amd64/apic.c
new file mode 100644
index 00000000000..aa21491781b
--- /dev/null
+++ b/sys/arch/amd64/amd64/apic.c
@@ -0,0 +1,79 @@
+/* $OpenBSD: apic.c,v 1.1 2004/06/25 11:03:27 art Exp $ */
+/* $NetBSD: apic.c,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by RedBack Networks Inc.
+ *
+ * Author: Bill Sommerfeld
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY 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/lock.h> /* XXX */
+
+#include <machine/i82489reg.h>
+#include <machine/i82489var.h>
+#include <machine/apicvar.h>
+
+
+const char redirlofmt[] = "\177\20"
+ "f\0\10vector\0"
+ "f\10\3delmode\0"
+ "b\13logical\0"
+ "b\14pending\0"
+ "b\15actlo\0"
+ "b\16irrpending\0"
+ "b\17level\0"
+ "b\20masked\0"
+ "f\22\1dest\0" "=\1self" "=\2all" "=\3all-others";
+
+const char redirhifmt[] = "\177\20"
+ "f\30\10target\0";
+
+void
+apic_format_redir(where1, where2, idx, redirhi, redirlo)
+ char *where1;
+ char *where2;
+ int idx;
+ u_int32_t redirhi;
+ u_int32_t redirlo;
+{
+ printf("%s: %s%d 0x%x", where1, where2, idx, redirlo);
+
+ if ((redirlo & LAPIC_DEST_MASK) == 0)
+ printf(" 0x%x", redirhi);
+
+ printf("\n");
+}
diff --git a/sys/arch/amd64/amd64/cpu.c b/sys/arch/amd64/amd64/cpu.c
index 5f71091cc7a..f415bcc5d31 100644
--- a/sys/arch/amd64/amd64/cpu.c
+++ b/sys/arch/amd64/amd64/cpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.c,v 1.4 2004/06/24 19:35:23 tholo Exp $ */
+/* $OpenBSD: cpu.c,v 1.5 2004/06/25 11:03:27 art Exp $ */
/* $NetBSD: cpu.c,v 1.1 2003/04/26 18:39:26 fvdl Exp $ */
/*-
@@ -347,6 +347,7 @@ cpu_attach(parent, self, aux)
cpu_intr_init(ci);
gdt_alloc_cpu(ci);
cpu_start_secondary(ci);
+ ncpus++;
if (ci->ci_flags & CPUF_PRESENT) {
identifycpu(ci);
ci->ci_next = cpu_info_list->ci_next;
@@ -447,27 +448,11 @@ cpu_start_secondary (ci)
{
struct pcb *pcb;
int i;
- struct pmap *kmp = pmap_kernel();
- extern u_int64_t mp_pdirpa;
- extern vaddr_t lo32_vaddr;
- extern paddr_t lo32_paddr;
-
- /*
- * The initial PML4 pointer must be below 4G, so if the
- * current one isn't, use a "bounce buffer"
- */
- if (kmp->pm_pdirpa > 0xffffffff) {
- memcpy((void *)lo32_vaddr, kmp->pm_pdir, PAGE_SIZE);
- mp_pdirpa = lo32_paddr;
- } else
- mp_pdirpa = kmp->pm_pdirpa;
pcb = ci->ci_idle_pcb;
ci->ci_flags |= CPUF_AP;
- printf("%s: starting\n", ci->ci_dev->dv_xname);
-
CPU_STARTUP(ci);
/*
@@ -558,10 +543,6 @@ cpu_hatch(void *v)
enable_intr();
printf("%s: CPU %u running\n",ci->ci_dev->dv_xname, ci->ci_cpuid);
-#if defined(I586_CPU) || defined(I686_CPU)
- if (ci->ci_feature_flags & CPUID_TSC)
- cc_microset(ci);
-#endif
microuptime(&ci->ci_schedstate.spc_runtime);
splx(s);
}
@@ -601,12 +582,30 @@ cpu_copy_trampoline()
*/
extern u_char cpu_spinup_trampoline[];
extern u_char cpu_spinup_trampoline_end[];
+
+ struct pmap *kmp = pmap_kernel();
+ extern u_int32_t mp_pdirpa;
+ extern vaddr_t lo32_vaddr;
+ extern paddr_t lo32_paddr;
+
pmap_kenter_pa((vaddr_t)MP_TRAMPOLINE, /* virtual */
(paddr_t)MP_TRAMPOLINE, /* physical */
VM_PROT_ALL); /* protection */
memcpy((caddr_t)MP_TRAMPOLINE,
cpu_spinup_trampoline,
cpu_spinup_trampoline_end-cpu_spinup_trampoline);
+
+ /*
+ * The initial PML4 pointer must be below 4G, so if the
+ * current one isn't, use a "bounce buffer"
+ * We need to patch this after we copy the trampoline,
+ * the symbol points into the copied trampoline.
+ */
+ if (kmp->pm_pdirpa > 0xffffffff) {
+ memcpy((void *)lo32_vaddr, kmp->pm_pdir, PAGE_SIZE);
+ mp_pdirpa = lo32_paddr;
+ } else
+ mp_pdirpa = kmp->pm_pdirpa;
}
#endif
@@ -635,9 +634,9 @@ mp_cpu_start(struct cpu_info *ci)
dwordptr[0] = 0;
dwordptr[1] = MP_TRAMPOLINE >> 4;
- pmap_kenter_pa (0, 0, VM_PROT_READ|VM_PROT_WRITE);
- memcpy ((u_int8_t *) 0x467, dwordptr, 4);
- pmap_kremove (0, PAGE_SIZE);
+ pmap_kenter_pa(0, 0, VM_PROT_READ|VM_PROT_WRITE);
+ memcpy((u_int8_t *) 0x467, dwordptr, 4);
+ pmap_kremove(0, PAGE_SIZE);
#if NLAPIC > 0
/*
@@ -651,7 +650,6 @@ mp_cpu_start(struct cpu_info *ci)
delay(10000);
if (cpu_feature & CPUID_APIC) {
-
if ((error = x86_ipi(MP_TRAMPOLINE/PAGE_SIZE,
ci->ci_apicid,
LAPIC_DLMODE_STARTUP)) != 0)
diff --git a/sys/arch/amd64/amd64/fpu.c b/sys/arch/amd64/amd64/fpu.c
index 3c3298481b2..bd2ac4e4d3d 100644
--- a/sys/arch/amd64/amd64/fpu.c
+++ b/sys/arch/amd64/amd64/fpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fpu.c,v 1.4 2004/02/28 20:33:33 nordin Exp $ */
+/* $OpenBSD: fpu.c,v 1.5 2004/06/25 11:03:27 art Exp $ */
/* $NetBSD: fpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */
/*-
@@ -288,7 +288,7 @@ fpusave_proc(struct proc *p, int save)
#ifdef DIAGNOSTIC
spincount = 0;
#endif
- while (p->dpl_addr->u_pcb.pcb_fpcpu != NULL)
+ while (p->p_addr->u_pcb.pcb_fpcpu != NULL)
#ifdef DIAGNOSTIC
{
spincount++;
diff --git a/sys/arch/amd64/amd64/gdt.c b/sys/arch/amd64/amd64/gdt.c
index 837c82b8e88..ded8e4a421e 100644
--- a/sys/arch/amd64/amd64/gdt.c
+++ b/sys/arch/amd64/amd64/gdt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gdt.c,v 1.3 2004/05/20 21:06:46 nordin Exp $ */
+/* $OpenBSD: gdt.c,v 1.4 2004/06/25 11:03:27 art Exp $ */
/* $NetBSD: gdt.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */
/*-
@@ -81,15 +81,15 @@ void gdt_put_slot(int);
static __inline void
gdt_lock()
{
-
- (void) lockmgr(&gdt_lock_store, LK_EXCLUSIVE, NULL, curproc);
+ if (curproc != NULL) /* XXX - ugh. needed for startup */
+ (void) lockmgr(&gdt_lock_store, LK_EXCLUSIVE, NULL, curproc);
}
static __inline void
gdt_unlock()
{
-
- (void) lockmgr(&gdt_lock_store, LK_RELEASE, NULL, curproc);
+ if (curproc != NULL)
+ (void) lockmgr(&gdt_lock_store, LK_RELEASE, NULL, curproc);
}
void
diff --git a/sys/arch/amd64/amd64/genassym.cf b/sys/arch/amd64/amd64/genassym.cf
index 7061ce92c6b..43f25173c7f 100644
--- a/sys/arch/amd64/amd64/genassym.cf
+++ b/sys/arch/amd64/amd64/genassym.cf
@@ -1,4 +1,4 @@
-# $OpenBSD: genassym.cf,v 1.5 2004/06/22 01:16:50 art Exp $
+# $OpenBSD: genassym.cf,v 1.6 2004/06/25 11:03:27 art Exp $
# Written by Artur Grabowski art@openbsd.org, Public Domain
@@ -15,6 +15,8 @@ include <machine/pmap.h>
include <machine/pte.h>
include <machine/vmparam.h>
include <machine/intr.h>
+include <machine/pic.h>
+include <machine/i82093var.h>
export SRUN
export SONPROC
@@ -105,6 +107,7 @@ member CPU_INFO_IDEPTH ci_idepth
member CPU_INFO_ISOURCES ci_isources
member CPU_INFO_IPENDING ci_ipending
member CPU_INFO_IUNMASK ci_iunmask
+member CPU_INFO_GDT ci_gdt
struct intrsource
member is_recurse
@@ -123,6 +126,10 @@ member ih_arg
member ih_next
member ih_level
+struct ioapic_softc
+member IOAPIC_SC_REG sc_reg
+member IOAPIC_SC_DATA sc_data
+
# pte fields
export PG_V
export PG_KR
diff --git a/sys/arch/amd64/amd64/i8259.c b/sys/arch/amd64/amd64/i8259.c
index 12b04b2a40b..4cea529bde2 100644
--- a/sys/arch/amd64/amd64/i8259.c
+++ b/sys/arch/amd64/amd64/i8259.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: i8259.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $OpenBSD: i8259.c,v 1.2 2004/06/25 11:03:27 art Exp $ */
/* $NetBSD: i8259.c,v 1.2 2003/03/02 18:27:15 fvdl Exp $ */
/*
@@ -112,9 +112,7 @@ struct pic i8259_pic = {
{0, {NULL}, NULL, 0, "pic0", NULL, 0, 0},
PIC_I8259,
#ifdef MULTIPROCESSOR
- __SIMPLELOCK_UNLOCKED,
-#else
- 0,
+ {},
#endif
i8259_hwmask,
i8259_hwunmask,
diff --git a/sys/arch/amd64/amd64/identcpu.c b/sys/arch/amd64/amd64/identcpu.c
index 2f8fda8d2f8..9b1596646e8 100644
--- a/sys/arch/amd64/amd64/identcpu.c
+++ b/sys/arch/amd64/amd64/identcpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: identcpu.c,v 1.4 2004/02/28 18:12:21 deraadt Exp $ */
+/* $OpenBSD: identcpu.c,v 1.5 2004/06/25 11:03:27 art Exp $ */
/* $NetBSD: identcpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */
/*
@@ -163,11 +163,6 @@ identifycpu(struct cpu_info *ci)
printf("\n");
x86_print_cacheinfo(ci);
-
- return; /* TODO - warning to fix this ifdef later */
-#ifdef notyet
- microtime_func = cc_microtime;
-#endif
}
void
diff --git a/sys/arch/amd64/amd64/intr.c b/sys/arch/amd64/amd64/intr.c
index a80798e3a44..f5f929cbbd2 100644
--- a/sys/arch/amd64/amd64/intr.c
+++ b/sys/arch/amd64/amd64/intr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: intr.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $OpenBSD: intr.c,v 1.2 2004/06/25 11:03:27 art Exp $ */
/* $NetBSD: intr.c,v 1.3 2003/03/03 22:16:20 fvdl Exp $ */
/*
@@ -69,9 +69,7 @@ struct pic softintr_pic = {
{0, {NULL}, NULL, 0, "softintr_fakepic", NULL, 0, 0},
PIC_SOFT,
#ifdef MULTIPROCESSOR
- __SIMPLELOCK_UNLOCKED,
-#else
- 0,
+ {},
#endif
NULL,
NULL,
@@ -544,7 +542,7 @@ struct intrhand fake_softserial_intrhand;
struct intrhand fake_timer_intrhand;
struct intrhand fake_ipi_intrhand;
-#if NLAPIC > 0 && defined(MULTIPROCESSOR)
+#if NLAPIC > 0 && defined(MULTIPROCESSOR) && 0
static char *x86_ipi_names[X86_NIPI] = X86_IPI_NAMES;
#endif
@@ -556,7 +554,7 @@ void
cpu_intr_init(struct cpu_info *ci)
{
struct intrsource *isp;
-#if NLAPIC > 0 && defined(MULTIPROCESSOR)
+#if NLAPIC > 0 && defined(MULTIPROCESSOR) && 0
int i;
#endif
@@ -634,11 +632,13 @@ cpu_intr_init(struct cpu_info *ci)
isp->is_pic = &local_pic;
ci->ci_isources[LIR_IPI] = isp;
+#ifdef notyet
for (i = 0; i < X86_NIPI; i++)
evcnt_attach_dynamic(&ci->ci_ipi_events[i], EVCNT_TYPE_INTR,
NULL, ci->ci_dev->dv_xname, x86_ipi_names[i]);
#endif
#endif
+#endif
intr_calculatemasks(ci);
@@ -649,26 +649,26 @@ void
x86_intlock(struct intrframe iframe)
{
if (iframe.if_ppl < IPL_SCHED)
- spinlockmgr(&kernel_lock, LK_EXCLUSIVE|LK_CANRECURSE, 0);
+ __mp_lock(&kernel_lock);
}
void
x86_intunlock(struct intrframe iframe)
{
if (iframe.if_ppl < IPL_SCHED)
- spinlockmgr(&kernel_lock, LK_RELEASE, 0);
+ __mp_unlock(&kernel_lock);
}
void
x86_softintlock(void)
{
- spinlockmgr(&kernel_lock, LK_EXCLUSIVE|LK_CANRECURSE, 0);
+ __mp_lock(&kernel_lock);
}
void
x86_softintunlock(void)
{
- spinlockmgr(&kernel_lock, LK_RELEASE, 0);
+ __mp_unlock(&kernel_lock);
}
#endif
diff --git a/sys/arch/amd64/amd64/ioapic.c b/sys/arch/amd64/amd64/ioapic.c
new file mode 100644
index 00000000000..77874bc243d
--- /dev/null
+++ b/sys/arch/amd64/amd64/ioapic.c
@@ -0,0 +1,549 @@
+/* $OpenBSD: ioapic.c,v 1.1 2004/06/25 11:03:27 art Exp $ */
+/* $NetBSD: ioapic.c,v 1.6 2003/05/15 13:30:31 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by RedBack Networks Inc.
+ *
+ * Author: Bill Sommerfeld
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+ * Copyright (c) 1999 Stefan Grefen
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * 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>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/isa_machdep.h> /* XXX intrhand */
+
+#include <uvm/uvm_extern.h>
+#include <machine/i82093reg.h>
+#include <machine/i82093var.h>
+
+#include <machine/i82489reg.h>
+#include <machine/i82489var.h>
+
+#include <machine/pmap.h>
+
+#include <machine/mpbiosvar.h>
+
+#if !defined(MPBIOS) && !defined(MPACPI)
+#error "ioapic needs at least one of the MPBIOS or MPACPI options"
+#endif
+
+/*
+ * XXX locking
+ */
+
+int ioapic_match(struct device *, void *, void *);
+void ioapic_attach(struct device *, struct device *, void *);
+
+extern int x86_mem_add_mapping(bus_addr_t, bus_size_t,
+ int, bus_space_handle_t *); /* XXX XXX */
+
+void ioapic_hwmask(struct pic *, int);
+void ioapic_hwunmask(struct pic *, int);
+void ioapic_addroute(struct pic *, struct cpu_info *, int, int, int);
+void ioapic_delroute(struct pic *, struct cpu_info *, int, int, int);
+void apic_set_redir(struct ioapic_softc *, int, int, struct cpu_info *);
+
+int apic_verbose = 0;
+
+int ioapic_bsp_id = 0;
+int ioapic_cold = 1;
+
+struct ioapic_softc *ioapics; /* head of linked list */
+int nioapics = 0; /* number attached */
+static int ioapic_vecbase;
+
+static __inline u_long
+ioapic_lock(struct ioapic_softc *sc)
+{
+ u_long flags;
+
+ flags = read_psl();
+ disable_intr();
+ SIMPLE_LOCK(&sc->sc_pic.pic_lock);
+ return flags;
+}
+
+static __inline void
+ioapic_unlock(struct ioapic_softc *sc, u_long flags)
+{
+ SIMPLE_UNLOCK(&sc->sc_pic.pic_lock);
+ write_psl(flags);
+}
+
+/*
+ * Register read/write routines.
+ */
+static __inline u_int32_t
+ioapic_read_ul(struct ioapic_softc *sc,int regid)
+{
+ u_int32_t val;
+
+ *(sc->sc_reg) = regid;
+ val = *sc->sc_data;
+
+ return val;
+
+}
+
+static __inline void
+ioapic_write_ul(struct ioapic_softc *sc,int regid, u_int32_t val)
+{
+ *(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)
+{
+ struct ioapic_softc *sc;
+
+ if (apicid == MPS_ALL_APICS) { /* XXX mpbios-specific */
+ /*
+ * XXX kludge for all-ioapics interrupt support
+ * on single ioapic systems
+ */
+ if (nioapics <= 1)
+ return ioapics;
+ panic("unsupported: all-ioapics interrupt with >1 ioapic");
+ }
+
+ for (sc = ioapics; sc != NULL; sc = sc->sc_next)
+ if (sc->sc_apicid == apicid)
+ return sc;
+
+ return NULL;
+}
+
+/*
+ * For the case the I/O APICs were configured using ACPI, there must
+ * be an option to match global ACPI interrupts with APICs.
+ */
+struct ioapic_softc *
+ioapic_find_bybase(int vec)
+{
+ struct ioapic_softc *sc;
+
+ for (sc = ioapics; sc != NULL; sc = sc->sc_next) {
+ if (vec >= sc->sc_apic_vecbase &&
+ vec < (sc->sc_apic_vecbase + sc->sc_apic_sz))
+ return sc;
+ }
+
+ return NULL;
+}
+
+static __inline void
+ioapic_add(struct ioapic_softc *sc)
+{
+ sc->sc_next = ioapics;
+ ioapics = sc;
+ nioapics++;
+}
+
+void
+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_pic.pic_dev.dv_xname, why, pin, redirhi,
+ redirlo);
+}
+
+struct cfattach ioapic_ca = {
+ sizeof(struct ioapic_softc), ioapic_match, ioapic_attach
+};
+
+struct cfdriver ioapic_cd = {
+ NULL, "ioapic", DV_DULL
+};
+
+int
+ioapic_match(struct device *parent, void *v, void *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;
+ return 0;
+}
+
+/*
+ * can't use bus_space_xxx as we don't have a bus handle ...
+ */
+void
+ioapic_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct ioapic_softc *sc = (struct ioapic_softc *)self;
+ struct apic_attach_args *aaa = (struct apic_attach_args *) aux;
+ int apic_id;
+ bus_space_handle_t bh;
+ u_int32_t ver_sz;
+ int i;
+
+ sc->sc_flags = aaa->flags;
+ sc->sc_apicid = aaa->apic_id;
+
+ printf(" apid %d (I/O APIC)\n", aaa->apic_id);
+
+ if (ioapic_find(aaa->apic_id) != NULL) {
+ printf("%s: duplicate apic id (ignored)\n",
+ sc->sc_pic.pic_dev.dv_xname);
+ return;
+ }
+
+ ioapic_add(sc);
+
+ printf("%s: pa 0x%lx", sc->sc_pic.pic_dev.dv_xname, aaa->apic_address);
+
+ if (x86_mem_add_mapping(aaa->apic_address, PAGE_SIZE, 0, &bh) != 0) {
+ printf(": map failed\n");
+ return;
+ }
+ sc->sc_reg = (volatile u_int32_t *)(bh + IOAPIC_REG);
+ sc->sc_data = (volatile u_int32_t *)(bh + IOAPIC_DATA);
+
+ sc->sc_pic.pic_type = PIC_IOAPIC;
+ SIMPLE_LOCK_INIT(&sc->sc_pic.pic_lock);
+ sc->sc_pic.pic_hwmask = ioapic_hwmask;
+ sc->sc_pic.pic_hwunmask = ioapic_hwunmask;
+ sc->sc_pic.pic_addroute = ioapic_addroute;
+ sc->sc_pic.pic_delroute = ioapic_delroute;
+ sc->sc_pic.pic_edge_stubs = ioapic_edge_stubs;
+ sc->sc_pic.pic_level_stubs = ioapic_level_stubs;
+
+ apic_id = (ioapic_read(sc,IOAPIC_ID)&IOAPIC_ID_MASK)>>IOAPIC_ID_SHIFT;
+ ver_sz = ioapic_read(sc, IOAPIC_VER);
+
+ sc->sc_apic_vers = (ver_sz & IOAPIC_VER_MASK) >> IOAPIC_VER_SHIFT;
+ sc->sc_apic_sz = (ver_sz & IOAPIC_MAX_MASK) >> IOAPIC_MAX_SHIFT;
+ sc->sc_apic_sz++;
+
+ if (aaa->apic_vecbase != -1)
+ sc->sc_apic_vecbase = aaa->apic_vecbase;
+ else {
+ /*
+ * XXX this assumes ordering of ioapics in the table.
+ * Only needed for broken BIOS workaround (see mpbios.c)
+ */
+ sc->sc_apic_vecbase = ioapic_vecbase;
+ ioapic_vecbase += sc->sc_apic_sz;
+ }
+
+ if (mp_verbose) {
+ printf(", %s mode",
+ aaa->flags & IOAPIC_PICMODE ? "PIC" : "virtual wire");
+ }
+
+ printf(", version %x, %d pins\n", sc->sc_apic_vers, sc->sc_apic_sz);
+
+ sc->sc_pins = malloc(sizeof(struct ioapic_pin) * sc->sc_apic_sz,
+ M_DEVBUF, M_WAITOK);
+
+ for (i=0; i<sc->sc_apic_sz; i++) {
+ sc->sc_pins[i].ip_next = NULL;
+ sc->sc_pins[i].ip_map = NULL;
+ sc->sc_pins[i].ip_vector = 0;
+ sc->sc_pins[i].ip_type = IST_NONE;
+ }
+
+ /*
+ * In case the APIC is not initialized to the correct ID
+ * do it now.
+ * Maybe we should record the original ID for interrupt
+ * mapping later ...
+ */
+ if (apic_id != sc->sc_apicid) {
+ printf("%s: misconfigured as apic %d\n", sc->sc_pic.pic_dev.dv_xname, apic_id);
+
+ ioapic_write(sc,IOAPIC_ID,
+ (ioapic_read(sc,IOAPIC_ID)&~IOAPIC_ID_MASK)
+ |(sc->sc_apicid<<IOAPIC_ID_SHIFT));
+
+ apic_id = (ioapic_read(sc,IOAPIC_ID)&IOAPIC_ID_MASK)>>IOAPIC_ID_SHIFT;
+
+ if (apic_id != sc->sc_apicid) {
+ printf("%s: can't remap to apid %d\n",
+ sc->sc_pic.pic_dev.dv_xname,
+ sc->sc_apicid);
+ } else {
+ printf("%s: remapped to apic %d\n",
+ sc->sc_pic.pic_dev.dv_xname,
+ sc->sc_apicid);
+ }
+ }
+#if 0
+ /* output of this was boring. */
+ if (mp_verbose)
+ for (i=0; i<sc->sc_apic_sz; i++)
+ ioapic_print_redir(sc, "boot", i);
+#endif
+}
+
+void
+apic_set_redir(struct ioapic_softc *sc, int pin, int idt_vec,
+ struct cpu_info *ci)
+{
+ u_int32_t redlo;
+ u_int32_t redhi = 0;
+ int delmode;
+
+ struct ioapic_pin *pp;
+ struct mp_intr_map *map;
+
+ pp = &sc->sc_pins[pin];
+ map = pp->ip_map;
+ redlo = map == NULL ? IOAPIC_REDLO_MASK : map->redir;
+ delmode = (redlo & IOAPIC_REDLO_DEL_MASK) >> IOAPIC_REDLO_DEL_SHIFT;
+
+ /* XXX magic numbers */
+ if ((delmode != 0) && (delmode != 1))
+ ;
+ else if (pp->ip_type == IST_NONE) {
+ redlo |= IOAPIC_REDLO_MASK;
+ } else {
+ redlo |= (idt_vec & 0xff);
+ redlo &= ~IOAPIC_REDLO_DEL_MASK;
+ redlo |= (IOAPIC_REDLO_DEL_FIXED<<IOAPIC_REDLO_DEL_SHIFT);
+ redlo &= ~IOAPIC_REDLO_DSTMOD;
+
+ /*
+ * Destination: BSP CPU
+ *
+ * XXX will want to distribute interrupts across cpu's
+ * eventually. most likely, we'll want to vector each
+ * interrupt to a specific CPU and load-balance across
+ * cpu's. but there's no point in doing that until after
+ * most interrupts run without the kernel lock.
+ */
+ redhi |= (ci->ci_apicid << IOAPIC_REDHI_DEST_SHIFT);
+
+ /* XXX derive this bit from BIOS info */
+ if (pp->ip_type == IST_LEVEL)
+ redlo |= IOAPIC_REDLO_LEVEL;
+ else
+ redlo &= ~IOAPIC_REDLO_LEVEL;
+ if (map != NULL && ((map->flags & 3) == MPS_INTPO_DEF)) {
+ if (pp->ip_type == IST_LEVEL)
+ redlo |= IOAPIC_REDLO_ACTLO;
+ else
+ redlo &= ~IOAPIC_REDLO_ACTLO;
+ }
+ }
+ ioapic_write(sc, IOAPIC_REDLO(pin), redlo);
+ ioapic_write(sc, IOAPIC_REDHI(pin), redhi);
+ if (mp_verbose)
+ ioapic_print_redir(sc, "int", pin);
+}
+
+/*
+ * Throw the switch and enable interrupts..
+ */
+
+void
+ioapic_enable(void)
+{
+ int p;
+ struct ioapic_softc *sc;
+ struct ioapic_pin *ip;
+
+ ioapic_cold = 0;
+
+ if (ioapics == NULL)
+ return;
+
+ if (ioapics->sc_flags & IOAPIC_PICMODE) {
+ printf("%s: writing to IMCR to disable pics\n",
+ ioapics->sc_pic.pic_dev.dv_xname);
+ outb(IMCR_ADDR, IMCR_REGISTER);
+ outb(IMCR_DATA, IMCR_APIC);
+ }
+
+ for (sc = ioapics; sc != NULL; sc = sc->sc_next) {
+ printf("%s: enabling\n", sc->sc_pic.pic_dev.dv_xname);
+
+ for (p = 0; p < sc->sc_apic_sz; p++) {
+ ip = &sc->sc_pins[p];
+ if (ip->ip_type != IST_NONE)
+ apic_set_redir(sc, p, ip->ip_vector,
+ ip->ip_cpu);
+ }
+ }
+}
+
+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);
+}
+
+void
+ioapic_addroute(struct pic *pic, struct cpu_info *ci, int pin,
+ int idtvec, int type)
+
+{
+ struct ioapic_softc *sc = (struct ioapic_softc *)pic;
+ struct ioapic_pin *pp;
+
+ if (ioapic_cold) {
+ pp = &sc->sc_pins[pin];
+ pp->ip_type = type;
+ pp->ip_vector = idtvec;
+ pp->ip_cpu = ci;
+ return;
+ }
+ apic_set_redir(sc, pin, idtvec, ci);
+}
+
+void
+ioapic_delroute(struct pic *pic, struct cpu_info *ci, int pin,
+ int idtvec, int type)
+{
+ struct ioapic_softc *sc = (struct ioapic_softc *)pic;
+ struct ioapic_pin *pp;
+
+ if (ioapic_cold) {
+ pp = &sc->sc_pins[pin];
+ pp->ip_type = IST_NONE;
+ return;
+ }
+ ioapic_hwmask(pic, pin);
+}
+
+#ifdef DDB
+void ioapic_dump(void);
+
+void
+ioapic_dump(void)
+{
+ struct ioapic_softc *sc;
+ struct ioapic_pin *ip;
+ int p;
+
+ for (sc = ioapics; sc != NULL; sc = sc->sc_next) {
+ for (p = 0; p < sc->sc_apic_sz; p++) {
+ ip = &sc->sc_pins[p];
+ if (ip->ip_type != IST_NONE)
+ ioapic_print_redir(sc, "dump", p);
+ }
+ }
+}
+#endif
diff --git a/sys/arch/amd64/amd64/ipi.c b/sys/arch/amd64/amd64/ipi.c
new file mode 100644
index 00000000000..8cdecb60207
--- /dev/null
+++ b/sys/arch/amd64/amd64/ipi.c
@@ -0,0 +1,142 @@
+/* $OpenBSD: ipi.c,v 1.1 2004/06/25 11:03:27 art Exp $ */
+/* $NetBSD: ipi.c,v 1.2 2003/03/01 13:05:37 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by RedBack Networks Inc.
+ *
+ * Author: Bill Sommerfeld
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <machine/intr.h>
+#include <machine/atomic.h>
+#include <machine/cpuvar.h>
+#include <machine/i82093var.h>
+#include <machine/i82489reg.h>
+#include <machine/i82489var.h>
+
+int
+x86_send_ipi(struct cpu_info *ci, int ipimask)
+{
+ int ret;
+
+ x86_atomic_setbits_l(&ci->ci_ipis, ipimask);
+
+ /* Don't send IPI to cpu which isn't (yet) running. */
+ if (!(ci->ci_flags & CPUF_RUNNING))
+ return ENOENT;
+
+ ret = x86_ipi(LAPIC_IPI_VECTOR, ci->ci_apicid, LAPIC_DLMODE_FIXED);
+ if (ret != 0) {
+ printf("ipi of %x from %s to %s failed\n",
+ ipimask,
+ curcpu()->ci_dev->dv_xname,
+ ci->ci_dev->dv_xname);
+ }
+
+ return ret;
+}
+
+void
+x86_self_ipi (int vector)
+{
+ i82489_writereg(LAPIC_ICRLO,
+ vector | LAPIC_DLMODE_FIXED | LAPIC_LVL_ASSERT | LAPIC_DEST_SELF);
+}
+
+
+void
+x86_broadcast_ipi (int ipimask)
+{
+ struct cpu_info *ci, *self = curcpu();
+ int count = 0;
+
+ CPU_INFO_ITERATOR cii;
+
+ for (CPU_INFO_FOREACH(cii, ci)) {
+ if (ci == self)
+ continue;
+ if ((ci->ci_flags & CPUF_RUNNING) == 0)
+ continue;
+ x86_atomic_setbits_l(&ci->ci_ipis, ipimask);
+ count++;
+ }
+ if (!count)
+ return;
+
+ i82489_writereg(LAPIC_ICRLO,
+ LAPIC_IPI_VECTOR | LAPIC_DLMODE_FIXED | LAPIC_LVL_ASSERT |
+ LAPIC_DEST_ALLEXCL);
+}
+
+void
+x86_multicast_ipi(int cpumask, int ipimask)
+{
+ struct cpu_info *ci;
+ CPU_INFO_ITERATOR cii;
+
+ cpumask &= ~(1U << cpu_number());
+ if (cpumask == 0)
+ return;
+
+ for (CPU_INFO_FOREACH(cii, ci)) {
+ if ((cpumask & (1U << ci->ci_cpuid)) == 0)
+ continue;
+ x86_send_ipi(ci, ipimask);
+ }
+}
+
+void
+x86_ipi_handler(void)
+{
+ struct cpu_info *ci = curcpu();
+ u_int32_t pending;
+ int bit;
+
+ pending = x86_atomic_testset_ul(&ci->ci_ipis, 0);
+
+ for (bit = 0; bit < X86_NIPI && pending; bit++) {
+ if (pending & (1<<bit)) {
+ pending &= ~(1<<bit);
+ ci->ci_ipi_events[bit].ev_count++;
+ (*ipifunc[bit])(ci);
+ }
+ }
+}
diff --git a/sys/arch/amd64/amd64/ipifuncs.c b/sys/arch/amd64/amd64/ipifuncs.c
new file mode 100644
index 00000000000..fea247d36fc
--- /dev/null
+++ b/sys/arch/amd64/amd64/ipifuncs.c
@@ -0,0 +1,135 @@
+/* $OpenBSD: ipifuncs.c,v 1.1 2004/06/25 11:03:27 art Exp $ */
+/* $NetBSD: ipifuncs.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by RedBack Networks Inc.
+ *
+ * Author: Bill Sommerfeld
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
+
+/*
+ * Interprocessor interrupt handlers.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/intr.h>
+#include <machine/atomic.h>
+#include <machine/cpuvar.h>
+#include <machine/i82093var.h>
+#include <machine/i82489reg.h>
+#include <machine/i82489var.h>
+#include <machine/mtrr.h>
+#include <machine/gdt.h>
+#include <machine/fpu.h>
+
+#include <ddb/db_output.h>
+
+void x86_64_ipi_halt(struct cpu_info *);
+
+void x86_64_ipi_synch_fpu(struct cpu_info *);
+void x86_64_ipi_flush_fpu(struct cpu_info *);
+
+void x86_64_ipi_nop(struct cpu_info *);
+
+#ifdef MTRR
+void x86_64_reload_mtrr(struct cpu_info *);
+#else
+#define x86_64_reload_mtrr NULL
+#endif
+
+void (*ipifunc[X86_NIPI])(struct cpu_info *) =
+{
+ x86_64_ipi_halt,
+#if 0
+ cc_microset,
+#else
+ x86_64_ipi_nop,
+#endif
+ x86_64_ipi_flush_fpu,
+ x86_64_ipi_synch_fpu,
+ pmap_do_tlb_shootdown,
+ x86_64_reload_mtrr,
+ gdt_reload_cpu,
+};
+
+void
+x86_64_ipi_nop(struct cpu_info *ci)
+{
+}
+
+void
+x86_64_ipi_halt(struct cpu_info *ci)
+{
+ disable_intr();
+
+ printf("%s: shutting down\n", ci->ci_dev->dv_xname);
+ for(;;) {
+ __asm __volatile("hlt");
+ }
+}
+
+void
+x86_64_ipi_flush_fpu(struct cpu_info *ci)
+{
+ fpusave_cpu(ci, 0);
+}
+
+void
+x86_64_ipi_synch_fpu(struct cpu_info *ci)
+{
+ fpusave_cpu(ci, 1);
+}
+
+#ifdef MTRR
+
+/*
+ * mtrr_reload_cpu() is a macro in mtrr.h which picks the appropriate
+ * function to use..
+ */
+
+void
+x86_64_reload_mtrr(struct cpu_info *ci)
+{
+ if (mtrr_funcs != NULL)
+ mtrr_reload_cpu(ci);
+}
+#endif
diff --git a/sys/arch/amd64/amd64/lapic.c b/sys/arch/amd64/amd64/lapic.c
new file mode 100644
index 00000000000..dcf6df2a8c5
--- /dev/null
+++ b/sys/arch/amd64/amd64/lapic.c
@@ -0,0 +1,491 @@
+/* $OpenBSD: lapic.c,v 1.1 2004/06/25 11:03:27 art Exp $ */
+/* $NetBSD: lapic.c,v 1.2 2003/05/08 01:04:35 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by RedBack Networks Inc.
+ *
+ * Author: Bill Sommerfeld
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <dev/ic/i8253reg.h>
+
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/cpuvar.h>
+#include <machine/pmap.h>
+#include <machine/vmparam.h>
+#include <machine/mpbiosvar.h>
+#include <machine/pcb.h>
+#include <machine/specialreg.h>
+#include <machine/segments.h>
+
+#include <machine/apicvar.h>
+#include <machine/i82489reg.h>
+#include <machine/i82489var.h>
+
+void lapic_delay(int);
+void lapic_microtime(struct timeval *);
+static u_int32_t lapic_gettick(void);
+void lapic_clockintr(void *, struct intrframe);
+void lapic_map(paddr_t);
+
+void lapic_hwmask(struct pic *, int);
+void lapic_hwunmask(struct pic *, int);
+void lapic_setup(struct pic *, struct cpu_info *, int, int, int);
+
+extern char idt_allocmap[];
+
+struct pic local_pic = {
+ {0, {NULL}, NULL, 0, "lapic", NULL, 0, 0},
+ PIC_LAPIC,
+#ifdef MULTIPROCESSOR
+ {},
+#endif
+ lapic_hwmask,
+ lapic_hwunmask,
+ lapic_setup,
+ lapic_setup,
+};
+
+void
+lapic_map(lapic_base)
+ paddr_t lapic_base;
+{
+ int s;
+ pt_entry_t *pte;
+ vaddr_t va = (vaddr_t)&local_apic;
+
+ disable_intr();
+ s = lapic_tpr;
+
+ /*
+ * Map local apic. If we have a local apic, it's safe to assume
+ * we're on a 486 or better and can use invlpg and non-cacheable PTE's
+ *
+ * Whap the PTE "by hand" rather than calling pmap_kenter_pa because
+ * the latter will attempt to invoke TLB shootdown code just as we
+ * might have changed the value of cpu_number()..
+ */
+
+ pte = kvtopte(va);
+ *pte = lapic_base | PG_RW | PG_V | PG_N | pmap_pg_g;
+ invlpg(va);
+
+#ifdef MULTIPROCESSOR
+ cpu_init_first(); /* catch up to changed cpu_number() */
+#endif
+
+ lapic_tpr = s;
+ enable_intr();
+}
+
+/*
+ * enable local apic
+ */
+void
+lapic_enable()
+{
+ i82489_writereg(LAPIC_SVR, LAPIC_SVR_ENABLE | LAPIC_SPURIOUS_VECTOR);
+}
+
+void
+lapic_set_lvt()
+{
+ struct cpu_info *ci = curcpu();
+ int i;
+ struct mp_intr_map *mpi;
+ uint32_t lint0;
+
+#ifdef MULTIPROCESSOR
+ if (mp_verbose) {
+ apic_format_redir (ci->ci_dev->dv_xname, "prelint", 0, 0,
+ i82489_readreg(LAPIC_LVINT0));
+ apic_format_redir (ci->ci_dev->dv_xname, "prelint", 1, 0,
+ i82489_readreg(LAPIC_LVINT1));
+ }
+#endif
+
+ /*
+ * Disable ExtINT by default when using I/O APICs.
+ * XXX mp_nintr > 0 isn't quite the right test for this.
+ */
+ if (mp_nintr > 0) {
+ lint0 = i82489_readreg(LAPIC_LVINT0);
+ lint0 |= LAPIC_LVT_MASKED;
+ i82489_writereg(LAPIC_LVINT0, lint0);
+ }
+
+ for (i = 0; i < mp_nintr; i++) {
+ mpi = &mp_intrs[i];
+ if (mpi->ioapic == NULL && (mpi->cpu_id == MPS_ALL_APICS
+ || mpi->cpu_id == ci->ci_apicid)) {
+#ifdef DIAGNOSTIC
+ if (mpi->ioapic_pin > 1)
+ panic("lapic_set_lvt: bad pin value %d",
+ mpi->ioapic_pin);
+#endif
+ if (mpi->ioapic_pin == 0)
+ i82489_writereg(LAPIC_LVINT0, mpi->redir);
+ else
+ i82489_writereg(LAPIC_LVINT1, mpi->redir);
+ }
+ }
+
+#ifdef MULTIPROCESSOR
+ if (mp_verbose) {
+ apic_format_redir (ci->ci_dev->dv_xname, "timer", 0, 0,
+ i82489_readreg(LAPIC_LVTT));
+ apic_format_redir (ci->ci_dev->dv_xname, "pcint", 0, 0,
+ i82489_readreg(LAPIC_PCINT));
+ apic_format_redir (ci->ci_dev->dv_xname, "lint", 0, 0,
+ i82489_readreg(LAPIC_LVINT0));
+ apic_format_redir (ci->ci_dev->dv_xname, "lint", 1, 0,
+ i82489_readreg(LAPIC_LVINT1));
+ apic_format_redir (ci->ci_dev->dv_xname, "err", 0, 0,
+ i82489_readreg(LAPIC_LVERR));
+ }
+#endif
+}
+
+/*
+ * Initialize fixed idt vectors for use by local apic.
+ */
+void
+lapic_boot_init(lapic_base)
+ paddr_t lapic_base;
+{
+
+ lapic_map(lapic_base);
+
+#ifdef MULTIPROCESSOR
+ idt_allocmap[LAPIC_IPI_VECTOR] = 1;
+ idt_vec_set(LAPIC_IPI_VECTOR, Xintr_lapic_ipi);
+#endif
+ idt_allocmap[LAPIC_SPURIOUS_VECTOR] = 1;
+ idt_vec_set(LAPIC_SPURIOUS_VECTOR, Xintrspurious);
+
+ idt_allocmap[LAPIC_TIMER_VECTOR] = 1;
+ idt_vec_set(LAPIC_TIMER_VECTOR, Xintr_lapic_ltimer);
+}
+
+static inline u_int32_t lapic_gettick()
+{
+ return i82489_readreg(LAPIC_CCR_TIMER);
+}
+
+#include <sys/kernel.h> /* for hz */
+
+int lapic_timer = 0;
+u_int32_t lapic_tval;
+
+/*
+ * this gets us up to a 4GHz busclock....
+ */
+u_int32_t lapic_per_second;
+u_int32_t lapic_frac_usec_per_cycle;
+u_int64_t lapic_frac_cycle_per_usec;
+u_int32_t lapic_delaytab[26];
+
+void
+lapic_clockintr(void *arg, struct intrframe frame)
+{
+
+ hardclock((struct clockframe *)&frame);
+}
+
+void
+lapic_initclocks()
+{
+ /*
+ * Start local apic countdown timer running, in repeated mode.
+ *
+ * Mask the clock interrupt and set mode,
+ * then set divisor,
+ * then unmask and set the vector.
+ */
+ i82489_writereg (LAPIC_LVTT, LAPIC_LVTT_TM|LAPIC_LVTT_M);
+ i82489_writereg (LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
+ i82489_writereg (LAPIC_ICR_TIMER, lapic_tval);
+ i82489_writereg (LAPIC_LVTT, LAPIC_LVTT_TM|LAPIC_TIMER_VECTOR);
+}
+
+extern int gettick(void); /* XXX put in header file */
+extern u_long rtclock_tval; /* XXX put in header file */
+extern void (*initclock_func)(void); /* XXX put in header file */
+
+/*
+ * Calibrate the local apic count-down timer (which is running at
+ * bus-clock speed) vs. the i8254 counter/timer (which is running at
+ * a fixed rate).
+ *
+ * The Intel MP spec says: "An MP operating system may use the IRQ8
+ * real-time clock as a reference to determine the actual APIC timer clock
+ * speed."
+ *
+ * We're actually using the IRQ0 timer. Hmm.
+ */
+void
+lapic_calibrate_timer(ci)
+ struct cpu_info *ci;
+{
+ unsigned int starttick, tick1, tick2, endtick;
+ unsigned int startapic, apic1, apic2, endapic;
+ u_int64_t dtick, dapic, tmp;
+ int i;
+
+ printf("%s: calibrating local timer\n", ci->ci_dev->dv_xname);
+
+ /*
+ * Configure timer to one-shot, interrupt masked,
+ * large positive number.
+ */
+ i82489_writereg (LAPIC_LVTT, LAPIC_LVTT_M);
+ i82489_writereg (LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
+ i82489_writereg (LAPIC_ICR_TIMER, 0x80000000);
+
+ starttick = gettick();
+ startapic = lapic_gettick();
+
+ for (i=0; i<hz; i++) {
+ DELAY(2);
+ do {
+ tick1 = gettick();
+ apic1 = lapic_gettick();
+ } while (tick1 < starttick);
+ DELAY(2);
+ do {
+ tick2 = gettick();
+ apic2 = lapic_gettick();
+ } while (tick2 > starttick);
+ }
+
+ endtick = gettick();
+ endapic = lapic_gettick();
+
+ dtick = hz * rtclock_tval + (starttick-endtick);
+ dapic = startapic-endapic;
+
+ /*
+ * there are TIMER_FREQ ticks per second.
+ * in dtick ticks, there are dapic bus clocks.
+ */
+ tmp = (TIMER_FREQ * dapic) / dtick;
+
+ lapic_per_second = tmp;
+
+ printf("%s: apic clock running at %lldHz\n", ci->ci_dev->dv_xname, tmp);
+
+ if (lapic_per_second != 0) {
+ /*
+ * reprogram the apic timer to run in periodic mode.
+ * XXX need to program timer on other cpu's, too.
+ */
+ lapic_tval = (lapic_per_second * 2) / hz;
+ lapic_tval = (lapic_tval / 2) + (lapic_tval & 0x1);
+
+ i82489_writereg (LAPIC_LVTT, LAPIC_LVTT_TM|LAPIC_LVTT_M
+ |LAPIC_TIMER_VECTOR);
+ i82489_writereg (LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
+ i82489_writereg (LAPIC_ICR_TIMER, lapic_tval);
+
+ /*
+ * Compute fixed-point ratios between cycles and
+ * microseconds to avoid having to do any division
+ * in lapic_delay and lapic_microtime.
+ */
+
+ tmp = (1000000 * (u_int64_t)1<<32) / lapic_per_second;
+ lapic_frac_usec_per_cycle = tmp;
+
+ tmp = (lapic_per_second * (u_int64_t)1<<32) / 1000000;
+
+ lapic_frac_cycle_per_usec = tmp;
+
+ /*
+ * Compute delay in cycles for likely short delays in usec.
+ */
+ for (i=0; i<26; i++)
+ lapic_delaytab[i] = (lapic_frac_cycle_per_usec * i) >>
+ 32;
+
+ /*
+ * Now that the timer's calibrated, use the apic timer routines
+ * for all our timing needs..
+ */
+ delay_func = lapic_delay;
+ initclock_func = lapic_initclocks;
+ }
+}
+
+/*
+ * delay for N usec.
+ */
+
+void
+lapic_delay(usec)
+ int usec;
+{
+ int32_t tick, otick;
+ int64_t deltat; /* XXX may want to be 64bit */
+
+ otick = lapic_gettick();
+
+ if (usec <= 0)
+ return;
+ if (usec <= 25)
+ deltat = lapic_delaytab[usec];
+ else
+ deltat = (lapic_frac_cycle_per_usec * usec) >> 32;
+
+ while (deltat > 0) {
+ tick = lapic_gettick();
+ if (tick > otick)
+ deltat -= lapic_tval - (tick - otick);
+ else
+ deltat -= otick - tick;
+ otick = tick;
+
+ x86_pause();
+ }
+}
+
+/*
+ * XXX the following belong mostly or partly elsewhere..
+ */
+
+int
+x86_ipi_init(target)
+ int target;
+{
+ unsigned j;
+
+ if ((target&LAPIC_DEST_MASK)==0) {
+ i82489_writereg(LAPIC_ICRHI, target<<LAPIC_ID_SHIFT);
+ }
+
+ i82489_writereg(LAPIC_ICRLO, (target & LAPIC_DEST_MASK) |
+ LAPIC_DLMODE_INIT | LAPIC_LVL_ASSERT );
+
+ for (j=100000; j > 0; j--)
+ if ((i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) == 0)
+ break;
+
+ delay(10000);
+
+ i82489_writereg(LAPIC_ICRLO, (target & LAPIC_DEST_MASK) |
+ LAPIC_DLMODE_INIT | LAPIC_LVL_TRIG | LAPIC_LVL_DEASSERT);
+
+ for (j=100000; j > 0; j--)
+ if ((i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) == 0)
+ break;
+
+ return (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY)?EBUSY:0;
+}
+
+int
+x86_ipi(vec,target,dl)
+ int vec,target,dl;
+{
+ unsigned j;
+ int result;
+
+ for (j=100000;
+ j > 0 && (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY);
+ j--)
+ ;
+
+ if ((target & LAPIC_DEST_MASK) == 0)
+ i82489_writereg(LAPIC_ICRHI, target << LAPIC_ID_SHIFT);
+
+ i82489_writereg(LAPIC_ICRLO,
+ (target & LAPIC_DEST_MASK) | vec | dl | LAPIC_LVL_ASSERT);
+
+ for (j=100000;
+ j > 0 && (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY);
+ j--)
+ ;
+
+ result = (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) ? EBUSY : 0;
+
+ return result;
+}
+
+
+/*
+ * Using 'pin numbers' as:
+ * 0 - timer
+ * 1 - unused
+ * 2 - PCINT
+ * 3 - LVINT0
+ * 4 - LVINT1
+ * 5 - LVERR
+ */
+
+void
+lapic_hwmask(struct pic *pic, int pin)
+{
+ int reg;
+ u_int32_t val;
+
+ reg = LAPIC_LVTT + (pin << 4);
+ val = i82489_readreg(reg);
+ val |= LAPIC_LVT_MASKED;
+ i82489_writereg(reg, val);
+}
+
+void
+lapic_hwunmask(struct pic *pic, int pin)
+{
+ int reg;
+ u_int32_t val;
+
+ reg = LAPIC_LVTT + (pin << 4);
+ val = i82489_readreg(reg);
+ val &= ~LAPIC_LVT_MASKED;
+ i82489_writereg(reg, val);
+}
+
+void
+lapic_setup(struct pic *pic, struct cpu_info *ci, int pin, int idtvec, int type)
+{
+}
diff --git a/sys/arch/amd64/amd64/locore.S b/sys/arch/amd64/amd64/locore.S
index a32e5de4edb..5270eb9df22 100644
--- a/sys/arch/amd64/amd64/locore.S
+++ b/sys/arch/amd64/amd64/locore.S
@@ -1,5 +1,4 @@
-/* $OpenBSD: locore.S,v 1.13 2004/06/22 01:16:50 art Exp $ */
-/* $NetBSD: locore.S,v 1.2 2003/04/26 19:34:45 fvdl Exp $ */
+/* $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $ */
/*
* Copyright-o-rama!
@@ -92,11 +91,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
@@ -184,7 +179,6 @@ _C_LABEL(lapic_isr):
.globl _C_LABEL(proc0paddr),_C_LABEL(PTDpaddr)
.globl _C_LABEL(biosbasemem),_C_LABEL(biosextmem)
.globl _C_LABEL(bootapiver)
- .globl _C_LABEL(gdtstore)
_C_LABEL(cpu): .long 0 # are we 386, 386sx, or 486,
# or Pentium, or..
_C_LABEL(cpu_id): .long 0 # saved from `cpuid' instruction
@@ -544,7 +538,7 @@ compat:
movl $RELOC(farjmp64),%eax
ljmp *(%eax)
- .code64
+.code64
longmode:
/*
* 6.
@@ -583,7 +577,7 @@ longmode_hi:
movq $NKL4_KIMG_ENTRIES,%rcx
leaq (PROC0_PML4_OFF)(%rsi),%rbx # old, phys address of PML4
- addq %r8, %rbx # new, virtual adress of PML4
+ addq %r8, %rbx # new, virtual address of PML4
1: movq $0,(%rbx)
addq $8,%rbx
loop 1b
@@ -721,38 +715,7 @@ NENTRY(switch_error3)
#endif /* DIAGNOSTIC */
/*
- * When no processes are on the runq, cpu_switch() branches to here to wait for
- * something to come ready.
- */
-ENTRY(idle)
-#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
- call _C_LABEL(sched_unlock_idle)
-#endif
- jmp idle_start
-idle_zero:
- sti
- call _C_LABEL(uvm_pageidlezero)
- jmp idle_start
-idle_loop:
- /* Try to zero some pages. */
- movl _C_LABEL(uvm)+UVM_PAGE_IDLE_ZERO(%rip),%ecx
- testl %ecx,%ecx
- jnz idle_zero
- sti
- hlt
-NENTRY(mpidle)
-idle_start:
- cli
- movl _C_LABEL(whichqs)(%rip),%ecx
- testl %ecx, %ecx
- jz idle_loop
-#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
- call _C_LABEL(sched_lock_idle)
-#endif
- jmp sw1
-
-/*
- * void cpu_switch(struct proc *)
+ * int cpu_switch(struct proc *)
* Find a runnable process and switch to it. Wait if necessary. If the new
* proc is the same as the old one, we short-circuit the context save and
* restore.
@@ -764,8 +727,6 @@ ENTRY(cpu_switch)
pushq %r13
pushq %r14
pushq %r15
- movl CPUVAR(ILEVEL), %ebx
- pushq %rbx
movq %rdi,%r13
@@ -776,10 +737,8 @@ ENTRY(cpu_switch)
* below and changes the priority. (See corresponding comment in
* userret()).
*/
- movq $0, CPUVAR(CURPROC)
+ movq $0,CPUVAR(CURPROC)
- movl $IPL_NONE, %edi
- call _C_LABEL(Xspllower)
/*
* First phase: find new proc.
@@ -793,15 +752,111 @@ ENTRY(cpu_switch)
* %r12 - new proc
*/
-switch_search:
/* Look for new proc. */
cli # splhigh doesn't do a cli
movl _C_LABEL(whichqs)(%rip),%ecx
+ bsfl %ecx,%r8d # find a full q
+ jnz switch_dequeue
-sw1: bsfl %ecx,%r8d # find a full q
- jz _C_LABEL(idle)
+ /*
+ * idling: save old context
+ *
+ * Registers:
+ * %rax, %rcx - scratch
+ * %r13 - old proc, then old pcb
+ * %r12 - idle pcb
+ */
+
+ /* old proc still in %rdi */
+ call _C_LABEL(pmap_deactivate)
+
+ movq P_ADDR(%r13),%r13
+
+ /* Save stack pointers */
+
+ movq %rsp,PCB_RSP(%r13)
+ movq %rbp,PCB_RBP(%r13)
+
+ /* Find idle PCB for this CPU */
+#ifndef MULTIPROCESSOR
+ leaq _C_LABEL(proc0)(%rip),%rcx
+ movq P_ADDR(%rcx),%r12
+ movl P_MD_TSS_SEL(%rcx),%edx
+#else
+ movq CPUVAR(IDLE_PCB),%r12
+ movl CPUVAR(IDLE_TSS_SEL),%edx
+#endif
+ movq $0,CPUVAR(CURPROC)
+
+ /* Restore the idle context (avoid interrupts) */
+ cli
+
+ /* Restore stack pointers. */
+ movq PCB_RSP(%r12),%rsp
+ movq PCB_RBP(%r12),%rbp
+
+ /* Switch address space. */
+ movq PCB_CR3(%r12),%rcx
+ movq %rcx,%cr3
+
+#ifdef MULTIPROCESSOR
+ movq CPUVAR(GDT),%rax
+#else
+ movq _C_LABEL(gdtstore)(%rip),%rax
+#endif
+
+ /* Switch TSS. Reset "task busy" flag before */
+ andl $~0x0200,4(%rax,%rdx, 1)
+ ltr %dx
+
+ /* Restore cr0 (including FPU state). */
+ movl PCB_CR0(%r12),%ecx
+ movq %rcx,%cr0
+
+ SET_CURPCB(%r12)
+
+ xorq %r13,%r13
+ sti
+idle_unlock:
+#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
+ call _C_LABEL(sched_unlock_idle)
+#endif
+ /* Interrupts are okay again. */
+ movl $IPL_NONE,%edi
+ call _C_LABEL(Xspllower)
+ jmp idle_start
+idle_zero:
+ sti
+ call _C_LABEL(uvm_pageidlezero)
+ cli
+ cmpl $0,_C_LABEL(whichqs)(%rip)
+ jnz idle_exit
+idle_loop:
+ /* Try to zero some pages. */
+ movl _C_LABEL(uvm)+UVM_PAGE_IDLE_ZERO(%rip),%ecx
+ testl %ecx,%ecx
+ jnz idle_zero
+ sti
+ hlt
+NENTRY(mpidle)
+idle_start:
+ cli
+ cmpl $0,_C_LABEL(whichqs)(%rip)
+ jz idle_loop
+idle_exit:
+ movl $IPL_HIGH,CPUVAR(ILEVEL)
+ sti
+#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
+ call _C_LABEL(sched_lock_idle)
+#endif
+switch_search:
+ movl _C_LABEL(whichqs)(%rip),%ecx
+ bsfl %ecx,%r8d
+ jz idle_unlock
switch_dequeue:
+
+ sti
movq %r8,%r9
shlq $4, %r9
@@ -842,10 +897,8 @@ switch_resume:
movb $SONPROC,P_STAT(%r12) # p->p_stat = SONPROC
SET_CURPROC(%r12,%rcx)
- sti
-
/* Skip context switch if same proc. */
- movl $1,%eax
+ xorl %ebx,%ebx
cmpq %r12,%r13
je switch_return
@@ -862,6 +915,9 @@ switch_resume:
* %r12 - new proc
*/
+ movq %r13,%rdi
+ call pmap_deactivate
+
movq P_ADDR(%r13),%r13
/* Save stack pointers. */
@@ -900,16 +956,13 @@ switch_exited:
#endif
movl P_MD_TSS_SEL(%r12),%edx
- /* Switch address space. */
- movq PCB_CR3(%r13),%rcx
- movq %rcx,%cr3
-
/* Switch TSS. Reset "task busy" flag before */
andl $~0x0200,4(%rax,%rdx, 1)
ltr %dx
- movq PCB_LDT_SEL(%r13),%rcx
- lldt %cx
+ movq %r12,%rdi
+ call _C_LABEL(pmap_activate)
+
#if 0
switch_restored:
#endif
@@ -933,12 +986,12 @@ switch_return:
#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
call _C_LABEL(sched_unlock_idle)
#endif
- /*
- * Restore old cpl from stack. Note that this is always an increase,
- * due to the spl0() on entry.
- */
- popq %rbx
- movl %ebx, CPUVAR(ILEVEL)
+
+ movl $IPL_NONE,%edi
+ call _C_LABEL(Xspllower)
+ movl $IPL_HIGH,CPUVAR(ILEVEL)
+
+ movl %ebx,%eax
popq %r15
popq %r14
@@ -1027,7 +1080,7 @@ ENTRY(switch_exit)
call *%rsi
/* Jump into cpu_switch() with the right state. */
- xorq %r13, %r13
+ xorq %r13,%r13
movq %r13, CPUVAR(CURPROC)
jmp switch_search
@@ -1083,6 +1136,7 @@ IDTVEC(syscall)
movq CPUVAR(CURPROC),%r14
movq %rsp,P_MD_REGS(%r14) # save pointer to frame
andl $~MDP_IRET,P_MD_FLAGS(%r14)
+ movq %rsp,%rdi
call _C_LABEL(syscall)
1: /* Check for ASTs on exit to user mode. */
cli
@@ -1092,6 +1146,7 @@ IDTVEC(syscall)
CLEAR_ASTPENDING(%r11)
sti
/* Pushed T_ASTFLT into tf_trapno on entry. */
+ movq %rsp,%rdi
call _C_LABEL(trap)
jmp 1b
2:
@@ -1100,8 +1155,7 @@ IDTVEC(syscall)
jne iret_return;
syscall_return:
#ifdef DIAGNOSTIC
- movl CPUVAR(ILEVEL), %r8d
- testl %r8d, %r8d
+ cmpl $IPL_NONE,CPUVAR(ILEVEL)
jne 3f
#endif
/*
@@ -1109,15 +1163,17 @@ syscall_return:
*/
cli
swapgs
- movw TF_GS(%rsp),%gs
- movw TF_FS(%rsp),%fs
movw TF_ES(%rsp),%es
+ movw TF_FS(%rsp),%fs
+ movw TF_GS(%rsp),%gs
INTR_RESTORE_GPRS
+ movw $(LSEL(LUDATA_SEL, SEL_UPL)),%r11
+ movw %r11,%ds
addq $48,%rsp
popq %rcx /* return rip */
addq $8,%rsp
popq %r11 /* flags as set by sysret insn */
- movq (%rsp),%rsp
+ movq %ss:(%rsp),%rsp
sysretq
#ifdef DIAGNOSTIC
@@ -1125,6 +1181,7 @@ syscall_return:
movl TF_RAX(%rsp),%esi
movl TF_RDI(%rsp),%edx
movl %ebx,%ecx
+ movl CPUVAR(ILEVEL),%r8d
xorq %rax,%rax
call _C_LABEL(printf)
#ifdef DDB
@@ -1157,8 +1214,10 @@ NENTRY(child_trampoline)
.globl _C_LABEL(osyscall_return)
+/* XXX - can we zap the following two? */
+
/*
- * Old call gate entry for syscall. XXXfvdl: only needed if we're
+ * Old call gate entry for syscall. only needed if we're
* going to support running old NetBSD or ibcs2 binaries, etc,
* on NetBSD/amd64.
*/
@@ -1180,6 +1239,7 @@ osyscall1:
sti
movq CPUVAR(CURPROC),%rdx
movq %rsp,P_MD_REGS(%rdx) # save pointer to frame
+ movq %rsp,%rdi
call _C_LABEL(syscall)
_C_LABEL(osyscall_return):
2: /* Check for ASTs on exit to user mode. */
@@ -1190,8 +1250,10 @@ _C_LABEL(osyscall_return):
CLEAR_ASTPENDING(%r11)
sti
/* Pushed T_ASTFLT into tf_trapno on entry. */
+ movq %rsp,%rdi
call _C_LABEL(trap)
jmp 2b
+
iret_return:
#ifndef DIAGNOSTIC
1: INTRFASTEXIT
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index 7516289ac0b..e0caab7883e 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.25 2004/06/22 01:16:50 art Exp $ */
+/* $OpenBSD: machdep.c,v 1.26 2004/06/25 11:03:27 art Exp $ */
/* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
/*-
@@ -201,6 +201,10 @@ pid_t sigpid = 0;
extern paddr_t avail_start, avail_end;
+void (*delay_func)(int) = i8254_delay;
+void (*microtime_func)(struct timeval *) = i8254_microtime;
+void (*initclock_func)(void) = i8254_initclocks;
+
struct mtrr_funcs *mtrr_funcs;
/*
@@ -1793,33 +1797,11 @@ cpu_dump_mempagecnt()
return (n);
}
-#if 0
-extern void i8254_microtime(struct timeval *tv);
-
-/*
- * XXXXXXX
- * the simulator's 8254 seems to travel backward in time sometimes?
- * work around this with this hideous code. Unacceptable for
- * real hardware, but this is just a patch to stop the weird
- * effects. SMP unsafe, etc.
- */
void
-microtime(struct timeval *tv)
+cpu_initclocks(void)
{
- static struct timeval mtv;
-
- i8254_microtime(tv);
- if (tv->tv_sec <= mtv.tv_sec && tv->tv_usec < mtv.tv_usec) {
- mtv.tv_usec++;
- if (mtv.tv_usec > 1000000) {
- mtv.tv_sec++;
- mtv.tv_usec = 0;
- }
- *tv = mtv;
- } else
- mtv = *tv;
+ (*initclock_func)();
}
-#endif
void
need_resched(struct cpu_info *ci)
diff --git a/sys/arch/amd64/amd64/microtime.S b/sys/arch/amd64/amd64/microtime.S
index ce3c24f01e6..4e245266772 100644
--- a/sys/arch/amd64/amd64/microtime.S
+++ b/sys/arch/amd64/amd64/microtime.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: microtime.S,v 1.3 2004/03/22 19:43:29 nordin Exp $ */
+/* $OpenBSD: microtime.S,v 1.4 2004/06/25 11:03:27 art Exp $ */
/* $NetBSD: microtime.S,v 1.1 2003/04/26 18:39:30 fvdl Exp $ */
/*-
@@ -43,7 +43,7 @@
#define IRQ_BIT(irq_num) (1 << ((irq_num) & 7))
#define IRQ_BYTE(irq_num) ((irq_num) >> 3)
-ENTRY(microtime)
+ENTRY(i8254_microtime)
# clear registers and do whatever we can up front
xorl %edx,%edx
movl $(TIMER_SEL0|TIMER_LATCH),%eax
diff --git a/sys/arch/amd64/amd64/mpbios.c b/sys/arch/amd64/amd64/mpbios.c
new file mode 100644
index 00000000000..e9b8cd67f86
--- /dev/null
+++ b/sys/arch/amd64/amd64/mpbios.c
@@ -0,0 +1,1108 @@
+/* $OpenBSD: mpbios.c,v 1.1 2004/06/25 11:03:27 art Exp $ */
+/* $NetBSD: mpbios.c,v 1.7 2003/05/15 16:32:50 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by RedBack Networks Inc.
+ *
+ * Author: Bill Sommerfeld
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999 Stefan Grefen
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Derived from FreeBSD's mp_machdep.c
+ */
+/*
+ * Copyright (c) 1996, by Steve Passe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * The Intel MP-stuff is just one way of x86 SMP systems
+ * so only Intel MP specific stuff is here.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/specialreg.h>
+#include <machine/cpuvar.h>
+#include <machine/bus.h>
+#include <machine/mpbiosvar.h>
+
+#include <machine/i82093reg.h>
+#include <machine/i82093var.h>
+#include <machine/i82489reg.h>
+#include <machine/i82489var.h>
+
+#include <dev/isa/isareg.h>
+
+#ifdef X86_MPBIOS_SUPPORT_EISA
+#include <dev/eisa/eisavar.h> /* for ELCR* def'ns */
+#endif
+
+
+static struct mpbios_ioapic default_ioapic = {
+ 2, 0, 1, IOAPICENTRY_FLAG_EN, (u_int32_t)IOAPIC_BASE_DEFAULT
+};
+
+/* descriptions of MP basetable entries */
+struct mpbios_baseentry {
+ u_int8_t type;
+ u_int8_t length;
+ u_int16_t count;
+ const char *name;
+};
+
+static const char *loc_where[] = {
+ "extended bios data area",
+ "last page of base memory",
+ "bios"
+};
+
+struct mp_map
+{
+ vaddr_t baseva;
+ int vsize;
+ paddr_t pa;
+ paddr_t pg;
+ int psize;
+};
+
+int mp_print(void *, const char *);
+int mp_match(struct device *, void *,void *);
+const void *mpbios_search(struct device *, paddr_t, int, struct mp_map *);
+static __inline int mpbios_cksum(const void *,int);
+
+void mp_cfg_special_intr(const struct mpbios_int *, u_int32_t *);
+void mp_print_special_intr(int intr);
+
+void mp_cfg_pci_intr(const struct mpbios_int *, u_int32_t *);
+void mp_print_pci_intr(int intr);
+
+#ifdef X86_MPBIOS_SUPPORT_EISA
+void mp_print_eisa_intr(int intr);
+void mp_cfg_eisa_intr(const struct mpbios_int *, u_int32_t *);
+#endif
+
+void mp_cfg_isa_intr(const struct mpbios_int *, u_int32_t *);
+void mp_print_isa_intr (int intr);
+
+void mpbios_cpu(const u_int8_t *, struct device *);
+void mpbios_bus(const u_int8_t *, struct device *);
+void mpbios_ioapic(const u_int8_t *, struct device *);
+void mpbios_int(const u_int8_t *, int, struct mp_intr_map *);
+
+const void *mpbios_map(paddr_t, int, struct mp_map *);
+void mpbios_unmap(struct mp_map *);
+
+/*
+ * globals to help us bounce our way through parsing the config table.
+ */
+
+static struct mp_map mp_cfg_table_map;
+static struct mp_map mp_fp_map;
+const struct mpbios_cth *mp_cth;
+const struct mpbios_fps *mp_fps;
+
+int mpbios_scanned;
+
+int
+mp_print(aux, pnp)
+ void *aux;
+ const char *pnp;
+{
+ struct cpu_attach_args * caa = (struct cpu_attach_args *) aux;
+ if (pnp)
+ printf("%s at %s:",caa->caa_name, pnp);
+ return (UNCONF);
+}
+
+int
+mp_match(parent, cfv, aux)
+ struct device *parent;
+ void *cfv;
+ void *aux;
+{
+ struct cfdata *cf = (struct cfdata *)cfv;
+ struct cpu_attach_args * caa = (struct cpu_attach_args *) aux;
+ if (strcmp(caa->caa_name, cf->cf_driver->cd_name))
+ return 0;
+
+ return ((*cf->cf_attach->ca_match)(parent, cf, aux));
+}
+
+/*
+ * Map a chunk of memory read-only and return an appropraitely
+ * const'ed pointer.
+ */
+
+const void *
+mpbios_map(pa, len, handle)
+ paddr_t pa;
+ int len;
+ struct mp_map *handle;
+{
+ paddr_t pgpa = x86_trunc_page(pa);
+ paddr_t endpa = x86_round_page(pa + len);
+ vaddr_t va = uvm_km_valloc(kernel_map, endpa - pgpa);
+ vaddr_t retva = va + (pa & PGOFSET);
+
+ handle->pa = pa;
+ handle->pg = pgpa;
+ handle->psize = len;
+ handle->baseva = va;
+ handle->vsize = endpa-pgpa;
+
+ do {
+ pmap_kenter_pa (va, pgpa, VM_PROT_READ);
+ va += PAGE_SIZE;
+ pgpa += PAGE_SIZE;
+ } while (pgpa < endpa);
+
+ return (const void *)retva;
+}
+
+void
+mpbios_unmap(handle)
+ struct mp_map *handle;
+{
+ pmap_kremove (handle->baseva, handle->vsize);
+ uvm_km_free (kernel_map, handle->baseva, handle->vsize);
+}
+
+/*
+ * Look for an Intel MP spec table, indicating SMP capable hardware.
+ */
+int
+mpbios_probe(self)
+ struct device *self;
+{
+ paddr_t ebda, memtop;
+
+ paddr_t cthpa;
+ int cthlen;
+ const u_int8_t *mpbios_page;
+ int scan_loc;
+
+ struct mp_map t;
+
+ /* see if EBDA exists */
+
+ mpbios_page = mpbios_map (0, PAGE_SIZE, &t);
+
+ ebda = *(const u_int16_t *) (&mpbios_page[0x40e]);
+ ebda <<= 4;
+
+ memtop = *(const u_int16_t *) (&mpbios_page[0x413]);
+ memtop <<= 10;
+
+ mpbios_page = NULL;
+ mpbios_unmap(&t);
+
+ scan_loc = 0;
+
+ if (ebda && ebda < IOM_BEGIN ) {
+ mp_fps = mpbios_search(self, ebda, 1024, &mp_fp_map);
+ if (mp_fps != NULL)
+ goto found;
+ }
+
+ scan_loc = 1;
+
+ if (memtop && memtop <= IOM_BEGIN ) {
+ mp_fps = mpbios_search(self, memtop - 1024, 1024, &mp_fp_map);
+ if (mp_fps != NULL)
+ goto found;
+ }
+
+ scan_loc = 2;
+
+ mp_fps = mpbios_search(self, BIOS_BASE, BIOS_COUNT, &mp_fp_map);
+ if (mp_fps != NULL)
+ goto found;
+
+ /* nothing found */
+ return 0;
+
+ found:
+ if (mp_verbose)
+ printf("%s: MP floating pointer found in %s at 0x%lx\n",
+ self->dv_xname, loc_where[scan_loc], mp_fp_map.pa);
+
+ if (mp_fps->pap == 0) {
+ if (mp_fps->mpfb1 == 0) {
+ printf("%s: MP fps invalid: "
+ "no default config and no configuration table\n",
+ self->dv_xname);
+
+ goto err;
+ }
+ printf("%s: MP default configuration %d\n",
+ self->dv_xname, mp_fps->mpfb1);
+ return 10;
+ }
+
+ cthpa = mp_fps->pap;
+
+ mp_cth = mpbios_map (cthpa, sizeof (*mp_cth), &mp_cfg_table_map);
+ cthlen = mp_cth->base_len;
+ mpbios_unmap(&mp_cfg_table_map);
+
+ mp_cth = mpbios_map (cthpa, cthlen, &mp_cfg_table_map);
+
+ if (mp_verbose)
+ printf("%s: MP config table at 0x%lx, %d bytes long\n",
+ self->dv_xname, cthpa, cthlen);
+
+ if (mp_cth->signature != MP_CT_SIG) {
+ printf("%s: MP signature mismatch (%x vs %x)\n",
+ self->dv_xname,
+ MP_CT_SIG, mp_cth->signature);
+ goto err;
+ }
+
+ if (mpbios_cksum(mp_cth, cthlen)) {
+ printf ("%s: MP Configuration Table checksum mismatch\n",
+ self->dv_xname);
+ goto err;
+ }
+ return 10;
+ err:
+ if (mp_fps) {
+ mp_fps = NULL;
+ mpbios_unmap(&mp_fp_map);
+ }
+ if (mp_cth) {
+ mp_cth = NULL;
+ mpbios_unmap(&mp_cfg_table_map);
+ }
+ return 0;
+}
+
+
+/*
+ * Simple byte checksum used on config tables.
+ */
+
+static __inline int
+mpbios_cksum (start, len)
+ const void *start;
+ int len;
+{
+ unsigned char res=0;
+ const char *p = start;
+ const char *end = p + len;
+
+ while (p < end)
+ res += *p++;
+
+ return res;
+}
+
+
+/*
+ * Look for the MP floating pointer signature in the given physical
+ * address range.
+ *
+ * We map the memory, scan through it, and unmap it.
+ * If we find it, remap the floating pointer structure and return it.
+ */
+
+const void *
+mpbios_search (self, start, count, map)
+ struct device *self;
+ paddr_t start;
+ int count;
+ struct mp_map *map;
+{
+ struct mp_map t;
+
+ int i, len;
+ const struct mpbios_fps *m;
+ int end = count - sizeof(*m);
+ const u_int8_t *base = mpbios_map (start, count, &t);
+
+ if (mp_verbose)
+ printf("%s: scanning 0x%lx to 0x%lx for MP signature\n",
+ self->dv_xname, start, start+count-sizeof(*m));
+
+ for (i = 0; i <= end; i += 4) {
+ m = (struct mpbios_fps *)&base[i];
+
+ if ((m->signature == MP_FP_SIG) &&
+ ((len = m->length << 4) != 0) &&
+ mpbios_cksum(m, (m->length << 4)) == 0) {
+
+ mpbios_unmap (&t);
+
+ return mpbios_map (start+i, len, map);
+ }
+ }
+ mpbios_unmap(&t);
+
+ return 0;
+}
+
+/*
+ * MP configuration table parsing.
+ */
+
+static struct mpbios_baseentry mp_conf[] =
+{
+ {0, 20, 0, "cpu"},
+ {1, 8, 0, "bus"},
+ {2, 8, 0, "ioapic"},
+ {3, 8, 0, "ioint"},
+ {4, 8, 0, "lint"},
+};
+
+static struct mp_bus extint_bus = {
+ "ExtINT",
+ -1,
+ mp_print_special_intr,
+ mp_cfg_special_intr,
+ 0
+};
+static struct mp_bus smi_bus = {
+ "SMI",
+ -1,
+ mp_print_special_intr,
+ mp_cfg_special_intr,
+ 0
+};
+static struct mp_bus nmi_bus = {
+ "NMI",
+ -1,
+ mp_print_special_intr,
+ mp_cfg_special_intr,
+ 0
+};
+
+
+/*
+ * 1st pass on BIOS's Intel MP specification table.
+ *
+ * initializes:
+ * mp_ncpus = 1
+ *
+ * determines:
+ * cpu_apic_address (common to all CPUs)
+ * ioapic_address[N]
+ * mp_naps
+ * mp_nbusses
+ * mp_napics
+ * nintrs
+ */
+void
+mpbios_scan(self)
+ struct device *self;
+{
+ const u_int8_t *position, *end;
+ int count;
+ int type;
+ int intr_cnt, cur_intr;
+ paddr_t lapic_base;
+ const struct mpbios_int *iep;
+ struct mpbios_int ie;
+ struct ioapic_softc *sc;
+
+ printf ("%s: Intel MP Specification ", self->dv_xname);
+
+ switch (mp_fps->spec_rev) {
+ case 1:
+ printf("(Version 1.1)");
+ break;
+ case 4:
+ printf("(Version 1.4)");
+ break;
+ default:
+ printf("(unrecognized rev %d)", mp_fps->spec_rev);
+ }
+
+ /*
+ * looks like we've got a MP system. start setting up
+ * infrastructure..
+ * XXX is this the right place??
+ */
+
+ lapic_base = LAPIC_BASE;
+ if (mp_cth != NULL)
+ lapic_base = (paddr_t)mp_cth->apic_address;
+
+ lapic_boot_init(lapic_base);
+
+ /* check for use of 'default' configuration */
+ if (mp_fps->mpfb1 != 0) {
+ struct mpbios_proc pe;
+
+ printf("\n%s: MP default configuration %d\n",
+ self->dv_xname, mp_fps->mpfb1);
+
+ /* use default addresses */
+ pe.apic_id = lapic_cpu_number();
+ pe.cpu_flags = PROCENTRY_FLAG_EN|PROCENTRY_FLAG_BP;
+ pe.cpu_signature = cpu_info_primary.ci_signature;
+ pe.feature_flags = cpu_info_primary.ci_feature_flags;
+
+ mpbios_cpu((u_int8_t *)&pe, self);
+
+ pe.apic_id = 1 - lapic_cpu_number();
+ pe.cpu_flags = PROCENTRY_FLAG_EN;
+
+ mpbios_cpu((u_int8_t *)&pe, self);
+
+ mpbios_ioapic((u_int8_t *)&default_ioapic, self);
+
+ /* XXX */
+ printf("%s: WARNING: interrupts not configured\n",
+ self->dv_xname);
+ panic("lazy bum");
+ return;
+ } else {
+ /*
+ * should not happen; mp_probe returns 0 in this case,
+ * but..
+ */
+ if (mp_cth == NULL)
+ panic ("mpbios_scan: no config (can't happen?)");
+
+ printf(" (%8.8s %12.12s)\n",
+ mp_cth->oem_id, mp_cth->product_id);
+
+ /*
+ * Walk the table once, counting items
+ */
+ position = (const u_int8_t *)(mp_cth);
+ end = position + mp_cth->base_len;
+ position += sizeof(*mp_cth);
+
+ count = mp_cth->entry_count;
+ intr_cnt = 0;
+
+ while ((count--) && (position < end)) {
+ type = *position;
+ if (type >= MPS_MCT_NTYPES) {
+ printf("%s: unknown entry type %x"
+ " in MP config table\n",
+ self->dv_xname, type);
+ break;
+ }
+ mp_conf[type].count++;
+ if (type == MPS_MCT_BUS) {
+ const struct mpbios_bus *bp =
+ (const struct mpbios_bus *)position;
+ if (bp->bus_id >= mp_nbus)
+ mp_nbus = bp->bus_id + 1;
+ }
+ /*
+ * Count actual interrupt instances.
+ * dst_apic_id of MPS_ALL_APICS means "wired to all
+ * apics of this type".
+ */
+ if (type == MPS_MCT_IOINT) {
+ iep = (const struct mpbios_int *)position;
+ if (iep->dst_apic_id == MPS_ALL_APICS)
+ intr_cnt +=
+ mp_conf[MPS_MCT_IOAPIC].count;
+ else
+ intr_cnt++;
+ } else if (type == MPS_MCT_LINT)
+ intr_cnt++;
+ position += mp_conf[type].length;
+ }
+
+ mp_busses = malloc(sizeof(struct mp_bus)*mp_nbus,
+ M_DEVBUF, M_NOWAIT);
+ memset(mp_busses, 0, sizeof(struct mp_bus) * mp_nbus);
+ mp_intrs = malloc(sizeof(struct mp_intr_map)*intr_cnt,
+ M_DEVBUF, M_NOWAIT);
+ mp_nintr = intr_cnt;
+
+ /* re-walk the table, recording info of interest */
+ position = (const u_int8_t *) mp_cth + sizeof(*mp_cth);
+ count = mp_cth->entry_count;
+ cur_intr = 0;
+
+ while ((count--) && (position < end)) {
+ switch (type = *(u_char *) position) {
+ case MPS_MCT_CPU:
+ mpbios_cpu(position, self);
+ break;
+ case MPS_MCT_BUS:
+ mpbios_bus(position, self);
+ break;
+ case MPS_MCT_IOAPIC:
+ mpbios_ioapic(position, self);
+ break;
+ case MPS_MCT_IOINT:
+ iep = (const struct mpbios_int *)position;
+ ie = *iep;
+ if (iep->dst_apic_id == MPS_ALL_APICS) {
+ for (sc = ioapics ; sc != NULL;
+ sc = sc->sc_next) {
+ ie.dst_apic_id = sc->sc_apicid;
+ mpbios_int((char *)&ie, type,
+ &mp_intrs[cur_intr++]); }
+ } else {
+ mpbios_int(position, type,
+ &mp_intrs[cur_intr++]);
+ }
+ break;
+ case MPS_MCT_LINT:
+ mpbios_int(position, type,
+ &mp_intrs[cur_intr]);
+ cur_intr++;
+ break;
+ default:
+ printf("%s: unknown entry type %x in MP config table\n",
+ self->dv_xname, type);
+ /* NOTREACHED */
+ return;
+ }
+
+ (u_char*)position += mp_conf[type].length;
+ }
+ if (mp_verbose && mp_cth->ext_len)
+ printf("%s: MP WARNING: %d bytes of extended entries not examined\n",
+ self->dv_xname,
+ mp_cth->ext_len);
+ }
+ /* Clean up. */
+ mp_fps = NULL;
+ mpbios_unmap (&mp_fp_map);
+ if (mp_cth != NULL) {
+ mp_cth = NULL;
+ mpbios_unmap (&mp_cfg_table_map);
+ }
+ mpbios_scanned = 1;
+}
+
+void
+mpbios_cpu(ent, self)
+ const u_int8_t *ent;
+ struct device *self;
+{
+ const struct mpbios_proc *entry = (const struct mpbios_proc *)ent;
+ struct cpu_attach_args caa;
+
+ /* XXX move this into the CPU attachment goo. */
+ /* check for usability */
+ if (!(entry->cpu_flags & PROCENTRY_FLAG_EN))
+ return;
+
+ /* check for BSP flag */
+ if (entry->cpu_flags & PROCENTRY_FLAG_BP)
+ caa.cpu_role = CPU_ROLE_BP;
+ else
+ caa.cpu_role = CPU_ROLE_AP;
+
+ caa.caa_name = "cpu";
+ caa.cpu_number = entry->apic_id;
+ caa.cpu_func = &mp_cpu_funcs;
+
+ config_found_sm(self, &caa, mp_print, mp_match);
+}
+
+/*
+ * The following functions conspire to compute base ioapic redirection
+ * table entry for a given interrupt line.
+ *
+ * Fill in: trigger mode, polarity, and possibly delivery mode.
+ */
+void mp_cfg_special_intr (entry, redir)
+ const struct mpbios_int *entry;
+ u_int32_t *redir;
+{
+
+ /*
+ * All of these require edge triggered, zero vector,
+ * appropriate delivery mode.
+ * see page 13 of the 82093AA datasheet.
+ */
+ *redir &= ~IOAPIC_REDLO_DEL_MASK;
+ *redir &= ~IOAPIC_REDLO_VECTOR_MASK;
+ *redir &= ~IOAPIC_REDLO_LEVEL;
+
+ switch (entry->int_type) {
+ case MPS_INTTYPE_NMI:
+ *redir |= (IOAPIC_REDLO_DEL_NMI<<IOAPIC_REDLO_DEL_SHIFT);
+ break;
+
+ case MPS_INTTYPE_SMI:
+ *redir |= (IOAPIC_REDLO_DEL_SMI<<IOAPIC_REDLO_DEL_SHIFT);
+ break;
+ case MPS_INTTYPE_ExtINT:
+ /*
+ * We are using the ioapic in "native" mode.
+ * This indicates where the 8259 is wired to the ioapic
+ * and/or local apic..
+ */
+ *redir |= (IOAPIC_REDLO_DEL_EXTINT<<IOAPIC_REDLO_DEL_SHIFT);
+ *redir |= (IOAPIC_REDLO_MASK);
+ break;
+ default:
+ panic("unknown MPS interrupt type %d", entry->int_type);
+ }
+}
+
+/* XXX too much duplicated code here. */
+
+void mp_cfg_pci_intr (entry, redir)
+ const struct mpbios_int *entry;
+ u_int32_t *redir;
+{
+ int mpspo = entry->int_flags & 0x03; /* XXX magic */
+ int mpstrig = (entry->int_flags >> 2) & 0x03; /* XXX magic */
+
+ *redir &= ~IOAPIC_REDLO_DEL_MASK;
+ switch (mpspo) {
+ case MPS_INTPO_ACTHI:
+ *redir &= ~IOAPIC_REDLO_ACTLO;
+ break;
+ case MPS_INTPO_DEF:
+ case MPS_INTPO_ACTLO:
+ *redir |= IOAPIC_REDLO_ACTLO;
+ break;
+ default:
+ panic("unknown MPS interrupt polarity %d", mpspo);
+ }
+
+ if (entry->int_type != MPS_INTTYPE_INT) {
+ mp_cfg_special_intr(entry, redir);
+ return;
+ }
+ *redir |= (IOAPIC_REDLO_DEL_LOPRI<<IOAPIC_REDLO_DEL_SHIFT);
+
+ switch (mpstrig) {
+ case MPS_INTTR_DEF:
+ case MPS_INTTR_LEVEL:
+ *redir |= IOAPIC_REDLO_LEVEL;
+ break;
+ case MPS_INTTR_EDGE:
+ *redir &= ~IOAPIC_REDLO_LEVEL;
+ break;
+ default:
+ panic("unknown MPS interrupt trigger %d", mpstrig);
+ }
+}
+
+#ifdef X86_MPBIOS_SUPPORT_EISA
+void mp_cfg_eisa_intr (entry, redir)
+ const struct mpbios_int *entry;
+ u_int32_t *redir;
+{
+ int mpspo = entry->int_flags & 0x03; /* XXX magic */
+ int mpstrig = (entry->int_flags >> 2) & 0x03; /* XXX magic */
+
+ *redir &= ~IOAPIC_REDLO_DEL_MASK;
+ switch (mpspo) {
+ case MPS_INTPO_DEF:
+ case MPS_INTPO_ACTHI:
+ *redir &= ~IOAPIC_REDLO_ACTLO;
+ break;
+ case MPS_INTPO_ACTLO:
+ *redir |= IOAPIC_REDLO_ACTLO;
+ break;
+ default:
+ panic("unknown MPS interrupt polarity %d", mpspo);
+ }
+
+ if (entry->int_type != MPS_INTTYPE_INT) {
+ mp_cfg_special_intr(entry, redir);
+ return;
+ }
+ *redir |= (IOAPIC_REDLO_DEL_LOPRI<<IOAPIC_REDLO_DEL_SHIFT);
+
+ switch (mpstrig) {
+ case MPS_INTTR_LEVEL:
+ *redir |= IOAPIC_REDLO_LEVEL;
+ break;
+ case MPS_INTTR_EDGE:
+ *redir &= ~IOAPIC_REDLO_LEVEL;
+ break;
+ case MPS_INTTR_DEF:
+ /*
+ * Set "default" setting based on ELCR value snagged
+ * earlier.
+ */
+ if (mp_busses[entry->src_bus_id].mb_data &
+ (1<<entry->src_bus_irq)) {
+ *redir |= IOAPIC_REDLO_LEVEL;
+ } else {
+ *redir &= ~IOAPIC_REDLO_LEVEL;
+ }
+ break;
+ default:
+ panic("unknown MPS interrupt trigger %d", mpstrig);
+ }
+}
+#endif
+
+
+void mp_cfg_isa_intr (entry, redir)
+ const struct mpbios_int *entry;
+ u_int32_t *redir;
+{
+ int mpspo = entry->int_flags & 0x03; /* XXX magic */
+ int mpstrig = (entry->int_flags >> 2) & 0x03; /* XXX magic */
+
+ *redir &= ~IOAPIC_REDLO_DEL_MASK;
+ switch (mpspo) {
+ case MPS_INTPO_DEF:
+ case MPS_INTPO_ACTHI:
+ *redir &= ~IOAPIC_REDLO_ACTLO;
+ break;
+ case MPS_INTPO_ACTLO:
+ *redir |= IOAPIC_REDLO_ACTLO;
+ break;
+ default:
+ panic("unknown MPS interrupt polarity %d", mpspo);
+ }
+
+ if (entry->int_type != MPS_INTTYPE_INT) {
+ mp_cfg_special_intr(entry, redir);
+ return;
+ }
+ *redir |= (IOAPIC_REDLO_DEL_LOPRI<<IOAPIC_REDLO_DEL_SHIFT);
+
+ switch (mpstrig) {
+ case MPS_INTTR_LEVEL:
+ *redir |= IOAPIC_REDLO_LEVEL;
+ break;
+ case MPS_INTTR_DEF:
+ case MPS_INTTR_EDGE:
+ *redir &= ~IOAPIC_REDLO_LEVEL;
+ break;
+ default:
+ panic("unknown MPS interrupt trigger %d", mpstrig);
+ }
+}
+
+void
+mp_print_special_intr (intr)
+ int intr;
+{
+}
+
+void
+mp_print_pci_intr (intr)
+ int intr;
+{
+ printf(" device %d INT_%c", (intr>>2)&0x1f, 'A' + (intr & 0x3));
+}
+
+void
+mp_print_isa_intr (intr)
+ int intr;
+{
+ printf(" irq %d", intr);
+}
+
+#ifdef X86_MPBIOS_SUPPORT_EISA
+void
+mp_print_eisa_intr (intr)
+ int intr;
+{
+ printf(" EISA irq %d", intr);
+}
+#endif
+
+
+
+#define TAB_UNIT 4
+#define TAB_ROUND(a) _TAB_ROUND(a, TAB_UNIT)
+
+#define _TAB_ROUND(a,u) (((a) + (u - 1)) & ~(u-1))
+#define EXTEND_TAB(a,u) (!(_TAB_ROUND(a,u) == _TAB_ROUND((a+1),u)))
+
+void
+mpbios_bus(ent, self)
+ const u_int8_t *ent;
+ struct device *self;
+{
+ const struct mpbios_bus *entry = (const struct mpbios_bus *)ent;
+ int bus_id = entry->bus_id;
+
+ printf("mpbios: bus %d is type %6.6s\n", bus_id, entry->bus_type);
+
+#ifdef DIAGNOSTIC
+ /*
+ * This "should not happen" unless the table changes out
+ * from underneath us
+ */
+ if (bus_id >= mp_nbus) {
+ panic("mpbios: bus number %d out of range?? (type %6.6s)\n",
+ bus_id, entry->bus_type);
+ }
+#endif
+
+ mp_busses[bus_id].mb_intrs = NULL;
+
+ if (memcmp(entry->bus_type, "PCI ", 6) == 0) {
+ mp_busses[bus_id].mb_name = "pci";
+ mp_busses[bus_id].mb_idx = bus_id;
+ mp_busses[bus_id].mb_intr_print = mp_print_pci_intr;
+ mp_busses[bus_id].mb_intr_cfg = mp_cfg_pci_intr;
+#ifdef X86_MPBIOS_SUPPORT_EISA
+ } else if (memcmp(entry->bus_type, "EISA ", 6) == 0) {
+ mp_busses[bus_id].mb_name = "eisa";
+ mp_busses[bus_id].mb_idx = bus_id;
+ mp_busses[bus_id].mb_intr_print = mp_print_eisa_intr;
+ mp_busses[bus_id].mb_intr_cfg = mp_cfg_eisa_intr;
+
+ mp_busses[bus_id].mb_data =
+ inb(ELCR0) | (inb(ELCR1) << 8);
+
+ if (mp_eisa_bus != -1)
+ printf("oops: multiple isa busses?\n");
+ else
+ mp_eisa_bus = bus_id;
+#endif
+
+ } else if (memcmp(entry->bus_type, "ISA ", 6) == 0) {
+ mp_busses[bus_id].mb_name = "isa";
+ mp_busses[bus_id].mb_idx = 0; /* XXX */
+ mp_busses[bus_id].mb_intr_print = mp_print_isa_intr;
+ mp_busses[bus_id].mb_intr_cfg = mp_cfg_isa_intr;
+ if (mp_isa_bus != -1)
+ printf("oops: multiple isa busses?\n");
+ else
+ mp_isa_bus = bus_id;
+ } else {
+ printf("%s: unsupported bus type %6.6s\n", self->dv_xname,
+ entry->bus_type);
+ }
+}
+
+
+void
+mpbios_ioapic(ent, self)
+ const u_int8_t *ent;
+ struct device *self;
+{
+ const struct mpbios_ioapic *entry = (const struct mpbios_ioapic *)ent;
+ struct apic_attach_args aaa;
+
+ /* XXX let flags checking happen in ioapic driver.. */
+ if (!(entry->apic_flags & IOAPICENTRY_FLAG_EN))
+ return;
+
+ aaa.aaa_name = "ioapic";
+ aaa.apic_id = entry->apic_id;
+ aaa.apic_version = entry->apic_version;
+ aaa.apic_address = (paddr_t)entry->apic_address;
+ aaa.apic_vecbase = -1;
+ aaa.flags = (mp_fps->mpfb2 & 0x80) ? IOAPIC_PICMODE : IOAPIC_VWIRE;
+
+ config_found_sm(self, &aaa, mp_print, mp_match);
+}
+
+static const char inttype_fmt[] = "\177\020"
+ "f\0\2type\0" "=\1NMI\0" "=\2SMI\0" "=\3ExtINT\0";
+
+static const char flagtype_fmt[] = "\177\020"
+ "f\0\2pol\0" "=\1Act Hi\0" "=\3Act Lo\0"
+ "f\2\2trig\0" "=\1Edge\0" "=\3Level\0";
+
+void
+mpbios_int(ent, enttype, mpi)
+ const u_int8_t *ent;
+ int enttype;
+ struct mp_intr_map *mpi;
+{
+ const struct mpbios_int *entry = (const struct mpbios_int *)ent;
+ struct ioapic_softc *sc = NULL, *sc2;
+
+ struct mp_intr_map *altmpi;
+ struct mp_bus *mpb;
+
+ u_int32_t id = entry->dst_apic_id;
+ u_int32_t pin = entry->dst_apic_int;
+ u_int32_t bus = entry->src_bus_id;
+ u_int32_t dev = entry->src_bus_irq;
+ u_int32_t type = entry->int_type;
+ u_int32_t flags = entry->int_flags;
+
+ switch (type) {
+ case MPS_INTTYPE_INT:
+ mpb = &(mp_busses[bus]);
+ break;
+ case MPS_INTTYPE_ExtINT:
+ mpb = &extint_bus;
+ break;
+ case MPS_INTTYPE_SMI:
+ mpb = &smi_bus;
+ break;
+ case MPS_INTTYPE_NMI:
+ mpb = &nmi_bus;
+ break;
+ }
+ mpi->next = mpb->mb_intrs;
+ mpb->mb_intrs = mpi;
+ mpi->bus = mpb;
+ mpi->bus_pin = dev;
+ mpi->global_int = -1;
+
+ mpi->type = type;
+ mpi->flags = flags;
+ mpi->redir = 0;
+ if (mpb->mb_intr_cfg == NULL) {
+ printf("mpbios: can't find bus %d for apic %d pin %d\n",
+ bus, id, pin);
+ return;
+ }
+
+ (*mpb->mb_intr_cfg)(entry, &mpi->redir);
+
+ if (enttype == MPS_MCT_IOINT) {
+ sc = ioapic_find(id);
+ if (sc == NULL) {
+ printf("mpbios: can't find ioapic %d\n", id);
+ return;
+ }
+
+ /*
+ * XXX workaround for broken BIOSs that put the ACPI
+ * global interrupt number in the entry, not the pin
+ * number.
+ */
+ if (pin >= sc->sc_apic_sz) {
+ sc2 = ioapic_find_bybase(pin);
+ if (sc2 != sc) {
+ printf("mpbios: bad pin %d for apic %d\n",
+ pin, id);
+ return;
+ }
+ printf("mpbios: WARNING: pin %d for apic %d too high; "
+ "assuming ACPI global int value\n", pin, id);
+ pin -= sc->sc_apic_vecbase;
+ }
+
+ mpi->ioapic = sc;
+ mpi->ioapic_pin = pin;
+
+ altmpi = sc->sc_pins[pin].ip_map;
+
+ if (altmpi != NULL) {
+ if ((altmpi->type != type) ||
+ (altmpi->flags != flags)) {
+ printf("%s: conflicting map entries for pin %d\n",
+ sc->sc_pic.pic_dev.dv_xname, pin);
+ }
+ } else {
+ sc->sc_pins[pin].ip_map = mpi;
+ }
+ } else {
+ if (pin >= 2)
+ printf("pin %d of local apic doesn't exist!\n", pin);
+ else {
+ mpi->ioapic = NULL;
+ mpi->ioapic_pin = pin;
+ mpi->cpu_id = id;
+ }
+ }
+
+ mpi->ioapic_ih = APIC_INT_VIA_APIC |
+ ((id<<APIC_INT_APIC_SHIFT) | ((pin<<APIC_INT_PIN_SHIFT)));
+
+ if (mp_verbose) {
+
+ printf("%s: int%d attached to %s",
+ sc ? sc->sc_pic.pic_dev.dv_xname : "local apic",
+ pin, mpb->mb_name);
+
+ if (mpb->mb_idx != -1)
+ printf("%d", mpb->mb_idx);
+
+ (*(mpb->mb_intr_print))(dev);
+
+ printf(" (type 0x%x flags 0x%x)\n", type, flags);
+ }
+}
diff --git a/sys/arch/amd64/amd64/mptramp.S b/sys/arch/amd64/amd64/mptramp.S
new file mode 100644
index 00000000000..22d6a60c7f1
--- /dev/null
+++ b/sys/arch/amd64/amd64/mptramp.S
@@ -0,0 +1,239 @@
+/* $OpenBSD: mptramp.S,v 1.1 2004/06/25 11:03:27 art Exp $ */
+/* $NetBSD: mptramp.S,v 1.1 2003/04/26 18:39:30 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by RedBack Networks Inc.
+ *
+ * Author: Bill Sommerfeld
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999 Stefan Grefen
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * MP startup ...
+ * the stuff from cpu_spinup_trampoline to mp_startup
+ * is copied into the first 640 KB
+ *
+ * We startup the processors now when the kthreads become ready.
+ * The steps are:
+ * 1) Get the processors running kernel-code from a special
+ * page-table and stack page, do chip identification.
+ * 2) halt the processors waiting for them to be enabled
+ * by a idle-thread
+ */
+
+#include "assym.h"
+#include <machine/param.h>
+#include <machine/asm.h>
+#include <machine/specialreg.h>
+#include <machine/segments.h>
+#include <machine/mpbiosvar.h>
+#include <machine/i82489reg.h>
+#include <machine/gdt.h>
+
+#define _RELOC(x) ((x) - KERNBASE)
+#define RELOC(x) _RELOC(_C_LABEL(x))
+
+#define _TRMP_LABEL(a) a = . - _C_LABEL(cpu_spinup_trampoline) + MP_TRAMPOLINE
+
+ .globl _C_LABEL(mpidle)
+ .global _C_LABEL(cpu_spinup_trampoline)
+ .global _C_LABEL(cpu_spinup_trampoline_end)
+ .global _C_LABEL(cpu_hatch)
+ .global _C_LABEL(local_apic)
+ .global _C_LABEL(mp_pdirpa)
+
+ .global gdt64
+
+#define HALT 1: jmp 1b
+
+ .text
+ .align 4,0x0
+ .code16
+_C_LABEL(cpu_spinup_trampoline):
+ cli
+ xorw %ax,%ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+ data32 addr32 lgdt (mptramp_gdt32_desc) # load flat descriptor table
+ movl %cr0, %eax # get cr0
+ orl $0x1, %eax # enable protected mode
+ movl %eax, %cr0 # doit
+ ljmpl $0x8, $mp_startup
+
+_TRMP_LABEL(mp_startup)
+ .code32
+
+ movl $0x10, %eax # data segment
+ movw %ax, %ds
+ movw %ax, %ss
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+
+ movl $ (MP_TRAMPOLINE+NBPG-16),%esp # bootstrap stack end,
+ # with scratch space..
+
+ /* First, reset the PSL. */
+ pushl $PSL_MBO
+ popfl
+
+ movl %cr4,%eax
+ orl $(CR4_PAE|CR4_OSFXSR|CR4_OSXMMEXCPT),%eax
+ movl %eax,%cr4
+
+ movl $MSR_EFER,%ecx
+ rdmsr
+ movl %edx, %edi # %edx is needed by wrmsr below
+
+ # Check if we need to enable NXE
+ movl $0x80000001, %eax
+ cpuid
+ andl $CPUID_NXE, %edx
+ xorl %eax,%eax
+ testl %edx, %edx
+ jz 1f
+ orl $EFER_NXE, %eax
+1:
+ orl $(EFER_LME|EFER_SCE), %eax
+
+ movl %edi, %edx # Restore saved %edx
+ movl $MSR_EFER,%ecx
+ wrmsr
+
+ movl $mp_tramp_pdirpa, %ecx
+ movl (%ecx), %ecx
+ movl %ecx,%cr3 # load ptd addr into mmu
+
+ movl $GSEL(GDATA_SEL, SEL_KPL),%eax #switch to new segment
+ movl %eax,%ds
+ movl %eax,%es
+ movl %eax,%ss
+
+ movl $mptramp_gdt64_desc,%eax
+ lgdt (%eax)
+ movl $mptramp_jmp64,%eax
+
+ movl %cr0,%ecx # get control word
+ orl $(CR0_PE|CR0_PG|CR0_NE|CR0_TS|CR0_MP|CR0_WP),%ecx
+ movl %ecx, %cr0
+
+ ljmp *(%eax)
+
+_TRMP_LABEL(mptramp_jmp64)
+ .long mptramp_longmode
+ .word GSEL(GCODE_SEL, SEL_KPL)
+
+_TRMP_LABEL(mptramp_gdt32)
+ .quad 0x0000000000000000
+ .quad 0x00cf9f000000ffff
+ .quad 0x00cf93000000ffff
+_TRMP_LABEL(mptramp_gdt32_desc)
+ .word 0x17
+ .long mptramp_gdt32
+
+_TRMP_LABEL(mptramp_gdt64)
+ .quad 0x0000000000000000
+ .quad 0x00af9a000000ffff
+ .quad 0x00cf92000000ffff
+_TRMP_LABEL(mptramp_gdt64_desc)
+ .word 0x17
+ .long mptramp_gdt64
+
+ .global mp_pdirpa
+_TRMP_LABEL(mp_pdirpa)
+_TRMP_LABEL(mp_tramp_pdirpa)
+ .long 0
+
+_TRMP_LABEL(mptramp_longmode)
+ .code64
+ movabsq $_C_LABEL(cpu_spinup_trampoline_end),%rax
+ jmp *%rax
+
+
+
+_C_LABEL(cpu_spinup_trampoline_end): #end of code copied to MP_TRAMPOLINE
+ movl _C_LABEL(local_apic)+LAPIC_ID,%ecx
+ shrl $LAPIC_ID_SHIFT,%ecx
+ movq _C_LABEL(cpu_info)(,%rcx,8),%rdi
+
+ movq CPU_INFO_IDLE_PCB(%rdi),%rsi
+
+ movq PCB_RSP(%rsi),%rsp
+ movq PCB_RBP(%rsi),%rbp
+
+ movq CPU_INFO_GDT(%rdi),%rax
+ movw $(MAXGDTSIZ-1),-10(%rsp)
+ movq %rax,-8(%rsp)
+ lgdt -10(%rsp)
+
+ /* Switch address space. */
+ movq PCB_CR3(%rsi),%rax
+ movq %rax,%cr3
+ movl PCB_CR0(%rsi),%eax
+ movq %rax,%cr0
+ call _C_LABEL(cpu_hatch)
+ xorq %r13,%r13
+ jmp _C_LABEL(mpidle)
diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c
index 30c65946713..f1bb906ba88 100644
--- a/sys/arch/amd64/amd64/pmap.c
+++ b/sys/arch/amd64/amd64/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.3 2004/02/23 08:32:36 mickey Exp $ */
+/* $OpenBSD: pmap.c,v 1.4 2004/06/25 11:03:27 art Exp $ */
/* $NetBSD: pmap.c,v 1.3 2003/05/08 18:13:13 thorpej Exp $ */
/*
@@ -288,7 +288,7 @@ pd_entry_t *alternate_pdes[] = APDES_INITIALIZER;
struct simplelock pvalloc_lock;
struct simplelock pmaps_lock;
-#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
+#if (defined(MULTIPROCESSOR) || defined(LOCKDEBUG)) && 0
struct lock pmap_main_lock;
#define PMAP_MAP_TO_HEAD_LOCK() \
(void) spinlockmgr(&pmap_main_lock, LK_SHARED, NULL)
@@ -345,7 +345,7 @@ struct pmap_tlb_shootdown_q {
TAILQ_HEAD(, pmap_tlb_shootdown_job) pq_head;
int pq_pte; /* aggregate PTE bits */
int pq_count; /* number of pending requests */
- struct simplelock pq_slock; /* spin lock on queue */
+ struct SIMPLELOCK pq_slock; /* spin lock on queue */
int pq_flushg; /* pending flush global */
int pq_flushu; /* pending flush user */
} pmap_tlb_shootdown_q[X86_MAXPROCS];
@@ -358,7 +358,7 @@ struct pmap_tlb_shootdown_job *pmap_tlb_shootdown_job_get
void pmap_tlb_shootdown_job_put(struct pmap_tlb_shootdown_q *,
struct pmap_tlb_shootdown_job *);
-struct simplelock pmap_tlb_shootdown_job_lock;
+struct SIMPLELOCK pmap_tlb_shootdown_job_lock;
union pmap_tlb_shootdown_job_al *pj_page, *pj_free;
/*
@@ -661,11 +661,11 @@ pmap_apte_flush(struct pmap *pmap)
pq = &pmap_tlb_shootdown_q[ci->ci_cpuid];
s = splipi();
#ifdef MULTIPROCESSOR
- __cpu_simple_lock(&pq->pq_slock);
+ SIMPLE_LOCK(&pq->pq_slock);
#endif
pq->pq_flushu++;
#ifdef MULTIPROCESSOR
- __cpu_simple_unlock(&pq->pq_slock);
+ SIMPLE_UNLOCK(&pq->pq_slock);
#endif
splx(s);
x86_send_ipi(ci, X86_IPI_TLB);
@@ -1089,7 +1089,7 @@ pmap_bootstrap(kva_start)
* init the static-global locks and global lists.
*/
-#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
+#if (defined(MULTIPROCESSOR) || defined(LOCKDEBUG)) && 0
spinlockinit(&pmap_main_lock, "pmaplk", 0);
#endif
simple_lock_init(&pvalloc_lock);
@@ -1109,11 +1109,11 @@ pmap_bootstrap(kva_start)
* Initialize the TLB shootdown queues.
*/
- simple_lock_init(&pmap_tlb_shootdown_job_lock);
+ SIMPLE_LOCK_INIT(&pmap_tlb_shootdown_job_lock);
for (i = 0; i < X86_MAXPROCS; i++) {
TAILQ_INIT(&pmap_tlb_shootdown_q[i].pq_head);
- simple_lock_init(&pmap_tlb_shootdown_q[i].pq_slock);
+ SIMPLE_LOCK_INIT(&pmap_tlb_shootdown_q[i].pq_slock);
}
/*
@@ -3560,7 +3560,7 @@ pmap_tlb_shootnow(int32_t cpumask)
while (self->ci_tlb_ipi_mask != 0)
#ifdef DIAGNOSTIC
- if (count++ > 10000000)
+ if (count++ > 1000000000)
panic("TLB IPI rendezvous failed (mask %x)",
self->ci_tlb_ipi_mask);
#else
@@ -3611,7 +3611,7 @@ pmap_tlb_shootdown(pmap, va, pte, cpumaskp)
continue;
pq = &pmap_tlb_shootdown_q[ci->ci_cpuid];
#if defined(MULTIPROCESSOR)
- simple_lock(&pq->pq_slock);
+ SIMPLE_LOCK(&pq->pq_slock);
#endif
/*
@@ -3622,7 +3622,7 @@ pmap_tlb_shootdown(pmap, va, pte, cpumaskp)
if (pq->pq_flushg > 0 ||
(pq->pq_flushu > 0 && (pte & pmap_pg_g) == 0)) {
#if defined(MULTIPROCESSOR)
- simple_unlock(&pq->pq_slock);
+ SIMPLE_UNLOCK(&pq->pq_slock);
#endif
continue;
}
@@ -3656,7 +3656,7 @@ pmap_tlb_shootdown(pmap, va, pte, cpumaskp)
if (ci == self && pq->pq_count < PMAP_TLB_MAXJOBS) {
pmap_update_pg(va);
#if defined(MULTIPROCESSOR)
- simple_unlock(&pq->pq_slock);
+ SIMPLE_LOCK(&pq->pq_slock);
#endif
continue;
} else {
@@ -3680,7 +3680,7 @@ pmap_tlb_shootdown(pmap, va, pte, cpumaskp)
*cpumaskp |= 1U << ci->ci_cpuid;
}
#if defined(MULTIPROCESSOR)
- simple_unlock(&pq->pq_slock);
+ SIMPLE_UNLOCK(&pq->pq_slock);
#endif
}
splx(s);
@@ -3706,7 +3706,7 @@ pmap_do_tlb_shootdown(struct cpu_info *self)
s = splipi();
#ifdef MULTIPROCESSOR
- simple_lock(&pq->pq_slock);
+ SIMPLE_LOCK(&pq->pq_slock);
#endif
if (pq->pq_flushg) {
@@ -3741,7 +3741,7 @@ pmap_do_tlb_shootdown(struct cpu_info *self)
for (CPU_INFO_FOREACH(cii, ci))
x86_atomic_clearbits_ul(&ci->ci_tlb_ipi_mask,
(1U << cpu_id));
- simple_unlock(&pq->pq_slock);
+ SIMPLE_UNLOCK(&pq->pq_slock);
#endif
splx(s);
@@ -3788,11 +3788,11 @@ pmap_tlb_shootdown_job_get(pq)
return (NULL);
#ifdef MULTIPROCESSOR
- simple_lock(&pmap_tlb_shootdown_job_lock);
+ SIMPLE_LOCK(&pmap_tlb_shootdown_job_lock);
#endif
if (pj_free == NULL) {
#ifdef MULTIPROCESSOR
- simple_unlock(&pmap_tlb_shootdown_job_lock);
+ SIMPLE_UNLOCK(&pmap_tlb_shootdown_job_lock);
#endif
return NULL;
}
@@ -3800,7 +3800,7 @@ pmap_tlb_shootdown_job_get(pq)
pj_free =
(union pmap_tlb_shootdown_job_al *)pj_free->pja_job.pj_nextfree;
#ifdef MULTIPROCESSOR
- simple_unlock(&pmap_tlb_shootdown_job_lock);
+ SIMPLE_UNLOCK(&pmap_tlb_shootdown_job_lock);
#endif
pq->pq_count++;
@@ -3825,12 +3825,12 @@ pmap_tlb_shootdown_job_put(pq, pj)
panic("pmap_tlb_shootdown_job_put: queue length inconsistency");
#endif
#ifdef MULTIPROCESSOR
- simple_lock(&pmap_tlb_shootdown_job_lock);
+ SIMPLE_LOCK(&pmap_tlb_shootdown_job_lock);
#endif
pj->pj_nextfree = &pj_free->pja_job;
pj_free = (union pmap_tlb_shootdown_job_al *)pj;
#ifdef MULTIPROCESSOR
- simple_unlock(&pmap_tlb_shootdown_job_lock);
+ SIMPLE_UNLOCK(&pmap_tlb_shootdown_job_lock);
#endif
pq->pq_count--;
diff --git a/sys/arch/amd64/amd64/spl.S b/sys/arch/amd64/amd64/spl.S
index c9b674ff648..7772f14205b 100644
--- a/sys/arch/amd64/amd64/spl.S
+++ b/sys/arch/amd64/amd64/spl.S
@@ -178,6 +178,7 @@ IDTVEC(doreti)
sti
movl $T_ASTFLT,TF_TRAPNO(%rsp) /* XXX undo later.. */
/* Pushed T_ASTFLT into tf_trapno on entry. */
+ movq %rsp, %rdi
call _C_LABEL(trap)
cli
jmp 5b
diff --git a/sys/arch/amd64/amd64/vector.S b/sys/arch/amd64/amd64/vector.S
index b2c3819dd2d..ddef85a0c43 100644
--- a/sys/arch/amd64/amd64/vector.S
+++ b/sys/arch/amd64/amd64/vector.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: vector.S,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $OpenBSD: vector.S,v 1.2 2004/06/25 11:03:27 art Exp $ */
/* $NetBSD: vector.S,v 1.2 2003/05/04 23:46:41 fvdl Exp $ */
/*
@@ -223,6 +223,7 @@ calltrap:
#ifdef DIAGNOSTIC
movl CPUVAR(ILEVEL),%ebx
#endif /* DIAGNOSTIC */
+ movq %rsp, %rdi
call _C_LABEL(trap)
2: /* Check for ASTs on exit to user mode. */
cli
@@ -233,6 +234,7 @@ calltrap:
5: CLEAR_ASTPENDING(%r11)
sti
movl $T_ASTFLT,TF_TRAPNO(%rsp)
+ movq %rsp, %rdi
call _C_LABEL(trap)
jmp 2b
#ifndef DIAGNOSTIC
@@ -368,8 +370,8 @@ IDTVEC(intr_lapic_ltimer)
#endif /* NLAPIC > 0 */
#ifdef MULTIPROCESSOR
-#define LOCK_KERNEL call _C_LABEL(x86_intlock)
-#define UNLOCK_KERNEL call _C_LABEL(x86_intunlock)
+#define LOCK_KERNEL movq %rsp, %rdi; call _C_LABEL(x86_intlock)
+#define UNLOCK_KERNEL movq %rsp, %rdi; call _C_LABEL(x86_intunlock)
#else
#define LOCK_KERNEL
#define UNLOCK_KERNEL
diff --git a/sys/arch/amd64/amd64/vm_machdep.c b/sys/arch/amd64/amd64/vm_machdep.c
index 9e38904ac64..24f856f99d2 100644
--- a/sys/arch/amd64/amd64/vm_machdep.c
+++ b/sys/arch/amd64/amd64/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.2 2004/05/13 20:20:24 sturm Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.3 2004/06/25 11:03:27 art Exp $ */
/* $NetBSD: vm_machdep.c,v 1.1 2003/04/26 18:39:33 fvdl Exp $ */
/*-
@@ -144,7 +144,6 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
tf->tf_rsp = (u_int64_t)stack + stacksize;
sf = (struct switchframe *)tf - 1;
- sf->sf_ppl = IPL_NONE;
sf->sf_r12 = (u_int64_t)func;
sf->sf_r13 = (u_int64_t)arg;
if (func == child_return)
diff --git a/sys/arch/amd64/compile/.cvsignore b/sys/arch/amd64/compile/.cvsignore
index 0ff0325754e..4741f3d9201 100644
--- a/sys/arch/amd64/compile/.cvsignore
+++ b/sys/arch/amd64/compile/.cvsignore
@@ -1,3 +1,4 @@
GENERIC
+GENERIC.MP
RAMDISK
RAMDISK_CD
diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC
index 13182c94128..39f82697894 100644
--- a/sys/arch/amd64/conf/GENERIC
+++ b/sys/arch/amd64/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.24 2004/06/06 04:50:57 pvalchev Exp $
+# $OpenBSD: GENERIC,v 1.25 2004/06/25 11:03:28 art Exp $
#
# GENERIC -- everything that's currently supported
#
@@ -32,7 +32,7 @@ config bsd swap generic
mainbus0 at root
-cpu* at mainbus0
+cpu0 at mainbus? apid ?
isa0 at mainbus0
#isa0 at pcib?
pci* at mainbus0 bus ?
diff --git a/sys/arch/amd64/conf/GENERIC.MP b/sys/arch/amd64/conf/GENERIC.MP
new file mode 100644
index 00000000000..af4666420ca
--- /dev/null
+++ b/sys/arch/amd64/conf/GENERIC.MP
@@ -0,0 +1,9 @@
+include "arch/amd64/conf/GENERIC"
+
+option MULTIPROCESSOR
+option MPBIOS
+option CPU
+
+cpu* at mainbus? apid ?
+ioapic* at mainbus? apid ?
+#aapic* at pci? dev ? function ?
diff --git a/sys/arch/amd64/conf/RAMDISK b/sys/arch/amd64/conf/RAMDISK
index b102eb0d808..73ee3071df9 100644
--- a/sys/arch/amd64/conf/RAMDISK
+++ b/sys/arch/amd64/conf/RAMDISK
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK,v 1.9 2004/06/06 04:50:57 pvalchev Exp $
+# $OpenBSD: RAMDISK,v 1.10 2004/06/25 11:03:28 art Exp $
machine amd64 # architecture, used by config; REQUIRED
@@ -33,7 +33,7 @@ config bsd root on rd0a swap on rd0b and wd0b and sd0b
mainbus0 at root
-cpu* at mainbus0
+cpu* at mainbus0 apid ?
isa0 at mainbus0
#isa0 at pcib?
pci* at mainbus0
diff --git a/sys/arch/amd64/conf/RAMDISK_CD b/sys/arch/amd64/conf/RAMDISK_CD
index 7c74b27a9a7..d41ff38451d 100644
--- a/sys/arch/amd64/conf/RAMDISK_CD
+++ b/sys/arch/amd64/conf/RAMDISK_CD
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK_CD,v 1.10 2004/06/06 04:50:57 pvalchev Exp $
+# $OpenBSD: RAMDISK_CD,v 1.11 2004/06/25 11:03:28 art Exp $
machine amd64 # architecture, used by config; REQUIRED
@@ -33,7 +33,7 @@ config bsd root on rd0a swap on rd0b and wd0b and sd0b
mainbus0 at root
-cpu* at mainbus0
+cpu* at mainbus0 apid ?
isa0 at mainbus0
#isa0 at pcib?
pci* at mainbus0
diff --git a/sys/arch/amd64/conf/files.amd64 b/sys/arch/amd64/conf/files.amd64
index 9dcd8d58e06..b52a9083423 100644
--- a/sys/arch/amd64/conf/files.amd64
+++ b/sys/arch/amd64/conf/files.amd64
@@ -1,4 +1,4 @@
-# $OpenBSD: files.amd64,v 1.2 2004/02/25 00:16:41 deraadt Exp $
+# $OpenBSD: files.amd64,v 1.3 2004/06/25 11:03:28 art Exp $
maxpartitions 16
maxusers 2 16 128
@@ -26,6 +26,15 @@ file arch/amd64/amd64/intr.c
file arch/amd64/amd64/bus_space.c
file arch/amd64/amd64/bus_dma.c
+file arch/amd64/amd64/mptramp.S multiprocessor
+file arch/amd64/amd64/ipifuncs.c multiprocessor
+file arch/amd64/amd64/ipi.c multiprocessor
+
+file arch/amd64/amd64/apic.c ioapic | lapic
+
+file arch/amd64/amd64/mpbios.c mpbios
+
+
file arch/amd64/amd64/consinit.c
file dev/cons.c
file dev/cninit.c
@@ -54,12 +63,12 @@ include "dev/i2o/files.i2o"
include "dev/atapiscsi/files.atapiscsi"
include "dev/ata/files.ata"
-define mainbus { }
+define mainbus { apid = -1 }
device mainbus: isabus, pcibus, mainbus
attach mainbus at root
file arch/amd64/amd64/mainbus.c mainbus
-define cpu { [apid = -1] }
+define cpu { apid = -1 }
device cpu
attach cpu at mainbus
file arch/amd64/amd64/cpu.c cpu
diff --git a/sys/arch/amd64/include/cpu.h b/sys/arch/amd64/include/cpu.h
index 4cd297e86b9..7c527d7d7cb 100644
--- a/sys/arch/amd64/include/cpu.h
+++ b/sys/arch/amd64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.8 2004/06/22 01:16:50 art Exp $ */
+/* $OpenBSD: cpu.h,v 1.9 2004/06/25 11:03:28 art Exp $ */
/* $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $ */
/*-
@@ -140,6 +140,8 @@ extern struct cpu_info *cpu_info_list;
#define CPU_INFO_FOREACH(cii, ci) cii = 0, ci = cpu_info_list; \
ci != NULL; ci = ci->ci_next
+#define CPU_INFO_UNIT(ci) ((ci)->ci_dev->dv_unit)
+
/*
* Preempt the current process if in interrupt from user mode,
* or after the current trap/syscall if in system mode.
@@ -177,8 +179,6 @@ extern struct cpu_info cpu_info_primary;
#endif
-#include <machine/psl.h>
-
/*
* definitions of cpu-dependent requirements
* referenced in generic code
@@ -188,6 +188,12 @@ extern struct cpu_info cpu_info_primary;
#endif /* MULTIPROCESSOR */
+#include <machine/psl.h>
+
+#ifdef MULTIPROCESSOR
+#include <sys/mplock.h>
+#endif
+
#define aston(p) ((p)->p_md.md_astpending = 1)
extern u_int32_t cpus_attached;
@@ -223,11 +229,13 @@ extern u_int32_t cpus_attached;
/*
* We need a machine-independent name for this.
*/
-extern void delay(int);
+extern void (*delay_func)(int);
struct timeval;
-extern void microtime(struct timeval *);
+extern void (*microtime_func)(struct timeval *);
-#define DELAY(x) delay(x)
+#define DELAY(x) (*delay_func)(x)
+#define delay(x) (*delay_func)(x)
+#define microtime(tv) (*microtime_func)(tv)
/*
@@ -256,7 +264,6 @@ int cpu_amd64speed(int *);
void cpu_probe_features(struct cpu_info *);
/* machdep.c */
-void delay(int);
void dumpconf(void);
int cpu_maxproc(void);
void cpu_reset(void);
diff --git a/sys/arch/amd64/include/frame.h b/sys/arch/amd64/include/frame.h
index d0fb538ceeb..7ab818494fa 100644
--- a/sys/arch/amd64/include/frame.h
+++ b/sys/arch/amd64/include/frame.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: frame.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $OpenBSD: frame.h,v 1.2 2004/06/25 11:03:28 art Exp $ */
/* $NetBSD: frame.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */
/*-
@@ -162,7 +162,6 @@ struct intrframe {
* Stack frame inside cpu_switch()
*/
struct switchframe {
- int64_t sf_ppl;
int64_t sf_r15;
int64_t sf_r14;
int64_t sf_r13;
diff --git a/sys/arch/amd64/include/i82093reg.h b/sys/arch/amd64/include/i82093reg.h
index 91dc73bb1df..2259306db6a 100644
--- a/sys/arch/amd64/include/i82093reg.h
+++ b/sys/arch/amd64/include/i82093reg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: i82093reg.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $OpenBSD: i82093reg.h,v 1.2 2004/06/25 11:03:28 art Exp $ */
/* $NetBSD: i82093reg.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */
/*-
@@ -119,3 +119,65 @@
#define IMCR_REGISTER 0x70
#define IMCR_PIC 0x00
#define IMCR_APIC 0x01
+
+#ifdef _KERNEL
+
+#define ioapic_asm_ack(num) \
+ movl $0,(_C_LABEL(local_apic)+LAPIC_EOI)(%rip)
+
+#ifdef MULTIPROCESSOR
+
+#ifdef notyet
+#define ioapic_asm_lock(num) \
+ movl $1,%esi ;\
+77: \
+ xchgl %esi,PIC_LOCK(%rdi) ;\
+ testl %esi,%esi ;\
+ jne 77b
+
+#define ioapic_asm_unlock(num) \
+ movl $0,PIC_LOCK(%rdi)
+#else
+#define ioapic_asm_lock(num)
+#define ioapic_asm_unlock(num)
+#endif
+
+#else
+
+#define ioapic_asm_lock(num)
+#define ioapic_asm_unlock(num)
+
+#endif /* MULTIPROCESSOR */
+
+
+#define ioapic_mask(num) \
+ movq IS_PIC(%r14),%rdi ;\
+ ioapic_asm_lock(num) ;\
+ movl IS_PIN(%r14),%esi ;\
+ leaq 0x10(%rsi,%rsi,1),%rsi ;\
+ movq IOAPIC_SC_REG(%rdi),%r15 ;\
+ movl %esi, (%r15) ;\
+ movq IOAPIC_SC_DATA(%rdi),%r15 ;\
+ movl (%r15),%esi ;\
+ orl $IOAPIC_REDLO_MASK,%esi ;\
+ movl %esi,(%r15) ;\
+ ioapic_asm_unlock(num)
+
+#define ioapic_unmask(num) \
+ cmpq $IREENT_MAGIC,(TF_ERR+8)(%rsp) ;\
+ jne 79f ;\
+ movq IS_PIC(%r14),%rdi ;\
+ ioapic_asm_lock(num) ;\
+ movl IS_PIN(%r14),%esi ;\
+ leaq 0x10(%rsi,%rsi,1),%rsi ;\
+ movq IOAPIC_SC_REG(%rdi),%r15 ;\
+ movq IOAPIC_SC_DATA(%rdi),%r13 ;\
+ movl %esi, (%r15) ;\
+ movl (%r13),%r12d ;\
+ andl $~IOAPIC_REDLO_MASK,%r12d ;\
+ movl %esi,(%r15) ;\
+ movl %r12d,(%r13) ;\
+ ioapic_asm_unlock(num) ;\
+79:
+
+#endif
diff --git a/sys/arch/amd64/include/i82489var.h b/sys/arch/amd64/include/i82489var.h
new file mode 100644
index 00000000000..22fdcb2edc5
--- /dev/null
+++ b/sys/arch/amd64/include/i82489var.h
@@ -0,0 +1,122 @@
+/* $NetBSD: i82489var.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Frank van der Linden.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _X86_I82489REG_H_
+#define _X86_I82489REG_H_
+
+/*
+ * Software definitions belonging to Local APIC driver.
+ */
+
+static __inline__ u_int32_t i82489_readreg __P((int));
+static __inline__ void i82489_writereg __P((int, u_int32_t));
+
+#ifdef _KERNEL
+extern volatile u_int32_t local_apic[];
+extern volatile u_int32_t lapic_tpr;
+#endif
+
+static __inline__ u_int32_t
+i82489_readreg(reg)
+ int reg;
+{
+ return *((volatile u_int32_t *)(((volatile u_int8_t *)local_apic)
+ + reg));
+}
+
+static __inline__ void
+i82489_writereg(reg, val)
+ int reg;
+ u_int32_t val;
+{
+ *((volatile u_int32_t *)(((volatile u_int8_t *)local_apic) + reg)) = val;
+}
+
+#define lapic_cpu_number() (i82489_readreg(LAPIC_ID)>>LAPIC_ID_SHIFT)
+
+/*
+ * "spurious interrupt vector"; vector used by interrupt which was
+ * aborted because the CPU masked it after it happened but before it
+ * was delivered.. "Oh, sorry, i caught you at a bad time".
+ * Low-order 4 bits must be all ones.
+ */
+extern void Xintrspurious(void);
+#define LAPIC_SPURIOUS_VECTOR 0xef
+
+/*
+ * Vector used for inter-processor interrupts.
+ */
+extern void Xintr_lapic_ipi(void);
+extern void Xrecurse_lapic_ipi(void);
+extern void Xresume_lapic_ipi(void);
+#define LAPIC_IPI_VECTOR 0xe0
+
+/*
+ * Vector used for local apic timer interrupts.
+ */
+
+extern void Xintr_lapic_ltimer(void);
+extern void Xresume_lapic_ltimer(void);
+extern void Xrecurse_lapic_ltimer(void);
+#define LAPIC_TIMER_VECTOR 0xc0
+
+/*
+ * 'pin numbers' for local APIC
+ */
+#define LAPIC_PIN_TIMER 0
+#define LAPIC_PIN_PCINT 2
+#define LAPIC_PIN_LVINT0 3
+#define LAPIC_PIN_LVINT1 4
+#define LAPIC_PIN_LVERR 5
+
+extern void Xintr_lapic0(void);
+extern void Xintr_lapic2(void);
+extern void Xintr_lapic3(void);
+extern void Xintr_lapic4(void);
+extern void Xintr_lapic5(void);
+
+
+struct cpu_info;
+
+extern void lapic_boot_init __P((paddr_t));
+extern void lapic_set_lvt __P((void));
+extern void lapic_enable __P((void));
+extern void lapic_calibrate_timer __P((struct cpu_info *ci));
+extern void lapic_initclocks __P((void));
+
+#endif
diff --git a/sys/arch/amd64/include/intr.h b/sys/arch/amd64/include/intr.h
index a9ba202472f..f468f1a0b27 100644
--- a/sys/arch/amd64/include/intr.h
+++ b/sys/arch/amd64/include/intr.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: intr.h,v 1.2 2004/05/07 20:33:04 tedu Exp $ */
+/* $OpenBSD: intr.h,v 1.3 2004/06/25 11:03:28 art Exp $ */
/* $NetBSD: intr.h,v 1.2 2003/05/04 22:01:56 fvdl Exp $ */
/*-
@@ -44,7 +44,6 @@
#ifndef _LOCORE
#include <machine/cpu.h>
-#include <machine/pic.h>
/*
* Struct describing an interrupt source for a CPU. struct cpu_info
@@ -252,6 +251,8 @@ softintr(int sir)
#define IPLSHIFT 4 /* The upper nibble of vectors is the IPL. */
#define IPL(level) ((level) >> IPLSHIFT) /* Extract the IPL. */
+#include <machine/pic.h>
+
/*
* Stub declarations.
*/
diff --git a/sys/arch/amd64/include/lock.h b/sys/arch/amd64/include/lock.h
new file mode 100644
index 00000000000..35b1974f910
--- /dev/null
+++ b/sys/arch/amd64/include/lock.h
@@ -0,0 +1,119 @@
+/* $OpenBSD: lock.h,v 1.1 2004/06/25 11:03:28 art Exp $ */
+/* $NetBSD: lock.h,v 1.1.2.2 2000/05/03 14:40:55 sommerfeld Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Machine-dependent spin lock operations.
+ */
+
+#ifndef _AMD64_LOCK_H_
+#define _AMD64_LOCK_H_
+
+typedef __volatile int __cpu_simple_lock_t;
+
+#define __SIMPLELOCK_LOCKED 1
+#define __SIMPLELOCK_UNLOCKED 0
+
+/*
+ * compiler barrier: prevent reordering of instructions.
+ * XXX something similar will move to <sys/cdefs.h>
+ * or thereabouts.
+ * This prevents the compiler from reordering code around
+ * this "instruction", acting as a sequence point for code generation.
+ */
+
+#define __lockbarrier() __asm __volatile("": : :"memory")
+
+#ifdef LOCKDEBUG
+
+extern void __cpu_simple_lock_init(__cpu_simple_lock_t *);
+extern void __cpu_simple_lock(__cpu_simple_lock_t *);
+extern int __cpu_simple_lock_try(__cpu_simple_lock_t *);
+extern void __cpu_simple_unlock(__cpu_simple_lock_t *);
+
+#else
+
+#include <machine/atomic.h>
+
+static __inline void __cpu_simple_lock_init(__cpu_simple_lock_t *)
+ __attribute__((__unused__));
+static __inline void __cpu_simple_lock(__cpu_simple_lock_t *)
+ __attribute__((__unused__));
+static __inline int __cpu_simple_lock_try(__cpu_simple_lock_t *)
+ __attribute__((__unused__));
+static __inline void __cpu_simple_unlock(__cpu_simple_lock_t *)
+ __attribute__((__unused__));
+
+static __inline void
+__cpu_simple_lock_init(__cpu_simple_lock_t *lockp)
+{
+ *lockp = __SIMPLELOCK_UNLOCKED;
+ __lockbarrier();
+}
+
+static __inline void
+__cpu_simple_lock(__cpu_simple_lock_t *lockp)
+{
+ while (x86_atomic_testset_i(lockp, __SIMPLELOCK_LOCKED)
+ == __SIMPLELOCK_LOCKED) {
+ continue; /* spin */
+ }
+ __lockbarrier();
+}
+
+static __inline int
+__cpu_simple_lock_try(__cpu_simple_lock_t *lockp)
+{
+ int r = (x86_atomic_testset_i(lockp, __SIMPLELOCK_LOCKED)
+ == __SIMPLELOCK_UNLOCKED);
+
+ __lockbarrier();
+
+ return (r);
+}
+
+static __inline void
+__cpu_simple_unlock(__cpu_simple_lock_t *lockp)
+{
+ __lockbarrier();
+ *lockp = __SIMPLELOCK_UNLOCKED;
+}
+
+#endif /* !LOCKDEBUG */
+
+#endif /* _AMD64_LOCK_H_ */
diff --git a/sys/arch/amd64/include/mpconfig.h b/sys/arch/amd64/include/mpconfig.h
index 7c12822824c..54f340adfc9 100644
--- a/sys/arch/amd64/include/mpconfig.h
+++ b/sys/arch/amd64/include/mpconfig.h
@@ -1,4 +1,4 @@
-/* $NetBSD: mpconfig.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */
+/* $NetBSD: mpconfig.h,v 1.2 2003/05/11 00:05:52 fvdl Exp $ */
/*
* Definitions originally from the mpbios code, but now used for ACPI
@@ -50,6 +50,7 @@ struct mp_intr_map
int flags; /* from mp spec intr record */
u_int32_t redir;
int cpu_id;
+ int global_int; /* ACPI global interrupt number */
};
#if defined(_KERNEL)
diff --git a/sys/arch/amd64/include/pic.h b/sys/arch/amd64/include/pic.h
index c9d9a5082a6..b6a222b2780 100644
--- a/sys/arch/amd64/include/pic.h
+++ b/sys/arch/amd64/include/pic.h
@@ -1,11 +1,15 @@
-/* $OpenBSD: pic.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $OpenBSD: pic.h,v 1.2 2004/06/25 11:03:28 art 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>
+#ifdef MULTIPROCESSOR
+#include <sys/mplock.h>
+#else
#include <sys/lock.h>
+#endif
struct cpu_info;
@@ -15,7 +19,9 @@ struct cpu_info;
struct pic {
struct device pic_dev;
int pic_type;
- simple_lock_t pic_lock;
+#ifdef MULTIPROCESSOR
+ struct SIMPLE_LOCK pic_lock;
+#endif
void (*pic_hwmask)(struct pic *, int);
void (*pic_hwunmask)(struct pic *, int);
void (*pic_addroute)(struct pic *, struct cpu_info *, int, int, int);
diff --git a/sys/arch/amd64/isa/clock.c b/sys/arch/amd64/isa/clock.c
index fcf6db666e5..2132a6e5b63 100644
--- a/sys/arch/amd64/isa/clock.c
+++ b/sys/arch/amd64/isa/clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clock.c,v 1.3 2004/03/22 19:43:29 nordin Exp $ */
+/* $OpenBSD: clock.c,v 1.4 2004/06/25 11:03:28 art Exp $ */
/* $NetBSD: clock.c,v 1.1 2003/04/26 18:39:50 fvdl Exp $ */
/*-
@@ -184,7 +184,7 @@ mc146818_write(sc, reg, datum)
DELAY(1);
}
-static u_long rtclock_tval;
+u_long rtclock_tval;
/* minimal initialization, enough for delay() */
void
@@ -313,28 +313,7 @@ int
clockintr(void *arg)
{
struct clockframe *frame = arg;
-#if defined(I586_CPU) || defined(I686_CPU)
- static int microset_iter; /* call cc_microset once/sec */
- struct cpu_info *ci = curcpu();
-
- /*
- * If we have a cycle counter, do the microset thing.
- */
- if (ci->ci_feature_flags & CPUID_TSC) {
- if (
-#if defined(MULTIPROCESSOR)
- CPU_IS_PRIMARY(ci) &&
-#endif
- (microset_iter--) == 0) {
- cc_microset_time = time;
- microset_iter = hz - 1;
-#if defined(MULTIPROCESSOR)
- x86_broadcast_ipi(X86_IPI_MICROSET);
-#endif
- cc_microset(ci);
- }
- }
-#endif
+
hardclock(frame);
return 1;
@@ -383,7 +362,7 @@ gettick()
* wave' mode counts at 2:1).
*/
void
-delay(int n)
+i8254_delay(int n)
{
int limit, tick, otick;
static const int delaytab[26] = {
@@ -518,7 +497,7 @@ rtcdrain(void *v)
}
void
-cpu_initclocks()
+i8254_initclocks()
{
static struct timeout rtcdrain_timeout;
diff --git a/sys/arch/amd64/pci/pci_machdep.c b/sys/arch/amd64/pci/pci_machdep.c
index 138afc1ba23..e1af0882118 100644
--- a/sys/arch/amd64/pci/pci_machdep.c
+++ b/sys/arch/amd64/pci/pci_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_machdep.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.2 2004/06/25 11:03:28 art Exp $ */
/* $NetBSD: pci_machdep.c,v 1.3 2003/05/07 21:33:58 fvdl Exp $ */
/*-
@@ -111,7 +111,7 @@
int pci_mode = -1;
-#ifdef MULTIPROCESSOR
+#if defined(MULTIPROCESSOR) && 0
struct simplelock pci_conf_slock = SIMPLELOCK_INITIALIZER;
#else
struct simplelock pci_conf_slock = { 0 };