eBPFでゲストのCPUIDをトレースする
これはMCC Advent Caleandar 20日目の記事です.
前日はUm6ra1さんによるMediBang Paintのmdpファイルを解析してみたでした.
はじめに
eBPFのチュートリアルとして,KVMゲストによるCPUID Instructionの実行をホスト側でeBPF(とTracepoints)を使ってトレースしてみる.ここでは,eBPFはBCCを使って書く.BCCのサンプルソースには kvm_hypercall.py
というのがあり,このサンプルの動きは以下のようになっている.
kvm_exit
,kvm_entry
,kvm_hypercall
をフックする.kvm_exit
のフックにおいて,VMExit ReasonがVMCALLによるものであったら,eBPF Mapにフラグを立ててprintする.kvm_hypercall
のフックにおいて,eBPF Mapにフラグが立っていれば,args->nr
(VCPU_REGS_RAX
) をprintする.kvm_entry
のフックにおいて,eBPF Mapのフラグを0にし,args->vcpi_id
をprintする.
例えば,ゲストで適当にVMCALL Instructionを実行すると以下のようなトレースが取れる.
$ sudo python kvm_hypercall.py TIME(s) COMM PID EVENT 15163.410112000 qemu-system-x86 9819 KVM_EXIT exit_reason : 18 15163.410130000 qemu-system-x86 9819 HYPERCALL nr : 114514 15163.410132000 qemu-system-x86 9819 KVM_ENTRY vcpu_id : 0
今回はこのサンプルをVMExit ReasonがCPUIDによるものかどうかのチェックに改変し,さらに kvm_cpuid
をフックする.args
で取れる値については /sys/kernel/debug/tracing/events/kvm/kvm_xxx(イベント名)/format
(TracepointsかつKVMイベントの場合) 辺りを見るとわかる.
環境
ホスト
- OS : Ubuntu 18.04.1 LTS
- Linux Kernel : 4.15.0-39-generic
- CPU : Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz
- Memory : 32GB
- QEMU-KVM : 2.11.1
- Python : 2.7.15rc1
- libbcc : 0.7.0-1
- bcc-tools : 0.7.0-1
ゲスト
コード
ホスト
ゲスト
CPUID Instructionのコードを適当に書いた. gist.github.com
結果
$ sudo python kvm_cpuid.py TIME(s) COMM PID EVENT 20422.473108000 qemu-system-x86 9819 KVM_EXIT exit_reason : 0xa 20422.473128000 qemu-system-x86 9819 KVM_CPUID rax : 0xd, rbx : 0x756e6547, rcx : 0x6c65746e 20422.473132000 qemu-system-x86 9819 KVM_ENTRY vcpu_id : 0x0 20422.473142000 qemu-system-x86 9819 KVM_EXIT exit_reason : 0xa 20422.473144000 qemu-system-x86 9819 KVM_CPUID rax : 0x663, rbx : 0x800, rcx : 0x80202021 20422.473146000 qemu-system-x86 9819 KVM_ENTRY vcpu_id : 0x0 20422.473149000 qemu-system-x86 9819 KVM_EXIT exit_reason : 0xa 20422.473151000 qemu-system-x86 9819 KVM_CPUID rax : 0x0, rbx : 0x0, rcx : 0x0 20422.473153000 qemu-system-x86 9819 KVM_ENTRY vcpu_id : 0x0 20422.473688000 qemu-system-x86 9819 KVM_EXIT exit_reason : 0xa 20422.473702000 qemu-system-x86 9819 KVM_CPUID rax : 0x1, rbx : 0x0, rcx : 0x4d 20422.473704000 qemu-system-x86 9819 KVM_ENTRY vcpu_id : 0x0 20422.473714000 qemu-system-x86 9819 KVM_EXIT exit_reason : 0xa 20422.473718000 qemu-system-x86 9819 KVM_CPUID rax : 0x1, rbx : 0x0, rcx : 0x4d 20422.473719000 qemu-system-x86 9819 KVM_ENTRY vcpu_id : 0x0 20422.473722000 qemu-system-x86 9819 KVM_EXIT exit_reason : 0xa 20422.473725000 qemu-system-x86 9819 KVM_CPUID rax : 0x121, rbx : 0x1c0003f, rcx : 0x3f 20422.473726000 qemu-system-x86 9819 KVM_ENTRY vcpu_id : 0x0 20422.473729000 qemu-system-x86 9819 KVM_EXIT exit_reason : 0xa 20422.473731000 qemu-system-x86 9819 KVM_CPUID rax : 0x122, rbx : 0x1c0003f, rcx : 0x3f 20422.473733000 qemu-system-x86 9819 KVM_ENTRY vcpu_id : 0x0 20422.473735000 qemu-system-x86 9819 KVM_EXIT exit_reason : 0xa 20422.473738000 qemu-system-x86 9819 KVM_CPUID rax : 0x143, rbx : 0x3c0003f, rcx : 0xfff 20422.473742000 qemu-system-x86 9819 KVM_ENTRY vcpu_id : 0x0 20422.473747000 qemu-system-x86 9819 KVM_EXIT exit_reason : 0xa 20422.473750000 qemu-system-x86 9819 KVM_CPUID rax : 0x163, rbx : 0x3c0003f, rcx : 0x3fff 20422.473751000 qemu-system-x86 9819 KVM_ENTRY vcpu_id : 0x0 20422.473760000 qemu-system-x86 9819 KVM_EXIT exit_reason : 0xa 20422.473763000 qemu-system-x86 9819 KVM_CPUID rax : 0xd, rbx : 0x756e6547, rcx : 0x6c65746e 20422.473764000 qemu-system-x86 9819 KVM_ENTRY vcpu_id : 0x0 20422.979395000 qemu-system-x86 9819 KVM_EXIT exit_reason : 0xa 20422.979412000 qemu-system-x86 9819 KVM_CPUID rax : 0x663, rbx : 0x800, rcx : 0x80202021 20422.979414000 qemu-system-x86 9819 KVM_ENTRY vcpu_id : 0x0 20422.979453000 qemu-system-x86 9819 KVM_EXIT exit_reason : 0xa 20422.979460000 qemu-system-x86 9819 KVM_CPUID rax : 0x663, rbx : 0x800, rcx : 0x80202021 20422.979462000 qemu-system-x86 9819 KVM_ENTRY vcpu_id : 0x0