Skip to contentSkip to conversation

Add definitions for current cpu models..

PATCH In review john cooper 5 participants 6 messages Dec 21, 2009 – Jan 5, 2010 KVM

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Add definitions for current cpu models..

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.

---

target-i386/helper.c +197 -2
index 9a50da6..a706cae 100644
@@ -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;
 
Signature · 1 line
[email protected]
#1 lore raw
Quoted 32 lines · 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.

---

target-i386/helper.c +0 -0
index 9a50da6..a706cae 100644

target-i386/helper.c static const char *feature_name[] = { · line 49

Quoted 7 lines
target-i386/helper.c +1 -1
@@ -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?

Quoted 106 lines
target-i386/helper.c +94 -0
 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,

target-i386/helper.c static x86_def_t x86_defs[] = { · line 277

Quoted 10 lines
target-i386/helper.c +10 -0
+        .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?

Quoted 4 lines
target-i386/helper.c +4 -0
+static int unavailable_host_feature(struct model_features_t *f, uint32_t mask)
+{
+    int i;
+

target-i386/helper.c static int cpu_x86_fill_host(x86_def_t *x86_cpu_def) · line 531

Quoted 10 lines
target-i386/helper.c +10 -0
+    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.

#3 lore raw
In reply to john cooper
Quoted 17 lines · 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.

Quoted 7 lines

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.

Signature · 1 line
error compiling committee.c: too many arguments to function
#4 lore raw
In reply to john cooper
Quoted 5 lines · john cooper
     {
target-i386/helper.c +4 -0
+        .name = "Merom",
+        .level = 2,
+        .vendor1 = CPUID_VENDOR_INTEL_1,
+        .vendor2 = CPUID_VENDOR_INTEL_2,

target-i386/helper.c static x86_def_t x86_defs[] = { · line 199

Quoted 10 lines
target-i386/helper.c +10 -0
+        .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?

Quoted 1 line

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

target-i386/helper.c static x86_def_t x86_defs[] = { · line 205

Quoted 5 lines
target-i386/helper.c +5 -0
+            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.

Quoted 12 lines
target-i386/helper.c +12 -0
+    {
+        .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 |

target-i386/helper.c static x86_def_t x86_defs[] = { · line 227

Quoted 10 lines
target-i386/helper.c +10 -0
+        /* 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?

Quoted 13 lines
target-i386/helper.c +13 -0
+    {
+        .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 */

target-i386/helper.c static x86_def_t x86_defs[] = { · line 250

Quoted 10 lines
target-i386/helper.c +10 -0
+            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.

target-i386/helper.c static x86_def_t x86_defs[] = { · line 256

Quoted 6 lines
target-i386/helper.c +6 -0
+    {
+        .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?

Quoted 5 lines
target-i386/helper.c +5 -0
+        .family = 15,
+        .model = 6,
+        .stepping = 1,
+        .features = PPRO_FEATURES | 
+        /* these features are needed for Win64 and aren't fully implemented */

target-i386/helper.c static x86_def_t x86_defs[] = { · line 271

Quoted 10 lines
target-i386/helper.c +10 -0
+            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?

Quoted 4 lines
target-i386/helper.c +4 -0
+    {
+        .name = "Opteron_G2",
+        .level = 5,
+        .vendor1 = CPUID_VENDOR_INTEL_1,

target-i386/helper.c static x86_def_t x86_defs[] = { · line 285

Quoted 10 lines
target-i386/helper.c +10 -0
+        .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 :-)

target-i386/helper.c static x86_def_t x86_defs[] = { · line 318

Quoted 4 lines
target-i386/helper.c +4 -0
+        .model_id = "AMD Opteron G3",
+    },
+        /* this feature is needed for Solaris and isn't fully implemented */
+    {

The above Solaris comment seems out of place.

Quoted 1 line
         .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.

target-i386/helper.c static x86_def_t x86_defs[] = { · line 468

Quoted 9 lines
         .level = 10,
         .family = 6,
target-i386/helper.c +1 -1
@@ -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 :-)

target-i386/helper.c static int cpu_x86_fill_host(x86_def_t *x86_cpu_def) · line 536

Quoted 4 lines
target-i386/helper.c +4 -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.
+ */

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

#5 lore raw
In reply to john cooper

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" <[email protected]> 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.

---

target-i386/helper.c +0 -0
index 9a50da6..a706cae 100644
@@ -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;

--
[email protected]
--
To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#2 lore raw
In reply to Marcelo Tosatti
Quoted 9 lines · Marcelo Tosatti

target-i386/helper.c static x86_def_t x86_defs[] = { · line 277

Quoted 6 lines · john cooper
target-i386/helper.c +6 -0
+    {
+        .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

Signature · 1 line
[email protected]