OS自作入門12日目

問題のタイマのお話。ちょっと、QEMUの内部まで見てみようと思う。
PCには、PIT(Programmable Interval Timer)とRTC(Real Time Clock)というタイマに関するものが2つあって、それぞれirq 0とirq 8につながれている。
RTCには、日時の情報とかがあるみたいです。
Hariboteのクロックを実際の時間と比べると、少し遅い。1分で4秒くらい遅くなります。なぜ?
PITを1msで割り込みを発生しようと、count=1193=0x04a9を入れてみると、タイマは少し速くなりますけど、1.6倍くらいにしかなりません。QEMUのタイマには限界があるのかな。
WinXPホストのクロックを起動したりすると、hariboteのクロックが一瞬停止したりするのが見れる。Kqemu/Qvm86を使ったときにフリーズしてしまうのはこんなのが関係しているのだろうか。
WinNTは、RTCを見て時計の較正をしているそうです。Win2k/XPも同じなんだろうか。どんな較正なのかわからないですけどね。
Windows上のQEMUではtimeSetEventというマルチメディアタイマを使っていますけど、1msを刻むことはどうやってやっているのでしょう。
なんか、疑問ばかり。

Accelerated-KNOPPIX

試してみた。
ずいぶん速くなっています。素のKnoppixでは、QEMUで起動する気にならないくらい遅かったのですが、こんな感じでした。
QEMU-0.8.0/kqemu-0.7.2
qemu -L ./pc-bios -cdrom accel.img -m 256
で起動。
knoppix desktop=icewm のとき、1min 45sec
knoppix desktop=twm のとき、 1min 40sec
knoppix desktop=kde のとき、 2min 50sec
KDEでは、遅いなと思うけど、icewmなら何とかという感じ。-m 256 がないとスワップしてつらいと思います。
キーを押し続けてもリピートがうまくいかないみたいですけど。
ちなみに、Morphixは、1minで立ち上がるのでまだまだですけどね。

OS自作入門7日目&8日目

FIFOは、読み書きの位置のほかに長さの情報を持っているというのがポイントになるかな。
もし、位置を変えることと、長さを変えることの間で割り込みが入ると、長さが0でも読み書きの位置が違うという変なことになるけど、そのへん割り込みの禁止をうまく使っているなと思った。
OSの起動のところは、3日目に調べたのでそれでいいかな。

OS自作入門5日目&6日目

この開発環境って、関数名を間違えるとWarningがでるだけで、エラーにならない。バイナリができてしまうので、走らせて見ると、突然OSが暴走し始めてなかなかバグが見つからないということがあった。
Makefileの一般規則で書いた場合、生成された中間ファイル.nasとか.gasが削除されるみたいです。こういうものなんでしょうか。
割り込みが動き出すと、システムが動いてるっていう気がする。割り込みの動作をイメージするのは難しいと思う。以前、デバッガを動かしていたときにステップ実行で次の行に行こうとすると、突然見知らぬコードが実行されてなかなか次の行に行けなかったことがあります。後で気づいたら、タイマの割り込みハンドラが実行されていたのでした。それで、割り込みってこういうものなんだと納得したことがあります。

シリアルの名前つきパイプとファイル出力

シリアルのパッチとバイナリを作りました。
http://www.h6.dion.ne.jp/~kazuw/qemu-win/qemu-20060320-serial.zip
http://www.h7.dion.ne.jp/~qemu-win/download/qemu-20060320-serial-3.patch
サポートすオプションは、
-serial pipe:com_1
-serial file:test.txt
です。pipe:とfile:は小文字を使ってください。-serialオプションは、1つだけサポートします。-serial pipe:オプションで、windbgと接続できます。
詳しくはこちらに書くつもり。
http://www.h7.dion.ne.jp/~qemu-win/DebuggingTips-ja.html#windbg
書いた。

OS自作入門4日目

読んだ。
用意されている開発環境は、CygwinやMinGW/MSYSのmakeではうまく動かないようです。
SET PATH=
としてPATHを消すと用意されたものが動くようです。
MinGW/MSYSのrxvtで動かすときは、Makefileを
COPY = cp
DEL = rm -f
としてやるといいです。haribote.sysを作るときは、copy /Bの代わりにcatが使えます。
cat asmhead.bin bootpack.hrb >haribote.sys
コマンドの前に-をつけると、エラーがあっても続けるという意味になるんですね。
-$(DEL)とか。
ポインタが説明されていますけど、自分の場合はgdbで変数の実際の値を何度も確認することで理解したように思います。
ただ説明を聞いただけでは、なかなか実感することは難しいと思うので、値を書き出したりgdbで確認したりするといいのではないかと思いますけどね。

OS自作入門3日目

読んだ。
この辺でつまずく人が多い気がする。bimとかhrbとか出てきて気になった。せっかく起動から追っかけてきたのにというのもあって、少し調べてみることにしました。
bimとhrbは、情報を見つけました。
omake/tolsrc/bim2hrb.cの引用。
******************************
[ .bimファイルの構造 ]
+ 0 : .textサイズ
+ 4 : ファイル中の.textスタートアドレス(0x24)
+ 8 : メモリロード時の.textスタートアドレス(0x24)
+12 : .dataサイズ
+16 : ファイル中の.dataスタートアドレス
+20 : メモリロード時の.dataスタートアドレス
+24 : エントリポイント
+28 : bss領域のバイト数
+36 : コード
[ .hrbファイルの構造 ]
+ 0 : stack+.data+heap の大きさ(4KBの倍数)
+ 4 : シグネチャ "Hari"
+ 8 : mmarea の大きさ(4KBの倍数)
+12 : スタック初期値&.data転送先
+16 : .dataのサイズ
+20 : .dataの初期値列がファイルのどこにあるか
+24 : 0xe9000000
+28 : エントリアドレス-0x20
+32 : heap領域(malloc領域)開始アドレス
*******************************
.bimファイルも、.hrbファイルも、上のような構造のヘッダーを持ったファイルになっています。WCOFFという形式は、調べてみたけどわからなかった。普通のCOFFと同じなのか。
Haribote.sysは、asmhead.binとbootpack.hrbを単純にくっつけたものになっているので、
asmhead.bin本体
bootpack.hrbのヘッダー
bootpack.hrbの本体
の三層構造になっています。これが、起動のときに重要な役割をします。
パソコンの電源を投入後、フロッピーが読み込まれて、IPLが実行され、asmhead.binに制御が移るところまではこれまで説明されているのでわかると思います。
その後、asmhead.nasでは、bootpack以下をBOTPAK(0x280000)に転送しています。bootpack:というラベルはasmhead.nasの最後にありますが、上に書いたようにasmhead.binの後ろにはbootpack.hrbがあるので、bootpack.hrbを0x280000に転送していることになります。また、最後にbootpackの起動のところで
JMP DWORD 2*8:0x0000001b
として2番目のデスクリプタの0x1bにジャンプすることで処理が終わっています。2番目のデスクリプタというのは、コピーされたbootpack.hrbがあるところなので、bootpack.hrbの0x1bに飛ぶことになるけど、0x1bというのが謎だった。
bootpack.hrbのヘッダーを見るとちょうど+24の0xe9000000の最後のバイトを指している。バイナリエディタで調べてみると、こんな風になっている。
+24: 0x00 0x00 0x00 0xe9 (0xe9000000)
+32: 0x09 0x00 0x00 0x00 (エントリーアドレス)
ここで、bootpack.hrbの0x1b番目(27番目)から並べてみると、エントリーアドレスはリトルエンディアンなので並べかえて、
0xe9 0x00000009
となって、これを逆アセンブルすると、
JMP _HariStartup
になります。つまり、0xe9というデータを実行可能なコードとみたてて、_HariStartupにジャンプするようになっていました。この_HariStartupというのは、obj2bimで、bootpack.bimにリンクされるライブラリの中にあります。ソースコードはomake/tolsrc/hrblib0a/startup.cにあって、内部でCのソースコードのHariMainを呼んでいます。そこでやっと、bootpack.cのHariMainが実行されます。
HariMainの起動までを要約すると、こんな感じです。
BIOSが、フロッピーのシリンダー0、ヘッド0、セクタ1の512バイト(IPL)を、0x7c00に読み込みます。
[ipl10.nas]
フロッピーのシリンダー10まで、0x8200を先頭に読み込み。Haribote.sysが読み込まれます。
Haribote.sysの先頭asmhead.bin(0xc200)にジャンプ。
[asmhead.nas]
Haribote.sys内のbootpack.hrbを0x280000を先頭にコピー。
コピーしたbootpack.hrbのヘッダー(0x280000 + 0x1b)にジャンプ。
[bootpack.hrbのヘッダー]
bootpack.hrb本体のHariStartupにジャンプ。
[startup.c]
HariMainを呼び出す。
[bootpack.c]
HariMain()を実行します。
フロッピーの内容を1度、メモリーにロードした後、コピーして実行しているところが複雑になっているのかな。

非同期のWriteFile

非同期のWriteFileで、普通のファイルに書こうとするとファイルポインタが動かなくて、ファイルの先頭から毎度書き込もうとします。最初、1文字しか書かれなくてよくわからなかった。書こうとする位置を自分で管理しないといけないらしい。OVERLAPPED構造体のoffsetに書こうとする位置をセットするのだそうです。

名前つきパイプ

日本語キーボードと、シリアルのパッチをホームページに載せておきました。
名前つきパイプでwindbgと接続する方法を試してみた。
名前つきパイプのサンプルはMSのサイトにある。
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ipc/base/interprocess_communications.asp
非同期の通信でやることにした。
CreateNamedPipeでパイプを作り、ConnectNamedPipeでクライアントからの接続を待ち、あとはReadFile/WriteFileするだけみたい。クライアントはwindbgになるけど。
パイプのタイプにBYTEとMESSAGEがあるけど、BYTEのほうでいいみたいだ。
作ってみるとすごい遅いんです。Win2kが立ち上がるのに8分ぐらいかかります。VMwareでwindbgを使ったリモートデバッグでもこんなもんなんですかね。実機でもすごく遅いみたいなんですけど、どれくらい遅いのかやったことがないのでわからない。
ときどきCPUが100%になってマウスのカーソルが動かないことも起きるし。
バッファのサイズとか変えてみたけど変化ないみたい。
仕方ないかなと思いますが、少し残念です。使えるようになっただけでOKとするかな。

仮想化やクラウドについて