summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/sparc64/include/intr_machdep.h3
-rw-r--r--sys/sparc64/include/smp.h156
-rw-r--r--sys/sparc64/sparc64/mp_exception.S169
-rw-r--r--sys/sparc64/sparc64/mp_exception.s169
-rw-r--r--sys/sparc64/sparc64/mp_locore.S137
-rw-r--r--sys/sparc64/sparc64/mp_locore.s137
-rw-r--r--sys/sparc64/sparc64/mp_machdep.c322
7 files changed, 1093 insertions, 0 deletions
diff --git a/sys/sparc64/include/intr_machdep.h b/sys/sparc64/include/intr_machdep.h
index c4991de..165f644 100644
--- a/sys/sparc64/include/intr_machdep.h
+++ b/sys/sparc64/include/intr_machdep.h
@@ -41,6 +41,9 @@
#define PIL_LOW 1 /* stray interrupts */
#define PIL_ITHREAD 2 /* interrupts that use ithreads */
+#define PIL_RENDEZVOUS 3 /* smp rendezvous ipi */
+#define PIL_AST 4 /* ast ipi */
+#define PIL_STOP 5 /* stop cpu ipi */
#define PIL_FAST 13 /* fast interrupts */
#define PIL_TICK 14
diff --git a/sys/sparc64/include/smp.h b/sys/sparc64/include/smp.h
index 57a0f87..d97e191 100644
--- a/sys/sparc64/include/smp.h
+++ b/sys/sparc64/include/smp.h
@@ -29,4 +29,160 @@
#ifndef _MACHINE_SMP_H_
#define _MACHINE_SMP_H_
+#include <machine/intr_machdep.h>
+
+#define CPU_INITING 1
+#define CPU_INITED 2
+#define CPU_REJECT 3
+#define CPU_STARTING 4
+#define CPU_STARTED 5
+#define CPU_BOOTSTRAPING 6
+#define CPU_BOOTSTRAPPED 7
+
+#ifndef LOCORE
+
+#define IDR_BUSY (1<<0)
+#define IDR_NACK (1<<1)
+
+#define IPI_AST PIL_AST
+#define IPI_RENDEZVOUS PIL_RENDEZVOUS
+#define IPI_STOP PIL_STOP
+
+#define IPI_RETRIES 100
+
+struct cpu_start_args {
+ u_int csa_mid;
+ u_int csa_state;
+ u_long csa_data;
+ vm_offset_t csa_va;
+};
+
+struct ipi_level_args {
+ u_int ila_count;
+ u_int ila_level;
+};
+
+struct ipi_tlb_args {
+ u_int ita_count;
+ u_long ita_tlb;
+ u_long ita_ctx;
+ u_long ita_start;
+ u_long ita_end;
+};
+#define ita_va ita_start
+
+struct pcpu;
+
+void cpu_mp_bootstrap(struct pcpu *pc);
+
+void cpu_ipi_selected(u_int cpus, u_long d0, u_long d1, u_long d2);
+void cpu_ipi_send(u_int mid, u_long d0, u_long d1, u_long d2);
+
+void ipi_selected(u_int cpus, u_int ipi);
+void ipi_all(u_int ipi);
+void ipi_all_but_self(u_int ipi);
+
+struct ipi_level_args ipi_level_args;
+struct ipi_tlb_args ipi_tlb_args;
+
+extern int mp_ncpus;
+
+extern char tl_ipi_level[];
+extern char tl_ipi_test[];
+extern char tl_ipi_tlb_context_demap[];
+extern char tl_ipi_tlb_page_demap[];
+extern char tl_ipi_tlb_range_demap[];
+
+#ifdef SMP
+
+static __inline void *
+ipi_tlb_context_demap(u_int ctx)
+{
+ struct ipi_tlb_args *ita;
+
+ if (mp_ncpus == 1)
+ return (NULL);
+ ita = &ipi_tlb_args;
+ ita->ita_count = mp_ncpus;
+ ita->ita_ctx = ctx;
+ cpu_ipi_selected(PCPU_GET(other_cpus), 0,
+ (u_long)tl_ipi_tlb_context_demap, (u_long)ita);
+ return (&ita->ita_count);
+}
+
+static __inline void *
+ipi_tlb_page_demap(u_int tlb, u_int ctx, vm_offset_t va)
+{
+ struct ipi_tlb_args *ita;
+
+ if (mp_ncpus == 1)
+ return (NULL);
+ ita = &ipi_tlb_args;
+ ita->ita_count = mp_ncpus;
+ ita->ita_tlb = tlb;
+ ita->ita_ctx = ctx;
+ ita->ita_va = va;
+ cpu_ipi_selected(PCPU_GET(other_cpus), 0,
+ (u_long)tl_ipi_tlb_page_demap, (u_long)ita);
+ return (&ita->ita_count);
+}
+
+static __inline void *
+ipi_tlb_range_demap(u_int ctx, vm_offset_t start, vm_offset_t end)
+{
+ struct ipi_tlb_args *ita;
+
+ if (mp_ncpus == 1)
+ return (NULL);
+ ita = &ipi_tlb_args;
+ ita->ita_count = mp_ncpus;
+ ita->ita_ctx = ctx;
+ ita->ita_start = start;
+ ita->ita_end = end;
+ cpu_ipi_selected(PCPU_GET(other_cpus), 0,
+ (u_long)tl_ipi_tlb_range_demap, (u_long)ita);
+ return (&ita->ita_count);
+}
+
+static __inline void
+ipi_wait(void *cookie)
+{
+ u_int *count;
+
+ if ((count = cookie) != NULL) {
+ atomic_subtract_int(count, 1);
+ while (*count != 0)
+ membar(LoadStore);
+ }
+}
+
+#else
+
+static __inline void *
+ipi_tlb_context_demap(u_int ctx)
+{
+ return (NULL);
+}
+
+static __inline void *
+ipi_tlb_page_demap(u_int tlb, u_int ctx, vm_offset_t va)
+{
+ return (NULL);
+}
+
+static __inline void *
+ipi_tlb_range_demap(u_int ctx, vm_offset_t start, vm_offset_t end)
+{
+ return (NULL);
+}
+
+static __inline void
+ipi_wait(void *cookie)
+{
+}
+
+#endif /* SMP */
+
+#endif /* !LOCORE */
+
#endif /* !_MACHINE_SMP_H_ */
diff --git a/sys/sparc64/sparc64/mp_exception.S b/sys/sparc64/sparc64/mp_exception.S
new file mode 100644
index 0000000..61e67b0
--- /dev/null
+++ b/sys/sparc64/sparc64/mp_exception.S
@@ -0,0 +1,169 @@
+/*-
+ * Copyright (c) 2002 Jake Burkholder.
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <machine/asi.h>
+#include <machine/ktr.h>
+#include <machine/asmacros.h>
+#include <machine/pstate.h>
+
+#include "assym.s"
+
+ .register %g2, #ignore
+ .register %g3, #ignore
+
+#define IPI_WAIT(r1, r2, r3) \
+ ATOMIC_DEC_INT(r1, r2, r3) ; \
+9: membar #StoreLoad ; \
+ lduw [r1], r2 ; \
+ brnz,a,pn r2, 9b ; \
+ nop
+
+/*
+ * Trigger a softint at the desired level.
+ */
+ENTRY(tl_ipi_level)
+ lduw [%g5 + ILA_LEVEL], %g2
+
+ mov 1, %g1
+ sllx %g1, %g2, %g1
+ wr %g1, 0, %asr20
+
+ IPI_WAIT(%g5, %g1, %g2)
+ retry
+END(tl_ipi_level)
+
+ENTRY(tl_ipi_test)
+#if KTR_COMPILE & KTR_SMP
+ CATR(KTR_SMP, "ipi_test: cpuid=%d mid=%d d1=%#lx d2=%#lx"
+ , %g1, %g2, %g3, 7, 8, 9)
+ lduw [PCPU(CPUID)], %g2
+ stx %g2, [%g1 + KTR_PARM1]
+ lduw [PCPU(MID)], %g2
+ stx %g2, [%g1 + KTR_PARM2]
+ stx %g4, [%g1 + KTR_PARM3]
+ stx %g5, [%g1 + KTR_PARM4]
+9:
+#endif
+ retry
+END(tl_ipi_test)
+
+/*
+ * Demap a page from the dtlb and/or itlb.
+ */
+ENTRY(tl_ipi_tlb_page_demap)
+ ldx [%g5 + ITA_TLB], %g1
+ ldx [%g5 + ITA_CTX], %g2
+ ldx [%g5 + ITA_VA], %g3
+
+ wr %g0, ASI_DMMU, %asi
+
+ brz,a,pt %g2, 1f
+ or %g3, TLB_DEMAP_NUCLEUS | TLB_DEMAP_PAGE, %g3
+
+ stxa %g2, [%g0 + AA_DMMU_SCXR] %asi
+ membar #Sync
+ or %g3, TLB_DEMAP_SECONDARY | TLB_DEMAP_PAGE, %g3
+
+1: andcc %g1, TLB_DTLB, %g0
+ bz,a,pn %xcc, 2f
+ nop
+ stxa %g0, [%g3] ASI_DMMU_DEMAP
+
+2: andcc %g1, TLB_ITLB, %g0
+ bz,a,pn %xcc, 3f
+ nop
+ stxa %g0, [%g3] ASI_IMMU_DEMAP
+
+3: brz,a,pt %g2, 4f
+ nop
+ stxa %g0, [%g0 + AA_DMMU_SCXR] %asi
+
+4: membar #Sync
+
+ IPI_WAIT(%g5, %g1, %g2)
+ retry
+END(tl_ipi_tlb_page_demap)
+
+/*
+ * Demap a range of pages from the dtlb and itlb.
+ */
+ENTRY(tl_ipi_tlb_range_demap)
+ ldx [%g5 + ITA_CTX], %g1
+ ldx [%g5 + ITA_START], %g2
+ ldx [%g5 + ITA_END], %g3
+
+ wr %g0, ASI_DMMU, %asi
+
+ brz,a,pt %g1, 1f
+ mov TLB_DEMAP_NUCLEUS | TLB_DEMAP_PAGE, %g4
+
+ stxa %g1, [%g0 + AA_DMMU_SCXR] %asi
+ membar #Sync
+ mov TLB_DEMAP_SECONDARY | TLB_DEMAP_PAGE, %g4
+
+1: set PAGE_SIZE, %g5
+
+2: or %g4, %g2, %g4
+ stxa %g0, [%g4] ASI_DMMU_DEMAP
+ stxa %g0, [%g4] ASI_IMMU_DEMAP
+
+ add %g2, %g5, %g2
+ cmp %g2, %g3
+ bne,a,pt %xcc, 2b
+ nop
+
+ brz,a,pt %g1, 3f
+ nop
+ stxa %g0, [%g0 + AA_DMMU_SCXR] %asi
+
+3: membar #Sync
+
+ IPI_WAIT(%g5, %g1, %g2)
+ retry
+END(tl_ipi_tlb_range_demap)
+
+/*
+ * Demap an entire context from the dtlb and itlb.
+ */
+ENTRY(tl_ipi_tlb_context_demap)
+ ldx [%g5 + ITA_CTX], %g1
+
+ mov AA_DMMU_SCXR, %g2
+ stxa %g1, [%g2] ASI_DMMU
+ membar #Sync
+
+ mov TLB_DEMAP_SECONDARY | TLB_DEMAP_CONTEXT, %g3
+ stxa %g0, [%g3] ASI_DMMU_DEMAP
+ stxa %g0, [%g3] ASI_IMMU_DEMAP
+
+ stxa %g0, [%g2] ASI_DMMU
+ membar #Sync
+
+ IPI_WAIT(%g5, %g1, %g2)
+ retry
+END(tl_ipi_tlb_context_demap)
diff --git a/sys/sparc64/sparc64/mp_exception.s b/sys/sparc64/sparc64/mp_exception.s
new file mode 100644
index 0000000..61e67b0
--- /dev/null
+++ b/sys/sparc64/sparc64/mp_exception.s
@@ -0,0 +1,169 @@
+/*-
+ * Copyright (c) 2002 Jake Burkholder.
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <machine/asi.h>
+#include <machine/ktr.h>
+#include <machine/asmacros.h>
+#include <machine/pstate.h>
+
+#include "assym.s"
+
+ .register %g2, #ignore
+ .register %g3, #ignore
+
+#define IPI_WAIT(r1, r2, r3) \
+ ATOMIC_DEC_INT(r1, r2, r3) ; \
+9: membar #StoreLoad ; \
+ lduw [r1], r2 ; \
+ brnz,a,pn r2, 9b ; \
+ nop
+
+/*
+ * Trigger a softint at the desired level.
+ */
+ENTRY(tl_ipi_level)
+ lduw [%g5 + ILA_LEVEL], %g2
+
+ mov 1, %g1
+ sllx %g1, %g2, %g1
+ wr %g1, 0, %asr20
+
+ IPI_WAIT(%g5, %g1, %g2)
+ retry
+END(tl_ipi_level)
+
+ENTRY(tl_ipi_test)
+#if KTR_COMPILE & KTR_SMP
+ CATR(KTR_SMP, "ipi_test: cpuid=%d mid=%d d1=%#lx d2=%#lx"
+ , %g1, %g2, %g3, 7, 8, 9)
+ lduw [PCPU(CPUID)], %g2
+ stx %g2, [%g1 + KTR_PARM1]
+ lduw [PCPU(MID)], %g2
+ stx %g2, [%g1 + KTR_PARM2]
+ stx %g4, [%g1 + KTR_PARM3]
+ stx %g5, [%g1 + KTR_PARM4]
+9:
+#endif
+ retry
+END(tl_ipi_test)
+
+/*
+ * Demap a page from the dtlb and/or itlb.
+ */
+ENTRY(tl_ipi_tlb_page_demap)
+ ldx [%g5 + ITA_TLB], %g1
+ ldx [%g5 + ITA_CTX], %g2
+ ldx [%g5 + ITA_VA], %g3
+
+ wr %g0, ASI_DMMU, %asi
+
+ brz,a,pt %g2, 1f
+ or %g3, TLB_DEMAP_NUCLEUS | TLB_DEMAP_PAGE, %g3
+
+ stxa %g2, [%g0 + AA_DMMU_SCXR] %asi
+ membar #Sync
+ or %g3, TLB_DEMAP_SECONDARY | TLB_DEMAP_PAGE, %g3
+
+1: andcc %g1, TLB_DTLB, %g0
+ bz,a,pn %xcc, 2f
+ nop
+ stxa %g0, [%g3] ASI_DMMU_DEMAP
+
+2: andcc %g1, TLB_ITLB, %g0
+ bz,a,pn %xcc, 3f
+ nop
+ stxa %g0, [%g3] ASI_IMMU_DEMAP
+
+3: brz,a,pt %g2, 4f
+ nop
+ stxa %g0, [%g0 + AA_DMMU_SCXR] %asi
+
+4: membar #Sync
+
+ IPI_WAIT(%g5, %g1, %g2)
+ retry
+END(tl_ipi_tlb_page_demap)
+
+/*
+ * Demap a range of pages from the dtlb and itlb.
+ */
+ENTRY(tl_ipi_tlb_range_demap)
+ ldx [%g5 + ITA_CTX], %g1
+ ldx [%g5 + ITA_START], %g2
+ ldx [%g5 + ITA_END], %g3
+
+ wr %g0, ASI_DMMU, %asi
+
+ brz,a,pt %g1, 1f
+ mov TLB_DEMAP_NUCLEUS | TLB_DEMAP_PAGE, %g4
+
+ stxa %g1, [%g0 + AA_DMMU_SCXR] %asi
+ membar #Sync
+ mov TLB_DEMAP_SECONDARY | TLB_DEMAP_PAGE, %g4
+
+1: set PAGE_SIZE, %g5
+
+2: or %g4, %g2, %g4
+ stxa %g0, [%g4] ASI_DMMU_DEMAP
+ stxa %g0, [%g4] ASI_IMMU_DEMAP
+
+ add %g2, %g5, %g2
+ cmp %g2, %g3
+ bne,a,pt %xcc, 2b
+ nop
+
+ brz,a,pt %g1, 3f
+ nop
+ stxa %g0, [%g0 + AA_DMMU_SCXR] %asi
+
+3: membar #Sync
+
+ IPI_WAIT(%g5, %g1, %g2)
+ retry
+END(tl_ipi_tlb_range_demap)
+
+/*
+ * Demap an entire context from the dtlb and itlb.
+ */
+ENTRY(tl_ipi_tlb_context_demap)
+ ldx [%g5 + ITA_CTX], %g1
+
+ mov AA_DMMU_SCXR, %g2
+ stxa %g1, [%g2] ASI_DMMU
+ membar #Sync
+
+ mov TLB_DEMAP_SECONDARY | TLB_DEMAP_CONTEXT, %g3
+ stxa %g0, [%g3] ASI_DMMU_DEMAP
+ stxa %g0, [%g3] ASI_IMMU_DEMAP
+
+ stxa %g0, [%g2] ASI_DMMU
+ membar #Sync
+
+ IPI_WAIT(%g5, %g1, %g2)
+ retry
+END(tl_ipi_tlb_context_demap)
diff --git a/sys/sparc64/sparc64/mp_locore.S b/sys/sparc64/sparc64/mp_locore.S
new file mode 100644
index 0000000..cb81e6c
--- /dev/null
+++ b/sys/sparc64/sparc64/mp_locore.S
@@ -0,0 +1,137 @@
+/*-
+ * Copyright (c) 2002 Jake Burkholder.
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <machine/asi.h>
+#include <machine/asmacros.h>
+#include <machine/ktr.h>
+#include <machine/pstate.h>
+
+#include "assym.s"
+
+ .register %g2, #ignore
+ .register %g3, #ignore
+
+/*
+ * void _mp_start(u_long o0, u_int *state, u_int mid, u_long o3, u_long o4)
+ */
+ENTRY(_mp_start)
+ /*
+ * Give away our stack to another processor that may be starting in the
+ * loader.
+ */
+ clr %sp
+
+ /*
+ * Inform the boot processor which is waiting in the loader that we
+ * made it.
+ */
+ mov CPU_INITED, %l0
+ stw %l0, [%o1]
+ membar #StoreLoad
+
+#if KTR_COMPILE & KTR_SMP
+ CATR(KTR_SMP, "_mp_start: cpu %d entered kernel"
+ , %g1, %g2, %g3, 7, 8, 9)
+ stx %o2, [%g1 + KTR_PARM1]
+9:
+#endif
+
+ SET(cpu_start_args, %l1, %l0)
+
+ /*
+ * Wait till its our turn to start.
+ */
+1: membar #StoreLoad
+ lduw [%l0 + CSA_MID], %l1
+ cmp %l1, %o2
+ bne %xcc, 1b
+ nop
+
+#if KTR_COMPILE & KTR_SMP
+ CATR(KTR_SMP, "_mp_start: cpu %d got start signal"
+ , %g1, %g2, %g3, 7, 8, 9)
+ stx %o2, [%g1 + KTR_PARM1]
+9:
+#endif
+
+ /*
+ * Find our per-cpu page and the tte data that we will use to map it.
+ */
+ ldx [%l0 + CSA_DATA], %l1
+ ldx [%l0 + CSA_VA], %l2
+
+ /*
+ * Map the per-cpu page. It uses a locked tlb entry.
+ */
+ wr %g0, ASI_DMMU, %asi
+ stxa %l2, [%g0 + AA_DMMU_TAR] %asi
+ stxa %l1, [%g0] ASI_DTLB_DATA_IN_REG
+ membar #Sync
+
+ /*
+ * Get onto our per-cpu panic stack, which precedes the struct pcpu
+ * in the per-cpu page.
+ */
+ set PAGE_SIZE - PC_SIZEOF, %l3
+ add %l2, %l3, %l2
+ sub %l2, SPOFF + CCFSZ, %sp
+
+ /*
+ * Inform the boot processor that we're about to start.
+ */
+ mov CPU_STARTED, %l3
+ stw %l3, [%l0 + CSA_STATE]
+ membar #StoreLoad
+
+ /*
+ * Enable interrupts.
+ */
+ wrpr %g0, PSTATE_KERNEL, %pstate
+
+#if KTR_COMPILE & KTR_SMP
+ CATR(KTR_SMP,
+ "_mp_start: bootstrap cpuid=%d mid=%d pcpu=%#lx data=%#lx sp=%#lx"
+ , %g1, %g2, %g3, 7, 8, 9)
+ lduw [%l2 + PC_CPUID], %g2
+ stx %g2, [%g1 + KTR_PARM1]
+ lduw [%l2 + PC_MID], %g2
+ stx %g2, [%g1 + KTR_PARM2]
+ stx %l2, [%g1 + KTR_PARM3]
+ stx %l1, [%g1 + KTR_PARM4]
+ stx %sp, [%g1 + KTR_PARM5]
+9:
+#endif
+
+ /*
+ * And away we go. This doesn't return.
+ */
+ call cpu_mp_bootstrap
+ mov %l2, %o0
+ sir
+ ! NOTREACHED
+END(_mp_start)
diff --git a/sys/sparc64/sparc64/mp_locore.s b/sys/sparc64/sparc64/mp_locore.s
new file mode 100644
index 0000000..cb81e6c
--- /dev/null
+++ b/sys/sparc64/sparc64/mp_locore.s
@@ -0,0 +1,137 @@
+/*-
+ * Copyright (c) 2002 Jake Burkholder.
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <machine/asi.h>
+#include <machine/asmacros.h>
+#include <machine/ktr.h>
+#include <machine/pstate.h>
+
+#include "assym.s"
+
+ .register %g2, #ignore
+ .register %g3, #ignore
+
+/*
+ * void _mp_start(u_long o0, u_int *state, u_int mid, u_long o3, u_long o4)
+ */
+ENTRY(_mp_start)
+ /*
+ * Give away our stack to another processor that may be starting in the
+ * loader.
+ */
+ clr %sp
+
+ /*
+ * Inform the boot processor which is waiting in the loader that we
+ * made it.
+ */
+ mov CPU_INITED, %l0
+ stw %l0, [%o1]
+ membar #StoreLoad
+
+#if KTR_COMPILE & KTR_SMP
+ CATR(KTR_SMP, "_mp_start: cpu %d entered kernel"
+ , %g1, %g2, %g3, 7, 8, 9)
+ stx %o2, [%g1 + KTR_PARM1]
+9:
+#endif
+
+ SET(cpu_start_args, %l1, %l0)
+
+ /*
+ * Wait till its our turn to start.
+ */
+1: membar #StoreLoad
+ lduw [%l0 + CSA_MID], %l1
+ cmp %l1, %o2
+ bne %xcc, 1b
+ nop
+
+#if KTR_COMPILE & KTR_SMP
+ CATR(KTR_SMP, "_mp_start: cpu %d got start signal"
+ , %g1, %g2, %g3, 7, 8, 9)
+ stx %o2, [%g1 + KTR_PARM1]
+9:
+#endif
+
+ /*
+ * Find our per-cpu page and the tte data that we will use to map it.
+ */
+ ldx [%l0 + CSA_DATA], %l1
+ ldx [%l0 + CSA_VA], %l2
+
+ /*
+ * Map the per-cpu page. It uses a locked tlb entry.
+ */
+ wr %g0, ASI_DMMU, %asi
+ stxa %l2, [%g0 + AA_DMMU_TAR] %asi
+ stxa %l1, [%g0] ASI_DTLB_DATA_IN_REG
+ membar #Sync
+
+ /*
+ * Get onto our per-cpu panic stack, which precedes the struct pcpu
+ * in the per-cpu page.
+ */
+ set PAGE_SIZE - PC_SIZEOF, %l3
+ add %l2, %l3, %l2
+ sub %l2, SPOFF + CCFSZ, %sp
+
+ /*
+ * Inform the boot processor that we're about to start.
+ */
+ mov CPU_STARTED, %l3
+ stw %l3, [%l0 + CSA_STATE]
+ membar #StoreLoad
+
+ /*
+ * Enable interrupts.
+ */
+ wrpr %g0, PSTATE_KERNEL, %pstate
+
+#if KTR_COMPILE & KTR_SMP
+ CATR(KTR_SMP,
+ "_mp_start: bootstrap cpuid=%d mid=%d pcpu=%#lx data=%#lx sp=%#lx"
+ , %g1, %g2, %g3, 7, 8, 9)
+ lduw [%l2 + PC_CPUID], %g2
+ stx %g2, [%g1 + KTR_PARM1]
+ lduw [%l2 + PC_MID], %g2
+ stx %g2, [%g1 + KTR_PARM2]
+ stx %l2, [%g1 + KTR_PARM3]
+ stx %l1, [%g1 + KTR_PARM4]
+ stx %sp, [%g1 + KTR_PARM5]
+9:
+#endif
+
+ /*
+ * And away we go. This doesn't return.
+ */
+ call cpu_mp_bootstrap
+ mov %l2, %o0
+ sir
+ ! NOTREACHED
+END(_mp_start)
diff --git a/sys/sparc64/sparc64/mp_machdep.c b/sys/sparc64/sparc64/mp_machdep.c
new file mode 100644
index 0000000..d5a73d3
--- /dev/null
+++ b/sys/sparc64/sparc64/mp_machdep.c
@@ -0,0 +1,322 @@
+/*-
+ * Copyright (c) 1997 Berkeley Software Design, 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. Berkeley Software Design Inc's name may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``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 BERKELEY SOFTWARE DESIGN INC 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.
+ *
+ * from BSDI: locore.s,v 1.36.2.15 1999/08/23 22:34:41 cp Exp
+ */
+/*-
+ * Copyright (c) 2002 Jake Burkholder.
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/mutex.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/smp.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_map.h>
+
+#include <dev/ofw/openfirm.h>
+
+#include <machine/asi.h>
+#include <machine/md_var.h>
+#include <machine/smp.h>
+#include <machine/tte.h>
+
+static ih_func_t cpu_ipi_ast;
+static ih_func_t cpu_ipi_stop;
+
+/*
+ * Argument area used to pass data to non-boot processors as they start up.
+ * This must be statically initialized with a known invalid upa module id,
+ * since the other processors will use it before the boot cpu enters the
+ * kernel.
+ */
+struct cpu_start_args cpu_start_args = { -1, -1, 0, 0 };
+
+static struct mtx ap_boot_mtx;
+
+u_int mp_boot_mid;
+
+/*
+ * Probe for other cpus.
+ */
+int
+cpu_mp_probe(void)
+{
+ phandle_t child;
+ phandle_t root;
+ char buf[128];
+ int cpus;
+
+ all_cpus = 1 << PCPU_GET(cpuid);
+ mp_boot_mid = PCPU_GET(mid);
+ mp_ncpus = 1;
+
+ cpus = 0;
+ root = OF_peer(0);
+ for (child = OF_child(root); child != 0; child = OF_peer(child)) {
+ if (OF_getprop(child, "device_type", buf, sizeof(buf)) > 0 &&
+ strcmp(buf, "cpu") == 0)
+ cpus++;
+ }
+ return (cpus > 1);
+}
+
+/*
+ * Fire up any non-boot processors.
+ */
+void
+cpu_mp_start(void)
+{
+ volatile struct cpu_start_args *csa;
+ struct pcpu *pc;
+ phandle_t child;
+ phandle_t root;
+ vm_offset_t pa;
+ vm_offset_t va;
+ char buf[128];
+ u_long data;
+ u_int mid;
+ int cpuid;
+
+ mtx_init(&ap_boot_mtx, "ap boot", MTX_SPIN);
+
+ intr_setup(PIL_AST, cpu_ipi_ast, -1, NULL, NULL);
+ intr_setup(PIL_RENDEZVOUS, (ih_func_t *)smp_rendezvous_action,
+ -1, NULL, NULL);
+ intr_setup(PIL_STOP, cpu_ipi_stop, -1, NULL, NULL);
+
+ root = OF_peer(0);
+ csa = &cpu_start_args;
+ for (child = OF_child(root); child != 0; child = OF_peer(child)) {
+ if (OF_getprop(child, "device_type", buf, sizeof(buf)) <= 0 ||
+ strcmp(buf, "cpu") != 0)
+ continue;
+ if (OF_getprop(child, "upa-portid", &mid, sizeof(mid)) <= 0)
+ panic("cpu_mp_start: can't get module id");
+ if (mid == mp_boot_mid)
+ continue;
+
+ /*
+ * Found a non-boot processor. It is currently spinning in
+ * _mp_start, and it has no stack. Allocate a per-cpu page
+ * for it, which it will use as a bootstrap stack, and pass
+ * it through the argument area.
+ */
+ cpuid = mp_ncpus++;
+ va = kmem_alloc(kernel_map, PAGE_SIZE);
+ pa = pmap_kextract(va);
+ if (pa == 0)
+ panic("cpu_mp_start: pmap_kextract\n");
+ pc = (struct pcpu *)(va + PAGE_SIZE) - 1;
+ pcpu_init(pc, cpuid, sizeof(*pc));
+ pc->pc_mid = mid;
+ data = TD_V | TD_8K | TD_VA_LOW(va) | TD_PA(pa) |
+ TD_L | TD_CP | TD_CV | TD_P | TD_W;
+
+ /*
+ * Initialize the argument area to start this cpu.
+ * Note, order is important here. We must set the pcpu pointer
+ * and the tte data before letting it loose.
+ */
+ csa->csa_data = data;
+ csa->csa_va = va;
+ membar(StoreLoad);
+ csa->csa_mid = mid;
+ csa->csa_state = CPU_STARTING;
+ while (csa->csa_state == CPU_STARTING)
+ membar(StoreLoad);
+ if (csa->csa_state != CPU_STARTED)
+ panic("cpu_mp_start: bad state %d for cpu %d\n",
+ csa->csa_state, mid);
+ csa->csa_state = CPU_BOOTSTRAPING;
+ while (csa->csa_state == CPU_BOOTSTRAPING)
+ membar(StoreLoad);
+ if (csa->csa_state != CPU_BOOTSTRAPPED)
+ panic("cpu_mp_start: bad state %d for cpu %d\n",
+ csa->csa_state, mid);
+ cpu_ipi_send(mid, 0, (u_long)tl_ipi_test, 0);
+ all_cpus |= 1 << cpuid;
+ }
+ PCPU_SET(other_cpus, all_cpus & ~(1 << PCPU_GET(cpuid)));
+}
+
+void
+cpu_mp_announce(void)
+{
+ TODO;
+}
+
+void
+cpu_mp_bootstrap(struct pcpu *pc)
+{
+ struct cpu_start_args *csa;
+
+ csa = &cpu_start_args;
+ CTR1(KTR_SMP, "cpu_mp_bootstrap: cpuid=%d", pc->pc_cpuid);
+ while (csa->csa_state != CPU_BOOTSTRAPING)
+ membar(StoreLoad);
+ cpu_setregs(pc);
+ pmap_map_tsb();
+
+ CTR0(KTR_SMP, "cpu_mp_bootstrap: spinning");
+ csa->csa_state = CPU_BOOTSTRAPPED;
+ membar(StoreLoad);
+ for (;;)
+ ;
+
+ mtx_lock_spin(&ap_boot_mtx);
+
+ CTR1(KTR_SMP, "SMP: AP CPU #%d Launched", PCPU_GET(cpuid));
+
+ smp_cpus++;
+
+ /* Build our map of 'other' CPUs. */
+ PCPU_SET(other_cpus, all_cpus & ~(1 << PCPU_GET(cpuid)));
+
+ printf("SMP: AP CPU #%d Launched!\n", PCPU_GET(cpuid));
+
+ if (smp_cpus == mp_ncpus) {
+ smp_started = 1; /* enable IPI's, tlb shootdown, freezes etc */
+ smp_active = 1; /* historic */
+ }
+
+ mtx_unlock_spin(&ap_boot_mtx);
+
+ /* wait until all the AP's are up */
+ while (smp_started == 0)
+ ; /* nothing */
+
+ microuptime(PCPU_PTR(switchtime));
+ PCPU_SET(switchticks, ticks);
+
+ /* ok, now grab sched_lock and enter the scheduler */
+ mtx_lock_spin(&sched_lock);
+ cpu_throw(); /* doesn't return */
+}
+
+static void
+cpu_ipi_ast(struct trapframe *tf)
+{
+}
+
+static void
+cpu_ipi_stop(struct trapframe *tf)
+{
+ TODO;
+}
+
+void
+cpu_ipi_selected(u_int cpus, u_long d0, u_long d1, u_long d2)
+{
+ struct pcpu *pc;
+ u_int cpu;
+
+ while (cpus) {
+ cpu = ffs(cpus) - 1;
+ cpus &= ~(1 << cpu);
+ pc = pcpu_find(cpu);
+ cpu_ipi_send(pc->pc_mid, d0, d1, d2);
+ }
+}
+
+void
+cpu_ipi_send(u_int mid, u_long d0, u_long d1, u_long d2)
+{
+ u_long pstate;
+ int i;
+
+ KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) & IDR_BUSY) == 0,
+ ("ipi_send: outstanding dispatch"));
+ pstate = rdpr(pstate);
+ for (i = 0; i < IPI_RETRIES; i++) {
+ if (pstate & PSTATE_IE)
+ wrpr(pstate, pstate, PSTATE_IE);
+ stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0);
+ stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1);
+ stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2);
+ stxa(AA_INTR_SEND | (mid << 14), ASI_SDB_INTR_W, 0);
+ membar(Sync);
+ while (ldxa(0, ASI_INTR_DISPATCH_STATUS) & IDR_BUSY)
+ ;
+ wrpr(pstate, pstate, 0);
+ if ((ldxa(0, ASI_INTR_DISPATCH_STATUS) & IDR_NACK) == 0)
+ return;
+ }
+ panic("ipi_send: couldn't send ipi");
+}
+
+void
+ipi_selected(u_int cpus, u_int ipi)
+{
+ cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_level, ipi);
+}
+
+void
+ipi_all(u_int ipi)
+{
+ TODO;
+}
+
+void
+ipi_all_but_self(u_int ipi)
+{
+ cpu_ipi_selected(PCPU_GET(other_cpus), 0, (u_long)tl_ipi_level, ipi);
+}
OpenPOWER on IntegriCloud