All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Add definitions for current cpu models..
@ 2010-01-18 16:45 ` john cooper
  0 siblings, 0 replies; 76+ 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] 76+ messages in thread
* [Qemu-devel] [PATCH] Add definitions for current cpu models..
@ 2009-12-21  6:46 john cooper
  2009-12-24 13:45 ` Avi Kivity
  2009-12-31  3:13 ` Jamie Lokier
  0 siblings, 2 replies; 76+ 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] 76+ messages in thread

end of thread, other threads:[~2010-01-28 14:10 UTC | newest]

Thread overview: 76+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-01-18 16:45 [PATCH] Add definitions for current cpu models john cooper
2010-01-18 16:45 ` [Qemu-devel] " john cooper
2010-01-19 19:39 ` Anthony Liguori
2010-01-19 19:39   ` Anthony Liguori
2010-01-19 20:03   ` Chris Wright
2010-01-19 22:12     ` Jamie Lokier
2010-01-19 22:12       ` Jamie Lokier
2010-01-19 22:20       ` Chris Wright
2010-01-19 22:20         ` Chris Wright
2010-01-19 22:25     ` Anthony Liguori
2010-01-20  0:15       ` Chris Wright
2010-01-20  0:15         ` Chris Wright
2010-01-20 14:21         ` Anthony Liguori
2010-01-20 14:27           ` Gleb Natapov
2010-01-20 14:27             ` Gleb Natapov
2010-01-20  1:38       ` Jamie Lokier
2010-01-20  1:38         ` Jamie Lokier
2010-01-20 20:09       ` john cooper
2010-01-20 20:26         ` Daniel P. Berrange
2010-01-20 20:26           ` Daniel P. Berrange
2010-01-20 20:53           ` Anthony Liguori
2010-01-20 20:53             ` Anthony Liguori
2010-01-21  0:25           ` Chris Wright
2010-01-21  0:25             ` Chris Wright
2010-01-21  1:18             ` john cooper
2010-01-21  1:18               ` john cooper
2010-01-21 14:39               ` Andre Przywara
2010-01-21 14:39                 ` Andre Przywara
2010-01-21 17:06                 ` Blue Swirl
2010-01-21 15:05               ` Anthony Liguori
2010-01-21 15:05                 ` Anthony Liguori
2010-01-21 16:43                 ` john cooper
2010-01-21 16:43                   ` john cooper
2010-01-21 18:59                   ` Anthony Liguori
2010-01-21 18:59                     ` Anthony Liguori
2010-01-25  9:08                 ` Dor Laor
2010-01-25  9:08                   ` Dor Laor
2010-01-25 11:27                   ` Jamie Lokier
2010-01-25 11:27                     ` Jamie Lokier
2010-01-25 14:21                   ` Anthony Liguori
2010-01-25 14:21                     ` Anthony Liguori
2010-01-25 22:35                     ` Dor Laor
2010-01-26  8:26                       ` Gerd Hoffmann
2010-01-26  8:26                         ` Gerd Hoffmann
2010-01-26 12:54                         ` Anthony Liguori
2010-01-26 12:54                           ` Anthony Liguori
2010-01-28  8:19                   ` Arnd Bergmann
2010-01-28  8:19                     ` Arnd Bergmann
2010-01-28  8:43                     ` Alexander Graf
2010-01-28  8:43                       ` Alexander Graf
2010-01-28 10:09                       ` Arnd Bergmann
2010-01-28 10:09                         ` Arnd Bergmann
2010-01-28 14:10                       ` Anthony Liguori
2010-01-28 14:10                         ` Anthony Liguori
2010-01-19 22:11   ` Jamie Lokier
2010-01-20 20:09     ` john cooper
2010-01-20 20:09       ` john cooper
2010-01-21 17:50       ` Jamie Lokier
2010-01-21 17:50         ` Jamie Lokier
2010-01-21 18:13       ` Jamie Lokier
2010-01-21 18:13         ` Jamie Lokier
2010-01-21 18:36         ` john cooper
2010-01-21 18:36           ` john cooper
2010-01-19 22:15 ` Jamie Lokier
2010-01-19 22:15   ` Jamie Lokier
2010-01-20 20:11   ` john cooper
2010-01-20 20:11     ` john cooper
2010-01-21 17:55     ` Jamie Lokier
2010-01-21 17:55       ` Jamie Lokier
2010-01-21 18:34       ` john cooper
2010-01-21 18:34         ` john cooper
2010-01-20 23:20 ` Arnd Bergmann
2010-01-20 23:20   ` [Qemu-devel] " Arnd Bergmann
  -- strict thread matches above, loose matches on Subject: below --
2009-12-21  6:46 [Qemu-devel] " john cooper
2009-12-24 13:45 ` Avi Kivity
2009-12-31  3:13 ` Jamie Lokier

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.