livaの雑記帳

livaの雑記帳

OSとか作ってみたい

uio_pci_genericでデバドラを書く<その3>

その2はこちら。

 

今回は厳密にはuio_pci_genericの話ではないのだけども、uioでデバドラを書く上で必須となるであろうお話。

 

当たり前だけど、DMAができないと多くのデバドラは書けない。

DMAするためには良さげなページと物理アドレスが欲しいですよね。

じゃあどうやってページとその物理アドレスを手に入れるか、というわけなのだけど。

 

結論から書くと、hugepageをallocateして、/proc/self/pagemapを舐める。簡単。

 

まずなんでhugepageを使うかというと、普通にmallocした場合、allocateしたページがカーネルによって勝手にスワップされて消えちゃうかもしれないじゃないですか。

hugepageだとそんな事がないらしい。

 

Huge pages cannot be swapped out under memory pressure.

https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt

 

hugepageをallocateしたい時は、事前に(デバドラプログラムを実行する前に)以下のようにしてhugepageを予約しておく。

echo 20 > /proc/sys/vm/nr_hugepages

 

その上で、デバドラ内で以下のような感じでmmapを呼ぶと2MB huge pageが割当たった仮想アドレスが戻り値として帰ってくる。

mmap(NULL, 2 * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_HUGETLB | MAP_ANONYMOUS | MAP_POPULATE, 0, 0);

 

次に/proc/self/pagemapというのを舐めて、仮想アドレスから物理アドレスに変換する。mmapで受け取った値をそのまま食わせれば良い。

stackoverflow.com

 

ほぼこのコードをコピペしたら動く。なんか一箇所コンパイルエラーが出たような気がしないでもないが、自明すぎて忘れてしまった。

 

おしまい。