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