diff options
Diffstat (limited to 'sys/arch/amd64')
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 }; |