ioeventfd & irqfd
2.6.32でマージされた*1KVMの新機能ioeventfdとirqfdについて調べてみました。
eventfd
どちらもeventfd(2)を利用しているので、まずはその概略から。
eventfdは2.6.22から利用可能なユーザプロセス間もしくはユーザ・カーネル間のイベント通知専用のシステムコールです。eventfdはeventfdオブジェクトと呼ばれるディスクリプタを返します。利用者はこのディスクリプタに対してread/write/select/pollなどをすることでイベントの通知や受け取りを行ないます。この種のディスクリプタを介したイベント通知はpipeやsocketでも可能ですが、特化している分eventfdの方が簡潔に書けて軽量です。
同種のシステムコールにsignalfdやtimerfdなどがあり、各種ディスクリプタとまとめてselect/pollすることができて便利です。
共通
ioeventfd
ioeventfdゲストのPIO/MMIOによる書き込みをeventfdの通知に変換してくれる機能です。
qemuはPIO/MMIO領域(アドレスとサイズ)とeventfdオブジェクトを引数にioeventfd(ioctl)を呼び出します。KVMは指定領域と同オブジェクトを自身のI/Oバスに登録(__kvm_io_bus_register_dev)し、そのコールバックにioeventfd独自のものを登録します。そのコールバックはeventfdオブジェクトにイベントを通知する(eventfd_signalを呼ぶ)だけです。これでPIO/MMIO書き込みがあればeventfdオブジェクトで待っているプロセスやカーネルの他のモジュールを起こすことができます。
vhost-netを例に挙げるならば、ゲストのvirtio_netのMMIO書き込みでホストカーネル側のvhost-netモジュールにパケット送信命令を発行することができるようになるでしょう。
irqfd
irqfdはゲストへの割り込み挿入を非同期に、またカーネルからも行なえるようにする機能です。
qemuはGSI*4とeventfdオブジェクトを引数にirqfd(ioctl)を呼び出します。KVMでは同オブジェクトをカーネル内pollに登録して、イベントがあれば当該IRQに割り込みを発行します。こうすることで、qemuからでもカーネルからでも割り込みを発行することができますし、間にeventfdを挟むことで、KVMの仕組みを知らない他のプロセス/カーネルモジュールも、内部構造を知る必要なく割り込みを発行することができます。
こちらもvhost-netのパケット受信時の割り込みに利用できそうですね。
雑感
どちらの機能もqemuをショートカットしてホスト・ゲスト間の軽量なイベント通知を行なうための基盤となります。やはり、ユーザ・カーネルモード遷移は処理によっては無視できないオーバヘッドになっていたということでしょうか。
あと、どう考えてもvhostのための機能とみて間違いないでしょうね (^^; virtio in host kernelは構想だけならKVM Forum 2007のKVM Para-Virtualized Guest Drivers [pdf]に既にあった話なので、ようやくここまで来たかーといったところでしょうか。
リンク
- Kernelnewbie: http://kernelnewbies.org/Linux_2_6_32#head-46d4cfdd7eab47ed62a43fcab8bc2d971d1797c1
- ioeventfd in git: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=d34e6b175e61821026893ec5298cc8e7558df43a
- commit logにユーザモードへの遷移がないことによりどれくらい処理時間を短縮できるたかの簡単なマイクロベンチマーク結果もあります
- 4us短くなったとか
- commit logにユーザモードへの遷移がないことによりどれくらい処理時間を短縮できるたかの簡単なマイクロベンチマーク結果もあります
- irqfd in git: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=721eecbf4fe995ca94a9edec0c9843b1cc0eaaf3