Lions' 本読み (94)

今日の昼、人がやたらに多い某スーパーのベンチにてアセンブラのトラップルーチンあたりを再確認。Lions' 本読み (93) なソレとカブりますが、もう少しきちんと纏めておきたいと思います。

きっかけは psig 手続き

シグナルハンドラを実行する準備をする 4052 以降の記述が課題になってました。特に、で言うと以下の部分です。

4055            n = u.u_ar0[R6] - 4;
4056            grow(n);
4057            suword(n+2, u.u_ar0[RPS]);
4058            suword(n, u.u_ar0[R7]);
4059            u.u_ar0[R6] = n;
4060            u.u_ar0[RPS] =& ~TBIT;
4061            u.u_ar0[R7] = p;
4062            return;

命令の意図を以下に順に列挙してみます。

  • 4055 でユーザモードスタック (u.u_ar0[R6] に格納) の新たな値を n に代入
  • 4056 でユーザモードスタックの領域を 2word 拡張
  • 4057 で拡張されたユーザモードスタックに_古い PS_を格納 (push)
  • 4058 で拡張されたユーザモードスタックに_古い PC_を格納 (push)
  • 4059 で_前モードに対する古い SP_に n (拡張されたユーザーモードスタックを指すべき SP の値) を代入
  • 4060 シグナルハンドラ実行のための PS の設定
  • 4061 シグナルハンドラ実行のための PC の設定

ここで、4059 で u.u_ar0[R6] に新しい SP なナニを設定しても無駄だろう、と思っていた訳です。敗因の一つとして前モードがカーネルモードの場合の処理を見ていた、という事があります。

800    cmp    (sp)+, (sp)+

ここで u.u_ar0[R6] をステてるんですが、シグナルハンドラを云々する場合は前モードがユーザモードというのが前提なのか。
で、上の処理はシグナルハンドラから脱出する時に rtt な命令と同様に PC と PS をスタックから pop して設定する、という仕様 (?) を発見したおかげで腑に落ちていたんですが、

SP がステられる、という固定観念 (?) のおかげでスタックポインタをどうやって設定しているのか分からない、という落とし穴にハマッておりました。

v6 呑み会 #2

にて @mgwsuzuki さんセッションでこのあたり (トラップでレジスタをスタックに保存して云々) の解説がありました。その時にスタックポインタが mfpi および mtpi で操作されている旨の発信があり、その時は「違うんじゃないスか」的な反応をしてしまった (どうも 0797 以降の手続きを実行する的脅迫観念がアレだったようです) のですが、今日再度確認したところ (あるいは v6 呑み会の次の日の #台風そん で確認したところ)、

  • 0785 から 0796 までの一連の処理は前モードがユーザモードの場合に実行される
  • sp は mfpi で保存され mtpi で復帰されている
    • これ 342p の mfpi の説明によれば、_スタック上に以前のアドレス空間に対するスタックポインタをコピーする (これは前モードがユーザーモードであった場合にだけ重要である)。(Lions' Commentary on UNIX より引用)_ というもので、mfpi でユーザモードのスタックポインタの値を現在の (カーネルモードの) スタックに push する、ということになります。
    • 逆に mtpi sp は現在のスタックから pop した値を前モードのスタックポインタに設定する、ということになるのか
    • これ、トラップ経由なナニはユーザモードスタックを操作し放題ですね

ということが分かった次第ッス。

沖縄の v6 unix な取り組み

やはり読んだソレを出力することは大事だなあ、と思うと同時にピアレビュ頂くことはとてもありがたいです。そういった意味ではお互いに理解をレビュし合う仕組みが必要だなぁ、とかあるいはもっと沢山で同じ取り組みを、という思いもあったりしてます。
10 月にアンカンファレンスを、って思っているのですが、v6 関連で何か発信できたら良いな、と思っていたり。