12/3 奥多摩から風張峠をのぼってきた
続きを読むソースコードリーディング: KVM_RUN
おそらく KVM API の中で一番利用頻度の高い API で、複雑なAPI である。ユーザランドのスレッドが ioctl(2) + KVM_RUN を呼び出して、ゲストに移るまでを追っている
( ソースを追うだけで精一杯で、解説のようなことはできていないのでご了承を )
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 は過去エントリでとりあげた
CentOS7 1611 CR リポジトリを使う
アナウンスから少し時間が経ったが、 CentOS7 1611 ( RHEL 7.3 ベース ) の RPM が CR リポジトリ で公開されている
Early access to next CentOS Linux 7 release (1611) based on RHEL sources 7.3) is now available in the CR repos ( https://t.co/4TbnOQzoL9 )
— Karanbir Singh (@CentOS) November 24, 2016
AdditionalResources/Repositories/CR - CentOS Wiki に書いてある手順で CR リポジトリを使えるようになる
$ sudo yum update $ sudo yum-config-manager --enable cr 読み込んだプラグイン:fastestmirror ==================================================================================================== repo: cr ===================================================================================================== [cr] async = True bandwidth = 0 base_persistdir = /var/lib/yum/repos/x86_64/7 baseurl = http://mirror.centos.org/centos/7/cr/x86_64/ cache = 0 cachedir = /var/cache/yum/x86_64/7/cr check_config_file_age = True compare_providers_priority = 80 .... 省略
おもむろに全部 update するならえいやっと
$ sudo yum update
各種パッケージのバージョンを上げてあれこれ試せる。機能追加やバグっていた不具合なんかが修正されているかもしれない。とりあえずはカーネルのバージョンをあげただけで満足しいている 🍵
[vagrant@localhost ~]$ uname -a Linux localhost.localdomain 3.10.0-514.el7.x86_64 #1 SMP Tue Nov 22 16:42:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
CR リポジトリについて詳しいことは あらためてを参照されたし
AdditionalResources/Repositories/CR - CentOS Wiki
正式リリースはいつだろう?
CentOS - Wikipedia で過去のリリース日を見ると、新しいバージョンの RHEL がでて1ヶ月も経てば CentOS のリリースも追随している。RHEL 7.3 が出たのが 2016/11/3 なので 12月初週にはリリースされるだろうか。
もうちょっと早く書けばよかった
__GFP_ZERO と 0 初期化
kvm のソースを読んでたら kvm_kvzalloc() なる関数が出てきた
/* * Avoid using vmalloc for a small buffer. * Should not be used when the size is statically known. */ void *kvm_kvzalloc(unsigned long size) { if (size > PAGE_SIZE) return vzalloc(size); else return kzalloc(size, GFP_KERNEL); }
割り当てたいサイズによって vzalloc() と kzalloc() を使い分ける。 kzalloc() は下記のような感じ
/** * kzalloc - allocate memory. The memory is set to zero. * @size: how many bytes of memory are required. * @flags: the type of memory to allocate (see kmalloc). */ static inline void *kzalloc(size_t size, gfp_t flags) { return kmalloc(size, flags | __GFP_ZERO);
__GFP_ZERO を指定すると 割り当てた領域は 0
で初期化済みで返してくれる。
#define __GFP_ZERO ((__force gfp_t)___GFP_ZERO) /* Return zeroed page on success */
疑問
ここんところの実装がどうなってるかを追ってみた
といっても memset() しているだけだった。ちょっと面白みがないので下記のような検証を加えた
続きを読む