diff options
author | Visa Hankala <visa@cvs.openbsd.org> | 2015-12-25 09:02:58 +0000 |
---|---|---|
committer | Visa Hankala <visa@cvs.openbsd.org> | 2015-12-25 09:02:58 +0000 |
commit | 5430870495c1eaf9405739d118a4cd5945e74b1f (patch) | |
tree | fde3a18e0d16eb7b6671efe3b1d2f26dc01197e3 /sys/arch/sgi | |
parent | e6fbd07ca4280f36578f4256f610a56b1e4f63b3 (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.h | 10 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/ip27_machdep.c | 182 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/locore.S | 27 |
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 */ |