did2さんにOpenBSDの立派な環境構築メモを書いて頂きまんた

もちろんOpenBSDですよね、わかります。RT @did2memo: OSなど買ってきた
という私のTwitterでのネタつぶやきが発端でdid2さんにOpenBSDの立派な環境構築メモを書いて頂きました!
こちらからどうぞ↓
OpenBSDのインストール方法詳細メモ(1) - 情報科学屋さんを目指す人のメモ(FC2ブログ版)

感謝。

cpu1にIPIがかからないずら。

現状:

  • cpu1でクロック割り込みはかかる
  • cpu0→cpu0のIPIはかかる
  • cpu1→cpu0のIPIはかかる
  • cpu1→cpu1のIPIはかからない
  • cpu0→cpu1のIPIはかからない

何となく、割り込みコントローラへの設定などなどがしくってるような気がするけど、IMR0の値もステータスレジスタの値も一見正しく見えるし、どこが悪いのか良く分からない。
実はIRQが違うとか?
そしてコミット出来ぬまま太り続けるパッチ。

Index: mips64/include/autoconf.h
===================================================================
RCS file: /cvs/src/sys/arch/mips64/include/autoconf.h,v
retrieving revision 1.1
diff -u -p -r1.1 autoconf.h
--- mips64/include/autoconf.h	9 Jan 2010 20:33:16 -0000	1.1
+++ mips64/include/autoconf.h	31 May 2010 14:20:54 -0000
@@ -30,6 +30,6 @@ struct cpu_attach_args {
 	struct cpu_hwinfo		*caa_hw;
 };
 
-extern struct cpu_hwinfo bootcpu_hwinfo;
+extern struct cpu_hwinfo cpu_hwinfo[MAXCPUS];
 
 #endif /* _MIPS64_AUTOCONF_H_ */
Index: mips64/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/mips64/include/cpu.h,v
retrieving revision 1.58
diff -u -p -r1.58 cpu.h
--- mips64/include/cpu.h	28 Apr 2010 16:20:28 -0000	1.58
+++ mips64/include/cpu.h	31 May 2010 14:20:55 -0000
@@ -370,6 +370,10 @@ struct cpu_hwinfo {
 	uint32_t	tlbsize;
 	uint		type;
 	uint32_t	l2size;
+#ifdef TGT_ORIGIN
+	int		nasid;
+	int		physid;
+#endif
 };
 
 struct cpu_info {
Index: mips64/mips64/clock.c
===================================================================
RCS file: /cvs/src/sys/arch/mips64/mips64/clock.c,v
retrieving revision 1.33
diff -u -p -r1.33 clock.c
--- mips64/mips64/clock.c	28 Feb 2010 17:23:25 -0000	1.33
+++ mips64/mips64/clock.c	31 May 2010 14:20:55 -0000
@@ -194,7 +194,7 @@ delay(int n)
 
 	delayconst = ci->ci_delayconst;
 	if (delayconst == 0)
-		delayconst = bootcpu_hwinfo.clock / 2;
+		delayconst = cpu_hwinfo[cpu_number()].clock / 2;
 	p = cp0_get_count();
 	dly = (delayconst / 1000000) * n;
 	while (dly > 0) { 
Index: sgi/include/intr.h
===================================================================
RCS file: /cvs/src/sys/arch/sgi/include/intr.h,v
retrieving revision 1.41
diff -u -p -r1.41 intr.h
--- sgi/include/intr.h	18 Jan 2010 16:59:23 -0000	1.41
+++ sgi/include/intr.h	31 May 2010 14:20:56 -0000
@@ -190,6 +190,8 @@ void	dosoftint(void);
 #ifdef MULTIPROCESSOR
 #if defined (TGT_OCTANE)
 #define ENABLEIPI() updateimask(~CR_INT_2) /* enable IPI interrupt level */
+#elif defined (TGT_ORIGIN)
+#define ENABLEIPI() updateimask(~CR_INT_0) /* enable IPI interrupt level */
 #else
 #error MULTIPROCESSOR kernel not supported on this configuration
 #endif
Index: sgi/sgi/ip27_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/sgi/sgi/ip27_machdep.c,v
retrieving revision 1.51
diff -u -p -r1.51 ip27_machdep.c
--- sgi/sgi/ip27_machdep.c	9 May 2010 18:37:47 -0000	1.51
+++ sgi/sgi/ip27_machdep.c	31 May 2010 14:20:56 -0000
@@ -28,6 +28,7 @@
 #include <sys/malloc.h>
 #include <sys/reboot.h>
 #include <sys/tty.h>
+#include <sys/proc.h>
 
 #include <mips64/arcbios.h>
 #include <mips64/archtype.h>
@@ -56,6 +57,7 @@ extern char *hw_prod;
 
 extern void (*md_halt)(int);
 
+
 paddr_t	ip27_widget_short(int16_t, u_int);
 paddr_t	ip27_widget_long(int16_t, u_int);
 paddr_t	ip27_widget_map(int16_t, u_int,bus_addr_t *, bus_size_t *);
@@ -108,7 +110,7 @@ struct intrhand *hubpi_intrhand1[HUBPI_N
 
 struct {
 	uint64_t hw[2];
-} hubpi_intem, hubpi_imask[NIPLS];
+} hubpi_intem[MAXCPUS], hubpi_imask[MAXCPUS][NIPLS];
 
 void
 ip27_setup()
@@ -297,6 +299,10 @@ ip27_setup()
 void
 ip27_autoconf(struct device *parent)
 {
+#ifdef MULTIPROCESSOR
+	int cpuid;
+#endif
+
 	union {
 		struct mainbus_attach_args maa;
 		struct cpu_attach_args caa;
@@ -313,11 +319,20 @@ ip27_autoconf(struct device *parent)
 	bzero(&u, sizeof u);
 	u.maa.maa_name = "cpu";
 	u.maa.maa_nasid = currentnasid = masternasid;
-	u.caa.caa_hw = &bootcpu_hwinfo;
+	u.caa.caa_hw = &cpu_hwinfo[0];
 	config_found(parent, &u, ip27_print);
 	u.maa.maa_name = "clock";
 	config_found(parent, &u, ip27_print);
-
+#ifdef MULTIPROCESSOR
+	for (cpuid = 1; cpuid < MAXCPUS; cpuid++)
+		if (cpu_hwinfo[cpuid].clock != 0 
+		&& cpu_hwinfo[cpuid].nasid == currentnasid) {
+			u.maa.maa_name = "cpu";
+			u.maa.maa_nasid = currentnasid;
+			u.caa.caa_hw = &cpu_hwinfo[cpuid];
+			config_found(parent, &u, ip27_print);
+		}
+#endif
 	/*
 	 * Now attach all nodes' I/O devices.
 	 */
@@ -645,12 +660,13 @@ int
 ip27_hub_intr_register(int widget, int level, int *intrbit)
 {
 	int bit;
+	u_long cpuid = cpu_number();
 
 	/*
 	 * Try to allocate a bit on hardware level 0 first.
 	 */
 	for (bit = HUBPI_INTR0_WIDGET_MAX; bit >= HUBPI_INTR0_WIDGET_MIN; bit--)
-		if ((hubpi_intem.hw[0] & (1UL << bit)) == 0)
+		if ((hubpi_intem[cpuid].hw[0] & (1UL << bit)) == 0)
 			goto found;
 
 	/*
@@ -658,7 +674,7 @@ ip27_hub_intr_register(int widget, int l
 	 * level 1.
 	 */
 	for (bit = HUBPI_INTR1_WIDGET_MAX; bit >= HUBPI_INTR1_WIDGET_MIN; bit--)
-		if ((hubpi_intem.hw[1] & (1UL << bit)) == 0) {
+		if ((hubpi_intem[cpuid].hw[1] & (1UL << bit)) == 0) {
 			bit += HUBPI_NINTS;
 			goto found;
 		}
@@ -679,6 +695,7 @@ ip27_hub_intr_establish(int (*func)(void
 {
 	struct intrhand *ih, **anchor;
 	int s;
+	u_long cpuid = cpu_number();
 
 #ifdef DIAGNOSTIC
 	if (intrbit < 0 || intrbit >= HUBPI_NINTS + HUBPI_NINTS)
@@ -723,7 +740,8 @@ ip27_hub_intr_establish(int (*func)(void
 
 	*anchor = ih;
 
-	hubpi_intem.hw[intrbit / HUBPI_NINTS] |= 1UL << (intrbit % HUBPI_NINTS);
+	hubpi_intem[cpuid].hw[intrbit / HUBPI_NINTS]
+		|= 1UL << (intrbit % HUBPI_NINTS);
 	if (intrbit / HUBPI_NINTS != 0)
 		ip27_hub_intr_makemasks1();
 	else
@@ -739,6 +757,7 @@ ip27_hub_intr_disestablish(int intrbit)
 {
 	struct intrhand *ih, **anchor;
 	int s;
+	u_long cpuid = cpu_number();
 
 #ifdef DIAGNOSTIC
 	if (intrbit < 0 || intrbit >= HUBPI_NINTS + HUBPI_NINTS)
@@ -759,7 +778,7 @@ ip27_hub_intr_disestablish(int intrbit)
 
 	*anchor = NULL;
 
-	hubpi_intem.hw[intrbit / HUBPI_NINTS] &=
+	hubpi_intem[cpuid].hw[intrbit / HUBPI_NINTS] &=
 	    ~(1UL << (intrbit % HUBPI_NINTS));
 	if (intrbit / HUBPI_NINTS != 0)
 		ip27_hub_intr_makemasks1();
@@ -806,21 +825,25 @@ ip27_hub_splx(int newipl)
 
 #define	INTR_FUNCTIONNAME	hubpi_intr0
 #define	MASK_FUNCTIONNAME	ip27_hub_intr_makemasks0
-#define	INTR_LOCAL_DECLS
-#define	MASK_LOCAL_DECLS
+#define	INTR_LOCAL_DECLS \
+	u_long cpuid = cpu_number();
+#define	MASK_LOCAL_DECLS \
+	u_long cpuid = cpu_number();
 #define	INTR_GETMASKS \
 do { \
-	/* XXX this assumes we run on cpu0 */ \
+	int physid = curcpu()->ci_hw.physid; \
 	isr = IP27_LHUB_L(HUBPI_IR0); \
-	imr = IP27_LHUB_L(HUBPI_CPU0_IMR0); \
+	imr = IP27_LHUB_L(!physid ? HUBPI_CPU0_IMR0 : HUBPI_CPU1_IMR0); \
 	bit = HUBPI_INTR0_WIDGET_MAX; \
 } while (0)
 #define	INTR_MASKPENDING \
 do { \
-	IP27_LHUB_S(HUBPI_CPU0_IMR0, imr & ~isr); \
+	int physid = curcpu()->ci_hw.physid; \
+	IP27_LHUB_S(!physid ? HUBPI_CPU0_IMR0 : HUBPI_CPU1_IMR0, \
+		imr & ~isr); \
 	(void)IP27_LHUB_L(HUBPI_IR0); \
 } while (0)
-#define	INTR_IMASK(ipl)		hubpi_imask[ipl].hw[0]
+#define	INTR_IMASK(ipl)		hubpi_imask[cpuid][ipl].hw[0]
 #define	INTR_HANDLER(bit)	hubpi_intrhand0[bit]
 #define	INTR_SPURIOUS(bit) \
 do { \
@@ -828,7 +851,8 @@ do { \
 } while (0)
 #define	INTR_MASKRESTORE \
 do { \
-	IP27_LHUB_S(HUBPI_CPU0_IMR0, imr); \
+	int physid = curcpu()->ci_hw.physid; \
+	IP27_LHUB_S(!physid ? HUBPI_CPU0_IMR0 : HUBPI_CPU1_IMR0, imr); \
 	(void)IP27_LHUB_L(HUBPI_IR0); \
 } while (0)
 #define	INTR_MASKSIZE	HUBPI_NINTS
@@ -837,21 +861,25 @@ do { \
 
 #define	INTR_FUNCTIONNAME	hubpi_intr1
 #define	MASK_FUNCTIONNAME	ip27_hub_intr_makemasks1
-#define	INTR_LOCAL_DECLS
-#define	MASK_LOCAL_DECLS
+#define	INTR_LOCAL_DECLS \
+	u_long cpuid = cpu_number();
+#define	MASK_LOCAL_DECLS \
+	u_long cpuid = cpu_number();
 #define	INTR_GETMASKS \
 do { \
-	/* XXX this assumes we run on cpu0 */ \
+	int physid = curcpu()->ci_hw.physid; \
 	isr = IP27_LHUB_L(HUBPI_IR1); \
-	imr = IP27_LHUB_L(HUBPI_CPU0_IMR1); \
+	imr = IP27_LHUB_L(!physid ? HUBPI_CPU0_IMR1 : HUBPI_CPU1_IMR1); \
 	bit = HUBPI_INTR1_WIDGET_MAX; \
 } while (0)
 #define	INTR_MASKPENDING \
 do { \
-	IP27_LHUB_S(HUBPI_CPU0_IMR1, imr & ~isr); \
+	int physid = curcpu()->ci_hw.physid; \
+	IP27_LHUB_S(!physid ? HUBPI_CPU0_IMR1 : HUBPI_CPU1_IMR1, \
+		imr & ~isr); \
 	(void)IP27_LHUB_L(HUBPI_IR1); \
 } while (0)
-#define	INTR_IMASK(ipl)		hubpi_imask[ipl].hw[1]
+#define	INTR_IMASK(ipl)		hubpi_imask[cpuid][ipl].hw[1]
 #define	INTR_HANDLER(bit)	hubpi_intrhand1[bit]
 #define	INTR_SPURIOUS(bit) \
 do { \
@@ -859,7 +887,8 @@ do { \
 } while (0)
 #define	INTR_MASKRESTORE \
 do { \
-	IP27_LHUB_S(HUBPI_CPU0_IMR1, imr); \
+	int physid = curcpu()->ci_hw.physid; \
+	IP27_LHUB_S(!physid ? HUBPI_CPU0_IMR1 : HUBPI_CPU1_IMR1, imr); \
 	(void)IP27_LHUB_L(HUBPI_IR1); \
 } while (0)
 #define	INTR_MASKSIZE	HUBPI_NINTS
@@ -869,12 +898,13 @@ do { \
 void
 ip27_hub_setintrmask(int level)
 {
-	/* XXX this assumes we run on cpu0 */
-	IP27_LHUB_S(HUBPI_CPU0_IMR0,
-	    hubpi_intem.hw[0] & ~hubpi_imask[level].hw[0]);
+	int physid = curcpu()->ci_hw.physid;
+	u_long cpuid = cpu_number();
+	IP27_LHUB_S(!physid ? HUBPI_CPU0_IMR0 : HUBPI_CPU1_IMR0,
+	    hubpi_intem[cpuid].hw[0] & ~hubpi_imask[cpuid][level].hw[0]);
 	(void)IP27_LHUB_L(HUBPI_IR0);
-	IP27_LHUB_S(HUBPI_CPU0_IMR1,
-	    hubpi_intem.hw[1] & ~hubpi_imask[level].hw[1]);
+	IP27_LHUB_S(!physid ? HUBPI_CPU0_IMR1 : HUBPI_CPU1_IMR1,
+	    hubpi_intem[cpuid].hw[1] & ~hubpi_imask[cpuid][level].hw[1]);
 	(void)IP27_LHUB_L(HUBPI_IR1);
 }
 
@@ -919,3 +949,142 @@ ip27_nmi(void *arg)
 	printf("Resetting system...\n");
 	boot(RB_USERREQ);
 }
+
+#ifdef MULTIPROCESSOR
+void	build_trampoline(vaddr_t, vaddr_t);
+
+#define LAUNCH_SLAVE \
+	(*(void (*)(int nasid, int cpu, void *call_addr, uint64_t call_parm, \
+	void *stack_addr, void *gp_addr)) PHYS_TO_CKSEG1(0x1fc00038))
+
+void
+hw_cpu_boot_secondary(struct cpu_info *ci)
+{
+	vaddr_t kstack;
+
+	kstack = alloc_contiguous_pages(USPACE);
+	if (kstack == NULL)
+		panic("unable to allocate idle stack\n");
+	ci->ci_curprocpaddr = (void *)kstack;
+
+	LAUNCH_SLAVE(ci->ci_hw.nasid, ci->ci_hw.physid, 
+		hw_cpu_spinup_trampoline, (uint64_t)ci, 
+		(void *)(kstack + USPACE), 0);
+
+	while (!cpuset_isset(&cpus_running, ci))
+		;
+}
+
+void
+hw_cpu_hatch(struct cpu_info *ci)
+{
+	int s;
+	vaddr_t xtlb_handler;
+	extern char exception[], e_exception[];
+
+	/*
+	 * Set curcpu address on this processor.
+	 */
+	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_set_page_mask(TLB_PAGE_MASK);
+	tlb_set_wired(0);
+	tlb_flush(64);
+	tlb_set_wired(UPAGES / 2);
+
+	tlb_set_pid(0);
+
+	/*
+	 * Copy down exception vector code.
+	 */
+	bcopy(exception, (char *)CACHE_ERR_EXC_VEC, e_exception - exception);
+	bcopy(exception, (char *)GEN_EXC_VEC, e_exception - exception);
+
+	/*
+	 * Build proper TLB refill handler trampolines.
+	 */
+	extern void xtlb_miss;
+	xtlb_handler = (vaddr_t)&xtlb_miss;
+
+	build_trampoline(TLB_MISS_EXC_VEC, xtlb_handler);
+	build_trampoline(XTLB_MISS_EXC_VEC, xtlb_handler);
+
+	/*
+	 * Turn off bootstrap exception vectors.
+	 */
+	setsr(getsr() & ~SR_BOOT_EXC_VEC);
+
+	/*
+	 * Clear out the I and D caches.
+	 */
+	Mips10k_ConfigCache(ci);
+	Mips_SyncCache(ci);
+	
+	cpu_startclock(ci);
+	ncpus++;
+	cpuset_add(&cpus_running, ci);
+	mips64_ipi_init();
+	ip27_hub_setintrmask(0);
+	spl0();
+	(void)updateimask(0);
+
+#ifdef DEBUG
+	printf("imr0: %x\n",
+		IP27_LHUB_L(HUBPI_CPU1_IMR0));
+	printf("sr: %x\n",
+		getsr());
+#endif
+
+	SCHED_LOCK(s);
+	cpu_switchto(NULL, sched_chooseproc());
+}
+
+int
+hw_ipi_intr_establish(int (*func)(void *), u_long cpuid)
+{
+	int physid = get_cpu_info(cpuid)->ci_hw.physid;
+	int level = !physid ? HUBPI_ISR0_CPU_ACTION_A : HUBPI_ISR0_CPU_ACTION_B;
+
+#ifdef DEBUG
+	printf("hw_ipi_intr_establish(%d)\n", cpuid);
+#endif
+	ip27_hub_intr_establish(func, (void *)cpuid, level,
+		IPL_IPI, NULL, &curcpu()->ci_ipiih);
+
+	return 0;
+};
+
+void
+hw_ipi_intr_set(u_long cpuid)
+{
+	int physid = get_cpu_info(cpuid)->ci_hw.physid;
+	int level = !physid ? HUBPI_ISR0_CPU_ACTION_A : HUBPI_ISR0_CPU_ACTION_B;
+
+#ifdef DEBUG
+	printf("hw_ipi_intr_set(%d)\n", cpuid);
+#endif
+
+	ip27_hub_intr_set(level);
+}
+
+void
+hw_ipi_intr_clear(u_long cpuid)
+{
+	int physid = get_cpu_info(cpuid)->ci_hw.physid;
+	int level = !physid ? HUBPI_ISR0_CPU_ACTION_A : HUBPI_ISR0_CPU_ACTION_B;
+
+#ifdef DEBUG
+	printf("hw_ipi_intr_clear(%d)\n", cpuid);
+#endif
+
+	ip27_hub_intr_clear(level);
+}
+
+#endif
Index: sgi/sgi/ip30_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/sgi/sgi/ip30_machdep.c,v
retrieving revision 1.42
diff -u -p -r1.42 ip30_machdep.c
--- sgi/sgi/ip30_machdep.c	28 Apr 2010 16:20:28 -0000	1.42
+++ sgi/sgi/ip30_machdep.c	31 May 2010 14:20:56 -0000
@@ -160,14 +160,14 @@ ip30_setup()
 	xbow_widget_map = ip30_widget_map;
 	xbow_widget_id = ip30_widget_id;
 
-	bootcpu_hwinfo.c0prid = cp0_get_prid();
-	bootcpu_hwinfo.c1prid = cp1_get_prid();
+	cpu_hwinfo[0].c0prid = cp0_get_prid();
+	cpu_hwinfo[0].c1prid = cp1_get_prid();
 	cpuspeed = bios_getenvint("cpufreq");
 	if (cpuspeed < 100)
 		cpuspeed = 175;		/* reasonable default */
-	bootcpu_hwinfo.clock = cpuspeed * 1000000;
-	bootcpu_hwinfo.tlbsize = 64;	/* R10000 family */
-	bootcpu_hwinfo.type = (bootcpu_hwinfo.c0prid >> 8) & 0xff;
+	cpu_hwinfo[0].clock = cpuspeed * 1000000;
+	cpu_hwinfo[0].tlbsize = 64;	/* R10000 family */
+	cpu_hwinfo[0].type = (cpu_hwinfo[0].c0prid >> 8) & 0xff;
 
 	/*
 	 * Initialize the early console parameters.
@@ -232,7 +232,7 @@ ip30_autoconf(struct device *parent)
 	bzero(&caa, sizeof caa);
 	caa.caa_maa.maa_nasid = masternasid;
 	caa.caa_maa.maa_name = "cpu";
-	caa.caa_hw = &bootcpu_hwinfo;
+	caa.caa_hw = &cpu_hwinfo[0];
 	config_found(parent, &caa, mbprint);
 
 #ifdef MULTIPROCESSOR
@@ -245,7 +245,7 @@ ip30_autoconf(struct device *parent)
 			 * since Octane processors should be identical
 			 * (model, speed and cache), this should be safe.
 			 */
-			bcopy(&bootcpu_hwinfo, &hw, sizeof(struct cpu_hwinfo));
+			bcopy(&cpu_hwinfo[0], &hw, sizeof(struct cpu_hwinfo));
 			hw.c0prid = 
 		           *(volatile uint32_t *)(mpconf + MPCONF_PRID(cpuid));
 			hw.type = (hw.c0prid >> 8) & 0xff;
Index: sgi/sgi/ip32_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/sgi/sgi/ip32_machdep.c,v
retrieving revision 1.15
diff -u -p -r1.15 ip32_machdep.c
--- sgi/sgi/ip32_machdep.c	6 Apr 2010 19:15:29 -0000	1.15
+++ sgi/sgi/ip32_machdep.c	31 May 2010 14:20:57 -0000
@@ -127,18 +127,18 @@ ip32_setup()
 		break;
 	}
 
-	bootcpu_hwinfo.c0prid = cp0_get_prid();
-	bootcpu_hwinfo.c1prid = cp1_get_prid();
+	cpu_hwinfo[0].c0prid = cp0_get_prid();
+	cpu_hwinfo[0].c1prid = cp1_get_prid();
 	cpuspeed = bios_getenvint("cpufreq");
 	if (cpuspeed < 100)
 		cpuspeed = 180;		/* reasonable default */
-	bootcpu_hwinfo.clock = cpuspeed * 1000000;
-	bootcpu_hwinfo.type = (bootcpu_hwinfo.c0prid >> 8) & 0xff;
+	cpu_hwinfo[0].clock = cpuspeed * 1000000;
+	cpu_hwinfo[0].type = (cpu_hwinfo[0].c0prid >> 8) & 0xff;
 
 	/*
 	 * Figure out how many TLB are available.
 	 */
-	switch (bootcpu_hwinfo.type) {
+	switch (cpu_hwinfo[0].type) {
 #ifdef CPU_RM7000
 	case MIPS_RM7000:
 		/*
@@ -162,8 +162,8 @@ ip32_setup()
 		 * the highest valid TLB entry we can find and
 		 * see if it is in the upper 16 entries or not.
 		 */
-		bootcpu_hwinfo.tlbsize = 48;
-		if (((bootcpu_hwinfo.c0prid >> 4) & 0x0f) >= 2) {
+		cpu_hwinfo[0].tlbsize = 48;
+		if (((cpu_hwinfo[0].c0prid >> 4) & 0x0f) >= 2) {
 			struct tlb_entry te;
 			int e, lastvalid;
 
@@ -180,7 +180,7 @@ ip32_setup()
 			}
 			tlb_flush(64);
 			if (lastvalid >= 48)
-				bootcpu_hwinfo.tlbsize = 64;
+				cpu_hwinfo[0].tlbsize = 64;
 		}
 		break;
 #endif
@@ -188,11 +188,11 @@ ip32_setup()
 	case MIPS_R10000:
 	case MIPS_R12000:
 	case MIPS_R14000:
-		bootcpu_hwinfo.tlbsize = 64;
+		cpu_hwinfo[0].tlbsize = 64;
 		break;
 #endif
 	default:	/* R5000, RM52xx */
-		bootcpu_hwinfo.tlbsize = 48;
+		cpu_hwinfo[0].tlbsize = 48;
 		break;
 	}
 
Index: sgi/sgi/machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/sgi/sgi/machdep.c,v
retrieving revision 1.102
diff -u -p -r1.102 machdep.c
--- sgi/sgi/machdep.c	28 Apr 2010 21:26:47 -0000	1.102
+++ sgi/sgi/machdep.c	31 May 2010 14:20:57 -0000
@@ -111,7 +111,7 @@ int16_t	masternasid;
 
 int32_t *environment;
 struct sys_rec sys_config;
-struct cpu_hwinfo bootcpu_hwinfo;
+struct cpu_hwinfo cpu_hwinfo[MAXCPUS];
 
 /* Pointers to the start and end of the symbol table. */
 caddr_t	ssym;
@@ -352,7 +352,7 @@ mips_init(int argc, void *argv, caddr_t 
 	/*
 	 * Configure cache.
 	 */
-	switch (bootcpu_hwinfo.type) {
+	switch (cpu_hwinfo[0].type) {
 #ifdef CPU_R10000
 	case MIPS_R10000:
 	case MIPS_R12000:
@@ -425,7 +425,7 @@ mips_init(int argc, void *argv, caddr_t 
 
 	tlb_set_page_mask(TLB_PAGE_MASK);
 	tlb_set_wired(0);
-	tlb_flush(bootcpu_hwinfo.tlbsize);
+	tlb_flush(cpu_hwinfo[0].tlbsize);
 	tlb_set_wired(UPAGES / 2);
 
 	/*
Index: sgi/sgi/mainbus.c
===================================================================
RCS file: /cvs/src/sys/arch/sgi/sgi/mainbus.c,v
retrieving revision 1.8
diff -u -p -r1.8 mainbus.c
--- sgi/sgi/mainbus.c	9 Jan 2010 20:33:16 -0000	1.8
+++ sgi/sgi/mainbus.c	31 May 2010 14:20:57 -0000
@@ -96,7 +96,7 @@ mbattach(struct device *parent, struct d
 
 	bzero(&caa, sizeof caa);
 	caa.caa_maa.maa_name = "cpu";
-	caa.caa_hw = &bootcpu_hwinfo;
+	caa.caa_hw = &cpu_hwinfo[0];
 	config_found(self, &caa, mbprint);
 
 	caa.caa_maa.maa_name = "clock";
Index: sgi/sgi/sginode.c
===================================================================
RCS file: /cvs/src/sys/arch/sgi/sgi/sginode.c,v
retrieving revision 1.19
diff -u -p -r1.19 sginode.c
--- sgi/sgi/sginode.c	6 Apr 2010 19:09:50 -0000	1.19
+++ sgi/sgi/sginode.c	31 May 2010 14:20:57 -0000
@@ -76,6 +76,7 @@ int	kl_n_mode = 0;
 u_int	kl_n_shift = 32;
 klinfo_t *kl_glass_console = NULL;
 
+
 void
 kl_init(int ip35)
 {
@@ -249,17 +250,33 @@ kl_first_pass_comp(klinfo_t *comp, void 
 		 * XXX this assumes the first cpu encountered is the boot
 		 * XXX cpu.
 		 */
-		if (bootcpu_hwinfo.clock == 0) {
-			bootcpu_hwinfo.c0prid = cpucomp->cpu_prid;
+		if (cpu_hwinfo[0].clock == 0) {
+			cpu_hwinfo[0].c0prid = cpucomp->cpu_prid;
+			if (ip35)
+				cpu_hwinfo[0].c1prid = cpucomp->cpu_prid;
+			else
+				cpu_hwinfo[0].c1prid = cpucomp->cpu_fpirr;
+			cpu_hwinfo[0].clock = cpucomp->cpu_speed * 1000000;
+			cpu_hwinfo[0].tlbsize = 64;
+			cpu_hwinfo[0].type = (cpucomp->cpu_prid >> 8) & 0xff;
+			cpu_hwinfo[0].nasid = comp->nasid;
+			cpu_hwinfo[0].physid = comp->physid;
+		} else {
+#ifdef MULTIPROCESSOR
+			int cpuid = ncpusfound;
+			cpu_hwinfo[cpuid].c0prid = cpucomp->cpu_prid;
 			if (ip35)
-				bootcpu_hwinfo.c1prid = cpucomp->cpu_prid;
+				cpu_hwinfo[cpuid].c1prid = cpucomp->cpu_prid;
 			else
-				bootcpu_hwinfo.c1prid = cpucomp->cpu_fpirr;
-			bootcpu_hwinfo.clock = cpucomp->cpu_speed * 1000000;
-			bootcpu_hwinfo.tlbsize = 64;
-			bootcpu_hwinfo.type = (cpucomp->cpu_prid >> 8) & 0xff;
-		} else
+				cpu_hwinfo[cpuid].c1prid = cpucomp->cpu_fpirr;
+			cpu_hwinfo[cpuid].clock = cpucomp->cpu_speed * 1000000;
+		        cpu_hwinfo[cpuid].tlbsize = 64;
+			cpu_hwinfo[cpuid].type = (cpucomp->cpu_prid >> 8) & 0xff;
+			cpu_hwinfo[cpuid].nasid = comp->nasid;
+			cpu_hwinfo[cpuid].physid = comp->physid;
+#endif
 			ncpusfound++;
+		}
 		break;
 
 	case KLSTRUCT_MEMBNK:
Index: sgi/xbow/hub.h
===================================================================
RCS file: /cvs/src/sys/arch/sgi/xbow/hub.h,v
retrieving revision 1.7
diff -u -p -r1.7 hub.h
--- sgi/xbow/hub.h	8 Nov 2009 22:44:16 -0000	1.7
+++ sgi/xbow/hub.h	31 May 2010 14:20:57 -0000
@@ -145,7 +145,9 @@
 /* 35-0 available */
 
 /** Level 0 interrupt */
-/* 63-7 available */
+/* 63-9 available */
+#define HUBPI_ISR0_CPU_ACTION_B		8
+#define HUBPI_ISR0_CPU_ACTION_A		7
 /* IPI interrupts */
 #define	HUBPI_ISR0_IPI_B		6
 #define	HUBPI_ISR0_IPI_A		5

IPI

Linuxを参考に、IPIのIRQをヘッダに足してみる。

Index: hub.h
===================================================================
RCS file: /cvs/src/sys/arch/sgi/xbow/hub.h,v
retrieving revision 1.7
diff -u -p -r1.7 hub.h
--- hub.h	8 Nov 2009 22:44:16 -0000	1.7
+++ hub.h	22 May 2010 12:08:57 -0000
@@ -145,7 +145,11 @@
 /* 35-0 available */
 
 /** Level 0 interrupt */
-/* 63-7 available */
+/* 63-11 available */
+#define HUBPI_ISR0_CPU_CALL_B		10
+#define HUBPI_ISR0_CPU_CALL_A		9
+#define HUBPI_ISR0_CPU_RESCHED_B	8
+#define HUBPI_ISR0_CPU_RESCHED_A	7
 /* IPI interrupts */
 #define	HUBPI_ISR0_IPI_B		6
 #define	HUBPI_ISR0_IPI_A		5

しかし、元々IPI_A、IPI_Bというのがあるような…?なんでIRQLinuxと一致しとらんのかちょっとよく分かってない。
一つづつ試すしか無いのか。

LinuxではIPIの初期化・割り込み発生を直接HUBへの書き込みで設定していたが、OpenBSDには既に汎用化された関数が定義されてるのでこれを使ってみる。
やり方はIP30(Octane)の時と同じ。

+int
+hw_ipi_intr_establish(int (*func)(void *), u_long cpuid)
+{
+	printf("%s %s %d\n", __FILE__, __func__, __LINE__);
+	int irq = cpuid == 0 ? HUBPI_ISR0_CPU_CALL_A : HUBPI_ISR0_CPU_CALL_B;
+	return xbow_intr_establish(func, (void *)cpuid, irq,
+	    IPL_IPI, NULL, &curcpu()->ci_ipiih);
+	printf("%s %s %d\n", __FILE__, __func__, __LINE__);
+	return 0;
+};
+
+void
+hw_ipi_intr_set(u_long cpuid)
+{
+	printf("%s %s %d\n", __FILE__, __func__, __LINE__);
+	int irq = cpuid == 0 ? HUBPI_ISR0_CPU_CALL_A : HUBPI_ISR0_CPU_CALL_B;
+	xbow_intr_set(irq);
+	printf("%s %s %d\n", __FILE__, __func__, __LINE__);
+}
+
+void
+hw_ipi_intr_clear(u_long cpuid)
+{
+	printf("%s %s %d\n", __FILE__, __func__, __LINE__);
+	int irq = cpuid == 0 ? HUBPI_ISR0_CPU_CALL_A : HUBPI_ISR0_CPU_CALL_B;
+	xbow_intr_clear(irq);
+	printf("%s %s %d\n", __FILE__, __func__, __LINE__);
+}
+
+#endif

テストしてみる。
…割り込み掛からない。

原因は2通り考えられる:
・割り込みの起こし方が間違っている。hw_ipi_intr_set()側。
・割り込みの有効化方法が間違っている。hw_ipi_intr_establish()側。

どちらだか今の所分かっていない。
Linuxと同じく、一度低レベルな方法(直接HUBへアクセス)でためしてみるべきか。

追記:
HUBPI_ISR0_IPI_A|Bで再チャレンジしてみたが、やはり割り込みがかからない。
未だ理由は良く分からない。

割り込みコントローラへのSMP対応コード

全く動作確認取ってないしコンパイルすら通してないけど、俺のゴーストはこれで大丈夫とささやいてるから多分大体あってるはず。
アクセスするレジスタ類はLinuxのip27のコードに合わせて、interm,imaskの配列化は以前ip30向けに実装したコードを参照。

Index: ip27_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/sgi/sgi/ip27_machdep.c,v
retrieving revision 1.51
diff -u -p -r1.51 ip27_machdep.c
--- ip27_machdep.c	9 May 2010 18:37:47 -0000	1.51
+++ ip27_machdep.c	21 May 2010 05:58:48 -0000
@@ -108,7 +113,7 @@ struct intrhand *hubpi_intrhand1[HUBPI_N
 
 struct {
 	uint64_t hw[2];
-} hubpi_intem, hubpi_imask[NIPLS];
+} hubpi_intem[MAXCPUS], hubpi_imask[MAXCPUS][NIPLS];
 
 void
 ip27_setup()
@@ -645,12 +663,13 @@ int
 ip27_hub_intr_register(int widget, int level, int *intrbit)
 {
 	int bit;
+	u_long cpuid = cpu_number();
 
 	/*
 	 * Try to allocate a bit on hardware level 0 first.
 	 */
 	for (bit = HUBPI_INTR0_WIDGET_MAX; bit >= HUBPI_INTR0_WIDGET_MIN; bit--)
-		if ((hubpi_intem.hw[0] & (1UL << bit)) == 0)
+		if ((hubpi_intem[cpuid].hw[0] & (1UL << bit)) == 0)
 			goto found;
 
 	/*
@@ -806,21 +825,25 @@ ip27_hub_splx(int newipl)
 
 #define	INTR_FUNCTIONNAME	hubpi_intr0
 #define	MASK_FUNCTIONNAME	ip27_hub_intr_makemasks0
-#define	INTR_LOCAL_DECLS
-#define	MASK_LOCAL_DECLS
+#define	INTR_LOCAL_DECLS \
+	u_long cpuid = cpu_number();
+#define	MASK_LOCAL_DECLS \
+	u_long cpuid = cpu_number();
 #define	INTR_GETMASKS \
 do { \
-	/* XXX this assumes we run on cpu0 */ \
+	int cpu = curcpu()->ci_hw.physid; \
 	isr = IP27_LHUB_L(HUBPI_IR0); \
-	imr = IP27_LHUB_L(HUBPI_CPU0_IMR0); \
+	imr = IP27_LHUB_L(cpu == 0 ? HUBPI_CPU0_IMR0 : HUBPI_CPU1_IMR0); \
 	bit = HUBPI_INTR0_WIDGET_MAX; \
 } while (0)
 #define	INTR_MASKPENDING \
 do { \
-	IP27_LHUB_S(HUBPI_CPU0_IMR0, imr & ~isr); \
+	int cpu = curcpu()->ci_hw.physid; \
+	IP27_LHUB_S(cpu == 0 ? HUBPI_CPU0_IMR0 : HUBPI_CPU1_IMR0, \
+		imr & ~isr); \
 	(void)IP27_LHUB_L(HUBPI_IR0); \
 } while (0)
-#define	INTR_IMASK(ipl)		hubpi_imask[ipl].hw[0]
+#define	INTR_IMASK(ipl)		hubpi_imask[cpuid][ipl].hw[0]
 #define	INTR_HANDLER(bit)	hubpi_intrhand0[bit]
 #define	INTR_SPURIOUS(bit) \
 do { \
@@ -828,7 +851,8 @@ do { \
 } while (0)
 #define	INTR_MASKRESTORE \
 do { \
-	IP27_LHUB_S(HUBPI_CPU0_IMR0, imr); \
+	int cpu = curcpu()->ci_hw.physid; \
+	IP27_LHUB_S(cpu == 0 ? HUBPI_CPU0_IMR0 : HUBPI_CPU1_IMR0, imr); \
 	(void)IP27_LHUB_L(HUBPI_IR0); \
 } while (0)
 #define	INTR_MASKSIZE	HUBPI_NINTS
@@ -837,21 +861,25 @@ do { \
 
 #define	INTR_FUNCTIONNAME	hubpi_intr1
 #define	MASK_FUNCTIONNAME	ip27_hub_intr_makemasks1
-#define	INTR_LOCAL_DECLS
-#define	MASK_LOCAL_DECLS
+#define	INTR_LOCAL_DECLS \
+	u_long cpuid = cpu_number();
+#define	MASK_LOCAL_DECLS \
+	u_long cpuid = cpu_number();
 #define	INTR_GETMASKS \
 do { \
-	/* XXX this assumes we run on cpu0 */ \
+	int cpu = curcpu()->ci_hw.physid; \
 	isr = IP27_LHUB_L(HUBPI_IR1); \
-	imr = IP27_LHUB_L(HUBPI_CPU0_IMR1); \
+	imr = IP27_LHUB_L(cpuid == 0 ? HUBPI_CPU0_IMR1 : HUBPI_CPU1_IMR1); \
 	bit = HUBPI_INTR1_WIDGET_MAX; \
 } while (0)
 #define	INTR_MASKPENDING \
 do { \
-	IP27_LHUB_S(HUBPI_CPU0_IMR1, imr & ~isr); \
+	int cpu = curcpu()->ci_hw.physid; \
+	IP27_LHUB_S(cpu == 0 ? HUBPI_CPU0_IMR1 : HUBPI_CPU1_IMR1, \
+		imr & ~isr); \
 	(void)IP27_LHUB_L(HUBPI_IR1); \
 } while (0)
-#define	INTR_IMASK(ipl)		hubpi_imask[ipl].hw[1]
+#define	INTR_IMASK(ipl)		hubpi_imask[cpuid][ipl].hw[1]
 #define	INTR_HANDLER(bit)	hubpi_intrhand1[bit]
 #define	INTR_SPURIOUS(bit) \
 do { \
@@ -859,7 +887,8 @@ do { \
 } while (0)
 #define	INTR_MASKRESTORE \
 do { \
-	IP27_LHUB_S(HUBPI_CPU0_IMR1, imr); \
+	int cpu = curcpu()->ci_hw.physid; \
+	IP27_LHUB_S(cpu == 0 ? HUBPI_CPU0_IMR1 : HUBPI_CPU1_IMR1, imr); \
 	(void)IP27_LHUB_L(HUBPI_IR1); \
 } while (0)
 #define	INTR_MASKSIZE	HUBPI_NINTS
@@ -869,12 +898,13 @@ do { \
 void
 ip27_hub_setintrmask(int level)
 {
-	/* XXX this assumes we run on cpu0 */
-	IP27_LHUB_S(HUBPI_CPU0_IMR0,
-	    hubpi_intem.hw[0] & ~hubpi_imask[level].hw[0]);
+	int cpu = curcpu()->ci_hw.physid;
+	u_long cpuid = cpu_number();
+	IP27_LHUB_S(cpu == 0 ? HUBPI_CPU0_IMR0 : HUBPI_CPU1_IMR0,
+	    hubpi_intem[cpuid].hw[0] & ~hubpi_imask[cpuid][level].hw[0]);
 	(void)IP27_LHUB_L(HUBPI_IR0);
-	IP27_LHUB_S(HUBPI_CPU0_IMR1,
-	    hubpi_intem.hw[1] & ~hubpi_imask[level].hw[1]);
+	IP27_LHUB_S(cpu == 0 ? HUBPI_CPU0_IMR1 : HUBPI_CPU1_IMR1,
+	    hubpi_intem[cpuid].hw[1] & ~hubpi_imask[cpuid][level].hw[1]);
 	(void)IP27_LHUB_L(HUBPI_IR1);
 }

Exceptionはハンドル出来てるぽ

hw_cpu_hatch()で割り込み有効にしてbreakかけてddbが上がるかどうか確かめればExceptionをハンドルしてtrap出来てるか分かるという単純極まりない事実に気づいて早速試してみる。

        /*
         * Build proper TLB refill handler trampolines.
         */
        extern void xtlb_miss;
        xtlb_handler = (vaddr_t)&xtlb_miss;

        build_trampoline(TLB_MISS_EXC_VEC, xtlb_handler);
        build_trampoline(XTLB_MISS_EXC_VEC, xtlb_handler);
        
        /*
         * Turn off bootstrap exception vectors.
         */
        setsr(getsr() & ~SR_BOOT_EXC_VEC);
        
        /*
         * Clear out the I and D caches.
         */
        Mips10k_ConfigCache(ci);
        Mips_SyncCache(ci);
        
//      cpu_startclock(ci);

//      ncpus++;
//      cpuset_add(&cpus_running, ci);
 
//      mips64_ipi_init();
        /* XXX: setintrmask(0) here */

        spl0();
        (void)updateimask(0);
 
        Debugger();
vscsi0 at root
scsibus2 at vscsi0: 256 targets
softraid0 at root
boot device: sd0
root on sd0a swap on sd0b dump on sd0b
clock_int5
Stopped at      0xa800000000439064:     jr      ra
0xa800000000439068:      nop
ddb{1}> 

おk。ちゃんと動いとる。

Origin 350のセカンダリプロセッサ起動パッチを投げた

この間の起動テストコードに、CPU初期化時にセカンダリプロセッサを探してnasid, physidをstruct cpu_hwinfo secondarycpu_hwinfo[MAXCPUS]に保存し、後でこれを見に行って順に起こすというコードを足した。
でもbootcpu_hwinfoとsecondarycpu_hwinfo[]が分かれてるのはちょっとキモイよな。
と思うのでコメント求む的なメールを投げてみる。

Index: mips64/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/mips64/include/cpu.h,v
retrieving revision 1.58
diff -u -p -r1.58 cpu.h
--- mips64/include/cpu.h	28 Apr 2010 16:20:28 -0000	1.58
+++ mips64/include/cpu.h	18 May 2010 04:31:55 -0000
@@ -370,6 +370,10 @@ struct cpu_hwinfo {
	uint32_t	tlbsize;
	uint		type;
	uint32_t	l2size;
+#ifdef TGT_ORIGIN
+	int		nasid;
+	int		physid;
+#endif
};

struct cpu_info {
Index: sgi/include/intr.h
===================================================================
RCS file: /cvs/src/sys/arch/sgi/include/intr.h,v
retrieving revision 1.41
diff -u -p -r1.41 intr.h
--- sgi/include/intr.h	18 Jan 2010 16:59:23 -0000	1.41
+++ sgi/include/intr.h	18 May 2010 04:31:55 -0000
@@ -190,6 +190,8 @@ void	dosoftint(void);
#ifdef MULTIPROCESSOR
#if defined (TGT_OCTANE)
#define ENABLEIPI() updateimask(~CR_INT_2) /* enable IPI interrupt level */
+#elif defined (TGT_ORIGIN)
+#define ENABLEIPI() /* notyet */
#else
#error MULTIPROCESSOR kernel not supported on this configuration
#endif
Index: sgi/sgi/ip27_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/sgi/sgi/ip27_machdep.c,v
retrieving revision 1.51
diff -u -p -r1.51 ip27_machdep.c
--- sgi/sgi/ip27_machdep.c	9 May 2010 18:37:47 -0000	1.51
+++ sgi/sgi/ip27_machdep.c	18 May 2010 04:31:55 -0000
@@ -28,6 +28,7 @@
#include <sys/malloc.h>
#include <sys/reboot.h>
#include <sys/tty.h>
+#include <sys/proc.h>

#include <mips64/arcbios.h>
#include <mips64/archtype.h>
@@ -56,6 +57,10 @@ extern char *hw_prod;

extern void (*md_halt)(int);

+#ifdef MULTIPROCESSOR
+extern struct cpu_hwinfo secondarycpu_hwinfo[MAXCPUS];
+#endif
+
paddr_t	ip27_widget_short(int16_t, u_int);
paddr_t	ip27_widget_long(int16_t, u_int);
paddr_t	ip27_widget_map(int16_t, u_int,bus_addr_t *, bus_size_t *);
@@ -297,6 +302,10 @@ ip27_setup()
void
ip27_autoconf(struct device *parent)
{
+#ifdef MULTIPROCESSOR
+	int cpuid;
+#endif
+
	union {
		struct mainbus_attach_args maa;
		struct cpu_attach_args caa;
@@ -318,6 +327,15 @@ ip27_autoconf(struct device *parent)
	u.maa.maa_name = "clock";
	config_found(parent, &u, ip27_print);

+	for (cpuid = 1; cpuid < MAXCPUS; cpuid++)
+		if (secondarycpu_hwinfo[cpuid].clock != 0 
+		&& secondarycpu_hwinfo[cpuid].nasid == currentnasid) {
+			u.maa.maa_name = "cpu";
+			u.maa.maa_nasid = currentnasid;
+			u.caa.caa_hw = &secondarycpu_hwinfo[cpuid];
+			config_found(parent, &u, ip27_print);
+		}
+
	/*
	 * Now attach all nodes' I/O devices.
	 */
@@ -919,3 +937,90 @@ ip27_nmi(void *arg)
	printf("Resetting system...\n");
	boot(RB_USERREQ);
}
+
+#ifdef MULTIPROCESSOR
+
+#define LAUNCH_SLAVE \
+	(*(void (*)(int nasid, int cpu, void *call_addr, uint64_t call_parm, \
+	void *stack_addr, void *gp_addr)) PHYS_TO_CKSEG1(0x1fc00038))
+
+void
+hw_cpu_boot_secondary(struct cpu_info *ci)
+{
+	vaddr_t kstack;
+
+	kstack = alloc_contiguous_pages(USPACE);
+	if (kstack == NULL)
+		panic("unable to allocate idle stack\n");
+	bzero((char *)kstack, USPACE);
+	ci->ci_curprocpaddr = (void *)kstack;
+
+	LAUNCH_SLAVE(ci->ci_hw.nasid, ci->ci_hw.physid, hw_cpu_spinup_trampoline,
+		(uint64_t)ci, (void *)(kstack + USPACE), 0);
+
+	while (!cpuset_isset(&cpus_running, ci))
+		;
+}
+
+void
+hw_cpu_hatch(struct cpu_info *ci)
+{
+	int s;
+
+	/*
+	 * 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_set_page_mask(TLB_PAGE_MASK);
+	tlb_set_wired(0);
+	tlb_flush(64);
+	tlb_set_wired(UPAGES / 2);
+
+	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);
+
+	cpu_startclock(ci);
+
+	ncpus++;
+	cpuset_add(&cpus_running, ci);
+
+	mips64_ipi_init();
+	/* XXX: setintrmask(0) here */
+
+	spl0();
+	(void)updateimask(0);
+
+	SCHED_LOCK(s);
+	cpu_switchto(NULL, sched_chooseproc());
+}
+
+int
+hw_ipi_intr_establish(int (*func)(void *), u_long cpuid)
+{
+	return 0;
+};
+
+void
+hw_ipi_intr_set(u_long cpuid)
+{
+}
+
+void
+hw_ipi_intr_clear(u_long cpuid)
+{
+}
+
+#endif
Index: sgi/sgi/sginode.c
===================================================================
RCS file: /cvs/src/sys/arch/sgi/sgi/sginode.c,v
retrieving revision 1.19
diff -u -p -r1.19 sginode.c
--- sgi/sgi/sginode.c	6 Apr 2010 19:09:50 -0000	1.19
+++ sgi/sgi/sginode.c	18 May 2010 04:31:56 -0000
@@ -76,6 +76,10 @@ int	kl_n_mode = 0;
u_int	kl_n_shift = 32;
klinfo_t *kl_glass_console = NULL;

+#ifdef MULTIPROCESSOR
+struct cpu_hwinfo secondarycpu_hwinfo[MAXCPUS];
+#endif
+
void
kl_init(int ip35)
{
@@ -258,8 +262,24 @@ kl_first_pass_comp(klinfo_t *comp, void 
			bootcpu_hwinfo.clock = cpucomp->cpu_speed * 1000000;
			bootcpu_hwinfo.tlbsize = 64;
			bootcpu_hwinfo.type = (cpucomp->cpu_prid >> 8) & 0xff;
-		} else
+			bootcpu_hwinfo.nasid = comp->nasid;
+			bootcpu_hwinfo.physid = comp->physid;
+		} else {
+#ifdef MULTIPROCESSOR
+			int cpuid = ncpusfound;
+			secondarycpu_hwinfo[cpuid].c0prid = cpucomp->cpu_prid;
+			if (ip35)
+				secondarycpu_hwinfo[cpuid].c1prid = cpucomp->cpu_prid;
+			else
+				secondarycpu_hwinfo[cpuid].c1prid = cpucomp->cpu_fpirr;
+			secondarycpu_hwinfo[cpuid].clock = cpucomp->cpu_speed * 1000000;
+		        secondarycpu_hwinfo[cpuid].tlbsize = 64;
+			secondarycpu_hwinfo[cpuid].type = (cpucomp->cpu_prid >> 8) & 0xff;
+			secondarycpu_hwinfo[cpuid].nasid = comp->nasid;
+			secondarycpu_hwinfo[cpuid].physid = comp->physid;
+#endif
			ncpusfound++;
+		}
		break;

	case KLSTRUCT_MEMBNK:

CAlias

第四回 カーネルVM探検隊でも話した通り、Originのメモリレイアウトでは物理メモリの先頭64KBずつが各プロセッサで排他的に使えるメモリ領域として割り当てられており、実際の位置に関わらず物理アドレスは0x0になっている。
ので、Exception Vectorがこの仕様に巻き込まれて迷惑な訳で…。

Exception Vectorはarch/sgi/sgi/machdep.cで作っているんだが、ここへゴリゴリ#ifdef入れるのはあまりにも不恰好だろう、と思いarch/sgi/sgi/ip27_machdep.cのhw_cpu_hatch()にException Vectorを作るコードをそのまま持ってきた。
セカンダリプロセッサが起動した時に自力で初期化させる。

一応printfとか動いてたし多分イケてると思うんだけど…何か未だ自信なし。クロック割り込みの動作確認は取れず。

ところでCPUと完全独立なL1コンソールはCPUのデバッグに使えないのだろうか??

+void
+hw_cpu_hatch(struct cpu_info *ci)
+{
+	int s;
+	vaddr_t xtlb_handler;
+	extern char exception[], e_exception[];
+
+	/*
+	 * Set curcpu address on this processor.
+	 */
+	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_set_page_mask(TLB_PAGE_MASK);
+	tlb_set_wired(0);
+	tlb_flush(64);
+	tlb_set_wired(UPAGES / 2);
+
+	tlb_set_pid(0);
+
+	/*
+	 * Copy down exception vector code.
+	 */
+	bcopy(exception, (char *)CACHE_ERR_EXC_VEC, e_exception - exception);
+	bcopy(exception, (char *)GEN_EXC_VEC, e_exception - exception);
+
+	/*
+	 * Build proper TLB refill handler trampolines.
+	 */
+	extern void xtlb_miss;
+	xtlb_handler = (vaddr_t)&xtlb_miss;
+
+	build_trampoline(TLB_MISS_EXC_VEC, xtlb_handler);
+	build_trampoline(XTLB_MISS_EXC_VEC, xtlb_handler);
+
+	/*
+	 * Turn off bootstrap exception vectors.
+	 */
+	setsr(getsr() & ~SR_BOOT_EXC_VEC);
+
+	/*
+	 * Clear out the I and D caches.
+	 */
+	Mips10k_ConfigCache(ci);
+	Mips_SyncCache(ci);
+
+	cpu_startclock(ci);
+
+//	ncpus++;
+//	cpuset_add(&cpus_running, ci);
+
+//	mips64_ipi_init();
+	/* XXX: setintrmask(0) here */
+
+	spl0();
+	(void)updateimask(0);
+
+	while(1)
+		printf("cpu_hatch\n");
+
+	SCHED_LOCK(s);
+	cpu_switchto(NULL, sched_chooseproc());
+}