summaryrefslogtreecommitdiff
path: root/src/arch/x86/cpu_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86/cpu_common.c')
-rw-r--r--src/arch/x86/cpu_common.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/src/arch/x86/cpu_common.c b/src/arch/x86/cpu_common.c
index 77d08c4196..835cddd686 100644
--- a/src/arch/x86/cpu_common.c
+++ b/src/arch/x86/cpu_common.c
@@ -82,3 +82,135 @@ uint32_t cpu_get_feature_flags_edx(void)
{
return cpuid_edx(1);
}
+
+enum cpu_type cpu_check_deterministic_cache_cpuid_supported(void)
+{
+ struct cpuid_result res;
+
+ if (cpu_is_intel()) {
+ res = cpuid(0);
+ if (res.eax < 4)
+ return CPUID_COMMAND_UNSUPPORTED;
+ return CPUID_TYPE_INTEL;
+ } else if (cpu_is_amd()) {
+ res = cpuid(0x80000000);
+ if (res.eax < 0x80000001)
+ return CPUID_COMMAND_UNSUPPORTED;
+
+ res = cpuid(0x80000001);
+ if (!(res.ecx & (1 << 22)))
+ return CPUID_COMMAND_UNSUPPORTED;
+
+ return CPUID_TYPE_AMD;
+ } else {
+ return CPUID_TYPE_INVALID;
+ }
+}
+
+static uint32_t cpu_get_cache_info_leaf(void)
+{
+ switch (cpu_check_deterministic_cache_cpuid_supported()) {
+ case CPUID_TYPE_AMD:
+ return DETERMINISTIC_CACHE_PARAMETERS_CPUID_AMD;
+ case CPUID_TYPE_INTEL:
+ return DETERMINISTIC_CACHE_PARAMETERS_CPUID_IA;
+ default:
+ return 0;
+ }
+}
+
+size_t cpu_get_cache_ways_assoc_info(const struct cpu_cache_info *info)
+{
+ if (!info)
+ return 0;
+
+ return info->num_ways;
+}
+
+uint8_t cpu_get_cache_type(const struct cpu_cache_info *info)
+{
+ if (!info)
+ return 0;
+
+ return info->type;
+}
+
+uint8_t cpu_get_cache_level(const struct cpu_cache_info *info)
+{
+ if (!info)
+ return 0;
+
+ return info->level;
+}
+
+size_t cpu_get_cache_phy_partition_info(const struct cpu_cache_info *info)
+{
+ if (!info)
+ return 0;
+
+ return info->physical_partitions;
+}
+
+size_t cpu_get_cache_line_size(const struct cpu_cache_info *info)
+{
+ if (!info)
+ return 0;
+
+ return info->line_size;
+}
+
+size_t cpu_get_cache_sets(const struct cpu_cache_info *info)
+{
+ if (!info)
+ return 0;
+
+ return info->num_sets;
+}
+
+bool cpu_is_cache_full_assoc(const struct cpu_cache_info *info)
+{
+ if (!info)
+ return false;
+
+ return info->fully_associative;
+}
+
+size_t cpu_get_max_cache_share(const struct cpu_cache_info *info)
+{
+ if (!info)
+ return 0;
+
+ return info->num_cores_shared;
+}
+
+size_t get_cache_size(const struct cpu_cache_info *info)
+{
+ if (!info)
+ return 0;
+
+ return info->num_ways * info->physical_partitions * info->line_size * info->num_sets;
+}
+
+bool fill_cpu_cache_info(uint8_t level, struct cpu_cache_info *info)
+{
+ if (!info)
+ return false;
+
+ uint32_t leaf = cpu_get_cache_info_leaf();
+ if (!leaf)
+ return false;
+
+ struct cpuid_result cache_info_res = cpuid_ext(leaf, level);
+
+ info->type = CPUID_CACHE_TYPE(cache_info_res);
+ info->level = CPUID_CACHE_LEVEL(cache_info_res);
+ info->num_ways = CPUID_CACHE_WAYS_OF_ASSOC(cache_info_res) + 1;
+ info->num_sets = CPUID_CACHE_NO_OF_SETS(cache_info_res) + 1;
+ info->line_size = CPUID_CACHE_COHER_LINE(cache_info_res) + 1;
+ info->physical_partitions = CPUID_CACHE_PHYS_LINE(cache_info_res) + 1;
+ info->num_cores_shared = CPUID_CACHE_SHARING_CACHE(cache_info_res) + 1;
+ info->fully_associative = CPUID_CACHE_FULL_ASSOC(cache_info_res);
+ info->size = get_cache_size(info);
+
+ return true;
+}