/*ARGSUSED*/ void startup_kernel(void) { char *cmdline; uintptr_t addr; #if defined(__xpv) physdev_set_iopl_t set_iopl; #endif /* __xpv */ /* * At this point we are executing in a 32 bit real mode. */ #if defined(__xpv) cmdline = (char *)xen_info->cmd_line; #else /* __xpv */ cmdline = (char *)mb_info->cmdline; #endif /* __xpv */ prom_debug = (strstr(cmdline, "prom_debug") != NULL); map_debug = (strstr(cmdline, "map_debug") != NULL); #if defined(__xpv) /* * For dom0, before we initialize the console subsystem we'll * need to enable io operations, so set I/O priveldge level to 1. */ if (DOMAIN_IS_INITDOMAIN(xen_info)) { set_iopl.iopl = 1; (void) HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl); } #endif /* __xpv */ bcons_init(cmdline); DBG_MSG("\n\nSolaris prekernel set: "); DBG_MSG(cmdline); DBG_MSG("\n"); if (strstr(cmdline, "multiboot") != NULL) { dboot_panic(NO_MULTIBOOT); } /* * boot info must be 16 byte aligned for 64 bit kernel ABI */ addr = (uintptr_t)boot_info; addr = (addr + 0xf) & ~0xf; bi = (struct xboot_info *)addr; DBG((uintptr_t)bi); bi->bi_cmdline = (native_ptr_t)(uintptr_t)cmdline; /* * Need correct target_kernel_text value */ #if defined(_BOOT_TARGET_amd64) target_kernel_text = KERNEL_TEXT_amd64; #elif defined(__xpv) target_kernel_text = KERNEL_TEXT_i386_xpv; #else target_kernel_text = KERNEL_TEXT_i386; #endif DBG(target_kernel_text); #if defined(__xpv) /* * XXPV Derive this stuff from CPUID / what the hypervisor has enabled */ #if defined(_BOOT_TARGET_amd64) /* * 64-bit hypervisor. */ amd64_support = 1; pae_support = 1; #else /* _BOOT_TARGET_amd64 */ /* * See if we are running on a PAE Hypervisor */ { xen_capabilities_info_t caps; if (HYPERVISOR_xen_version(XENVER_capabilities, &caps) != 0) dboot_panic("HYPERVISOR_xen_version(caps) failed"); caps[sizeof (caps) - 1] = 0; if (prom_debug) dboot_printf("xen capabilities %s\n", caps); if (strstr(caps, "x86_32p") != NULL) pae_support = 1; } #endif /* _BOOT_TARGET_amd64 */ { xen_platform_parameters_t p; if (HYPERVISOR_xen_version(XENVER_platform_parameters, &p) != 0) dboot_panic("HYPERVISOR_xen_version(parms) failed"); DBG(p.virt_start); mfn_to_pfn_mapping = (pfn_t *)(xen_virt_start = p.virt_start); } /* * The hypervisor loads stuff starting at 1Gig */ mfn_base = ONE_GIG; DBG(mfn_base); /* * enable writable page table mode for the hypervisor */ if (HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writable_pagetables) < 0) dboot_panic("HYPERVISOR_vm_assist(writable_pagetables) failed"); /* * check for NX support */ if (pae_support) { uint32_t eax = 0x80000000; uint32_t edx = get_cpuid_edx(&eax); if (eax >= 0x80000001) { eax = 0x80000001; edx = get_cpuid_edx(&eax); if (edx & CPUID_AMD_EDX_NX) NX_support = 1; } } #if !defined(_BOOT_TARGET_amd64) /* * The 32-bit hypervisor uses segmentation to protect itself from * guests. This means when a guest attempts to install a flat 4GB * code or data descriptor the 32-bit hypervisor will protect itself * by silently shrinking the segment such that if the guest attempts * any access where the hypervisor lives a #gp fault is generated. * The problem is that some applications expect a full 4GB flat * segment for their current thread pointer and will use negative * offset segment wrap around to access data. TLS support in linux * brand is one example of this. * * The 32-bit hypervisor can catch the #gp fault in these cases * and emulate the access without passing the #gp fault to the guest * but only if VMASST_TYPE_4gb_segments is explicitly turned on. * Seems like this should have been the default. * Either way, we want the hypervisor -- and not Solaris -- to deal * to deal with emulating these accesses. */ if (HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments) < 0) dboot_panic("HYPERVISOR_vm_assist(4gb_segments) failed"); #endif /* !_BOOT_TARGET_amd64 */ #else /* __xpv */ /* * use cpuid to enable MMU features */ if (have_cpuid()) { uint32_t eax, edx; eax = 1; edx = get_cpuid_edx(&eax); if (edx & CPUID_INTC_EDX_PSE) largepage_support = 1; if (edx & CPUID_INTC_EDX_PGE) pge_support = 1; if (edx & CPUID_INTC_EDX_PAE) pae_support = 1; eax = 0x80000000; edx = get_cpuid_edx(&eax); if (eax >= 0x80000001) { eax = 0x80000001; edx = get_cpuid_edx(&eax); if (edx & CPUID_AMD_EDX_LM) amd64_support = 1; if (edx & CPUID_AMD_EDX_NX) NX_support = 1; } } else { dboot_printf("cpuid not supported\n"); } #endif /* __xpv */ #if defined(_BOOT_TARGET_amd64) if (amd64_support == 0) dboot_panic("long mode not supported, rebooting"); else if (pae_support == 0) dboot_panic("long mode, but no PAE; rebooting"); #else /* * Allow the command line to over-ride use of PAE for 32 bit. */ if (strstr(cmdline, "disablePAE=true") != NULL) { pae_support = 0; NX_support = 0; amd64_support = 0; } #endif /* * initialize the simple memory allocator */ init_mem_alloc(); #if !defined(__xpv) && !defined(_BOOT_TARGET_amd64) /* * disable PAE on 32 bit h/w w/o NX and < 4Gig of memory */ if (max_mem < FOUR_GIG && NX_support == 0) pae_support = 0; #endif /* * configure mmu information */ if (pae_support) { shift_amt = shift_amt_pae; ptes_per_table = 512; pte_size = 8; lpagesize = TWO_MEG; #if defined(_BOOT_TARGET_amd64) top_level = 3; #else top_level = 2; #endif } else { pae_support = 0; NX_support = 0; shift_amt = shift_amt_nopae; ptes_per_table = 1024; pte_size = 4; lpagesize = FOUR_MEG; top_level = 1; } DBG(pge_support); DBG(NX_support); DBG(largepage_support); DBG(amd64_support); DBG(top_level); DBG(pte_size); DBG(ptes_per_table); DBG(lpagesize); #if defined(__xpv) ktext_phys = ONE_GIG; /* from UNIX Mapfile */ #else ktext_phys = FOUR_MEG; /* from UNIX Mapfile */ #endif #if !defined(__xpv) && defined(_BOOT_TARGET_amd64) /* * For grub, copy kernel bits from the ELF64 file to final place. */ DBG_MSG("\nAllocating nucleus pages.\n"); ktext_phys = (uintptr_t)do_mem_alloc(ksize, FOUR_MEG); if (ktext_phys == 0) dboot_panic("failed to allocate aligned kernel memory"); if (dboot_elfload64(mb_header.load_addr) != 0) dboot_panic("failed to parse kernel ELF image, rebooting"); #endif DBG(ktext_phys); /* * Allocate page tables. */ build_page_tables(); /* * return to assembly code to switch to running kernel */ entry_addr_low = (uint32_t)target_kernel_text; DBG(entry_addr_low); bi->bi_use_largepage = largepage_support; bi->bi_use_pae = pae_support; bi->bi_use_pge = pge_support; bi->bi_use_nx = NX_support; #if defined(__xpv) bi->bi_next_paddr = next_avail_addr - mfn_base; DBG(bi->bi_next_paddr); bi->bi_next_vaddr = (native_ptr_t)next_avail_addr; DBG(bi->bi_next_vaddr); /* * unmap unused pages in start area to make them available for DMA */ while (next_avail_addr < scratch_end) { (void) HYPERVISOR_update_va_mapping(next_avail_addr, 0, UVMF_INVLPG | UVMF_LOCAL); next_avail_addr += MMU_PAGESIZE; } bi->bi_xen_start_info = (uintptr_t)xen_info; DBG((uintptr_t)HYPERVISOR_shared_info); bi->bi_shared_info = (native_ptr_t)HYPERVISOR_shared_info; bi->bi_top_page_table = (uintptr_t)top_page_table - mfn_base; #else /* __xpv */ bi->bi_next_paddr = next_avail_addr; DBG(bi->bi_next_paddr); bi->bi_next_vaddr = (uintptr_t)next_avail_addr; DBG(bi->bi_next_vaddr); bi->bi_mb_info = (uintptr_t)mb_info; bi->bi_top_page_table = (uintptr_t)top_page_table; #endif /* __xpv */ bi->bi_kseg_size = FOUR_MEG; DBG(bi->bi_kseg_size); #ifndef __xpv if (map_debug) dump_tables(); #endif DBG_MSG("\n\n*** DBOOT DONE -- back to asm to jump to kernel\n\n"); }
int get_cputype(int gettype){ int eax, ebx, ecx, edx; int extend_family, family; int extend_model, model; int type, stepping; int feature = 0; cpuid(1, &eax, &ebx, &ecx, &edx); switch (gettype) { case GET_EXFAMILY : return BITMASK(eax, 20, 0xff); case GET_EXMODEL : return BITMASK(eax, 16, 0x0f); case GET_TYPE : return BITMASK(eax, 12, 0x03); case GET_FAMILY : return BITMASK(eax, 8, 0x0f); case GET_MODEL : return BITMASK(eax, 4, 0x0f); case GET_APICID : return BITMASK(ebx, 24, 0x0f); case GET_LCOUNT : return BITMASK(ebx, 16, 0x0f); case GET_CHUNKS : return BITMASK(ebx, 8, 0x0f); case GET_STEPPING : return BITMASK(eax, 0, 0x0f); case GET_BLANDID : return BITMASK(ebx, 0, 0xff); case GET_NUMSHARE : if (have_cpuid() < 4) return 0; cpuid(4, &eax, &ebx, &ecx, &edx); return BITMASK(eax, 14, 0xfff); case GET_NUMCORES : if (have_cpuid() < 4) return 0; cpuid(4, &eax, &ebx, &ecx, &edx); return BITMASK(eax, 26, 0x3f); case GET_FEATURE : if ((edx & (1 << 3)) != 0) feature |= HAVE_PSE; if ((edx & (1 << 15)) != 0) feature |= HAVE_CMOV; if ((edx & (1 << 19)) != 0) feature |= HAVE_CFLUSH; if ((edx & (1 << 23)) != 0) feature |= HAVE_MMX; if ((edx & (1 << 25)) != 0) feature |= HAVE_SSE; if ((edx & (1 << 26)) != 0) feature |= HAVE_SSE2; if ((edx & (1 << 27)) != 0) { if (BITMASK(ebx, 16, 0x0f) > 0) feature |= HAVE_HIT; } if ((ecx & (1 << 0)) != 0) feature |= HAVE_SSE3; if ((ecx & (1 << 9)) != 0) feature |= HAVE_SSSE3; if ((ecx & (1 << 19)) != 0) feature |= HAVE_SSE4_1; if ((ecx & (1 << 20)) != 0) feature |= HAVE_SSE4_2; #ifndef NO_AVX if (support_avx()) feature |= HAVE_AVX; #endif if (have_excpuid() >= 0x01) { cpuid(0x80000001, &eax, &ebx, &ecx, &edx); if ((ecx & (1 << 6)) != 0) feature |= HAVE_SSE4A; if ((ecx & (1 << 7)) != 0) feature |= HAVE_MISALIGNSSE; if ((edx & (1 << 30)) != 0) feature |= HAVE_3DNOWEX; if ((edx & (1 << 31)) != 0) feature |= HAVE_3DNOW; } if (have_excpuid() >= 0x1a) { cpuid(0x8000001a, &eax, &ebx, &ecx, &edx); if ((eax & (1 << 0)) != 0) feature |= HAVE_128BITFPU; if ((eax & (1 << 1)) != 0) feature |= HAVE_FASTMOVU; } } return feature; }
int get_cpuname(void){ int family, exfamily, model, vendor, exmodel; if (!have_cpuid()) return CPUTYPE_80386; family = get_cputype(GET_FAMILY); exfamily = get_cputype(GET_EXFAMILY); model = get_cputype(GET_MODEL); exmodel = get_cputype(GET_EXMODEL); vendor = get_vendor(); if (vendor == VENDOR_INTEL){ switch (family) { case 0x4: return CPUTYPE_80486; case 0x5: return CPUTYPE_PENTIUM; case 0x6: switch (exmodel) { case 0: switch (model) { case 1: case 3: case 5: case 6: return CPUTYPE_PENTIUM2; case 7: case 8: case 10: case 11: return CPUTYPE_PENTIUM3; case 9: case 13: case 14: return CPUTYPE_PENTIUMM; case 15: return CPUTYPE_CORE2; } break; case 1: switch (model) { case 6: return CPUTYPE_CORE2; case 7: return CPUTYPE_PENRYN; case 10: case 11: case 14: case 15: return CPUTYPE_NEHALEM; case 12: return CPUTYPE_ATOM; case 13: return CPUTYPE_DUNNINGTON; } break; case 2: switch (model) { case 5: //Intel Core (Clarkdale) / Core (Arrandale) // Pentium (Clarkdale) / Pentium Mobile (Arrandale) // Xeon (Clarkdale), 32nm return CPUTYPE_NEHALEM; case 10: //Intel Core i5-2000 /i7-2000 (Sandy Bridge) if(support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; //OS doesn't support AVX case 12: //Xeon Processor 5600 (Westmere-EP) return CPUTYPE_NEHALEM; case 13: //Intel Core i7-3000 / Xeon E5 (Sandy Bridge) if(support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 15: //Xeon Processor E7 (Westmere-EX) return CPUTYPE_NEHALEM; } break; case 3: switch (model) { case 10: if(support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; } break; } break; case 0x7: return CPUTYPE_ITANIUM; case 0xf: switch (exfamily) { case 0 : return CPUTYPE_PENTIUM4; case 1 : return CPUTYPE_ITANIUM; } break; } return CPUTYPE_INTEL_UNKNOWN; } if (vendor == VENDOR_AMD){ switch (family) { case 0x4: return CPUTYPE_AMD5X86; case 0x5: return CPUTYPE_AMDK6; case 0x6: return CPUTYPE_ATHLON; case 0xf: switch (exfamily) { case 0: case 2: return CPUTYPE_OPTERON; case 1: case 10: case 6: //AMD Bulldozer Opteron 6200 / Opteron 4200 / AMD FX-Series return CPUTYPE_BARCELONA; case 5: return CPUTYPE_BOBCAT; } break; } return CPUTYPE_AMD_UNKNOWN; } if (vendor == VENDOR_CYRIX){ switch (family) { case 0x4: return CPUTYPE_CYRIX5X86; case 0x5: return CPUTYPE_CYRIXM1; case 0x6: return CPUTYPE_CYRIXM2; } return CPUTYPE_CYRIX_UNKNOWN; } if (vendor == VENDOR_NEXGEN){ switch (family) { case 0x5: return CPUTYPE_NEXGENNX586; } return CPUTYPE_NEXGEN_UNKNOWN; } if (vendor == VENDOR_CENTAUR){ switch (family) { case 0x5: return CPUTYPE_CENTAURC6; break; case 0x6: return CPUTYPE_NANO; break; } return CPUTYPE_VIAC3; } if (vendor == VENDOR_RISE){ switch (family) { case 0x5: return CPUTYPE_RISEMP6; } return CPUTYPE_RISE_UNKNOWN; } if (vendor == VENDOR_SIS){ switch (family) { case 0x5: return CPUTYPE_SYS55X; } return CPUTYPE_SIS_UNKNOWN; } if (vendor == VENDOR_TRANSMETA){ switch (family) { case 0x5: return CPUTYPE_CRUSOETM3X; } return CPUTYPE_TRANSMETA_UNKNOWN; } if (vendor == VENDOR_NSC){ switch (family) { case 0x5: return CPUTYPE_NSGEODE; } return CPUTYPE_NSC_UNKNOWN; } return CPUTYPE_UNKNOWN; }
int get_coretype(void){ int family, exfamily, model, exmodel, vendor; if (!have_cpuid()) return CORE_80486; family = get_cputype(GET_FAMILY); exfamily = get_cputype(GET_EXFAMILY); model = get_cputype(GET_MODEL); exmodel = get_cputype(GET_EXMODEL); vendor = get_vendor(); if (vendor == VENDOR_INTEL){ switch (family) { case 4: return CORE_80486; case 5: return CORE_P5; case 6: switch (exmodel) { case 0: switch (model) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: return CORE_P6; case 7: return CORE_KATMAI; case 8: case 10: case 11: return CORE_COPPERMINE; case 9: case 13: case 14: return CORE_BANIAS; case 15: return CORE_CORE2; } break; case 1: switch (model) { case 6: return CORE_CORE2; case 7: return CORE_PENRYN; case 10: case 11: case 14: case 15: return CORE_NEHALEM; case 12: return CORE_ATOM; case 13: return CORE_DUNNINGTON; } break; case 2: switch (model) { case 5: //Intel Core (Clarkdale) / Core (Arrandale) // Pentium (Clarkdale) / Pentium Mobile (Arrandale) // Xeon (Clarkdale), 32nm return CORE_NEHALEM; case 10: //Intel Core i5-2000 /i7-2000 (Sandy Bridge) if(support_avx()) return CORE_SANDYBRIDGE; else return CORE_NEHALEM; //OS doesn't support AVX case 12: //Xeon Processor 5600 (Westmere-EP) return CORE_NEHALEM; case 13: //Intel Core i7-3000 / Xeon E5 (Sandy Bridge) if(support_avx()) return CORE_SANDYBRIDGE; else return CORE_NEHALEM; //OS doesn't support AVX case 15: //Xeon Processor E7 (Westmere-EX) return CORE_NEHALEM; } break; case 3: switch (model) { case 10: if(support_avx()) return CORE_SANDYBRIDGE; else return CORE_NEHALEM; //OS doesn't support AVX } break; } break; case 15: if (model <= 0x2) return CORE_NORTHWOOD; else return CORE_PRESCOTT; } } if (vendor == VENDOR_AMD){ if (family <= 0x5) return CORE_80486; if (family <= 0xe) return CORE_ATHLON; if (family == 0xf){ if ((exfamily == 0) || (exfamily == 2)) return CORE_OPTERON; else if (exfamily == 5) return CORE_BOBCAT; else if (exfamily == 6) return CORE_BARCELONA; //AMD Bulldozer Opteron 6200 / Opteron 4200 / AMD FX-Series else return CORE_BARCELONA; } } if (vendor == VENDOR_CENTAUR) { switch (family) { case 0x6: return CORE_NANO; break; } return CORE_VIAC3; } return CORE_UNKNOWN; }
int get_cpuname(void){ int family, exfamily, model, vendor, exmodel; if (!have_cpuid()) return CPUTYPE_80386; family = get_cputype(GET_FAMILY); exfamily = get_cputype(GET_EXFAMILY); model = get_cputype(GET_MODEL); exmodel = get_cputype(GET_EXMODEL); vendor = get_vendor(); if (vendor == VENDOR_INTEL){ switch (family) { case 0x4: return CPUTYPE_80486; case 0x5: return CPUTYPE_PENTIUM; case 0x6: switch (exmodel) { case 0: switch (model) { case 1: case 3: case 5: case 6: return CPUTYPE_PENTIUM2; case 7: case 8: case 10: case 11: return CPUTYPE_PENTIUM3; case 9: case 13: case 14: return CPUTYPE_PENTIUMM; case 15: return CPUTYPE_CORE2; } break; case 1: switch (model) { case 6: return CPUTYPE_CORE2; case 7: return CPUTYPE_PENRYN; case 10: case 11: case 14: case 15: return CPUTYPE_NEHALEM; case 12: return CPUTYPE_ATOM; case 13: return CPUTYPE_DUNNINGTON; } break; case 2: switch (model) { case 5: //Intel Core (Clarkdale) / Core (Arrandale) // Pentium (Clarkdale) / Pentium Mobile (Arrandale) // Xeon (Clarkdale), 32nm return CPUTYPE_NEHALEM; case 10: //Intel Core i5-2000 /i7-2000 (Sandy Bridge) if(support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; //OS doesn't support AVX case 12: //Xeon Processor 5600 (Westmere-EP) return CPUTYPE_NEHALEM; case 13: //Intel Core i7-3000 / Xeon E5 (Sandy Bridge) if(support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 14: // Xeon E7540 case 15: //Xeon Processor E7 (Westmere-EX) return CPUTYPE_NEHALEM; } break; case 3: switch (model) { case 10: case 14: // Ivy Bridge if(support_avx()) return CPUTYPE_SANDYBRIDGE; else return CPUTYPE_NEHALEM; case 12: case 15: if(support_avx()) #ifndef NO_AVX2 return CPUTYPE_HASWELL; #else return CPUTYPE_SANDYBRIDGE; #endif else return CPUTYPE_NEHALEM; } break; case 4: switch (model) { case 5: case 6: if(support_avx()) #ifndef NO_AVX2 return CPUTYPE_HASWELL; #else return CPUTYPE_SANDYBRIDGE; #endif else return CPUTYPE_NEHALEM; } break; } break; case 0x7: return CPUTYPE_ITANIUM; case 0xf: switch (exfamily) { case 0 : return CPUTYPE_PENTIUM4; case 1 : return CPUTYPE_ITANIUM; } break; }
int get_cpuname(void){ int family, exfamily, model, vendor, exmodel; if (!have_cpuid()) return CPUTYPE_80386; family = get_cputype(GET_FAMILY); exfamily = get_cputype(GET_EXFAMILY); model = get_cputype(GET_MODEL); exmodel = get_cputype(GET_EXMODEL); vendor = get_vendor(); if (vendor == VENDOR_INTEL){ switch (family) { case 0x4: return CPUTYPE_80486; case 0x5: return CPUTYPE_PENTIUM; case 0x6: switch (exmodel) { case 0: switch (model) { case 1: case 3: case 5: case 6: return CPUTYPE_PENTIUM2; case 7: case 8: case 10: case 11: return CPUTYPE_PENTIUM3; case 9: case 13: case 14: return CPUTYPE_PENTIUMM; case 15: return CPUTYPE_CORE2; } break; case 1: switch (model) { case 6: return CPUTYPE_CORE2; case 7: return CPUTYPE_PENRYN; case 10: case 11: case 14: case 15: return CPUTYPE_NEHALEM; case 12: return CPUTYPE_ATOM; case 13: return CPUTYPE_DUNNINGTON; break; } } break; case 0x7: return CPUTYPE_ITANIUM; case 0xf: switch (exfamily) { case 0 : return CPUTYPE_PENTIUM4; case 1 : return CPUTYPE_ITANIUM; } break; } return CPUTYPE_INTEL_UNKNOWN; } if (vendor == VENDOR_AMD){ switch (family) { case 0x4: return CPUTYPE_AMD5X86; case 0x5: return CPUTYPE_AMDK6; case 0x6: return CPUTYPE_ATHLON; case 0xf: switch (exfamily) { case 0: case 2: return CPUTYPE_OPTERON; case 1: case 10: return CPUTYPE_BARCELONA; } break; } return CPUTYPE_AMD_UNKNOWN; } if (vendor == VENDOR_CYRIX){ switch (family) { case 0x4: return CPUTYPE_CYRIX5X86; case 0x5: return CPUTYPE_CYRIXM1; case 0x6: return CPUTYPE_CYRIXM2; } return CPUTYPE_CYRIX_UNKNOWN; } if (vendor == VENDOR_NEXGEN){ switch (family) { case 0x5: return CPUTYPE_NEXGENNX586; } return CPUTYPE_NEXGEN_UNKNOWN; } if (vendor == VENDOR_CENTAUR){ switch (family) { case 0x5: return CPUTYPE_CENTAURC6; break; case 0x6: return CPUTYPE_NANO; break; } return CPUTYPE_VIAC3; } if (vendor == VENDOR_RISE){ switch (family) { case 0x5: return CPUTYPE_RISEMP6; } return CPUTYPE_RISE_UNKNOWN; } if (vendor == VENDOR_SIS){ switch (family) { case 0x5: return CPUTYPE_SYS55X; } return CPUTYPE_SIS_UNKNOWN; } if (vendor == VENDOR_TRANSMETA){ switch (family) { case 0x5: return CPUTYPE_CRUSOETM3X; } return CPUTYPE_TRANSMETA_UNKNOWN; } if (vendor == VENDOR_NSC){ switch (family) { case 0x5: return CPUTYPE_NSGEODE; } return CPUTYPE_NSC_UNKNOWN; } return CPUTYPE_UNKNOWN; }
int get_coretype(void){ int family, exfamily, model, exmodel, vendor; if (!have_cpuid()) return CORE_80486; family = get_cputype(GET_FAMILY); exfamily = get_cputype(GET_EXFAMILY); model = get_cputype(GET_MODEL); exmodel = get_cputype(GET_EXMODEL); vendor = get_vendor(); if (vendor == VENDOR_INTEL){ switch (family) { case 4: return CORE_80486; case 5: return CORE_P5; case 6: switch (exmodel) { case 0: switch (model) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: return CORE_P6; case 7: return CORE_KATMAI; case 8: case 10: case 11: return CORE_COPPERMINE; case 9: case 13: case 14: return CORE_BANIAS; case 15: return CORE_CORE2; } break; case 1: switch (model) { case 6: return CORE_CORE2; case 7: return CORE_PENRYN; case 10: case 11: case 14: case 15: return CORE_NEHALEM; case 12: return CORE_ATOM; case 13: return CORE_DUNNINGTON; break; } } case 15: if (model <= 0x2) return CORE_NORTHWOOD; return CORE_PRESCOTT; } } if (vendor == VENDOR_AMD){ if (family <= 0x5) return CORE_80486; if (family <= 0xe) return CORE_ATHLON; if (family == 0xf){ if ((exfamily == 0) || (exfamily == 2)) return CORE_OPTERON; else return CORE_BARCELONA; } } if (vendor == VENDOR_CENTAUR) { switch (family) { case 0x6: return CORE_NANO; break; } return CORE_VIAC3; } return CORE_UNKNOWN; }
int cpu_detect() { int eax, ebx, ecx, edx; int vendor, family, extend_family, model, extend_model; if (!have_cpuid()) return CPUNAME_REFERENCE; vendor=get_vendor(); cpuid(1, &eax, &ebx, &ecx, &edx); extend_family = BITMASK(eax, 20, 0xff); extend_model=BITMASK(eax, 16, 0x0f); family=BITMASK(eax, 8, 0x0f); model=BITMASK(eax, 4, 0x0f); if (vendor == VENDOR_INTEL){ switch (family) { case 0x6: switch (extend_model) { case 1: switch (model) { case 7: //penryn uses dunnington config. return CPUNAME_DUNNINGTON; case 13: return CPUNAME_DUNNINGTON; } break; case 2: switch (model) { case 10: case 13: if(support_avx()) { return CPUNAME_SANDYBRIDGE; }else{ return CPUNAME_REFERENCE; //OS doesn't support AVX } } break; case 3: switch (model) { case 10: case 14: //Ivy Bridge if(support_avx()) { return CPUNAME_SANDYBRIDGE; }else{ return CPUNAME_REFERENCE; //OS doesn't support AVX } case 12: case 15: //Haswell. Temp use Sandy Brdige if(support_avx()) { return CPUNAME_SANDYBRIDGE; }else{ return CPUNAME_REFERENCE; //OS doesn't support AVX } } break; case 4: switch (model) { case 5: case 6: //Haswell. Temp use Sandy Brdige if(support_avx()) { return CPUNAME_SANDYBRIDGE; }else{ return CPUNAME_REFERENCE; //OS doesn't support AVX } } break; } break; } }else if (vendor == VENDOR_AMD){ switch (family) { case 0xf: switch (extend_family) { case 6: switch (model) { case 1: if(support_avx()) return CPUNAME_BULLDOZER; else return CPUNAME_REFERENCE; //OS don't support AVX. case 2: if(support_avx()) return CPUNAME_PILEDRIVER; else return CPUNAME_REFERENCE; //OS don't support AVX. case 0: //Steamroller. Temp use Piledriver. if(support_avx()) return CPUNAME_PILEDRIVER; else return CPUNAME_REFERENCE; //OS don't support AVX. } } break; } } return CPUNAME_REFERENCE; }