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_PAE: 55 return edx & CPUID1_EDX_PAE; 56 case _CPUF_I386_PGE: 57 return edx & CPUID1_EDX_PGE; 58 case _CPUF_I386_APIC_ON_CHIP: 59 return edx & CPUID1_EDX_APIC_ON_CHIP; 60 case _CPUF_I386_TSC: 61 return edx & CPUID1_EDX_TSC; 62 case _CPUF_I386_FPU: 63 return edx & CPUID1_EDX_FPU; 64 #define SSE_FULL_EDX (CPUID1_EDX_FXSR | CPUID1_EDX_SSE | CPUID1_EDX_SSE2) 65 #define SSE_FULL_ECX (CPUID1_ECX_SSE3 | CPUID1_ECX_SSSE3 | \ 66 CPUID1_ECX_SSE4_1 | CPUID1_ECX_SSE4_2) 67 case _CPUF_I386_SSE1234_12: 68 return (edx & SSE_FULL_EDX) == SSE_FULL_EDX && 69 (ecx & SSE_FULL_ECX) == SSE_FULL_ECX; 70 case _CPUF_I386_FXSR: 71 return edx & CPUID1_EDX_FXSR; 72 case _CPUF_I386_SSE: 73 return edx & CPUID1_EDX_SSE; 74 case _CPUF_I386_SSE2: 75 return edx & CPUID1_EDX_SSE2; 76 case _CPUF_I386_SSE3: 77 return ecx & CPUID1_ECX_SSE3; 78 case _CPUF_I386_SSSE3: 79 return ecx & CPUID1_ECX_SSSE3; 80 case _CPUF_I386_SSE4_1: 81 return ecx & CPUID1_ECX_SSE4_1; 82 case _CPUF_I386_SSE4_2: 83 return ecx & CPUID1_ECX_SSE4_2; 84 case _CPUF_I386_HTT: 85 return edx & CPUID1_EDX_HTT; 86 case _CPUF_I386_HTT_MAX_NUM: 87 return (ebx >> 16) & 0xff; 88 case _CPUF_I386_SYSENTER: 89 if(!is_intel) return 0; 90 if(!(edx & CPUID1_EDX_SYSENTER)) return 0; 91 if(family == 6 && model < 3 && stepping < 3) return 0; 92 return 1; 93 case _CPUF_I386_SYSCALL: 94 if(!is_amd) return 0; 95 if(!(ef_edx & CPUID_EF_EDX_SYSENTER)) return 0; 96 return 1; 97 } 98 99 return 0; 100 } 101 102