diff options
Diffstat (limited to 'arch/x86/cpuid/Cpuid.cpp')
| -rw-r--r-- | arch/x86/cpuid/Cpuid.cpp | 381 |
1 files changed, 71 insertions, 310 deletions
diff --git a/arch/x86/cpuid/Cpuid.cpp b/arch/x86/cpuid/Cpuid.cpp index b246ef7..91d159f 100644 --- a/arch/x86/cpuid/Cpuid.cpp +++ b/arch/x86/cpuid/Cpuid.cpp @@ -1,345 +1,106 @@ -#include "Cpuinfo.h" +#include "Cpuid.h" +#include <MemoryOperations.h> - -inline Cpuinfo::cpuidFunctionIndex operator++(Cpuinfo::cpuidFunctionIndex& command) +bool cpuid::cpuidOutRegs::isNull() { - command = Cpuinfo::cpuidFunctionIndex(int(command) + 1); - switch(int(command)) - { - case 0x8: command = Cpuinfo::DirectCacheAccessInfo; break; - case 0xC: command = Cpuinfo::ExtendedStateInfo; break; - case 0xE: command = Cpuinfo::RDTMonitoring; break; - case 0x11: command = Cpuinfo::SGXInfo; break; - case 0x13: command = Cpuinfo::TraceInfo; break; - default: - { - uint32 commandInt(command); - if(commandInt > Cpuinfo::SOCInfo - and commandInt < Cpuinfo::UnimplementedStart) - { - command = Cpuinfo::UnimplementedStart; - } - else if(commandInt > Cpuinfo::UnimplementedStart - and commandInt < Cpuinfo::UnimplementedEnd) - { - command = Cpuinfo::UnimplementedEnd; - } - else if(commandInt > Cpuinfo::UnimplementedEnd - and commandInt < Cpuinfo::ExtendedCpuidStart) - { - command = Cpuinfo::ExtendedCpuidStart; - } - else if(commandInt > Cpuinfo::ExtendedCpuidEnd) - { - command = Cpuinfo::BasicInfo; - } - break; - } - }; - - return command; -}; + if(eax and ebx and ecx and edx) return false; + else return true; +} -Cpuinfo::Cpuinfo() +void cpuid::acquireInformation(cpuid::BasicInfo &cpuidRes) { - eax = ebx = ecx = edx = 0; - cpuidAvailable = CPUIDCHK(); - isBrandStringSupported = false; - maximumInputValue = maximumInputValueExtended = 0; - displayModel = displayFamily = stepping = 0; - brandIndex = clflushLineSize = maxNumberApicsIds = initialApicId = 0; - maxNumberProcessorsIds = 0; - currentCpuType = processorType::NotRead; - serialNumber = 0; + cpuidOutRegs regs = cpuid(cpuidRes.initVal); - MemoryOperations::set(vendorString, '\0', vendorStringSize); - MemoryOperations::set(brandString, '\0', brandStringSize); + cpuidRes.maxCmdForBasicInfo = regs.eax; + uint32 seqRegs[3] = {regs.ebx, regs.edx, regs.ecx}; + for(uint8 i = 0; i <= 3; i++) + { + MemoryOperations::copy( + &seqRegs[i], + cpuidRes.manufacturerString + sizeof(uint32) * i, + sizeof(uint32)); + } + cpuidRes.manufacturerString[12] = '\0'; - dataFilling(Cpuinfo::BasicInfo, Cpuinfo::ExtendedCpuidEnd); -}; +} -bool Cpuinfo::isEaxValueCorrect(const cpuidFunctionIndex eaxInitValue) +cpuid::cpuidOutRegs cpuid::cpuid(uint32 eax) { - if(!cpuidAvailable) return false; - - else if(eaxInitValue > maximumInputValue - and eaxInitValue < ExtendedCpuidStart) return false; + cpuidOutRegs out; + asm inline("mov %%eax, %[initValue]\n" + "cpuid" + : "=eax" (out.eax), "=ebx" (out.ebx), "=ecx" (out.ecx), + "=edx" (out.edx) + : [initValue] "r" (eax)); + return out; +} - else if(eaxInitValue > maximumInputValueExtended - and eaxInitValue > ExtendedCpuidStart) return false; - - else if(eaxInitValue == 0x8 - or eaxInitValue == 0xC - or eaxInitValue == 0xE - or eaxInitValue == 0x11 - or eaxInitValue == 0x13) return false; - - else return true; -}; - -void Cpuinfo::setBasicData() +cpuid::cpuidOutRegs cpuid::cpuid(uint32 eax, uint32 ecx) { - maximumInputValue = eax; - - uint32 vendorStringInt[3] = {ebx, edx, ecx}; - - MemoryOperations::copy(vendorStringInt, vendorString, sizeof(uint32) * 3); -}; + cpuidOutRegs out; + asm inline("mov %%eax, %[initValue]\n" + "mov %%ecx, %[addiValue]\n" + "cpuid" + : "=eax" (out.eax), "=ebx" (out.ebx), "=ecx" (out.ecx), + "=edx" (out.edx) + : [initValue] "r" (eax), [addiValue] "r" (ecx)); + return out; +} -void Cpuinfo::setVersionData() +void cpuid::acquireInformation(cpuid::VersionInfo &cpuidRes) { - uint8 steppingId, modelId, familyId, modelIdExt, familyIdExt; - - steppingId = eax & 0xf; - modelId = (eax >> 4) & 0xf; - familyId = (eax >> 8) & 0xf; - modelIdExt = (eax >> 16) & 0xf; - familyIdExt = (eax >> 20) & 0xf; - - stepping = steppingId; - currentCpuType = (processorType)((eax >> 12) & 0x3); + cpuidOutRegs regs = cpuid(cpuidRes.initVal); - if(familyId != 0xf) - { - displayFamily = familyId; - } - else displayFamily = familyIdExt + familyId; - - if(familyId == 0x6 or familyId == 0xf) - { - displayModel = (modelIdExt << 4) + modelId; - } - else displayModel = modelId; + cpuidRes.ecx = regs.ecx; + cpuidRes.edx = regs.edx; - brandIndex = (uint8)ebx; - clflushLineSize = ((uint8)(ebx >> 8)) << 3; - maxNumberProcessorsIds = (ebx >> 16) & 0x0F; - initialApicId = ebx >> 24; + cpuidRes.eax.steppingId = regs.eax; + cpuidRes.eax.modelId = regs.eax >> 4; + cpuidRes.eax.familyId = regs.eax >> 8; + cpuidRes.eax.processorType = regs.eax >> 12; + cpuidRes.eax.extendedModelId = regs.eax >> 16; + cpuidRes.eax.extendedFamilyId = regs.eax >> 20; +} - if(edx & Cpuinfo::HTT) - { - uint8 powerOfTwo = 1; - for(; powerOfTwo < maxNumberProcessorsIds; powerOfTwo *= 2); - if(maxNumberProcessorsIds == NULL) maxNumberApicsIds = NULL; - else maxNumberApicsIds = powerOfTwo; - } -}; - -void Cpuinfo::setInternalData() +void cpuid::acquireInformation(cpuid::ExtendedMaxInputValue &cpuidRes) { - uint32 regs[4] = {eax, ebx, ecx, edx}; - uint8 idxDesc = 0; + cpuidOutRegs regs = cpuid(cpuidRes.initVal); - for(uint8 idx = 0; idx < 4; idx++) - { - uint32 ® = regs[idx]; - for(uint8 bytes = 0; bytes < 4; bytes++) - { - internalInfoDescriptors[idxDesc++] = reg & 0xff; - reg >>= 8; - } - } + cpuidRes.eax = regs.eax; }; -void Cpuinfo::setSerialData() +void cpuid::acquireInformation(cpuid::ExtendedAddressSize &cpuidRes) { - if(cpuid(VersionInfo) - || !(edx & Cpuinfo::PSN) - || cpuid(SerialNumberInfo)) return; + cpuid::ExtendedMaxInputValue extendedMaxValDetails; + acquireInformation(extendedMaxValDetails); - serialNumber = ((uint64)ecx) | (((uint64)edx) << 32); -}; - -void Cpuinfo::setExtendedBasicData() -{ - if(eax & Cpuinfo::ExtendedBasicInfo) + if(extendedMaxValDetails.eax >= cpuidRes.initVal) { - maximumInputValueExtended = eax; - isBrandStringSupported = true; + cpuidOutRegs regs = cpuid(cpuidRes.initVal); + cpuidRes.eax.physicalAddressBits = regs.eax; + cpuidRes.eax.linearAddressBits = regs.eax >> 8; + cpuidRes.isWbnoinvdAvailable = regs.ebx >> 9; } - else isBrandStringSupported = false; + else cpuidRes.isValid = false; }; -void Cpuinfo::setBrandString(brandStringPart part) +uint8 cpuid::VersionInfo::getFamilyId() { - if((part == Cpuinfo::brandString_low or - part == Cpuinfo::brandString_middle or - part == Cpuinfo::brandString_hight) - and isBrandStringSupported) + if(eax.familyId != 0x0F) { - uint8 partUint = uint8(part); - uint32 regs[4] = {eax, ebx, ecx, edx}; - - MemoryOperations::copy(regs, &brandString[partUint], sizeof(uint32) * 4); + return eax.familyId; } + else return eax.extendedFamilyId + eax.familyId; }; -bool Cpuinfo::decodeCpuidResult(const cpuidFunctionIndex eaxValue) -{ - switch(eaxValue) - { - case Cpuinfo::BasicInfo: setBasicData(); break; - case Cpuinfo::VersionInfo: setVersionData(); break; - case Cpuinfo::InternalInfo: setInternalData(); break; - case Cpuinfo::SerialNumberInfo: setSerialData(); break; - case Cpuinfo::MonitorMwaitInfo: break; - case Cpuinfo::ThermalPowerInfo: break; - case Cpuinfo::DirectCacheAccessInfo: break; - case Cpuinfo::PerformanceMonitoring: break; - case Cpuinfo::ClockInfo: break; - case Cpuinfo::FrequencyInfo: break; - case Cpuinfo::ExtendedBasicInfo: setExtendedBasicData(); break; - case Cpuinfo::MoreFeatureInfo: break; - case Cpuinfo::BrandStringLow: setBrandString(brandString_low); break; - case Cpuinfo::BrandStringMiddle: setBrandString(brandString_middle); break; - case Cpuinfo::BrandStringHight: setBrandString(brandString_hight); break; - case Cpuinfo::CacheInfo: break; - case Cpuinfo::MiscFeatureInfo: break; - case Cpuinfo::AddressSize: break; - default: return true; break; - }; - - return false; -}; - -bool Cpuinfo::decodeCpuidCommand(const cpuidFunctionIndex eaxValue) +uint8 cpuid::VersionInfo::getModelId() { - if(cpuid(eaxValue)) - { - return true; - } - else + if(eax.familyId == 0x06 or eax.familyId == 0x0F) { - return decodeCpuidResult(eaxValue); + return (static_cast<uint8>(eax.extendedModelId) << 4) + + eax.modelId; } + else return eax.modelId; }; -bool Cpuinfo::cpuid(const cpuidFunctionIndex eaxValue) -{ - // Clear registers - eax = ebx = ecx = edx = 0; - - if(!isEaxValueCorrect(eaxValue) - or isCommandSupportSubLeaf(eaxValue)) return true; - - asm("movl %[eaxValue], %%eax\n\t" - "movl %0, %%eax\n\t" - "cpuid\n\t" - "movl %%eax, %0\n\t" - "movl %%ebx, %1\n\t" - "movl %%ecx, %2\n\t" - "movl %%edx, %3\n\t" - : "=r" (eax), "=r" (ebx), "=r" (ecx), "=r" (edx) - : [eaxValue] "r" (eaxValue)); - - return false; -}; - -bool Cpuinfo::cpuid(const cpuidFunctionIndex eaxValue, uint32 ecxValue) -{ - // Clear registers - eax = ebx = ecx = edx = 0; - - if(!isEaxValueCorrect(eaxValue) - or !isCommandSupportSubLeaf(eaxValue)) return true; - - asm("movl %[eaxValue], %%eax\n\t" - "movl %[ecxValue], %%ecx\n\t" - "cpuid\n\t" - "movl %%eax, %0\n\t" - "movl %%ebx, %1\n\t" - "movl %%ecx, %2\n\t" - "movl %%edx, %3\n\t" - : "=r" (eax), "=r" (ebx), "=r" (ecx), "=r" (edx) - : [eaxValue] "r" (eaxValue), [ecxValue] "r" (ecxValue)); - - return false; -}; - -bool Cpuinfo::isCommandSupportSubLeaf(const cpuidFunctionIndex eaxValue) -{ - switch(eaxValue) - { - case DeterministicCacheInfo: return true; break; - case FeatureInfo: return true; break; - case ExtendedTopologyInfo: return true; break; - case ExtendedStateInfo: return true; break; - case RDTMonitoring: return true; break; - case AllocationInfo: return true; break; - case SGXInfo: return true; break; - case TraceInfo: return true; break; - case SOCInfo: return true; break; - default: return false; break; - }; -}; - -const char* Cpuinfo::getVendorString() -{ - const char* vendorStringInvalid = "VendorStringInvalid"; - - if(maximumInputValue != NULL) return (const char *)vendorString; - else return vendorStringInvalid; -}; - -void Cpuinfo::dataFilling(cpuidFunctionIndex startValue, - cpuidFunctionIndex endValue) -{ - cpuidFunctionIndex command = startValue; - uint32 ecx = 0; - - do{ - if(isEaxValueCorrect(command)) - { - if(isCommandSupportSubLeaf(command)) - { - cpuid(command, ecx); - } - else decodeCpuidCommand(command); - } - }while(++command <= endValue and command != Cpuinfo::BasicInfo); -}; - -cpuidOutputRegisters Cpuinfo::getRegs() -{ - return {eax, ebx, ecx, edx}; -}; - -uint8 Cpuinfo::getDisplayFamily() -{ - return displayFamily; -}; - -uint8 Cpuinfo::getDisplayModel() -{ - return displayModel; -}; - -uint8 Cpuinfo::getStepping() -{ - return stepping; -}; - -Cpuinfo::processorType Cpuinfo::getProcessorType() -{ - return currentCpuType; -}; - -uint8 Cpuinfo::getMaxFunctionIndex() -{ - return maximumInputValue; -}; - -uint32 Cpuinfo::getMaxFunctionIndexExtended() -{ - return maximumInputValueExtended; -}; - -const char* Cpuinfo::getBrandString() -{ - return (const char*)brandString; -}; - -uint8* Cpuinfo::getInternalDescriptors() -{ - return internalInfoDescriptors; -}; +cpuid::Executor::Executor() : isCpuidAvailable(CPUIDCHK()) {}; |
