summaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/cpuid/Cpuid.cpp381
-rw-r--r--arch/x86/cpuid/Cpuid.h40
2 files changed, 110 insertions, 311 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 &reg = 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()) {};
diff --git a/arch/x86/cpuid/Cpuid.h b/arch/x86/cpuid/Cpuid.h
index 42fb692..a65cdc8 100644
--- a/arch/x86/cpuid/Cpuid.h
+++ b/arch/x86/cpuid/Cpuid.h
@@ -207,10 +207,46 @@ public:
SS = (1 << 27),
HTT = (1 << 28),
TM = (1 << 29),
- PBE = (1 << 31),
+ PBE = static_cast<uint32>(1 << 31),
};
};
+inline uint32 operator&(uint32 r, VersionInfo::EdxFlags flag)
+{
+ return r & static_cast<uint32>(flag);
+};
+
+inline uint32 operator&(uint32 r, cpuid::VersionInfo::EcxFlags flag)
+{
+ return r & static_cast<uint32>(flag);
+};
+
+struct ExtendedAddressSize : public CmdWithNoSubleaf
+{
+ constexpr static uint32 initialValue = 0x80000008;
+
+ ExtendedAddressSize() : CmdWithNoSubleaf(initialValue){};
+
+private:
+ struct AddressSize
+ {
+ uint8 physicalAddressBits,
+ linearAddressBits;
+ };
+
+public:
+ AddressSize eax;
+ bool isWbnoinvdAvailable;
+};
+
+struct ExtendedMaxInputValue : public CmdWithNoSubleaf
+{
+ constexpr static uint32 initialValue = 0x80000000;
+
+ ExtendedMaxInputValue() : CmdWithNoSubleaf(initialValue){};
+
+ uint32 eax;
+};
/**
* Getters are acquire information from cpuid instruction
@@ -221,6 +257,8 @@ public:
*/
void acquireInformation(BasicInfo &cpuidRes);
void acquireInformation(VersionInfo &cpuidRes);
+void acquireInformation(ExtendedAddressSize &cpuidRes);
+void acquireInformation(ExtendedMaxInputValue &cpuidRes);
/**
* Validators are check filling correctness for some cpuid command instance