1 /** 2 * Program entry point. 3 * 4 * NOTE: printf is mainly used for two reasons. First, fputs with stdout 5 * crashes on Windows. Secondly, line buffering. 6 * 7 * Authors: dd86k (dd@dax.moe) 8 * Copyright: © 2016-2021 dd86k 9 * License: MIT 10 */ 11 module main; 12 13 import ddcpuid; 14 15 private: 16 @system: 17 extern (C): 18 19 int strcmp(scope const char*, scope const char*); 20 int puts(scope const char*); 21 int putchar(int); 22 int atoi(scope const char*); 23 24 static if (__VERSION__ >= 2092) { 25 pragma(printf) 26 int printf(scope const char*, ...); 27 } else { 28 int printf(scope const char*, ...); 29 } 30 31 /// Compiler version template for betterC usage 32 template CVER(int v) { 33 enum CVER = 34 cast(char)((v / 1000) + '0') ~ 35 "." ~ 36 cast(char)(((v % 1000) / 100) + '0') ~ 37 cast(char)(((v % 100) / 10) + '0') ~ 38 cast(char)((v % 10) + '0'); 39 } 40 41 /// Make a bit mask of one bit at n position 42 template BIT(int n) if (n <= 31) { enum uint BIT = 1 << n; } 43 44 enum : uint { 45 MAX_LEAF = 0x20, /// Maximum leaf override 46 MAX_VLEAF = 0x4000_0020, /// Maximum virt leaf override 47 MAX_ELEAF = 0x8000_0020, /// Maximum extended leaf override 48 } 49 50 /// Command-line options 51 struct options_t { 52 uint maxsub; /// Maximum subleaf for -r (-s) 53 bool table; /// Raw table (-r) 54 bool override_; /// Override leaves (-o) 55 } 56 57 /// print help page 58 void clih() { 59 puts( 60 "x86/AMD64 CPUID information tool\n"~ 61 "\n"~ 62 "USAGE\n"~ 63 " ddcpuid [OPTIONS...]\n"~ 64 "\n"~ 65 "OPTIONS\n"~ 66 " -r Show raw CPUID data in a table\n"~ 67 " -s Set subleaf (ECX) input value with -r\n"~ 68 " -o Override maximum leaves to 20h, 4000_0020h, and 8000_0020h\n"~ 69 "\n"~ 70 "PAGES\n"~ 71 " --version Print version screen and quit\n"~ 72 " --ver Print version and quit\n"~ 73 " -h, --help Print this help screen and quit" 74 ); 75 } 76 77 /// print version page 78 void cliv() { 79 puts( 80 "ddcpuid-"~DDCPUID_PLATFORM~" v"~DDCPUID_VERSION~" ("~__TIMESTAMP__~")\n"~ 81 "Copyright (c) dd86k 2016-2021\n"~ 82 "License: MIT License <http://opensource.org/licenses/MIT>\n"~ 83 "Project page: <https://github.com/dd86k/ddcpuid>\n"~ 84 "Compiler: "~__VENDOR__~" v"~CVER!(__VERSION__) 85 ); 86 } 87 88 /// Print cpuid table entry into stdout. 89 /// Params: 90 /// leaf = EAX input 91 /// sub = ECX input 92 pragma(inline, false) // ldc optimization thing 93 void printc(uint leaf, uint sub) { 94 REGISTERS regs = void; 95 asmcpuid(regs, leaf, sub); 96 with (regs) 97 printf("| %8x | %8x | %8x | %8x | %8x | %8x |\n", 98 leaf, sub, eax, ebx, ecx, edx); 99 } 100 101 int main(int argc, const(char) **argv) { 102 options_t opts; /// Command-line options 103 104 const(char) *arg = void; 105 for (int argi = 1; argi < argc; ++argi) { 106 if (argv[argi][1] == '-') { // Long arguments 107 arg = argv[argi] + 2; 108 if (strcmp(arg, "help") == 0) { clih; return 0; } 109 if (strcmp(arg, "version") == 0) { cliv; return 0; } 110 if (strcmp(arg, "ver") == 0) { puts(DDCPUID_VERSION); return 0; } 111 printf("Unknown parameter: '%s'\n", arg); 112 return 1; 113 } else if (argv[argi][0] == '-') { // Short arguments 114 arg = argv[argi] + 1; 115 char o = void; 116 while ((o = *arg) != 0) { 117 ++arg; 118 switch (o) { 119 case 'o': opts.override_ = true; continue; 120 case 'r': opts.table = true; continue; 121 case 's': 122 if (++argi >= argc) { 123 puts("Missing parameter: sub-leaf (-s)"); 124 return 1; 125 } 126 opts.maxsub = atoi(argv[argi]); 127 continue; 128 case 'h': clih; return 0; 129 case 'V': cliv; return 0; 130 default: 131 printf("Unknown parameter: '-%c'\n", o); 132 return 1; 133 } 134 } 135 } // else if 136 } // for 137 138 CPUINFO info; 139 140 if (opts.override_ == false) { 141 getLeaves(info); 142 } else { 143 info.max_leaf = MAX_LEAF; 144 info.max_virt_leaf = MAX_VLEAF; 145 info.max_ext_leaf = MAX_ELEAF; 146 } 147 148 if (opts.table) { // -r 149 puts( 150 "| Leaf | Sub-leaf | EAX | EBX | ECX | EDX |\n"~ 151 "|----------|----------|----------|----------|----------|----------|" 152 ); 153 154 // Normal 155 uint l = void, s = void; 156 for (l = 0; l <= info.max_leaf; ++l) 157 for (s = 0; s <= opts.maxsub; ++s) 158 printc(l, s); 159 160 // Paravirtualization 161 if (info.max_virt_leaf > 0x4000_0000) 162 for (l = 0x4000_0000; l <= info.max_virt_leaf; ++l) 163 for (s = 0; s <= opts.maxsub; ++s) 164 printc(l, s); 165 166 // Extended 167 for (l = 0x8000_0000; l <= info.max_ext_leaf; ++l) 168 for (s = 0; s <= opts.maxsub; ++s) 169 printc(l, s); 170 return 0; 171 } 172 173 getInfo(info); 174 175 // NOTE: .ptr crash with GDC -O3 176 // glibc!__strlen_sse2 (in printf) 177 char *vendor = cast(char*)info.vendor; 178 char *brand = cast(char*)info.brand; 179 180 switch (info.vendor_id) { 181 case VENDOR_INTEL: // Common in Intel processor brand strings 182 while (*brand == ' ') ++brand; // left trim cpu string 183 break; 184 default: 185 } 186 187 // 188 // ANCHOR Processor basic information 189 // 190 191 printf( 192 "Vendor : %.12s\n"~ 193 "Brand : %.48s\n"~ 194 "Identifier : Family %u (0x%x) [0x%x:0x%x] Model %u (0x%x) [0x%x:0x%x] Stepping %u\n"~ 195 "Cores : %u threads\n"~ 196 "Extensions :", 197 vendor, brand, 198 info.family, info.family, info.family_base, info.family_ext, 199 info.model, info.model, info.model_base, info.model_ext, 200 info.stepping, 201 info.cores.logical 202 ); 203 204 if (info.ext.fpu) { 205 printf(" x87/FPU"); 206 if (info.ext.f16c) printf(" +F16C"); 207 } 208 if (info.ext.mmx) { 209 printf(" MMX"); 210 if (info.ext.mmxext) printf(" ExtMMX"); 211 } 212 if (info.ext._3dnow) { 213 printf(" 3DNow!"); 214 if (info.ext._3dnowext) printf(" Ext3DNow!"); 215 } 216 if (info.ext.sse) { 217 printf(" SSE"); 218 if (info.ext.sse2) printf(" SSE2"); 219 if (info.ext.sse3) printf(" SSE3"); 220 if (info.ext.ssse3) printf(" SSSE3"); 221 if (info.ext.sse41) printf(" SSE4.1"); 222 if (info.ext.sse42) printf(" SSE4.2"); 223 if (info.ext.sse4a) printf(" SSE4a"); 224 if (info.ext.xop) printf(" XOP"); 225 } 226 if (info.ext.x86_64) { 227 switch (info.vendor_id) { 228 case VENDOR_INTEL: printf(" Intel64/x86-64"); break; 229 case VENDOR_AMD: printf(" AMD64/x86-64"); break; 230 default: printf(" x86-64"); 231 } 232 if (info.ext.lahf64) 233 printf(" +LAHF64"); 234 } 235 if (info.virt.available) 236 switch (info.vendor_id) { 237 case VENDOR_INTEL: printf(" VT-x/VMX"); break; 238 case VENDOR_AMD: // SVM 239 printf(" AMD-V/VMX"); 240 if (info.virt.version_) 241 printf(":v%u", info.virt.version_); 242 break; 243 case VENDOR_VIA: printf(" VIA-VT/VMX"); break; 244 default: printf(" VMX"); 245 } 246 if (info.ext.aes_ni) printf(" AES-NI"); 247 if (info.ext.avx) printf(" AVX"); 248 if (info.ext.avx2) printf(" AVX2"); 249 if (info.ext.avx512f) { 250 printf(" AVX512F"); 251 if (info.ext.avx512er) printf(" AVX512ER"); 252 if (info.ext.avx512pf) printf(" AVX512PF"); 253 if (info.ext.avx512cd) printf(" AVX512CD"); 254 if (info.ext.avx512dq) printf(" AVX512DQ"); 255 if (info.ext.avx512bw) printf(" AVX512BW"); 256 if (info.ext.avx512vl) printf(" AVX512VL"); 257 if (info.ext.avx512_ifma) printf(" AVX512_IFMA"); 258 if (info.ext.avx512_vbmi) printf(" AVX512_VBMI"); 259 if (info.ext.avx512_4vnniw) printf(" AVX512_4VNNIW"); 260 if (info.ext.avx512_4fmaps) printf(" AVX512_4FMAPS"); 261 if (info.ext.avx512_vbmi2) printf(" AVX512_VBMI2"); 262 if (info.ext.avx512_gfni) printf(" AVX512_GFNI"); 263 if (info.ext.avx512_vaes) printf(" AVX512_VAES"); 264 if (info.ext.avx512_vnni) printf(" AVX512_VNNI"); 265 if (info.ext.avx512_bitalg) printf(" AVX512_BITALG"); 266 if (info.ext.avx512_bf16) printf(" AVX512_BF16"); 267 if (info.ext.avx512_vp2intersect) printf(" AVX512_VP2INTERSECT"); 268 } 269 if (info.ext.adx) printf(" ADX"); 270 if (info.ext.sha) printf(" SHA"); 271 if (info.ext.fma3) printf(" FMA3"); 272 if (info.ext.fma4) printf(" FMA4"); 273 if (info.ext.tbm) printf(" TBM"); 274 if (info.ext.bmi1) printf(" BMI1"); 275 if (info.ext.bmi2) printf(" BMI2"); 276 if (info.ext.waitpkg) printf(" WAITPKG"); 277 if (info.ext.amx) printf(" AMX"); 278 if (info.ext.amx_bf16) printf(" +BF16"); 279 if (info.ext.amx_int8) printf(" +INT8"); 280 if (info.ext.amx_xtilecfg) printf(" +XTILECFG"); 281 if (info.ext.amx_xtiledata) printf(" +XTILEDATA"); 282 if (info.ext.amx_xfd) printf(" +XFD"); 283 284 // 285 // ANCHOR Extra/lone instructions 286 // 287 288 printf("\nExtra :"); 289 if (info.extras.monitor) { 290 printf(" MONITOR+MWAIT"); 291 if (info.extras.mwait_min) 292 printf(" +MIN=%u +MAX=%u", 293 info.extras.mwait_min, info.extras.mwait_max); 294 if (info.extras.monitorx) printf(" MONITORX+MWAITX"); 295 } 296 if (info.extras.pclmulqdq) printf(" PCLMULQDQ"); 297 if (info.extras.cmpxchg8b) printf(" CMPXCHG8B"); 298 if (info.extras.cmpxchg16b) printf(" CMPXCHG16B"); 299 if (info.extras.movbe) printf(" MOVBE"); 300 if (info.extras.rdrand) printf(" RDRAND"); 301 if (info.extras.rdseed) printf(" RDSEED"); 302 if (info.extras.rdmsr) printf(" RDMSR+WRMSR"); 303 if (info.extras.sysenter) printf(" SYSENTER+SYSEXIT"); 304 if (info.extras.syscall) printf(" SYSCALL+SYSRET"); 305 if (info.extras.rdtsc) { 306 printf(" RDTSC"); 307 if (info.extras.rdtsc_deadline) 308 printf(" +TSC-Deadline"); 309 if (info.extras.rdtsc_invariant) 310 printf(" +TSC-Invariant"); 311 } 312 if (info.extras.rdtscp) printf(" RDTSCP"); 313 if (info.extras.rdpid) printf(" RDPID"); 314 if (info.extras.cmov) { 315 printf(" CMOV"); 316 if (info.ext.fpu) printf(" FCOMI+FCMOV"); 317 } 318 if (info.extras.lzcnt) printf(" LZCNT"); 319 if (info.extras.popcnt) printf(" POPCNT"); 320 if (info.extras.xsave) printf(" XSAVE+XRSTOR"); 321 if (info.extras.osxsave) printf(" XSETBV+XGETBV"); 322 if (info.extras.fxsr) printf(" FXSAVE+FXRSTOR"); 323 if (info.extras.pconfig) printf(" PCONFIG"); 324 if (info.extras.cldemote) printf(" CLDEMOTE"); 325 if (info.extras.movdiri) printf(" MOVDIRI"); 326 if (info.extras.movdir64b) printf(" MOVDIR64B"); 327 if (info.extras.enqcmd) printf(" ENQCMD"); 328 if (info.extras.skinit) printf(" SKINIT+STGI"); 329 if (info.extras.serialize) printf(" SERIALIZE"); 330 331 // 332 // ANCHOR Vendor specific technologies 333 // 334 335 printf("\nTechnologies:"); 336 337 switch (info.vendor_id) { 338 case VENDOR_INTEL: 339 if (info.tech.eist) printf(" EIST"); 340 if (info.tech.turboboost) 341 printf(info.tech.turboboost30 ? 342 " TurboBoot-3.0" : " TurboBoost"); 343 if (info.mem.tsx) { 344 printf(" TSX"); 345 if (info.mem.hle) 346 printf(" +HLE"); 347 if (info.mem.rtm) 348 printf(" +RTM"); 349 if (info.mem.tsxldtrk) 350 printf(" +TSXLDTRK"); 351 } 352 if (info.tech.smx) printf(" Intel-TXT/SMX"); 353 if (info.tech.sgx) printf(" SGX"); 354 break; 355 case VENDOR_AMD: 356 if (info.tech.turboboost) printf(" Core-Performance-Boost"); 357 break; 358 default: 359 } 360 if (info.tech.htt) printf(" HTT"); 361 362 // 363 // ANCHOR Cache information 364 // 365 366 printf("\nCache :"); 367 if (info.cache.clflush) 368 printf(" CLFLUSH=%uB", info.cache.clflush_linesize << 3); 369 if (info.cache.clflushopt) printf(" CLFLUSHOPT"); 370 if (info.cache.cnxt_id) printf(" CNXT_ID"); 371 if (info.cache.ss) printf(" SS"); 372 if (info.cache.prefetchw) printf(" PREFETCHW"); 373 if (info.cache.invpcid) printf(" INVPCID"); 374 if (info.cache.wbnoinvd) printf(" WBNOINVD"); 375 376 for (uint i; i < info.cache.levels && i < DDCPUID_CACHE_MAX; ++i) { 377 CACHEINFO *cache = &info.cache.level[i]; 378 char c = 'K'; 379 if (cache.size >= 1024) { 380 cache.size >>= 10; 381 c = 'M'; 382 } 383 printf("\n\tL%u-%c: %ux %4u %ciB, %u ways, %u parts, %u B, %u sets", 384 cache.level, cache.type, cache.sharedCores, cache.size, c, 385 cache.ways, cache.partitions, cache.linesize, cache.sets 386 ); 387 if (cache.feat & BIT!(0)) printf(" +SI"); // Self Initiative 388 if (cache.feat & BIT!(1)) printf(" +FA"); // Fully Associative 389 if (cache.feat & BIT!(2)) printf(" +NWBV"); // No Write-Back Validation 390 if (cache.feat & BIT!(3)) printf(" +CI"); // Cache Inclusive 391 if (cache.feat & BIT!(4)) printf(" +CCI"); // Complex Cache Indexing 392 } 393 394 printf("\nACPI :"); 395 if (info.acpi.available) printf(" ACPI"); 396 if (info.acpi.apic) printf(" APIC"); 397 if (info.acpi.x2apic) printf(" x2APIC"); 398 if (info.acpi.arat) printf(" ARAT"); 399 if (info.acpi.tm) printf(" TM"); 400 if (info.acpi.tm2) printf(" TM2"); 401 printf(" APIC-ID=%u", info.acpi.apic_id); 402 if (info.acpi.max_apic_id) printf(" MAX-ID=%u", info.acpi.max_apic_id); 403 404 printf("\nVirtual :"); 405 if (info.virt.vme) printf(" VME"); 406 if (info.virt.apivc) printf(" APICv"); 407 408 // Paravirtualization 409 if (info.virt.vendor_id) { 410 // See earlier NOTE 411 char *virtvendor = cast(char*)info.virt.vendor; 412 printf(" HOST=%.12s", virtvendor); 413 } 414 switch (info.virt.vendor_id) { 415 case VIRT_VENDOR_VBOX_MIN: // VBox Minimal Paravirt 416 if (info.virt.vbox_tsc_freq_khz) 417 printf(" TSC_FREQ_KHZ=%u", info.virt.vbox_tsc_freq_khz); 418 if (info.virt.vbox_apic_freq_khz) 419 printf(" APIC_FREQ_KHZ=%u", info.virt.vbox_apic_freq_khz); 420 break; 421 case VIRT_VENDOR_VBOX_HV: // Hyper-V 422 printf(" OPENSOURCE=%d VENDOR_ID=%d OS=%d MAJOR=%d MINOR=%d SERVICE=%d BUILD=%d", 423 info.virt.hv_guest_opensource, 424 info.virt.hv_guest_vendor_id, 425 info.virt.hv_guest_os, 426 info.virt.hv_guest_major, 427 info.virt.hv_guest_minor, 428 info.virt.hv_guest_service, 429 info.virt.hv_guest_build); 430 if (info.virt.hv_base_feat_vp_runtime_msr) printf(" HV_BASE_FEAT_VP_RUNTIME_MSR"); 431 if (info.virt.hv_base_feat_part_time_ref_count_msr) printf(" HV_BASE_FEAT_PART_TIME_REF_COUNT_MSR"); 432 if (info.virt.hv_base_feat_basic_synic_msrs) printf(" HV_BASE_FEAT_BASIC_SYNIC_MSRS"); 433 if (info.virt.hv_base_feat_stimer_msrs) printf(" HV_BASE_FEAT_STIMER_MSRS"); 434 if (info.virt.hv_base_feat_apic_access_msrs) printf(" HV_BASE_FEAT_APIC_ACCESS_MSRS"); 435 if (info.virt.hv_base_feat_hypercall_msrs) printf(" HV_BASE_FEAT_HYPERCALL_MSRS"); 436 if (info.virt.hv_base_feat_vp_id_msr) printf(" HV_BASE_FEAT_VP_ID_MSR"); 437 if (info.virt.hv_base_feat_virt_sys_reset_msr) printf(" HV_BASE_FEAT_VIRT_SYS_RESET_MSR"); 438 if (info.virt.hv_base_feat_stat_pages_msr) printf(" HV_BASE_FEAT_STAT_PAGES_MSR"); 439 if (info.virt.hv_base_feat_part_ref_tsc_msr) printf(" HV_BASE_FEAT_PART_REF_TSC_MSR"); 440 if (info.virt.hv_base_feat_guest_idle_state_msr) printf(" HV_BASE_FEAT_GUEST_IDLE_STATE_MSR"); 441 if (info.virt.hv_base_feat_timer_freq_msrs) printf(" HV_BASE_FEAT_TIMER_FREQ_MSRS"); 442 if (info.virt.hv_base_feat_debug_msrs) printf(" HV_BASE_FEAT_DEBUG_MSRS"); 443 if (info.virt.hv_part_flags_create_part) printf(" HV_PART_FLAGS_CREATE_PART"); 444 if (info.virt.hv_part_flags_access_part_id) printf(" HV_PART_FLAGS_ACCESS_PART_ID"); 445 if (info.virt.hv_part_flags_access_memory_pool) printf(" HV_PART_FLAGS_ACCESS_MEMORY_POOL"); 446 if (info.virt.hv_part_flags_adjust_msg_buffers) printf(" HV_PART_FLAGS_ADJUST_MSG_BUFFERS"); 447 if (info.virt.hv_part_flags_post_msgs) printf(" HV_PART_FLAGS_POST_MSGS"); 448 if (info.virt.hv_part_flags_signal_events) printf(" HV_PART_FLAGS_SIGNAL_EVENTS"); 449 if (info.virt.hv_part_flags_create_port) printf(" HV_PART_FLAGS_CREATE_PORT"); 450 if (info.virt.hv_part_flags_connect_port) printf(" HV_PART_FLAGS_CONNECT_PORT"); 451 if (info.virt.hv_part_flags_access_stats) printf(" HV_PART_FLAGS_ACCESS_STATS"); 452 if (info.virt.hv_part_flags_debugging) printf(" HV_PART_FLAGS_DEBUGGING"); 453 if (info.virt.hv_part_flags_cpu_mgmt) printf(" HV_PART_FLAGS_CPU_MGMT"); 454 if (info.virt.hv_part_flags_cpu_profiler) printf(" HV_PART_FLAGS_CPU_PROFILER"); 455 if (info.virt.hv_part_flags_expanded_stack_walk) printf(" HV_PART_FLAGS_EXPANDED_STACK_WALK"); 456 if (info.virt.hv_part_flags_access_vsm) printf(" HV_PART_FLAGS_ACCESS_VSM"); 457 if (info.virt.hv_part_flags_access_vp_regs) printf(" HV_PART_FLAGS_ACCESS_VP_REGS"); 458 if (info.virt.hv_part_flags_extended_hypercalls) printf(" HV_PART_FLAGS_EXTENDED_HYPERCALLS"); 459 if (info.virt.hv_part_flags_start_vp) printf(" HV_PART_FLAGS_START_VP"); 460 if (info.virt.hv_pm_max_cpu_power_state_c0) printf(" HV_PM_MAX_CPU_POWER_STATE_C0"); 461 if (info.virt.hv_pm_max_cpu_power_state_c1) printf(" HV_PM_MAX_CPU_POWER_STATE_C1"); 462 if (info.virt.hv_pm_max_cpu_power_state_c2) printf(" HV_PM_MAX_CPU_POWER_STATE_C2"); 463 if (info.virt.hv_pm_max_cpu_power_state_c3) printf(" HV_PM_MAX_CPU_POWER_STATE_C3"); 464 if (info.virt.hv_pm_hpet_reqd_for_c3) printf(" HV_PM_HPET_REQD_FOR_C3"); 465 if (info.virt.hv_misc_feat_mwait) printf(" HV_MISC_FEAT_MWAIT"); 466 if (info.virt.hv_misc_feat_guest_debugging) printf(" HV_MISC_FEAT_GUEST_DEBUGGING"); 467 if (info.virt.hv_misc_feat_perf_mon) printf(" HV_MISC_FEAT_PERF_MON"); 468 if (info.virt.hv_misc_feat_pcpu_dyn_part_event) printf(" HV_MISC_FEAT_PCPU_DYN_PART_EVENT"); 469 if (info.virt.hv_misc_feat_xmm_hypercall_input) printf(" HV_MISC_FEAT_XMM_HYPERCALL_INPUT"); 470 if (info.virt.hv_misc_feat_guest_idle_state) printf(" HV_MISC_FEAT_GUEST_IDLE_STATE"); 471 if (info.virt.hv_misc_feat_hypervisor_sleep_state) printf(" HV_MISC_FEAT_HYPERVISOR_SLEEP_STATE"); 472 if (info.virt.hv_misc_feat_query_numa_distance) printf(" HV_MISC_FEAT_QUERY_NUMA_DISTANCE"); 473 if (info.virt.hv_misc_feat_timer_freq) printf(" HV_MISC_FEAT_TIMER_FREQ"); 474 if (info.virt.hv_misc_feat_inject_synmc_xcpt) printf(" HV_MISC_FEAT_INJECT_SYNMC_XCPT"); 475 if (info.virt.hv_misc_feat_guest_crash_msrs) printf(" HV_MISC_FEAT_GUEST_CRASH_MSRS"); 476 if (info.virt.hv_misc_feat_debug_msrs) printf(" HV_MISC_FEAT_DEBUG_MSRS"); 477 if (info.virt.hv_misc_feat_npiep1) printf(" HV_MISC_FEAT_NPIEP1"); 478 if (info.virt.hv_misc_feat_disable_hypervisor) printf(" HV_MISC_FEAT_DISABLE_HYPERVISOR"); 479 if (info.virt.hv_misc_feat_ext_gva_range_for_flush_va_list) printf(" HV_MISC_FEAT_EXT_GVA_RANGE_FOR_FLUSH_VA_LIST"); 480 if (info.virt.hv_misc_feat_hypercall_output_xmm) printf(" HV_MISC_FEAT_HYPERCALL_OUTPUT_XMM"); 481 if (info.virt.hv_misc_feat_sint_polling_mode) printf(" HV_MISC_FEAT_SINT_POLLING_MODE"); 482 if (info.virt.hv_misc_feat_hypercall_msr_lock) printf(" HV_MISC_FEAT_HYPERCALL_MSR_LOCK"); 483 if (info.virt.hv_misc_feat_use_direct_synth_msrs) printf(" HV_MISC_FEAT_USE_DIRECT_SYNTH_MSRS"); 484 if (info.virt.hv_hint_hypercall_for_process_switch) printf(" HV_HINT_HYPERCALL_FOR_PROCESS_SWITCH"); 485 if (info.virt.hv_hint_hypercall_for_tlb_flush) printf(" HV_HINT_HYPERCALL_FOR_TLB_FLUSH"); 486 if (info.virt.hv_hint_hypercall_for_tlb_shootdown) printf(" HV_HINT_HYPERCALL_FOR_TLB_SHOOTDOWN"); 487 if (info.virt.hv_hint_msr_for_apic_access) printf(" HV_HINT_MSR_FOR_APIC_ACCESS"); 488 if (info.virt.hv_hint_msr_for_sys_reset) printf(" HV_HINT_MSR_FOR_SYS_RESET"); 489 if (info.virt.hv_hint_relax_time_checks) printf(" HV_HINT_RELAX_TIME_CHECKS"); 490 if (info.virt.hv_hint_dma_remapping) printf(" HV_HINT_DMA_REMAPPING"); 491 if (info.virt.hv_hint_interrupt_remapping) printf(" HV_HINT_INTERRUPT_REMAPPING"); 492 if (info.virt.hv_hint_x2apic_msrs) printf(" HV_HINT_X2APIC_MSRS"); 493 if (info.virt.hv_hint_deprecate_auto_eoi) printf(" HV_HINT_DEPRECATE_AUTO_EOI"); 494 if (info.virt.hv_hint_synth_cluster_ipi_hypercall) printf(" HV_HINT_SYNTH_CLUSTER_IPI_HYPERCALL"); 495 if (info.virt.hv_hint_ex_proc_masks_interface) printf(" HV_HINT_EX_PROC_MASKS_INTERFACE"); 496 if (info.virt.hv_hint_nested_hyperv) printf(" HV_HINT_NESTED_HYPERV"); 497 if (info.virt.hv_hint_int_for_mbec_syscalls) printf(" HV_HINT_INT_FOR_MBEC_SYSCALLS"); 498 if (info.virt.hv_hint_nested_enlightened_vmcs_interface) printf(" HV_HINT_NESTED_ENLIGHTENED_VMCS_INTERFACE"); 499 if (info.virt.hv_host_feat_avic) printf(" HV_HOST_FEAT_AVIC"); 500 if (info.virt.hv_host_feat_msr_bitmap) printf(" HV_HOST_FEAT_MSR_BITMAP"); 501 if (info.virt.hv_host_feat_perf_counter) printf(" HV_HOST_FEAT_PERF_COUNTER"); 502 if (info.virt.hv_host_feat_nested_paging) printf(" HV_HOST_FEAT_NESTED_PAGING"); 503 if (info.virt.hv_host_feat_dma_remapping) printf(" HV_HOST_FEAT_DMA_REMAPPING"); 504 if (info.virt.hv_host_feat_interrupt_remapping) printf(" HV_HOST_FEAT_INTERRUPT_REMAPPING"); 505 if (info.virt.hv_host_feat_mem_patrol_scrubber) printf(" HV_HOST_FEAT_MEM_PATROL_SCRUBBER"); 506 if (info.virt.hv_host_feat_dma_prot_in_use) printf(" HV_HOST_FEAT_DMA_PROT_IN_USE"); 507 if (info.virt.hv_host_feat_hpet_requested) printf(" HV_HOST_FEAT_HPET_REQUESTED"); 508 if (info.virt.hv_host_feat_stimer_volatile) printf(" HV_HOST_FEAT_STIMER_VOLATILE"); 509 break; 510 case VIRT_VENDOR_KVM: 511 if (info.virt.kvm_feature_clocksource) printf(" KVM_FEATURE_CLOCKSOURCE"); 512 if (info.virt.kvm_feature_nop_io_delay) printf(" KVM_FEATURE_NOP_IO_DELAY"); 513 if (info.virt.kvm_feature_mmu_op) printf(" KVM_FEATURE_MMU_OP"); 514 if (info.virt.kvm_feature_clocksource2) printf(" KVM_FEATURE_CLOCKSOURCE2"); 515 if (info.virt.kvm_feature_async_pf) printf(" KVM_FEATURE_ASYNC_PF"); 516 if (info.virt.kvm_feature_steal_time) printf(" KVM_FEATURE_STEAL_TIME"); 517 if (info.virt.kvm_feature_pv_eoi) printf(" KVM_FEATURE_PV_EOI"); 518 if (info.virt.kvm_feature_pv_unhault) printf(" KVM_FEATURE_PV_UNHAULT"); 519 if (info.virt.kvm_feature_pv_tlb_flush) printf(" KVM_FEATURE_PV_TLB_FLUSH"); 520 if (info.virt.kvm_feature_async_pf_vmexit) printf(" KVM_FEATURE_ASYNC_PF_VMEXIT"); 521 if (info.virt.kvm_feature_pv_send_ipi) printf(" KVM_FEATURE_PV_SEND_IPI"); 522 if (info.virt.kvm_feature_pv_poll_control) printf(" KVM_FEATURE_PV_POLL_CONTROL"); 523 if (info.virt.kvm_feature_pv_sched_yield) printf(" KVM_FEATURE_PV_SCHED_YIELD"); 524 if (info.virt.kvm_feature_clocsource_stable_bit) printf(" KVM_FEATURE_CLOCSOURCE_STABLE_BIT"); 525 if (info.virt.kvm_hint_realtime) printf(" KVM_HINTS_REALTIME"); 526 break; 527 default: 528 } 529 530 printf("\nMemory :"); 531 if (info.mem.phys_bits) printf(" P-Bits=%u", info.mem.phys_bits); 532 if (info.mem.line_bits) printf(" L-Bits=%u", info.mem.line_bits); 533 if (info.mem.pae) printf(" PAE"); 534 if (info.mem.pse) printf(" PSE"); 535 if (info.mem.pse_36) printf(" PSE-36"); 536 if (info.mem.page1gb) printf(" Page1GB"); 537 if (info.mem.nx) 538 switch (info.vendor_id) { 539 case VENDOR_INTEL: printf(" Intel-XD/NX"); break; 540 case VENDOR_AMD: printf(" AMD-EVP/NX"); break; 541 default: printf(" NX"); 542 } 543 if (info.mem.dca) printf(" DCA"); 544 if (info.mem.pat) printf(" PAT"); 545 if (info.mem.mtrr) printf(" MTRR"); 546 if (info.mem.pge) printf(" PGE"); 547 if (info.mem.smep) printf(" SMEP"); 548 if (info.mem.smap) printf(" SMAP"); 549 if (info.mem.pku) printf(" PKU"); 550 if (info.mem._5pl) printf(" 5PL"); 551 if (info.mem.fsrepmov) printf(" FSRM"); 552 if (info.mem.lam) printf(" LAM"); 553 554 printf("\nDebugging :"); 555 if (info.dbg.mca) printf(" MCA"); 556 if (info.dbg.mce) printf(" MCE"); 557 if (info.dbg.de) printf(" DE"); 558 if (info.dbg.ds) printf(" DS"); 559 if (info.dbg.ds_cpl) printf(" DS-CPL"); 560 if (info.dbg.dtes64) printf(" DTES64"); 561 if (info.dbg.pdcm) printf(" PDCM"); 562 if (info.dbg.sdbg) printf(" SDBG"); 563 if (info.dbg.pbe) printf(" PBE"); 564 565 printf("\nSecurity :"); 566 if (info.sec.ia32_arch_capabilities) printf(" IA32_ARCH_CAPABILITIES"); 567 if (info.sec.ibpb) printf(" IBPB"); 568 if (info.sec.ibrs) printf(" IBRS"); 569 if (info.sec.ibrs_on) printf(" IBRS_ON"); // AMD 570 if (info.sec.ibrs_pref) printf(" IBRS_PREF"); // AMD 571 if (info.sec.stibp) printf(" STIBP"); 572 if (info.sec.stibp_on) printf(" STIBP_ON"); // AMD 573 if (info.sec.ssbd) printf(" SSBD"); 574 if (info.sec.l1d_flush) printf(" L1D_FLUSH"); // Intel 575 if (info.sec.md_clear) printf(" MD_CLEAR"); // Intel 576 if (info.sec.cet_ibt) printf(" CET_IBT"); // Intel 577 if (info.sec.cet_ss) printf(" CET_SS"); // Intel 578 579 printf("\nMisc. : HLeaf=0x%x HVLeaf=0x%x HELeaf=0x%x Type=%s Index=%u", 580 info.max_leaf, info.max_virt_leaf, info.max_ext_leaf, 581 info.type_string, info.brand_index); 582 if (info.misc.xtpr) printf(" xTPR"); 583 if (info.misc.psn) printf(" PSN"); 584 if (info.misc.pcid) printf(" PCID"); 585 if (info.misc.fsgsbase) printf(" FSGSBASE"); 586 if (info.misc.uintr) printf(" UINTR"); 587 588 putchar('\n'); 589 590 return 0; 591 }