1 /* SPDX-License-Identifier: GPL-2.0-only */
6 /* Standard macro to see if a specific flag is changeable */
7 static inline int flag_is_changeable_p(uint32_t flag
)
22 : "=&r" (f1
), "=&r" (f2
)
24 return ((f1
^f2
) & flag
) != 0;
27 /* Probe for the CPUID instruction */
28 int cpu_have_cpuid(void)
30 return flag_is_changeable_p(X86_EFLAGS_ID
);
35 int cpu_have_cpuid(void)
41 unsigned int cpu_cpuid_extended_level(void)
43 return cpuid_eax(0x80000000);
46 int cpu_phys_address_size(void)
48 if (!(cpu_have_cpuid()))
51 if (cpu_cpuid_extended_level() >= 0x80000008)
52 return cpuid_eax(0x80000008) & 0xff;
54 if (cpuid_edx(1) & (CPUID_FEATURE_PAE
| CPUID_FEATURE_PSE36
))
60 * Get processor id using cpuid eax=1
61 * return value in EAX register
63 uint32_t cpu_get_cpuid(void)
69 * Get processor feature flag using cpuid eax=1
70 * return value in ECX register
72 uint32_t cpu_get_feature_flags_ecx(void)
78 * Get processor feature flag using cpuid eax=1
79 * return value in EDX register
81 uint32_t cpu_get_feature_flags_edx(void)
86 enum cpu_type
cpu_check_deterministic_cache_cpuid_supported(void)
88 struct cpuid_result res
;
93 return CPUID_COMMAND_UNSUPPORTED
;
94 return CPUID_TYPE_INTEL
;
95 } else if (cpu_is_amd()) {
96 res
= cpuid(0x80000000);
97 if (res
.eax
< 0x80000001)
98 return CPUID_COMMAND_UNSUPPORTED
;
100 res
= cpuid(0x80000001);
101 if (!(res
.ecx
& (1 << 22)))
102 return CPUID_COMMAND_UNSUPPORTED
;
104 return CPUID_TYPE_AMD
;
106 return CPUID_TYPE_INVALID
;
110 static uint32_t cpu_get_cache_info_leaf(void)
112 uint32_t leaf
= (cpu_check_deterministic_cache_cpuid_supported() == CPUID_TYPE_AMD
) ?
113 DETERMINISTIC_CACHE_PARAMETERS_CPUID_AMD
:
114 DETERMINISTIC_CACHE_PARAMETERS_CPUID_IA
;
119 size_t cpu_get_cache_ways_assoc_info(const struct cpu_cache_info
*info
)
124 return info
->num_ways
;
127 uint8_t cpu_get_cache_type(const struct cpu_cache_info
*info
)
135 uint8_t cpu_get_cache_level(const struct cpu_cache_info
*info
)
143 size_t cpu_get_cache_phy_partition_info(const struct cpu_cache_info
*info
)
148 return info
->physical_partitions
;
151 size_t cpu_get_cache_line_size(const struct cpu_cache_info
*info
)
156 return info
->line_size
;
159 size_t cpu_get_cache_sets(const struct cpu_cache_info
*info
)
164 return info
->num_sets
;
167 bool cpu_is_cache_full_assoc(const struct cpu_cache_info
*info
)
172 return info
->fully_associative
;
175 size_t cpu_get_max_cache_share(const struct cpu_cache_info
*info
)
180 return info
->num_cores_shared
;
183 size_t get_cache_size(const struct cpu_cache_info
*info
)
188 return info
->num_ways
* info
->physical_partitions
* info
->line_size
* info
->num_sets
;
191 bool fill_cpu_cache_info(uint8_t level
, struct cpu_cache_info
*info
)
196 uint32_t leaf
= cpu_get_cache_info_leaf();
200 struct cpuid_result cache_info_res
= cpuid_ext(leaf
, level
);
202 info
->type
= CPUID_CACHE_TYPE(cache_info_res
);
203 info
->level
= CPUID_CACHE_LEVEL(cache_info_res
);
204 info
->num_ways
= CPUID_CACHE_WAYS_OF_ASSOC(cache_info_res
) + 1;
205 info
->num_sets
= CPUID_CACHE_NO_OF_SETS(cache_info_res
) + 1;
206 info
->line_size
= CPUID_CACHE_COHER_LINE(cache_info_res
) + 1;
207 info
->physical_partitions
= CPUID_CACHE_PHYS_LINE(cache_info_res
) + 1;
208 info
->num_cores_shared
= CPUID_CACHE_SHARING_CACHE(cache_info_res
) + 1;
209 info
->fully_associative
= CPUID_CACHE_FULL_ASSOC(cache_info_res
);
210 info
->size
= get_cache_size(info
);