CPU<---Cache<---Memory<---Device
DeviceからMemoryにDMAでデータを転送して、そのデータをCPUで読む場合、以下のどちらの操作が必要か。
1. DeviceからMemoryへの転送前に、cacheのinvalidate(cacheの内容を捨てる)をする。
3. DeviceからMemoryへの転送後に、cacheのinvalidateをする。
答えは、
「1が正しく、3だと正しくデータが読めない事がある」
3.だとダメな理由は以下の通り。
--------
例として、DMA転送先のアドレスを0xa0000000とする。
3.は、以下のように細分化できる。
3-1 0xa0000000の内容(古い内容)が、既にcache上にある。
3-2 DeviceからMemoryの0xa0000000へDMA転送を開始する。
3-3 DMAの完了を待つ。
3-4 0xa0000000の古い内容がcacheにあるので、それをinvalidateする。
3-5 0xa0000000の新しい内容をMemoryから読む。
問題は、3-3の間に0xa0000000の古い内容がcacheから追い出されてしまい、新しい0xa0000000の内容を古い内容で上書きしてしまう可能性がある事。
3-3の間に、他のスレッドが頻繁にメモリアクセスを行うなどすると、0xa0000000の古い内容がcacheから追い出されやすい。
2 件のコメント:
うへ、READ_BEFORE_READ相当のことくらいしか考えてなかった、ふだんbus_dmaにおまかせしてるのがあかんなー。
# 大ハズレ
ただ、write-backなキャッシュかどうかのフラグは大概あるから、なんとなく正常に動いたりするんだろうな...
# 読み込みメインだと書き戻しフラグがなくて、cacheから追い出されても書き戻すアクションが必要なくてしない実装とか
bus_dmaは、実は以前マニュアル(man bus_dma)を読んだ時に理解できなくて、全然わかっていません。
せっかくTsuyoshiさんが話題にしてくれたので、この機に読んでみます。
そんなわけで、
「bus_dmaのフラグがarchに実装を期待する機能のドキュメント」
「write-backなキャッシュかどうかのフラグ」
は、どのあたりのソースやドキュメントを読むと良いのか教えていただけると嬉しいです。
コメントを投稿