SL-C3000はここが出発点

atty2004-12-03


うぉ、もうこんなページが作ってある。(Linuxザウルス開発メモ/独自ビルドカーネル/SL-C3000) SL-C3000用のupdater.shも公開されてたんですね。気づかなかった。

iWMMXtについての調査

まず、最新のLinuxカーネルで既にiWMMXtがサポートされていないか調べたところ、2.6.9で入っていました。そのコードはこちら(http://source.scl.ameslab.gov:14690/linux-2.5/patch@1.1320.1485.2)。

このコードから新たに分かったことは、

という点です。このパッチでは、ELFファイル(実行ファイル)に記録されているEF_ARM_SOFT_FLOATフラグを見て、CP1をiWMMXtとFPAのどちらに割り当てる*1かを決めています。soft-floatなELFがロードされたプロセスではFPA命令を使えず、hard-floatなELFのプロセスではiWMMXt命令が使えないというように、排他的なものであることが分かりました。

このことから、以前に書いたCP0/CP1を有効にした状態でhard-floatバイナリを実行するとillegal instructionで落ちる件は、以下のように説明できます。

Cの浮動小数演算からはFPA11命令が生成されます。しかし、XScaleには浮動小数演算ユニットが無いので、そのバイナリを実行するとXScaleコアが未定義命令割り込みを発生させます。CP1が無効になっている場合は、カーネルの割り込みハンドラに制御が移り、そのまま浮動小数演算エミュレータに制御が渡されFPA11命令をエミュレーション処理します。CP1が有効になっている場合は、まずiWMMXtコプロセッサに制御が渡りますが、FPA11命令なのでiWMMXtコプロセッサには処理出来ません。そこで未定義命令割り込みが発生し、カーネルの割り込みハンドラに制御が移りますが、浮動小数演算エミュレータが実行されることなくSIGILLシグナルを発生させるようです。(ここのところはよく分かりませんでした。ARMコアとコプロセッサで割り込みの発生のさせかたが違うのでしょうか)

  • CP1 disabled : FPA11 instruction -> XScale core -> Undefined instruction interrupt -> Linux kernel -> FP emulator -> Normal return
  • CP1 enabled : FPA11 instruction -> XScale core -> iWMMXt coprocesser -> Undefined instruction interrupt -> Linux kernel -> Abnormal return

この流れからすると、カーネルの割り込みハンドラから強制的に浮動小数演算エミュレータへ飛ぶようすれば良さそうに思えますが、例えそうしたところで根本的な解決にはなりません。CP1を有効にしていると、コード作成者の意図と違ってFPA11命令がiWMMXtコプロセッサに処理されてしまったり、逆にCP0が無効になっているとiWMMXt命令がFPA11命令として浮動小数演算エミュレータに処理されてしまう可能性があるからです。FPA11とiWMMXtのどちらもそれなりの命令セットを備えていますから、命令フォーマットが被っていないとは考えにくいです(正確に調べたわけではありませんが)。

結局のところ、iWMMXtを使うにはsoft-floatが必須である、という結論に達しました。どうりでどれだけ調べてもhard-float + iWMMXtを使っている事例が見つからなかったわけです。

あと、純正カーネルではコンテクストスイッチの際にiWMMXtレジスタが保存/復元されないのを確認しました。まぁ上記の結果からすると納得のできることです。また、ユーザランドがhard-floatで構成されたままの状態でiWMMXtレジスタを保存/復元するようにするのは無理だと思います。よってiWMMXtを使うプロセスを複数動かすことは出来ませんが、実際の使用状況を考えるとそれほど問題では無さそうです。

……と、なんとなくですます調で書いてみた。

*1:というのは正しくない表現ですが