1// Copyright 2016 The Fuchsia Authors 2// 3// Use of this source code is governed by a MIT-style 4// license that can be found in the LICENSE file or at 5// https://opensource.org/licenses/MIT 6 7#include <arch/x86/feature.h> 8 9#include <assert.h> 10#include <bits.h> 11#include <stdint.h> 12#include <string.h> 13#include <trace.h> 14 15#include <arch/ops.h> 16 17#include <fbl/algorithm.h> 18 19#define LOCAL_TRACE 0 20 21struct cpuid_leaf _cpuid[MAX_SUPPORTED_CPUID + 1]; 22struct cpuid_leaf _cpuid_hyp[MAX_SUPPORTED_CPUID_HYP - X86_CPUID_HYP_BASE + 1]; 23struct cpuid_leaf _cpuid_ext[MAX_SUPPORTED_CPUID_EXT - X86_CPUID_EXT_BASE + 1]; 24uint32_t max_cpuid = 0; 25uint32_t max_hyp_cpuid = 0; 26uint32_t max_ext_cpuid = 0; 27 28enum x86_vendor_list x86_vendor; 29enum x86_microarch_list x86_microarch; 30const x86_microarch_config_t* x86_microarch_config; 31 32static struct x86_model_info model_info; 33 34bool g_x86_feature_fsgsbase; 35 36enum x86_hypervisor_list x86_hypervisor; 37 38static int initialized = 0; 39 40static enum x86_microarch_list get_microarch(struct x86_model_info* info); 41static void select_microarch_config(void); 42 43static enum x86_hypervisor_list get_hypervisor(); 44 45void x86_feature_init(void) { 46 if (atomic_swap(&initialized, 1)) { 47 return; 48 } 49 /* test for cpuid count */ 50 cpuid(0, &_cpuid[0].a, &_cpuid[0].b, &_cpuid[0].c, &_cpuid[0].d); 51 52 max_cpuid = _cpuid[0].a; 53 if (max_cpuid > MAX_SUPPORTED_CPUID) 54 max_cpuid = MAX_SUPPORTED_CPUID; 55 56 LTRACEF("max cpuid 0x%x\n", max_cpuid); 57 58 /* figure out the vendor */ 59 union { 60 uint32_t vendor_id[3]; 61 char vendor_string[12]; 62 } vu; 63 vu.vendor_id[0] = _cpuid[0].b; 64 vu.vendor_id[1] = _cpuid[0].d; 65 vu.vendor_id[2] = _cpuid[0].c; 66 if (!memcmp(vu.vendor_string, "GenuineIntel", sizeof(vu.vendor_string))) { 67 x86_vendor = X86_VENDOR_INTEL; 68 } else if (!memcmp(vu.vendor_string, "AuthenticAMD", sizeof(vu.vendor_string))) { 69 x86_vendor = X86_VENDOR_AMD; 70 } else { 71 x86_vendor = X86_VENDOR_UNKNOWN; 72 } 73 74 /* read in the base cpuids */ 75 for (uint32_t i = 1; i <= max_cpuid; i++) { 76 cpuid_c(i, 0, &_cpuid[i].a, &_cpuid[i].b, &_cpuid[i].c, &_cpuid[i].d); 77 } 78 79 /* test for extended cpuid count */ 80 cpuid(X86_CPUID_EXT_BASE, &_cpuid_ext[0].a, &_cpuid_ext[0].b, &_cpuid_ext[0].c, 81 &_cpuid_ext[0].d); 82 83 max_ext_cpuid = _cpuid_ext[0].a; 84 LTRACEF("max extended cpuid 0x%x\n", max_ext_cpuid); 85 if (max_ext_cpuid > MAX_SUPPORTED_CPUID_EXT) 86 max_ext_cpuid = MAX_SUPPORTED_CPUID_EXT; 87 88 /* read in the extended cpuids */ 89 for (uint32_t i = X86_CPUID_EXT_BASE + 1; i - 1 < max_ext_cpuid; i++) { 90 uint32_t index = i - X86_CPUID_EXT_BASE; 91 cpuid_c(i, 0, &_cpuid_ext[index].a, &_cpuid_ext[index].b, &_cpuid_ext[index].c, 92 &_cpuid_ext[index].d); 93 } 94 95 /* read in the hypervisor cpuids. the maximum leaf is reported at X86_CPUID_HYP_BASE. */ 96 cpuid(X86_CPUID_HYP_VENDOR, &_cpuid_ext[0].a, &_cpuid_ext[0].b, &_cpuid_ext[0].c, 97 &_cpuid_ext[0].d); 98 max_hyp_cpuid = _cpuid_ext[0].a; 99 if (max_hyp_cpuid > MAX_SUPPORTED_CPUID_HYP) 100 max_hyp_cpuid = MAX_SUPPORTED_CPUID_HYP; 101 for (uint32_t i = X86_CPUID_HYP_BASE; i <= max_hyp_cpuid; i++) { 102 uint32_t index = i - X86_CPUID_HYP_BASE; 103 cpuid(i, &_cpuid_hyp[index].a, &_cpuid_hyp[index].b, &_cpuid_hyp[index].c, 104 &_cpuid_hyp[index].d); 105 } 106 107 /* populate the model info */ 108 const struct cpuid_leaf* leaf = x86_get_cpuid_leaf(X86_CPUID_MODEL_FEATURES); 109 if (leaf) { 110 model_info.processor_type = (uint8_t)BITS_SHIFT(leaf->a, 13, 12); 111 model_info.family = (uint8_t)BITS_SHIFT(leaf->a, 11, 8); 112 model_info.model = (uint8_t)BITS_SHIFT(leaf->a, 7, 4); 113 model_info.stepping = (uint8_t)BITS_SHIFT(leaf->a, 3, 0); 114 model_info.display_family = model_info.family; 115 model_info.display_model = model_info.model; 116 117 if (model_info.family == 0xf) { 118 model_info.display_family += BITS_SHIFT(leaf->a, 27, 20); 119 } 120 121 if (model_info.family == 0xf || model_info.family == 0x6) { 122 model_info.display_model += BITS_SHIFT(leaf->a, 19, 16) << 4; 123 } 124 125 x86_microarch = get_microarch(&model_info); 126 } 127 select_microarch_config(); 128 129 g_x86_feature_fsgsbase = x86_feature_test(X86_FEATURE_FSGSBASE); 130 131 x86_hypervisor = get_hypervisor(); 132} 133 134static enum x86_microarch_list get_microarch(struct x86_model_info* info) { 135 if (x86_vendor == X86_VENDOR_INTEL && info->family == 0x6) { 136 switch (info->display_model) { 137 case 0x1a: /* Nehalem */ 138 case 0x1e: /* Nehalem */ 139 case 0x1f: /* Nehalem */ 140 case 0x2e: /* Nehalem */ 141 return X86_MICROARCH_INTEL_NEHALEM; 142 case 0x25: /* Westmere */ 143 case 0x2c: /* Westmere */ 144 case 0x2f: /* Westmere */ 145 return X86_MICROARCH_INTEL_WESTMERE; 146 case 0x2a: /* Sandy Bridge */ 147 case 0x2d: /* Sandy Bridge EP */ 148 return X86_MICROARCH_INTEL_SANDY_BRIDGE; 149 case 0x3a: /* Ivy Bridge */ 150 case 0x3e: /* Ivy Bridge EP */ 151 return X86_MICROARCH_INTEL_IVY_BRIDGE; 152 case 0x3c: /* Haswell DT */ 153 case 0x3f: /* Haswell MB */ 154 case 0x45: /* Haswell ULT */ 155 case 0x46: /* Haswell ULX */ 156 return X86_MICROARCH_INTEL_HASWELL; 157 case 0x3d: /* Broadwell */ 158 case 0x47: /* Broadwell H */ 159 case 0x56: /* Broadwell EP */ 160 case 0x4f: /* Broadwell EX */ 161 return X86_MICROARCH_INTEL_BROADWELL; 162 case 0x4e: /* Skylake Y/U */ 163 case 0x5e: /* Skylake H/S */ 164 case 0x55: /* Skylake E */ 165 return X86_MICROARCH_INTEL_SKYLAKE; 166 case 0x8e: /* Kabylake Y/U */ 167 case 0x9e: /* Kabylake H/S */ 168 return X86_MICROARCH_INTEL_KABYLAKE; 169 case 0x4d: /* Silvermont */ 170 return X86_MICROARCH_INTEL_SILVERMONT; 171 } 172 } else if (x86_vendor == X86_VENDOR_AMD && info->family == 0xf) { 173 switch (info->display_family) { // zen 174 case 0x15: /* Bulldozer */ 175 return X86_MICROARCH_AMD_BULLDOZER; 176 case 0x16: /* Jaguar */ 177 return X86_MICROARCH_AMD_JAGUAR; 178 case 0x17: /* Zen */ 179 return X86_MICROARCH_AMD_ZEN; 180 } 181 } 182 return X86_MICROARCH_UNKNOWN; 183} 184 185static enum x86_hypervisor_list get_hypervisor() { 186 if (!x86_feature_test(X86_FEATURE_HYPERVISOR)) { 187 return X86_HYPERVISOR_UNKNOWN; 188 } 189 uint32_t a, b, c, d; 190 cpuid(X86_CPUID_HYP_VENDOR, &a, &b, &c, &d); 191 union { 192 uint32_t vendor_id[3]; 193 char vendor_string[12]; 194 } vu; 195 vu.vendor_id[0] = b; 196 vu.vendor_id[1] = c; 197 vu.vendor_id[2] = d; 198 if (a >= X86_CPUID_KVM_FEATURES && 199 !memcmp(vu.vendor_string, "KVMKVMKVM\0\0\0", sizeof(vu.vendor_string))) { 200 return X86_HYPERVISOR_KVM; 201 } else { 202 return X86_HYPERVISOR_UNKNOWN; 203 } 204} 205 206bool x86_get_cpuid_subleaf( 207 enum x86_cpuid_leaf_num num, uint32_t subleaf, struct cpuid_leaf* leaf) { 208 if (num < X86_CPUID_EXT_BASE) { 209 if (num > max_cpuid) 210 return false; 211 } else if (num > max_ext_cpuid) { 212 return false; 213 } 214 215 cpuid_c((uint32_t)num, subleaf, &leaf->a, &leaf->b, &leaf->c, &leaf->d); 216 return true; 217} 218 219bool x86_topology_enumerate(uint8_t level, struct x86_topology_level* info) { 220 DEBUG_ASSERT(info); 221 222 uint32_t eax, ebx, ecx, edx; 223 cpuid_c(X86_CPUID_TOPOLOGY, level, &eax, &ebx, &ecx, &edx); 224 225 uint8_t type = (ecx >> 8) & 0xff; 226 if (type == X86_TOPOLOGY_INVALID) { 227 return false; 228 } 229 230 info->right_shift = eax & 0x1f; 231 info->type = type; 232 return true; 233} 234 235const struct x86_model_info* x86_get_model(void) { 236 return &model_info; 237} 238 239void x86_feature_debug(void) { 240 const struct { 241 struct x86_cpuid_bit bit; 242 const char* name; 243 } features[] = { 244 {X86_FEATURE_FPU, "fpu"}, 245 {X86_FEATURE_SSE, "sse"}, 246 {X86_FEATURE_SSE2, "sse2"}, 247 {X86_FEATURE_SSE3, "sse3"}, 248 {X86_FEATURE_SSSE3, "ssse3"}, 249 {X86_FEATURE_SSE4_1, "sse4.1"}, 250 {X86_FEATURE_SSE4_2, "sse4.2"}, 251 {X86_FEATURE_MMX, "mmx"}, 252 {X86_FEATURE_AVX, "avx"}, 253 {X86_FEATURE_AVX2, "avx2"}, 254 {X86_FEATURE_FXSR, "fxsr"}, 255 {X86_FEATURE_PCID, "pcid"}, 256 {X86_FEATURE_XSAVE, "xsave"}, 257 {X86_FEATURE_MON, "mon"}, 258 {X86_FEATURE_AESNI, "aesni"}, 259 {X86_FEATURE_CLFLUSH, "clflush"}, 260 {X86_FEATURE_CLFLUSHOPT, "clflushopt"}, 261 {X86_FEATURE_CLWB, "clwb"}, 262 {X86_FEATURE_FSGSBASE, "fsgsbase"}, 263 {X86_FEATURE_TSC_ADJUST, "tsc_adj"}, 264 {X86_FEATURE_SMEP, "smep"}, 265 {X86_FEATURE_SMAP, "smap"}, 266 {X86_FEATURE_ERMS, "erms"}, 267 {X86_FEATURE_RDRAND, "rdrand"}, 268 {X86_FEATURE_RDSEED, "rdseed"}, 269 {X86_FEATURE_UMIP, "umip"}, 270 {X86_FEATURE_PKU, "pku"}, 271 {X86_FEATURE_SYSCALL, "syscall"}, 272 {X86_FEATURE_NX, "nx"}, 273 {X86_FEATURE_HUGE_PAGE, "huge"}, 274 {X86_FEATURE_RDTSCP, "rdtscp"}, 275 {X86_FEATURE_INVAR_TSC, "invar_tsc"}, 276 {X86_FEATURE_TSC_DEADLINE, "tsc_deadline"}, 277 {X86_FEATURE_X2APIC, "x2apic"}, 278 {X86_FEATURE_VMX, "vmx"}, 279 {X86_FEATURE_HYPERVISOR, "hypervisor"}, 280 {X86_FEATURE_PT, "pt"}, 281 {X86_FEATURE_HWP, "hwp"}, 282 }; 283 284 const char* vendor_string = nullptr; 285 switch (x86_vendor) { 286 case X86_VENDOR_UNKNOWN: 287 vendor_string = "unknown"; 288 break; 289 case X86_VENDOR_INTEL: 290 vendor_string = "Intel"; 291 break; 292 case X86_VENDOR_AMD: 293 vendor_string = "AMD"; 294 break; 295 } 296 printf("Vendor: %s\n", vendor_string); 297 298 const char* microarch_string = nullptr; 299 switch (x86_microarch) { 300 case X86_MICROARCH_UNKNOWN: 301 microarch_string = "unknown"; 302 break; 303 case X86_MICROARCH_INTEL_NEHALEM: 304 microarch_string = "Nehalem"; 305 break; 306 case X86_MICROARCH_INTEL_WESTMERE: 307 microarch_string = "Westmere"; 308 break; 309 case X86_MICROARCH_INTEL_SANDY_BRIDGE: 310 microarch_string = "Sandy Bridge"; 311 break; 312 case X86_MICROARCH_INTEL_IVY_BRIDGE: 313 microarch_string = "Ivy Bridge"; 314 break; 315 case X86_MICROARCH_INTEL_BROADWELL: 316 microarch_string = "Broadwell"; 317 break; 318 case X86_MICROARCH_INTEL_HASWELL: 319 microarch_string = "Haswell"; 320 break; 321 case X86_MICROARCH_INTEL_SKYLAKE: 322 microarch_string = "Skylake"; 323 break; 324 case X86_MICROARCH_INTEL_KABYLAKE: 325 microarch_string = "Kaby Lake"; 326 break; 327 case X86_MICROARCH_INTEL_SILVERMONT: 328 microarch_string = "Silvermont"; 329 break; 330 case X86_MICROARCH_AMD_BULLDOZER: 331 microarch_string = "Bulldozer"; 332 break; 333 case X86_MICROARCH_AMD_JAGUAR: 334 microarch_string = "Jaguar"; 335 break; 336 case X86_MICROARCH_AMD_ZEN: 337 microarch_string = "Zen"; 338 break; 339 } 340 printf("Microarch: %s\n", microarch_string); 341 printf("F/M/S: %x/%x/%x\n", model_info.display_family, model_info.display_model, 342 model_info.stepping); 343 344 char brand_string[50]; 345 memset(brand_string, 0, sizeof(brand_string)); 346 const struct cpuid_leaf* leaf; 347 uint32_t leaf_num = X86_CPUID_BRAND; 348 for (int i = 0; i < 3; i++) { 349 leaf = x86_get_cpuid_leaf((enum x86_cpuid_leaf_num)(leaf_num + i)); 350 if (!leaf) { 351 break; 352 } 353 memcpy(brand_string + (i * 16), &leaf->a, sizeof(uint32_t)); 354 memcpy(brand_string + (i * 16) + 4, &leaf->b, sizeof(uint32_t)); 355 memcpy(brand_string + (i * 16) + 8, &leaf->c, sizeof(uint32_t)); 356 memcpy(brand_string + (i * 16) + 12, &leaf->d, sizeof(uint32_t)); 357 } 358 printf("Brand: %s\n", brand_string); 359 360 printf("Features: "); 361 uint col = 0; 362 for (uint i = 0; i < fbl::count_of(features); ++i) { 363 if (x86_feature_test(features[i].bit)) 364 col += printf("%s ", features[i].name); 365 if (col >= 80) { 366 printf("\n"); 367 col = 0; 368 } 369 } 370 if (col > 0) 371 printf("\n"); 372} 373 374static uint64_t default_apic_freq() { 375 // The APIC frequency is the core crystal clock frequency if it is 376 // enumerated in the CPUID leaf 0x15, or the processor's bus clock 377 // frequency. 378 379 const struct cpuid_leaf* tsc_leaf = x86_get_cpuid_leaf(X86_CPUID_TSC); 380 if (tsc_leaf && tsc_leaf->c != 0) { 381 return tsc_leaf->c; 382 } 383 return 0; 384} 385 386static uint64_t kbl_apic_freq() { 387 uint64_t v = default_apic_freq(); 388 if (v != 0) { 389 return v; 390 } 391 return 24ul * 1000 * 1000; 392} 393 394static uint64_t bdw_apic_freq() { 395 uint64_t v = default_apic_freq(); 396 if (v != 0) { 397 return v; 398 } 399 uint64_t platform_info; 400 const uint32_t msr_platform_info = 0xce; 401 if (read_msr_safe(msr_platform_info, &platform_info) == ZX_OK) { 402 uint64_t bus_freq_mult = (platform_info >> 8) & 0xf; 403 return bus_freq_mult * 100 * 1000 * 1000; 404 } 405 return 0; 406} 407 408static uint64_t bulldozer_apic_freq() { 409 uint64_t v = default_apic_freq(); 410 if (v != 0) { 411 return v; 412 } 413 414 // 15h-17h BKDGs mention the APIC timer rate is 2xCLKIN, 415 // which experimentally appears to be 100Mhz always 416 return 100ul * 1000 * 1000; 417} 418 419static uint64_t unknown_freq() { 420 return 0; 421} 422 423static uint64_t intel_tsc_freq() { 424 const uint64_t core_crystal_clock_freq = x86_get_microarch_config()->get_apic_freq(); 425 426 // If this leaf is present, then 18.18.3 (Determining the Processor Base 427 // Frequency) documents this as the nominal TSC frequency. 428 const struct cpuid_leaf* tsc_leaf = x86_get_cpuid_leaf(X86_CPUID_TSC); 429 if (tsc_leaf && tsc_leaf->a) { 430 return (core_crystal_clock_freq * tsc_leaf->b) / tsc_leaf->a; 431 } 432 return 0; 433} 434 435static uint64_t amd_compute_p_state_clock(uint64_t p_state_msr) { 436 // is it valid? 437 if (!BIT(p_state_msr, 63)) 438 return 0; 439 440 // different AMD microarchitectures use slightly different formulas to compute 441 // the effective clock rate of a P state 442 uint64_t clock = 0; 443 switch (x86_microarch) { 444 case X86_MICROARCH_AMD_BULLDOZER: 445 case X86_MICROARCH_AMD_JAGUAR: { 446 uint64_t did = BITS_SHIFT(p_state_msr, 8, 6); 447 uint64_t fid = BITS(p_state_msr, 5, 0); 448 449 clock = (100 * (fid + 0x10) / (1 << did)) * 1000 * 1000; 450 break; 451 } 452 case X86_MICROARCH_AMD_ZEN: { 453 uint64_t fid = BITS(p_state_msr, 7, 0); 454 455 clock = (fid * 25) * 1000 * 1000; 456 break; 457 } 458 default: 459 break; 460 } 461 462 return clock; 463} 464 465static uint64_t zen_tsc_freq() { 466 const uint32_t p0_state_msr = 0xc0010064; // base P-state MSR 467 // According to the Family 17h PPR, the first P-state MSR is indeed 468 // P0 state and appears to be experimentally so 469 uint64_t p0_state; 470 if (read_msr_safe(p0_state_msr, &p0_state) != ZX_OK) 471 return 0; 472 473 return amd_compute_p_state_clock(p0_state); 474} 475 476static void unknown_reboot_system(void) { 477 return; 478} 479 480static void hsw_reboot_system(void) { 481 // 100-Series Chipset Reset Control Register: CPU + SYS Reset 482 outp(0xcf9, 0x06); 483} 484 485// Intel microarches 486static const x86_microarch_config_t kbl_config{ 487 .get_apic_freq = kbl_apic_freq, 488 .get_tsc_freq = intel_tsc_freq, 489 .reboot_system = hsw_reboot_system, 490 .disable_c1e = true, 491}; 492static const x86_microarch_config_t skl_config{ 493 .get_apic_freq = kbl_apic_freq, 494 .get_tsc_freq = intel_tsc_freq, 495 .reboot_system = hsw_reboot_system, 496 .disable_c1e = true, 497}; 498static const x86_microarch_config_t bdw_config{ 499 .get_apic_freq = bdw_apic_freq, 500 .get_tsc_freq = intel_tsc_freq, 501 .reboot_system = hsw_reboot_system, 502 .disable_c1e = true, 503}; 504static const x86_microarch_config_t hsw_config{ 505 .get_apic_freq = bdw_apic_freq, 506 .get_tsc_freq = intel_tsc_freq, 507 .reboot_system = hsw_reboot_system, 508 .disable_c1e = true, 509}; 510static const x86_microarch_config_t ivb_config{ 511 .get_apic_freq = bdw_apic_freq, 512 .get_tsc_freq = intel_tsc_freq, 513 .reboot_system = unknown_reboot_system, 514 .disable_c1e = true, 515}; 516static const x86_microarch_config_t snb_config{ 517 .get_apic_freq = bdw_apic_freq, 518 .get_tsc_freq = intel_tsc_freq, 519 .reboot_system = unknown_reboot_system, 520 .disable_c1e = true, 521}; 522static const x86_microarch_config_t westmere_config{ 523 .get_apic_freq = default_apic_freq, 524 .get_tsc_freq = intel_tsc_freq, 525 .reboot_system = unknown_reboot_system, 526 .disable_c1e = true, 527}; 528static const x86_microarch_config_t nehalem_config{ 529 .get_apic_freq = default_apic_freq, 530 .get_tsc_freq = intel_tsc_freq, 531 .reboot_system = unknown_reboot_system, 532 .disable_c1e = true, 533}; 534static const x86_microarch_config_t smt_config{ 535 .get_apic_freq = default_apic_freq, 536 .get_tsc_freq = intel_tsc_freq, 537 .reboot_system = unknown_reboot_system, 538 .disable_c1e = false, 539}; 540static const x86_microarch_config_t intel_default_config{ 541 .get_apic_freq = default_apic_freq, 542 .get_tsc_freq = intel_tsc_freq, 543 .reboot_system = unknown_reboot_system, 544 .disable_c1e = false, 545}; 546 547// AMD microarches 548static const x86_microarch_config_t zen_config{ 549 .get_apic_freq = bulldozer_apic_freq, 550 .get_tsc_freq = zen_tsc_freq, 551 .reboot_system = unknown_reboot_system, 552 .disable_c1e = false, 553}; 554static const x86_microarch_config_t jaguar_config{ 555 .get_apic_freq = bulldozer_apic_freq, 556 .get_tsc_freq = unknown_freq, 557 .reboot_system = unknown_reboot_system, 558 .disable_c1e = false, 559}; 560static const x86_microarch_config_t bulldozer_config{ 561 .get_apic_freq = bulldozer_apic_freq, 562 .get_tsc_freq = unknown_freq, 563 .reboot_system = unknown_reboot_system, 564 .disable_c1e = false, 565}; 566static const x86_microarch_config_t amd_default_config{ 567 .get_apic_freq = default_apic_freq, 568 .get_tsc_freq = unknown_freq, 569 .reboot_system = unknown_reboot_system, 570 .disable_c1e = false, 571}; 572 573// Unknown vendor config 574static const x86_microarch_config_t unknown_vendor_config{ 575 .get_apic_freq = unknown_freq, 576 .get_tsc_freq = unknown_freq, 577 .reboot_system = unknown_reboot_system, 578 .disable_c1e = false, 579}; 580 581void select_microarch_config(void) { 582 switch (x86_microarch) { 583 case X86_MICROARCH_INTEL_NEHALEM: 584 x86_microarch_config = &nehalem_config; 585 break; 586 case X86_MICROARCH_INTEL_WESTMERE: 587 x86_microarch_config = &westmere_config; 588 break; 589 case X86_MICROARCH_INTEL_SANDY_BRIDGE: 590 x86_microarch_config = &snb_config; 591 break; 592 case X86_MICROARCH_INTEL_IVY_BRIDGE: 593 x86_microarch_config = &ivb_config; 594 break; 595 case X86_MICROARCH_INTEL_BROADWELL: 596 x86_microarch_config = &bdw_config; 597 break; 598 case X86_MICROARCH_INTEL_HASWELL: 599 x86_microarch_config = &hsw_config; 600 break; 601 case X86_MICROARCH_INTEL_SKYLAKE: 602 x86_microarch_config = &skl_config; 603 break; 604 case X86_MICROARCH_INTEL_KABYLAKE: 605 x86_microarch_config = &kbl_config; 606 break; 607 case X86_MICROARCH_INTEL_SILVERMONT: 608 x86_microarch_config = &smt_config; 609 break; 610 case X86_MICROARCH_AMD_BULLDOZER: 611 x86_microarch_config = &bulldozer_config; 612 break; 613 case X86_MICROARCH_AMD_JAGUAR: 614 x86_microarch_config = &jaguar_config; 615 break; 616 case X86_MICROARCH_AMD_ZEN: 617 x86_microarch_config = &zen_config; 618 break; 619 case X86_MICROARCH_UNKNOWN: { 620 printf("WARNING: Could not identify microarch.\n"); 621 printf("Please file a bug with your boot log and description of hardware.\n"); 622 switch (x86_vendor) { 623 case X86_VENDOR_INTEL: 624 x86_microarch_config = &intel_default_config; 625 break; 626 case X86_VENDOR_AMD: 627 x86_microarch_config = &amd_default_config; 628 break; 629 case X86_VENDOR_UNKNOWN: 630 x86_microarch_config = &unknown_vendor_config; 631 break; 632 } 633 } 634 } 635} 636