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することができて便利です。

共通

  • 主な機能は、ユーザモード(qemu)へ遷移する事なしに、ゲストへ割り込みを挿入したり、PIO/MMIOをハンドリングすることです*2
  • どちらの機能もシステムコールではありません
    • KVMではお馴染みのioctl(2)を使います
  • どちらも利用者はまだいません
    • qemu-kvmにも実際に利用しているコードはありません*3
    • おそらくvhost-net(virtio in host kernel)が最初の利用者になるはずです

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]に既にあった話なので、ようやくここまで来たかーといったところでしょうか。

リンク

*1:irqfdはkvm-87、ioeventfdはkvm-88でkvm.gitに入っていたので知っている人にとっては今更かもしれませんが。。。

*2:現在もPIC仮想化などはqemuへの遷移を必要としませんが、そちらはゲスト←→KVMで完結する処理。ioeventfd/irqfdはゲスト←→KVM←→他のコンポーネントを結びつけるという点が違います

*3:irqfd(ioctl)を呼び出している関数はあるのですが、その関数を使っている関数がないみたいです

*4:Global System Interrupt: ACPIが提供するシステム全体の統一的な割り込み番号