2011年07月19日

ARM LinuxでのVFP(FPU)レジスタの退避、復帰

LinuxではVFP(FPU)のレジスタの退避、復帰は遅延的に行われます。

ARMのLinuxのソース上のどこでそれが行われているかを調べました。



ARMの浮動小数点ユニットはARM11ではVFPと呼ばれています。(Vector Floating Point). しかしこのVector機能は変則的でコンパイラにもサポートされていません。NEON登場後はVector演算はそちらをつかうようになってきています。Cortex-A9では浮動小数点ユニットでのVector機能は削除され、名前もFPUに改められました。

しかし、ARM LinuxのソースコードではVFP/FPU関連のソースコードは共通にvfpの名称が使われています。この記事でもVFPと呼称します。

VFPの初期化

arch/arm/vfp/vfpmodule.c: vfp_init

VFPの有無と種類を確認します。

VFPのレジスタはdouble(8バイト)が16個ですが、NEON搭載のVFPv3では32個あります。

VFPの例外ハンドラの設定、thread切り替え時のフックを設定。

thread切り替え時

arch/arm/vfp/vfpmodule.c: vfp_notifer

SMPでない場合はVFPのENビットを落とすだけで、この時点ではVFPのレジスタの保存は行いません。

SMPの場合で、そのスレッドですでにVFPを使用していた場合には、VFPのレジスタを保存します。

VFP例外処理

arch/arm/vfp/vfphw.S: vfp_support_entry

VFP関連の例外の入り口は全てここです。VFPのENビットが落ちている状態で、VFPのレジスタを使用する命令を実行したときも例外が発生してここに来ます。

まず、VFPのENビットを調べてこれが立っていなかった場合には、VFPのレジスタを以前VFPを使っていたスレッドの領域に保存します。(SMPの場合はすでに保存済みなのでスキップ。) その後に現在のスレッドのVFPの状態をVFPレジスタにロードします。この時点でVFPのENビットは立てられています。

次にそれ以外のVFP例外の処理を行います。

実際にVFPレジスタのセーブ、ロードを行う場所

マクロで定義されています。

arch/arm/include/asm/vfpmacros.h

VFPFSTMIA 全てのVFPレジスタのセーブ

VFPFLDMIA 全てのVFPレジスタのロード

VFPFLDMIAが使われているのは1箇所だけ。vfphw.Sのvfp_support_entry

VFPFSTMIAは2箇所。vfphw.Sのvfp_support_entryとvfp_save_state

vfp_save_stateはvfpmodule.cの中の3箇所で使われている。vfp_notifer, vfp_pm_suspend, vfp_sync_hwstate

SMPの場合の違う箇所

SMPでない場合にはCPUはひとつだけなので、VFPのレジスタも一組だけです。そのためVFPのレジスタの内容はメモリに退避していなくてもいつでもアクセス可能です。

SMPの場合にはCPUが複数あり、VFPはそれぞれのCPUについています。アクセス可能なのは自分のCPUのVFPレジスタだけです。SMPではスレッドが一度スリープした後に以前とは異なるCPUで実行を再開することがあります。このときにこのスレッドのVFPのレジスタの内容が以前のCPUのVFPレジスタに置いたままだと、それを持ってくるのがやっかいです。そのためにSMPではスレッド切り替えのたびにVFPレジスタをメモリ上に保存しているのだと思います。



トラックバックURL

コメントする

名前
URL
 
  絵文字
 
 
記事検索
最新コメント
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード