APC8750にNetBSD/evbarmを移植するための記録 10/3
一日releaseさせて、いざ。
ramdisk.fsがインストールカーネルのfsなので、それをmdsetimageしてブートしてみたが、症状は同じであった。つまり、何にも変わらない。
ということで、mdsetimageやらramdisk.fsを疑うよりも、/sbin/initが動いているのか追っかけてみるのがよさそうである。
/sbin/initはユーザ空間では動いていないので、コンソール出力といってもcnputcは使えないよなぁ、と思いながらinit.cを読む。
するとsbin/init/init.c#393にはprint_consoleという関数が用意されている。少し手前の#if 0で潰されているけれど、なんだこれは。
さて、init.cをいじってramdisk.fsを作るのは面倒くさそうである。build.sh releaseを毎回やるのは時間がかかりすぎる。もっと良い手があるはず。
build中のログを見ると、
ということで、main関数の最初のほうでprint_consoleを仕込んでみた。
トレースからなんとなく、openがソフトウェア割込み(swi)を発生させて、その割込みをswi_handlerが拾って割込み処理をしているように見える。
panicとともに表示されているno console deviceと出力しているのは//nxr.netbsd.org/xref/src/sys/dev/cons.c#cnopen関数である。
なんとなくcn_tabに見覚えがあったので、sys/arch/arm/ixp12x0/ixp12x0_com.c#ixpcom_attach_subrをみてみると、
動かしてみると、wmtcom_attach_subrで止まる。printf debugしてみるとdelay(10000)で止まっている。
とはいえ、delayを#ifdef hogeで飛ばすと、ひとまず先に進んで、やっぱりとまる。
wmtcomxxxxのaprintf_normalが動く保証がどこにもないな。
うーん、かたっぱしからpanicするようにしたらいいんだろうか。
まず、//nxr.netbsd.org/xref/src/sys/dev/cons.c#cnopenをprintf debug
sys/dev/cons.c#cnopenの手前にある定義ではこうなっている。
あらためて考えたら、ちゃんとsbin/init/init.cの中が実行されているということだよな。
ramdisk.fsがインストールカーネルのfsなので、それをmdsetimageしてブートしてみたが、症状は同じであった。つまり、何にも変わらない。
ということで、mdsetimageやらramdisk.fsを疑うよりも、/sbin/initが動いているのか追っかけてみるのがよさそうである。
/sbin/initはユーザ空間では動いていないので、コンソール出力といってもcnputcは使えないよなぁ、と思いながらinit.cを読む。
するとsbin/init/init.c#393にはprint_consoleという関数が用意されている。少し手前の#if 0で潰されているけれど、なんだこれは。
392 static void 393 print_console(int level, const char *message, va_list ap) 394 { 395 /* 396 * XXX: syslog seems to just plain not work in console-only 397 * XXX: situation... that should be fixed. Let's leave this 398 * XXX: note + code here in case someone gets in trouble and 399 * XXX: wants to debug. -- Jachym Holecek <freza (at) liberouter.org> 400 */ 401 char errbuf[1024]; 402 int fd, len; 403 404 /* We can't do anything on errors, anyway... */ 405 fd = open(_PATH_CONSOLE, O_WRONLY); 406 if (fd == -1) 407 return ; 408 409 /* %m will get lost... */ 410 len = vsnprintf(errbuf, sizeof(errbuf), message, ap); 411 (void)write(fd, (void *)errbuf, len); 412 (void)close(fd); 413 }いかにもopen, write, closeてな調子でシステムコールを呼んでくれそうだ。ひいては、それがwmtcomopenやwmtcomwriteを読んでくれるのではないか。まぁ、open, writeは実装されていないから、シリアルドライバをちゃんと動くようにしなきゃダメだろうけど。ひとまず、手掛かりを追ってみよう。
さて、init.cをいじってramdisk.fsを作るのは面倒くさそうである。build.sh releaseを毎回やるのは時間がかかりすぎる。もっと良い手があるはず。
build中のログを見ると、
===> Updated makewrapper: /usr/src/obj/tooldir.NetBSD-6.99.23-amd64/bin/nbmake-evbarmなる行がある。これを使えば、とても楽ちんである。
builder# cd /usr/src/distrib/evbarm/instkernel/ramdisk/ builder# vi /usr/src/sbin/init/init.c builder# /usr/src/obj/tooldir.NetBSD-6.99.23-amd64/bin/nbmake-evbarm > make.log builder# cp obj/ramdisk.fs /root/mdこれでinit.cを修正した版のramdisk.fsができるのである。
ということで、main関数の最初のほうでprint_consoleを仕込んでみた。
wmtmr0 at obio0 addr 0xd8100000-0xd810ffff intr 48 : WMT System Timer wmtcom0 at obio0 addr 0xd8200000-0xd820ffff intr 32 : WMT UART wmtcom:wmtcom_attach_subr icu: establish_irq: is->is_irq=0x20 icu: unblock: irqbase=0x00000020, irqmask=0x00000001, irq_num=32, reg=0x00000008 icu: establish_irq: is->is_irq=0x30 icu: unblock: irqbase=0x00000020, irqmask=0x00010000, irq_num=48, reg=0x00000008 rn_init: radix functions require max_keylen be set start_init module_init_class boot device: <unknown> root on md0a dumps on md0b mountroot: trying nfs... mountroot: trying msdos... mountroot: trying ffs... root file system type: ffs configure3 inittodr WARNING: no TOD clock present WARNING: using filesystem time WARNING: CHECK AND RESET THE DATE! uvm_swap_init uvm_scheduler init: copying out flags `-s' 3 init: copying out path `/sbin/init' 11 move out arg pinters sys_execve sys_execve: eror = -2 panic: cnopen: no console device Stopped in pid 1.1 (init) at netbsd:cpu_Debugger+0x4: bx r14 0xca86cc94: netbsd:vpanic+0xc 0xca86ccac: netbsd:printf_nolog 0xca86ccd8: netbsd:cnopen+0xf0 0xca86cd00: netbsd:cdev_open+0x68 0xca86cd50: netbsd:spec_open+0x198 0xca86cd70: netbsd:VOP_OPEN+0x60 0xca86ce24: netbsd:vn_open+0x1dc 0xca86ce9c: netbsd:do_open+0xb0 0xca86cecc: netbsd:do_sys_openat+0x7c 0xca86cef0: netbsd:sys_open+0x34 0xca86cf84: netbsd:syscall+0x88 0xca86cfac: netbsd:swi_handler+0x98 db>よっしゃpanicしてくれた。
トレースからなんとなく、openがソフトウェア割込み(swi)を発生させて、その割込みをswi_handlerが拾って割込み処理をしているように見える。
panicとともに表示されているno console deviceと出力しているのは//nxr.netbsd.org/xref/src/sys/dev/cons.c#cnopen関数である。
96 cndev = cn_tab->cn_dev; 97 if (cndev == NODEV) { 98 /* 99 * This is most likely an error in the console attach 100 * code. Panicking looks better than jumping into nowhere 101 * through cdevsw below.... 102 */ 103 panic("cnopen: no console device"); 104 }ということで、cn_tab->cn_devがないのである。
なんとなくcn_tabに見覚えがあったので、sys/arch/arm/ixp12x0/ixp12x0_com.c#ixpcom_attach_subrをみてみると、
183 void 184 ixpcom_attach_subr(struct ixpcom_softc *sc) 185 { ... 223 224 tty_attach(tp); 225 226 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { 227 int maj; 228 229 /* locate the major number */ 230 maj = cdevsw_lookup_major(&ixpcom_cdevsw); 231 232 cn_tab->cn_dev = makedev(maj, device_unit(sc->sc_dev)); 233 234 aprint_normal("%s: console\n", device_xname(sc->sc_dev)); 235 }ここで定義している。つまり、wmtcom_attach_subrで同じようにしてやればよいのであろう。コピーして、すこし手直しすればよさそうである。
動かしてみると、wmtcom_attach_subrで止まる。printf debugしてみるとdelay(10000)で止まっている。
196 /* Make sure the console is always "hardwired". */ 197 /* XXX IXPCOM_SR should be checked */ 198 delay(10000); /* wait for output to finish */これは、やっぱしdelayを適当に作ったのがイカンかったようですな。wmt_tmr.cもやっぱりちゃんとやらないとダメなんですね。うーん。
とはいえ、delayを#ifdef hogeで飛ばすと、ひとまず先に進んで、やっぱりとまる。
d814007c: 00000000 -> 00000000 wmtmr0 at obio0 addr 0xd8100000-0xd810ffff intr 48 : WMT System Timer wmtcom0 at obio0 addr 0xd8200000-0xd820ffff intr 32 : WMT UART wmtcom:wmtcom_attach_subr wmtcom:wmtcom_attach_subr 1 wmtcom:wmtcom_attach_subr 1-1 wmtcom:wmtcom_attach_subr 1-2 wmtcom:wmtcom_attach_subr 1-3 wmtcom:wmtcom_attach_subr 2 wmtcom:wmtcom_attach_subr 3 wmtcom:wmtcom_attach_subr 3-1 wmtcom0: console icu: establish_irq: is->is_irq=0x20 icu: unblock: irqbase=0x00000020, irqmask=0x00000001, irq_num=32, reg=0x00000008 icu: establish_irq: is->is_irq=0x30 icu: unblock: irqbase=0x00000020, irqmask=0x00010000, irq_num=48, reg=0x00000008 rn_init: radix functions require max_keylen be set start_init module_init_class boot device: <unknown> root on md0a dumps on md0b mountroot: trying nfs... mountroot: trying msdos... mountroot: trying ffs... root file system type: ffs configure3 inittodr WARNING: no TOD clock present WARNING: using filesystem time WARNING: CHECK AND RESET THE DATE! uvm_swap_init uvm_scheduler init: copying out flags `-s' 3 init: copying out path `/sbin/init' 11 move out arg pinters sys_execve sys_execve: eror = -2cons.cは通っているんだろうか?
wmtcomxxxxのaprintf_normalが動く保証がどこにもないな。
うーん、かたっぱしからpanicするようにしたらいいんだろうか。
まず、//nxr.netbsd.org/xref/src/sys/dev/cons.c#cnopenをprintf debug
uvm_swap_init uvm_scheduler init: copying out flags `-s' 3 init: copying out path `/sbin/init' 11 move out arg pinters sys_execve sys_execve: eror = -2 cnopen: minor cnopen: cn_tab == NULL? cnopen: cndev == NODEV? cnopen: dev == cndev? cnopen: cn_devvp == NULLVP? Process (pid 1) got sig 11 Process (pid 1) got sig 11 Process (pid 1) got sig 11 Process (pid 1) got sig 11 Process (pid 1) got sig 11 以降sig 11が続く二回やっても同じ。signal 11はsys/signal.hより、
63 #define SIGSEGV 11 /* segmentation violation */らしい。うーん、変なところを指しているのかな。というか、NULLVPということは、
114 if (cn_devvp[unit] != NULLVP) 115 return 0;ということだから、unitがめちゃくちゃなのかな?
sys_execve: eror = -2 cnopen: minor cnopen: cn_tab == NULL? cnopen: cndev == NODEV? cnopen: dev == cndev? cnopen: cn_devvp == NULLVP? unit=0 Process (pid 1) got sig 11 Process (pid 1) got sig 11 Process (pid 1) got sig 11 Process (pid 1) got sig 11unit=0である。cn_devvp触ったら死んでいるということか。
sys/dev/cons.c#cnopenの手前にある定義ではこうなっている。
struct tty *constty = NULL; /* virtual console output device */ struct consdev *cn_tab; /* physical console device info */ struct vnode *cn_devvp[2]; /* vnode for underlying device. */ int cnopen(dev_t dev, int flag, int mode, struct lwp *l)うーん。なにがいかんのか。わからんので寝る!
あらためて考えたら、ちゃんとsbin/init/init.cの中が実行されているということだよな。
コメント(0件)
- TB-URL http://www.tokuda.net/diary/0838/tb/