Module Name: src Committed By: skrll Date: Sun Jan 23 21:53:40 UTC 2011
Modified Files: src/sys/arch/hp700/dev: cpu.c src/sys/arch/hp700/hp700: genassym.cf locore.S machdep.c mainbus.c src/sys/arch/hp700/include: cpu.h src/sys/arch/hppa/hppa: machdep.h Log Message: Detect and spin up non-boot CPUs. Mostly from OpenBSD. To generate a diff of this commit: cvs rdiff -u -r1.16 -r1.17 src/sys/arch/hp700/dev/cpu.c cvs rdiff -u -r1.30 -r1.31 src/sys/arch/hp700/hp700/genassym.cf cvs rdiff -u -r1.52 -r1.53 src/sys/arch/hp700/hp700/locore.S cvs rdiff -u -r1.97 -r1.98 src/sys/arch/hp700/hp700/machdep.c cvs rdiff -u -r1.76 -r1.77 src/sys/arch/hp700/hp700/mainbus.c cvs rdiff -u -r1.59 -r1.60 src/sys/arch/hp700/include/cpu.h cvs rdiff -u -r1.14 -r1.15 src/sys/arch/hppa/hppa/machdep.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/hp700/dev/cpu.c diff -u src/sys/arch/hp700/dev/cpu.c:1.16 src/sys/arch/hp700/dev/cpu.c:1.17 --- src/sys/arch/hp700/dev/cpu.c:1.16 Wed Dec 8 09:48:27 2010 +++ src/sys/arch/hp700/dev/cpu.c Sun Jan 23 21:53:39 2011 @@ -1,6 +1,6 @@ -/* $NetBSD: cpu.c,v 1.16 2010/12/08 09:48:27 skrll Exp $ */ +/* $NetBSD: cpu.c,v 1.17 2011/01/23 21:53:39 skrll Exp $ */ -/* $OpenBSD: cpu.c,v 1.28 2004/12/28 05:18:25 mickey Exp $ */ +/* $OpenBSD: cpu.c,v 1.29 2009/02/08 18:33:28 miod Exp $ */ /* * Copyright (c) 1998-2003 Michael Shalayeff @@ -29,13 +29,17 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.16 2010/12/08 09:48:27 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.17 2011/01/23 21:53:39 skrll Exp $"); + +#include "opt_multiprocessor.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/reboot.h> +#include <uvm/uvm.h> + #include <machine/cpufunc.h> #include <machine/pdc.h> #include <machine/iomod.h> @@ -53,6 +57,9 @@ #ifdef MULTIPROCESSOR int hppa_ncpus; + +struct cpu_info *cpu_hatch_info; +static volatile int start_secondary_cpu; #endif int cpumatch(device_t, cfdata_t, void *); @@ -61,20 +68,19 @@ CFATTACH_DECL_NEW(cpu, sizeof(struct cpu_softc), cpumatch, cpuattach, NULL, NULL); -static int cpu_attached; - int cpumatch(device_t parent, cfdata_t cf, void *aux) { struct confargs *ca = aux; - /* there will be only one for now XXX */ /* probe any 1.0, 1.1 or 2.0 */ - if (cpu_attached || - ca->ca_type.iodc_type != HPPA_TYPE_NPROC || + if (ca->ca_type.iodc_type != HPPA_TYPE_NPROC || ca->ca_type.iodc_sv_model != HPPA_NPROC_HPPA) return 0; + if (cf->cf_unit >= MAXCPUS) + return 0; + return 1; } @@ -89,11 +95,22 @@ struct cpu_softc *sc = device_private(self); struct confargs *ca = aux; - const char lvls[4][4] = { "0", "1", "1.5", "2" }; + struct cpu_info *ci; + static const char lvls[4][4] = { "0", "1", "1.5", "2" }; u_int mhz = 100 * cpu_ticksnum / cpu_ticksdenom; + int cpuno = device_unit(self); + +#ifdef MULTIPROCESSOR + struct pglist mlist; + struct vm_page *m; + int error; +#endif sc->sc_dev = self; - cpu_attached = 1; + + ci = &cpus[cpuno]; + ci->ci_cpuid = cpuno; + ci->ci_hpa = ca->ca_hpa; /* Print the CPU chip name, nickname, and rev. */ aprint_normal(": %s", hppa_cpu_info->hci_chip_name); @@ -151,12 +168,42 @@ aprint_normal("\n"); /* sanity against luser amongst config editors */ - if (ca->ca_irq == 31) { - sc->sc_ih = hp700_intr_establish(IPL_CLOCK, clock_intr, - NULL /*clockframe*/, &int_reg_cpu, ca->ca_irq); - } else { + if (ca->ca_irq != 31) { aprint_error_dev(self, "bad irq number %d\n", ca->ca_irq); + return; } + + sc->sc_ih = hp700_intr_establish(IPL_CLOCK, clock_intr, + NULL /*clockframe*/, &int_reg_cpu, 31); + +#ifdef MULTIPROCESSOR + + /* Allocate stack for spin up and FPU emulation. */ + TAILQ_INIT(&mlist); + error = uvm_pglistalloc(PAGE_SIZE, 0, -1L, PAGE_SIZE, 0, &mlist, 1, + 0); + + if (error) { + aprint_error(": unable to allocate CPU stack!\n"); + return; + } + m = TAILQ_FIRST(&mlist); + ci->ci_stack = VM_PAGE_TO_PHYS(m); + + if (ci->ci_hpa == hppa_mcpuhpa) { + ci->ci_flags |= CPUF_PRIMARY|CPUF_RUNNING; + } else { + int err; + + err = mi_cpu_attach(ci); + if (err) { + aprint_error_dev(self, + "mi_cpu_attach failed with %d\n", err); + return; + } + } + +#endif /* * Set the allocatable bits in the CPU interrupt registers. @@ -168,3 +215,77 @@ int_reg_cpu.int_reg_allocatable_bits = (1 << 28) | (1 << 27) | (1 << 26); } + + +#ifdef MULTIPROCESSOR +void +cpu_boot_secondary_processors(void) +{ + struct cpu_info *ci; + struct iomod *cpu; + int i, j; + + for (i = 0; i < HPPA_MAXCPUS; i++) { + + ci = &cpus[i]; + if (ci->ci_cpuid == 0) + continue; + + if (ci->ci_data.cpu_idlelwp == NULL) + continue; + + if (ci->ci_flags & CPUF_PRIMARY) + continue; + + /* Release the specified CPU by triggering an EIR{0}. */ + cpu_hatch_info = ci; + cpu = (struct iomod *)(ci->ci_hpa); + cpu->io_eir = 0; + membar_sync(); + + /* Wait for CPU to wake up... */ + j = 0; + while (!(ci->ci_flags & CPUF_RUNNING) && j++ < 10000) + delay(1000); + if (!(ci->ci_flags & CPUF_RUNNING)) + printf("failed to hatch cpu %i!\n", ci->ci_cpuid); + } + + /* Release secondary CPUs. */ + start_secondary_cpu = 1; + membar_sync(); +} + +void +cpu_hw_init(void) +{ + struct cpu_info *ci = curcpu(); + + /* Purge TLB and flush caches. */ + ptlball(); + fcacheall(); + + /* Enable address translations. */ + ci->ci_psw = PSW_I | PSW_Q | PSW_P | PSW_C | PSW_D; + ci->ci_psw |= (cpus[0].ci_psw & PSW_O); + + ci->ci_curlwp = ci->ci_data.cpu_idlelwp; +} + +void +cpu_hatch(void) +{ + struct cpu_info *ci = curcpu(); + + ci->ci_flags |= CPUF_RUNNING; + + /* Wait for additional CPUs to spinup. */ + while (!start_secondary_cpu) + ; + + /* Spin for now */ + for (;;) + ; + +} +#endif Index: src/sys/arch/hp700/hp700/genassym.cf diff -u src/sys/arch/hp700/hp700/genassym.cf:1.30 src/sys/arch/hp700/hp700/genassym.cf:1.31 --- src/sys/arch/hp700/hp700/genassym.cf:1.30 Sun Jan 23 09:44:58 2011 +++ src/sys/arch/hp700/hp700/genassym.cf Sun Jan 23 21:53:39 2011 @@ -1,4 +1,4 @@ -# $NetBSD: genassym.cf,v 1.30 2011/01/23 09:44:58 skrll Exp $ +# $NetBSD: genassym.cf,v 1.31 2011/01/23 21:53:39 skrll Exp $ # $OpenBSD: genassym.cf,v 1.18 2001/09/20 18:31:14 mickey Exp $ @@ -101,9 +101,9 @@ define CI_FPU_STATE offsetof(struct cpu_info, ci_fpu_state) ifdef MULTIPROCESSOR define CI_CURLWP offsetof(struct cpu_info, ci_curlwp) +define CI_STACK offsetof(struct cpu_info, ci_stack) endif - define MTX_IPL offsetof(struct kmutex, mtx_ipl) define MTX_LOCK offsetof(struct kmutex, mtx_lock) define MTX_OWNER offsetof(struct kmutex, mtx_owner) Index: src/sys/arch/hp700/hp700/locore.S diff -u src/sys/arch/hp700/hp700/locore.S:1.52 src/sys/arch/hp700/hp700/locore.S:1.53 --- src/sys/arch/hp700/hp700/locore.S:1.52 Sun Jan 23 09:44:58 2011 +++ src/sys/arch/hp700/hp700/locore.S Sun Jan 23 21:53:39 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: locore.S,v 1.52 2011/01/23 09:44:58 skrll Exp $ */ +/* $NetBSD: locore.S,v 1.53 2011/01/23 21:53:39 skrll Exp $ */ /* $OpenBSD: locore.S,v 1.158 2008/07/28 19:08:46 miod Exp $ */ /* @@ -258,6 +258,18 @@ */ mtctl %r0, %ccr +#ifdef MULTIPROCESSOR + +#define PZ_MEM_RENDEZ 0x10 +#define PZ_MEM_RENDEZ_HI 0x28 + + /* Setup SMP rendezvous address. */ + ldil L%hw_cpu_spinup_trampoline, %r1 + ldo R%hw_cpu_spinup_trampoline(%r1), %r1 + stw %r1, PZ_MEM_RENDEZ(%r0) + stw %r0, PZ_MEM_RENDEZ_HI(%r0) +#endif + /* * We need to set the Q bit so that we can take TLB misses after we * turn on virtual memory. @@ -411,6 +423,129 @@ nop EXIT(kernel_setup) + +#ifdef MULTIPROCESSOR +/* + * Trampoline to spin up secondary processors. + */ +LEAF_ENTRY_NOPROFILE(hw_cpu_spinup_trampoline) + + /* + * disable interrupts and turn off all bits in the psw so that + * we start in a known state. + */ + rsm RESET_PSW, %r0 + nop ! nop ! nop ! nop ! nop ! nop + + /* go to virtual mode... + /* get things ready for the kernel to run in virtual mode */ + ldi HPPA_PID_KERNEL, %r1 + mtctl %r1, %pidr1 + mtctl %r1, %pidr2 +#if pbably_not_worth_it + mtctl %r0, %pidr3 + mtctl %r0, %pidr4 +#endif + mtsp %r0, %sr0 + mtsp %r0, %sr1 + mtsp %r0, %sr2 + mtsp %r0, %sr3 + mtsp %r0, %sr4 + mtsp %r0, %sr5 + mtsp %r0, %sr6 + mtsp %r0, %sr7 + + /* + * disable all coprocessors + */ + mtctl %r0, %ccr + + /* + * to keep the spl() routines consistent we need to put the correct + * spl level into eiem, and reset any pending interrupts + */ + ldi -1, %r1 + mtctl %r0, %eiem /* disable interrupts */ + mtctl %r1, %eirr + + /* + * load address of interrupt vector table + */ + ldil L%ivaaddr, %t2 + ldo R%ivaaddr(%t2), %t2 + mtctl %t2, %iva + + /* + * set up the dp pointer so that we can do quick references off of it + */ + ldil L%$global$, %dp + ldo R%$global$(%dp), %dp + + /* + * Store address of cpu_info in CR_CURCPU. + */ + ldil L%cpu_hatch_info, %r3 + ldw R%cpu_hatch_info(%r3), %r3 + mtctl %r3, CR_CURCPU + + /* + * Setup the stack frame for us to call C with and mark this as the + * first frame on the stack. + */ + ldw CI_STACK(%r3), %sp + stw,ma %r0, HPPA_FRAME_SIZE(%sp) + stw %r0, HPPA_FRAME_CRP(%sp) + stw %r0, HPPA_FRAME_PSP(%sp) + + /* Provide CPU with page tables. */ + ldil L%hppa_vtop, %t1 + ldw R%hppa_vtop(%t1), %t1 + mtctl %t1, CR_VTOP + + /* Turn on the Q bit so that we can handle TLB traps. */ + ldil L%qenabled, %t1 + ldo R%qenabled(%t1), %t1 + mtctl %r0, %pcsq + mtctl %r0, %pcsq + mtctl %t1, %pcoq + ldo 4(%t1), %t1 + mtctl %t1, %pcoq + ldi PSW_Q|PSW_I, %t2 + mtctl %t2, %ipsw + rfi + nop + +qenabled: + /* Call C routine to setup CPU. */ + .import cpu_hw_init, code + CALL(cpu_hw_init, %r1) + + /* Switch CPU mode. */ + ldil L%cpu_spinup_vm, %t1 + ldo R%cpu_spinup_vm(%t1), %t1 + mtctl %r0, %pcsq + mtctl %r0, %pcsq + mtctl %t1, %pcoq + ldo 4(%t1), %t1 + mtctl %t1, %pcoq + mfctl CR_CURCPU, %t2 + ldw CI_PSW(%t2), %t2 + mtctl %t2, %ipsw + rfi + nop + +cpu_spinup_vm: + + /* + * Okay, time to return to the land of C. + */ + b cpu_hatch + nop + +EXIT(hw_cpu_spinup_trampoline) +#endif + + /* * int pdc_call(iodcio_t func,int pdc_flag, ...) */ Index: src/sys/arch/hp700/hp700/machdep.c diff -u src/sys/arch/hp700/hp700/machdep.c:1.97 src/sys/arch/hp700/hp700/machdep.c:1.98 --- src/sys/arch/hp700/hp700/machdep.c:1.97 Sun Jan 23 09:44:58 2011 +++ src/sys/arch/hp700/hp700/machdep.c Sun Jan 23 21:53:40 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.97 2011/01/23 09:44:58 skrll Exp $ */ +/* $NetBSD: machdep.c,v 1.98 2011/01/23 21:53:40 skrll Exp $ */ /*- * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc. @@ -58,7 +58,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.97 2011/01/23 09:44:58 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.98 2011/01/23 21:53:40 skrll Exp $"); #include "opt_cputype.h" #include "opt_ddb.h" @@ -137,6 +137,9 @@ */ void *msgbufaddr; +/* The primary (aka monarch) cpu HPA */ +hppa_hpa_t hppa_mcpuhpa; + /* * cache configuration, for most machines is the same * numbers, so it makes sense to do defines w/ numbers depending @@ -454,8 +457,15 @@ pdc_init(); /* init PDC iface, so we can call em easy */ cpu_hzticks = (PAGE0->mem_10msec * 100) / hz; + delay_init(); /* calculate CPU clock ratio */ + /* fetch the monarch/"default" cpu hpa */ + + error = pdcproc_hpa_processor(&hppa_mcpuhpa); + if (error < 0) + panic("%s: PDC_HPA failed", __func__); + /* cache parameters */ error = pdcproc_cache(&pdc_cache); if (error < 0) { Index: src/sys/arch/hp700/hp700/mainbus.c diff -u src/sys/arch/hp700/hp700/mainbus.c:1.76 src/sys/arch/hp700/hp700/mainbus.c:1.77 --- src/sys/arch/hp700/hp700/mainbus.c:1.76 Thu Jan 13 21:15:15 2011 +++ src/sys/arch/hp700/hp700/mainbus.c Sun Jan 23 21:53:40 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: mainbus.c,v 1.76 2011/01/13 21:15:15 skrll Exp $ */ +/* $NetBSD: mainbus.c,v 1.77 2011/01/23 21:53:40 skrll Exp $ */ /*- * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc. @@ -58,7 +58,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.76 2011/01/13 21:15:15 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.77 2011/01/23 21:53:40 skrll Exp $"); #include "locators.h" #include "power.h" @@ -1359,18 +1359,11 @@ struct mainbus_softc *sc = device_private(self); struct confargs nca; bus_space_handle_t ioh; - hppa_hpa_t prochpa; int err; sc->sc_dv = self; mb_attached = 1; - /* fetch the "default" cpu hpa */ - - err = pdcproc_hpa_processor(&prochpa); - if (err < 0) - panic("mbattach: PDC_HPA failed"); - /* * Map all of Fixed Physical, Local Broadcast, and Global Broadcast * space. These spaces are adjacent and in that order and run to the @@ -1382,18 +1375,19 @@ */ /* map all the way till the end of the memory */ - if (bus_space_map(&hppa_bustag, prochpa, (~0LU - prochpa + 1), + if (bus_space_map(&hppa_bustag, hppa_mcpuhpa, (~0LU - hppa_mcpuhpa + 1), 0, &ioh)) panic("%s: cannot map mainbus IO space", __func__); /* * Local-Broadcast the HPA to all modules on the bus */ - ((struct iomod *)(prochpa & HPPA_FLEX_MASK))[FPA_IOMOD].io_flex = - (void *)((prochpa & HPPA_FLEX_MASK) | DMA_ENABLE); + ((struct iomod *)(hppa_mcpuhpa & HPPA_FLEX_MASK))[FPA_IOMOD].io_flex = + (void *)((hppa_mcpuhpa & HPPA_FLEX_MASK) | DMA_ENABLE); + + sc->sc_hpa = hppa_mcpuhpa; - sc->sc_hpa = prochpa; - aprint_normal(" [flex %lx]\n", prochpa & HPPA_FLEX_MASK); + aprint_normal(" [flex %lx]\n", hppa_mcpuhpa & HPPA_FLEX_MASK); /* PDC first */ memset(&nca, 0, sizeof(nca)); Index: src/sys/arch/hp700/include/cpu.h diff -u src/sys/arch/hp700/include/cpu.h:1.59 src/sys/arch/hp700/include/cpu.h:1.60 --- src/sys/arch/hp700/include/cpu.h:1.59 Sun Jan 23 09:44:58 2011 +++ src/sys/arch/hp700/include/cpu.h Sun Jan 23 21:53:40 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.h,v 1.59 2011/01/23 09:44:58 skrll Exp $ */ +/* $NetBSD: cpu.h,v 1.60 2011/01/23 21:53:40 skrll Exp $ */ /* $OpenBSD: cpu.h,v 1.55 2008/07/23 17:39:35 kettenis Exp $ */ @@ -253,9 +253,6 @@ struct cpu_data ci_data; /* MI per-cpu data */ #ifndef _KMEMUSER -#ifdef MULTIPROCESSOR - struct lwp *ci_curlwp; /* CPU owner */ -#endif int ci_cpuid; /* CPU index (see cpus[] array) */ int ci_mtx_count; int ci_mtx_oldspl; @@ -265,9 +262,20 @@ volatile int ci_ipending; /* The pending interrupts. */ u_int ci_intr_depth; /* Nonzero iff running an interrupt. */ + hppa_hpa_t ci_hpa; register_t ci_psw; /* Processor Status Word. */ paddr_t ci_fpu_state; /* LWP FPU state address, or zero. */ u_long ci_itmr; + +#if defined(MULTIPROCESSOR) + struct lwp *ci_curlwp; /* CPU owner */ + paddr_t ci_stack; /* stack for spin up */ + volatile int ci_flags; /* CPU status flags */ +#define CPUF_PRIMARY 0x0001 /* ... is monarch/primary */ +#define CPUF_RUNNING 0x0002 /* ... is running. */ + +#endif + #endif /* !_KMEMUSER */ } __aligned(64); @@ -369,6 +377,12 @@ void setfunc_trampoline(void); int cpu_dumpsize(void); int cpu_dump(void); + +#ifdef MULTIPROCESSOR +void cpu_boot_secondary_processors(void); +void cpu_hw_init(void); +void cpu_hatch(void); +#endif #endif /* _KERNEL */ /* Index: src/sys/arch/hppa/hppa/machdep.h diff -u src/sys/arch/hppa/hppa/machdep.h:1.14 src/sys/arch/hppa/hppa/machdep.h:1.15 --- src/sys/arch/hppa/hppa/machdep.h:1.14 Sun Jan 23 09:44:59 2011 +++ src/sys/arch/hppa/hppa/machdep.h Sun Jan 23 21:53:40 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.h,v 1.14 2011/01/23 09:44:59 skrll Exp $ */ +/* $NetBSD: machdep.h,v 1.15 2011/01/23 21:53:40 skrll Exp $ */ /* * Copyright (c) 2002 The NetBSD Foundation, Inc. @@ -44,6 +44,9 @@ #ifdef _KERNEL +/* The primary (aka monarch) CPU HPA */ +extern hppa_hpa_t hppa_mcpuhpa; + /* * cache configuration, for most machines is the same * numbers, so it makes sense to do defines w/ numbers depending