::log.1999

[ TOP | Recently ]

再開 / interrupt 捕獲。exec init ...? / 割り込みと packet receive / packet transmission / NVRAM / bus_space / bus.h / interrupt / clockattach / DP8393X SONIC Driver / TLB miss。ROM モニタのワークのmap / apbus probe。TLB miss / printf と egcs。egcs の mips-sony-netbsd patch / console 出る。copyright メッセージ / serial 出る / mach_init() のパラメタ / x_maxmem / serial / memory map / mach_init() を追う / make。boot。LED 点灯 / boot ?

1999-08-16 再開


さすがにひと月もほっとくとどこまでやったか忘れている...。
って、こんな時こそこのメモが役に立つのであった :P


とりあえずやるべきことは...

NEWS5000 に載ってる serial は Z85230 で、
Z8250 に FIFO やらが拡張されてる石。sys/dev/ic/z8530reg.h には

* This file also includes flags for the Z85C30 and Z85230 enhanced scc.
* The CMOS 8530 includes extra SDLC functionality, and is used in a
* number of Macs (often in the Z85C80, an 85C30 combined w/ a SCSI
* controller). -wrs

なんて書いてあるんだけど、これはきっと Z85230 のレジスタを定義しただけだろう。
z8530sc.c は Z85230 のレジスタはぜんぜん触ってないので。
つまり Z85230 のドライバは書かなきゃならないんだろうなぁ、ということが一点。

あとは serial の割り込みを拾うこと。
これは sonic ん時みたいに、Z85230 的だけでなく、
APBus 的と、拡張ボードコントローラ的にも割り込み enable に
しなきゃいけないだけなんだろうけど、
まだ調査が足りないのでよくわかってないだけ。...だろう。たぶん。

が、なんか ap_fifo_alloc とかいって APBus 上のメモリ(?) に
fifo 領域を確保したりなんかよくわからないことをしてるんだよなぁ。謎。

そんなわけでしばらくリハビリる。

1999-07-21 interrupt 捕獲。exec init ...?


あははー。割り込み捕れたよ。
なんでこうも割り込み enable mask が方々にあるんだ...

というわけで、news5000 は一つの device の割り込みを
enable するのには、

1) MIPS の StatusRegister の INTMASK を enable
2) NEWS5000 の APBUS の該当スロット(?)の INTMASK を enable
3) そのデバイスの割り込みコントローラ(?)の MASK を enable
4) そのデバイスの割り込みマスクレジスタを enable 

と、4個所もいじんなきゃならなかったのでした。
1,2,4 はやってたんだけど、3 をやってなかった。


で、ap_intr_establish を作って hardware trap から
それぞれのデバイスの割り込みハンドラを呼ばなきゃいけないんだけど、
これはめんどくさいので後まわし。
そんなことよりも、ほんとに packet receive と連動してるのか調べよう。

まず news5000_trap() の level0 割り込みの中で、いきなし snintr() を呼んでやるように仕込む。
level0 割り込みをかける奴は今のところ sonic しかいないので、まぁ、これで動くだろう。

snintr() の中で printf("#") とかやっといて、他の host から broadcast に向けて ping。
おー。ping に同期して '#' が表示されるよ。ばっちりじゃん。

つうわけで、そのまま dhcpd を用意して boot させる。
おぉ、init 読んでる...あ、sn0: receive buffers exhausted だと...。
割り込みおっついてないのかな? 石の叩き方がまずいのかも。
しかし nfs がしつこく retry してくれるから動かないわけではない。

ぐぁ。

init: copying out path `/sbin/init' 11
sn0: receive buffers exhausted
sn0: receive buffers exhausted
sn0: receive buffers exhausted
sn0: receive buffers exhausted
sn0: receive buffers exhausted
sn0: receive buffers exhausted
sn0: receive buffers exhausted
sn0: receive buffers exhausted
sn0: receive buffers exhausted
panic: init died (signal 0, exit 11)
800b792c+70 (c731b000,0,0,0) ra 8001bb88 sz 24
8001bb0c+7c (100,29,0,1) ra 8000b880 sz 32
8000b834+4c (100,b00,0,1) ra 8000b824 sz 104
8000b810+14 (100,b00,0,1) ra 800ac7ec sz 24
800ac64c+1a0 (100,b00,0,1) ra 800022b4 sz 176
mips3_SystemCall+d4 (100,b00,0,1) ra 430930 sz 0
PC 0x430930: not in kernel space
0+430930 (100,b00,0,1) ra 0 sz 0
User-level: pid 1
syncing disks... done
rebooting...

落ちた。

0x430930 というのは、init の仮想アドレス?
mips-sony-netbsd-objdump -Dr /src/boot/negx/root/sbin/init して調べると...

430920:       3c1c0fbe        lui     $gp,0xfbe
430924:       279c8900        addiu   $gp,$gp,-30464
430928:       0399e021        addu    $gp,$gp,$t9
43092c:       24020001        li      $v0,1
430930:       0000000c        syscall
430934:       03e00008        jr      $ra

syscall(1) だから、exit() か。
って、これはつまり sbin/init が exit() してるってことだよな。

grep exit sbin/init.c すると、

_exit(sig);
_exit(0);
_exit(1);

なので、きっと _exit(sig) で落ちてんだよなぁ。
panic させてるのは kern_exit.c の

void
exit1(p, rv)
	register struct proc *p;
	int rv;
{
	register struct proc *q, *nq;
	register struct vmspace *vm;

	if (p->p_pid == 1)
		panic("init died (signal %d, exit %d)",
		    WTERMSIG(rv), WEXITSTATUS(rv));

ここだから...

panic: init died (signal 0, exit 11)

てのはつまり、signal 11 = SEGV で init が死んだ、ってことか? なんか嫌な落ち方。
まぁ、まだ tty も作ってないので何があってもおかしくないが...。

しかしまぁとにかく、init は exec できてて、user mode で init が実行できてはいる、
ってことだな。おじゃほう。

って、それ以前にこの init は
1999 6/25のsnapshot から拾ってきてて、tsubai@wapiko:/a/0625/src/sys/arch/newsmips/compile/GENERIC
の NetBSD-1.4D kernel 用。

つまり NetBSD1.4 で 1.4D の binary を実行しているわけで、それも不安のタネだ。

いや、userland を cross で作るのってめんどくさいし、
NetBSD1.4 の newsmips の binary が見つからなかったからこっから拾っただけなのですが :P

せっかくなので current とシンクロするかなぁ。

1999-07-19 割り込みと packet receive


次は割り込み...
のはずなのだが、なぜか APbus の割り込みが入ってこない。
TIMER の時はあっさり interrupt 捕れたので、
APbus も割り込みマスクさえテキトーに設定すれば trap とんで来るだろう、
と思ってたのだが、来ない...

news5000_intr() でごそごそ printf を仕込むがぜんぜん来てる様子なし。
level2 interrupt の TIMER は元気に動いてるのに...

APBus controller もちゃんと叩かないといけないのか?
とりあえず保留...

*	*	*

並行して sonic で packet の受信。

送信の時にやったように、mac68k/dev/if_sn.c から cut & paste して、
packet descriptor のところをガリガリ変更してテスト。
割り込み status を printf してやると、受信要因の bit は立ってる...
SONIC 的にはちゃんと割り込んでるんだよなぁ。

といっても CPU まで割り込みが上がってこないのでどうしようもない。
しょうがないので packet を送った後に自分で rxintr() を呼んでやる(ひでー

(他の多くの ether driver と同じく) rxintr() 内で割り込み status 見て、
割り込み原因が存在しつづける限り loop して packet 受ける構造なので、
rxintr() は任意のタイミングで呼んでもなんとなく動く。
ふつうは割り込みで駆動されるんだけど。

#でもやっぱり ethernet で polling はしたくないなぁ... :P

テスト。
なんか、ぎこちなくではあるが、packet を受信できるようにはなった...?
すげぇ。ちゃんと rarp の答えを受けとってるよ :)
割り込みなくても結構動くやん。24ヶの ring buffer のおかげだな。

調子にのって options NFS_BOOT_DHCP で make して、
server 側の dhcpd.conf に

host negx {
	hardware ethernet 8:0:46:1:2:af;
	fixed-address 172.17.4.48;
	option host-name "negx.?????????.org";
	option root-path "/src/boot/negx";
	option routers 172.17.4.40;
}

と書いておいて、boot。おー。

Copyright (c) 1996, 1997, 1998, 1999
    The NetBSD Foundation, Inc.  All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
    The Regents of the University of California.  All rights reserved.

NetBSD 1.4 (MISAKI) #325: Mon Jul 19 08:49:48 JST 1999
    ryo@moveq:/src/news5000/sys/arch/newsmips/compile/MISAKI
real mem  = 66060288
avail mem = 56676352
using 1612 buffers containing 6602752 bytes of memory
SONY NET WORK STATION, Model NWS-5000, Machine ID #14894
mainbus0 (root)
cpu0 at mainbus0
cpu0: MIPS R4400 CPU Rev. 6.0 with MIPS R4010 FPC Rev. 0.0
cpu0: L1 cache: 16kb/32b Instruction, 16kb/16b Data, direct mapped
cpu0: L2 cache: 1024kb/64b mixed, no snooping
ap0 at mainbus0
mkclock0 at ap0 slot0 addr 0xbf881fe0: Mostek MK48T02 2KB nvram
sn0 at ap0 slot0 addr 0xbe600000: DP83932 SONIC Ethernet (Rev.0x0004)
sn0: address 08:00:46:01:02:af, using 32KB on-board buffer
sn1 at ap0 slot2 addr 0xb8600000: DP83932 SONIC Ethernet (Rev.0x0004)
sn1: address 08:00:46:01:00:ef, using 32KB on-board buffer
boot device: <unknown>
root device: sn0
dump device: 
file system (default generic): nfs
nfs_boot: trying DHCP/BOOTP
sn0: receive buffers exhausted
nfs_boot: DHCP server: 0xac110428
nfs_boot: my_name=negx
nfs_boot: my_domain=?????????.org
nfs_boot: my_addr=0xac110430
nfs_boot: my_mask=0xffff0000
nfs_boot: gateway=0xac110428
root on :/src/boot/negx
root time: 0x37926898
warning: no /dev/console
init: copying out path `/sbin/init' 11
init: copying out path `/sbin/oinit' 12
init: copying out path `/sbin/init.bak' 15
init: not found
panic: no init
800b7804+70 (c731b000,0,0,0) ra 8001bb88 sz 24
8001bb0c+7c (100,74,0,0) ra 80007d84 sz 32
80007b30+254 (100,74,0,0) ra 80002ff8 sz 264
80002ff0+8 (100,74,0,0) ra 0 sz 0
User-level: pid 1
syncing disks... done
setclock: 72/7/18/23/44/57
rebooting...

すげー。ちゃんと mount して init 読もうとしてるよ :)
#ってこんなことやってないで割り込みをなんとかせねば... ;_;

1999-07-17 packet transmission


やっと packet が出せるようになった...一週間もかかった...。むー。

DP83932 は Packet Desctiptor Area を使って packet を送受信する。
構造は

    ┌─────────┘
    └→┌─────┐
        │  status  │
        │ frag_cnt │
        │ pkt_size │
        │    :     │
        │   ptr  ───→ packet の中身を指す ptr 
        │   link ───┐
        └─────┘  │
    ┌─────────┘
    └→┌─────┐
        │  status  │
        │ frag_cnt │
        │ pkt_size │
        │    :     │
        │   ptr  ───→ packet の中身を指す ptr 
        │   link ───┐
        └─────┘  │

のようになっている。かなり端折ってるけど。

で、これが ring になってて、End Of Link を指定して、
どっからどこまで送れとか、そんな風になっている。
DP8390(NE2000) の RING BUFFER 部分が、更に programmable になった感じ。
(X68000 の DMA Link Array Chain にも似てるね)。

これを使えば mbuf chain で保持されてるパケットも一発で送れる...
はずだが、if_sn.c はそこまではやっていなかった。
常に frag_cnt = 1 として、
mbuf を連続領域に bcopy してから送る。
まぁ、いろいろ問題があるからいいんだけど。
NEWS-OS もそうみたいだし...。
#うまく書けば bcopy 使わなくて済むと思うんだけどな

で、ポインタの類は当然物理アドレスで SONIC に教えてやらなければいけないのだが、
どうやら NEWS5000 はメインメモリ領域は SONIC から見えないらしく、
SONIC 用の packet descriptor/packet buffer用のメモリが用意されていて、そこを使う。
つまり NEWS5000 の EtherBoard は「MACROM + DP83930 + MEMORY」で一つのデバイスとなっているわけだ。

で、packet data もそのメモリ領域からしか送受信できない。
つまり絶対に、一旦 mbuf からそこへ bcopy しなければならない。
で、さらにサイズは 32kbyte。

#arch/pica/dev/if_sn.c も hardwire って書いてるからそういうハードウェアを
#してるのかと思ったけど、こっちは単に手抜きなだけらしい?


arch/mac68k/dev/if_sn.c にはそんな制限ないので、
当然 attach の際に descriptor/buffer 用のメモリを alloc し、
その領域を cache disable にし、
DP83932 にはその領域の physical address な pointer を渡している。

さらに NBPG 境界には desctiptor とか packet buffer がまたがないようにしたり、
それはそれで余計な気を使わなきゃいけなかったりするんだけど。
その代わりメモリ使う量は自由だよな。もちろん 32kbyte 以上メモリを使っている、

だから最初は arch/mac68k/dev/if_sn.c を適当に手直しして使おうと思ったのだが、
上のような障壁がいろいろあって、そのまま持ってくるのはやっぱり面倒...なのでパス。

そんなわけで、descriptor/buffer まわり大幅に書き直しつつも、
cut & paste でツギハギして作る。

が、動かん...う〜ん...

*	*	*

3〜4日ちまちまデバグしてみる。

*	*	*

で、なかなか動かなかったんだけど、なんとか
送信は完璧にできるようになった。おぉ〜〜。

というわけで記念に log っておこう。:D
(attach/kernel / attach/tcpdump)

次は割り込みと受信。また時間かかりそうな...

1999-07-11 NVRAM


ふと、newsmips/newsmips/clockreg.h に書いてある

/*
 * Mostek MK48T02 clock.
 */

というコメントが目にとまる。そう、これは NVRAM。
いや、NVRAM が載ってるのは知ってんだけど。
(以前 フタを あけて 掃除した )

というわけで、altavista で検索...発見。

 The Mostek MK48T02 2k nvram chip has been used in Sun3/80, sun4 and sun4c
systems.  In sun4m systems they use the 8k version -but these are
not dying yet.
Sun is selling the MK48T02 for $70.
In Germany they cost DM 45 / piece or DM 20 in larger quantities.
From this I think that they might be between $10 and $25 in the US.

sun のやつと同じなのね。size は 2kbyte。

ROM monitor でごそごそと調べる。

> ss -d
atr name/vendor    ctlr mu ab sl h/w base    softc rev   driver slave
co- bitmap           
c-- clock             0  0  0  - bf881fe0        -   0        - 
c-- console           0  0  0  -   pseudo ffff3fc0   0        - esccf(0,0)     
c-- dmac3             0  0  0  - be200000 ffff3f80   0        - 
                      1  0  0  - be300000 ffff3f40              

clock (RTC) が 0xbf881fe0 からなので、NVRAM はこの領域を含むはず。

> md bf880000
bf880000: 0000ff41 0000ff50 0000ff32 0000ff00 ...A...P...2....
bf880010: 0000ff66 0000ff64 0000ff64 0000ff69 ...f...d...d...i
bf880020: 0000ff00 0000ff00 0000ff20 0000ff20 ........... ... 
bf880030: 0000ff20 0000ff03 0000ff02 0000ff73 ... ...........s
bf880040: 0000ff6f 0000ff6e 0000ff69 0000ff63 ...o...n...i...c
bf880050: 0000ff00 0000ff00 0000ff20 0000ff21 ........... ...!
bf880060: 0000ff21 0000ff03 0000ff02 0000ff01 ...!............
bf880070: 0000ff00 0000ff00 0000ff00 0000ff00 ................
bf880080: 0000ff00 0000ff00 0000ff00 0000ff00 ................
bf880090: 0000ff00 0000ff00 0000ff00 0000ff00 ................
bf8800a0: 0000ff00 0000ff00 0000ff00 0000ff00 ................
bf8800b0: 0000ff00 0000ff00 0000ff00 0000ff00 ................

これっぽい。

> md bf881000
bf881000: 0000ff00 0000ff07 0000ff55 0000ffa1 ...........U....
bf881010: 0000ff00 0000ff00 0000ff00 0000ff15 ................
bf881020: 0000ff6e 0000ff65 0000ff74 0000ff77 ...n...e...t...w
bf881030: 0000ff6f 0000ff72 0000ff6b 0000ff00 ...o...r...k....
bf881040: 0000ff65 0000ff74 0000ff68 0000ff65 ...e...t...h...e
bf881050: 0000ff72 0000ff6e 0000ff65 0000ff74 ...r...n...e...t
bf881060: 0000ff00 0000ff00 0000ff00 0000ff00 ................
bf881070: 0000ff16 0000ff62 0000ff6f 0000ff6f .......b...o...o
bf881080: 0000ff74 0000ff64 0000ff65 0000ff76 ...t...d...e...v
bf881090: 0000ff00 0000ff73 0000ff63 0000ff73 .......s...c...s
bf8810a0: 0000ff69 0000ff28 0000ff30 0000ff2c ...i...(...0...,
bf8810b0: 0000ff30 0000ff29 0000ff00 0000ff00 ...0...)........
bf8810c0: 0000ff00 0000ff00 0000ff15 0000ff6d ...............m
bf8810d0: 0000ff61 0000ff63 0000ff68 0000ff69 ...a...c...h...i
bf8810e0: 0000ff6e 0000ff65 0000ff00 0000ff6e ...n...e.......n
bf8810f0: 0000ff65 0000ff77 0000ff73 0000ff35 ...e...w...s...5
bf881100: 0000ff30 0000ff30 0000ff30 0000ff00 ...0...0...0....
bf881110: 0000ff00 0000ff00 0000ff00 0000ff12 ................
bf881120: 0000ff63 0000ff70 0000ff75 0000ff74 ...c...p...u...t
bf881130: 0000ff79 0000ff70 0000ff65 0000ff00 ...y...p...e....
bf881140: 0000ff72 0000ff34 0000ff30 0000ff30 ...r...4...0...0

間違いないようだ。

NEWS5000 の rom monitor は環境変数みたいなものが使えて、

> set 
network=ethernet
bootdev=scsi(0,0)
machine=news5000
cputype=r4000
model=NWS-5000
mon=2

このように任意の変数を定義できる。当然電源を切ってもこれは保持されてる。
この内容がそのまま入ってるので、上の領域は間違いなく NVRAM がそのまま map
されてるんだろう。

#ちなみに、ここも 32bit 中 8bit しか使ってない変な bus。
#つっても、busspace 関数はもうちゃんと作ってあるので、
#bus_space_map あーんど bus_space_read_region_1 で何も考えず領域 copy できるけど :-)

size は 2kbyte なので、0x800。
NVRAM の 8bit が NEWS5000 では 32bit に map されてるので、
0xbf880000 〜 0x800*4 で、
0xbf880000 〜 0xbf882000 が NVRAM。そのうちの、
0xbf881fe0 〜 0xbf882000 が RTC と。

ROM monitor は、NVRAM を boot 情報の保持(default で scsi(0,0)からbootしろとか)
くらいにしか使ってないので
(だから電池が切れても時計が狂うくらいで別に支障はない)、
unix から見えてもあんまり嬉しくないんだけど、
やっぱり sparc みたいに /dev/ の下に見えるとかっこいいよなぁ、
とか思いつつ(思っただけ)、sonic の attach のつづきをやる。

#どうやらattach まではいったらしい
#まだ ether_ifattach() してないし割り込みは影も形も、だけど :P

1999-07-09 bus_space


結局 stride は使わずに、全てのタイプの I/O で bus_space_tag_t を変えた。
(遅いし、stride だけだと全部をカバーできないし)

というわけで、試しに readidrom() を bus_space_read_1() を使って書いて、
NWS3400 と NWS5000 とで共有できるようにしてみた。幸せだ。

結局 5 つの bus-space を作った。

struct peripheral_8_8 {
	volatile unsigned char data;		/* data */
};

普通の 8bit mapped I/O。
news3400 の I/O はあらかたこのタイプ(? ...と思う)。

struct peripheral_4_8 {
	volatile unsigned char dummy0:4,	/* pad */
			      data_hi:4;	/* data */
	volatile unsigned char dummy1:4,	/* pad */
			      data_lo:4;	/* data */
};

NEWS3400 の IDROM がこの形式。

struct peripheral_4_32 {
	volatile unsigned char dummy0[3];	/* pad */
	volatile unsigned char dummy1:4,	/* pad */
			      data_hi:4;	/* data */
	volatile unsigned char dummy2[3];	/* pad */
	volatile unsigned char dummy3:4,	/* pad */
			      data_lo:4;	/* data */
};

同じく NEWS5000 の IDROM。

struct peripheral_8_32 {
	volatile unsigned char dummy[3];	/* pad */
	volatile unsigned char data;		/* data */
};

NEWS5000(APBUS) の 8bit I/O port はほぼこの mapping。

struct peripheral_16_64 {
	volatile unsigned int dummy0;		/* pad */
	volatile unsigned short dummy1; 	/* pad */
	volatile unsigned short data;		/* data */
};

同じく APBus の 16bit I/O。SONIC の register はこの形式で map されてる。



で、

struct newsmips_bus_space newsmips_4bit_8bit_bus_space {
	NULL,
	newsmips_bus_space_map,
	newsmips_bus_space_unmap,
	newsmips_bus_space_subregion,
	newsmips_bus_space_alloc,
	newsmips_bus_space_free,
	newsmips_bus_space_barrier,
	newsmips_4bit_8bit_rs_1,
	newsmips_4bit_8bit_rs_2,
	newsmips_4bit_8bit_rs_4,
		:
		:
};

のようにして bus_space_tag を作って、
あとはそれぞれの構造体用に bus_space 関数群を作る。結構な作業量だ。

せっかく調べたので忘れないうちにまとめておこう。

bus_space_map( bus_space_tag_t space, bus_addr_t address,
               bus_size_t size, int flags,
               bus_space_handle_t *handlep)

address から size 分の領域を、space 型のバスとして map し、そのハンドルを *handlep に格納する。以後、この領域へのアクセスは space と handle を介して行う。

が、newsmips では、全ての I/O がリニアに mapping されてるので、実際は map もなにもしていない。
ただ address をそのまま handle に入れているだけ。size にも意味はない。

bus_space_unmap(bus_space_tag_t space,
                bus_space_handle_t handle,
                bus_size_t size)

map した領域を unmap する。
当然 newsmips ではなにもしてない。

bus_space_alloc/free との違いはよくわからず。
unimplement な arch が多いけど...。

bus_space_read_{1,2,4,8}(bus_space_tag_t space,
                         bus_space_handle_t handle,
                         bus_size_t offset)

space 型の bus で、handle で示される I/O 領域の、offset の位置から
{1,2,4,8}byte 読む。
それぞれ、unsigned char, unsigned short, unsigned int, unsigned long long を返す。

newsmips の場合、space はそれぞれの method関数の table なので、
macro で (*space->read_1)(space,handle,offset) みたいなことをして関数を呼びなおしている。
この機構により bus-space によって read/write などの method が切り換えられる仕組み。

それぞれの型に対してアクセス方法を規定しているという点ではオブジェクト思考に近い。
というか bus_space 関数群の仕組みってまさにそうなんだけど。


あと、bus_space_*_8 は他のアーキテクチャでは実装されてないことが多い。

64bit I/O なんてふつー無いからいいのか?
他の arch が実装されてないことに後から気づいたのと、
ヒヨって構造体定義して C で(他の arch は高速化のため asm になってたりする)
ヘラヘラ書いちゃってたこともあって、
勢いで全部 ( bus_space_*_{1,2,4,8}) 作っちゃったよ :-(
ダマサレ。

bus_space_read_multi_{1,2,4,8}(bus_space_tag_t space,
                               bus_space_handle_t handle,
                               bus_size_t offset,
                               u_int{8,16,32,64}_t *datap,
                               bus_size_t count)

bus_space_read_? とほぼ同じだが、同じ port を count回読んで、
読めたデータを datap に count 分書きだしていく。data port を連続して読んだりする場合に使う。

bus_space_read_region_{1,2,4,8}(bus_space_tag_t space,
                                bus_space_handle_t handle,
                                bus_size_t offset,
                                u_int{8,16,32,64}_t *datap,
                                bus_size_t count)

bus_space_read_multi_? とほぼ同じだが、I/O port address も increment しながら読む。

bus_space_write_*()

bus_space_write_* は、read の同名のそれと同じ。
data の分、引数がちょっと変わる程度。

bus_space_set_region_{1,2,4,8}(bus_space_tag_t space,
                               bus_space_handle_t handle,
                               bus_size_t offset,
                               u_int{8,16,32,64}_t value,
                               bus_size_t count)

space 型の bus で、handle で示される I/O 領域の、offset byte の位置から、count 分、
value で埋める。
memset のようなもの。


bus_space_set_multiple_{1,2,4,8}(bus_space_tag_t space,
                                 bus_space_handle_t handle,
                                 bus_size_t offset,
                                 u_int{8,16,32,64}_t value,
                                 bus_size_t count)

最初 bus_space(9) にも書いてないので何すればいいんだろう、とか思ったけど、
memset が I/O port を increment するのに対し、これは同じ port に value を
count 回書き込むもののようだ。


bus_space_copy_region_1(bus_space_tag_t space,
                        bus_space_handle_t srchandle,
                        bus_size_t srcoffset,
                        bus_space_handle_t dsthandle,
                        bus_size_t dstoffset,
                        bus_size_t count)

I/O から I/O への領域 copy。
ほとんど使うことはないんじゃなかろうか...。


...とくれば、bus_space_copy_multiple_? もありそうだけど、無いようだ :P


終わり。

次回はたぶん apbus 用の intr_establish か、
Ether の attach。MAC address くらいは読みたいなぁ :-)

1999-07-07 bus.h


memory mapped I/O の話。

NEWS5000 の SCC (ESCC) の register の map のされ方は

struct zschan {
	unsigned char pad1[3];
	volatile unsigned char zc_csr;
	unsigned char pad2[3];
	volatile unsigned char zc_data;
};

みたいに、8bit port が 32bit 幅に map されている。
まぁ、ぜんぶの I/O がこんなふうに map されてるなら、
bus_space_write_* を 32bit 幅に合わせた macro
(base + offset*4 + 3 を access するような)にすればいいんだけど、
たとえば IDROM は、

struct idrom_reg {
	unsigned int	dummy1:28,
			data1:4;
	unsigned int	dummy2:28,
			data2:4;
};

となってて、data1<<4|data2 としないと目的の 8bit が得られなかったり
(なんでこんななってんだ?)、さらに ether の register は、

struct sonic_regs {
	unsigned long pad1;
	unsigned long cr;
	unsigned long pad2;
	unsigned long dcr;
	unsigned long pad3;
	unsigned long rcr;
		:
		:
};

と、32bit 幅にさらに padding 付きで map されてる。
まぁ、これも macro で逃げればいいんだけど...せっかくある driver
(arhc/mac68k/dev/if_sn.c) が bus_space_* 使ってくれてるんだから、
やっぱり bus_space を用意すべきだよね、っつーことで、
つらつらと他 architecture の実装を見る。

少くとも、device により上のように register の幅を変える必要があるので、
bus_space_read_* を bus_space_tag によって切り変えれる仕組みが必要。

というわけでそんなふうにやってる実装を探す。

*	*	*

alpha,arm32,atari は、全ての method を関数 table 化してあって、
bus_space_tag によってなんでも切り変えられる。
(これらの場合、bus_space_tag は、実際は関数のテーブルへのポインタになっている)

i386 は tag により inb/outb か、memory を read/write するかが切り変わる。
bus_space_tag は定数マクロ。

その他は map/unmap/alloc/free あたりだけを
bus_space_tag で関数 table 化しただけだったり、
完全固定 macro だったり。

いちばん news5000 に合ってるのは、amiga のやつかなぁ。というのは、

struct bus_space_tag {
	bus_addr_t	base;
	u_int8_t	stride;
	u_int8_t	dum[3];
	const struct amiga_bus_space_methods *absm;
};


と、stride という変数があって、bus_space_read_1 が

#define bus_space_read_1(t, h, o) \
    ((void) t, (*(volatile u_int8_t *)((h) + ((o)<<(t)->stride))))

という macro とか、

u_int16_t
amiga_interleaved_read_2(t, h, o)
	bus_space_tag_t t;
	bus_space_handle_t h;
	bus_size_t o;
{
	volatile u_int8_t *q;
	int step;

	step = 1 << t->stride;
	q = (volatile u_int8_t *)(h + (o << t->stride));

	return ((*q) << 8) | *(q + step);
}

といった関数になっている。
まさに news5000 の変則すきま空き I/O にぴったりというか。

ただ、amiga のは map/unmap/alloc/free とかが切り変えられない(固定マクロ)ので、
alpha/arm32/atari をベースにして、なおかつ amiga の stride を導入することにする。
ちょっと冗長な気もするが...

これでほぼどんな変態 I/O map があっても平気なはずだ。
最悪 bus_space_read_* をその device 特有のものに差し換えればいい。

というわけで、alpha/include/bus.h を copy して、s/alpha/newsmips/g して :)
それに amiga の stride のところを cut & paste して適当に書き変えてゆく。

先は長い...

*	*	*

整理する。

ex)ESCC
	struct peripheral_8_32 {
		unsigned char dummy[3];
		volatile unsigned char reg;
	};

ex)SONIC ETHER
	struct peripheral_32_64 {
		unsigned int dummy;
		volatile unsigned int reg;
	};

ex)IDROM とか
	struct peripheral_4_32 {
		unsigned char		dummy[3];
		volatile unsigned char	dummy_reg:4,
					reg:4;
	};

とりあえずこんだけのタイプが access できるようにすればいいのかな。

ただ、32bit 中下 8bit しか使ってない port は、word
(X68k で育ったせいか、word と聞くと 16bit を思い浮かべてしまう。
この場合の word は 32bit のこと)でアクセスしてもちゃんと読めるんだよな。
31-8bit にゴミが付く場合があるけど。

実際 NEWS-OS の device driver はそうやってアクセスしてるし。
そっちの方が符号拡張しなくていい分速い気がする。
とするならば、

ex)ESCC
	struct peripheral_8_32 {
		volatile unsigned int reg;
	};

ex)SONIC ETHER
	struct peripheral_32_64 {
		unsigned int dummy;
		volatile unsigned int reg;
	};

ex)IDROM とか
	struct peripheral_4_32 {
		volatile unsigned int	dummy_bit:28,
					reg:4;
	};

こうしたほうが速い? あんまかわんないか。
asm で見てみる..

struct peripheral_8_32 {
	volatile unsigned char dummy[3];
	volatile unsigned char reg;
};

struct peripheral_32_32 {
	volatile unsigned int reg;
};

/*
 * 8bit access をして unsigned char で返す。
 * いたって普通。
 */
unsigned char
test8_uc(p)
struct peripheral_8_32 *p;
{
	p->reg = 1;
	return(p->reg);
}

/*
 * 8bit access をして unsigned int で返す。
 * 符号(zero)拡張が入るはず。
 */
unsigned int
test8_ui(p)
struct peripheral_8_32 *p;
{
	p->reg = 1;
	return(p->reg);
}

/*
 * 32bit access をして unsigned char で返す。
 * いちばん遅いと思う。
 */
unsigned char
test32_uc(p)
struct peripheral_32_32 *p;
{
	p->reg = 1;
	return(p->reg);
}

/*
 * 32bit access をして unsigned int で返す。
 * ゴミが残る場合あり。
 * いちばん速いと思う。
 */
unsigned int
test32_ui(p)
struct peripheral_32_32 *p;
{
	p->reg = 1;
	return(p->reg);
}

で、gcc にお伺いをたててみる。
mips-sony-netbsd-gcc -mrnames -S -O9 -fomit-frame-pointer rw_test.c
と...

test8_uc:
	li	$v0,1			# 0x1
	sb	$v0,3($a0)
	lbu	$v0,3($a0)
	j	$31
	nop

test8_ui:
	li	$v0,1			# 0x1
	sb	$v0,3($a0)
	lbu	$v0,3($a0)
	j	$31
	nop

test32_uc:
	li	$v0,1			# 0x1
	sw	$v0,0($a0)
	lw	$v0,0($a0)
	j	$31
	andi	$v0,$v0,0x00ff

test32_ui:
	li	$v0,1			# 0x1
	sw	$v0,0($a0)
	lw	$v0,0($a0)
	j	$31
	nop

lbu なんて命令があるのか。load byte すると同時にゼロ拡張。
となると結局スピードは変わんないか。

32bit で読んで自分で unsigned char を返さなきゃいけない
test32_uc() が一番遅い...気もするけど、
and 操作は遅延 slot に入るから変わらないような気もする。
うーむ。MIPS 強し... :-)

*	*	*

う〜ん、結局この三つでカバーできるのかなぁ?
そうすると stride を導入しなくてもいいような気もしてきた。
毎回 stride を評価しなきゃいけないのでオーバーヘッドでかいし。

せっかく bus_space_read_* を関数へのポインタにしたんだから、
その内部でそれぞれの bus 幅形式用のものにしてしまったほうが
スッキリするような気もする...ということは alpha/arm32/atari のまんまパクれば ok ?

もうちょっと考えよう。

1999-07-05 interrupt


mips/trap.c と、newsmips/newsmips_intr.c と、R4400 の pdf を読む。

MIPS の割り込みは、割り込んだ際に、CPU の CAUSE register
に割り込み原因が入っている。
TLB miss とか illegal instruction とかの CPU 的な割り込みは、
arch/mips/mips/ の下でうまくやってくれてるので(私は)考えなくてよい。

hardware 割り込みがかかった時のみ、arch/mips 以下のルーチン群が、
mips_hardware_intr に登録してあるハンドラを呼んでくれる。
ここに machine dependent な関数を登録する。
引数として cause register などなどが渡される。

hardware 割り込みがかかった際は、
CAUSE register の IM0〜IM7 のどれかが立っている。
これが上の bit から順に、level5 interrupt、level4 interrupt、ときて、
level0 interrupt、software1 interrupt、software0 interrupt となる。

つまり、いわゆる vector 割り込みじゃなくて、レベル割り込み。
デバイスはとうぜんこれらのレベルの数以上あるので、
いくつかのデバイスは同じレベルの割り込みを共有することになる、と。

...ということは、割り込みハンドラだけではどのデバイスの割り込みかわからないので、
どのデバイスの割り込みかを知るためには、
どっかの(CPU ではなく NEWS5000 の hardware が用意してくれている)
status port を見る必要がある。

ということをふまえつつ、いろいろ調べる。

NEWS5000 は

level0	APBUS
level1	APBUS
level2	TIMER
level4	SB,MB,FB,AB
level5	SB,MB,AB

となっている。

デバイス毎の割り込み status は、
0xBFA00020 から level0、level1、level2、... と並んでる。
割り込み level と、この status を見れば、どのデバイスの割り込みかが
特定できる、と。

*	*	*

忘れないうちにまとめよう。

例えば APBUS 上のデバイス (etherとしよう) から割り込みがかかる場合。

最初に MIPS 的に割り込みがかかり、arch/mips/ がうまいこと処理してくれて、
結果、hardware 割り込みなので、(*mips_hardware_intr)() が呼ばれて、
最終的に news5000_intr() が呼ばれる。

news5000_intr() で、cause register を見て、割り込み level を調べる。
(この場合 APbus 上の ether だから level0 とする)

cause Register を見ると level0 なので、apbus 上のどれかのデバイスである。

よって次はどのデバイスかを特定するために、
0xBFA00020 の interrupt status を見る。
bit がそれぞれの device に対応しているので、
立っている bit があればそのデバイスの割り込みである。

で、内蔵 ether の場合だと、0xBFA00020 の bit1 が立つことになっているので、
ここで ether driver の interrupt handler を呼ぶ、と。

...でいいのか?

*	*	*

こんなかんじで、とりあえず timer 割り込みを書いてみたが、
...確認できない。

割り込みルーチン内で LED をつけるようにすると、確かに点灯。
少くとも一回は呼ばれている様子。

が、つばいさんがやっていた(跡が newsmips_trap.c に残ってるけど)ように、
割り込み回数を count して LED を blink させると、ぜんぜん動かん。

いっそのこと...と思って serial に printf すると...
ぐぁ。
字をまき散らして死んだ :P

むーーーーーー。

*	*	*

落ち付いて考えよう。

ap0 at mainbus0
mkclock0 at ap0 slot0 addr bf881fe0

TIMERの初期化はここでやっている。
で、timer 割り込みルーチン内で LED を付けると付く。

その後

boot device: <unknown>
root device: _

となる。timer 割り込み内で count up して LED を blink させるようにしてるのに、
来ない。

そうだよな。あたりまえか。

root device: _

の時は、CPU はスパるsplhigh()でシリアルをpollingしてるので
割り込みは入らないか。
ふむ。

ためしに serial の polling んところで splhigh をとっぱらってみると...。

> bo -a
APbus Primary Boot Program
APbus Full Boot Program (0x83e00000-0x83e153df)
: scsi()/netbsd
text_start=0x80001000, data_start=0x800914d0, entry=0x80001000
.text:  address=0x80001000-0x800914cf, size=591056  
.rodata:        address=0x800914d0-0x8009c3bf, size=44784  
.reginfo:        address=0x8009c3c0-0x8009c3d7, size=24  
.data:  address=0x8009d3e0-0x800a23df, size=20480  
.sdata: address=0x800a23e0-0x800a241f, size=64  
.sbss:  address=0x800a2420-0x800a241f, size=0   
.bss:   address=0x800a2420-0x800bc08f, size=105584   
.mdebug:        address=0x800bc084-0x80102e83, size=290304  
Copyright (c) 1996, 1997, 1998, 1999
    The NetBSD Foundation, Inc.  All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
    The Regents of the University of California.  All rights reserved.

NetBSD 1.4 (MISAKI) #215: Mon Jul  5 04:35:23 JST 1999
    ryo@moveq:/src/news5000/sys/arch/newsmips/compile/MISAKI
real mem  = 66060288
avail mem = 56889344
using 1612 buffers containing 6602752 bytes of memory
SONY NET WORK STATION, Model NWS-5000, Machine ID #14894
mainbus0 (root)
cpu0 at mainbus0
cpu0: MIPS R4400 CPU Rev. 6.0 with MIPS R4010 FPC Rev. 0.0
cpu0: L1 cache: 16kb/32b Instruction, 16kb/16b Data, direct mapped
cpu0: L2 cache: 1024kb/64b mixed, no snooping
ap0 at mainbus0
mkclock0 at ap0 slot0 addr bf881fe0

boot device: <unknown>
root device: 

の polling キー入力待ちの状態で、LED が点滅。
じゃなくて点だ。
間違いないって。

なんだ、動いてるやん。だまされ。悩んで損した。

1999-07-02 clockattach


今週は休みなのでNEWS作業。
軽い所から攻める。
clock.c を分離分割。(つっても news3400 の方はそのまま...)
newsmips/clock.c は alpha や pmax のように clockfns の
ハンドラ見て該当ルーチンに飛ばす式にしてやる。

clock のドライバ本体は newsmips/apbus/mkclock.c に置いて、attach の中で
clockattach すればよいと。なるほど。

#もう一段階がんばって apbus → apclock → mkclock とやろうかと
#思ったけど萎えたので apbus attach → mkclock attach で済ます。

alpha が一番最初にこの方法をとったのかな。次に pmax ?
というか clockattach して clock 分離してるのってこの二つだけみたいだけど...
全部の arch でこの方式を使えばいいのに...(んで clock.c を arch の下に持たない)
それだと machine dependent な clock routine 書き下ろすのすげー楽になると思うんだけど。

*	*	*

あとは news3400 の clock.c も hb/ の下あたりに追いやって mkclock.c にして
clockattach させればいいんだけど...まぁ、これはとりあえずほっとくいつかそのうち。

最終的には同一 GENERIC kernel で news3400/news5000
両方が起動できるようにしなきゃだめだしなぁ。

現状だと #ifdef news5000 したら news5000 でしか動かない kernel しかできない。
いちおう念頭に置いてコード書いとかないときっとあとで苦労するな...

1999-06-28 DP8393X SONIC Driver


一枚仕上げたので、ふたたび news5000 作業に戻る。

割り込みはややこしそうなので置いとく。もうちょっと気力が充実している時にやろう。

で、sonic ether のドライバを書かなきゃなぁ、と思って、ふと
locate sonic とか locate if_sn とかしてみると...
なんだ。あんじゃん。

/src/NetBSD-1.4/sys/arch/mac68k/dev/if_sn.c
/src/NetBSD-1.4/sys/arch/mac68k/dev/if_snreg.h
/src/NetBSD-1.4/sys/arch/mac68k/dev/if_snvar.h
/src/NetBSD-1.4/sys/arch/mac68k/nubus/if_sn_nubus.c
/src/NetBSD-1.4/sys/arch/mac68k/obio/if_sn_obio.c
/src/NetBSD-1.4/sys/arch/pica/dev/if_sn.c
/src/NetBSD-1.4/sys/arch/pica/dev/if_sn.h

ほんとに sonic ether の sonic ? と思ってちゃんと中身を見てみる。

National Semiconductor  DP8393X SONIC Driver

ホンモノだ....
しかも同じものが違う実装で二つもあるよ。
嬉しくて泣けてくる...。

さらに mac68k のほうは obio と nubus の二つの bus から、
ちゃんと bus_space つかって一つの dev/if_sn.c を使ってくれている。
さらに泣けてくる...。

とゆーことは、newsmips/apbus/if_sn_ap.c を作って bus_space_map して、
あとは if_sn.c 内の関数を呼べばいい?


あ、でも DMA とか L2Cache とかのカラミがあるのか...それを考えると
同じ mips3 の pica のをもってくるほうが楽そうやね。
bus_space とか bus_dma 使って綺麗に作れ、って話もあるけど。

1999-06-27 TLB miss。ROM モニタのワークのmap


日曜は他の仕事をやろうと思ってたのに、TLB のところをいじってたらいつのまにか夜だった。ダメ。

pmap_enter でいけるかな〜、と試してみたんだけど、
0xfff00000 なんて変なアドレスはやっぱりダメのようだ。

結局 mips/mips/locore_mips3.S の tlb miss のところで、runtime に
0xfff????? = 0x03f????? な TLB を作ってやることにした。

R4000 の TLB まわりの資料が無いので全然わからん...。

TLB miss で panic: out of universe する個所でさらに
fault address をチェックして、0xfff00000 以上ならば
0xfff????? = 0x03f????? な TLB を作って復帰させてやる。

わからないまま見よう見まね(cut & paste とも言う)で作ったら
なんとなく動いちゃったよ。
しばらくはこれでいい。

で、無事、APbus の attach の所で、ROM モニタワークの dump に成功。
これでどんなデバイスがつながってるやら、hardware i/o address やらの情報が
取り出し放題だ。しかも apcall 使えばドライバ書かずにデバイス叩けるぞ。
やるかどうかはわかんないけど...

次は割り込みについて調べないと。
Ether をなんとかして動かさないとなにもできん...

#そろそろ backup とっとかないと、何かあった時泣きを見るな...

*	*	*

ってもう今日はやめようと思ったんだけど、他の仕事する気も無くなったので、
ROMモニタワークをもっと細かく dump (device の link chain をおっかける) してたら、
やっぱりうまくメモリが map できてないことが発覚。

隣のページを見にいっちゃってる?
0xfff????? の TLB を map したところだな。
TLBLO0/LO1 とか EVEN/ODD ってのがよくわかってないから、きっとこのへんなはずだ。

やっぱり R4000 の TLB の構造を理解しないまま書いてはいけなかったらしい。(そりゃそうだ)

R4000 の pdf はたしか MIPS (SGI) の site にあったはずなので、続きはそれを落としてプリントアウトしてからだな。

というわけで今日はもう掃除してメシくって原稿描いて寝ることにしよう。

*	*	*

AM1:33...

とかいいつつ、メシ食った後やっぱりいじってる。
R4000 の pdf 落として Adobe Acrobat Reader で見ながらもっかい書き修したら、ちゃんと動いちゃったよ。

何が悪かったかというと、つまり偶数ページのTLBエントリに対して、偶数と奇数のページを lo0 と lo1 に map しなければいけなかったのがうまくできてなかったようだ。
いや、なんとなくそうやったつもりだったんだけど、bit の意味とかわかってなかったのでそのせいね。きっと。

やはりマニュアルは偉大だ。

というわけで今度こそここまで。

次回は割り込み。
...までは行かないかな。
config_found とか config_search まわりがまだイマイチよくわかってないので手間取るかも。

1999-06-27 apbus probe。TLB miss


ぐつぐつと apbus の attach をさせるべく書く。
なんか、pmax って異様に整ってるなぁ....というわけで、
bus まわりはこっちを見本にして加えてゆく。

あとは clock を綺麗に分離しなきゃなぁ。newsmips は clock.c で直接
I/O 叩いてるし...。これも pmax を参考にして、そのうちやろう。


てなわけで ap0 at mainbus0 のメッセージを拝む。
次は apbus についてる device。
ROM モニタの管理してる sysinfo 構造体から APBus についてる device がわかるから、
それを元に config_found していきゃいいのね。きっと。

で、ふにふにと link を辿って、とりあえず config_found せずに
device 構造体を print するようにして、様子見。make。実行。

がー。

ap0 at mainbus0
panic: TLB out of universe: ksp was 0x800bcd18
8008b1d4+54 (800bb000,0,0,0) ra 8001b928 sz 24
8001b8ac+7c (100,38,0,0) ra 8000280c sz 32
800027f0+1c (100,38,0,0) ra 0 sz -4096
User-level: pid 0
halted.

やはりこれは 0xFFF00000 問題か。

#ってなにげに初 panic だったりする。:)
#printf がちゃんと動くってなんて幸せなことなんだろう...


ROM モニタが設定してくれる APBUS のデバイス情報は
0xFFF????? にあって、0xFFF????? は
先日にも書いた通り、メモリの高位 1M に
TLB で map されているのだが、とうぜん NetBSD 的にはこんな MAP しておらず、
TLB miss でそのまま死ぬ、と。

これは mips/mips/pmap* をいじらなきゃダメってことですか?

0xfff00000 = 0x03f00000 (メモリ64Mな場合) な page table entry をちゃんと作るか、
NetBSD 的には、実装メモリサイズ - 1M分に見せてやって、
TLB routine をいじって runtime に生成してやるかのどちらかだな。

後者の方が楽?
前者の方が綺麗?

もしくは、kernel を load した直後に、ROM が管理している 0xfff00000 〜
にある情報を全て取り込んでしまって、あとはもう二度とROMワークは参照しない、
という手もあるかな。負けた気分だけど。
でもその場合、ちゃんと halt して ROM モニタに戻れるかどうかが謎だ。


とりあえず今日はここまで。
他の仕事やんないと...

1999-06-26 printf と egcs。egcs の mips-sony-netbsd patch


昨日の

real mem  = 008
avail mem = 004

とかの、printf の %d の表示が腐ってるのを調べることにする。
ためしに mach_init() の最初のほう (consinit() はし終わってる) で、

printf("%d\n",12345678);

とかやっても、

008

と表示される。豪謎。

printf の varargs がらみかな、とか思って、kern/subr_prf.c の %d で拾ってるところで
自前 itoa して puts。ちゃんと拾えてる...違うのか。

さらに追う。

case DEC:
	/* many numbers are 1 digit */
	while (_uquad >= 10) {
		*--cp = to_char(_uquad % 10);
		_uquad /= 10;
	}
	*--cp = to_char(_uquad);
	break;

ここか? 10進変換部分。前後に自前 puts を仕込むと....
なんか 0x01f00000 を 10 で割った結果が 0 になってるんですけど...
gcc のバグですか? それとも僕の make ミスですか?
quad_t だし、なんかそんなかんじだよなぁ...

「七度デバッグして人を疑え」ってのは祝一平の言葉だっけか...。

しかし二回デバッグしただけで gcc を疑うことにする :P
だって最近の gcc/egcs って信頼でき(以下略)

って、気づいたら今使ってた mips-sony-netbsd-gcc は 2.7.2.2 だった(古すぎ)。
一年前に作ったまんまだったのか...。せっかくなので egcs にしよう。
#さくさく binutils と egcs を make する。時間かかりまくり。う〜。

*	*	*

できあがった egcs で試す。今度はコンパイルエラーが...なぜぇ?

/usr/local/mips-sony-netbsd/include を 1.4 に合わせてなかったみたいだ。
うぐぅ
rsync -av /usr/src/include /usr/local/mips-sony-netbsd/
rsync -av /usr/src/sys/sys /usr/local/mips-sony-netbsd/include/
rsync -av /usr/src/sys/arch/mips/include/ /usr/local/mips-sony-netbsd/include/mips
rsync -av /usr/src/sys/arch/newsmips/include/ /usr/local/mips-sony-netbsd/include/machine

う、まだ LEAF() のマクロがラベルに "_" を付けやがる...
なぜか __NO_LEADING_UNDERSCORES__ が pre-define されてないぞ。なぜだ...うぅぅ。
gcc/config/mips/netbsd.h にはあるのに...

再度 make。

*	*	*

それでも undefined symbol bzero ... って、なぜ?
gcc -E で見ても systm.h で define bzero memset してるのに...と思ったら、
gcc が bzero なコードを吐いてる...。うがー。

gcc/config/mips.h に #define TARGET_MEM_FUNCTIONS を付け加える。

再度 make。

*	*	*

はぅ。やっと link できた...平和が戻る。

*	*	*

って案の定 printf も修った...。
が、こんどは他の個所の動作が変だ...
どうやら gcc が endian little らしい?

もー gcc を make するの嫌だよ、っつっても -EB だけじゃ変わらず。
うー。また make しなおしか...

*	*	*

やっと修った。printf も動く。その他もちゃんと動く。
はぁ〜。

丸24時間つぶれたよ。くそー。他にもやんなきゃいけないことたくさんあるんだけどなぁ...

七度デバッグしてコンパイラを疑おう。



おまけ。egcs-19990623のmips-sony-netbsd化patch

1999-06-24 console 出る。copyright メッセージ


うおおおおおおおおおおおおおおおおおおおおおおおおおおお〜〜〜

> bo -a
APbus Primary Boot Program
APbus Full Boot Program (0x83e00000-0x83e153df)
: scsi(0,0)/netbsd
text_start=0x80001000, data_start=0x80091db0, entry=0x80001000
.text:  address=0x80001000-0x80091daf, size=593328  
.rodata:        address=0x80091db0-0x8009c94f, size=43936  
.reginfo                :       address=0x8009c950-0x8009c967, size=24  
.data:  address=0x8009d970-0x800a295f, size=20464  
.sdata: address=0x800a2960-0x800a299f, size=64  
.sbss:  address=0x800a29a0-0x800a299f, size=0   
.bss:   address=0x800a29a0-0x800bc60f, size=105584   
.mdebug:        address=0x800bc604-0x80102593, size=286608  
0xbe950000
x_maxmem = 03f00000
seg set
kernend = 800bd000
bzero done
uvm_setpagesize done
mips vector init done
mips_init_proc0 done
readidrom done
pmap_bootstrap...
pmap_bootstrap_done
Copyright (c) 1996, 1997, 1998, 1999
    The NetBSD Foundation, Inc.  All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
    The Regents of the University of California.  All rights reserved.

NetBSD 1.4 (MISAKI) #59: Thu Jun 24 14:14:14 JST 1999
    ryo@moveq:/src/news5000/sys/arch/newsmips/compile/MISAKI
real mem  = 008
avail mem = 004
using 002 buffers containing 002 bytes of memory
mainbus0 (root)
cpu0 at mainbus0: cpu0: MIPS R4400 CPU Rev. 0.0 with MIPS R4010 FPC Rev. 0.0
cpu0: L1 cache: 006kb/002b Instruction, 006kb/006b Data, direct mapped
cpu0: L2 cache: unknown size/004b mixed, no snooping
boot device: <unknown>
root device:  
root device:  
use one of: halt
root device: 
use one of: halt
root device: 
use one of: halt
root device: 
use one of: halt
root device: 
use one of: halt
root device: aaaa
use one of: halt
root device: halt
syncing disks... done
halted.

** Syscall **
cause=0x00000020, status=0x00400002, badvaddr=0xc0000088, epc=0xa0001b20
Begin trace back...
            pc=0xa0001b20, sp=0x800bed70
called from pc=0xa008cce8, sp=0x800bed70
called from pc=0xa008ce58, sp=0x800bed88
called from pc=0xa0014228, sp=0x800beda0
called from pc=0xa00140e4, sp=0x800bede0
called from pc=0xa00138b8, sp=0x800bee10
called from pc=0xa008c078, sp=0x800beef0
called from pc=0xa0007864, sp=0x800bef10
called from pc=0xa0001084, sp=0x800bef50
> 

なんか思いのほか進んだぞ。ちゃんと halt までしてる。
locore_machdep.s が news3400 のままなので変な syscall で ROM モニタに落ちてるけど...

** Syscall ** ってのは NEWS5000 の ROM モニタが出してるメッセージだな。
うわわわ〜〜ん。でもここまで動いたよ。うれしー。

ってよく見ると avail mem とかむちゃくちゃな値やな

1999-06-24 serial 出る


わーい。文字が出た。:D

まだ console とかいうレベルじゃなくて、
SCC の I/O port 直叩きで文字が出せただけなんだけど。

一文字出力ができたから、あとは consinit を作って kernel から
呼ばれるようにちゃんと仕組めばおっけーだ。

あぁ、あと少しで copyright メッセージが拝める? :)

1999-06-24 mach_init() のパラメタ


とか思ったら pmax/pmax/machdep.c の mach_init() は 6 つもパラメタ
受けてるぞ。謎。

/*
 * Initialize stack and call machine startup.
 */
	la	$3,start
	slt	$2,$3,sp
	bne	$2,$0,1f
	addu	$2,$3,-CALLFRAME_SIZ
	subu	$2,$3,sp
	slt	$2,$2,4096			# within 4kB of _start
	beq	$2,$0,2f
	addu	$2,$3,-CALLFRAME_SIZ
1:
	move	sp,$2
2:

遅延スロットに入る命令を考慮しつつ人間語に翻訳すると

if (start < sp) {
	sp = start - CALLFRAME_SIZ;
} else {
	tmp = start - sp;
	if (tmp < 4096)
		sp = start - CALLFRAME_SIZ;
}

か? ちなみに #define CALLFRAME_SIZ (4 * (4 + 2))。

start は 0x80001000 なので、つまり kernel が走ると同時に stack ptr は
0x80001000 - CALLFRAME_SIZ に設定される。

stack が kernel text 内にある場合は、kernel が使う memory 領域とかぶるので
やめさせる。当然 0x80000000 以下の場合もやめさせる。
唯一 0x80000000 〜 0x80001000 以内にあった場合にのみ、そのまま使う、と。

なんかよくわからんが...やっぱり news5000 の場合は kernel に渡された
sp はどっかいっちゃってるよなぁ...。pmax は bootloader が kernel を load
する時に、sp を 0x80000000〜0x80001000 の中に設定するんだなぁ。たぶん。
で、sp が壊されずに mach_init() までくるために引数が拾える、と。

さて、news5000 ではどうしよう?

#define	KERNEL_ARG_NUM	5
#define	KERNEL_ARG_SIZE	sizeof(int)*KERNEL_ARG_NUM

とかやって、mips/locore.S のあたまで、

#ifdef KERNEL_ARG_SIZE
	bcopy(sp,start-CALLFRAME_SIZ-KERNEL_ARG_SIZE,KERNEL_ARG_SIZE);
#endif

みたいにすればそこそこ綺麗?
機会があった時にでも曽のつく偉い人に質問しよう...

1999-06-23 x_maxmem


mips の locore.S は、start() に渡された引数 4 つ
(a0,a1,a2,a3 レジスタ)
をそのまま保持して、mach_init() に渡す。

ので、mach_init(a,b,c,d) として受ければ、それは bootstrap が kernel に
渡した引数がそのまま 4 つ取りだせるのだが、この引数は news3400 と news5000 では
違ってた。

news3400 の場合は、

mach_init(x_boothowto,x_bootdev,x_bootname,x_maxmem)

なのだが、

news5000 の場合は、

mach_init(x_boothowto,x_bootdev,x_argv,x_argc)

となる(ようだ)。

となると NEWS5000 の ROM モニタで見える sysinfo 構造体へのポインタは
どうやって知るのか、っつーと、実は NEWS5000 の ROM モニタは kernel に
5 つの引数を渡していて、

start(x_boothowto,x_bootdev,x_argv,x_argc,sysinfo)

と5つ目に pointer が入っていた。
( 16(sp) から拾ってるから mips の場合これは 5th 引数)

が、mips/locore.S で有難くも余計なお世話的にスタックを自前で
設定しれくれているので、ROM モニタが kernel に渡した引数は
メモリの彼方へ。

う〜ん。
しょうがないので mips/mips/locore.S の start: の最初で
伝家の宝刀 #ifdef news5000 を持ちだして変数に格納しておくことにする。
汚いどいいよね。とりあえずだし。
これで、

sip = 0x9ff03270;

と非常にキモチワルイことをしなくてもよくなった。:)
で、mach_init() の中で sysinfo 構造体から maxmem を拾って x_maxmem に set する。
(ただし ROM モニタ用に一応 1M とっておく)

9ff03270: 00000002 9fc1f900 000003ee a0001000 ................
9ff03280: a0300000 ffff8e80 ffffbfc0 00000000 .0..............
9ff03290: 00000001 00000000 04000000 00004000 ..............@.
9ff032a0: 03ff0db8 bf881000 ffffb2c0 ffffbff8 ................
9ff032b0: ffff9680 00000000 fffefe01 9fc26190 ..............a.
9ff032c0: fffdfc01 9fc26190 fffbf801 9fc26190 ......a.......a.
9ff032d0: fff7f001 9fc26190 ffefe001 9fc26190 ......a.......a.
9ff032e0: ffdfc001 9fc26190 ffbf8001 9fc26190 ......a.......a.
9ff032f0: ff7f0001 9fc26190 9fc261d4 0300ca00 ......a...a.....
9ff03300: 00000050 00000000 00000000 00000000 ...P............
9ff03310: 536f6e79 00000000 00000000 00000000 Sony............
9ff03320: 00000000 00000000 00000000 00000000 ................
9ff03330: 00000000 00000000 00000000 00000000 ................
9ff03340: 00000000 00000000 00000000 00000000 ................
9ff03350: 00000000 00000000 00000000 00000000 ................

maxmem は +40 の 0x04000000 というやつ(だろう)。
この情報は /usr/include/apbus/sysinfo.h と
/usr/include/apbus/news/sysinfo.h に書いてるし、楽勝。

で、x_maxmem をちゃんと設定してやっただけで pmap_bootstrap で
止まらなくなった。ほんと? main まで来ちゃってんの?

恐る恐る kern/init_main.c の main() の中に kitt() をつっこむ。
あ、ほんとにここまで来てるよ...がーん(←喜べよ)

というわけで、なにがなんでも次は serial に文字を出そうと心に決める。

1999-06-23 serial


「consinit() は kern/init_main.c の main() の中で出てくるのに、
それ以前に panic() とか printf() した場合どうやって文字が出てんの?」
と聞いたら、
「consinit() は二回以上呼ばれてもおっけーなように作って、
machdep.c の中とかで呼べばいい」と msaitoh 師匠がおっしゃられた。
あっそ。そゆこと。

というわけでシリアル周りをしらべる。

console に文字を出すのは、APBUS SYSTEM MONITOR ROM
routine を使うとすごく簡単(/usr/include/apbus/ap*.h 参照)である、
とうことは先日書いた通りなのだが、まぁ、NEWS5000 の serial (esccf) も、
文字出すだけならたぶんタイミングとって port にキャラクタ書くだけ
だろうから、sccfputc とか作っても簡単なはずだ。(きっと)

ということで後者でゆく。なんとなく I/O 叩きたい年頃だし。

いやしかし、apcall できる仕組をつくっとくのも重要なのだな。
なんてったってドライバ書かずに ether しゃべれるし、:-)
よく見ると、すげーおいしそうな ioctl

#define 	APIOC_SYS	(APIOC_CIO+200)
#define 		APSIOCGNLEDS	(APIOC_SYS+0)
#define 		APSIOCLEDON	(APIOC_SYS+1)
#define 		APSIOCLEDOFF	(APIOC_SYS+2)
#define 		APSIOCGLEDSTAT	(APIOC_SYS+3)
#define 		APSIOCSHUTDOWN	(APIOC_SYS+4)
#define 		APSIOCEXIT	(APIOC_SYS+5)
#define 			APEXIT_REBOOT	0x00000000
#define 			APEXIT_HALT	0x00000008
#define 			APEXIT_POWOFF	0x00000080

がたくさんあるし...

それにはメモリの最後 1M を残しとかなきゃいけないのか...?

1999-06-22 memory map


メモリマップ整理。
MIPS 的なメモリは、sys/arch/mips/include/cpureg.h にもあるけど、

/*
 * Address space.
 * 32-bit mips CPUS partition their 32-bit address space into four segments:
 *
 * kuseg   0x00000000 - 0x7fffffff  User virtual mem,  mapped
 * kseg0   0x80000000 - 0x9fffffff  Physical memory, cached, unmapped
 * kseg1   0xa0000000 - 0xbfffffff  Physical memory, uncached, unmapped
 * kseg2   0xc0000000 - 0xffffffff  kernel-virtual,  mapped
 *
 * mips1 physical memory is limited to 512Mbytes, which is
 * doubly mapped in kseg0 (cached) and kseg1 (uncached.)
 * Caching of mapped addresses is controlled by bits in the TLB entry.
 */

である。つまり、64Mメモリが実装されてたとすれば、

0x80000000 〜 0x83FFFFFF
0xA0000000 〜 0xA3FFFFFF

は、cache enable/disable が違うだけで、同じものを指す。
(ただし片方に書いてからもう片方の同じ場所を読むには cache flush しなきゃいけない)



0x00000000 〜 0x03FFFFFF
0xC0000000 〜 0xC3FFFFFF

この二つは TLB に map された的な値なアドレス???
つまり大概 TLB miss が発生する?
(ほんと?)

で、NEWS5000 は、

0xB8000000 〜 0xBFFFFFFF	APBUS。I/O なので no-cache 領域
0xFFF00000 〜 0xFFFFFFFF	ROM の work ? (1Mbyte)

となっている。
で、特に ROM のワークである

0xFFF00000 〜 0xFFFFFFFF	は、
0x03F00000 〜 0x03FFFFFF	と同一のものらしい。

つまり、0xFFF00000 〜 に限っては PA = VA ではないと。

ROM用ワークはメモリのおしり 1M を TLB で 0xFFF00000 に map しているようだ。

って、ひみつの ROM モニタコマンド 'mp' (TLBを見るコマンド)で見ると、
やっぱりそうみたいだ。

適当な個所をメモリダンプして、mp して TLB を見ることを
繰り返すと、メモリダンプした領域用の TLB がガシガシ作られているのがわかる。

ってことは ROM が上がってる時点で既に TLB 使ってるんやなぁ...

> mp  
 0|80000...:ASID=00|000000...:???:---|000000...:???:---|PGSIZE=4K
 1|80000...:ASID=00|000000...:???:---|000000...:???:---|PGSIZE=4K
 2|80000...:ASID=00|000000...:???:---|000000...:???:---|PGSIZE=4K
 3|80000...:ASID=00|000000...:???:---|000000...:???:---|PGSIZE=4K
 4|80000...:ASID=00|000000...:???:---|000000...:???:---|PGSIZE=4K
 5|80000...:ASID=00|000000...:???:---|000000...:???:---|PGSIZE=4K
 6|80000...:ASID=00|000000...:???:---|000000...:???:---|PGSIZE=4K
 7|80000...:ASID=00|000000...:???:---|000000...:???:---|PGSIZE=4K
 8|fff00...:ASID=00|103f00...:NC :DVG|103f01...:NC :DVG|PGSIZE=4K
 9|03ffc...:ASID=00|003ffc...:UC :DVG|003ffd...:UC :DVG|PGSIZE=4K
10|00010...:ASID=00|000010...:UC :DVG|000011...:UC :DVG|PGSIZE=4K
11|0000c...:ASID=00|00000c...:UC :DVG|00000d...:UC :DVG|PGSIZE=4K
12|00110...:ASID=00|000110...:UC :DVG|000111...:UC :DVG|PGSIZE=4K
13|03ff6...:ASID=00|003ff6...:UC :DVG|003ff7...:UC :DVG|PGSIZE=4K
14|03fe4...:ASID=00|003fe4...:UC :DVG|003fe5...:UC :DVG|PGSIZE=4K
15|fff0e...:ASID=00|103f0e...:NC :DVG|103f0f...:NC :DVG|PGSIZE=4K
16|fff10...:ASID=00|103f10...:NC :DVG|103f11...:NC :DVG|PGSIZE=4K
17|03fe8...:ASID=00|003fe8...:UC :DVG|003fe9...:UC :DVG|PGSIZE=4K
18|03ffa...:ASID=00|003ffa...:UC :DVG|003ffb...:UC :DVG|PGSIZE=4K
19|ffff4...:ASID=00|103ff4...:NC :DVG|103ff5...:NC :DVG|PGSIZE=4K
20|00006...:ASID=00|000006...:UC :DVG|000007...:UC :DVG|PGSIZE=4K
21|0000a...:ASID=00|00000a...:UC :DVG|00000b...:UC :DVG|PGSIZE=4K
22|fff1c...:ASID=00|103f1c...:NC :DVG|103f1d...:NC :DVG|PGSIZE=4K
23|03ff4...:ASID=00|003ff4...:UC :DVG|003ff5...:UC :DVG|PGSIZE=4K
24|00012...:ASID=00|000012...:UC :DVG|000013...:UC :DVG|PGSIZE=4K
25|03ffe...:ASID=00|003ffe...:UC :DVG|003fff...:UC :DVG|PGSIZE=4K
26|fff24...:ASID=00|103f24...:NC :DVG|103f25...:NC :DVG|PGSIZE=4K
27|03fee...:ASID=00|003fee...:UC :DVG|003fef...:UC :DVG|PGSIZE=4K
28|fff28...:ASID=00|103f28...:NC :DVG|103f29...:NC :DVG|PGSIZE=4K
29|ffff2...:ASID=00|103ff2...:NC :DVG|103ff3...:NC :DVG|PGSIZE=4K
30|ffff6...:ASID=00|103ff6...:NC :DVG|103ff7...:NC :DVG|PGSIZE=4K
31|00008...:ASID=00|000008...:UC :DVG|000009...:UC :DVG|PGSIZE=4K
32|fff30...:ASID=00|103f30...:NC :DVG|103f31...:NC :DVG|PGSIZE=4K
33|03ff2...:ASID=00|003ff2...:UC :DVG|003ff3...:UC :DVG|PGSIZE=4K
34|03fe0...:ASID=00|003fe0...:UC :DVG|003fe1...:UC :DVG|PGSIZE=4K
35|00002...:ASID=00|000002...:UC :DVG|000003...:UC :DVG|PGSIZE=4K
36|c0010...:ASID=00|100010...:NC :DVG|100011...:NC :DVG|PGSIZE=4K
37|03fec...:ASID=00|003fec...:UC :DVG|003fed...:UC :DVG|PGSIZE=4K
38|00000...:ASID=00|000000...:UC :DVG|000001...:UC :DVG|PGSIZE=4K
39|ffff8...:ASID=00|103ff8...:NC :DVG|103ff9...:NC :DVG|PGSIZE=4K
40|fff40...:ASID=00|103f40...:NC :DVG|103f41...:NC :DVG|PGSIZE=4K
41|03ff8...:ASID=00|003ff8...:UC :DVG|003ff9...:UC :DVG|PGSIZE=4K
42|ffffa...:ASID=00|103ffa...:NC :DVG|103ffb...:NC :DVG|PGSIZE=4K
43|fff46...:ASID=00|103f46...:NC :DVG|103f47...:NC :DVG|PGSIZE=4K
44|03fe6...:ASID=00|003fe6...:UC :DVG|003fe7...:UC :DVG|PGSIZE=4K
45|fff4a...:ASID=00|103f4a...:NC :DVG|103f4b...:NC :DVG|PGSIZE=4K
46|fff4c...:ASID=00|103f4c...:NC :DVG|103f4d...:NC :DVG|PGSIZE=4K
47|03fea...:ASID=00|003fea...:UC :DVG|003feb...:UC :DVG|PGSIZE=4K

つまり TLB miss の時は VA = PA ってやるような処理が走っているのかな。
きっとそうに違いない。

1999-06-22 mach_init() を追う


ちまちまとどこまで動いてるかを調べる。
こないだ作った LED でナイトライダーをやるルーチン(←気にいってるらしい)void kitt()を
いろんなところにつっこんで boot。

...え、まじ? mach_init() にある、pmap_bootstrap() の手前まできてんの? ホントに?
pmap_bootstrap(); の後に kitt() をつけても...反応なし。

ということは pmap_bootstrap() の中で死んでる。

pmap_bootstrap ってあやしいことしてるんやったっけか...メモリ確保してって
pmap_steal_memory とかでミスってんのかな。
vm_physmem とかがちゃんと設定されてないのか...?
(って設定した覚えもないのであたりまえといえばあたりまえな気もする)

ま〜 printf もとい LED debug すればどこまで来てるかわかるので
なんとかなるだろう....ということで眠いので次回につづく。

#consinit する前に panic() を呼ぶ個所ってのがいくつも存在するんだけど、
#これはいったいどうやって出力させるんだろう...

1999-06-18 make。boot。LED 点灯


というわけで、いろいろやる。
とりあえず newsmips をベースにして、

-DMIPS3 -Dnews5000

で kernel を作れるようにした。
でもって、一度 NEWS-OS 4.2.1 を立ち上げて、
filesystem の / に netbsd として copy しといて、halt して、ROM モニタから、

> bo -a
APbus Primary Boot Program
APbus Full Boot Program (0x83e00000-0x83e153df)
: scsi(0,0)/netbsd
text_start=0x80001000, data_start=0x8008eb30, entry=0x80001000
.text:  address=0x80001000-0x8008eb2f, size=580400  
.rodata:        address=0x8008eb30-0x8009956f, size=43584  
.reginfo        p       p:      address=0x80099570-0x80099587, size=24  
.data:  address=0x8009a590-0x8009f45f, size=20176  
.sdata: address=0x8009f460-0x8009f49f, size=64  
.sbss:  address=0x8009f4a0-0x8009f49f, size=0   
.bss:   address=0x8009f4a0-0x800b90ef, size=105552   
.mdebug:        address=0x800b90e4-0x800fd35b, size=279160  

というわけで、load してくれそうなことは確認。
(実はこれは一年前に確認済みである)

NEWS5000 の LED port の位置はわかったので、machdep.c の mach_init() の中で
LEDナイトライダーをさせる code をつっこんで、boot してみる...

...動いたよ〜(ちょっと感激

arch/mips/mips/locore.S → arch/newsmips/newsmips/machdep.c
とちゃんと来てるね。おっけーおっけー。
次はシリアルだな。
apbus の probe もめんどくさいな...。
とりあえず apbus.h もでっちあげ中。

と、今日はここまで。

1999-06-17 boot ?


ROMモニタで ss -m で見える値

> ss -m
Memory use:
 diag info:  bf881800
   environ:  bf881000
    apinfo:  bf880000
   sysinfo:  9ff03270
alloc list:  ffffbff8
   max mem:  04000000
  free mem:  03ff0db8
  mem base: 100000000

の、sysinfo (0x9ff03270) が、NEWS-OS の /usr/include/apbus/sysinfo.h に定義されてる構造体

/*
 * System's information block.
 * Starts at SYSINFO_BASE.
 */
struct apf_sysinfo {
/*  0*/ long32			si_revision;	/* APbus firmware revision	*/
/*  4*/ long32			(*si_apcall)(); /* APcall entry point		*/
/*  8*/ ulong32 		si_errno;	/* general error code register	*/
/* 12*/ addr32			si_loadbase;	/* base of program load area	*/
/* 16*/ addr32			si_loadlimit;	/* limit of program load area	*/
/* 20*/ struct apf_device	*si_devlist;	/* device structure list	*/
/* 24*/ struct apf_bus		*si_buslist;	/* APbus structure list 	*/
/* 28*/ ulong32 		si_exerrno; 	/* extended error code register */
	:

だということがわかった。
で、(*si_apcall)() が ROM のサービスルーチンへのポインタで、こいつを
/usr/include/apbus/apcall.h に定義されてる通り、

apcall.h:#define	_apcall 		(*APS_APCENT)
apcall.h:#define	_exit(a)		(*APS_APCENT)(APC_EXIT,(a))
apcall.h:#define	_read(a,b,c)		(*APS_APCENT)(APC_READ,(a),(b),(c))
apcall.h:#define	_write(a,b,c)		(*APS_APCENT)(APC_WRITE,(a),(b),(c))
apcall.h:#define	_open(a,b)		(*APS_APCENT)(APC_OPEN,(a),(b))
apcall.h:#define	_close(a)		(*APS_APCENT)(APC_CLOSE,(a))
apcall.h:#define	_lseek(a,b,c)		(*APS_APCENT)(APC_LSEEK,(a),(b),(c))
			:

sysinfo.h:#define	APS_APCENT		(_sip->si_apcall)

みたいに呼べばいいだけのようだ。
kernel から bios の routing を呼べるようにしとけば、何も考えずにおっけー?

やった。
かんぺき。

#define	SYSINFO_BASE	0x9ff03270

とやっちゃっていいのかな...? よくないよな。
なにかでわかるはずだけど...(ごそごそ

vmunix を見ると、どうやら boot が kernel に register で渡してるようだ...。

/vmunix
〜
80001a04 <start>:
80001a04:	24020023	li	$v0,35
80001a08:	40828000	mtc0	$v0,$16
80001a0c:	3c023000	lui	$v0,0x3000
〜〜
80001a44:	0080d821	move	$k1,$a0 	← argv[0]
80001a48:	00a0b821	move	$s7,$a1		← argv[1]
80001a4c:	3c04a000	lui	$a0,0xa000
80001a50:	8fba0010	lw	$k0,16($sp)	← argv[4]
80001a54:	00c0b021	move	$s6,$a2		← argv[2]
80001a58:	00e0a821	move	$s5,$a3		← argv[3]
80001a5c:	24851000	addiu	$a1,$a0,4096
〜〜
80001b5c:	3c088015	lui	$t0,0x8015
80001b60:	2508065c	addiu	$t0,$t0,1628
80001b64:	3c01a000	lui	$at,0xa000
80001b68:	01014025	or	$t0,$t0,$at	← t0 = x0x80150000+1628 = 0x8015065c = _sip
80001b6c:	0c02f5c9	jal	800bd724 <config_cache>
80001b70:	ad1a0000	sw	$k0,0($t0)	← k0 を _sip に格納

どうしよう。#ifdef news5000 で locore.s の最初でどっか変数に格納するか。
でも arch/mips/mips/ の下に ifdef news5000 を入れるのも汚いなぁ。むぅ。


EOF