OpenBSD/sgi on octane2 - どうしてもprintf()で死ぬ

ここで、cpu1のブートシーケンスを頭から書いておこう。
まず、エントリポイントはこれ:

LEAF(cpu_spinup_trampoline, 0)
	mfc0    v0, COP_0_STATUS_REG
	li	v1, ~SR_INT_ENAB
	and	v0, v1
	ori	v0, SR_KX | SR_UX
	mtc0    v0, COP_0_STATUS_REG    # disable all interrupts
	mtc0	zero, COP_0_CAUSE_REG	# Clear soft interrupts
	LA	gp, _gp
	jal	cpu_hatch
	nop
END(cpu_spinup_trampoline)

引数には現在のcpu_infoが渡されてる。
まぁ、curcpu()使えば必要ないんだけど。

次に、cpu_hatch()が呼ばれる:

#include <mips64/arcbios.h>
void
cpu_hatch(struct cpu_info *ci)
{
	bios_printf("cpu_hatch ci:%p\n", ci);

	prom_cpu_hatch(ci);

	u_long cpumask = (1UL << ci->ci_cpuid);
	atomic_setbits_int(&cpus_running, cpumask);

	for (;;)
		;
}

これは今の所prom_cpu_hatch()を呼ぶだけ。
出来ればこちらにコードを移行したいけど、今の所無理かな。

こちらが実際に初期化を行うコードのprom_cpu_hatch():

extern int atoi(const char *, int, const char **);
void 
prom_cpu_hatch(struct cpu_info *ci)
{
	char *cp;

	void *gp, *sp;
	asm volatile(
		"move %0, $gp\n"
		"move %1, $sp\n"
		: "=r"(gp), "=r"(sp));
	bios_printf("ci:%p\n", ci);
	bios_printf("gp:%p\n", gp);
	bios_printf("sp:%p\n", sp);

	int cpuid = cpu_number();
	bios_printf("cpuid:%d\n", cpuid);

	/*
	 * 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);

	bios_printf("[%s:%s:%d]\n", __FILE__, __func__, __LINE__);
	/*
	 * Determine system type and set up configuration record data.
	 */
	sys_config.cpu[cpuid].clock = 175000000;  /* Reasonable default */
	cp = Bios_GetEnvironmentVariable("cpufreq");
	if (cp && atoi(cp, 10, NULL) > 100)
		sys_config.cpu[cpuid].clock = atoi(cp, 10, NULL) * 1000000;
	bios_printf("[%s:%s:%d]\n", __FILE__, __func__, __LINE__);
	sys_config.cpu[cpuid].type = (cp0_get_prid() >> 8) & 0xff;
	sys_config.cpu[cpuid].vers_maj = (cp0_get_prid() >> 4) & 0x0f;
	sys_config.cpu[cpuid].vers_min = cp0_get_prid() & 0x0f;
	sys_config.cpu[cpuid].fptype = (cp1_get_prid() >> 8) & 0xff;
	sys_config.cpu[cpuid].fpvers_maj = (cp1_get_prid() >> 4) & 0x0f;
	sys_config.cpu[cpuid].fpvers_min = cp1_get_prid() & 0x0f;
	sys_config.cpu[cpuid].tlbsize = 64;
	bios_printf("[%s:%s:%d]\n", __FILE__, __func__, __LINE__);
	Mips10k_ConfigCache();
	bios_printf("[%s:%s:%d]\n", __FILE__, __func__, __LINE__);
	/*
	 * Last chance to call the BIOS. Wiping the TLB means the BIOS' data
	 * areas are demapped on most systems. O2s are okay as they do not have 
	 * mapped BIOS text or data.
	 */
	delay(20*1000);		/* Let any UART FIFO drain... */
	bios_printf("[%s:%s:%d]\n", __FILE__, __func__, __LINE__);
	sys_config.cpu[cpuid].tlbwired = UPAGES / 2;
	tlb_set_wired(0);
	bios_printf("[%s:%s:%d]\n", __FILE__, __func__, __LINE__);
	tlb_flush(sys_config.cpu[cpuid].tlbsize);
	bios_printf("[%s:%s:%d]\n", __FILE__, __func__, __LINE__);
	tlb_set_wired(sys_config.cpu[cpuid].tlbwired);
	bios_printf("[%s:%s:%d]\n", __FILE__, __func__, __LINE__);

	/* XXX it may not correct */
	tlb_set_pid(1);
	bios_printf("[%s:%s:%d]\n", __FILE__, __func__, __LINE__);

	/*
	 * Turn off bootstrap exception vectors.
	 */
	setsr(getsr() & ~SR_BOOT_EXC_VEC);
	bios_printf("[%s:%s:%d]\n", __FILE__, __func__, __LINE__);
	/*
	 * Clear out the I and D caches.
	 */
	Mips_SyncCache();
	bios_printf("[%s:%s:%d]\n", __FILE__, __func__, __LINE__);
	printf("printftest\n");
	bios_printf("[%s:%s:%d]\n", __FILE__, __func__, __LINE__);
	while(1)
		;
}

初期化時に行っている処理はarch/sgi/sgi/machdep.cを参考にしている。
が、多分なにか間違ってるんだろう。

最後あたりの

	Mips_SyncCache();
	bios_printf("[%s:%s:%d]\n", __FILE__, __func__, __LINE__);

までは到達するが、

	printf("printftest\n");
	bios_printf("[%s:%s:%d]\n", __FILE__, __func__, __LINE__);

は出力されない。
printfの中で死んでいるんじゃないだろうか。

TLBがおかしいかな?
pmap.cをSMP化しないで動かせる限界ってここら辺までだっけ・・・?
カーネルの中なら動いたような気がしたんだけどなぁ。
tlb_set_pid(1)は合っているかものすごく怪しいので、そこら辺も確認した方が良さそう。
DDBで細かく追ってみたいが、printfが動かないとなると・・・。

もう少し追おうか、取り合えずIPIを実装するか思案中。
そうか、、そのためにはまず割り込みもテストしなきゃならないな。
まだ色々とゴールまでは遠い。