From patchwork Fri Apr 24 19:37:32 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eduardo Habkost X-Patchwork-Id: 464395 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id A27A414007D for ; Sat, 25 Apr 2015 05:42:12 +1000 (AEST) Received: from localhost ([::1]:46266 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YljUI-0003Rx-Lj for incoming@patchwork.ozlabs.org; Fri, 24 Apr 2015 15:42:10 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40435) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YljQG-0005Dp-Gz for qemu-devel@nongnu.org; Fri, 24 Apr 2015 15:38:03 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YljQB-0001tR-Ng for qemu-devel@nongnu.org; Fri, 24 Apr 2015 15:38:00 -0400 Received: from mx1.redhat.com ([209.132.183.28]:33035) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YljQB-0001t3-B7 for qemu-devel@nongnu.org; Fri, 24 Apr 2015 15:37:55 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t3OJbhOO016242 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 24 Apr 2015 15:37:44 -0400 Received: from localhost (ovpn-113-180.phx2.redhat.com [10.3.113.180]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t3OJbglq002557; Fri, 24 Apr 2015 15:37:42 -0400 From: Eduardo Habkost To: qemu-devel@nongnu.org Date: Fri, 24 Apr 2015 16:37:32 -0300 Message-Id: <1429904252-9841-4-git-send-email-ehabkost@redhat.com> In-Reply-To: <1429904252-9841-1-git-send-email-ehabkost@redhat.com> References: <1429904252-9841-1-git-send-email-ehabkost@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: "Michael S. Tsirkin" , Riku Voipio , Blue Swirl , Paolo Bonzini , Igor Mammedov , =?UTF-8?q?Andreas=20F=C3=A4rber?= , Richard Henderson Subject: [Qemu-devel] [PATCH 3/3] target-i386: Move CPUID fields to X86CPU X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Cc: Blue Swirl Cc: Riku Voipio Cc: "Michael S. Tsirkin" Signed-off-by: Eduardo Habkost --- hw/i386/kvm/clock.c | 4 +- hw/i386/pc.c | 2 +- linux-user/elfload.c | 2 +- linux-user/main.c | 4 +- target-i386/cpu-qom.h | 11 +++ target-i386/cpu.c | 214 +++++++++++++++++++++------------------------- target-i386/cpu.h | 11 --- target-i386/helper.c | 6 +- target-i386/kvm.c | 10 +-- target-i386/misc_helper.c | 16 ++-- target-i386/translate.c | 14 +-- 11 files changed, 140 insertions(+), 154 deletions(-) diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c index efdf165..e5d87c2 100644 --- a/hw/i386/kvm/clock.c +++ b/hw/i386/kvm/clock.c @@ -195,8 +195,8 @@ void kvmclock_create(void) X86CPU *cpu = X86_CPU(first_cpu); if (kvm_enabled() && - cpu->env.features[FEAT_KVM] & ((1ULL << KVM_FEATURE_CLOCKSOURCE) | - (1ULL << KVM_FEATURE_CLOCKSOURCE2))) { + cpu->features[FEAT_KVM] & ((1ULL << KVM_FEATURE_CLOCKSOURCE) | + (1ULL << KVM_FEATURE_CLOCKSOURCE2))) { sysbus_create_simple(TYPE_KVM_CLOCK, -1, NULL); } } diff --git a/hw/i386/pc.c b/hw/i386/pc.c index f86c58e..f49d549 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1096,7 +1096,7 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) } /* tell smbios about cpuid version and features */ - smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]); + smbios_set_cpuid(cpu->cpuid_version, cpu->features[FEAT_1_EDX]); } /* pci-info ROM file. Little endian format */ diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 399c021..202dadf 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -140,7 +140,7 @@ static uint32_t get_elf_hwcap(void) { X86CPU *cpu = X86_CPU(thread_cpu); - return cpu->env.features[FEAT_1_EDX]; + return cpu->features[FEAT_1_EDX]; } #ifdef TARGET_X86_64 diff --git a/linux-user/main.c b/linux-user/main.c index e6a93b2..7432f49 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -4086,13 +4086,13 @@ int main(int argc, char **argv, char **envp) #if defined(TARGET_I386) env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK; env->hflags |= HF_PE_MASK | HF_CPL_MASK; - if (env->features[FEAT_1_EDX] & CPUID_SSE) { + if (X86_CPU(cpu)->features[FEAT_1_EDX] & CPUID_SSE) { env->cr[4] |= CR4_OSFXSR_MASK; env->hflags |= HF_OSFXSR_MASK; } #ifndef TARGET_ABI32 /* enable 64 bit mode if possible */ - if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) { + if (!(X86_CPU(cpu)->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) { fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n"); exit(1); } diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h index 31a0c1e..c57073f 100644 --- a/target-i386/cpu-qom.h +++ b/target-i386/cpu-qom.h @@ -95,6 +95,17 @@ typedef struct X86CPU { bool host_features; int64_t apic_id; + /* processor features (e.g. for CPUID insn) */ + uint32_t cpuid_level; + uint32_t cpuid_xlevel; + uint32_t cpuid_xlevel2; + uint32_t cpuid_vendor1; + uint32_t cpuid_vendor2; + uint32_t cpuid_vendor3; + uint32_t cpuid_version; + FeatureWordArray features; + uint32_t cpuid_model[12]; + /* if true the CPUID code directly forward host cache leaves to the guest */ bool cache_info_passthrough; diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 928e2be..c458e47 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1448,7 +1448,6 @@ static void host_x86_cpu_class_init(ObjectClass *oc, void *data) static void host_x86_cpu_initfn(Object *obj) { X86CPU *cpu = X86_CPU(obj); - CPUX86State *env = &cpu->env; KVMState *s = kvm_state; assert(kvm_enabled()); @@ -1458,9 +1457,9 @@ static void host_x86_cpu_initfn(Object *obj) */ cpu->host_features = true; - env->cpuid_level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX); - env->cpuid_xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX); - env->cpuid_xlevel2 = kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX); + cpu->cpuid_level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX); + cpu->cpuid_xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX); + cpu->cpuid_xlevel2 = kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX); object_property_set_bool(OBJECT(cpu), true, "pmu", &error_abort); } @@ -1497,12 +1496,11 @@ static void x86_cpuid_version_get_family(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { X86CPU *cpu = X86_CPU(obj); - CPUX86State *env = &cpu->env; int64_t value; - value = (env->cpuid_version >> 8) & 0xf; + value = (cpu->cpuid_version >> 8) & 0xf; if (value == 0xf) { - value += (env->cpuid_version >> 20) & 0xff; + value += (cpu->cpuid_version >> 20) & 0xff; } visit_type_int(v, &value, name, errp); } @@ -1511,7 +1509,6 @@ static void x86_cpuid_version_set_family(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { X86CPU *cpu = X86_CPU(obj); - CPUX86State *env = &cpu->env; const int64_t min = 0; const int64_t max = 0xff + 0xf; Error *local_err = NULL; @@ -1528,11 +1525,11 @@ static void x86_cpuid_version_set_family(Object *obj, Visitor *v, void *opaque, return; } - env->cpuid_version &= ~0xff00f00; + cpu->cpuid_version &= ~0xff00f00; if (value > 0x0f) { - env->cpuid_version |= 0xf00 | ((value - 0x0f) << 20); + cpu->cpuid_version |= 0xf00 | ((value - 0x0f) << 20); } else { - env->cpuid_version |= value << 8; + cpu->cpuid_version |= value << 8; } } @@ -1540,11 +1537,10 @@ static void x86_cpuid_version_get_model(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { X86CPU *cpu = X86_CPU(obj); - CPUX86State *env = &cpu->env; int64_t value; - value = (env->cpuid_version >> 4) & 0xf; - value |= ((env->cpuid_version >> 16) & 0xf) << 4; + value = (cpu->cpuid_version >> 4) & 0xf; + value |= ((cpu->cpuid_version >> 16) & 0xf) << 4; visit_type_int(v, &value, name, errp); } @@ -1552,7 +1548,6 @@ static void x86_cpuid_version_set_model(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { X86CPU *cpu = X86_CPU(obj); - CPUX86State *env = &cpu->env; const int64_t min = 0; const int64_t max = 0xff; Error *local_err = NULL; @@ -1569,8 +1564,8 @@ static void x86_cpuid_version_set_model(Object *obj, Visitor *v, void *opaque, return; } - env->cpuid_version &= ~0xf00f0; - env->cpuid_version |= ((value & 0xf) << 4) | ((value >> 4) << 16); + cpu->cpuid_version &= ~0xf00f0; + cpu->cpuid_version |= ((value & 0xf) << 4) | ((value >> 4) << 16); } static void x86_cpuid_version_get_stepping(Object *obj, Visitor *v, @@ -1578,10 +1573,9 @@ static void x86_cpuid_version_get_stepping(Object *obj, Visitor *v, Error **errp) { X86CPU *cpu = X86_CPU(obj); - CPUX86State *env = &cpu->env; int64_t value; - value = env->cpuid_version & 0xf; + value = cpu->cpuid_version & 0xf; visit_type_int(v, &value, name, errp); } @@ -1590,7 +1584,6 @@ static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v, Error **errp) { X86CPU *cpu = X86_CPU(obj); - CPUX86State *env = &cpu->env; const int64_t min = 0; const int64_t max = 0xf; Error *local_err = NULL; @@ -1607,19 +1600,18 @@ static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v, return; } - env->cpuid_version &= ~0xf; - env->cpuid_version |= value & 0xf; + cpu->cpuid_version &= ~0xf; + cpu->cpuid_version |= value & 0xf; } static char *x86_cpuid_get_vendor(Object *obj, Error **errp) { X86CPU *cpu = X86_CPU(obj); - CPUX86State *env = &cpu->env; char *value; value = g_malloc(CPUID_VENDOR_SZ + 1); - x86_cpu_vendor_words2str(value, env->cpuid_vendor1, env->cpuid_vendor2, - env->cpuid_vendor3); + x86_cpu_vendor_words2str(value, cpu->cpuid_vendor1, cpu->cpuid_vendor2, + cpu->cpuid_vendor3); return value; } @@ -1627,7 +1619,6 @@ static void x86_cpuid_set_vendor(Object *obj, const char *value, Error **errp) { X86CPU *cpu = X86_CPU(obj); - CPUX86State *env = &cpu->env; int i; if (strlen(value) != CPUID_VENDOR_SZ) { @@ -1636,26 +1627,25 @@ static void x86_cpuid_set_vendor(Object *obj, const char *value, return; } - env->cpuid_vendor1 = 0; - env->cpuid_vendor2 = 0; - env->cpuid_vendor3 = 0; + cpu->cpuid_vendor1 = 0; + cpu->cpuid_vendor2 = 0; + cpu->cpuid_vendor3 = 0; for (i = 0; i < 4; i++) { - env->cpuid_vendor1 |= ((uint8_t)value[i + 0]) << (8 * i); - env->cpuid_vendor2 |= ((uint8_t)value[i + 4]) << (8 * i); - env->cpuid_vendor3 |= ((uint8_t)value[i + 8]) << (8 * i); + cpu->cpuid_vendor1 |= ((uint8_t)value[i + 0]) << (8 * i); + cpu->cpuid_vendor2 |= ((uint8_t)value[i + 4]) << (8 * i); + cpu->cpuid_vendor3 |= ((uint8_t)value[i + 8]) << (8 * i); } } static char *x86_cpuid_get_model_id(Object *obj, Error **errp) { X86CPU *cpu = X86_CPU(obj); - CPUX86State *env = &cpu->env; char *value; int i; value = g_malloc(48 + 1); for (i = 0; i < 48; i++) { - value[i] = env->cpuid_model[i >> 2] >> (8 * (i & 3)); + value[i] = cpu->cpuid_model[i >> 2] >> (8 * (i & 3)); } value[48] = '\0'; return value; @@ -1665,21 +1655,20 @@ static void x86_cpuid_set_model_id(Object *obj, const char *model_id, Error **errp) { X86CPU *cpu = X86_CPU(obj); - CPUX86State *env = &cpu->env; int c, len, i; if (model_id == NULL) { model_id = ""; } len = strlen(model_id); - memset(env->cpuid_model, 0, 48); + memset(cpu->cpuid_model, 0, 48); for (i = 0; i < 48; i++) { if (i >= len) { c = '\0'; } else { c = (uint8_t)model_id[i]; } - env->cpuid_model[i >> 2] |= c << (8 * (i & 3)); + cpu->cpuid_model[i >> 2] |= c << (8 * (i & 3)); } } @@ -1853,7 +1842,6 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features, /* Features to be removed */ FeatureWordArray minus_features = { 0 }; uint32_t numvalue; - CPUX86State *env = &cpu->env; Error *local_err = NULL; featurestr = features ? strtok(features, ",") : NULL; @@ -1930,14 +1918,14 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features, if (cpu->host_features) { for (w = 0; w < FEATURE_WORDS; w++) { - env->features[w] = + cpu->features[w] = x86_cpu_get_supported_feature_word(w, cpu->migratable); } } for (w = 0; w < FEATURE_WORDS; w++) { - env->features[w] |= plus_features[w]; - env->features[w] &= ~minus_features[w]; + cpu->features[w] |= plus_features[w]; + cpu->features[w] &= ~minus_features[w]; } } @@ -2035,16 +2023,15 @@ static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, */ static int x86_cpu_filter_features(X86CPU *cpu) { - CPUX86State *env = &cpu->env; FeatureWord w; int rv = 0; for (w = 0; w < FEATURE_WORDS; w++) { uint32_t host_feat = x86_cpu_get_supported_feature_word(w, cpu->migratable); - uint32_t requested_features = env->features[w]; - env->features[w] &= host_feat; - cpu->filtered_features[w] = requested_features & ~env->features[w]; + uint32_t requested_features = cpu->features[w]; + cpu->features[w] &= host_feat; + cpu->filtered_features[w] = requested_features & ~cpu->features[w]; if (cpu->filtered_features[w]) { if (cpu->check_cpuid || cpu->enforce_cpuid) { report_unavailable_features(w, cpu->filtered_features[w]); @@ -2060,7 +2047,6 @@ static int x86_cpu_filter_features(X86CPU *cpu) */ static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp) { - CPUX86State *env = &cpu->env; const char *vendor; char host_vendor[CPUID_VENDOR_SZ + 1]; FeatureWord w; @@ -2074,19 +2060,19 @@ static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp) cpu->cache_info_passthrough = def->cache_info_passthrough; object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp); for (w = 0; w < FEATURE_WORDS; w++) { - env->features[w] = def->features[w]; + cpu->features[w] = def->features[w]; } /* Special cases not set in the X86CPUDefinition structs: */ if (kvm_enabled()) { FeatureWord w; for (w = 0; w < FEATURE_WORDS; w++) { - env->features[w] |= kvm_default_features[w]; - env->features[w] &= ~kvm_default_unset_features[w]; + cpu->features[w] |= kvm_default_features[w]; + cpu->features[w] &= ~kvm_default_unset_features[w]; } } - env->features[FEAT_1_ECX] |= CPUID_EXT_HYPERVISOR; + cpu->features[FEAT_1_ECX] |= CPUID_EXT_HYPERVISOR; /* sysenter isn't supported in compatibility mode on AMD, * syscall isn't supported in compatibility mode on Intel. @@ -2204,7 +2190,7 @@ static void x86_register_cpudef_type(X86CPUDefinition *def) void cpu_clear_apic_feature(X86CPU *cpu) { - cpu->env.features[FEAT_1_EDX] &= ~CPUID_APIC; + cpu->features[FEAT_1_EDX] &= ~CPUID_APIC; } #endif /* !CONFIG_USER_ONLY */ @@ -2237,45 +2223,44 @@ void cpu_x86_cpuid(X86CPU *cpu, uint32_t index, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { - CPUX86State *env = &cpu->env; CPUState *cs = CPU(cpu); /* test if maximum index reached */ if (index & 0x80000000) { - if (index > env->cpuid_xlevel) { - if (env->cpuid_xlevel2 > 0) { + if (index > cpu->cpuid_xlevel) { + if (cpu->cpuid_xlevel2 > 0) { /* Handle the Centaur's CPUID instruction. */ - if (index > env->cpuid_xlevel2) { - index = env->cpuid_xlevel2; + if (index > cpu->cpuid_xlevel2) { + index = cpu->cpuid_xlevel2; } else if (index < 0xC0000000) { - index = env->cpuid_xlevel; + index = cpu->cpuid_xlevel; } } else { /* Intel documentation states that invalid EAX input will * return the same information as EAX=cpuid_level * (Intel SDM Vol. 2A - Instruction Set Reference - CPUID) */ - index = env->cpuid_level; + index = cpu->cpuid_level; } } } else { - if (index > env->cpuid_level) - index = env->cpuid_level; + if (index > cpu->cpuid_level) + index = cpu->cpuid_level; } switch(index) { case 0: - *eax = env->cpuid_level; - *ebx = env->cpuid_vendor1; - *edx = env->cpuid_vendor2; - *ecx = env->cpuid_vendor3; + *eax = cpu->cpuid_level; + *ebx = cpu->cpuid_vendor1; + *edx = cpu->cpuid_vendor2; + *ecx = cpu->cpuid_vendor3; break; case 1: - *eax = env->cpuid_version; + *eax = cpu->cpuid_version; *ebx = (cpu->apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */ - *ecx = env->features[FEAT_1_ECX]; - *edx = env->features[FEAT_1_EDX]; + *ecx = cpu->features[FEAT_1_ECX]; + *edx = cpu->features[FEAT_1_EDX]; if (cs->nr_cores * cs->nr_threads > 1) { *ebx |= (cs->nr_cores * cs->nr_threads) << 16; *edx |= 1 << 28; /* HTT bit */ @@ -2367,7 +2352,7 @@ void cpu_x86_cpuid(X86CPU *cpu, uint32_t index, uint32_t count, /* Structured Extended Feature Flags Enumeration Leaf */ if (count == 0) { *eax = 0; /* Maximum ECX value for sub-leaves */ - *ebx = env->features[FEAT_7_0_EBX]; /* Feature flags */ + *ebx = cpu->features[FEAT_7_0_EBX]; /* Feature flags */ *ecx = 0; /* Reserved */ *edx = 0; /* Reserved */ } else { @@ -2410,7 +2395,7 @@ void cpu_x86_cpuid(X86CPU *cpu, uint32_t index, uint32_t count, *ebx = 0; *ecx = 0; *edx = 0; - if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE) || !kvm_enabled()) { + if (!(cpu->features[FEAT_1_ECX] & CPUID_EXT_XSAVE) || !kvm_enabled()) { break; } kvm_mask = @@ -2421,7 +2406,7 @@ void cpu_x86_cpuid(X86CPU *cpu, uint32_t index, uint32_t count, *ecx = 0x240; for (i = 2; i < ARRAY_SIZE(ext_save_areas); i++) { const ExtSaveArea *esa = &ext_save_areas[i]; - if ((env->features[esa->feature] & esa->bits) == esa->bits && + if ((cpu->features[esa->feature] & esa->bits) == esa->bits && (kvm_mask & (1 << i)) != 0) { if (i < 32) { *eax |= 1 << i; @@ -2434,10 +2419,10 @@ void cpu_x86_cpuid(X86CPU *cpu, uint32_t index, uint32_t count, *eax |= kvm_mask & (XSTATE_FP | XSTATE_SSE); *ebx = *ecx; } else if (count == 1) { - *eax = env->features[FEAT_XSAVE]; + *eax = cpu->features[FEAT_XSAVE]; } else if (count < ARRAY_SIZE(ext_save_areas)) { const ExtSaveArea *esa = &ext_save_areas[count]; - if ((env->features[esa->feature] & esa->bits) == esa->bits && + if ((cpu->features[esa->feature] & esa->bits) == esa->bits && (kvm_mask & (1 << count)) != 0) { *eax = esa->size; *ebx = esa->offset; @@ -2446,25 +2431,25 @@ void cpu_x86_cpuid(X86CPU *cpu, uint32_t index, uint32_t count, break; } case 0x80000000: - *eax = env->cpuid_xlevel; - *ebx = env->cpuid_vendor1; - *edx = env->cpuid_vendor2; - *ecx = env->cpuid_vendor3; + *eax = cpu->cpuid_xlevel; + *ebx = cpu->cpuid_vendor1; + *edx = cpu->cpuid_vendor2; + *ecx = cpu->cpuid_vendor3; break; case 0x80000001: - *eax = env->cpuid_version; + *eax = cpu->cpuid_version; *ebx = 0; - *ecx = env->features[FEAT_8000_0001_ECX]; - *edx = env->features[FEAT_8000_0001_EDX]; + *ecx = cpu->features[FEAT_8000_0001_ECX]; + *edx = cpu->features[FEAT_8000_0001_EDX]; /* The Linux kernel checks for the CMPLegacy bit and * discards multiple thread information if it is set. * So dont set it here for Intel to make Linux guests happy. */ if (cs->nr_cores * cs->nr_threads > 1) { - if (env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1 || - env->cpuid_vendor2 != CPUID_VENDOR_INTEL_2 || - env->cpuid_vendor3 != CPUID_VENDOR_INTEL_3) { + if (cpu->cpuid_vendor1 != CPUID_VENDOR_INTEL_1 || + cpu->cpuid_vendor2 != CPUID_VENDOR_INTEL_2 || + cpu->cpuid_vendor3 != CPUID_VENDOR_INTEL_3) { *ecx |= 1 << 1; /* CmpLegacy bit */ } } @@ -2472,10 +2457,10 @@ void cpu_x86_cpuid(X86CPU *cpu, uint32_t index, uint32_t count, case 0x80000002: case 0x80000003: case 0x80000004: - *eax = env->cpuid_model[(index - 0x80000002) * 4 + 0]; - *ebx = env->cpuid_model[(index - 0x80000002) * 4 + 1]; - *ecx = env->cpuid_model[(index - 0x80000002) * 4 + 2]; - *edx = env->cpuid_model[(index - 0x80000002) * 4 + 3]; + *eax = cpu->cpuid_model[(index - 0x80000002) * 4 + 0]; + *ebx = cpu->cpuid_model[(index - 0x80000002) * 4 + 1]; + *ecx = cpu->cpuid_model[(index - 0x80000002) * 4 + 2]; + *edx = cpu->cpuid_model[(index - 0x80000002) * 4 + 3]; break; case 0x80000005: /* cache info (L1 cache) */ @@ -2517,17 +2502,17 @@ void cpu_x86_cpuid(X86CPU *cpu, uint32_t index, uint32_t count, *eax = 0; *ebx = 0; *ecx = 0; - *edx = env->features[FEAT_8000_0007_EDX]; + *edx = cpu->features[FEAT_8000_0007_EDX]; break; case 0x80000008: /* virtual & phys address size in low 2 bytes. */ /* XXX: This value must match the one used in the MMU code. */ - if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) { + if (cpu->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) { /* 64 bit processor */ /* XXX: The physical address space is limited to 42 bits in exec.c. */ *eax = 0x00003028; /* 48 bits virtual, 40 bits physical */ } else { - if (env->features[FEAT_1_EDX] & CPUID_PSE36) { + if (cpu->features[FEAT_1_EDX] & CPUID_PSE36) { *eax = 0x00000024; /* 36 bits physical */ } else { *eax = 0x00000020; /* 32 bits physical */ @@ -2541,11 +2526,11 @@ void cpu_x86_cpuid(X86CPU *cpu, uint32_t index, uint32_t count, } break; case 0x8000000A: - if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) { + if (cpu->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) { *eax = 0x00000001; /* SVM Revision */ *ebx = 0x00000010; /* nr of ASIDs */ *ecx = 0; - *edx = env->features[FEAT_SVM]; /* optional features */ + *edx = cpu->features[FEAT_SVM]; /* optional features */ } else { *eax = 0; *ebx = 0; @@ -2554,17 +2539,17 @@ void cpu_x86_cpuid(X86CPU *cpu, uint32_t index, uint32_t count, } break; case 0xC0000000: - *eax = env->cpuid_xlevel2; + *eax = cpu->cpuid_xlevel2; *ebx = 0; *ecx = 0; *edx = 0; break; case 0xC0000001: /* Support for VIA CPU's CPUID instruction */ - *eax = env->cpuid_version; + *eax = cpu->cpuid_version; *ebx = 0; *ecx = 0; - *edx = env->features[FEAT_C000_0001_EDX]; + *edx = cpu->features[FEAT_C000_0001_EDX]; break; case 0xC0000002: case 0xC0000003: @@ -2639,7 +2624,7 @@ static void x86_cpu_reset(CPUState *s) DESC_A_MASK); env->eip = 0xfff0; - env->regs[R_EDX] = env->cpuid_version; + env->regs[R_EDX] = cpu->cpuid_version; env->eflags = 0x2; @@ -2704,8 +2689,8 @@ static void mce_init(X86CPU *cpu) CPUX86State *cenv = &cpu->env; unsigned int bank; - if (((cenv->cpuid_version >> 8) & 0xf) >= 6 - && (cenv->features[FEAT_1_EDX] & (CPUID_MCE | CPUID_MCA)) == + if (((cpu->cpuid_version >> 8) & 0xf) >= 6 + && (cpu->features[FEAT_1_EDX] & (CPUID_MCE | CPUID_MCA)) == (CPUID_MCE | CPUID_MCA)) { cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF; cenv->mcg_ctl = ~(uint64_t)0; @@ -2757,18 +2742,17 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp) #endif -#define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \ - (env)->cpuid_vendor2 == CPUID_VENDOR_INTEL_2 && \ - (env)->cpuid_vendor3 == CPUID_VENDOR_INTEL_3) -#define IS_AMD_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && \ - (env)->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && \ - (env)->cpuid_vendor3 == CPUID_VENDOR_AMD_3) +#define IS_INTEL_CPU(cpu) ((cpu)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \ + (cpu)->cpuid_vendor2 == CPUID_VENDOR_INTEL_2 && \ + (cpu)->cpuid_vendor3 == CPUID_VENDOR_INTEL_3) +#define IS_AMD_CPU(cpu) ((cpu)->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && \ + (cpu)->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && \ + (cpu)->cpuid_vendor3 == CPUID_VENDOR_AMD_3) static void x86_cpu_realizefn(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); X86CPU *cpu = X86_CPU(dev); X86CPUClass *xcc = X86_CPU_GET_CLASS(dev); - CPUX86State *env = &cpu->env; Error *local_err = NULL; static bool ht_warned; @@ -2777,16 +2761,16 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) return; } - if (env->features[FEAT_7_0_EBX] && env->cpuid_level < 7) { - env->cpuid_level = 7; + if (cpu->features[FEAT_7_0_EBX] && cpu->cpuid_level < 7) { + cpu->cpuid_level = 7; } /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on * CPUID[1].EDX. */ - if (IS_AMD_CPU(env)) { - env->features[FEAT_8000_0001_EDX] &= ~CPUID_EXT2_AMD_ALIASES; - env->features[FEAT_8000_0001_EDX] |= (env->features[FEAT_1_EDX] + if (IS_AMD_CPU(cpu)) { + cpu->features[FEAT_8000_0001_EDX] &= ~CPUID_EXT2_AMD_ALIASES; + cpu->features[FEAT_8000_0001_EDX] |= (cpu->features[FEAT_1_EDX] & CPUID_EXT2_AMD_ALIASES); } @@ -2802,7 +2786,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) #ifndef CONFIG_USER_ONLY qemu_register_reset(x86_cpu_machine_reset_cb, cpu); - if (cpu->env.features[FEAT_1_EDX] & CPUID_APIC || smp_cpus > 1) { + if (cpu->features[FEAT_1_EDX] & CPUID_APIC || smp_cpus > 1) { x86_cpu_apic_create(cpu, &local_err); if (local_err != NULL) { goto out; @@ -2821,7 +2805,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) * NOTE: the following code has to follow qemu_init_vcpu(). Otherwise * cs->nr_threads hasn't be populated yet and the checking is incorrect. */ - if (!IS_INTEL_CPU(env) && cs->nr_threads > 1 && !ht_warned) { + if (!IS_INTEL_CPU(cpu) && cs->nr_threads > 1 && !ht_warned) { error_report("AMD CPU doesn't support hyperthreading. Please configure" " -smp options properly."); ht_warned = true; @@ -2875,7 +2859,7 @@ static void x86_cpu_initfn(Object *obj) x86_cpuid_set_apic_id, NULL, NULL, NULL); object_property_add(obj, "feature-words", "X86CPUFeatureWordInfo", x86_cpu_get_feature_words, - NULL, NULL, (void *)env->features, NULL); + NULL, NULL, (void *)cpu->features, NULL); object_property_add(obj, "filtered-features", "X86CPUFeatureWordInfo", x86_cpu_get_feature_words, NULL, NULL, (void *)cpu->filtered_features, NULL); @@ -2953,9 +2937,9 @@ static Property x86_cpu_properties[] = { DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, false), DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false), DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true), - DEFINE_PROP_UINT32("level", X86CPU, env.cpuid_level, 0), - DEFINE_PROP_UINT32("xlevel", X86CPU, env.cpuid_xlevel, 0), - DEFINE_PROP_UINT32("xlevel2", X86CPU, env.cpuid_xlevel2, 0), + DEFINE_PROP_UINT32("level", X86CPU, cpuid_level, 0), + DEFINE_PROP_UINT32("xlevel", X86CPU, cpuid_xlevel, 0), + DEFINE_PROP_UINT32("xlevel2", X86CPU, cpuid_xlevel2, 0), DEFINE_PROP_END_OF_LIST() }; diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 750b5b7..9f58b87 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -933,17 +933,6 @@ typedef struct CPUX86State { /* Fields from here on are preserved across CPU reset. */ struct {} end_reset_fields; - /* processor features (e.g. for CPUID insn) */ - uint32_t cpuid_level; - uint32_t cpuid_xlevel; - uint32_t cpuid_xlevel2; - uint32_t cpuid_vendor1; - uint32_t cpuid_vendor2; - uint32_t cpuid_vendor3; - uint32_t cpuid_version; - FeatureWordArray features; - uint32_t cpuid_model[12]; - /* MTRRs */ uint64_t mtrr_fixed[11]; uint64_t mtrr_deftype; diff --git a/target-i386/helper.c b/target-i386/helper.c index 54a0fdb..04ebeb6 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -27,7 +27,7 @@ static void cpu_x86_version(X86CPU *cpu, int *family, int *model) { - int cpuver = cpu->env.cpuid_version; + int cpuver = cpu->cpuid_version; if (family == NULL || model == NULL) { return; @@ -465,7 +465,7 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4) tlb_flush(CPU(cpu), 1); } /* SSE handling */ - if (!(env->features[FEAT_1_EDX] & CPUID_SSE)) { + if (!(cpu->features[FEAT_1_EDX] & CPUID_SSE)) { new_cr4 &= ~CR4_OSFXSR_MASK; } env->hflags &= ~HF_OSFXSR_MASK; @@ -473,7 +473,7 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4) env->hflags |= HF_OSFXSR_MASK; } - if (!(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_SMAP)) { + if (!(cpu->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_SMAP)) { new_cr4 &= ~CR4_SMAP_MASK; } env->hflags &= ~HF_SMAP_MASK; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index a4cb7e3..bdd5351 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -544,7 +544,7 @@ int kvm_arch_init_vcpu(CPUState *cs) c = &cpuid_data.entries[cpuid_i++]; c->function = KVM_CPUID_FEATURES | kvm_base; - c->eax = env->features[FEAT_KVM]; + c->eax = cpu->features[FEAT_KVM]; has_msr_async_pf_en = c->eax & (1 << KVM_FEATURE_ASYNC_PF); @@ -656,7 +656,7 @@ int kvm_arch_init_vcpu(CPUState *cs) } /* Call Centaur's CPUID instructions they are supported. */ - if (env->cpuid_xlevel2 > 0) { + if (cpu->cpuid_xlevel2 > 0) { cpu_x86_cpuid(cpu, 0xC0000000, 0, &limit, &unused, &unused, &unused); for (i = 0xC0000000; i <= limit; i++) { @@ -674,8 +674,8 @@ int kvm_arch_init_vcpu(CPUState *cs) cpuid_data.cpuid.nent = cpuid_i; - if (((env->cpuid_version >> 8)&0xF) >= 6 - && (env->features[FEAT_1_EDX] & (CPUID_MCE | CPUID_MCA)) == + if (((cpu->cpuid_version >> 8)&0xF) >= 6 + && (cpu->features[FEAT_1_EDX] & (CPUID_MCE | CPUID_MCA)) == (CPUID_MCE | CPUID_MCA) && kvm_check_extension(cs->kvm_state, KVM_CAP_MCE) > 0) { uint64_t mcg_cap; @@ -740,7 +740,7 @@ int kvm_arch_init_vcpu(CPUState *cs) env->kvm_xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave)); } - if (env->features[FEAT_1_EDX] & CPUID_MTRR) { + if (cpu->features[FEAT_1_EDX] & CPUID_MTRR) { has_msr_mtrr = true; } diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c index 0f96c38..5fc1261 100644 --- a/target-i386/misc_helper.c +++ b/target-i386/misc_helper.c @@ -226,6 +226,7 @@ void helper_rdmsr(CPUX86State *env) #else void helper_wrmsr(CPUX86State *env) { + X86CPU *cpu = x86_env_get_cpu(env); uint64_t val; cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1); @@ -251,22 +252,22 @@ void helper_wrmsr(CPUX86State *env) uint64_t update_mask; update_mask = 0; - if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) { + if (cpu->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) { update_mask |= MSR_EFER_SCE; } - if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) { + if (cpu->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) { update_mask |= MSR_EFER_LME; } - if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) { + if (cpu->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) { update_mask |= MSR_EFER_FFXSR; } - if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) { + if (cpu->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) { update_mask |= MSR_EFER_NXE; } - if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) { + if (cpu->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) { update_mask |= MSR_EFER_SVME; } - if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) { + if (cpu->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) { update_mask |= MSR_EFER_FFXSR; } cpu_load_efer(env, (env->efer & ~update_mask) | @@ -380,6 +381,7 @@ void helper_wrmsr(CPUX86State *env) void helper_rdmsr(CPUX86State *env) { + X86CPU *cpu = x86_env_get_cpu(env); uint64_t val; cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0); @@ -483,7 +485,7 @@ void helper_rdmsr(CPUX86State *env) val = env->mtrr_deftype; break; case MSR_MTRRcap: - if (env->features[FEAT_1_EDX] & CPUID_MTRR) { + if (cpu->features[FEAT_1_EDX] & CPUID_MTRR) { val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT | MSR_MTRRcap_WC_SUPPORTED; } else { diff --git a/target-i386/translate.c b/target-i386/translate.c index fdbb4af..adea74e 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -7090,7 +7090,7 @@ static target_ulong disas_insn(X86CPU *cpu, DisasContext *s, break; case 0x134: /* sysenter */ /* For Intel SYSENTER is valid on 64-bit */ - if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) + if (CODE64(s) && cpu->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) goto illegal_op; if (!s->pe) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); @@ -7103,7 +7103,7 @@ static target_ulong disas_insn(X86CPU *cpu, DisasContext *s, break; case 0x135: /* sysexit */ /* For Intel SYSEXIT is valid on 64-bit */ - if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) + if (CODE64(s) && cpu->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) goto illegal_op; if (!s->pe) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); @@ -7946,11 +7946,11 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, if (flags & HF_SOFTMMU_MASK) { dc->mem_index = cpu_mmu_index(env); } - dc->cpuid_features = env->features[FEAT_1_EDX]; - dc->cpuid_ext_features = env->features[FEAT_1_ECX]; - dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX]; - dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX]; - dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX]; + dc->cpuid_features = cpu->features[FEAT_1_EDX]; + dc->cpuid_ext_features = cpu->features[FEAT_1_ECX]; + dc->cpuid_ext2_features = cpu->features[FEAT_8000_0001_EDX]; + dc->cpuid_ext3_features = cpu->features[FEAT_8000_0001_ECX]; + dc->cpuid_7_0_ebx_features = cpu->features[FEAT_7_0_EBX]; #ifdef TARGET_X86_64 dc->lma = (flags >> HF_LMA_SHIFT) & 1; dc->code64 = (flags >> HF_CS64_SHIFT) & 1;