summaryrefslogtreecommitdiff
path: root/sys/arch/sgi
diff options
context:
space:
mode:
authorVisa Hankala <visa@cvs.openbsd.org>2015-12-25 09:02:58 +0000
committerVisa Hankala <visa@cvs.openbsd.org>2015-12-25 09:02:58 +0000
commit5430870495c1eaf9405739d118a4cd5945e74b1f (patch)
treefde3a18e0d16eb7b6671efe3b1d2f26dc01197e3 /sys/arch/sgi
parente6fbd07ca4280f36578f4256f610a56b1e4f63b3 (diff)
Add launch logic for secondary CPUs. The PROM's launch entry point address
and function signature are from Linux.
Diffstat (limited to 'sys/arch/sgi')
-rw-r--r--sys/arch/sgi/sgi/ip27.h10
-rw-r--r--sys/arch/sgi/sgi/ip27_machdep.c182
-rw-r--r--sys/arch/sgi/sgi/locore.S27
3 files changed, 216 insertions, 3 deletions
diff --git a/sys/arch/sgi/sgi/ip27.h b/sys/arch/sgi/sgi/ip27.h
index 35618ad12d6..9504e2756e0 100644
--- a/sys/arch/sgi/sgi/ip27.h
+++ b/sys/arch/sgi/sgi/ip27.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip27.h,v 1.5 2015/12/25 08:34:51 visa Exp $ */
+/* $OpenBSD: ip27.h,v 1.6 2015/12/25 09:02:57 visa Exp $ */
/*
* Copyright (c) 2009 Miodrag Vallat.
@@ -55,6 +55,14 @@
#define IP27_IOC_SLOTNO 2
#define IP27_IOC2_SLOTNO 6
+/* PROM entry points */
+
+#define IP27_PROM_LAUNCH_SLAVE 0x1fc00038
+
+#define ip27_prom_launch_slave (*(void (*)(int nasid, int cpu, \
+ void (*func)(uint64_t), uint64_t param, uint64_t sp, \
+ uint64_t gp))PHYS_TO_CKSEG1(IP27_PROM_LAUNCH_SLAVE))
+
/*
* IP27 configuration structure. Used to tell Origin 200 and Origin 2000
* apart.
diff --git a/sys/arch/sgi/sgi/ip27_machdep.c b/sys/arch/sgi/sgi/ip27_machdep.c
index d6bbe6af713..7ee64dbc594 100644
--- a/sys/arch/sgi/sgi/ip27_machdep.c
+++ b/sys/arch/sgi/sgi/ip27_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip27_machdep.c,v 1.68 2015/12/25 08:34:51 visa Exp $ */
+/* $OpenBSD: ip27_machdep.c,v 1.69 2015/12/25 09:02:57 visa Exp $ */
/*
* Copyright (c) 2008, 2009 Miodrag Vallat.
@@ -27,12 +27,14 @@
#include <sys/atomic.h>
#include <sys/device.h>
#include <sys/malloc.h>
+#include <sys/proc.h>
#include <sys/reboot.h>
#include <sys/timetc.h>
#include <sys/tty.h>
#include <mips64/arcbios.h>
#include <mips64/archtype.h>
+#include <mips64/cache.h>
#include <machine/autoconf.h>
#include <machine/bus.h>
@@ -92,6 +94,13 @@ void ip27_nmi(void *);
#ifdef MULTIPROCESSOR
+unsigned int ip27_ncpus;
+
+int ip27_kl_launch_cpu(klinfo_t *, void *);
+int ip27_kl_launch_cpu_board(lboard_t *, void *);
+int ip27_kl_attach_cpu(klinfo_t *, void *);
+int ip27_kl_attach_cpu_board(lboard_t *, void *);
+
uint ip27_hub_get_timecount(struct timecounter *);
struct timecounter ip27_hub_timecounter = {
@@ -103,6 +112,14 @@ struct timecounter ip27_hub_timecounter = {
.tc_quality = 100
};
+volatile uint64_t ip27_spinup_a0;
+volatile uint64_t ip27_spinup_sp;
+volatile uint32_t ip27_spinup_turn = ~0;
+
+#define SPINUP_TICKET(nasid, slice) (((nasid) << 8) | (slice))
+
+void ip27_cpu_spinup_trampoline(uint64_t);
+
#endif /* MULTIPROCESSOR */
/*
@@ -218,6 +235,17 @@ ip27_setup()
if (kl_n_mode != 0)
xbow_long_shift = 28;
+#ifdef MULTIPROCESSOR
+ /*
+ * Pre-launch secondary CPUs with the help of the PROM. This has to be
+ * done now, before tearing down the PROM TLB and disabling interrupts
+ * on the secondary CPUs. The CPUs will wait in the spinup trampoline
+ * until the system launches them for real.
+ */
+ ip27_ncpus = 1;
+ kl_scan_all_nodes(IP27_BC_NODE, ip27_kl_launch_cpu_board, NULL);
+#endif
+
/*
* Initialize the early console parameters.
* This assumes it is either on IOC3 or IOC4, accessible through
@@ -363,6 +391,9 @@ ip27_autoconf(struct device *parent)
* Now attach all nodes' I/O devices.
*/
+#ifdef MULTIPROCESSOR
+ ip27_ncpus = 1;
+#endif
ip27_attach_node(parent, masternasid);
for (node = 0; node < maxnodes; node++) {
if (gda->nasid[node] < 0)
@@ -385,6 +416,11 @@ ip27_attach_node(struct device *parent, int16_t nasid)
currentnasid = nasid;
bzero(&u, sizeof u);
+
+#ifdef MULTIPROCESSOR
+ kl_scan_node(nasid, IP27_BC_NODE, ip27_kl_attach_cpu_board, parent);
+#endif
+
if (ip35) {
l1_display(nasid, TRUE, "OpenBSD/sgi");
@@ -994,10 +1030,154 @@ ip27_nmi(void *arg)
#ifdef MULTIPROCESSOR
+int
+ip27_kl_launch_cpu(klinfo_t *comp, void *arg)
+{
+ struct cpu_info *ci = curcpu();
+
+ /* Skip the running CPU. */
+ if (comp->nasid == ci->ci_nasid &&
+ comp->physid == ci->ci_slice)
+ return 0;
+
+ /* XXX Skip CPUs on other nodes. */
+ if (comp->nasid != ci->ci_nasid)
+ return 0;
+
+ if (ip27_ncpus >= MAXCPUS)
+ return 0;
+
+ ip27_prom_launch_slave(comp->nasid, comp->physid,
+ ip27_cpu_spinup_trampoline,
+ SPINUP_TICKET(comp->nasid, comp->physid), 0, 0);
+ ip27_ncpus++;
+
+ return 0;
+}
+
+int
+ip27_kl_launch_cpu_board(lboard_t *board, void *arg)
+{
+ kl_scan_board(board, KLSTRUCT_CPU, ip27_kl_launch_cpu, arg);
+ return 0;
+}
+
+int
+ip27_kl_attach_cpu(klinfo_t *comp, void *arg)
+{
+ struct cpu_attach_args caa;
+ struct cpu_hwinfo hw;
+ struct cpu_info *ci = curcpu();
+ struct device *parent = arg;
+ klcpu_t *cpucomp;
+
+ /* Skip the running CPU. */
+ if (comp->nasid == ci->ci_nasid &&
+ comp->physid == ci->ci_slice)
+ return 0;
+
+ /* XXX Skip CPUs on other nodes. */
+ if (comp->nasid != ci->ci_nasid)
+ return 0;
+
+ if (ip27_ncpus >= MAXCPUS)
+ return 0;
+
+ cpucomp = (klcpu_t *)comp;
+
+ hw.c0prid = cpucomp->cpu_prid;
+ hw.c1prid = cpucomp->cpu_prid;
+ hw.clock = cpucomp->cpu_speed * 1000000;
+ hw.tlbsize = 64;
+ hw.type = (cpucomp->cpu_prid >> 8) & 0xff;
+
+ caa.caa_maa.maa_name = "cpu";
+ caa.caa_maa.maa_nasid = comp->nasid;
+ caa.caa_maa.maa_physid = comp->physid;
+ caa.caa_hw = &hw;
+ config_found(parent, &caa, ip27_print);
+ ip27_ncpus++;
+
+ return 0;
+}
+
+int
+ip27_kl_attach_cpu_board(lboard_t *board, void *arg)
+{
+ kl_scan_board(board, KLSTRUCT_CPU, ip27_kl_attach_cpu, arg);
+ return 0;
+}
+
uint
ip27_hub_get_timecount(struct timecounter *tc)
{
return IP27_RHUB_L(masternasid, HUBPI_RT_COUNT);
}
+void
+hw_cpu_hatch(struct cpu_info *ci)
+{
+ int s;
+
+ setcurcpu(ci);
+
+ /*
+ * Make sure we can access the extended address space.
+ * Note that r10k and later do not allow XUSEG accesses
+ * from kernel mode unless SR_UX is set.
+ */
+ setsr(getsr() | SR_KX | SR_UX);
+
+ tlb_init(64);
+ tlb_set_pid(0);
+
+ /*
+ * Turn off bootstrap exception vectors.
+ */
+ setsr(getsr() & ~SR_BOOT_EXC_VEC);
+
+ /*
+ * Clear out the I and D caches.
+ */
+ Mips10k_ConfigCache(ci);
+ Mips_SyncCache(ci);
+
+ printf("cpu%lu launched\n", cpu_number());
+
+ (*md_startclock)(ci);
+
+ ncpus++;
+ cpuset_add(&cpus_running, ci);
+
+ mips64_ipi_init();
+ ip27_hub_setintrmask(0);
+
+ spl0();
+ (void)updateimask(0);
+
+ SCHED_LOCK(s);
+ cpu_switchto(NULL, sched_chooseproc());
+}
+
+void
+hw_cpu_boot_secondary(struct cpu_info *ci)
+{
+ vaddr_t kstack;
+
+ kstack = alloc_contiguous_pages(USPACE);
+ if (kstack == 0)
+ panic("unable to allocate idle stack\n");
+
+ __asm__ (".set noreorder\n");
+ ci->ci_curprocpaddr = (void *)kstack;
+ ip27_spinup_a0 = (uint64_t)ci;
+ ip27_spinup_sp = (uint64_t)(kstack + USPACE);
+ mips_sync();
+ __asm__ (".set reorder\n");
+ ip27_spinup_turn = SPINUP_TICKET(ci->ci_nasid, ci->ci_slice);
+
+ while (!cpuset_isset(&cpus_running, ci))
+ ;
+}
+
#endif /* MULTIPROCESSOR */
diff --git a/sys/arch/sgi/sgi/locore.S b/sys/arch/sgi/sgi/locore.S
index 5241eab6054..96a094b42bd 100644
--- a/sys/arch/sgi/sgi/locore.S
+++ b/sys/arch/sgi/sgi/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.16 2015/12/25 05:52:29 visa Exp $ */
+/* $OpenBSD: locore.S,v 1.17 2015/12/25 09:02:57 visa Exp $ */
/*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -127,6 +127,31 @@ LEAF(hw_setcurcpu, 0)
NOP
END(hw_setcurcpu)
+LEAF(ip27_cpu_spinup_trampoline, 0)
+ MFC0 v0, COP_0_STATUS_REG
+ LI v1, ~SR_INT_ENAB
+ and v0, v1
+ MTC0 v0, COP_0_STATUS_REG # Disable all interrupts.
+ MTC0 zero, COP_0_CAUSE_REG # Clear soft interrupts.
+ LA gp, _gp
+
+ /* Wait the turn of this CPU. */
+1: ll v0, ip27_spinup_turn
+ bne v0, a0, 1b
+ not v0, zero
+ sc v0, ip27_spinup_turn
+ beqz v0, 1b
+ nop
+
+ LA v0, ip27_spinup_a0
+ ld a0, 0(v0)
+ LA v0, ip27_spinup_sp
+ ld sp, 0(v0)
+ jal hw_cpu_hatch
+ nop
+ PANIC("secondary CPU start failed")
+END(ip27_cpu_spinup_trampoline)
+
#endif /* TGT_ORIGIN */
#endif /* MULTIPROCESSOR */