diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index dd5985eb61b4c3..10b895a452ba42 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -23,6 +23,7 @@ #include "mmu.h" #include "trace.h" #include "pmu.h" +// #include "./vmx/vmx.h" static u32 xstate_required_size(u64 xstate_bv, bool compacted) { @@ -1013,16 +1014,58 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, } EXPORT_SYMBOL_GPL(kvm_cpuid); +u64 totalCycles; +EXPORT_SYMBOL_GPL(totalCycles); + +u64 exitCycleArray[EXIT_SIZE]; +EXPORT_SYMBOL_GPL(exitCycleArray); + +u32 totalCounts; +EXPORT_SYMBOL_GPL(totalCounts); + +u32 exitCountArray[EXIT_SIZE]; +EXPORT_SYMBOL_GPL(exitCountArray); + int kvm_emulate_cpuid(struct kvm_vcpu *vcpu) { - u32 eax, ebx, ecx, edx; + u32 eax, ebx, ecx, edx, counts, low32, high32; + u64 cycles; if (cpuid_fault_enabled(vcpu) && !kvm_require_cpl(vcpu, 0)) return 1; eax = kvm_rax_read(vcpu); ecx = kvm_rcx_read(vcpu); - kvm_cpuid(vcpu, &eax, &ebx, &ecx, &edx, true); + + if ( eax == 0x4FFFFFFF ) { + counts = totalCounts; + // printk("0x4FFFFFFF: %u \n", counts); + eax = counts; + } else if ( eax == 0x4FFFFFFE ) { + cycles = totalCycles; + // printk("0x4FFFFFFE: %llu \n", cycles); + low32 = (u32)(cycles & 0xffffffff); // low 32 bit + high32 = (u32)(cycles >> 32); // high 32 bit + // printk("0x4FFFFFFE, low32: %u \n", low32); + // printk("0x4FFFFFFE, high32: %u \n", high32); + ecx = low32; + ebx = high32; + } else if ( eax == 0x4FFFFFFD ) { + counts = exitCountArray[ecx % EXIT_SIZE]; + printk("0x4FFFFFFD: %u \n", counts); + eax = counts; + } else if ( eax == 0x4FFFFFFC ) { + cycles = exitCycleArray[ecx % EXIT_SIZE]; + // printk("0x4FFFFFFE: %llu \n", cycles); + low32 = (u32)(cycles & 0xffffffff); // low 32 bit + high32 = (u32)(cycles >> 32); // high 32 bit + // printk("0x4FFFFFFE, low32: %u \n", low32); + // printk("0x4FFFFFFE, high32: %u \n", high32); + ecx = low32; + ebx = high32; + } else { + kvm_cpuid(vcpu, &eax, &ebx, &ecx, &edx, true); + } kvm_rax_write(vcpu, eax); kvm_rbx_write(vcpu, ebx); kvm_rcx_write(vcpu, ecx); diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index d78a61408243f2..c75b2c6c2f751f 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -165,4 +165,12 @@ static inline bool cpuid_fault_enabled(struct kvm_vcpu *vcpu) MSR_MISC_FEATURES_ENABLES_CPUID_FAULT; } +#define EXIT_SIZE 100 + +extern u32 totalCounts; +extern u64 totalCycles; + +extern u64 exitCycleArray[EXIT_SIZE]; +extern u32 exitCountArray[EXIT_SIZE]; + #endif diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 4a99be1fae4e58..fb160cd8e22760 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,7 @@ #include #include #include +#include #include "capabilities.h" #include "cpuid.h" @@ -61,6 +63,7 @@ #include "vmx.h" #include "x86.h" + MODULE_AUTHOR("Qumranet"); MODULE_LICENSE("GPL"); @@ -5775,16 +5778,31 @@ void dump_vmcs(void) vmcs_read16(VIRTUAL_PROCESSOR_ID)); } +static void record(u32 exitReason, clock_t start) { + u64 elapsed_time = (u64)(get_cycles() - start); + u32 index = exitReason % EXIT_SIZE; + mutex_lock(&map_lock); + + totalCounts++; + exitCountArray[index]++; + + exitCycleArray[index] += elapsed_time; + totalCycles += elapsed_time; + + mutex_unlock(&map_lock); +} + + /* * The guest has exited. See if we can fix it or if we need userspace * assistance. */ static int vmx_handle_exit(struct kvm_vcpu *vcpu) { + clock_t start = get_cycles(); struct vcpu_vmx *vmx = to_vmx(vcpu); u32 exit_reason = vmx->exit_reason; u32 vectoring_info = vmx->idt_vectoring_info; - trace_kvm_exit(exit_reason, vcpu, KVM_ISA_VMX); /* @@ -5798,17 +5816,25 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu) vmx_flush_pml_buffer(vcpu); /* If guest state is invalid, start emulating */ - if (vmx->emulation_required) + if (vmx->emulation_required) { + // capture exist reason via insturmentation code + record(exit_reason, start); return handle_invalid_guest_state(vcpu); + } - if (is_guest_mode(vcpu) && nested_vmx_exit_reflected(vcpu, exit_reason)) + if (is_guest_mode(vcpu) && nested_vmx_exit_reflected(vcpu, exit_reason)) { + // capture exist reason via insturmentation code + record(exit_reason, start); return nested_vmx_reflect_vmexit(vcpu, exit_reason); + } if (exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) { dump_vmcs(); vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY; vcpu->run->fail_entry.hardware_entry_failure_reason = exit_reason; + // capture exist reason via insturmentation code + record(exit_reason, start); return 0; } @@ -5817,6 +5843,8 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu) vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY; vcpu->run->fail_entry.hardware_entry_failure_reason = vmcs_read32(VM_INSTRUCTION_ERROR); + // capture exist reason via insturmentation code + record(exit_reason, start); return 0; } @@ -5843,6 +5871,8 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu) vcpu->run->internal.data[3] = vmcs_read64(GUEST_PHYSICAL_ADDRESS); } + // capture exist reason via insturmentation code + record(exit_reason, start); return 0; } @@ -5866,9 +5896,11 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu) } if (exit_reason < kvm_vmx_max_exit_handlers - && kvm_vmx_exit_handlers[exit_reason]) + && kvm_vmx_exit_handlers[exit_reason]) { + // capture exist reason via insturmentation code + record(exit_reason, start); return kvm_vmx_exit_handlers[exit_reason](vcpu); - else { + } else { vcpu_unimpl(vcpu, "vmx: unexpected exit reason 0x%x\n", exit_reason); dump_vmcs(); @@ -5877,6 +5909,8 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu) KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON; vcpu->run->internal.ndata = 1; vcpu->run->internal.data[0] = exit_reason; + // capture exist reason via insturmentation code + record(exit_reason, start); return 0; } } diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 64d5a4890aa9e3..998b453341c0f5 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -3,6 +3,7 @@ #define __KVM_X86_VMX_H #include +#include #include #include @@ -499,4 +500,8 @@ static inline void decache_tsc_multiplier(struct vcpu_vmx *vmx) void dump_vmcs(void); +static DEFINE_MUTEX(map_lock); + +#define EXIT_SIZE 100 + #endif /* __KVM_X86_VMX_H */ diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index dfd64124356806..d13063b0031d7c 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -7333,6 +7333,9 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) kvm_sched_yield(vcpu->kvm, a0); ret = 0; break; + case 0x283: + ret = 0x0033383245504D43; + break; default: ret = -KVM_ENOSYS; break;