All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Add definitions for current cpu models..
@ 2009-12-21  6:46 ` john cooper
  0 siblings, 0 replies; 10+ messages in thread
From: john cooper @ 2009-12-21  6:46 UTC (permalink / raw)
  To: KVM list; +Cc: qemu-devel, john.cooper

This adds definitions for contemporary processors
which may be selected via -cpu <model>, as an
alternative to the existing use of -cpu qemu64
augmented with a series of feature flags.

The primary motivation was determination of a
least common denominator within a given processor
class for simplification of guest migration.  It
is still possible to modify an arbitrary model via
additional feature flags however the goal here was
to make doing so unnecessary in typical usage.  The
other consideration was providing models names
reflective of current processors.  Both AMD and
Intel have reviewed the models in terms of balancing
generality of migration vs. excessive feature
downgrade relative to released silicon. 

A cpu feature 'check' option is also added which
warns when feature flags (either implicit in a cpu
model or explicit on the command line) would have
otherwise been quietly disabled for a guest.

This patch was tested relative to qemu-kvm.git.

Signed-off-by: john cooper <john.cooper@redhat.com>
---

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;
 
-- 
john.cooper@redhat.com

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH] Add definitions for current cpu models..
@ 2009-12-21  6:46 ` john cooper
  0 siblings, 0 replies; 10+ messages in thread
From: john cooper @ 2009-12-21  6:46 UTC (permalink / raw)
  To: KVM list; +Cc: john.cooper, qemu-devel

This adds definitions for contemporary processors
which may be selected via -cpu <model>, as an
alternative to the existing use of -cpu qemu64
augmented with a series of feature flags.

The primary motivation was determination of a
least common denominator within a given processor
class for simplification of guest migration.  It
is still possible to modify an arbitrary model via
additional feature flags however the goal here was
to make doing so unnecessary in typical usage.  The
other consideration was providing models names
reflective of current processors.  Both AMD and
Intel have reviewed the models in terms of balancing
generality of migration vs. excessive feature
downgrade relative to released silicon. 

A cpu feature 'check' option is also added which
warns when feature flags (either implicit in a cpu
model or explicit on the command line) would have
otherwise been quietly disabled for a guest.

This patch was tested relative to qemu-kvm.git.

Signed-off-by: john cooper <john.cooper@redhat.com>
---

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;
 
-- 
john.cooper@redhat.com

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH] Add definitions for current cpu models..
  2009-12-21  6:46 ` [Qemu-devel] " john cooper
  (?)
@ 2009-12-24 13:05 ` Marcelo Tosatti
  2010-01-05  6:06     ` [Qemu-devel] " john cooper
  -1 siblings, 1 reply; 10+ messages in thread
From: Marcelo Tosatti @ 2009-12-24 13:05 UTC (permalink / raw)
  To: john cooper; +Cc: KVM list, qemu-devel

On Mon, Dec 21, 2009 at 01:46:36AM -0500, john cooper wrote:
> This adds definitions for contemporary processors
> which may be selected via -cpu <model>, as an
> alternative to the existing use of -cpu qemu64
> augmented with a series of feature flags.
> 
> The primary motivation was determination of a
> least common denominator within a given processor
> class for simplification of guest migration.  It
> is still possible to modify an arbitrary model via
> additional feature flags however the goal here was
> to make doing so unnecessary in typical usage.  The
> other consideration was providing models names
> reflective of current processors.  Both AMD and
> Intel have reviewed the models in terms of balancing
> generality of migration vs. excessive feature
> downgrade relative to released silicon. 
> 
> A cpu feature 'check' option is also added which
> warns when feature flags (either implicit in a cpu
> model or explicit on the command line) would have
> otherwise been quietly disabled for a guest.
> 
> This patch was tested relative to qemu-kvm.git.
> 
> Signed-off-by: john cooper <john.cooper@redhat.com>
> ---
> 
> 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",
>  };

Separate patch?

>  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,

Silly question: why a CPU named "Opteron_G2" uses intel vendor id's?

> +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;
> +}

Deserves a separate patch, too.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH] Add definitions for current cpu models..
  2009-12-21  6:46 ` [Qemu-devel] " john cooper
  (?)
  (?)
@ 2009-12-24 13:45 ` Avi Kivity
  -1 siblings, 0 replies; 10+ messages in thread
From: Avi Kivity @ 2009-12-24 13:45 UTC (permalink / raw)
  To: john cooper; +Cc: KVM list, qemu-devel

On 12/21/2009 08:46 AM, john cooper wrote:
> This adds definitions for contemporary processors
> which may be selected via -cpu<model>, as an
> alternative to the existing use of -cpu qemu64
> augmented with a series of feature flags.
>
> The primary motivation was determination of a
> least common denominator within a given processor
> class for simplification of guest migration.  It
> is still possible to modify an arbitrary model via
> additional feature flags however the goal here was
> to make doing so unnecessary in typical usage.  The
> other consideration was providing models names
> reflective of current processors.  Both AMD and
> Intel have reviewed the models in terms of balancing
> generality of migration vs. excessive feature
> downgrade relative to released silicon.
>
> A cpu feature 'check' option is also added which
> warns when feature flags (either implicit in a cpu
> model or explicit on the command line) would have
> otherwise been quietly disabled for a guest.
>
> This patch was tested relative to qemu-kvm.git.
>    


Nothing kvm-specific in there, yes?  If so, it should go though qemu.git.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH] Add definitions for current cpu models..
  2009-12-21  6:46 ` [Qemu-devel] " john cooper
                   ` (2 preceding siblings ...)
  (?)
@ 2009-12-31  3:13 ` Jamie Lokier
  -1 siblings, 0 replies; 10+ messages in thread
From: Jamie Lokier @ 2009-12-31  3:13 UTC (permalink / raw)
  To: john cooper; +Cc: KVM list, qemu-devel

john cooper wrote:
>      {
> +        .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 */

Isn't SSE3 a generic feature on these Intel CPUs, so this comment is unnecessary?
Or is SSE3 not present on a real Merom?  If so, wouldn't it be better to omit it?

> +        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | 

Could we have a meaningful name for the magic number, please?
Maybe even a:

   #define PPRO_EXT2_FEATURES (PPRO_FEATURES & PPRO_EXT2_MASK)
   #define PPRO_EXT2_MASK     (CPUID_... | CPUID_... | ...) /* Fill in. */

> +            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
> +        .ext3_features = CPUID_EXT3_SVM,	/* from qemu64 */
> +        .xlevel = 0x8000000A,
> +        .model_id = "Intel Merom Core 2",
> +    },

Does this mean requesting an Intel Merom will give the guest AMD's SVM
capability?  That's handy for virtualisation, but not an accurate CPU
model.  It seems inappropriate to name it "Merom", with model_id
"Intel Merom Core 2", if it's adding extra qemu-specific capabilities.

I would think few guests are likely to need the nested-SVM capability,
so it could be omitted when "Merom" is requested, and added as an
additional feature on request from the command line, just like other
cpuid features can be added.

> +    {
> +        .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",
> +    },

Same comments as above for Merom about SVM and the PPRO_FEATURES mask.

You don't include the "from qemu64" comments this time.  Is there a reason?

> +    {
> +        .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",
> +    },

Same as previous.

> +    {
> +        .name = "Opteron_G1",
> +        .level = 5,
> +        .vendor1 = CPUID_VENDOR_INTEL_1,
> +        .vendor2 = CPUID_VENDOR_INTEL_2,
> +        .vendor3 = CPUID_VENDOR_INTEL_3,

Someone else has already enquired - why Intel vendor id?

> +        .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",
> +    },

Why do the AMD models have CPUID_EXT_MONITOR but the Intel ones don't.
Is it correct for the CPU models?  Even a lowly 32-bit Intel Core has MONITOR.
Is it omitted for performance?  In that case shouldn't it be omitted for AMD too?

> +    {
> +        .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,

Solaris comment can use plurals here, like Win64 :-)

> +        .model_id = "AMD Opteron G3",
> +    },
> +        /* this feature is needed for Solaris and isn't fully implemented */
> +    {
The above Solaris comment seems out of place.

>          .name = "core2duo",

The new name style is clearly different from the old name style,
"Merom" and "Opteron_G3" vs "core2duo".  It's a bit untidy.

I'm thinking The names "Merom", "Penryn" and so on might be better as
"Intel Meron", "Intel Penryn" and so on (or perhaps with underscores),
and changing "core2duo" to "Intel Core 2 Duo" and so on.

>          .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",
> -    },
> +    }
>  };

What does qemu coding style say about comma after the last element in a list?
(Not serious :-)

> +/* 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.
> + */

With the recent KVM special handling of the SYSCALL feature, so that
Intel 64-bit hosts can run 64-bit guest kernels with 32-bit userspace
without triggering SYSCALL emulation (and working on older host kernels),
how does the feature masking work out for the SYSCALL feature with "check"?

And general comments:

Thanks for adding the CPU models.  You said they've been checked by
Intel and AMD, but as you can tell from my comments, it's hard to tell
(without consulting processor manuals) if they are accurate
descriptions of real CPU models, or approximations.  What's the intention?

They are all 64-bit models.  Any plans to add contemporary 32-bit
models, or is the existing list of those complete enough already?

Thanks,
-- Jamie

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Add definitions for current cpu models..
  2009-12-21  6:46 ` [Qemu-devel] " john cooper
                   ` (3 preceding siblings ...)
  (?)
@ 2009-12-31 14:38 ` Anthony Liguori
  -1 siblings, 0 replies; 10+ messages in thread
From: Anthony Liguori @ 2009-12-31 14:38 UTC (permalink / raw)
  To: john cooper; +Cc: qemu-devel, KVM list

[-- Attachment #1: Type: text/plain, Size: 11411 bytes --]

Please use actual cpu models verses family names.  Nehalem is a wide class
of processors and the EX has a fair bit that isn't present in earlier
models.

The patch also doesn't follow CODING_STYLE.

On Dec 21, 2009 1:13 AM, "john cooper" <john.cooper@redhat.com> wrote:

This adds definitions for contemporary processors
which may be selected via -cpu <model>, as an
alternative to the existing use of -cpu qemu64
augmented with a series of feature flags.

The primary motivation was determination of a
least common denominator within a given processor
class for simplification of guest migration.  It
is still possible to modify an arbitrary model via
additional feature flags however the goal here was
to make doing so unnecessary in typical usage.  The
other consideration was providing models names
reflective of current processors.  Both AMD and
Intel have reviewed the models in terms of balancing
generality of migration vs. excessive feature
downgrade relative to released silicon.

A cpu feature 'check' option is also added which
warns when feature flags (either implicit in a cpu
model or explicit on the command line) would have
otherwise been quietly disabled for a guest.

This patch was tested relative to qemu-kvm.git.

Signed-off-by: john cooper <john.cooper@redhat.com>
---

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;

--
john.cooper@redhat.com
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[-- Attachment #2: Type: text/html, Size: 13902 bytes --]

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH] Add definitions for current cpu models..
  2009-12-24 13:05 ` Marcelo Tosatti
@ 2010-01-05  6:06     ` john cooper
  0 siblings, 0 replies; 10+ messages in thread
From: john cooper @ 2010-01-05  6:06 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: KVM list, qemu-devel, john.cooper

Marcelo Tosatti wrote:
> On Mon, Dec 21, 2009 at 01:46:36AM -0500, john cooper wrote:
>> +    {
>> +        .name = "Opteron_G2",
>> +        .level = 5,
>> +        .vendor1 = CPUID_VENDOR_INTEL_1,
>> +        .vendor2 = CPUID_VENDOR_INTEL_2,
>> +        .vendor3 = CPUID_VENDOR_INTEL_3,
> 
> Silly question: why a CPU named "Opteron_G2" uses intel vendor id's?

The feedback I had from AMD indicated using the Intel
strings for a family 15 cpu resulted in the least
amount of guest confusion.  The upstream kvm64 model
does similarly.

Sorry for my late response here which was preempted
by the intervening holiday.

-john

-- 
john.cooper@redhat.com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Qemu-devel] Re: [PATCH] Add definitions for current cpu models..
@ 2010-01-05  6:06     ` john cooper
  0 siblings, 0 replies; 10+ messages in thread
From: john cooper @ 2010-01-05  6:06 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: john.cooper, qemu-devel, KVM list

Marcelo Tosatti wrote:
> On Mon, Dec 21, 2009 at 01:46:36AM -0500, john cooper wrote:
>> +    {
>> +        .name = "Opteron_G2",
>> +        .level = 5,
>> +        .vendor1 = CPUID_VENDOR_INTEL_1,
>> +        .vendor2 = CPUID_VENDOR_INTEL_2,
>> +        .vendor3 = CPUID_VENDOR_INTEL_3,
> 
> Silly question: why a CPU named "Opteron_G2" uses intel vendor id's?

The feedback I had from AMD indicated using the Intel
strings for a family 15 cpu resulted in the least
amount of guest confusion.  The upstream kvm64 model
does similarly.

Sorry for my late response here which was preempted
by the intervening holiday.

-john

-- 
john.cooper@redhat.com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Add definitions for current cpu models..
  2010-01-18 16:45 john cooper
@ 2010-01-20 23:20 ` Arnd Bergmann
  0 siblings, 0 replies; 10+ messages in thread
From: Arnd Bergmann @ 2010-01-20 23:20 UTC (permalink / raw)
  To: john cooper; +Cc: KVM list, qemu-devel, Przywara, Andre, donald.d.dugger

On Monday 18 January 2010, john cooper wrote:
> +        .name = "Conroe",
> +        .level = 2,
> +        .vendor1 = CPUID_VENDOR_INTEL_1,
> +        .vendor2 = CPUID_VENDOR_INTEL_2,
> +        .vendor3 = CPUID_VENDOR_INTEL_3,
> +        .family = 6,   /* P6 */
> +        .model = 2,

                ^^^^^^^^ that looks wrong -- what is model 2 actually?

> +        .stepping = 3,
> +        .features = PPRO_FEATURES | 
> +            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |    /* note 1 */
> +            CPUID_PSE36,                                /* note 2 */
> +        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_SSSE3,
> +        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_MASK) | 
> +            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
> +        .ext3_features = CPUID_EXT3_LAHF_LM,
> +        .xlevel = 0x8000000A,
> +        .model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)",
> +    },

Celeron_4x0 is a rather bad example, because it is based on the 
single-core Conroe-L, which is family 6 / model 22 unlike all the dual-
and quad-core Merom/Conroe that are model 15.

> +    {
> +        .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 | 
> +            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |    /* note 1 */
> +            CPUID_PSE36,                                /* note 2 */
> +        .ext_features = CPUID_EXT_SSE3 |
> +            CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE41,
> +        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_MASK) | 
> +            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
> +        .ext3_features = CPUID_EXT3_LAHF_LM,
> +        .xlevel = 0x8000000A,
> +        .model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)",
> +    },

This would be model 23 for Penryn-class Xeon/Core/Pentium/Celeron processors
without L3 cache.

> +    {
> +        .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 | 
> +            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |    /* note 1 */
> +            CPUID_PSE36,                                /* note 2 */
> +        .ext_features = CPUID_EXT_SSE3 |
> +            CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE41 |
> +            CPUID_EXT_SSE42 | CPUID_EXT_POPCNT,
> +        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_MASK) | 
> +            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
> +        .ext3_features = CPUID_EXT3_LAHF_LM,
> +        .xlevel = 0x8000000A,
> +        .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)",
> +    },

Apparently, not all the i7-9xx CPUs are Nehalem, the i7-980X is supposed
to be Westmere, which has more features.

Because of the complexity, I'd recommend passing down the *model* number
of the emulated CPU, the interesting Intel ones (those supported by KVM) being:

15-6: CedarMill/Presler/Dempsey/Tulsa (Pentium 4/Pentium D/Xeon 50xx/Xeon 71xx)
6-14: Yonah/Sossaman (Celeron M4xx, Core Solo/Duo, Pentium Dual-Core T1000, Xeon ULV)
6-15: Merom/Conroe/Kentsfield/Woodcrest/Clovertown/Tigerton
      (Celeron M5xx/E1xxx/T1xxx, Pentium T2xxx/T3xxx/E2xxx,Core 2 Solo U2xxx,
       Core 2 Duo E4xxx/E6xxx/Q6xxx/T5xxx/T7xxx/L7xxx/U7xxx/SP7xxx,
       Xeon 30xx/32xx/51xx/52xx/72xx/73xx)
6-22: Penryn/Wolfdale/Yorkfield/Harpertown (Celeron 7xx/9xx/SU2xxx/T3xxx/E3xxx,
       Pentium T4xxx/SU2xxx/SU4xxx/E5xxx/E6xxx, Core 2 Solo SU3xxx,
       Core 2 Duo Pxxxx/SUxxxx/T6xxx/x8xxx/x9xxx,
       Xeon 31xx/33xx/52xx/54xx)
6-26: Gainestown/Bloomfield (Xeon 35xx/55xx, Core i7-9xx)
6-28: Atom
6-29: Dunnington (Xeon 74xx)
6-30: Lynnfield/Clarksfield/JasperForest (Xeon 34xx, Core i7-8xx, Core i7-xxxQM,
       Core i5-7xx)
6-37: Arrandale/Clarkdale (Dual-Core Core i3/i5/i7)
6-44: Gulftown (six-core)

	Arnd

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH] Add definitions for current cpu models..
@ 2010-01-18 16:45 john cooper
  2010-01-20 23:20 ` Arnd Bergmann
  0 siblings, 1 reply; 10+ messages in thread
From: john cooper @ 2010-01-18 16:45 UTC (permalink / raw)
  To: KVM list, qemu-devel; +Cc: john.cooper, Przywara, Andre, donald.d.dugger

This is a rework of the prior version which adds definitions
for contemporary processors selected via -cpu <model>, as an
alternative to the existing use of "-cpu qemu64" augmented
with a series of feature flags.

The primary motivation was determination of a least common
denominator within a given processor class to simplify guest
migration.  It is still possible to modify an arbitrary model
via additional feature flags however the goal here was to
make doing so unnecessary in typical usage.  The other
consideration was providing models names reflective of
current processors.  Both AMD and Intel have reviewed the
models in terms of balancing generality of migration vs.
excessive feature downgrade relative to released silicon. 

Concerning the prior version of the patch, the proposed name
used for a given model drew a fair amount of debate, the
main concern being use of names as mnemonic as possible to
the wisest group of users.  Another suggestion was to use
the vendor name of released silicon corresponding to a least
common denominator CPU within the class, rational being doing
so is more definitive of the intended functionality.  However
something like:

     -cpu "Intel Core 2 Duo P9xxx"

probably isn't all that easy to remember nor type when
selecting a Penryn class cpu.  So I struck what I believe to
be a reasonable compromise where the original x86_def_t.name
was for the most part retained with the x86_def_t.model_id
capturing the marketing name of the cpu being used as the
least common denominator for the class.  To make it easier for
a user to associate a *.name with *.model_id, "-cpu ?" invoked
rather as "-cpu ??" will append *.model_id to the generated
table:

        :
    x86           Conroe  Intel Celeron_4x0 (Conroe/Merom Class Core 2)   
    x86           Penryn  Intel Core 2 Duo P9xxx (Penryn Class Core 2)    
    x86          Nehalem  Intel Core i7 9xx (Nehalem Class Core i7)       
    x86       Opteron_G1  AMD Opteron 240 (Gen 1 Class Opteron)           
    x86       Opteron_G2  AMD Opteron 22xx (Gen 2 Class Opteron)          
    x86       Opteron_G3  AMD Opteron 23xx (Gen 3 Class Opteron)
        :         

As before a cpu feature 'check' option is added which warns when
feature flags (either implicit in a cpu model or explicit on the
command line) would have otherwise been quietly unavailable to a
guest:

    # qemu-system-x86_64 ... -cpu Nehalem,check
    warning: host cpuid 0000_0001 lacks requested flag 'sse4.2' [0x00100000]
    warning: host cpuid 0000_0001 lacks requested flag 'popcnt' [0x00800000]

This patch was tested relative to qemu.git.

Signed-off-by: john cooper <john.cooper@redhat.com>
---

diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index f3834b3..58400ab 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -722,8 +722,8 @@ typedef struct CPUX86State {
 CPUX86State *cpu_x86_init(const char *cpu_model);
 int cpu_x86_exec(CPUX86State *s);
 void cpu_x86_close(CPUX86State *s);
-void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt,
-                                                 ...));
+void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+                                const char *optarg);
 int cpu_get_pic_interrupt(CPUX86State *s);
 /* MSDOS compatibility mode FPU exception support */
 void cpu_set_ferr(CPUX86State *s);
@@ -875,7 +875,7 @@ uint64_t cpu_get_tsc(CPUX86State *env);
 #define cpu_exec cpu_x86_exec
 #define cpu_gen_code cpu_x86_gen_code
 #define cpu_signal_handler cpu_x86_signal_handler
-#define cpu_list x86_cpu_list
+#define cpu_list_id x86_cpu_list
 
 #define CPU_SAVE_VERSION 11
 
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 730e396..34f4936 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -42,7 +42,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, NULL, 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[] = {
@@ -58,6 +58,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,
@@ -111,10 +123,25 @@ typedef struct x86_def_t {
           CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
           CPUID_PSE36 | CPUID_FXSR)
 #define PENTIUM3_FEATURES (PENTIUM2_FEATURES | CPUID_SSE)
-#define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
-          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
-          CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
-          CPUID_PAE | CPUID_SEP | CPUID_APIC)
+
+#define PPRO_FEATURES (\
+    0|CPUID_SSE2|CPUID_SSE|CPUID_FXSR|            /* 7 */ \
+    CPUID_MMX|0 << 22|0 << 21|0 << 20|            /* 8 */ \
+    0 << 19|0 << 18|0 << 17|CPUID_PAT|            /* 1 */ \
+    CPUID_CMOV|0 << 14|CPUID_PGE|0 << 12|         /* a */ \
+    CPUID_SEP|0 << 10|CPUID_APIC|CPUID_CX8|       /* b */ \
+    CPUID_MCE|CPUID_PAE|CPUID_MSR|CPUID_TSC|      /* f */ \
+    CPUID_PSE|CPUID_DE|0 << 1|CPUID_FP87)         /* d */
+
+#define CPUID_EXT2_MASK (\
+    0 << 27|0 << 26|0 << 25|CPUID_FXSR|           /* 1 */ \
+    CPUID_MMX|0 << 22|0 << 21|0 << 20|            /* 8 */ \
+    0 << 19|0 << 18|CPUID_PSE36|CPUID_PAT|        /* 3 */ \
+    CPUID_CMOV|CPUID_MCA|CPUID_PGE|CPUID_MTRR|    /* f */ \
+    0 << 11|0 << 10|CPUID_APIC|CPUID_CX8|         /* 3 */ \
+    CPUID_MCE|CPUID_PAE|CPUID_MSR|CPUID_TSC|      /* f */ \
+    CPUID_PSE|CPUID_DE|CPUID_VME|CPUID_FP87)      /* f */
+
 static x86_def_t x86_defs[] = {
 #ifdef TARGET_X86_64
     {
@@ -127,12 +154,10 @@ static x86_def_t x86_defs[] = {
         .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,
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |    /* note 1 */
+            CPUID_PSE36,                                /* note 2 */
         .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT,
-        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | 
+        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_MASK) | 
             CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
         .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
             CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
@@ -155,7 +180,7 @@ static x86_def_t x86_defs[] = {
         .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 |
             CPUID_EXT_POPCNT,
         /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */
-        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | 
+        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_MASK) | 
             CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
             CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
             CPUID_EXT2_FFXSR,
@@ -169,6 +194,126 @@ static x86_def_t x86_defs[] = {
         .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor"
     },
     {
+        .name = "Conroe",
+        .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 | 
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |    /* note 1 */
+            CPUID_PSE36,                                /* note 2 */
+        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_SSSE3,
+        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_MASK) | 
+            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
+        .ext3_features = CPUID_EXT3_LAHF_LM,
+        .xlevel = 0x8000000A,
+        .model_id = "Intel Celeron_4x0 (Conroe/Merom Class 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 | 
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |    /* note 1 */
+            CPUID_PSE36,                                /* note 2 */
+        .ext_features = CPUID_EXT_SSE3 |
+            CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE41,
+        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_MASK) | 
+            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
+        .ext3_features = CPUID_EXT3_LAHF_LM,
+        .xlevel = 0x8000000A,
+        .model_id = "Intel Core 2 Duo P9xxx (Penryn Class 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 | 
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |    /* note 1 */
+            CPUID_PSE36,                                /* note 2 */
+        .ext_features = CPUID_EXT_SSE3 |
+            CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE41 |
+            CPUID_EXT_SSE42 | CPUID_EXT_POPCNT,
+        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_MASK) | 
+            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
+        .ext3_features = CPUID_EXT3_LAHF_LM,
+        .xlevel = 0x8000000A,
+        .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)",
+    },
+    {
+        .name = "Opteron_G1",
+        .level = 5,
+        .vendor1 = CPUID_VENDOR_AMD_1,
+        .vendor2 = CPUID_VENDOR_AMD_2,
+        .vendor3 = CPUID_VENDOR_AMD_3,
+        .family = 15,
+        .model = 6,
+        .stepping = 1,
+        .features = PPRO_FEATURES | 
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |    /* note 1 */
+            CPUID_PSE36,                                /* note 2 */
+        .ext_features = CPUID_EXT_SSE3,
+        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_MASK) | 
+            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
+        .xlevel = 0x80000008,
+        .model_id = "AMD Opteron 240 (Gen 1 Class Opteron)",
+    },
+    {
+        .name = "Opteron_G2",
+        .level = 5,
+        .vendor1 = CPUID_VENDOR_AMD_1,
+        .vendor2 = CPUID_VENDOR_AMD_2,
+        .vendor3 = CPUID_VENDOR_AMD_3,
+        .family = 15,
+        .model = 6,
+        .stepping = 1,
+        .features = PPRO_FEATURES | 
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |    /* note 1 */
+            CPUID_PSE36,                                /* note 2 */
+        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16,
+        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_MASK) | 
+            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
+            CPUID_EXT2_RDTSCP,
+        .ext3_features = CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
+        .xlevel = 0x80000008,
+        .model_id = "AMD Opteron 22xx (Gen 2 Class Opteron)",
+    },
+    {
+        .name = "Opteron_G3",
+        .level = 5,
+        .vendor1 = CPUID_VENDOR_AMD_1,
+        .vendor2 = CPUID_VENDOR_AMD_2,
+        .vendor3 = CPUID_VENDOR_AMD_3,
+        .family = 15,
+        .model = 6,
+        .stepping = 1,
+        .features = PPRO_FEATURES | 
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |    /* note 1 */
+            CPUID_PSE36,                                /* note 2 */
+        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR |
+            CPUID_EXT_POPCNT | CPUID_EXT_CX16,
+        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_MASK) | 
+            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 | CPUID_EXT3_LAHF_LM,
+        .xlevel = 0x80000008,
+        .model_id = "AMD Opteron 23xx (Gen 3 Class Opteron)",
+    },
+    {
         .name = "core2duo",
         .level = 10,
         .family = 6,
@@ -205,7 +350,7 @@ static x86_def_t x86_defs[] = {
         /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */
         .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16,
         /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */
-        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) |
+        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_MASK) |
             CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
         /* Missing: CPUID_EXT3_LAHF_LM, CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
                     CPUID_EXT3_CR8LEG, CPUID_EXT3_ABM, CPUID_EXT3_SSE4A,
@@ -292,7 +437,7 @@ static x86_def_t x86_defs[] = {
         .model = 2,
         .stepping = 3,
         .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA,
-        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
+        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_MASK) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
         .xlevel = 0x80000008,
         /* XXX: put another string ? */
         .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
@@ -313,12 +458,16 @@ static x86_def_t x86_defs[] = {
             CPUID_EXT_SSE3 /* PNI */ | CPUID_EXT_SSSE3,
             /* Missing: CPUID_EXT_DSCPL | CPUID_EXT_EST |
              * CPUID_EXT_TM2 | CPUID_EXT_XTPR */
-        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | CPUID_EXT2_NX,
+        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_MASK) | CPUID_EXT2_NX,
         /* Missing: .ext3_features = CPUID_EXT3_LAHF_LM */
         .xlevel = 0x8000000A,
         .model_id = "Intel(R) Atom(TM) CPU N270   @ 1.60GHz",
-    },
+    }
 };
+/* notes for preceeding cpu models:
+ *   1: these features are needed for Win64 and aren't fully implemented
+ *   2: this feature is needed for Solaris and isn't fully implemented
+ */
 
 static void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax,
                                uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
@@ -368,6 +517,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;
@@ -471,6 +665,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;
@@ -485,6 +681,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;
 
@@ -493,12 +692,19 @@ error:
     return -1;
 }
 
-void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
+void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+                  const char *optarg)
 {
     unsigned int i;
+    unsigned char id = !strcmp("??", optarg);
 
     for (i = 0; i < ARRAY_SIZE(x86_defs); i++)
-        (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name);
+        if (id) {
+            (*cpu_fprintf)(f, "x86 %16s  %-48s\n", x86_defs[i].name,
+                x86_defs[i].model_id);
+        } else {
+            (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name);
+        }
 }
 
 static int cpu_x86_register (CPUX86State *env, const char *cpu_model)
diff --git a/vl.c b/vl.c
index e606903..b1d8490 100644
--- a/vl.c
+++ b/vl.c
@@ -4982,8 +4982,12 @@ int main(int argc, char **argv, char **envp)
                 /* hw initialization will check this */
                 if (*optarg == '?') {
 /* XXX: implement xxx_cpu_list for targets that still miss it */
-#if defined(cpu_list)
+#if defined(cpu_list_id)
+                    cpu_list_id(stdout, &fprintf, optarg);
+#elif defined(cpu_list)	/* revert to previous func definition */
                     cpu_list(stdout, &fprintf);
+#else
+#error cpu_list_id() is undefined for this architecture.
 #endif
                     exit(0);
                 } else {

-- 
john.cooper@redhat.com

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2010-01-20 23:20 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-12-21  6:46 [PATCH] Add definitions for current cpu models john cooper
2009-12-21  6:46 ` [Qemu-devel] " john cooper
2009-12-24 13:05 ` Marcelo Tosatti
2010-01-05  6:06   ` john cooper
2010-01-05  6:06     ` [Qemu-devel] " john cooper
2009-12-24 13:45 ` [Qemu-devel] " Avi Kivity
2009-12-31  3:13 ` Jamie Lokier
2009-12-31 14:38 ` Anthony Liguori
2010-01-18 16:45 john cooper
2010-01-20 23:20 ` Arnd Bergmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.