summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKanoj Sarcar <kanoj@engr.sgi.com>2000-04-04 18:28:17 +0000
committerKanoj Sarcar <kanoj@engr.sgi.com>2000-04-04 18:28:17 +0000
commit09b51a8bad6352607cc40618d3be5a7525eb4470 (patch)
tree4ad25ffaaace035cc1cfba0a44546ae351c0cf56
parentd49f62d0497bc81a70b1c2e01ddec71d8ea93c30 (diff)
Rudimentary code to launch slave processors by the master processor.
Completely untested, never executed ...
-rw-r--r--arch/mips64/sgi-ip27/ip27-init.c124
-rw-r--r--include/asm-mips64/addrspace.h5
-rw-r--r--include/asm-mips64/sn/launch.h149
3 files changed, 277 insertions, 1 deletions
diff --git a/arch/mips64/sgi-ip27/ip27-init.c b/arch/mips64/sgi-ip27/ip27-init.c
index e09bc6036..5c0ab4062 100644
--- a/arch/mips64/sgi-ip27/ip27-init.c
+++ b/arch/mips64/sgi-ip27/ip27-init.c
@@ -1,4 +1,5 @@
#include <linux/kernel.h>
+#include <linux/sched.h>
#include <linux/mmzone.h> /* for numnodes */
#include <asm/sn/types.h>
#include <asm/sn/sn0/addrs.h>
@@ -8,16 +9,25 @@
#include <asm/ioc3.h>
#include <asm/mipsregs.h>
#include <asm/sn/gda.h>
+#include <asm/sn/intr.h>
+#include <asm/current.h>
+#include <asm/smp.h>
+#include <asm/processor.h>
+#include <asm/sn/launch.h>
typedef unsigned long cpumask_t; /* into asm/sn/types.h */
typedef unsigned long cpuid_t;
#define CPUMASK_CLRALL(p) (p) = 0
#define CPUMASK_SETB(p, bit) (p) |= 1 << (bit)
+#define CPUMASK_CLRB(p, bit) (p) &= ~(1ULL << (bit))
+#define CPUMASK_TSTB(p, bit) ((p) & (1ULL << (bit)))
cpumask_t boot_cpumask;
+static volatile cpumask_t boot_barrier;
hubreg_t region_mask = 0;
static int fine_mode = 0;
+int maxcpus;
cnodeid_t nasid_to_compact_node[MAX_NASIDS];
nasid_t compact_to_nasid_node[MAX_COMPACT_NODES];
@@ -184,7 +194,7 @@ cpuid_t cpu_node_probe(cpumask_t *boot_cpumask, int *numnodes)
void mlreset (void)
{
- int i, maxcpus;
+ int i;
fine_mode = is_fine_dirmode();
@@ -225,3 +235,115 @@ void mlreset (void)
}
}
+
+void intr_clear_bits(nasid_t nasid, volatile hubreg_t *pend, int base_level,
+ char *name)
+{
+ volatile hubreg_t bits;
+ int i;
+
+ /* Check pending interrupts */
+ if ((bits = HUB_L(pend)) != 0)
+ for (i = 0; i < N_INTPEND_BITS; i++)
+ if (bits & (1 << i))
+ LOCAL_HUB_CLR_INTR(base_level + i);
+}
+
+void intr_clear_all(nasid_t nasid)
+{
+ REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0);
+ REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0);
+ REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0);
+ REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0);
+ intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND0),
+ INT_PEND0_BASELVL, "INT_PEND0");
+ intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND1),
+ INT_PEND1_BASELVL, "INT_PEND1");
+}
+
+void sn_mp_setup(void)
+{
+ cnodeid_t cnode;
+#if 0
+ cpuid_t cpu;
+#endif
+
+ for (cnode = 0; cnode < numnodes; cnode++) {
+#if 0
+ init_platform_nodepda();
+#endif
+ intr_clear_all(COMPACT_TO_NASID_NODEID(cnode));
+ }
+#if 0
+ for (cpu = 0; cpu < maxcpus; cpu++) {
+ init_platform_pda();
+ }
+#endif
+}
+
+void per_cpu_init(void)
+{
+#if 0
+ cpuid_t cpu = getcpuid();
+ cnodeid_t cnode = get_compact_nodeid();
+
+ intr_init();
+ per_hub_init(cnode);
+ install_cpuintr(cpu);
+ install_tlbintr(cpu);
+#endif
+}
+
+void allowboot(void)
+{
+ int num_cpus = 0;
+ cpuid_t cpu;
+ cnodeid_t cnode;
+
+ sn_mp_setup();
+ per_cpu_init();
+#if 0
+ bte_lateinit();
+ ecc_init();
+#endif
+
+ boot_barrier = boot_cpumask;
+ /* Launch slaves. */
+ for (cpu = 0; cpu < maxcpus; cpu++) {
+ if (cpu == smp_processor_id()) {
+ num_cpus++;
+ /* We're already started, clear our bit */
+ CPUMASK_CLRB(boot_barrier, cpu);
+ continue;
+ }
+
+ /* Skip holes in CPU space */
+ if (CPUMASK_TSTB(boot_cpumask, cpu)) {
+ num_cpus++;
+
+ /*
+ * Launch a slave into bootstrap().
+ * It doesn't take an argument, and we'll
+ * take care of sp and gp when we get there.
+ */
+/* cputonasid/cputoslice not working yet */
+ LAUNCH_SLAVE(cputonasid(cpu), cputoslice(cpu), 0, 0, 0, 0);
+ }
+ }
+
+#ifdef LATER
+ Wait logic goes here.
+#endif
+ for (cnode = 0; cnode < numnodes; cnode++) {
+#if 0
+ if (cnodetocpu(cnode) == -1) {
+ printk("Initializing headless hub,cnode %d", cnode);
+ per_hub_init(cnode);
+ }
+#endif
+ }
+#if 0
+ cpu_io_setup();
+ init_mfhi_war();
+#endif
+}
diff --git a/include/asm-mips64/addrspace.h b/include/asm-mips64/addrspace.h
index d4343a4b9..1591e1071 100644
--- a/include/asm-mips64/addrspace.h
+++ b/include/asm-mips64/addrspace.h
@@ -104,4 +104,9 @@
#endif
#define K2BASE 0xc000000000000000
+#if !defined (CONFIG_CPU_R8000)
+#define COMPAT_K1BASE32 0xffffffffa0000000
+#define PHYS_TO_COMPATK1(x) ((x) | COMPAT_K1BASE32) /* 32-bit compat k1 */
+#endif
+
#endif /* _ASM_ADDRSPACE_H */
diff --git a/include/asm-mips64/sn/launch.h b/include/asm-mips64/sn/launch.h
new file mode 100644
index 000000000..5d1d683cf
--- /dev/null
+++ b/include/asm-mips64/sn/launch.h
@@ -0,0 +1,149 @@
+/**************************************************************************
+ * *
+ * Copyright (C) 1992-1997, Silicon Graphics, Inc. *
+ * *
+ * These coded instructions, statements, and computer programs contain *
+ * unpublished proprietary information of Silicon Graphics, Inc., and *
+ * are protected by Federal copyright law. They may not be disclosed *
+ * to third parties or copied or duplicated in any form, in whole or *
+ * in part, without the prior written consent of Silicon Graphics, Inc. *
+ * *
+ **************************************************************************/
+
+#ifndef __SYS_SN_LAUNCH_H__
+#define __SYS_SN_LAUNCH_H__
+
+#ident "$Revision: 1.10 $"
+
+#include <linux/config.h>
+#include <asm/sn/types.h>
+#include <asm/sn/addrs.h>
+
+/*
+ * The launch data structure resides at a fixed place in each node's memory
+ * and is used to communicate between the master processor and the slave
+ * processors.
+ *
+ * The master stores launch parameters in the launch structure
+ * corresponding to a target processor that is in a slave loop, then sends
+ * an interrupt to the slave processor. The slave calls the desired
+ * function, then returns to the slave loop. The master may poll or wait
+ * for the slaves to finish.
+ *
+ * There is an array of launch structures, one per CPU on the node. One
+ * interrupt level is used per local CPU.
+ */
+
+#define LAUNCH_MAGIC 0xaddbead2addbead3
+#define LAUNCH_SIZEOF 0x100
+
+#define LAUNCH_OFF_MAGIC 0x00 /* Struct offsets for assembly */
+#define LAUNCH_OFF_BUSY 0x08
+#define LAUNCH_OFF_CALL 0x10
+#define LAUNCH_OFF_CALLC 0x18
+#define LAUNCH_OFF_CALLPARM 0x20
+#define LAUNCH_OFF_STACK 0x28
+#define LAUNCH_OFF_GP 0x30
+#define LAUNCH_OFF_BEVUTLB 0x38
+#define LAUNCH_OFF_BEVNORMAL 0x40
+#define LAUNCH_OFF_BEVECC 0x48
+
+#define LAUNCH_STATE_DONE 0 /* Return value of LAUNCH_POLL */
+#define LAUNCH_STATE_SENT 1
+#define LAUNCH_STATE_RECD 2
+
+/*
+ * The launch routine is called only if the complement address is correct.
+ *
+ * Before control is transferred to a routine, the compliment address
+ * is zeroed (invalidated) to prevent an accidental call from a spurious
+ * interrupt.
+ *
+ * The slave_launch routine turns on the BUSY flag, and the slave loop
+ * clears the BUSY flag after control is returned to it.
+ */
+
+#ifdef _LANGUAGE_C
+
+typedef int launch_state_t;
+typedef void (*launch_proc_t)(u64 call_parm);
+
+typedef struct launch_s {
+ volatile u64 magic; /* Magic number */
+ volatile u64 busy; /* Slave currently active */
+ volatile launch_proc_t call_addr; /* Func. for slave to call */
+ volatile u64 call_addr_c; /* 1's complement of call_addr*/
+ volatile u64 call_parm; /* Single parm passed to call*/
+ volatile void *stack_addr; /* Stack pointer for slave function */
+ volatile void *gp_addr; /* Global pointer for slave func. */
+ volatile char *bevutlb;/* Address of bev utlb ex handler */
+ volatile char *bevnormal;/*Address of bev normal ex handler */
+ volatile char *bevecc;/* Address of bev cache err handler */
+ volatile char pad[160]; /* Pad to LAUNCH_SIZEOF */
+} launch_t;
+
+/*
+ * PROM entry points for launch routines are determined by IP27prom/start.s
+ */
+
+#ifdef CONFIG_SGI_IP27
+#define LAUNCH_SLAVE (*(void (*)(int nasid, int cpu, \
+ launch_proc_t call_addr, \
+ u64 call_parm, \
+ void *stack_addr, \
+ void *gp_addr)) \
+ IP27PROM_LAUNCHSLAVE)
+
+#define LAUNCH_WAIT (*(void (*)(int nasid, int cpu, int timeout_msec)) \
+ IP27PROM_WAITSLAVE)
+
+#define LAUNCH_POLL (*(launch_state_t (*)(int nasid, int cpu)) \
+ IP27PROM_POLLSLAVE)
+
+#define LAUNCH_LOOP (*(void (*)(void)) \
+ IP27PROM_SLAVELOOP)
+
+#define LAUNCH_FLASH (*(void (*)(void)) \
+ IP27PROM_FLASHLEDS)
+
+#else /* if defined (SN1) */
+
+#define LAUNCH_SLAVE (*(void (*)(int nasid, int cpu, \
+ launch_proc_t call_addr, \
+ __int64_t call_parm, \
+ void *stack_addr, \
+ void *gp_addr)) \
+ IP33PROM_LAUNCHSLAVE)
+
+#define LAUNCH_WAIT (*(void (*)(int nasid, int cpu, int timeout_msec)) \
+ IP33PROM_WAITSLAVE)
+
+#define LAUNCH_POLL (*(launch_state_t (*)(int nasid, int cpu)) \
+ IP33PROM_POLLSLAVE)
+
+#define LAUNCH_LOOP (*(void (*)(void)) \
+ IP33PROM_SLAVELOOP)
+
+#define LAUNCH_FLASH (*(void (*)(void)) \
+ IP33PROM_FLASHLEDS)
+
+#endif
+
+#ifdef _STANDALONE
+
+launch_t *launch_get(int nasid, int cpu);
+launch_t *launch_get_current(void);
+void launch_loop(void);
+void launch_slave(int nasid, int cpu,
+ launch_proc_t call_addr,
+ __int64_t call_parm,
+ void *stack_addr,
+ void *gp_addr);
+int launch_wait(int nasid, int cpu, int timeout_msec);
+launch_state_t launch_poll(int nasid, int cpu);
+
+#endif /* _STANDALONE */
+
+#endif /* _LANGUAGE_C */
+
+#endif /* __SYS_SN_LAUNCH_H__ */