Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/google/cpu_features.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/impl_x86__base_implementation.inl')
-rw-r--r--src/impl_x86__base_implementation.inl111
1 files changed, 111 insertions, 0 deletions
diff --git a/src/impl_x86__base_implementation.inl b/src/impl_x86__base_implementation.inl
index 7d4c34f..c34d2cf 100644
--- a/src/impl_x86__base_implementation.inl
+++ b/src/impl_x86__base_implementation.inl
@@ -1689,6 +1689,115 @@ static void ParseCacheInfo(const int max_cpuid_leaf, uint32_t leaf_id,
if (info.size > 0) *old_info = info;
}
+typedef struct {
+ int level;
+ int cache_id;
+ CacheType cache_type;
+} CacheLevelInfoLegacyAMD;
+
+static int GetWaysLegacyAMD(int cache_level, const uint32_t cache_id) {
+ // https://www.amd.com/system/files/TechDocs/25481.pdf page 23
+ // CPUID.8000_0005_ECX[23:16] L1 data cache associativity.
+ // CPUID.8000_0005_EDX[23:16] L1 instruction cache associativity.
+ if (cache_level == 1) {
+ return ExtractBitRange(cache_id, 23, 16);
+ }
+ // https://www.amd.com/system/files/TechDocs/25481.pdf page 24
+ // See Table 4: L2/L3 Cache and TLB Associativity Field Definition.
+ // CPUID.8000_0006_ECX[15:12] L2 cache associativity.
+ // CPUID.8000_0006_EDX[15:12] L3 cache associativity.
+ const int ways = ExtractBitRange(cache_id, 15, 12);
+ switch (ways) {
+ case 0x0:
+ case 0x1:
+ case 0x2:
+ case 0x4:
+ return ways;
+ case 0x6:
+ return 8;
+ case 0x8:
+ return 16;
+ case 0xA:
+ return 32;
+ case 0xB:
+ return 48;
+ case 0xC:
+ return 64;
+ case 0xD:
+ return 96;
+ case 0xE:
+ return 128;
+ case 0xF:
+ return 255;
+ default:
+ return -1; // Reserved
+ }
+}
+
+static int GetCacheSizeLegacyAMD(int cache_level, const uint32_t cache_id) {
+ switch (cache_level) {
+ case 1:
+ // https://www.amd.com/system/files/TechDocs/25481.pdf page 23
+ // CPUID.8000_0005_ECX[31:24] L1 data cache size in KB.
+ // CPUID.8000_0005_EDX[31:24] L1 instruction cache size KB.
+ return ExtractBitRange(cache_id, 31, 24);
+ case 2:
+ // https://www.amd.com/system/files/TechDocs/25481.pdf page 25
+ // CPUID.8000_0006_ECX[31:16] L2 cache size in KB.
+ return ExtractBitRange(cache_id, 31, 16);
+ case 3:
+ // https://www.amd.com/system/files/TechDocs/25481.pdf page 25
+ // CPUID.8000_0006_EDX[31:18] L3 cache size.
+ // Specifies the L3 cache size is within the following range:
+ // (L3Size[31:18] * 512KB) <= L3 cache size < ((L3Size[31:18]+1) * 512KB).
+ return ExtractBitRange(cache_id, 31, 18) * 512;
+ default:
+ return 0;
+ }
+}
+
+#define LEGACY_AMD_MAX_CACHE_LEVEL 4
+
+// https://www.amd.com/system/files/TechDocs/25481.pdf
+// CPUID Fn8000_0005_E[A,B,C,D]X, Fn8000_0006_E[A,B,C,D]X - TLB and Cache info
+static void ParseCacheInfoLegacyAMD(const uint32_t max_ext, CacheInfo* info) {
+ const Leaf cache_tlb_leaf1 = SafeCpuIdEx(max_ext, 0x80000005, 0);
+ const Leaf cache_tlb_leaf2 = SafeCpuIdEx(max_ext, 0x80000006, 0);
+
+ const CacheLevelInfoLegacyAMD legacy_cache_info[LEGACY_AMD_MAX_CACHE_LEVEL] =
+ {(CacheLevelInfoLegacyAMD){.cache_id = cache_tlb_leaf1.ecx,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .level = 1},
+ (CacheLevelInfoLegacyAMD){.cache_id = cache_tlb_leaf1.edx,
+ .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+ .level = 1},
+ (CacheLevelInfoLegacyAMD){.cache_id = cache_tlb_leaf2.ecx,
+ .cache_type = CPU_FEATURE_CACHE_UNIFIED,
+ .level = 2},
+ (CacheLevelInfoLegacyAMD){.cache_id = cache_tlb_leaf2.edx,
+ .cache_type = CPU_FEATURE_CACHE_UNIFIED,
+ .level = 3}};
+
+ const int KiB = 1024;
+ const int UNDEF = -1;
+ for (int i = 0; i < LEGACY_AMD_MAX_CACHE_LEVEL; ++i) {
+ const int level = legacy_cache_info[i].level;
+ const int cache_id = legacy_cache_info[i].cache_id;
+ const CacheType cache_type = legacy_cache_info[i].cache_type;
+ const int cache_size = GetCacheSizeLegacyAMD(level, cache_id);
+ if (cache_size == 0) break;
+ info->levels[i] =
+ (CacheLevelInfo){.level = level,
+ .cache_type = cache_type,
+ .cache_size = cache_size * KiB,
+ .ways = GetWaysLegacyAMD(level, cache_id),
+ .line_size = ExtractBitRange(cache_id, 7, 0),
+ .tlb_entries = UNDEF,
+ .partitioning = UNDEF};
+ ++info->size;
+ }
+}
+
CacheInfo GetX86CacheInfo(void) {
CacheInfo info = kEmptyCacheInfo;
const Leaves leaves = ReadLeaves();
@@ -1704,6 +1813,8 @@ CacheInfo GetX86CacheInfo(void) {
// https://www.amd.com/system/files/TechDocs/25481.pdf
if (IsBitSet(leaves.leaf_80000001.ecx, 22)) {
ParseCacheInfo(leaves.max_cpuid_leaf_ext, 0x8000001D, &info);
+ } else {
+ ParseCacheInfoLegacyAMD(leaves.max_cpuid_leaf_ext, &info);
}
}
return info;