From patchwork Mon Dec 21 06:46:36 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: john cooper X-Patchwork-Id: 69086 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.2) with ESMTP id nBL7D5YR001303 for ; Mon, 21 Dec 2009 07:13:05 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751350AbZLUHND (ORCPT ); Mon, 21 Dec 2009 02:13:03 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751257AbZLUHNA (ORCPT ); Mon, 21 Dec 2009 02:13:00 -0500 Received: from mx1.redhat.com ([209.132.183.28]:6705 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751243AbZLUHM7 (ORCPT ); Mon, 21 Dec 2009 02:12:59 -0500 Received: from int-mx03.intmail.prod.int.phx2.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id nBL7Cuwk012421 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 21 Dec 2009 02:12:57 -0500 Received: from anvil.naka.net (pilototp-int.redhat.com [10.11.232.41]) by int-mx03.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id nBL7CnQO027335; Mon, 21 Dec 2009 02:12:51 -0500 Message-ID: <4B2F19CC.5020808@redhat.com> Date: Mon, 21 Dec 2009 01:46:36 -0500 From: john cooper User-Agent: Thunderbird 2.0.0.9 (X11/20071115) MIME-Version: 1.0 To: KVM list CC: qemu-devel@nongnu.org, john.cooper@redhat.com Subject: [PATCH] Add definitions for current cpu models.. X-Scanned-By: MIMEDefang 2.67 on 10.5.11.16 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org diff --git a/target-i386/helper.c b/target-i386/helper.c index 9a50da6..a706cae 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -44,7 +44,7 @@ static const char *feature_name[] = { static const char *ext_feature_name[] = { "pni" /* Intel,AMD sse3 */, NULL, NULL, "monitor", "ds_cpl", "vmx", NULL /* Linux smx */, "est", "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL, - NULL, NULL, "dca", NULL, NULL, "x2apic", NULL, "popcnt", + NULL, NULL, "dca", "sse4.1", "sse4.2", "x2apic", NULL, "popcnt", NULL, NULL, NULL, NULL, NULL, NULL, NULL, "hypervisor", }; static const char *ext2_feature_name[] = { @@ -60,6 +60,18 @@ static const char *ext3_feature_name[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; +/* collects per-function cpuid data + */ +typedef struct model_features_t { + uint32_t *guest_feat; + uint32_t *host_feat; + uint32_t check_feat; + const char **flag_names; + uint32_t cpuid; + } model_features_t; + +int check_cpuid = 0; + static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features, uint32_t *ext_features, uint32_t *ext2_features, @@ -171,6 +183,139 @@ static x86_def_t x86_defs[] = { .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor" }, { + .name = "Merom", + .level = 2, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, /* P6 */ + .model = 2, + .stepping = 3, + .features = PPRO_FEATURES | + /* these features are needed for Win64 and aren't fully implemented */ + CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | + /* this feature is needed for Solaris and isn't fully implemented */ + CPUID_PSE36, + .ext_features = CPUID_EXT_SSE3, /* from qemu64 */ + .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .ext3_features = CPUID_EXT3_SVM, /* from qemu64 */ + .xlevel = 0x8000000A, + .model_id = "Intel Merom Core 2", + }, + { + .name = "Penryn", + .level = 2, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, /* P6 */ + .model = 2, + .stepping = 3, + .features = PPRO_FEATURES | + /* these features are needed for Win64 and aren't fully implemented */ + CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | + /* this feature is needed for Solaris and isn't fully implemented */ + CPUID_PSE36, + .ext_features = CPUID_EXT_SSE3 | + CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE41, + .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .ext3_features = CPUID_EXT3_SVM, + .xlevel = 0x8000000A, + .model_id = "Intel Penryn Core 2", + }, + { + .name = "Nehalem", + .level = 2, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, /* P6 */ + .model = 2, + .stepping = 3, + .features = PPRO_FEATURES | + /* these features are needed for Win64 and aren't fully implemented */ + CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | + /* this feature is needed for Solaris and isn't fully implemented */ + CPUID_PSE36, + .ext_features = CPUID_EXT_SSE3 | + CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE41 | + CPUID_EXT_SSE42 | CPUID_EXT_POPCNT, + .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .ext3_features = CPUID_EXT3_SVM, + .xlevel = 0x8000000A, + .model_id = "Intel Nehalem Core i7", + }, + { + .name = "Opteron_G1", + .level = 5, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 15, + .model = 6, + .stepping = 1, + .features = PPRO_FEATURES | + /* these features are needed for Win64 and aren't fully implemented */ + CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | + /* this feature is needed for Solaris and isn't fully implemented */ + CPUID_PSE36, + .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR, + .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .ext3_features = CPUID_EXT3_SVM, + .xlevel = 0x80000008, + .model_id = "AMD Opteron G1", + }, + { + .name = "Opteron_G2", + .level = 5, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 15, + .model = 6, + .stepping = 1, + .features = PPRO_FEATURES | + /* these features are needed for Win64 and aren't fully implemented */ + CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | + /* this feature is needed for Solaris and isn't fully implemented */ + CPUID_PSE36 | CPUID_EXT_CX16, + .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR, + .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX | + CPUID_EXT2_RDTSCP, + .ext3_features = CPUID_EXT3_SVM, + .xlevel = 0x80000008, + .model_id = "AMD Opteron G2", + }, + { + .name = "Opteron_G3", + .level = 5, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 15, + .model = 6, + .stepping = 1, + .features = PPRO_FEATURES | + /* these features are needed for Win64 and aren't fully implemented */ + CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | + /* this feature is needed for Solaris and isn't fully implemented */ + CPUID_PSE36 | CPUID_EXT_CX16, + .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_POPCNT, + .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX | + CPUID_EXT2_RDTSCP, + .ext3_features = CPUID_EXT3_SVM | CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | + CPUID_EXT3_MISALIGNSSE, + .xlevel = 0x80000008, + .model_id = "AMD Opteron G3", + }, + /* this feature is needed for Solaris and isn't fully implemented */ + { .name = "core2duo", .level = 10, .family = 6, @@ -319,7 +464,7 @@ static x86_def_t x86_defs[] = { /* Missing: .ext3_features = CPUID_EXT3_LAHF_LM */ .xlevel = 0x8000000A, .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz", - }, + } }; static void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax, @@ -370,6 +515,51 @@ static int cpu_x86_fill_host(x86_def_t *x86_cpu_def) return 0; } +static int unavailable_host_feature(struct model_features_t *f, uint32_t mask) +{ + int i; + + for (i = 0; i < 32; ++i) + if (1 << i & mask) { + fprintf(stderr, "warning: host cpuid %04x_%04x lacks requested" + " flag '%s' [0x%08x]\n", + f->cpuid >> 16, f->cpuid & 0xffff, + f->flag_names[i] ? f->flag_names[i] : "[reserved]", mask); + break; + } + return 0; +} + +/* best effort attempt to inform user requested cpu flags aren't making + * their way to the guest. Note: ft[].check_feat ideally should be + * specified via a guest_def field to suppress report of extraneous flags. + */ +static int check_features_against_host(x86_def_t *guest_def) +{ + x86_def_t host_def; + uint32_t mask; + int rv, i; + struct model_features_t ft[] = { + {&guest_def->features, &host_def.features, + ~0, feature_name, 0x00000000}, + {&guest_def->ext_features, &host_def.ext_features, + ~CPUID_EXT_HYPERVISOR, ext_feature_name, 0x00000001}, + {&guest_def->ext2_features, &host_def.ext2_features, + ~PPRO_FEATURES, ext2_feature_name, 0x80000000}, + {&guest_def->ext3_features, &host_def.ext3_features, + ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001}}; + + cpu_x86_fill_host(&host_def); + for (rv = 0, i = 0; i < sizeof (ft) / sizeof (ft[0]); ++i) + for (mask = 1; mask; mask <<= 1) + if (ft[i].check_feat & mask && *ft[i].guest_feat & mask && + !(*ft[i].host_feat & mask)) { + unavailable_host_feature(&ft[i], mask); + rv = 1; + } + return (rv); +} + static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) { unsigned int i; @@ -473,6 +663,8 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) fprintf(stderr, "unrecognized feature %s\n", featurestr); goto error; } + } else if (!strcmp(featurestr, "check")) { + check_cpuid = 1; } else { fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr); goto error; @@ -487,6 +679,9 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) x86_cpu_def->ext_features &= ~minus_ext_features; x86_cpu_def->ext2_features &= ~minus_ext2_features; x86_cpu_def->ext3_features &= ~minus_ext3_features; + if (check_cpuid) + check_features_against_host(x86_cpu_def); + free(s); return 0;