1 #include <sys/types.h> 2 #include <stdint.h> 3 #include <minix/minlib.h> 4 #include <minix/cpufeature.h> 5 #include <machine/vm.h> 6 #include <string.h> 7 8 int _cpufeature(int cpufeature) 9 { 10 u32_t eax, ebx, ecx, edx; 11 u32_t ef_eax = 0, ef_ebx = 0, ef_ecx = 0, ef_edx = 0; 12 unsigned int family, model, stepping; 13 int is_intel = 0, is_amd = 0; 14 15 eax = ebx = ecx = edx = 0; 16 17 /* We assume >= pentium for cpuid */ 18 eax = 0; 19 _cpuid(&eax, &ebx, &ecx, &edx); 20 if(eax > 0) { 21 char vendor[12]; 22 memcpy(vendor, &ebx, sizeof(ebx)); 23 memcpy(vendor+4, &edx, sizeof(edx)); 24 memcpy(vendor+8, &ecx, sizeof(ecx)); 25 if(!strncmp(vendor, "GenuineIntel", sizeof(vendor))) 26 is_intel = 1; 27 if(!strncmp(vendor, "AuthenticAMD", sizeof(vendor))) 28 is_amd = 1; 29 eax = 1; 30 _cpuid(&eax, &ebx, &ecx, &edx); 31 } else return 0; 32 33 stepping = eax & 0xf; 34 model = (eax >> 4) & 0xf; 35 36 if(model == 0xf || model == 0x6) { 37 model += ((eax >> 16) & 0xf) << 4; 38 } 39 40 family = (eax >> 8) & 0xf; 41 42 if(family == 0xf) { 43 family += (eax >> 20) & 0xff; 44 } 45 46 if(is_amd) { 47 ef_eax = 0x80000001; 48 _cpuid(&ef_eax, &ef_ebx, &ef_ecx, &ef_edx); 49 } 50 51 switch(cpufeature) { 52 case _CPUF_I386_PSE: 53 return edx & CPUID1_EDX_PSE; 54 case _CPUF_I386_PGE: 55 return edx & CPUID1_EDX_PGE; 56 case _CPUF_I386_APIC_ON_CHIP: 57 return edx & CPUID1_EDX_APIC_ON_CHIP; 58 case _CPUF_I386_TSC: 59 return edx & CPUID1_EDX_TSC; 60 case _CPUF_I386_FPU: 61 return edx & CPUID1_EDX_FPU; 62 #define SSE_FULL_EDX (CPUID1_EDX_FXSR | CPUID1_EDX_SSE | CPUID1_EDX_SSE2) 63 #define SSE_FULL_ECX (CPUID1_ECX_SSE3 | CPUID1_ECX_SSSE3 | \ 64 CPUID1_ECX_SSE4_1 | CPUID1_ECX_SSE4_2) 65 case _CPUF_I386_SSE1234_12: 66 return (edx & SSE_FULL_EDX) == SSE_FULL_EDX && 67 (ecx & SSE_FULL_ECX) == SSE_FULL_ECX; 68 case _CPUF_I386_FXSR: 69 return edx & CPUID1_EDX_FXSR; 70 case _CPUF_I386_SSE: 71 return edx & CPUID1_EDX_SSE; 72 case _CPUF_I386_SSE2: 73 return edx & CPUID1_EDX_SSE2; 74 case _CPUF_I386_SSE3: 75 return ecx & CPUID1_ECX_SSE3; 76 case _CPUF_I386_SSSE3: 77 return ecx & CPUID1_ECX_SSSE3; 78 case _CPUF_I386_SSE4_1: 79 return ecx & CPUID1_ECX_SSE4_1; 80 case _CPUF_I386_SSE4_2: 81 return ecx & CPUID1_ECX_SSE4_2; 82 case _CPUF_I386_HTT: 83 return edx & CPUID1_EDX_HTT; 84 case _CPUF_I386_HTT_MAX_NUM: 85 return (ebx >> 16) & 0xff; 86 case _CPUF_I386_SYSENTER: 87 if(!is_intel) return 0; 88 if(!(edx & CPUID1_EDX_SYSENTER)) return 0; 89 if(family == 6 && model < 3 && stepping < 3) return 0; 90 return 1; 91 case _CPUF_I386_SYSCALL: 92 if(!is_amd) return 0; 93 if(!(ef_edx & CPUID_EF_EDX_SYSENTER)) return 0; 94 return 1; 95 } 96 97 return 0; 98 } 99 100