ソースコードリーディング: KVM_RUN

おそらく KVM API の中で一番利用頻度の高い API で、複雑なAPI である。ユーザランドのスレッドが ioctl(2) + KVM_RUN を呼び出して、ゲストに移るまでを追っている

github.com

( ソースを追うだけで精一杯で、解説のようなことはできていないのでご了承を )

Intel VT-x の仕様が絡んでくる API で、詳細を含めた全貌把握は大変。ホストとゲスト間の遷移だけにフォーカスする

  • VMX non-root operation
  • VMX root operation
  • VMCS の Host State, Guest State、その他あれこれ
  • VMXON, VMLAUNCE, VMRESUME
  • VM entry , VM exit

... あたりのキーワードを syuu1228 さんのハイパーバイザの作り方Intel のマニュアル 等々で整理しつつ読み進めた

レジスタの扱いやハードウェア仮想化周りが難しいな

KVM_RUN を strace

qemu-kvm を strace すると ioctl(2) を捉えることができる

$ sudo ./strace -p $(  qemu-kvm の PID )  -f 

...

[pid 26557] <... ioctl resumed> , 0)    = 0
[pid 26557] ioctl(15, KVM_RUN, 0)       = 0
[pid 26579] <... ioctl resumed> , 0)    = 0
[pid 26557] ioctl(15, KVM_RUN <unfinished ...>
[pid 26574] <... ioctl resumed> , 0)    = 0
[pid 26579] ioctl(35, KVM_RUN <unfinished ...>
[pid 26574] ioctl(31, KVM_RUN <unfinished ...>
[pid 26579] <... ioctl resumed> , 0)    = 0
[pid 26579] ioctl(35, KVM_RUN, 0)       = 0
[pid 26579] ioctl(35, KVM_RUN, 0)       = 0
[pid 26579] ioctl(35, KVM_RUN, 0)       = 0
[pid 26579] ioctl(35, KVM_RUN, 0)       = 0
[pid 26579] ioctl(35, KVM_RUN, 0)       = 0
[pid 26579] ioctl(35, KVM_RUN <unfinished ...>
[pid 26574] <... ioctl resumed> , 0)    = 0
[pid 26557] <... ioctl resumed> , 0)    = 0
[pid 26574] ioctl(31, KVM_RUN <unfinished ...>
[pid 26557] ioctl(15, KVM_RUN <unfinished ...>
[pid 26574] <... ioctl resumed> , 0)    = 0
[pid 26557] <... ioctl resumed> , 0)    = 0
[pid 26574] ioctl(31, KVM_RUN <unfinished ...>

...

# 注: strace が古いと `KVM_FOO_BAR` のシンボルが逆引きされずに 16進数表記 = 0xae80 になる

ioctl(2) に渡しているデスクリプタは anon_inode:kvm-vcpu である。lsof でも確認できる

sudo ls -hal /proc/26520/fd
合計 0
dr-x------ 2 qemu qemu  0 12月  2 11:46 2016 .
dr-xr-xr-x 7 qemu qemu  0 11月 29 10:03 2016 ..
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 0 -> /dev/null
l-wx------ 1 qemu qemu 64 12月  2 11:46 2016 1 -> /var/log/libvirt/qemu/******.log
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 10 -> anon_inode:[signalfd]
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 11 -> /var/lib/libvirt/images/******-1359447098.87
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 12 -> /var/lib/libvirt/images/******-1371804908.61
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 13 -> /var/lib/libvirt/images/******-1477466023.96
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 14 -> /var/lib/libvirt/images/******-1477468895.71
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 15 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 16 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 17 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 18 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 19 -> anon_inode:kvm-vcpu
l-wx------ 1 qemu qemu 64 12月  2 11:46 2016 2 -> /var/log/libvirt/qemu/******.log
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 20 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 21 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 22 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 23 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 24 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 25 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 26 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 263 -> /dev/net/tun
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 264 -> /dev/net/tun
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 27 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 28 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 29 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 3 -> socket:[372948322]
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 30 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 31 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 32 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 33 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 34 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 35 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 36 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 37 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 38 -> anon_inode:kvm-vcpu
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 39 -> socket:[372948333]
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 4 -> /dev/ptmx
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 40 -> anon_inode:[eventfd]
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 41 -> anon_inode:[eventfd]
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 42 -> anon_inode:[signalfd]
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 43 -> socket:[372948334]
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 44 -> anon_inode:[eventfd]
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 45 -> anon_inode:[eventfd]
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 46 -> anon_inode:[eventfd]
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 47 -> anon_inode:[eventfd]
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 5 -> /dev/kvm
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 6 -> anon_inode:kvm-vm
lr-x------ 1 qemu qemu 64 12月  2 11:46 2016 7 -> pipe:[372948328]
l-wx------ 1 qemu qemu 64 12月  2 11:46 2016 8 -> pipe:[372948328]
lrwx------ 1 qemu qemu 64 12月  2 11:46 2016 9 -> /var/lib/libvirt/images/******-disk0

社内の暇している KVM サーバ 上で動かしている 24 vCPU の VM 。 anon_inode:kvm-vcpu がたくさん生えている 😄

anon_inode は過去エントリでとりあげた

hiboma.hatenadiary.jp