summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2007-09-10 21:33:17 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2007-09-10 21:33:17 +0000
commitb603ad717e260d2b8e25abcc7c8351ff27a51a33 (patch)
tree1b19e5b78b6d98d3869804008e3c3f36172ee843 /sys
parentdf58f470ea4ca0ee9ea2a64cb2b556f7a4176034 (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.sparc645
-rw-r--r--sys/arch/sparc64/sparc64/ipifuncs.c139
-rw-r--r--sys/arch/sparc64/sparc64/locore.s95
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)