使用しているマシンの仮想化機能対応状況の確認方法(AMD編)
先日のhbstudy #17で、仮想化するなら新しいハードウェア(NPT/EPTに対応したCPU)を使用した方が良いという話を聞いたので、対応しているか調べてみようと思いました。
AMD編としているのは、今社内で使っているサーバーで古めのものはAMD Opteronを搭載しているが殆どだったので、取り敢えずNPTに対応しているかどうかが分かれば最低限用事は足りるためです。
時間があればIntelについても調べてみたいと思います。
KVMに対応しているか調べる方法
EPT/NPTは取り敢えず置いておいて、KVMに対応しているかどうかは簡単な方法だと、
$ egrep '(vmx|svm)' --color=always /proc/cpuinfo
で確認できます。
しかし、NPTに対応しているかなど、CentOS 5.xでは細かい状況まではわかりません。
IOMMUに対応していればNPTにも対応しているだろうということで、dmesgが吐き出すメッセージで確認する方法もあります。
# dmesg | grep -e DMAR -e IOMMU
NPTに対応しているかどうかを調べる方法
/proc/cpuinfoでmodel nameが分かるので、そこから調べていくという方法もありますが、別の方法を模索してみました。
kvm-kmodのソースを調べてみところ、インラインアセンブラでcpuid命令を実行して取得しているようでしたので、適当にコードを抜粋してチェックするプログラムを書いてみました。
#include <stdio.h> #define __cpuid native_cpuid #define SVM_CPUID_FUNC (0x8000000a) #define SVM_FEATURE_NPT (1 << 0) #define SVM_FEATURE_LBRV (1 << 1) #define SVM_FEATURE_SVML (1 << 2) #define SVM_FEATURE_NRIP (1 << 3) #define SVM_FEATURE_PAUSE_FILTER (1 << 10) static inline void native_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { /* ecx is often an input as well as an output. */ asm volatile("cpuid" : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) : "0" (*eax), "2" (*ecx)); } static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { *eax = op; *ecx = 0; __cpuid(eax, ebx, ecx, edx); } static inline unsigned int cpuid_edx(unsigned int op) { unsigned int eax, ebx, ecx, edx; cpuid(op, &eax, &ebx, &ecx, &edx); return edx; } int main(int argc, const char **argv) { unsigned int svm_features = cpuid_edx(SVM_CPUID_FUNC); printf("NPT supported : %s\n", svm_features & SVM_FEATURE_NPT ? "YES" : "NO"); printf("LBRV supported : %s\n", svm_features & SVM_FEATURE_LBRV ? "YES" : "NO"); printf("SVML supported : %s\n", svm_features & SVM_FEATURE_SVML ? "YES" : "NO"); printf("NRIP supported : %s\n", svm_features & SVM_FEATURE_NRIP ? "YES" : "NO"); printf("PAUSE_FILTER supported : %s\n", svm_features & SVM_FEATURE_PAUSE_FILTER ? "YES" : "NO"); }
上記ソースをcpuid_check.cとか名前を付けて保存し、gccでコンパイルして実行。
$ gcc cpuid_check.c -o cpuid_check $ ./cpuid_check NPT supported : YES LBRV supported : YES SVML supported : YES NRIP supported : NO PAUSE_FILTER supported : NO
上手く動きました。
とりあえずNPTには対応しているようです。
以上、力技で調べてみましたが、もっと良い方法をご存知あればご教示頂けると幸いです。