diff --git a/qemu/target-i386/cpu.c b/qemu/target-i386/cpu.c index 7240505b..5bd5790e 100644 --- a/qemu/target-i386/cpu.c +++ b/qemu/target-i386/cpu.c @@ -523,7 +523,23 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { false, 0, R_EAX, TCG_6_EAX_FEATURES, - } + }, + // FEAT_XSAVE_COMP_LO + { + {NULL}, + 0xD, + true, 0, + R_EAX, + ~0U, + }, + // FEAT_XSAVE_COMP_HI + { + {NULL}, + 0xD, + true, 0, + R_EDX, + ~0U, + }, }; typedef struct X86RegisterInfo32 { @@ -621,6 +637,12 @@ static uint32_t xsave_area_size(uint64_t mask) return ret; } +static inline uint64_t x86_cpu_xsave_components(X86CPU *cpu) +{ + return ((uint64_t)cpu->env.features[FEAT_XSAVE_COMP_HI]) << 32 | + cpu->env.features[FEAT_XSAVE_COMP_LO]; +} + const char *get_register_name_32(unsigned int reg) { if (reg >= CPU_NB_REGS32) { @@ -2540,15 +2562,15 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, } if (count == 0) { - *ecx = xsave_area_size(env->xsave_components); - *eax = env->xsave_components; - *edx = env->xsave_components >> 32; + *ecx = xsave_area_size(x86_cpu_xsave_components(cpu)); + *eax = env->features[FEAT_XSAVE_COMP_LO]; + *edx = env->features[FEAT_XSAVE_COMP_HI]; *ebx = *ecx; } else if (count == 1) { *eax = env->features[FEAT_XSAVE]; } else if (count < ARRAY_SIZE(x86_ext_save_areas)) { - const ExtSaveArea *esa = &x86_ext_save_areas[count]; - if ((env->xsave_components >> count) & 1) { + if ((x86_cpu_xsave_components(cpu) >> count) & 1) { + const ExtSaveArea *esa = &x86_ext_save_areas[count]; *eax = esa->size; *ebx = esa->offset; } @@ -2946,27 +2968,22 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu) { CPUX86State *env = &cpu->env; int i; + uint64_t mask; if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) { return; } - env->xsave_components = (XSTATE_FP_MASK | XSTATE_SSE_MASK); + mask = (XSTATE_FP_MASK | XSTATE_SSE_MASK); for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) { const ExtSaveArea *esa = &x86_ext_save_areas[i]; if (env->features[esa->feature] & esa->bits) { - env->xsave_components |= (1ULL << i); + mask |= (1ULL << i); } } - /* Unicorn: commented out - if (kvm_enabled()) { - KVMState *s = kvm_state; - uint64_t kvm_mask = kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EDX); - kvm_mask <<= 32; - kvm_mask |= kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EAX); - env->xsave_components &= kvm_mask; - }*/ + env->features[FEAT_XSAVE_COMP_LO] = mask; + env->features[FEAT_XSAVE_COMP_HI] = mask >> 32; } #define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \ diff --git a/qemu/target-i386/cpu.h b/qemu/target-i386/cpu.h index 5dd48017..dc2875ae 100644 --- a/qemu/target-i386/cpu.h +++ b/qemu/target-i386/cpu.h @@ -452,6 +452,8 @@ typedef enum FeatureWord { FEAT_SVM, /* CPUID[8000_000A].EDX */ FEAT_XSAVE, /* CPUID[EAX=0xd,ECX=1].EAX */ FEAT_6_EAX, /* CPUID[6].EAX */ + FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */ + FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */ FEATURE_WORDS, } FeatureWord;