/* ##### FUNCTION DEFINITIONS - LOCAL TO THIS SOURCE FILE ########### */ static int get_cpu_perf_data(void) { uint32_t eax = 0x0U, ebx = 0x0U, ecx = 0x0U, edx = 0x0U; int largest_function = 0; eax = 0x00; CPUID(eax, ebx, ecx, edx); largest_function = eax; if (cpuid_info.family == P6_FAMILY && 0x0A <= largest_function) { eax = 0x0A; CPUID(eax, ebx, ecx, edx); cpuid_info.perf_version = (eax&0xFFU); cpuid_info.perf_num_ctr = ((eax>>8)&0xFFU); cpuid_info.perf_width_ctr = ((eax>>16)&0xFFU); cpuid_info.perf_num_fixed_ctr = (edx&0xFU); eax = 0x06; CPUID(eax, ebx, ecx, edx); if (eax & (1<<1)) { cpuid_info.turbo = 1; } else { cpuid_info.turbo = 0; } }
static void cpuid_cpu_get_brand(struct cpuid *cpuid) { long int eax; long int ebx; long int ecx; long int edx; eax = 0x80000002; CPUID(eax, eax, ebx, ecx, edx); cpuid->cpu_brand[48] = 0; /* init cpu_brand to null-terminate the string */ char *ccb = cpuid->cpu_brand; *(int*)(ccb + 0 ) = (int)eax; *(int*)(ccb + 4 ) = ebx; *(int*)(ccb + 8 ) = ecx; *(int*)(ccb + 12) = edx; eax = 0x80000003; CPUID(eax, eax, ebx, ecx, edx); *(int*)(ccb + 16) = eax; *(int*)(ccb + 20) = ebx; *(int*)(ccb + 24) = ecx; *(int*)(ccb + 28) = edx; eax = 0x80000004; CPUID(eax, eax, ebx, ecx, edx); *(int*)(cpuid->cpu_brand + 32) = eax; *(int*)(cpuid->cpu_brand + 36) = ebx; *(int*)(cpuid->cpu_brand + 40) = ecx; *(int*)(cpuid->cpu_brand + 44) = edx; }
VOID NTAPI INIT_FUNCTION KiSetProcessorType(VOID) { ULONG EFlags, NewEFlags; ULONG Reg, Dummy; ULONG Stepping, Type; /* Start by assuming no CPUID data */ KeGetCurrentPrcb()->CpuID = 0; /* Save EFlags */ EFlags = __readeflags(); /* XOR out the ID bit and update EFlags */ NewEFlags = EFlags ^ EFLAGS_ID; __writeeflags(NewEFlags); /* Get them back and see if they were modified */ NewEFlags = __readeflags(); if (NewEFlags != EFlags) { /* The modification worked, so CPUID exists. Set the ID Bit again. */ EFlags |= EFLAGS_ID; __writeeflags(EFlags); /* Peform CPUID 0 to see if CPUID 1 is supported */ CPUID(0, &Reg, &Dummy, &Dummy, &Dummy); if (Reg > 0) { /* Do CPUID 1 now */ CPUID(1, &Reg, &Dummy, &Dummy, &Dummy); /* * Get the Stepping and Type. The stepping contains both the * Model and the Step, while the Type contains the returned Type. * We ignore the family. * * For the stepping, we convert this: zzzzzzxy into this: x0y */ Stepping = Reg & 0xF0; Stepping <<= 4; Stepping += (Reg & 0xFF); Stepping &= 0xF0F; Type = Reg & 0xF00; Type >>= 8; /* Save them in the PRCB */ KeGetCurrentPrcb()->CpuID = TRUE; KeGetCurrentPrcb()->CpuType = (UCHAR)Type; KeGetCurrentPrcb()->CpuStep = (USHORT)Stepping; }
void cpu_init_mwait(struct cpu_softc *sc) { unsigned int smallest, largest, extensions, c_substates; if ((cpu_ecxfeature & CPUIDECX_MWAIT) == 0 || cpuid_level < 0x5) return; /* get the monitor granularity */ CPUID(0x5, smallest, largest, extensions, cpu_mwait_states); smallest &= 0xffff; largest &= 0xffff; printf("%s: mwait min=%u, max=%u", sc->sc_dev.dv_xname, smallest, largest); if (extensions & 0x1) { if (cpu_mwait_states > 0) { c_substates = cpu_mwait_states; printf(", C-substates=%u", 0xf & c_substates); while ((c_substates >>= 4) > 0) printf(".%u", 0xf & c_substates); } if (extensions & 0x2) printf(", IBE"); } else {
void pvbus_hyperv(struct pvbus_hv *hv) { uint32_t regs[4]; CPUID(hv->hv_base + CPUID_OFFSET_HYPERV_FEATURES, regs[0], regs[1], regs[2], regs[3]); hv->hv_features = regs[0]; CPUID(hv->hv_base + CPUID_OFFSET_HYPERV_VERSION, regs[0], regs[1], regs[2], regs[3]); hv->hv_major = (regs[1] & HYPERV_VERSION_EBX_MAJOR_M) >> HYPERV_VERSION_EBX_MAJOR_S; hv->hv_minor = (regs[1] & HYPERV_VERSION_EBX_MINOR_M) >> HYPERV_VERSION_EBX_MINOR_S; }
static int IsWIL( void ) { unsigned regs[4]; // get CPU feature bits CPUID( 1, regs ); // bit 26 of EDX denotes WIL existence if ( regs[3] & ( 1 << 26 ) ) { // Ok, CPU supports this instruction, but does the OS? // // Test a WIL instruction and make sure you don't get an exception... // __try { __asm { pushad; // xorpd xmm0,xmm0; // Willamette New Instructions __emit 0x0f __emit 0x56 __emit 0xc9 popad; } }// If OS creates an exception, it doesn't support PentiumIV Instructions __except(EXCEPTION_EXECUTE_HANDLER) { // if(_exception_code()==STATUS_ILLEGAL_INSTRUCTION) // forget it, any exception should count as fail for safety return qfalse; // Willamette New Instructions not supported } return qtrue; // Williamette/P4 instructions available }
PetscErrorCode PetscSSEHardwareTest(PetscBool *flag) { PetscErrorCode ierr; char *vendor; char Intel[13]="GenuineIntel"; char AMD[13] ="AuthenticAMD"; PetscFunctionBegin; ierr = PetscMalloc(13*sizeof(char),&vendor);CHKERRQ(ierr); strcpy(vendor,"************"); CPUID_GET_VENDOR(vendor); if (!strcmp(vendor,Intel) || !strcmp(vendor,AMD)) { /* Both Intel and AMD use bit 25 of CPUID_FEATURES */ /* to denote availability of SSE Support */ unsigned long myeax,myebx,myecx,myedx; CPUID(CPUID_FEATURES,&myeax,&myebx,&myecx,&myedx); if (myedx & SSE_FEATURE_FLAG) { *flag = PETSC_TRUE; } else { *flag = PETSC_FALSE; } } ierr = PetscFree(vendor);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* ================ IsAMD ================ */ static bool IsAMD( void ) { char pstring[16]; char processorString[13]; // get name of processor CPUID( 0, ( unsigned int * ) pstring ); processorString[0] = pstring[4]; processorString[1] = pstring[5]; processorString[2] = pstring[6]; processorString[3] = pstring[7]; processorString[4] = pstring[12]; processorString[5] = pstring[13]; processorString[6] = pstring[14]; processorString[7] = pstring[15]; processorString[8] = pstring[8]; processorString[9] = pstring[9]; processorString[10] = pstring[10]; processorString[11] = pstring[11]; processorString[12] = 0; if ( strcmp( processorString, "AuthenticAMD" ) == 0 ) { return true; } return false; }
static int IsP3() { unsigned regs[4]; // get CPU feature bits CPUID( 1, regs ); if ( regs[0] < 6 ) { return qfalse; } if ( !( regs[3] & 0x1 ) ) { return qfalse; // fp } if ( !( regs[3] & 0x8000 ) ) { // cmov return qfalse; } if ( !( regs[3] & 0x800000 ) ) { // mmx return qfalse; } if ( !( regs[3] & 0x2000000 ) ) { // simd return qfalse; } return qtrue; }
/* ================ Has3DNow ================ */ static bool Has3DNow( void ) { unsigned regs[4]; // check AMD-specific functions CPUID( 0x80000000, regs ); if ( regs[_REG_EAX] < 0x80000000 ) { return false; } // bit 31 of EDX denotes 3DNow! support CPUID( 0x80000001, regs ); if ( regs[_REG_EDX] & ( 1 << 31 ) ) { return true; } return false; }
bool BurnCheckMMXSupport() { unsigned int nSignatureEAX = 0, nSignatureEBX = 0, nSignatureECX = 0, nSignatureEDX = 0; CPUID(1, nSignatureEAX, nSignatureEBX, nSignatureECX, nSignatureEDX); return (nSignatureEDX >> 23) & 1; // bit 23 of edx indicates MMX support }
void k8_powernow_init(struct cpu_info *ci) { uint64_t status; u_int maxfid, maxvid, i; u_int32_t extcpuid, dummy; struct k8pnow_cpu_state *cstate; struct k8pnow_state *state; char * techname = NULL; if (setperf_prio > 1) return; cstate = malloc(sizeof(struct k8pnow_cpu_state), M_DEVBUF, M_NOWAIT); if (!cstate) return; cstate->n_states = 0; status = rdmsr(MSR_AMDK7_FIDVID_STATUS); maxfid = PN8_STA_MFID(status); maxvid = PN8_STA_MVID(status); /* * If start FID is different to max FID, then it is a * mobile processor. If not, it is a low powered desktop * processor. */ if (PN8_STA_SFID(status) != PN8_STA_MFID(status)) techname = "PowerNow! K8"; else techname = "Cool'n'Quiet K8"; #if NACPICPU > 0 /* If we have acpi check acpi first */ if (!k8pnow_acpi_init(cstate, status)) #endif { if (!k8pnow_states(cstate, ci->ci_signature, maxfid, maxvid)) { /* Extended CPUID signature value */ CPUID(0x80000001, extcpuid, dummy, dummy, dummy); k8pnow_states(cstate, extcpuid, maxfid, maxvid); } } if (cstate->n_states) { printf("%s: %s %d MHz: speeds:", ci->ci_dev->dv_xname, techname, cpuspeed); for (i = cstate->n_states; i > 0; i--) { state = &cstate->state_table[i-1]; printf(" %d", state->freq); } printf(" MHz\n"); k8pnow_current_state = cstate; cpu_setperf = k8_powernow_setperf; setperf_prio = 1; return; } free(cstate, M_DEVBUF, sizeof(*cstate)); }
void vmx_supported(void) { uint32_t eax, ebx, ecx, edx; uint32_t value = 1; CPUID(value, &eax, &ebx, &ecx, &edx); printf("< CPUID >\n\teax: %x\n\tebx: %x\n\tecx: %x\n\tedx: %x\n", eax, ebx, ecx, edx); printf("VMX-operations supported:\t"); if ((ecx & (1 << 5)) == 1) { printf("[OK]\n"); } else { printf("[NO]\n"); } printf("SYSENTER and SYSEXIT supported:\t"); if ((edx & (1 << 11)) == 1) { printf("[OK]\n"); } else { printf("[NO]\n"); } value = 1; CPUID(value, &eax, &ebx, &ecx, &edx); printf("PAE-ext supported:\t\t"); if ((edx & (1 << 6)) == 1) { printf("[OK]\n"); } else { printf("[NO]\n"); } while (1) ; }
void pvbus_kvm(struct pvbus_hv *hv) { uint32_t regs[4]; CPUID(hv->hv_base + CPUID_OFFSET_KVM_FEATURES, regs[0], regs[1], regs[2], regs[3]); hv->hv_features = regs[0]; }
static int Is3DNOW(void) { unsigned regs[4]; char pstring[16]; char processorString[13]; // get name of processor CPUID(0, (unsigned int *) pstring); processorString[0] = pstring[4]; processorString[1] = pstring[5]; processorString[2] = pstring[6]; processorString[3] = pstring[7]; processorString[4] = pstring[12]; processorString[5] = pstring[13]; processorString[6] = pstring[14]; processorString[7] = pstring[15]; processorString[8] = pstring[8]; processorString[9] = pstring[9]; processorString[10] = pstring[10]; processorString[11] = pstring[11]; processorString[12] = 0; // REMOVED because you can have 3DNow! on non-AMD systems // if ( strcmp( processorString, "AuthenticAMD" ) ) // return qfalse; // check AMD-specific functions CPUID(0x80000000, regs); if(regs[0] < 0x80000000) { return qfalse; } // bit 31 of EDX denotes 3DNOW! support CPUID(0x80000001, regs); if(regs[3] & (1 << 31)) { return qtrue; } return qfalse; }
int rdrand_check_support() { unsigned int j; DWORD maxCPUID; CPUIDinfo info; int got_intel_cpu=0; CPUID( &info,0,0 ); if(memcmp( ( char * )( &info.EBX ), "Genu", 4 ) == 0 && memcmp( ( char * )( &info.EDX ), "ineI", 4 ) == 0 && memcmp( ( char * )( &info.ECX), "ntel", 4 ) == 0 ) { got_intel_cpu = 1; } if ( got_intel_cpu ) { CPUID(&info,1,0); if ( ( info.ECX & 0x40000000 ) == 0x40000000 ) return 1; } return 0; }
bool BurnCheckMMXSupport() { #ifndef BUILD_PSP unsigned int nSignatureEAX = 0, nSignatureEBX = 0, nSignatureECX = 0, nSignatureEDX = 0; CPUID(1, nSignatureEAX, nSignatureEBX, nSignatureECX, nSignatureEDX); return (nSignatureEDX >> 23) & 1; // bit 23 of edx indicates MMX support #else return false; #endif }
/* * microbench: timing setup * x: input vector * y: output vector * n: length of the input vector * dest: used to avoid deadcode eliminiation */ double microbench_exp( double * x, double * y, double *dest, size_t n) { int i, num_runs; double cycles; tsc_counter start, end; num_runs = NUM_RUNS; // Cache warm-up for at least CYCLES_REQUIRED cycles, // recording the required number of executions CPUID(); RDTSC(start); RDTSC(end); CPUID(); RDTSC(start); RDTSC(end); CPUID(); RDTSC(start); RDTSC(end); while(1) { CPUID(); RDTSC(start); for(i = 0; i < num_runs; i++) { exp_bench(x,y,n); } RDTSC(end); CPUID(); for (i = 0; i< n; i++) *dest += y[i]; //this is done to avoid dead code eliminiation cycles = ((double)COUNTER_DIFF(end, start)); if(cycles >= CYCLES_REQUIRED) break; num_runs *= 2; } //Measurement of the selected function CPUID(); RDTSC(start); for(i = 0; i < num_runs; i++) { exp_bench(x,y,n); } RDTSC(end); CPUID(); for (i = 0; i< n; i++) *dest += y[i]; //this is done to avoid dead code eliminiation cycles = ((double)COUNTER_DIFF(end, start)) / ((double) num_runs); return cycles; }
/* ================ HasSSE3 ================ */ static bool HasSSE3( void ) { unsigned regs[4]; // get CPU feature bits CPUID( 1, regs ); // bit 0 of ECX denotes SSE3 existence if ( regs[_REG_ECX] & ( 1 << 0 ) ) { return true; } return false; }
/* ================ HasSSE2 ================ */ static bool HasSSE2( void ) { unsigned regs[4]; // get CPU feature bits CPUID( 1, regs ); // bit 26 of EDX denotes SSE2 existence if ( regs[_REG_EDX] & ( 1 << 26 ) ) { return true; } return false; }
/* ================ HasCMOV ================ */ static bool HasCMOV( void ) { unsigned regs[4]; // get CPU feature bits CPUID( 1, regs ); // bit 15 of EDX denotes CMOV existence if ( regs[_REG_EDX] & ( 1 << 15 ) ) { return true; } return false; }
bool BurnCheckMMXSupport() { #if defined BUILD_X86_ASM UINT32 nSignatureEAX = 0, nSignatureEBX = 0, nSignatureECX = 0, nSignatureEDX = 0; CPUID(1, nSignatureEAX, nSignatureEBX, nSignatureECX, nSignatureEDX); return (nSignatureEDX >> 23) & 1; // bit 23 of edx indicates MMX support #else return 0; #endif }
static int IsMMX( void ) { unsigned regs[4]; // get CPU feature bits CPUID( 1, regs ); // bit 23 of EDX denotes MMX existence if ( regs[3] & ( 1 << 23 ) ) return qtrue; return qfalse; }
static int IsKNI( void ) { unsigned regs[4]; // get CPU feature bits CPUID( 1, regs ); // bit 25 of EDX denotes KNI existence if ( regs[3] & ( 1 << 25 ) ) { return qtrue; } return qfalse; }
void parse_cpuid(struct cpu *me) { struct cpuid cpuid; long int eax; long int ebx; long int ecx; long int edx; eax = 0x00; CPUID(eax, eax, ebx, ecx, edx); cpuid.max_basic_input_val = eax; memset(cpuid.manufacturer_string, 0, 13); char *ccb = cpuid.manufacturer_string; *(int*)(ccb + 0) = ebx; *(int*)(cpuid.manufacturer_string + 4) = edx; *(int*)(cpuid.manufacturer_string + 8) = ecx; if(cpuid.max_basic_input_val >= 1) cpuid_get_features(&cpuid); eax = 0x80000000; CPUID(eax, eax, ebx, ecx, edx); cpuid.max_ext_input_val = eax; memcpy(&(me->cpuid), &cpuid, sizeof(me->cpuid)); }
void identifycpu(struct cpu_info *ci) { u_int32_t dummy, val, pnfeatset; u_int32_t brand[12]; char mycpu_model[48]; int i; char *brandstr_from, *brandstr_to; int skipspace; CPUID(1, ci->ci_signature, val, dummy, ci->ci_feature_flags); CPUID(0x80000000, pnfeatset, dummy, dummy, dummy); if (pnfeatset >= 0x80000001) { u_int32_t ecx; CPUID(0x80000001, dummy, dummy, ecx, ci->ci_feature_eflags); /* Other bits may clash */ ci->ci_feature_flags |= (ci->ci_feature_eflags & CPUID_NXE); if (ci->ci_flags & CPUF_PRIMARY) ecpu_ecxfeature = ecx; /* Let cpu_fature be the common bits */ cpu_feature &= ci->ci_feature_flags; } CPUID(0x80000002, brand[0], brand[1], brand[2], brand[3]); CPUID(0x80000003, brand[4], brand[5], brand[6], brand[7]); CPUID(0x80000004, brand[8], brand[9], brand[10], brand[11]); strlcpy(mycpu_model, (char *)brand, sizeof(mycpu_model)); /* Remove leading and duplicated spaces from mycpu_model */ brandstr_from = brandstr_to = mycpu_model; skipspace = 1; while (*brandstr_from != '\0') { if (!skipspace || *brandstr_from != ' ') { skipspace = 0; *(brandstr_to++) = *brandstr_from; } if (*brandstr_from == ' ') skipspace = 1; brandstr_from++; } *brandstr_to = '\0'; if (mycpu_model[0] == 0) strlcpy(mycpu_model, "Opteron or Athlon 64", sizeof(mycpu_model)); /* If primary cpu, fill in the global cpu_model used by sysctl */ if (ci->ci_flags & CPUF_PRIMARY) strlcpy(cpu_model, mycpu_model, sizeof(cpu_model)); ci->ci_family = (ci->ci_signature >> 8) & 0x0f; ci->ci_model = (ci->ci_signature >> 4) & 0x0f; if (ci->ci_family == 0x6 || ci->ci_family == 0xf) { ci->ci_family += (ci->ci_signature >> 20) & 0xff; ci->ci_model += ((ci->ci_signature >> 16) & 0x0f) << 4; }
static unsigned int GetCPUId(void) { unsigned int retval; _asm { mov eax,1 _emit 0x0f ; CPUID (00001111 10100010) - This is a Pentium ; specific instruction which gets information on the _emit 0xa2 ; processor. A Pentium family processor should set ; bits 11-8 of eax to 5. mov retval,edx } return retval; }
static void cpuid_get_features(struct cpuid *cpuid) { long int eax; long int ebx; long int ecx; long int edx; eax = 0x01; CPUID(eax, eax, ebx, ecx, edx); /* if no LAPIC is present, the INIT IPI will fail. */ cpuid->features_edx = edx; cpuid->features_ecx = ecx; cpuid->stepping = (eax & 0x0F); cpuid->model = ((eax >> 4) & 0x0F); cpuid->family = ((eax >> 8) & 0x0F); cpuid->type = ((eax >> 12) & 0x03); cpuid->cache_line_size = ((ebx >> 8) & 0xFF) * 8; /* cache_line_size * 8 = size in bytes */ cpuid->logical_processors = ((ebx >> 16) & 0xFF); /* # logical cpu's per physical cpu */ cpuid->lapic_id = ((ebx >> 24) & 0xFF); /* Local APIC ID */ eax = 0x80000001; CPUID(eax, eax, ebx, ecx, edx); cpuid->ext_features_edx = edx; cpuid->ext_features_ecx = ecx; }
void pvbus_xen(struct pvbus_hv *hv) { uint32_t regs[4]; CPUID(hv->hv_base + CPUID_OFFSET_XEN_VERSION, regs[0], regs[1], regs[2], regs[3]); hv->hv_major = regs[0] >> XEN_VERSION_MAJOR_S; hv->hv_minor = regs[0] & XEN_VERSION_MINOR_M; /* x2apic is broken in Xen 4.2 or older */ if ((hv->hv_major < 4) || (hv->hv_major == 4 && hv->hv_minor < 3)) { /* Remove CPU flag for x2apic */ cpu_ecxfeature &= ~CPUIDECX_X2APIC; } }
void identifycpu(struct cpu_info *ci) { u_int64_t last_tsc; u_int32_t dummy, val, pnfeatset; u_int32_t brand[12]; u_int32_t vendor[4]; int i, max; char *brandstr_from, *brandstr_to; int skipspace; CPUID(1, ci->ci_signature, val, dummy, ci->ci_feature_flags); CPUID(0x80000000, pnfeatset, dummy, dummy, dummy); CPUID(0x80000001, dummy, dummy, dummy, ci->ci_feature_eflags); vendor[3] = 0; CPUID(0, dummy, vendor[0], vendor[2], vendor[1]); /* yup, 0 2 1 */ CPUID(0x80000002, brand[0], brand[1], brand[2], brand[3]); CPUID(0x80000003, brand[4], brand[5], brand[6], brand[7]); CPUID(0x80000004, brand[8], brand[9], brand[10], brand[11]); strlcpy(cpu_model, (char *)brand, sizeof(cpu_model)); /* Remove leading and duplicated spaces from cpu_model */ brandstr_from = brandstr_to = cpu_model; skipspace = 1; while (*brandstr_from != '\0') { if (!skipspace || *brandstr_from != ' ') { skipspace = 0; *(brandstr_to++) = *brandstr_from; } if (*brandstr_from == ' ') skipspace = 1; brandstr_from++; } *brandstr_to = '\0'; if (cpu_model[0] == 0) strlcpy(cpu_model, "Opteron or Athlon 64", sizeof(cpu_model)); ci->ci_family = (ci->ci_signature >> 8) & 0x0f; ci->ci_model = (ci->ci_signature >> 4) & 0x0f; if (ci->ci_family == 0x6 || ci->ci_family == 0xf) { ci->ci_family += (ci->ci_signature >> 20) & 0xff; ci->ci_model += ((ci->ci_signature >> 16) & 0x0f) << 4; }