L.Entisの日記: ARMユーザーモードでCPUキャッシュフラッシュ方法 4
日記 by
L.Entis
ARMユーザーモードでCPUキャッシュをフラッシュする方法をご存知の方はいないでしょうか?
一般的な方法、或いは Android 上で実現する方法です。
具体的にはJITコンパイラで出力したバイナリを実行する前にCPUキャッシュをフラッシュしたいわけです。(ARMの場合、(データ)キャッシュをフラッシュしないと命令キャッシュに正しいバイナリが入ってこない)
もちろん、特権モードならキャッシュ制御の方法はあるのは知っているのですが、ユーザーモードでです。
Android(Linux)でcacheflush関数があるようで試してみたのですが、こいつは機能していないようです。
あと、ファイルマップトメモリでフラッシュ操作を行ってDMA転送を発生させればカーネル側でキャッシュのフラッシュ操作を行うはずなので試してみたのですが、私の環境ではDMA転送が発生しないのか、或いはデバイスがIO転送なのか、理由は分かりませんがキャッシュはフラッシュされないようでした。
結局現状では、キャッシュサイズ以上のメモリの転送を数回行うことでキャッシュからメモリへの追い出しを行っています。(まあこの方法では厳密にはキャッシュフラッシュの確証はないのですが…)
一般的な方法、或いは Android 上で実現する方法です。
具体的にはJITコンパイラで出力したバイナリを実行する前にCPUキャッシュをフラッシュしたいわけです。(ARMの場合、(データ)キャッシュをフラッシュしないと命令キャッシュに正しいバイナリが入ってこない)
もちろん、特権モードならキャッシュ制御の方法はあるのは知っているのですが、ユーザーモードでです。
Android(Linux)でcacheflush関数があるようで試してみたのですが、こいつは機能していないようです。
あと、ファイルマップトメモリでフラッシュ操作を行ってDMA転送を発生させればカーネル側でキャッシュのフラッシュ操作を行うはずなので試してみたのですが、私の環境ではDMA転送が発生しないのか、或いはデバイスがIO転送なのか、理由は分かりませんがキャッシュはフラッシュされないようでした。
結局現状では、キャッシュサイズ以上のメモリの転送を数回行うことでキャッシュからメモリへの追い出しを行っています。(まあこの方法では厳密にはキャッシュフラッシュの確証はないのですが…)
GCC拡張の __clear_cache() 関数 (スコア:0)
GCC拡張の __clear_cache() 関数は試しました?
環境にも依りますが、PROT_EXEC なメモリ領域なら キャッシュをクリアできる、という記述が google で検索すると見つかるような?
cacheflush()でいいはずです (スコア:0)
機能していないように見えるということで思い当たる点としては、man cacheflush で出てくるのはMIPS向けの記述で、ARMに対しては間違っているということ。
具体的には、manだと第3引数にICACHE,DCACHE,BCACHEのいずれかを指定するように見えますが、ARMの場合この引数は0でなければいけません。
ちなみに、キャッシュ制御用のmcr命令のうち、キャッシュフラッシュ等の一部のオペレーションはユーザモードでも実行可能なので、ポータビリティ無視でよければアセンブラで直接キャッシュフラッシュのコードを書くことはできます。
Re:cacheflush()でいいはずです (スコア:1)
情報ありがとうございました。
Re: (スコア:0)
もう解決したようですが、cacheflush()を使ってるのはAndroidの古いバージョンで、最新のdalvikVMだとgcc拡張の__builtin__clear_cache()を使ったCPUアーキテクチャに依存しないコードに書き換わってるようですね(dvmCompilerCacheFlush()を参照 [googlesource.com])。
こちらを使った場合も、ARMの場合はlibgcc.a内のcacheflush syscallを呼び出す関数を呼ぶので、処理内容としては同じになります。