Lions' 本ぼっち読み (22)

前回、call を読んでて力尽きている模様。とりあえず 0783 以降について確認してみます。

前モードがカーネルモードの場合

PS と $30000 と論理積を取ったら 0 になります。OS の前モードは 00 がカーネルで 11 がユーザとなっているためで、

0783    bit     $30000,PS
0784    beq     2f

なナニ的にはカーネルモードだった場合、0873 の結果はゼロであり、PS の Z フラグが立ち、次の beq 命令で Z フラグが立ってるので 1f に jmp する、という事になります。
ので、前モードがカーネルモードだった場合には

0797 1:
0798    bis     $30000,PS
0799    jsr     pc,*(r0)+
0800    cmp     (sp)+,(sp)+

が実行されて共通の後始末な 0801 以降を実行していく模様。上記については

  • 0798 で前モードがユーザモードであるように PS を修正
  • 0799 で r0 に格納されている割り込みハンドラ (ここでは clock) に jmp
  • 0800 で 戻ってきたら 0780 および 0781 でスタックに積まれたものを取り除く

という事になってるようです。

前モードがユーザモードだった場合

0783 な命令が 0 以外になる場合、0785 以降の命令が実行されていく模様。とりあえず 0784 で r0 に格納されている割り込みハンドラ (ここでは clock) を実行します。

0785   jsr     pc,*(r0)+

で、それ以降は runrun の値を見て swtch を呼び出すループになってます。

0786 2:
0787   bis     $340,PS
0788   tstb    _runrun
0789   beq     2f
0790   bic     $340,PS
0791   jsr     pc,_swtch
0792   br      2b
0793 2:

runrun の値がゼロなら 0793 に jmp してます。あ、その前に 0787 で PS な優先度を最高にして割り込みが入らないようにしてます。なので runrun がゼロだったら割り込み優先度が最高のまま割り込み元に戻るんかな。
あ、Lions' 本に以下な記述がありますね。

その結果カレントプロセスが実行を続けてよいのならば、割り込みからのリターン命令の前にレジスタを元に戻すので、そのプロセスが割り込みを受けないことが重要である。
Lions' Commentary on UNIX より引用


おそらくは rtt で PC と PS が復帰されるのでそれまでは割り込みが入らない形、ということは理解できたんですが、swtch 手続き呼び出し中は割り込み OK ってことなのかな。そりゃそうか。swtch から戻ってきて runrun が 0 なら割り込み禁止で rtt になることは分かります。
とは言え、0780 および 0781 でスタックに積まれるソレは前モードがユーザモードの場合に有効とありますが、現時点でその詳細は不明です。
0793 以降ですが、以下 (一部略)。

0793 2:
0794   tst     (sp)+
0795   mtpi    sp
0796   br      2f
(ry
0801 2:
0802   mov     (sp)+,r1
0803   tst     (sp)+
0804   mov     (sp)+,r0
0805   rtt

0794 および 0795 は 0780 および 0781 の後始末なのだろうなと。また、0801 以降は前モードがカーネルモードの場合もここを実行します。
最後の 0804 は割り込みハンドラな jsr 呼び出し時に push される r0 になるはず。
とは言え、0780 および 0781 の命令の意図は別途確認したい。あとはなんとなくベースで理解できているのかどうか。

このままトラップも見てみます

0756 以降の命令を手繰った後に call と同じことをしているようです。
あと、call の 0781 でも云々してたナニですが、なるべく素早く PS を保存するのは割り込みやトラップの種別を特定する必要がある上に、PS レジスタの下らへんは命令のステイタスで随時変わるので、ということなのですね。
とりあえず 344p のカーネルスタックの項は今の状態では難解に過ぎるので別途、ということにてエントリ投入。