VirtIO は準仮想化のフレームワークで、ゲストOSで特別なハードウェアを用意して VMM と直に通信する方法を提供してくれる。 実装的には virtqueue というメモリ空間をゲストと VMM で共有することでデータ送受信を可能にしているらしい。
ここまでは良いのだが、virtqueue への読み書きはあくまでメモリ上の操作なので、ゲスト、VMM 双方で処理可能になったか知る必要がある。
現状の linux カーネルでは drivers/virtio/virtio_pci_*.c
や drivers/virtio/virtio_mmio.c
で実装されているらしい。
前者は PCI サブシステムを利用していて、通知は io 命令でやっているように見えた。 後者は ARM のために用意されたようで特定のメモリアドレスへの読み書きを実行することで通知を行うらしい。
いずれにしても VMM が特権命令、あるいは特別なメモリアドレスをトラップすることで通知を認識しているようだ。
さて、巨視的視点に立つと、VirtIO、特にブロックデバイスの実装である virtio_blk と TCMU は、 カーネルに対してユーザーランドからブロックデバイスを提供するときに、 メモリ空間を共有しその空間への更新の通知のみを特別な方法で行うという点で類似のアーキテクチャを取っている。
TCMU は LIO のバックエンドのため、フロントエンドがないと直接はユーザープロセスの IO を扱うことができない。 また、TCMU をゲスト OS で利用する場合、バックエンドのユーザーランドプロセスは結局 VirtIO などを通じて VMM で IO を処理しなくてはならない。
一方、virtio_blk は直接デバイスを提供しているのでユーザーランド(VMM)へのオーバーヘッドは vmenter/vmexit がだけになる。
このように考えると、ゲストにストレージを提供するのであれば VMM で実装してやるのがいいのかなと思った。