summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/hppa/dev/cpu.c111
-rw-r--r--sys/arch/hppa/hppa/genassym.cf3
-rw-r--r--sys/arch/hppa/hppa/locore.S136
-rw-r--r--sys/arch/hppa/include/cpu.h10
4 files changed, 252 insertions, 8 deletions
diff --git a/sys/arch/hppa/dev/cpu.c b/sys/arch/hppa/dev/cpu.c
index 932da910220..262b8a989b1 100644
--- a/sys/arch/hppa/dev/cpu.c
+++ b/sys/arch/hppa/dev/cpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.c,v 1.33 2010/05/06 14:51:30 jsing Exp $ */
+/* $OpenBSD: cpu.c,v 1.34 2010/05/19 13:10:24 jsing Exp $ */
/*
* Copyright (c) 1998-2003 Michael Shalayeff
@@ -31,6 +31,8 @@
#include <sys/device.h>
#include <sys/reboot.h>
+#include <uvm/uvm_extern.h>
+
#include <machine/cpufunc.h>
#include <machine/pdc.h>
#include <machine/reg.h>
@@ -41,10 +43,13 @@
struct cpu_softc {
struct device sc_dev;
-
- hppa_hpa_t sc_hpa;
};
+#ifdef MULTIPROCESSOR
+struct cpu_info *cpu_hatch_info;
+static volatile int start_secondary_cpu;
+#endif
+
int cpumatch(struct device *, void *, void *);
void cpuattach(struct device *, struct device *, void *);
@@ -160,5 +165,105 @@ cpuattach(struct device *parent, struct device *self, void *aux)
void
cpu_boot_secondary_processors(void)
{
+ struct cpu_info *ci;
+ struct iomod *cpu;
+ struct pglist mlist;
+ struct vm_page *m;
+ int error, i, j;
+
+ /* Initialise primary CPU. */
+ ci = curcpu();
+ ci->ci_flags |= CPUF_RUNNING;
+
+ for (i = 0; i < HPPA_MAXCPUS; i++) {
+
+ ci = &cpu_info[i];
+ if (ci->ci_cpuid == 0)
+ continue;
+
+ ci->ci_randseed = random();
+
+#ifdef notyet
+ sched_init_cpu(ci);
+#endif
+
+ /* Allocate spinup stack. */
+ TAILQ_INIT(&mlist);
+ error = uvm_pglistalloc(PAGE_SIZE, 0, -1L, 0, 0, &mlist, 1,
+ UVM_PLA_NOWAIT);
+ if (error) {
+ printf("unable to allocate spinup stack!\n");
+ return;
+ }
+ m = TAILQ_FIRST(&mlist);
+ ci->ci_spinup_stack = VM_PAGE_TO_PHYS(m);
+
+ /* Release the specified CPU by triggering an EIR{0}. */
+ cpu_hatch_info = ci;
+ cpu = (struct iomod *)(ci->ci_hpa);
+ cpu->io_eir = 0;
+ asm volatile ("sync" ::: "memory");
+
+ /* 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;
+ asm volatile ("sync" ::: "memory");
+}
+
+void
+cpu_hw_init(void)
+{
+ struct cpu_info *ci = curcpu();
+
+ /* Purge TLB and flush caches. */
+ ptlball();
+ ficacheall();
+ fdcacheall();
+
+ /* Enable address translations. */
+ ci->ci_psw = PSL_I | PSL_Q | PSL_P | PSL_C | PSL_D;
+ ci->ci_psw |= (cpu_info[0].ci_psw & PSL_O);
+}
+
+void
+cpu_hatch(void)
+{
+ struct cpu_info *ci = curcpu();
+ extern u_long cpu_hzticks;
+ u_long itmr;
+
+ /* Initialise clock. */
+ mtctl((1 << 31), CR_EIRR);
+ mfctl(CR_ITMR, itmr);
+ ci->ci_itmr = itmr;
+ itmr += cpu_hzticks;
+ mtctl(itmr, CR_ITMR);
+ ci->ci_mask |= (1 << 31);
+
+ /* Enable interrupts. */
+ mtctl(ci->ci_mask, CR_EIEM);
+
+#ifdef notyet
+ ncpus++;
+#endif
+ ci->ci_flags |= CPUF_RUNNING;
+
+ /* Wait for additional CPUs to spinup. */
+ while (!start_secondary_cpu)
+ ;
+
+ for (;;) ;
+
+#ifdef notyet
+ SCHED_LOCK(s);
+ cpu_switchto(NULL, sched_chooseproc());
+#endif
}
#endif
diff --git a/sys/arch/hppa/hppa/genassym.cf b/sys/arch/hppa/hppa/genassym.cf
index e875dea0d54..1f4617ac2be 100644
--- a/sys/arch/hppa/hppa/genassym.cf
+++ b/sys/arch/hppa/hppa/genassym.cf
@@ -1,4 +1,4 @@
-# $OpenBSD: genassym.cf,v 1.37 2010/05/16 14:54:43 jsing Exp $
+# $OpenBSD: genassym.cf,v 1.38 2010/05/19 13:10:24 jsing Exp $
#
# Copyright (c) 1982, 1990, 1993
@@ -158,6 +158,7 @@ member fpswtch
struct cpu_info
member ci_curproc
+member ci_spinup_stack
member ci_psw
member ci_cpl
member ci_ipending
diff --git a/sys/arch/hppa/hppa/locore.S b/sys/arch/hppa/hppa/locore.S
index faec9089ef0..f8d87cba87b 100644
--- a/sys/arch/hppa/hppa/locore.S
+++ b/sys/arch/hppa/hppa/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.169 2010/05/16 14:54:43 jsing Exp $ */
+/* $OpenBSD: locore.S,v 1.170 2010/05/19 13:10:24 jsing Exp $ */
/*
* Copyright (c) 1998-2004 Michael Shalayeff
@@ -213,6 +213,14 @@ $start_zero_tf
ldo R%cpu_info(r1), r1
mtctl r1, cr29
+#ifdef MULTIPROCESSOR
+ /* Setup SMP rendezvous address. */
+ ldil L%hw_cpu_spinup_trampoline, r1
+ ldo R%hw_cpu_spinup_trampoline(r1), r1
+ stw r1, 0x10(0) /* MEM_RENDEZ */
+ stw r0, 0x28(0) /* MEM_RENDEZ */
+#endif
+
copy sp, arg1
ldil L%$qisnowon, rp
ldo R%$qisnowon(rp), rp
@@ -2914,6 +2922,132 @@ ENTRY(switch_trampoline,0)
ldw P_MD_REGS(t2), t3
EXIT(switch_trampoline)
+#ifdef MULTIPROCESSOR
+/*
+ * Trampoline to spin up secondary processors.
+ */
+ENTRY(hw_cpu_spinup_trampoline, 0)
+
+ /*
+ * disable interrupts and turn off all bits in the psw so that
+ * we start in a known state.
+ */
+ rsm RESET_PSL, r0
+ nop ! nop ! nop ! nop ! nop ! nop
+
+ /* 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
+ 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 CR29.
+ */
+ ldil L%cpu_hatch_info, r3
+ ldw R%cpu_hatch_info(r3), r3
+ mtctl r3, cr29
+
+ /*
+ * Setup the stack frame for us to call C with and mark this as the
+ * first frame on the stack.
+ */
+ ldw CI_SPINUP_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%$q_enabled, t1
+ ldo R%$q_enabled(t1), t1
+ mtctl r0, pcsq
+ mtctl r0, pcsq
+ mtctl t1, pcoq
+ ldo 4(t1), t1
+ mtctl t1, pcoq
+ ldi PSL_Q|PSL_I, t2
+ mtctl t2, ipsw
+ rfi
+ nop
+
+$q_enabled
+
+ /* Call C routine to setup CPU. */
+ ldil L%cpu_hw_init, r1
+ ldo R%cpu_hw_init(r1), r1
+ .import cpu_hw_init, code
+ .call
+ blr r0, rp
+ bv,n (r1)
+ nop
+
+ /* 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 cr29, 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
+
/*
* Signal "trampoline" code. Invoked from RTE setup by sendsig().
*/
diff --git a/sys/arch/hppa/include/cpu.h b/sys/arch/hppa/include/cpu.h
index 40b3af0414b..c404b0bf859 100644
--- a/sys/arch/hppa/include/cpu.h
+++ b/sys/arch/hppa/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.70 2010/05/16 14:54:43 jsing Exp $ */
+/* $OpenBSD: cpu.h,v 1.71 2010/05/19 13:10:24 jsing Exp $ */
/*
* Copyright (c) 2000-2004 Michael Shalayeff
@@ -79,8 +79,10 @@ struct cpu_info {
struct device *ci_dev;
int ci_cpuid;
hppa_hpa_t ci_hpa;
+ volatile int ci_flags;
struct proc *ci_curproc;
+ paddr_t ci_spinup_stack;
register_t ci_psw; /* Processor Status Word. */
volatile int ci_cpl;
@@ -94,10 +96,12 @@ struct cpu_info {
u_int32_t ci_randseed;
} __attribute__((__aligned__(64)));
+#define CPUF_RUNNING 0x0001 /* CPU is running. */
+
#ifdef MULTIPROCESSOR
-#define HPPA_MAXCPUS 1
+#define HPPA_MAXCPUS 4
#else
-#define HPPA_MAXCPUS 4
+#define HPPA_MAXCPUS 1
#endif
extern struct cpu_info cpu_info[HPPA_MAXCPUS];