针对由EPT Violation
引起的vm-exit
分析其调用链(一直找到了分配页面的核心函数)
// linux v5.17.8
vcpu_run()
vcpu_enter_guest()
static_call(kvm_x86_handle_exit)(vcpu, exit_fastpath);
↓
struct kvm_x86_ops{
...
int (*handle_exit)(struct kvm_vcpu *vcpu, enum exit_fastpath_completion exit_fastpath);
...
} // in /arch/x86/include/asm/kvm-x86-ops.h use marco KVM_X86_OP or KVM_X86_OP_NULL to generate static_call()
// in /arch/x86/kvm/x86.c #define KVM_X86_OP NULL KVM_X86_OP
// #define KVM_X86_OP(func) \
// DEFINE_STATIC_CALL_NULL(kvm_x86_##func, *(((struct kvm_x86_ops *)0)->func));
// function relocate in arch/x86/kvm/vmx/vmx.c
static struct kvm_x86_ops vmx_x86_ops __initdata = {
.name = "kvm_intel",
...
.handle_exit = vmx_handle_exit,
... |
} |
vmx_handle_exit() ← —— —— —— -
__vmx_handle_exit()
kvm_vmx_exit_handlers[exit_handler_index](vcpu)
// table defined in /arch/x86/kvm/vmx/vmx.c
static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
...
[EXIT_REASON_EPT_VIOLATION] = handle_ept_violation,
... |
} |
/* exit caused by ept violation */ |
handle_ept_violation() ← —— —— —— —— —— —— —— —— ——
kvm_mmu_page_fault()
kvm_mmu_do_page_fault()
kvm_tdp_page_fault()
direct_page_fault()
kvm_tdp_mmu_map()
alloc_tdp_mmu_page()
kvm_mmu_memory_cache_alloc()
mmu_memory_cache_alloc_obj()
__get_free_page()
__get_free_pages()
alloc_pages()
alloc_pages_node()
__alloc_pages_node()
__alloc_pages()
...