Created
November 17, 2024 18:24
-
-
Save zhangyoufu/7b114ae82de824adf86bea6acf6ce4f4 to your computer and use it in GitHub Desktop.
check enabled Hyper-V Enlightenment inside VM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <intrin.h> | |
| #include <stdbool.h> | |
| #include <stdint.h> | |
| #include <stdio.h> | |
| /******************************************************************************/ | |
| // include/qemu/bitops.h | |
| #define BIT(nr) (1UL << (nr)) | |
| /******************************************************************************/ | |
| // target/i386/kvm/hyperv-proto.h | |
| #define HV_CPUID_VENDOR_AND_MAX_FUNCTIONS 0x40000000 | |
| #define HV_CPUID_INTERFACE 0x40000001 | |
| #define HV_CPUID_VERSION 0x40000002 | |
| #define HV_CPUID_FEATURES 0x40000003 | |
| #define HV_CPUID_ENLIGHTMENT_INFO 0x40000004 | |
| #define HV_CPUID_IMPLEMENT_LIMITS 0x40000005 | |
| #define HV_CPUID_NESTED_FEATURES 0x4000000A | |
| #define HV_CPUID_SYNDBG_VENDOR_AND_MAX_FUNCTIONS 0x40000080 | |
| #define HV_CPUID_SYNDBG_INTERFACE 0x40000081 | |
| #define HV_CPUID_SYNDBG_PLATFORM_CAPABILITIES 0x40000082 | |
| #define HV_CPUID_MIN 0x40000005 | |
| #define HV_CPUID_MAX 0x4000ffff | |
| #define HV_HYPERVISOR_PRESENT_BIT 0x80000000 | |
| /* | |
| * HV_CPUID_FEATURES.EAX bits | |
| */ | |
| #define HV_VP_RUNTIME_AVAILABLE (1u << 0) | |
| #define HV_TIME_REF_COUNT_AVAILABLE (1u << 1) | |
| #define HV_SYNIC_AVAILABLE (1u << 2) | |
| #define HV_SYNTIMERS_AVAILABLE (1u << 3) | |
| #define HV_APIC_ACCESS_AVAILABLE (1u << 4) | |
| #define HV_HYPERCALL_AVAILABLE (1u << 5) | |
| #define HV_VP_INDEX_AVAILABLE (1u << 6) | |
| #define HV_RESET_AVAILABLE (1u << 7) | |
| #define HV_REFERENCE_TSC_AVAILABLE (1u << 9) | |
| #define HV_ACCESS_FREQUENCY_MSRS (1u << 11) | |
| #define HV_ACCESS_REENLIGHTENMENTS_CONTROL (1u << 13) | |
| /* | |
| * HV_CPUID_FEATURES.EBX bits | |
| */ | |
| #define HV_POST_MESSAGES (1u << 4) | |
| #define HV_SIGNAL_EVENTS (1u << 5) | |
| /* | |
| * HV_CPUID_FEATURES.EDX bits | |
| */ | |
| #define HV_MWAIT_AVAILABLE (1u << 0) | |
| #define HV_GUEST_DEBUGGING_AVAILABLE (1u << 1) | |
| #define HV_PERF_MONITOR_AVAILABLE (1u << 2) | |
| #define HV_CPU_DYNAMIC_PARTITIONING_AVAILABLE (1u << 3) | |
| #define HV_HYPERCALL_XMM_INPUT_AVAILABLE (1u << 4) | |
| #define HV_GUEST_IDLE_STATE_AVAILABLE (1u << 5) | |
| #define HV_FREQUENCY_MSRS_AVAILABLE (1u << 8) | |
| #define HV_GUEST_CRASH_MSR_AVAILABLE (1u << 10) | |
| #define HV_FEATURE_DEBUG_MSRS_AVAILABLE (1u << 11) | |
| #define HV_EXT_GVA_RANGES_FLUSH_AVAILABLE (1u << 14) | |
| #define HV_STIMER_DIRECT_MODE_AVAILABLE (1u << 19) | |
| /* | |
| * HV_CPUID_FEATURES.EBX bits | |
| */ | |
| #define HV_PARTITION_DEBUGGING_ALLOWED (1u << 12) | |
| /* | |
| * HV_CPUID_ENLIGHTMENT_INFO.EAX bits | |
| */ | |
| #define HV_AS_SWITCH_RECOMMENDED (1u << 0) | |
| #define HV_LOCAL_TLB_FLUSH_RECOMMENDED (1u << 1) | |
| #define HV_REMOTE_TLB_FLUSH_RECOMMENDED (1u << 2) | |
| #define HV_APIC_ACCESS_RECOMMENDED (1u << 3) | |
| #define HV_SYSTEM_RESET_RECOMMENDED (1u << 4) | |
| #define HV_RELAXED_TIMING_RECOMMENDED (1u << 5) | |
| #define HV_DEPRECATING_AEOI_RECOMMENDED (1u << 9) | |
| #define HV_CLUSTER_IPI_RECOMMENDED (1u << 10) | |
| #define HV_EX_PROCESSOR_MASKS_RECOMMENDED (1u << 11) | |
| #define HV_ENLIGHTENED_VMCS_RECOMMENDED (1u << 14) | |
| #define HV_NO_NONARCH_CORESHARING (1u << 18) | |
| /* | |
| * HV_CPUID_SYNDBG_PLATFORM_CAPABILITIES.EAX bits | |
| */ | |
| #define HV_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING (1u << 1) | |
| /* | |
| * HV_CPUID_NESTED_FEATURES.EAX bits | |
| */ | |
| #define HV_NESTED_DIRECT_FLUSH (1u << 17) | |
| #define HV_NESTED_MSR_BITMAP (1u << 19) | |
| /******************************************************************************/ | |
| // target/i386/cpu.h | |
| /* Supported Hyper-V Enlightenments */ | |
| #define HYPERV_FEAT_RELAXED 0 | |
| #define HYPERV_FEAT_VAPIC 1 | |
| #define HYPERV_FEAT_TIME 2 | |
| #define HYPERV_FEAT_CRASH 3 | |
| #define HYPERV_FEAT_RESET 4 | |
| #define HYPERV_FEAT_VPINDEX 5 | |
| #define HYPERV_FEAT_RUNTIME 6 | |
| #define HYPERV_FEAT_SYNIC 7 | |
| #define HYPERV_FEAT_STIMER 8 | |
| #define HYPERV_FEAT_FREQUENCIES 9 | |
| #define HYPERV_FEAT_REENLIGHTENMENT 10 | |
| #define HYPERV_FEAT_TLBFLUSH 11 | |
| #define HYPERV_FEAT_EVMCS 12 | |
| #define HYPERV_FEAT_IPI 13 | |
| #define HYPERV_FEAT_STIMER_DIRECT 14 | |
| #define HYPERV_FEAT_AVIC 15 | |
| #define HYPERV_FEAT_SYNDBG 16 | |
| #define HYPERV_FEAT_MSR_BITMAP 17 | |
| #define HYPERV_FEAT_XMM_INPUT 18 | |
| #define HYPERV_FEAT_TLBFLUSH_EXT 19 | |
| #define HYPERV_FEAT_TLBFLUSH_DIRECT 20 | |
| /******************************************************************************/ | |
| // modified | |
| enum { | |
| R_EAX = 0, | |
| R_EBX = 1, | |
| R_ECX = 2, | |
| R_EDX = 3, | |
| }; | |
| /******************************************************************************/ | |
| // target/i386/kvm/kvm.c | |
| static struct { | |
| const char* desc; | |
| struct { | |
| uint32_t func; | |
| int reg; | |
| uint32_t bits; | |
| } flags[2]; | |
| uint64_t dependencies; | |
| bool skip_passthrough; | |
| } kvm_hyperv_properties[] = { | |
| [HYPERV_FEAT_RELAXED] = { | |
| .desc = "relaxed timing (hv-relaxed)", | |
| .flags = { | |
| {.func = HV_CPUID_ENLIGHTMENT_INFO, .reg = R_EAX, | |
| .bits = HV_RELAXED_TIMING_RECOMMENDED} | |
| } | |
| }, | |
| [HYPERV_FEAT_VAPIC] = { | |
| .desc = "virtual APIC (hv-vapic)", | |
| .flags = { | |
| {.func = HV_CPUID_FEATURES, .reg = R_EAX, | |
| .bits = HV_APIC_ACCESS_AVAILABLE} | |
| } | |
| }, | |
| [HYPERV_FEAT_TIME] = { | |
| .desc = "clocksources (hv-time)", | |
| .flags = { | |
| {.func = HV_CPUID_FEATURES, .reg = R_EAX, | |
| .bits = HV_TIME_REF_COUNT_AVAILABLE | HV_REFERENCE_TSC_AVAILABLE} | |
| } | |
| }, | |
| [HYPERV_FEAT_CRASH] = { | |
| .desc = "crash MSRs (hv-crash)", | |
| .flags = { | |
| {.func = HV_CPUID_FEATURES, .reg = R_EDX, | |
| .bits = HV_GUEST_CRASH_MSR_AVAILABLE} | |
| } | |
| }, | |
| [HYPERV_FEAT_RESET] = { | |
| .desc = "reset MSR (hv-reset)", | |
| .flags = { | |
| {.func = HV_CPUID_FEATURES, .reg = R_EAX, | |
| .bits = HV_RESET_AVAILABLE} | |
| } | |
| }, | |
| [HYPERV_FEAT_VPINDEX] = { | |
| .desc = "VP_INDEX MSR (hv-vpindex)", | |
| .flags = { | |
| {.func = HV_CPUID_FEATURES, .reg = R_EAX, | |
| .bits = HV_VP_INDEX_AVAILABLE} | |
| } | |
| }, | |
| [HYPERV_FEAT_RUNTIME] = { | |
| .desc = "VP_RUNTIME MSR (hv-runtime)", | |
| .flags = { | |
| {.func = HV_CPUID_FEATURES, .reg = R_EAX, | |
| .bits = HV_VP_RUNTIME_AVAILABLE} | |
| } | |
| }, | |
| [HYPERV_FEAT_SYNIC] = { | |
| .desc = "synthetic interrupt controller (hv-synic)", | |
| .flags = { | |
| {.func = HV_CPUID_FEATURES, .reg = R_EAX, | |
| .bits = HV_SYNIC_AVAILABLE} | |
| } | |
| }, | |
| [HYPERV_FEAT_STIMER] = { | |
| .desc = "synthetic timers (hv-stimer)", | |
| .flags = { | |
| {.func = HV_CPUID_FEATURES, .reg = R_EAX, | |
| .bits = HV_SYNTIMERS_AVAILABLE} | |
| }, | |
| .dependencies = BIT(HYPERV_FEAT_SYNIC) | BIT(HYPERV_FEAT_TIME) | |
| }, | |
| [HYPERV_FEAT_FREQUENCIES] = { | |
| .desc = "frequency MSRs (hv-frequencies)", | |
| .flags = { | |
| {.func = HV_CPUID_FEATURES, .reg = R_EAX, | |
| .bits = HV_ACCESS_FREQUENCY_MSRS}, | |
| {.func = HV_CPUID_FEATURES, .reg = R_EDX, | |
| .bits = HV_FREQUENCY_MSRS_AVAILABLE} | |
| } | |
| }, | |
| [HYPERV_FEAT_REENLIGHTENMENT] = { | |
| .desc = "reenlightenment MSRs (hv-reenlightenment)", | |
| .flags = { | |
| {.func = HV_CPUID_FEATURES, .reg = R_EAX, | |
| .bits = HV_ACCESS_REENLIGHTENMENTS_CONTROL} | |
| } | |
| }, | |
| [HYPERV_FEAT_TLBFLUSH] = { | |
| .desc = "paravirtualized TLB flush (hv-tlbflush)", | |
| .flags = { | |
| {.func = HV_CPUID_ENLIGHTMENT_INFO, .reg = R_EAX, | |
| .bits = HV_REMOTE_TLB_FLUSH_RECOMMENDED | | |
| HV_EX_PROCESSOR_MASKS_RECOMMENDED} | |
| }, | |
| .dependencies = BIT(HYPERV_FEAT_VPINDEX) | |
| }, | |
| [HYPERV_FEAT_EVMCS] = { | |
| .desc = "enlightened VMCS (hv-evmcs)", | |
| .flags = { | |
| {.func = HV_CPUID_ENLIGHTMENT_INFO, .reg = R_EAX, | |
| .bits = HV_ENLIGHTENED_VMCS_RECOMMENDED} | |
| }, | |
| .dependencies = BIT(HYPERV_FEAT_VAPIC) | |
| }, | |
| [HYPERV_FEAT_IPI] = { | |
| .desc = "paravirtualized IPI (hv-ipi)", | |
| .flags = { | |
| {.func = HV_CPUID_ENLIGHTMENT_INFO, .reg = R_EAX, | |
| .bits = HV_CLUSTER_IPI_RECOMMENDED | | |
| HV_EX_PROCESSOR_MASKS_RECOMMENDED} | |
| }, | |
| .dependencies = BIT(HYPERV_FEAT_VPINDEX) | |
| }, | |
| [HYPERV_FEAT_STIMER_DIRECT] = { | |
| .desc = "direct mode synthetic timers (hv-stimer-direct)", | |
| .flags = { | |
| {.func = HV_CPUID_FEATURES, .reg = R_EDX, | |
| .bits = HV_STIMER_DIRECT_MODE_AVAILABLE} | |
| }, | |
| .dependencies = BIT(HYPERV_FEAT_STIMER) | |
| }, | |
| [HYPERV_FEAT_AVIC] = { | |
| .desc = "AVIC/APICv support (hv-avic/hv-apicv)", | |
| .flags = { | |
| {.func = HV_CPUID_ENLIGHTMENT_INFO, .reg = R_EAX, | |
| .bits = HV_DEPRECATING_AEOI_RECOMMENDED} | |
| } | |
| }, | |
| [HYPERV_FEAT_SYNDBG] = { | |
| .desc = "Enable synthetic kernel debugger channel (hv-syndbg)", | |
| .flags = { | |
| {.func = HV_CPUID_FEATURES, .reg = R_EDX, | |
| .bits = HV_FEATURE_DEBUG_MSRS_AVAILABLE} | |
| }, | |
| .dependencies = BIT(HYPERV_FEAT_SYNIC) | BIT(HYPERV_FEAT_RELAXED), | |
| .skip_passthrough = true, | |
| }, | |
| [HYPERV_FEAT_MSR_BITMAP] = { | |
| .desc = "enlightened MSR-Bitmap (hv-emsr-bitmap)", | |
| .flags = { | |
| {.func = HV_CPUID_NESTED_FEATURES, .reg = R_EAX, | |
| .bits = HV_NESTED_MSR_BITMAP} | |
| } | |
| }, | |
| [HYPERV_FEAT_XMM_INPUT] = { | |
| .desc = "XMM fast hypercall input (hv-xmm-input)", | |
| .flags = { | |
| {.func = HV_CPUID_FEATURES, .reg = R_EDX, | |
| .bits = HV_HYPERCALL_XMM_INPUT_AVAILABLE} | |
| } | |
| }, | |
| [HYPERV_FEAT_TLBFLUSH_EXT] = { | |
| .desc = "Extended gva ranges for TLB flush hypercalls (hv-tlbflush-ext)", | |
| .flags = { | |
| {.func = HV_CPUID_FEATURES, .reg = R_EDX, | |
| .bits = HV_EXT_GVA_RANGES_FLUSH_AVAILABLE} | |
| }, | |
| .dependencies = BIT(HYPERV_FEAT_TLBFLUSH) | |
| }, | |
| [HYPERV_FEAT_TLBFLUSH_DIRECT] = { | |
| .desc = "direct TLB flush (hv-tlbflush-direct)", | |
| .flags = { | |
| {.func = HV_CPUID_NESTED_FEATURES, .reg = R_EAX, | |
| .bits = HV_NESTED_DIRECT_FLUSH} | |
| }, | |
| .dependencies = BIT(HYPERV_FEAT_VAPIC) | |
| }, | |
| }; | |
| /******************************************************************************/ | |
| const char* hyperv_feature_macro[] = { | |
| "HYPERV_FEAT_RELAXED", | |
| "HYPERV_FEAT_VAPIC", | |
| "HYPERV_FEAT_TIME", | |
| "HYPERV_FEAT_CRASH", | |
| "HYPERV_FEAT_RESET", | |
| "HYPERV_FEAT_VPINDEX", | |
| "HYPERV_FEAT_RUNTIME", | |
| "HYPERV_FEAT_SYNIC", | |
| "HYPERV_FEAT_STIMER", | |
| "HYPERV_FEAT_FREQUENCIES", | |
| "HYPERV_FEAT_REENLIGHTENMENT", | |
| "HYPERV_FEAT_TLBFLUSH", | |
| "HYPERV_FEAT_EVMCS", | |
| "HYPERV_FEAT_IPI", | |
| "HYPERV_FEAT_STIMER_DIRECT", | |
| "HYPERV_FEAT_AVIC", | |
| "HYPERV_FEAT_SYNDBG", | |
| "HYPERV_FEAT_MSR_BITMAP", | |
| "HYPERV_FEAT_XMM_INPUT", | |
| "HYPERV_FEAT_TLBFLUSH_EXT", | |
| "HYPERV_FEAT_TLBFLUSH_DIRECT", | |
| }; | |
| int main(void) { | |
| for (int i = 0; i < sizeof(hyperv_feature_macro) / sizeof(hyperv_feature_macro[0]); ++i) { | |
| bool feature = true; | |
| for (int j = 0; j < 2; ++j) { | |
| int gpr[4]; | |
| if (kvm_hyperv_properties[i].flags[j].func == 0) break; | |
| __cpuid(gpr, kvm_hyperv_properties[i].flags[j].func); | |
| if ((gpr[kvm_hyperv_properties[i].flags[j].reg] & kvm_hyperv_properties[i].flags[j].bits) != kvm_hyperv_properties[i].flags[j].bits) { | |
| feature = false; | |
| break; | |
| } | |
| } | |
| printf("%c %-27s %s\n", feature ? '+' : '-', hyperv_feature_macro[i], kvm_hyperv_properties[i].desc); | |
| } | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment