2024-09-14

UNIX V6カーネルのlow.sを読む

UNIX V6カーネルを学ぶため、日本語版の『Lions' Commentary on UNIX』を参照し、DECが発行していた各種資料などを参考にしつつ、ロジックを追いかけていこうと思います。カーネルは、システムコールを受け付けたり、メモリやディスクなどのリソースを管理したり、割り込みを処理したり、様々な役割を担います。しかしそれはカーネルが起動し定常状態に達してからの話であって、マシンが起動しカーネルが読み込まれたブートストラップ処理とは違う世界の話です。カーネルを学ぶために、どの切り口から挑んでいくかは人それぞれかと思いますが、私はブートストラップ処理から始めようと考えています。そうであれば、まず最初に見ていくのはlow.sです。

 

Lions本でlow.sは、0500-0599行目に相当します。日本語版では66-67ページにあります。

  1. 0502-0505行では、br4からbr7という識別子に値を割り当てています。PDP-11に親しんでいれば疑問に思うことも無いのかもしれませんが、私はbr4やbr7というのが何なのか分かりませんでした。DECの資料を読んでいくと、brというのは「Bus Request」のことで、PSWのプロセッサ優先度ビットを定義していることが判明しました。
  2. 0507行では、アセンブルされた結果が格納されるアドレスを指定しています。同様の記述が0520行や0529行などにもあります。この記述はPDP-11アセンブラの記述方法なのか、UNIXアセンブラ独時の記法なのかわかりませんが、とても特徴的です。Lions本では266ページで開設されています。ともかく0507行は「. = 0^.」となっていますから、000000番地を指定していることになります。
  3. 0508行では、「br 1f」とあり、0522行目にある「1」というラベルに飛びます。これはそれだけのことだと思いますが、0509行には「4」という数字が突然表れます。これは何なのか、何故「4」なのか、これは誰かが参照しているのか、まったくわかりません。次の0512-0518行目には「トラップベクタ」が並んでおり、これらはアドレス毎に役割が決まっていますから、それとアドレスがずれないようにするための埋め草なのかもしれません。そうならば「4」などという意味の分からない数字ではなく「0」でも良いような気がしますし、または「. = 4^.」を入れても構わないような気がします。
  4. 0512-0518行では、上述したとおり「トラップベクタ」が並んでいます。これらはPDP-11によって構造が定義されており、最初のワードが呼び出すルーチンのアドレスで、次のワードがPSWに格納される値です。それはよいとしても、全て「trap」というルーチンを呼び出すことになっているのは何故かという疑問は残ります。さらに謎なのが、「br7+0.」のように、0505行で定義された「br7」に数字を加えていることです。表記上の注意事項としては、数字にピリオドが付加されており、これはLions本の265ページに書かれているように10進数と解釈されるための工夫です。わざわざ10進数としなくても、8進数で記述しても良かった気もしますが、それはどちらでも構いません。疑問なのは、何故「br7」に数値を加えているのかです。これはPDP-11によってPSWに格納されるワードなので、加算された値はNZVCフラグに何かが入ることになります。それを「trap」ルーチン側で参照しているのかというと、そうでもなさそうです。参照していないような気がしますが、これはm40.sにあるルーチンなので、そこで再度考えてみようと思います。ちなみに「br7」に数値を加算しているのは、0538行とか0547-0549行にもあります。しかも「br7+7.」というのが、0538行と0547行にあり、重複してもよいのだろうかという疑問もあります。
  5. 0522行では、「jmp start」があります。ここは40番地になっており、PDP-11としては「System Software」が利用する領域という扱いになっています。0番地では「br 1f」として40番地に飛び、40番地では「jmp start」として更にstartに飛ぶので、何故こんなに手間をかけるのだろうかとは思いますが、何か歴史的な事情とか、PDP-11の都合とかがあるのかもしれません。
  6. 0523行では、「jmp dump」という命令が置かれています。ここにはラベルも与えられていませんが、どのようにして呼び出されることになっているのでしょうか。おいおいわかってくることを期待しています。
  7. 0525-0544行では、デバイス事の割り込みベクタが定義されています。そもそもlow.sはmkconfによって生成されるものなので、現実のUNIX V6においては利用されるデバイスに相当する割り込みベクタが出現するはずです。Lions本では説明の都合上必要なデバイスだけが現れます。そこではbr4-br7の何れかが記述されていますが、それらはデバイスのデフォルト値として、それぞれのマニュアルに記述されています。マニュアルによって記述箇所は一定していませんが「Address and Priority Assignments」という箇所に書かれていることが多いようです。
  8. 0558-0577行では、0525-0544行の割り込みベクタで指定されているルーチンが定義されています。基本的な構造は同一で、0558行のklinであれば「jsr r0,call; _klrint」となっています。ここに現れる「call」はm40.sにあるので、あとで詳細に見ていくつもりです。ただし現時点で不思議なのは、なぜ「jsr」命令をつかっているんだろうということです。ここには「jsr」命令が並んでいますが、「Jump Sub Routine」という名前から想像されるところでは、サブルーチンから戻ってくるのだろうかと思うところですが、多分片道切符で、戻ってこないのでしょう。それならば「jmp」命令のほうが自然ではないかと思うのです。

 

low.sを見てきて、いろいろと疑問が生まれ、それらが全て解決したわけではありません。疑問が残ったままですが、カーネルのブートストラップ処理を追いかけるため、次は「start」処理を見ていこうと思います。

0 件のコメント:

コメントを投稿