diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2007-09-10 21:33:17 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2007-09-10 21:33:17 +0000 |
commit | b603ad717e260d2b8e25abcc7c8351ff27a51a33 (patch) | |
tree | 1b19e5b78b6d98d3869804008e3c3f36172ee843 /sys | |
parent | df58f470ea4ca0ee9ea2a64cb2b556f7a4176034 (diff) |
IPI implementation. Bits and pieces from NetBSD, but the interface has been
changed to free up another 64-bit word in the interrupt transaction. This
means we have two 64-bit words available for arguments, which means we
probably don't need to pass arguments through structures.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/sparc64/conf/files.sparc64 | 5 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/ipifuncs.c | 139 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/locore.s | 95 |
3 files changed, 226 insertions, 13 deletions
diff --git a/sys/arch/sparc64/conf/files.sparc64 b/sys/arch/sparc64/conf/files.sparc64 index b4a2764d28b..f3463fa8aa8 100644 --- a/sys/arch/sparc64/conf/files.sparc64 +++ b/sys/arch/sparc64/conf/files.sparc64 @@ -1,4 +1,4 @@ -# $OpenBSD: files.sparc64,v 1.88 2007/08/25 18:36:47 kettenis Exp $ +# $OpenBSD: files.sparc64,v 1.89 2007/09/10 21:33:16 kettenis Exp $ # $NetBSD: files.sparc64,v 1.50 2001/08/10 20:53:50 eeh Exp $ # maxpartitions must be first item in files.${ARCH} @@ -239,6 +239,7 @@ file arch/sparc64/sparc64/emul.c file arch/sparc64/sparc64/in_cksum.S inet file arch/sparc64/sparc64/in4_cksum.c inet file arch/sparc64/sparc64/intr.c +file arch/sparc64/sparc64/ipifuncs.c multiprocessor file arch/sparc64/sparc64/kgdb_machdep.c kgdb # sparc64/sparc64/locore.s is handled specially in the makefile, # because it must come first in the "ld" command line. @@ -256,7 +257,7 @@ file arch/sparc64/sparc64/trap.c file arch/sparc64/sparc64/vm_machdep.c file arch/sparc64/sparc64/db_interface.c ddb | kgdb -file arch/sparc64/sparc64/db_trace.c ddb +file arch/sparc64/sparc64/db_trace.c ddb file arch/sparc64/sparc64/db_disasm.c ddb file arch/sparc64/dev/md_root.c memory_disk_hooks diff --git a/sys/arch/sparc64/sparc64/ipifuncs.c b/sys/arch/sparc64/sparc64/ipifuncs.c new file mode 100644 index 00000000000..ab407201b64 --- /dev/null +++ b/sys/arch/sparc64/sparc64/ipifuncs.c @@ -0,0 +1,139 @@ +/* $NetBSD: ipifuncs.c,v 1.8 2006/10/07 18:11:36 rjs Exp $ */ + +/*- + * Copyright (c) 2004 The NetBSD Foundation, Inc. + * 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. 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/malloc.h> + +#include <machine/cpu.h> +#include <machine/ctlreg.h> +#include <machine/pmap.h> +#include <machine/sparc64.h> + +extern int db_active; + +#define SPARC64_IPI_RETRIES 10000 + +#define sparc64_ipi_sleep() delay(1000) + +/* + * These are the "function" entry points in locore.s to handle IPI's. + */ +void ipi_tlb_page_demap(void); +void ipi_tlb_context_demap(void); + +/* + * Send an interprocessor interrupt. + */ +void +sparc64_send_ipi(int upaid, void (*func)(void), u_int64_t arg0, u_int64_t arg1) +{ + int i, j; + + KASSERT((u_int64_t)func > MAXINTNUM); + + if (ldxa(0, ASR_IDSR) & IDSR_BUSY) { + __asm __volatile("ta 1; nop"); + } + + /* Schedule an interrupt. */ + for (i = 0; i < SPARC64_IPI_RETRIES; i++) { + int s = intr_disable(); + + stxa(IDDR_0H, ASI_INTERRUPT_DISPATCH, (u_int64_t)func); + stxa(IDDR_1H, ASI_INTERRUPT_DISPATCH, arg0); + stxa(IDDR_2H, ASI_INTERRUPT_DISPATCH, arg1); + stxa(IDCR(upaid), ASI_INTERRUPT_DISPATCH, 0); + membar(Sync); + + for (j = 0; j < 1000000; j++) { + if (ldxa(0, ASR_IDSR) & IDSR_BUSY) + continue; + else + break; + } + intr_restore(s); + + if (j == 1000000) + break; + + if ((ldxa(0, ASR_IDSR) & IDSR_NACK) == 0) + return; + } + +#if 1 + if (db_active || panicstr != NULL) + printf("ipi_send: couldn't send ipi to module %u\n", upaid); + else + panic("ipi_send: couldn't send ipi"); +#else + __asm __volatile("ta 1; nop" : :); +#endif +} + +/* + * Broadcast an IPI to all but ourselves. + */ +void +sparc64_broadcast_ipi(void (*func)(void), u_int64_t arg0, u_int64_t arg1) +{ + struct cpu_info *ci; + + for (ci = cpus; ci != NULL; ci = ci->ci_next) + if (ci->ci_number != cpu_number()) + sparc64_send_ipi(ci->ci_upaid, func, arg0, arg1); +} + +void +smp_tlb_flush_pte(vaddr_t va, int ctx) +{ + sp_tlb_flush_pte(va, ctx); + + if (db_active) + return; + + sparc64_broadcast_ipi(ipi_tlb_page_demap, va, ctx); +} + +void +smp_tlb_flush_ctx(int ctx) +{ + sp_tlb_flush_ctx(ctx); + + if (db_active) + return; + + sparc64_broadcast_ipi(ipi_tlb_context_demap, ctx, 0); +} diff --git a/sys/arch/sparc64/sparc64/locore.s b/sys/arch/sparc64/sparc64/locore.s index 9f06c2a5b80..35372f2eed0 100644 --- a/sys/arch/sparc64/sparc64/locore.s +++ b/sys/arch/sparc64/sparc64/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.80 2007/09/09 08:55:27 kettenis Exp $ */ +/* $OpenBSD: locore.s,v 1.81 2007/09/10 21:33:16 kettenis Exp $ */ /* $NetBSD: locore.s,v 1.137 2001/08/13 06:10:10 jdolecek Exp $ */ /* @@ -3183,18 +3183,28 @@ interrupt_vector: membar #Sync stxa %g0, [%g0] ASI_IRSR ! Ack IRQ membar #Sync ! Should not be needed due to retry - sethi %hi(_C_LABEL(intrlev)), %g3 - btst IRSR_BUSY, %g1 - or %g3, %lo(_C_LABEL(intrlev)), %g3 - bz,pn %icc, 3f ! spurious interrupt - sllx %g2, 3, %g5 ! Calculate entry number - cmp %g2, MAXINTNUM -#ifdef DEBUG - tgeu 55 -#endif /* DEBUG */ + btst IRSR_BUSY, %g1 + bz,pn %icc, 3f ! Spurious interrupt + cmp %g2, MAXINTNUM +#ifdef MULTIPROCESSOR + blu,pt %xcc, Lsoftint_regular + sllx %g2, 3, %g5 ! Calculate entry number + mov IRDR_1H, %g3 + ldxa [%g3] ASI_IRDR, %g3 ! Get IPI handler arg0 + mov IRDR_2H, %g5 + jmpl %g2, %g0 + ldxa [%g5] ASI_IRDR, %g5 ! Get IPI handler arg1 + Debugger() + NOTREACHED +#else bgeu,pn %xcc, 3f - nop + sllx %g2, 3, %g5 ! Calculate entry number +#endif + +Lsoftint_regular: + sethi %hi(_C_LABEL(intrlev)), %g3 + or %g3, %lo(_C_LABEL(intrlev)), %g3 ldx [%g3 + %g5], %g5 ! We have a pointer to the handler #ifdef DEBUG brnz,pt %g5, 1f @@ -3285,6 +3295,69 @@ ret_from_intr_vector: ba,a ret_from_intr_vector nop ! XXX spitfire bug? +#ifdef MULTIPROCESSOR +ENTRY(ipi_tlb_page_demap) + rdpr %pstate, %g1 + andn %g1, PSTATE_IE, %g2 + wrpr %g2, %pstate ! disable interrupts + + rdpr %tl, %g2 + brnz %g2, 1f + add %g2, 1, %g4 + wrpr %g0, %g4, %tl ! Switch to traplevel > 0 +1: + mov CTX_PRIMARY, %g4 + andn %g3, 0xfff, %g3 ! drop unused va bits + ldxa [%g4] ASI_DMMU, %g6 ! Save primary context + sethi %hi(KERNBASE), %g7 + membar #LoadStore + stxa %g5, [%g4] ASI_DMMU ! Insert context to demap + membar #Sync + or %g3, DEMAP_PAGE_PRIMARY, %g3 + stxa %g0, [%g3] ASI_DMMU_DEMAP + stxa %g0, [%g3] ASI_IMMU_DEMAP + membar #Sync + flush %g7 + stxa %g6, [%g4] ASI_DMMU + membar #Sync + flush %g7 + + wrpr %g2, %tl + wrpr %g1, %pstate + ba,a ret_from_intr_vector + nop + +ENTRY(ipi_tlb_context_demap) + rdpr %pstate, %g1 + andn %g1, PSTATE_IE, %g2 + wrpr %g2, %pstate ! disable interrupts + + rdpr %tl, %g2 + brnz %g2, 1f + add %g2, 1, %g4 + wrpr %g0, %g4, %tl ! Switch to traplevel > 0 +1: + mov CTX_PRIMARY, %g4 + sethi %hi(KERNBASE), %g7 + ldxa [%g4] ASI_DMMU, %g6 ! Save primary context + membar #LoadStore + stxa %g3, [%g4] ASI_DMMU ! Insert context to demap + membar #Sync + set DEMAP_CTX_PRIMARY, %g3 + stxa %g0, [%g3] ASI_DMMU_DEMAP + stxa %g0, [%g3] ASI_IMMU_DEMAP + membar #Sync + flush %g7 + stxa %g6, [%g4] ASI_DMMU + membar #Sync + flush %g7 + + wrpr %g2, %tl + wrpr %g1, %pstate + ba,a ret_from_intr_vector + nop +#endif + /* * Ultra1 and Ultra2 CPUs use soft interrupts for everything. What we do * on a soft interrupt, is we should check which bits in ASR_SOFTINT(0x16) |