APC8750にNetBSD/evbarmを移植するための記録 10/3
2014/01/26(日) 22:07 NetBSD はてブ情報 はてブに登録 はてブ数

一日releaseさせて、いざ。

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 = -2
cons.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 11
unit=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の中が実行されているということだよな。

名前:  非公開コメント   

  • TB-URL  http://www.tokuda.net/diary/adiary.cgi/0838/tb/