aarch64では、ページテーブルエントリによってページ単位でメモリ領域に属性をつけることができます。普通のメモリ領域とデバイスメモリ領域(MMIO領域など)にそれぞれNormalとDeviceという属性を付けるのが一般的です。
Deviceとマークされたメモリ領域はキャッシュされず、投機的なアクセスも禁止されます。そして、この領域はXN bitで実行不可能とマークすることが推奨されています*1。
さらに、Deviceではもっと詳細に属性を以下の4種類のうちから指定する必要があります。
- GRE
- nGRE
- nGnRE
- nGnRnE
GREは、それぞれ以下の意味を持ちます。
- G(Gathering)
write combiningを許可する。つまり、複数の同一領域への読み込み/書き込みを内部で単一の読み込み/書き込みにまとめて一回で処理する。詳細は以下を参照。
- R(Re-ordering)
メモリアクセスの順序変更を許可する。Normalメモリへのアクセス時と同じRe-orderingが発生し得る。
- E(Early Write Acknowledgement)
posted writeを許可する。つまり、CPUがデバイスメモリ領域にwriteをしたときにデバイスからの到達応答を待たずにwriteアクセスを完了させる。
全てを許可したい場合はGREを指定し、Eだけを許可したい場合はnGnREを指定する必要があります。
使用方法
結局どのデバイス領域にどの属性を付ければええねん、というのはLinuxのioremap
を基準に考えると分かりやすいです。
https://dri.freedesktop.org/docs/drm/driver-api/device-io.html#architecture-exampleから引用、一部改変:
API | Memory region type and cacheability |
---|---|
ioremap_np() |
Device-nGnRnE |
ioremap() |
Device-nGnRE |
ioremap_wc() |
Normal-Non Cacheable |
ioremap_cache() |
Normal-Write-Back Cacheable |
ioremap_wc()
はDevice-GREと同義な気がしますが(実際にそういうパッチも出ている)、Normal Non Cacheableとして実装されています。
GREはメモリアクセスの順序があまり気にならないFrameBuffer領域によく使用されているみたいです。
結論
何も考えずにnGnRnEを指定するのはあまりよろしくない
*1:DDI0487H B2.1.2 Memory type overview 参照