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を実装するか思案中。
そうか、、そのためにはまず割り込みもテストしなきゃならないな。
まだ色々とゴールまでは遠い。