1
0
mirror of https://github.com/google/cpu_features.git synced 2025-07-01 05:11:15 +02:00

Add cache info for new AMD CPUs (0x8000001D) (#171)

This commit is contained in:
Nikolay Hohsadze
2021-10-18 15:14:29 +03:00
committed by GitHub
parent 2939ece4d2
commit 0925f6953c
3 changed files with 136 additions and 15 deletions

View File

@ -256,6 +256,10 @@ static int IsVendor(const Leaf leaf, const char* const name) {
return leaf.ebx == ebx && leaf.ecx == ecx && leaf.edx == edx;
}
static int IsVendorByX86Info(const X86Info* info, const char* const name) {
return memcmp(info->vendor, name, sizeof(info->vendor)) == 0;
}
static const CacheLevelInfo kEmptyCacheLevelInfo;
static CacheLevelInfo GetCacheLevelInfo(const uint32_t reg) {
@ -1140,10 +1144,13 @@ static void ParseLeaf2(const int max_cpuid_leaf, CacheInfo* info) {
}
}
static void ParseLeaf4(const int max_cpuid_leaf, CacheInfo* info) {
// For newer Intel CPUs uses "CPUID, eax=0x00000004".
// For newer AMD CPUs uses "CPUID, eax=0x8000001D"
static void ParseCacheInfo(const int max_cpuid_leaf, uint32_t leaf_id,
CacheInfo* info) {
info->size = 0;
for (int cache_id = 0; cache_id < CPU_FEATURES_MAX_CACHE_LEVEL; cache_id++) {
const Leaf leaf = SafeCpuIdEx(max_cpuid_leaf, 4, cache_id);
const Leaf leaf = SafeCpuIdEx(max_cpuid_leaf, leaf_id, cache_id);
CacheType cache_type = ExtractBitRange(leaf.eax, 4, 0);
if (cache_type == CPU_FEATURE_CACHE_NULL) {
info->levels[cache_id] = kEmptyCacheLevelInfo;
@ -1402,10 +1409,13 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info,
// Reference
// https://en.wikipedia.org/wiki/CPUID#EAX=80000000h:_Get_Highest_Extended_Function_Implemented.
static Leaf GetLeafByIdAMD(uint32_t leaf_id) {
uint32_t max_extended = CpuId(0x80000000).eax;
return SafeCpuId(max_extended, leaf_id);
}
static void ParseExtraAMDCpuId(X86Info* info, OsPreserves os_preserves) {
const Leaf leaf_80000000 = CpuId(0x80000000);
const uint32_t max_extended_cpuid_leaf = leaf_80000000.eax;
const Leaf leaf_80000001 = SafeCpuId(max_extended_cpuid_leaf, 0x80000001);
const Leaf leaf_80000001 = GetLeafByIdAMD(0x80000001);
X86Features* const features = &info->features;
@ -1425,9 +1435,9 @@ static const OsPreserves kEmptyOsPreserves;
X86Info GetX86Info(void) {
X86Info info = kEmptyX86Info;
const Leaf leaf_0 = CpuId(0);
const bool is_intel = IsVendor(leaf_0, "GenuineIntel");
const bool is_amd = IsVendor(leaf_0, "AuthenticAMD");
const bool is_hygon = IsVendor(leaf_0, "HygonGenuine");
const bool is_intel = IsVendor(leaf_0, CPU_FEATURES_VENDOR_GENUINE_INTEL);
const bool is_amd = IsVendor(leaf_0, CPU_FEATURES_VENDOR_AUTHENTIC_AMD);
const bool is_hygon = IsVendor(leaf_0, CPU_FEATURES_VENDOR_HYGON_GENUINE);
SetVendor(leaf_0, info.vendor);
if (is_intel || is_amd || is_hygon) {
OsPreserves os_preserves = kEmptyOsPreserves;
@ -1443,10 +1453,20 @@ X86Info GetX86Info(void) {
CacheInfo GetX86CacheInfo(void) {
CacheInfo info = kEmptyCacheInfo;
const Leaf leaf_0 = CpuId(0);
const uint32_t max_cpuid_leaf = leaf_0.eax;
if (IsVendor(leaf_0, "GenuineIntel")) {
ParseLeaf2(max_cpuid_leaf, &info);
ParseLeaf4(max_cpuid_leaf, &info);
if (IsVendor(leaf_0, CPU_FEATURES_VENDOR_GENUINE_INTEL)) {
ParseLeaf2(leaf_0.eax, &info);
ParseCacheInfo(leaf_0.eax, 4, &info);
} else if (IsVendor(leaf_0, CPU_FEATURES_VENDOR_AUTHENTIC_AMD) ||
IsVendor(leaf_0, CPU_FEATURES_VENDOR_HYGON_GENUINE)) {
const uint32_t max_ext = CpuId(0x80000000).eax;
const uint32_t cpuid_ext = SafeCpuId(max_ext, 0x80000001).ecx;
// If CPUID Fn8000_0001_ECX[TopologyExtensions]==0
// then CPUID Fn8000_0001_E[D,C,B,A]X is reserved.
// https://www.amd.com/system/files/TechDocs/25481.pdf
if (IsBitSet(cpuid_ext, 22)) {
ParseCacheInfo(max_ext, 0x8000001D, &info);
}
}
return info;
}
@ -1454,7 +1474,7 @@ CacheInfo GetX86CacheInfo(void) {
#define CPUID(FAMILY, MODEL) ((((FAMILY)&0xFF) << 8) | ((MODEL)&0xFF))
X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
if (memcmp(info->vendor, "GenuineIntel", sizeof(info->vendor)) == 0) {
if (IsVendorByX86Info(info, CPU_FEATURES_VENDOR_GENUINE_INTEL)) {
switch (CPUID(info->family, info->model)) {
case CPUID(0x06, 0x1C): // Intel(R) Atom(TM) CPU 230 @ 1.60GHz
case CPUID(0x06, 0x35):
@ -1553,7 +1573,7 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
return X86_UNKNOWN;
}
}
if (memcmp(info->vendor, "AuthenticAMD", sizeof(info->vendor)) == 0) {
if (IsVendorByX86Info(info, CPU_FEATURES_VENDOR_AUTHENTIC_AMD)) {
switch (CPUID(info->family, info->model)) {
// https://en.wikichip.org/wiki/amd/cpuid
case CPUID(0xF, 0x04):
@ -1661,7 +1681,7 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
return X86_UNKNOWN;
}
}
if (memcmp(info->vendor, "HygonGenuine", sizeof(info->vendor)) == 0) {
if (IsVendorByX86Info(info, CPU_FEATURES_VENDOR_HYGON_GENUINE)) {
switch (CPUID(info->family, info->model)) {
case CPUID(0x18, 0x00):
return AMD_ZEN;