i386/cpu: Unify family, model and stepping calculation for x86 CPU
There are multiple places where CPUID family/model/stepping info are retrieved from env->cpuid_version. Besides, the calculation of family and model inside host_cpu_vendor_fms() doesn't comply to what Intel and AMD define. For family, both Intel and AMD define that Extended Family ID needs to be counted only when (base) Family is 0xF. For model, Intel counts Extended Model when (base) Family is 0x6 or 0xF, while AMD counts EXtended MOdel when (base) Family is 0xF. Introduce generic helper functions to get family, model and stepping from the EAX value of CPUID leaf 1, with the correct calculation formula. Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com> Link: https://lore.kernel.org/r/20250630080610.3151956-5-xiaoyao.li@intel.com Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
3359b588f1
commit
b6c5b41ba2
4 changed files with 38 additions and 12 deletions
|
|
@ -6325,10 +6325,7 @@ static void x86_cpuid_version_get_family(Object *obj, Visitor *v,
|
|||
CPUX86State *env = &cpu->env;
|
||||
uint64_t value;
|
||||
|
||||
value = (env->cpuid_version >> 8) & 0xf;
|
||||
if (value == 0xf) {
|
||||
value += (env->cpuid_version >> 20) & 0xff;
|
||||
}
|
||||
value = x86_cpu_family(env->cpuid_version);
|
||||
visit_type_uint64(v, name, &value, errp);
|
||||
}
|
||||
|
||||
|
|
@ -6366,8 +6363,7 @@ static void x86_cpuid_version_get_model(Object *obj, Visitor *v,
|
|||
CPUX86State *env = &cpu->env;
|
||||
uint64_t value;
|
||||
|
||||
value = (env->cpuid_version >> 4) & 0xf;
|
||||
value |= ((env->cpuid_version >> 16) & 0xf) << 4;
|
||||
value = x86_cpu_model(env->cpuid_version);
|
||||
visit_type_uint64(v, name, &value, errp);
|
||||
}
|
||||
|
||||
|
|
@ -6401,7 +6397,7 @@ static void x86_cpuid_version_get_stepping(Object *obj, Visitor *v,
|
|||
CPUX86State *env = &cpu->env;
|
||||
uint64_t value;
|
||||
|
||||
value = env->cpuid_version & 0xf;
|
||||
value = x86_cpu_stepping(env->cpuid_version);
|
||||
visit_type_uint64(v, name, &value, errp);
|
||||
}
|
||||
|
||||
|
|
@ -8155,7 +8151,7 @@ static void mce_init(X86CPU *cpu)
|
|||
CPUX86State *cenv = &cpu->env;
|
||||
unsigned int bank;
|
||||
|
||||
if (((cenv->cpuid_version >> 8) & 0xf) >= 6
|
||||
if (x86_cpu_family(cenv->cpuid_version) >= 6
|
||||
&& (cenv->features[FEAT_1_EDX] & (CPUID_MCE | CPUID_MCA)) ==
|
||||
(CPUID_MCE | CPUID_MCA)) {
|
||||
cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF |
|
||||
|
|
|
|||
|
|
@ -2678,6 +2678,36 @@ static inline int32_t x86_get_a20_mask(CPUX86State *env)
|
|||
}
|
||||
}
|
||||
|
||||
static inline uint32_t x86_cpu_family(uint32_t eax)
|
||||
{
|
||||
uint32_t family = (eax >> 8) & 0xf;
|
||||
|
||||
if (family == 0xf) {
|
||||
family += (eax >> 20) & 0xff;
|
||||
}
|
||||
|
||||
return family;
|
||||
}
|
||||
|
||||
static inline uint32_t x86_cpu_model(uint32_t eax)
|
||||
{
|
||||
uint32_t family, model;
|
||||
|
||||
family = x86_cpu_family(eax);
|
||||
model = (eax >> 4) & 0xf;
|
||||
|
||||
if (family >= 0x6) {
|
||||
model += ((eax >> 16) & 0xf) << 4;
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
static inline uint32_t x86_cpu_stepping(uint32_t eax)
|
||||
{
|
||||
return eax & 0xf;
|
||||
}
|
||||
|
||||
static inline bool cpu_has_vmx(CPUX86State *env)
|
||||
{
|
||||
return env->features[FEAT_1_ECX] & CPUID_EXT_VMX;
|
||||
|
|
|
|||
|
|
@ -117,13 +117,13 @@ void host_cpu_vendor_fms(char *vendor, int *family, int *model, int *stepping)
|
|||
|
||||
host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
|
||||
if (family) {
|
||||
*family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
|
||||
*family = x86_cpu_family(eax);
|
||||
}
|
||||
if (model) {
|
||||
*model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
|
||||
*model = x86_cpu_model(eax);
|
||||
}
|
||||
if (stepping) {
|
||||
*stepping = eax & 0x0F;
|
||||
*stepping = x86_cpu_stepping(eax);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2259,7 +2259,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
|||
cpuid_i = kvm_x86_build_cpuid(env, cpuid_data.entries, cpuid_i);
|
||||
cpuid_data.cpuid.nent = cpuid_i;
|
||||
|
||||
if (((env->cpuid_version >> 8)&0xF) >= 6
|
||||
if (x86_cpu_family(env->cpuid_version) >= 6
|
||||
&& (env->features[FEAT_1_EDX] & (CPUID_MCE | CPUID_MCA)) ==
|
||||
(CPUID_MCE | CPUID_MCA)) {
|
||||
uint64_t mcg_cap, unsupported_caps;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue