All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/13] i386 cpuid: cleanup and fixes
@ 2010-02-02 10:08 Andre Przywara
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 01/13] cpuid: move CPUID functions into separate file Andre Przywara
                   ` (12 more replies)
  0 siblings, 13 replies; 18+ messages in thread
From: Andre Przywara @ 2010-02-02 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: john.cooper

Hi,

first: I know that this conflicts with John Cooper's latest patch, but I want
to send this out for review and to help merging the stuff.

This patchset cleans up the CPUID handling code in QEMU. The biggest change
is obviously the move of the CPUID function to a separate file (cpuid.c).
This helps to split up a rather large source file, which's name (helper.c) is
also a bit misleading.
Please tell me soon if you don't like it so that I can rebase the rest of
patches.
Additionally the rest of the patches beautifies or simplifies some code.
Feature additions are:
 5/13: add missing CPUID feature bit names
 6/13: list CPUID feature bit names when using -cpu ?
 9/13: -cpu host propagates more CPUID leafs, so that the cache topology
       will be visibile in the guest
10/13: add CPUID feature bit trimming for TCG: Features not supported by
       the emulator will be masked out.
11/13: always show all CPU types: also expose the newer (64bit) CPU types
       for the i386 emulator. 64bit features will be masked out due to 10/13.
12/13: add kvm32 CPU model: Per popular request add a counterpart to kvm64
       describing a basic hardware virtualization capable CPU for migration
       purposes.

More details in the commit messages.

Note: In opposite to the last version I left out patches which change
the CPUID bits of existing CPU models to avoid regressions with guests.

Please review and comment.

Regards,
Andre.

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

* [Qemu-devel] [PATCH 01/13] cpuid: move CPUID functions into separate file
  2010-02-02 10:08 [Qemu-devel] [PATCH 00/13] i386 cpuid: cleanup and fixes Andre Przywara
@ 2010-02-02 10:08 ` Andre Przywara
  2010-03-06 18:25   ` Aurelien Jarno
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 02/13] cpuid: replace magic number with named constant Andre Przywara
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 18+ messages in thread
From: Andre Przywara @ 2010-02-02 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: john.cooper, Andre Przywara

about 40% of target-i386/helper.c consist of CPUID related functions.
Only one of them is a real TCG helper function. So move the whole
CPUID stuff out of this into a separate file to get better
maintainable parts.
This is only code reordering and should not affect QEMU's
functionality.

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
---
 Makefile.target      |    3 +
 target-i386/cpu.h    |    3 +
 target-i386/cpuid.c  |  821 ++++++++++++++++++++++++++++++++++++++++++++++++++
 target-i386/helper.c |  779 -----------------------------------------------
 4 files changed, 827 insertions(+), 779 deletions(-)
 create mode 100644 target-i386/cpuid.c

diff --git a/Makefile.target b/Makefile.target
index 5c0ef1f..37875b8 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -49,6 +49,9 @@ libobj-y += tcg/tcg.o
 libobj-$(CONFIG_SOFTFLOAT) += fpu/softfloat.o
 libobj-$(CONFIG_NOSOFTFLOAT) += fpu/softfloat-native.o
 libobj-y += op_helper.o helper.o
+ifeq ($(TARGET_BASE_ARCH), i386)
+libobj-y += cpuid.o
+endif
 libobj-$(CONFIG_NEED_MMU) += mmu.o
 libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
 libobj-$(TARGET_ALPHA) += alpha_palcode.o
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 216b00e..f826d3d 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -825,9 +825,12 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
                              int is_write, int mmu_idx, int is_softmmu);
 #define cpu_handle_mmu_fault cpu_x86_handle_mmu_fault
 void cpu_x86_set_a20(CPUX86State *env, int a20_state);
+
+/* cpuid.c */
 void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
                    uint32_t *eax, uint32_t *ebx,
                    uint32_t *ecx, uint32_t *edx);
+int cpu_x86_register (CPUX86State *env, const char *cpu_model);
 
 static inline int hw_breakpoint_enabled(unsigned long dr7, int index)
 {
diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
new file mode 100644
index 0000000..aaa14ba
--- /dev/null
+++ b/target-i386/cpuid.c
@@ -0,0 +1,821 @@
+/*
+ *  i386 CPUID helper functions
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "cpu.h"
+#include "kvm.h"
+
+/* feature flags taken from "Intel Processor Identification and the CPUID
+ * Instruction" and AMD's "CPUID Specification". In cases of disagreement
+ * about feature names, the Linux name is used. */
+static const char *feature_name[] = {
+    "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
+    "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
+    "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */,
+        NULL, "ds" /* Intel dts */, "acpi", "mmx",
+    "fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe",
+};
+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, NULL, NULL, NULL, NULL, NULL, "hypervisor",
+};
+static const char *ext2_feature_name[] = {
+    "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
+    "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall",
+        "mtrr", "pge", "mca", "cmov",
+    "pat", "pse36", NULL, NULL /* Linux mp */,
+        "nx" /* Intel xd */, NULL, "mmxext", "mmx",
+    "fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp",
+        NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow",
+};
+static const char *ext3_feature_name[] = {
+    "lahf_lm" /* AMD LahfSahf */, "cmp_legacy",
+        "svm", "extapic" /* AMD ExtApicSpace */,
+        "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
+    "3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+};
+
+static const char *kvm_feature_name[] = {
+    "kvmclock", "kvm_nopiodelay", "kvm_mmu", NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+};
+
+static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
+                                    uint32_t *ext_features,
+                                    uint32_t *ext2_features,
+                                    uint32_t *ext3_features,
+                                    uint32_t *kvm_features)
+{
+    int i;
+    int found = 0;
+
+    for ( i = 0 ; i < 32 ; i++ )
+        if (feature_name[i] && !strcmp (flagname, feature_name[i])) {
+            *features |= 1 << i;
+            found = 1;
+        }
+    for ( i = 0 ; i < 32 ; i++ )
+        if (ext_feature_name[i] && !strcmp (flagname, ext_feature_name[i])) {
+            *ext_features |= 1 << i;
+            found = 1;
+        }
+    for ( i = 0 ; i < 32 ; i++ )
+        if (ext2_feature_name[i] && !strcmp (flagname, ext2_feature_name[i])) {
+            *ext2_features |= 1 << i;
+            found = 1;
+        }
+    for ( i = 0 ; i < 32 ; i++ )
+        if (ext3_feature_name[i] && !strcmp (flagname, ext3_feature_name[i])) {
+            *ext3_features |= 1 << i;
+            found = 1;
+        }
+    for ( i = 0 ; i < 32 ; i++ )
+        if (kvm_feature_name[i] && !strcmp (flagname, kvm_feature_name[i])) {
+            *kvm_features |= 1 << i;
+            found = 1;
+        }
+
+    if (!found) {
+        fprintf(stderr, "CPU feature %s not found\n", flagname);
+    }
+}
+
+typedef struct x86_def_t {
+    const char *name;
+    uint32_t level;
+    uint32_t vendor1, vendor2, vendor3;
+    int family;
+    int model;
+    int stepping;
+    uint32_t features, ext_features, ext2_features, ext3_features, kvm_features;
+    uint32_t xlevel;
+    char model_id[48];
+    int vendor_override;
+} x86_def_t;
+
+#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
+#define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
+          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC)
+#define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
+          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)
+static x86_def_t x86_defs[] = {
+#ifdef TARGET_X86_64
+    {
+        .name = "qemu64",
+        .level = 4,
+        .vendor1 = CPUID_VENDOR_AMD_1,
+        .vendor2 = CPUID_VENDOR_AMD_2,
+        .vendor3 = CPUID_VENDOR_AMD_3,
+        .family = 6,
+        .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_POPCNT,
+        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | 
+            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
+        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
+            CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
+        .xlevel = 0x8000000A,
+        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
+    },
+    {
+        .name = "phenom",
+        .level = 5,
+        .vendor1 = CPUID_VENDOR_AMD_1,
+        .vendor2 = CPUID_VENDOR_AMD_2,
+        .vendor3 = CPUID_VENDOR_AMD_3,
+        .family = 16,
+        .model = 2,
+        .stepping = 3,
+        /* Missing: CPUID_VME, CPUID_HT */
+        .features = PPRO_FEATURES | 
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
+            CPUID_PSE36,
+        .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) | 
+            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
+            CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
+            CPUID_EXT2_FFXSR,
+        /* Missing: CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
+                    CPUID_EXT3_CR8LEG,
+                    CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
+                    CPUID_EXT3_OSVW, CPUID_EXT3_IBS */
+        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
+            CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
+        .xlevel = 0x8000001A,
+        .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor"
+    },
+    {
+        .name = "core2duo",
+        .level = 10,
+        .family = 6,
+        .model = 15,
+        .stepping = 11,
+	/* The original CPU also implements these features:
+               CPUID_VME, CPUID_DTS, CPUID_ACPI, CPUID_SS, CPUID_HT,
+               CPUID_TM, CPUID_PBE */
+        .features = PPRO_FEATURES |
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
+            CPUID_PSE36,
+	/* The original CPU also implements these ext features:
+               CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST,
+               CPUID_EXT_TM2, CPUID_EXT_CX16, CPUID_EXT_XTPR, CPUID_EXT_PDCM */
+        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3,
+        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
+        .ext3_features = CPUID_EXT3_LAHF_LM,
+        .xlevel = 0x80000008,
+        .model_id = "Intel(R) Core(TM)2 Duo CPU     T7700  @ 2.40GHz",
+    },
+    {
+        .name = "kvm64",
+        .level = 5,
+        .vendor1 = CPUID_VENDOR_INTEL_1,
+        .vendor2 = CPUID_VENDOR_INTEL_2,
+        .vendor3 = CPUID_VENDOR_INTEL_3,
+        .family = 15,
+        .model = 6,
+        .stepping = 1,
+        /* Missing: CPUID_VME, CPUID_HT */
+        .features = PPRO_FEATURES |
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
+            CPUID_PSE36,
+        /* 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) |
+            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,
+                    CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
+                    CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */
+        .ext3_features = 0,
+        .xlevel = 0x80000008,
+        .model_id = "Common KVM processor"
+    },
+#endif
+    {
+        .name = "qemu32",
+        .level = 4,
+        .family = 6,
+        .model = 3,
+        .stepping = 3,
+        .features = PPRO_FEATURES,
+        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
+        .xlevel = 0,
+        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
+    },
+    {
+        .name = "coreduo",
+        .level = 10,
+        .family = 6,
+        .model = 14,
+        .stepping = 8,
+        /* The original CPU also implements these features:
+               CPUID_DTS, CPUID_ACPI, CPUID_SS, CPUID_HT,
+               CPUID_TM, CPUID_PBE */
+        .features = PPRO_FEATURES | CPUID_VME |
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA,
+        /* The original CPU also implements these ext features:
+               CPUID_EXT_VMX, CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_XTPR,
+               CPUID_EXT_PDCM */
+        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR,
+        .ext2_features = CPUID_EXT2_NX,
+        .xlevel = 0x80000008,
+        .model_id = "Genuine Intel(R) CPU           T2600  @ 2.16GHz",
+    },
+    {
+        .name = "486",
+        .level = 0,
+        .family = 4,
+        .model = 0,
+        .stepping = 0,
+        .features = I486_FEATURES,
+        .xlevel = 0,
+    },
+    {
+        .name = "pentium",
+        .level = 1,
+        .family = 5,
+        .model = 4,
+        .stepping = 3,
+        .features = PENTIUM_FEATURES,
+        .xlevel = 0,
+    },
+    {
+        .name = "pentium2",
+        .level = 2,
+        .family = 6,
+        .model = 5,
+        .stepping = 2,
+        .features = PENTIUM2_FEATURES,
+        .xlevel = 0,
+    },
+    {
+        .name = "pentium3",
+        .level = 2,
+        .family = 6,
+        .model = 7,
+        .stepping = 3,
+        .features = PENTIUM3_FEATURES,
+        .xlevel = 0,
+    },
+    {
+        .name = "athlon",
+        .level = 2,
+        .vendor1 = CPUID_VENDOR_AMD_1,
+        .vendor2 = CPUID_VENDOR_AMD_2,
+        .vendor3 = CPUID_VENDOR_AMD_3,
+        .family = 6,
+        .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,
+        .xlevel = 0x80000008,
+        /* XXX: put another string ? */
+        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
+    },
+    {
+        .name = "n270",
+        /* original is on level 10 */
+        .level = 5,
+        .family = 6,
+        .model = 28,
+        .stepping = 2,
+        .features = PPRO_FEATURES |
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME,
+            /* Missing: CPUID_DTS | CPUID_ACPI | CPUID_SS |
+             * CPUID_HT | CPUID_TM | CPUID_PBE */
+            /* Some CPUs got no CPUID_SEP */
+        .ext_features = CPUID_EXT_MONITOR |
+            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,
+        /* 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,
+                               uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
+
+static int cpu_x86_fill_model_id(char *str)
+{
+    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+    int i;
+
+    for (i = 0; i < 3; i++) {
+        host_cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx);
+        memcpy(str + i * 16 +  0, &eax, 4);
+        memcpy(str + i * 16 +  4, &ebx, 4);
+        memcpy(str + i * 16 +  8, &ecx, 4);
+        memcpy(str + i * 16 + 12, &edx, 4);
+    }
+    return 0;
+}
+
+static int cpu_x86_fill_host(x86_def_t *x86_cpu_def)
+{
+    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+    x86_cpu_def->name = "host";
+    host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
+    x86_cpu_def->level = eax;
+    x86_cpu_def->vendor1 = ebx;
+    x86_cpu_def->vendor2 = edx;
+    x86_cpu_def->vendor3 = ecx;
+
+    host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
+    x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
+    x86_cpu_def->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
+    x86_cpu_def->stepping = eax & 0x0F;
+    x86_cpu_def->ext_features = ecx;
+    x86_cpu_def->features = edx;
+
+    host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx);
+    x86_cpu_def->xlevel = eax;
+
+    host_cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx);
+    x86_cpu_def->ext2_features = edx;
+    x86_cpu_def->ext3_features = ecx;
+    cpu_x86_fill_model_id(x86_cpu_def->model_id);
+    x86_cpu_def->vendor_override = 0;
+
+    return 0;
+}
+
+static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
+{
+    unsigned int i;
+    x86_def_t *def;
+
+    char *s = strdup(cpu_model);
+    char *featurestr, *name = strtok(s, ",");
+    uint32_t plus_features = 0, plus_ext_features = 0,
+        plus_ext2_features = 0, plus_ext3_features = 0, plus_kvm_features = 0;
+    uint32_t minus_features = 0, minus_ext_features = 0,
+        minus_ext2_features = 0, minus_ext3_features = 0,
+        minus_kvm_features = 0;
+    uint32_t numvalue;
+
+    def = NULL;
+    for (i = 0; i < ARRAY_SIZE(x86_defs); i++) {
+        if (strcmp(name, x86_defs[i].name) == 0) {
+            def = &x86_defs[i];
+            break;
+        }
+    }
+    if (kvm_enabled() && strcmp(name, "host") == 0) {
+        cpu_x86_fill_host(x86_cpu_def);
+    } else if (!def) {
+        goto error;
+    } else {
+        memcpy(x86_cpu_def, def, sizeof(*def));
+    }
+
+    plus_kvm_features = ~0; /* not supported bits will be filtered out later */
+
+    add_flagname_to_bitmaps("hypervisor", &plus_features,
+        &plus_ext_features, &plus_ext2_features, &plus_ext3_features,
+        &plus_kvm_features);
+
+    featurestr = strtok(NULL, ",");
+
+    while (featurestr) {
+        char *val;
+        if (featurestr[0] == '+') {
+            add_flagname_to_bitmaps(featurestr + 1, &plus_features,
+                                    &plus_ext_features, &plus_ext2_features,
+                                    &plus_ext3_features, &plus_kvm_features);
+        } else if (featurestr[0] == '-') {
+            add_flagname_to_bitmaps(featurestr + 1, &minus_features,
+                                    &minus_ext_features, &minus_ext2_features,
+                                    &minus_ext3_features, &minus_kvm_features);
+        } else if ((val = strchr(featurestr, '='))) {
+            *val = 0; val++;
+            if (!strcmp(featurestr, "family")) {
+                char *err;
+                numvalue = strtoul(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                x86_cpu_def->family = numvalue;
+            } else if (!strcmp(featurestr, "model")) {
+                char *err;
+                numvalue = strtoul(val, &err, 0);
+                if (!*val || *err || numvalue > 0xff) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                x86_cpu_def->model = numvalue;
+            } else if (!strcmp(featurestr, "stepping")) {
+                char *err;
+                numvalue = strtoul(val, &err, 0);
+                if (!*val || *err || numvalue > 0xf) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                x86_cpu_def->stepping = numvalue ;
+            } else if (!strcmp(featurestr, "level")) {
+                char *err;
+                numvalue = strtoul(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                x86_cpu_def->level = numvalue;
+            } else if (!strcmp(featurestr, "xlevel")) {
+                char *err;
+                numvalue = strtoul(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                if (numvalue < 0x80000000) {
+                	numvalue += 0x80000000;
+                }
+                x86_cpu_def->xlevel = numvalue;
+            } else if (!strcmp(featurestr, "vendor")) {
+                if (strlen(val) != 12) {
+                    fprintf(stderr, "vendor string must be 12 chars long\n");
+                    goto error;
+                }
+                x86_cpu_def->vendor1 = 0;
+                x86_cpu_def->vendor2 = 0;
+                x86_cpu_def->vendor3 = 0;
+                for(i = 0; i < 4; i++) {
+                    x86_cpu_def->vendor1 |= ((uint8_t)val[i    ]) << (8 * i);
+                    x86_cpu_def->vendor2 |= ((uint8_t)val[i + 4]) << (8 * i);
+                    x86_cpu_def->vendor3 |= ((uint8_t)val[i + 8]) << (8 * i);
+                }
+                x86_cpu_def->vendor_override = 1;
+            } else if (!strcmp(featurestr, "model_id")) {
+                pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id),
+                        val);
+            } else {
+                fprintf(stderr, "unrecognized feature %s\n", featurestr);
+                goto error;
+            }
+        } else {
+            fprintf(stderr, "feature string `%s' not in format "
+                            "(+feature|-feature|feature=xyz)\n", featurestr);
+            goto error;
+        }
+        featurestr = strtok(NULL, ",");
+    }
+    x86_cpu_def->features |= plus_features;
+    x86_cpu_def->ext_features |= plus_ext_features;
+    x86_cpu_def->ext2_features |= plus_ext2_features;
+    x86_cpu_def->ext3_features |= plus_ext3_features;
+    x86_cpu_def->kvm_features |= plus_kvm_features;
+    x86_cpu_def->features &= ~minus_features;
+    x86_cpu_def->ext_features &= ~minus_ext_features;
+    x86_cpu_def->ext2_features &= ~minus_ext2_features;
+    x86_cpu_def->ext3_features &= ~minus_ext3_features;
+    x86_cpu_def->kvm_features &= ~minus_kvm_features;
+    free(s);
+    return 0;
+
+error:
+    free(s);
+    return -1;
+}
+
+void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
+{
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(x86_defs); i++)
+        (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name);
+}
+
+int cpu_x86_register (CPUX86State *env, const char *cpu_model)
+{
+    x86_def_t def1, *def = &def1;
+
+    if (cpu_x86_find_by_name(def, cpu_model) < 0)
+        return -1;
+    if (def->vendor1) {
+        env->cpuid_vendor1 = def->vendor1;
+        env->cpuid_vendor2 = def->vendor2;
+        env->cpuid_vendor3 = def->vendor3;
+    } else {
+        env->cpuid_vendor1 = CPUID_VENDOR_INTEL_1;
+        env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2;
+        env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3;
+    }
+    env->cpuid_vendor_override = def->vendor_override;
+    env->cpuid_level = def->level;
+    if (def->family > 0x0f)
+        env->cpuid_version = 0xf00 | ((def->family - 0x0f) << 20);
+    else
+        env->cpuid_version = def->family << 8;
+    env->cpuid_version |= ((def->model & 0xf) << 4) | ((def->model >> 4) << 16);
+    env->cpuid_version |= def->stepping;
+    env->cpuid_features = def->features;
+    env->pat = 0x0007040600070406ULL;
+    env->cpuid_ext_features = def->ext_features;
+    env->cpuid_ext2_features = def->ext2_features;
+    env->cpuid_xlevel = def->xlevel;
+    env->cpuid_kvm_features = def->kvm_features;
+    {
+        const char *model_id = def->model_id;
+        int c, len, i;
+        if (!model_id)
+            model_id = "";
+        len = strlen(model_id);
+        for(i = 0; i < 48; i++) {
+            if (i >= len)
+                c = '\0';
+            else
+                c = (uint8_t)model_id[i];
+            env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
+        }
+    }
+    return 0;
+}
+
+static void host_cpuid(uint32_t function, uint32_t count,
+                       uint32_t *eax, uint32_t *ebx,
+                       uint32_t *ecx, uint32_t *edx)
+{
+#if defined(CONFIG_KVM)
+    uint32_t vec[4];
+
+#ifdef __x86_64__
+    asm volatile("cpuid"
+                 : "=a"(vec[0]), "=b"(vec[1]),
+                   "=c"(vec[2]), "=d"(vec[3])
+                 : "0"(function), "c"(count) : "cc");
+#else
+    asm volatile("pusha \n\t"
+                 "cpuid \n\t"
+                 "mov %%eax, 0(%2) \n\t"
+                 "mov %%ebx, 4(%2) \n\t"
+                 "mov %%ecx, 8(%2) \n\t"
+                 "mov %%edx, 12(%2) \n\t"
+                 "popa"
+                 : : "a"(function), "c"(count), "S"(vec)
+                 : "memory", "cc");
+#endif
+
+    if (eax)
+	*eax = vec[0];
+    if (ebx)
+	*ebx = vec[1];
+    if (ecx)
+	*ecx = vec[2];
+    if (edx)
+	*edx = vec[3];
+#endif
+}
+
+static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx,
+                             uint32_t *ecx, uint32_t *edx)
+{
+    *ebx = env->cpuid_vendor1;
+    *edx = env->cpuid_vendor2;
+    *ecx = env->cpuid_vendor3;
+
+    /* sysenter isn't supported on compatibility mode on AMD, syscall
+     * isn't supported in compatibility mode on Intel.
+     * Normally we advertise the actual cpu vendor, but you can override
+     * this if you want to use KVM's sysenter/syscall emulation
+     * in compatibility mode and when doing cross vendor migration
+     */
+    if (kvm_enabled() && env->cpuid_vendor_override) {
+        host_cpuid(0, 0, NULL, ebx, ecx, edx);
+    }
+}
+
+void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
+                   uint32_t *eax, uint32_t *ebx,
+                   uint32_t *ecx, uint32_t *edx)
+{
+    /* test if maximum index reached */
+    if (index & 0x80000000) {
+        if (index > env->cpuid_xlevel)
+            index = env->cpuid_level;
+    } else {
+        if (index > env->cpuid_level)
+            index = env->cpuid_level;
+    }
+
+    switch(index) {
+    case 0:
+        *eax = env->cpuid_level;
+        get_cpuid_vendor(env, ebx, ecx, edx);
+        break;
+    case 1:
+        *eax = env->cpuid_version;
+        /* CLFLUSH size in quad words, Linux wants it. */
+        *ebx = (env->cpuid_apic_id << 24) | 8 << 8;
+        *ecx = env->cpuid_ext_features;
+        *edx = env->cpuid_features;
+        if (env->nr_cores * env->nr_threads > 1) {
+            *ebx |= (env->nr_cores * env->nr_threads) << 16;
+            *edx |= 1 << 28;    /* HTT bit */
+        }
+        break;
+    case 2:
+        /* cache info: needed for Pentium Pro compatibility */
+        *eax = 1;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0x2c307d;
+        break;
+    case 4:
+        /* cache info: needed for Core compatibility */
+        if (env->nr_cores > 1) {
+        	*eax = (env->nr_cores - 1) << 26;
+        } else {
+        	*eax = 0;
+        }
+        switch (count) {
+            case 0: /* L1 dcache info */
+                *eax |= 0x0000121;
+                *ebx = 0x1c0003f;
+                *ecx = 0x000003f;
+                *edx = 0x0000001;
+                break;
+            case 1: /* L1 icache info */
+                *eax |= 0x0000122;
+                *ebx = 0x1c0003f;
+                *ecx = 0x000003f;
+                *edx = 0x0000001;
+                break;
+            case 2: /* L2 cache info */
+                *eax |= 0x0000143;
+                if (env->nr_threads > 1) {
+                    *eax |= (env->nr_threads - 1) << 14;
+                }
+                *ebx = 0x3c0003f;
+                *ecx = 0x0000fff;
+                *edx = 0x0000001;
+                break;
+            default: /* end of info */
+                *eax = 0;
+                *ebx = 0;
+                *ecx = 0;
+                *edx = 0;
+                break;
+        }
+        break;
+    case 5:
+        /* mwait info: needed for Core compatibility */
+        *eax = 0; /* Smallest monitor-line size in bytes */
+        *ebx = 0; /* Largest monitor-line size in bytes */
+        *ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
+        *edx = 0;
+        break;
+    case 6:
+        /* Thermal and Power Leaf */
+        *eax = 0;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        break;
+    case 9:
+        /* Direct Cache Access Information Leaf */
+        *eax = 0; /* Bits 0-31 in DCA_CAP MSR */
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        break;
+    case 0xA:
+        /* Architectural Performance Monitoring Leaf */
+        *eax = 0;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        break;
+    case 0x80000000:
+        *eax = env->cpuid_xlevel;
+        *ebx = env->cpuid_vendor1;
+        *edx = env->cpuid_vendor2;
+        *ecx = env->cpuid_vendor3;
+        break;
+    case 0x80000001:
+        *eax = env->cpuid_version;
+        *ebx = 0;
+        *ecx = env->cpuid_ext3_features;
+        *edx = env->cpuid_ext2_features;
+
+        /* The Linux kernel checks for the CMPLegacy bit and
+         * discards multiple thread information if it is set.
+         * So dont set it here for Intel to make Linux guests happy.
+         */
+        if (env->nr_cores * env->nr_threads > 1) {
+            uint32_t tebx, tecx, tedx;
+            get_cpuid_vendor(env, &tebx, &tecx, &tedx);
+            if (tebx != CPUID_VENDOR_INTEL_1 ||
+                tedx != CPUID_VENDOR_INTEL_2 ||
+                tecx != CPUID_VENDOR_INTEL_3) {
+                *ecx |= 1 << 1;    /* CmpLegacy bit */
+            }
+        }
+
+        if (kvm_enabled()) {
+            /* Nested SVM not yet supported in upstream QEMU */
+            *ecx &= ~CPUID_EXT3_SVM;
+        }
+        break;
+    case 0x80000002:
+    case 0x80000003:
+    case 0x80000004:
+        *eax = env->cpuid_model[(index - 0x80000002) * 4 + 0];
+        *ebx = env->cpuid_model[(index - 0x80000002) * 4 + 1];
+        *ecx = env->cpuid_model[(index - 0x80000002) * 4 + 2];
+        *edx = env->cpuid_model[(index - 0x80000002) * 4 + 3];
+        break;
+    case 0x80000005:
+        /* cache info (L1 cache) */
+        *eax = 0x01ff01ff;
+        *ebx = 0x01ff01ff;
+        *ecx = 0x40020140;
+        *edx = 0x40020140;
+        break;
+    case 0x80000006:
+        /* cache info (L2 cache) */
+        *eax = 0;
+        *ebx = 0x42004200;
+        *ecx = 0x02008140;
+        *edx = 0;
+        break;
+    case 0x80000008:
+        /* virtual & phys address size in low 2 bytes. */
+/* XXX: This value must match the one used in the MMU code. */ 
+        if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
+            /* 64 bit processor */
+/* XXX: The physical address space is limited to 42 bits in exec.c. */
+            *eax = 0x00003028;	/* 48 bits virtual, 40 bits physical */
+        } else {
+            if (env->cpuid_features & CPUID_PSE36)
+                *eax = 0x00000024; /* 36 bits physical */
+            else
+                *eax = 0x00000020; /* 32 bits physical */
+        }
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        if (env->nr_cores * env->nr_threads > 1) {
+            *ecx |= (env->nr_cores * env->nr_threads) - 1;
+        }
+        break;
+    case 0x8000000A:
+        *eax = 0x00000001; /* SVM Revision */
+        *ebx = 0x00000010; /* nr of ASIDs */
+        *ecx = 0;
+        *edx = 0; /* optional features */
+        break;
+    default:
+        /* reserved values: zero */
+        *eax = 0;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        break;
+    }
+}
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 70762bb..b120051 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -30,542 +30,6 @@
 
 //#define DEBUG_MMU
 
-/* feature flags taken from "Intel Processor Identification and the CPUID
- * Instruction" and AMD's "CPUID Specification". In cases of disagreement
- * about feature names, the Linux name is used. */
-static const char *feature_name[] = {
-    "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
-    "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
-    "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */, NULL, "ds" /* Intel dts */, "acpi", "mmx",
-    "fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe",
-};
-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, NULL, NULL, NULL, NULL, NULL, "hypervisor",
-};
-static const char *ext2_feature_name[] = {
-    "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
-    "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall", "mtrr", "pge", "mca", "cmov",
-    "pat", "pse36", NULL, NULL /* Linux mp */, "nx" /* Intel xd */, NULL, "mmxext", "mmx",
-    "fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp", NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow",
-};
-static const char *ext3_feature_name[] = {
-    "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
-    "3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL,
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-};
-
-static const char *kvm_feature_name[] = {
-    "kvmclock", "kvm_nopiodelay", "kvm_mmu", NULL, NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-};
-
-static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
-                                    uint32_t *ext_features,
-                                    uint32_t *ext2_features,
-                                    uint32_t *ext3_features,
-                                    uint32_t *kvm_features)
-{
-    int i;
-    int found = 0;
-
-    for ( i = 0 ; i < 32 ; i++ )
-        if (feature_name[i] && !strcmp (flagname, feature_name[i])) {
-            *features |= 1 << i;
-            found = 1;
-        }
-    for ( i = 0 ; i < 32 ; i++ )
-        if (ext_feature_name[i] && !strcmp (flagname, ext_feature_name[i])) {
-            *ext_features |= 1 << i;
-            found = 1;
-        }
-    for ( i = 0 ; i < 32 ; i++ )
-        if (ext2_feature_name[i] && !strcmp (flagname, ext2_feature_name[i])) {
-            *ext2_features |= 1 << i;
-            found = 1;
-        }
-    for ( i = 0 ; i < 32 ; i++ )
-        if (ext3_feature_name[i] && !strcmp (flagname, ext3_feature_name[i])) {
-            *ext3_features |= 1 << i;
-            found = 1;
-        }
-    for ( i = 0 ; i < 32 ; i++ )
-        if (kvm_feature_name[i] && !strcmp (flagname, kvm_feature_name[i])) {
-            *kvm_features |= 1 << i;
-            found = 1;
-        }
-
-    if (!found) {
-        fprintf(stderr, "CPU feature %s not found\n", flagname);
-    }
-}
-
-typedef struct x86_def_t {
-    const char *name;
-    uint32_t level;
-    uint32_t vendor1, vendor2, vendor3;
-    int family;
-    int model;
-    int stepping;
-    uint32_t features, ext_features, ext2_features, ext3_features, kvm_features;
-    uint32_t xlevel;
-    char model_id[48];
-    int vendor_override;
-} x86_def_t;
-
-#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
-#define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
-          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC)
-#define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
-          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)
-static x86_def_t x86_defs[] = {
-#ifdef TARGET_X86_64
-    {
-        .name = "qemu64",
-        .level = 4,
-        .vendor1 = CPUID_VENDOR_AMD_1,
-        .vendor2 = CPUID_VENDOR_AMD_2,
-        .vendor3 = CPUID_VENDOR_AMD_3,
-        .family = 6,
-        .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_POPCNT,
-        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | 
-            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
-        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
-            CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
-        .xlevel = 0x8000000A,
-        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
-    },
-    {
-        .name = "phenom",
-        .level = 5,
-        .vendor1 = CPUID_VENDOR_AMD_1,
-        .vendor2 = CPUID_VENDOR_AMD_2,
-        .vendor3 = CPUID_VENDOR_AMD_3,
-        .family = 16,
-        .model = 2,
-        .stepping = 3,
-        /* Missing: CPUID_VME, CPUID_HT */
-        .features = PPRO_FEATURES | 
-            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
-            CPUID_PSE36,
-        .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) | 
-            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
-            CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
-            CPUID_EXT2_FFXSR,
-        /* Missing: CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
-                    CPUID_EXT3_CR8LEG,
-                    CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
-                    CPUID_EXT3_OSVW, CPUID_EXT3_IBS */
-        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
-            CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
-        .xlevel = 0x8000001A,
-        .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor"
-    },
-    {
-        .name = "core2duo",
-        .level = 10,
-        .family = 6,
-        .model = 15,
-        .stepping = 11,
-	/* The original CPU also implements these features:
-               CPUID_VME, CPUID_DTS, CPUID_ACPI, CPUID_SS, CPUID_HT,
-               CPUID_TM, CPUID_PBE */
-        .features = PPRO_FEATURES |
-            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
-            CPUID_PSE36,
-	/* The original CPU also implements these ext features:
-               CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST,
-               CPUID_EXT_TM2, CPUID_EXT_CX16, CPUID_EXT_XTPR, CPUID_EXT_PDCM */
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3,
-        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
-        .ext3_features = CPUID_EXT3_LAHF_LM,
-        .xlevel = 0x80000008,
-        .model_id = "Intel(R) Core(TM)2 Duo CPU     T7700  @ 2.40GHz",
-    },
-    {
-        .name = "kvm64",
-        .level = 5,
-        .vendor1 = CPUID_VENDOR_INTEL_1,
-        .vendor2 = CPUID_VENDOR_INTEL_2,
-        .vendor3 = CPUID_VENDOR_INTEL_3,
-        .family = 15,
-        .model = 6,
-        .stepping = 1,
-        /* Missing: CPUID_VME, CPUID_HT */
-        .features = PPRO_FEATURES |
-            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
-            CPUID_PSE36,
-        /* 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) |
-            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,
-                    CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
-                    CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */
-        .ext3_features = 0,
-        .xlevel = 0x80000008,
-        .model_id = "Common KVM processor"
-    },
-#endif
-    {
-        .name = "qemu32",
-        .level = 4,
-        .family = 6,
-        .model = 3,
-        .stepping = 3,
-        .features = PPRO_FEATURES,
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
-        .xlevel = 0,
-        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
-    },
-    {
-        .name = "coreduo",
-        .level = 10,
-        .family = 6,
-        .model = 14,
-        .stepping = 8,
-        /* The original CPU also implements these features:
-               CPUID_DTS, CPUID_ACPI, CPUID_SS, CPUID_HT,
-               CPUID_TM, CPUID_PBE */
-        .features = PPRO_FEATURES | CPUID_VME |
-            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA,
-        /* The original CPU also implements these ext features:
-               CPUID_EXT_VMX, CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_XTPR,
-               CPUID_EXT_PDCM */
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR,
-        .ext2_features = CPUID_EXT2_NX,
-        .xlevel = 0x80000008,
-        .model_id = "Genuine Intel(R) CPU           T2600  @ 2.16GHz",
-    },
-    {
-        .name = "486",
-        .level = 0,
-        .family = 4,
-        .model = 0,
-        .stepping = 0,
-        .features = I486_FEATURES,
-        .xlevel = 0,
-    },
-    {
-        .name = "pentium",
-        .level = 1,
-        .family = 5,
-        .model = 4,
-        .stepping = 3,
-        .features = PENTIUM_FEATURES,
-        .xlevel = 0,
-    },
-    {
-        .name = "pentium2",
-        .level = 2,
-        .family = 6,
-        .model = 5,
-        .stepping = 2,
-        .features = PENTIUM2_FEATURES,
-        .xlevel = 0,
-    },
-    {
-        .name = "pentium3",
-        .level = 2,
-        .family = 6,
-        .model = 7,
-        .stepping = 3,
-        .features = PENTIUM3_FEATURES,
-        .xlevel = 0,
-    },
-    {
-        .name = "athlon",
-        .level = 2,
-        .vendor1 = CPUID_VENDOR_AMD_1,
-        .vendor2 = CPUID_VENDOR_AMD_2,
-        .vendor3 = CPUID_VENDOR_AMD_3,
-        .family = 6,
-        .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,
-        .xlevel = 0x80000008,
-        /* XXX: put another string ? */
-        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
-    },
-    {
-        .name = "n270",
-        /* original is on level 10 */
-        .level = 5,
-        .family = 6,
-        .model = 28,
-        .stepping = 2,
-        .features = PPRO_FEATURES |
-            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME,
-            /* Missing: CPUID_DTS | CPUID_ACPI | CPUID_SS |
-             * CPUID_HT | CPUID_TM | CPUID_PBE */
-            /* Some CPUs got no CPUID_SEP */
-        .ext_features = CPUID_EXT_MONITOR |
-            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,
-        /* 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,
-                               uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
-
-static int cpu_x86_fill_model_id(char *str)
-{
-    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
-    int i;
-
-    for (i = 0; i < 3; i++) {
-        host_cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx);
-        memcpy(str + i * 16 +  0, &eax, 4);
-        memcpy(str + i * 16 +  4, &ebx, 4);
-        memcpy(str + i * 16 +  8, &ecx, 4);
-        memcpy(str + i * 16 + 12, &edx, 4);
-    }
-    return 0;
-}
-
-static int cpu_x86_fill_host(x86_def_t *x86_cpu_def)
-{
-    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
-
-    x86_cpu_def->name = "host";
-    host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
-    x86_cpu_def->level = eax;
-    x86_cpu_def->vendor1 = ebx;
-    x86_cpu_def->vendor2 = edx;
-    x86_cpu_def->vendor3 = ecx;
-
-    host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
-    x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
-    x86_cpu_def->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
-    x86_cpu_def->stepping = eax & 0x0F;
-    x86_cpu_def->ext_features = ecx;
-    x86_cpu_def->features = edx;
-
-    host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx);
-    x86_cpu_def->xlevel = eax;
-
-    host_cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx);
-    x86_cpu_def->ext2_features = edx;
-    x86_cpu_def->ext3_features = ecx;
-    cpu_x86_fill_model_id(x86_cpu_def->model_id);
-    x86_cpu_def->vendor_override = 0;
-
-    return 0;
-}
-
-static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
-{
-    unsigned int i;
-    x86_def_t *def;
-
-    char *s = strdup(cpu_model);
-    char *featurestr, *name = strtok(s, ",");
-    uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0, plus_kvm_features = 0;
-    uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0, minus_kvm_features = 0;
-    uint32_t numvalue;
-
-    def = NULL;
-    for (i = 0; i < ARRAY_SIZE(x86_defs); i++) {
-        if (strcmp(name, x86_defs[i].name) == 0) {
-            def = &x86_defs[i];
-            break;
-        }
-    }
-    if (kvm_enabled() && strcmp(name, "host") == 0) {
-        cpu_x86_fill_host(x86_cpu_def);
-    } else if (!def) {
-        goto error;
-    } else {
-        memcpy(x86_cpu_def, def, sizeof(*def));
-    }
-
-    plus_kvm_features = ~0; /* not supported bits will be filtered out later */
-
-    add_flagname_to_bitmaps("hypervisor", &plus_features,
-        &plus_ext_features, &plus_ext2_features, &plus_ext3_features,
-        &plus_kvm_features);
-
-    featurestr = strtok(NULL, ",");
-
-    while (featurestr) {
-        char *val;
-        if (featurestr[0] == '+') {
-            add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features, &plus_kvm_features);
-        } else if (featurestr[0] == '-') {
-            add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features, &minus_kvm_features);
-        } else if ((val = strchr(featurestr, '='))) {
-            *val = 0; val++;
-            if (!strcmp(featurestr, "family")) {
-                char *err;
-                numvalue = strtoul(val, &err, 0);
-                if (!*val || *err) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                x86_cpu_def->family = numvalue;
-            } else if (!strcmp(featurestr, "model")) {
-                char *err;
-                numvalue = strtoul(val, &err, 0);
-                if (!*val || *err || numvalue > 0xff) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                x86_cpu_def->model = numvalue;
-            } else if (!strcmp(featurestr, "stepping")) {
-                char *err;
-                numvalue = strtoul(val, &err, 0);
-                if (!*val || *err || numvalue > 0xf) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                x86_cpu_def->stepping = numvalue ;
-            } else if (!strcmp(featurestr, "level")) {
-                char *err;
-                numvalue = strtoul(val, &err, 0);
-                if (!*val || *err) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                x86_cpu_def->level = numvalue;
-            } else if (!strcmp(featurestr, "xlevel")) {
-                char *err;
-                numvalue = strtoul(val, &err, 0);
-                if (!*val || *err) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                if (numvalue < 0x80000000) {
-                	numvalue += 0x80000000;
-                }
-                x86_cpu_def->xlevel = numvalue;
-            } else if (!strcmp(featurestr, "vendor")) {
-                if (strlen(val) != 12) {
-                    fprintf(stderr, "vendor string must be 12 chars long\n");
-                    goto error;
-                }
-                x86_cpu_def->vendor1 = 0;
-                x86_cpu_def->vendor2 = 0;
-                x86_cpu_def->vendor3 = 0;
-                for(i = 0; i < 4; i++) {
-                    x86_cpu_def->vendor1 |= ((uint8_t)val[i    ]) << (8 * i);
-                    x86_cpu_def->vendor2 |= ((uint8_t)val[i + 4]) << (8 * i);
-                    x86_cpu_def->vendor3 |= ((uint8_t)val[i + 8]) << (8 * i);
-                }
-                x86_cpu_def->vendor_override = 1;
-            } else if (!strcmp(featurestr, "model_id")) {
-                pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id),
-                        val);
-            } else {
-                fprintf(stderr, "unrecognized feature %s\n", featurestr);
-                goto error;
-            }
-        } else {
-            fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
-            goto error;
-        }
-        featurestr = strtok(NULL, ",");
-    }
-    x86_cpu_def->features |= plus_features;
-    x86_cpu_def->ext_features |= plus_ext_features;
-    x86_cpu_def->ext2_features |= plus_ext2_features;
-    x86_cpu_def->ext3_features |= plus_ext3_features;
-    x86_cpu_def->kvm_features |= plus_kvm_features;
-    x86_cpu_def->features &= ~minus_features;
-    x86_cpu_def->ext_features &= ~minus_ext_features;
-    x86_cpu_def->ext2_features &= ~minus_ext2_features;
-    x86_cpu_def->ext3_features &= ~minus_ext3_features;
-    x86_cpu_def->kvm_features &= ~minus_kvm_features;
-    free(s);
-    return 0;
-
-error:
-    free(s);
-    return -1;
-}
-
-void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
-{
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_SIZE(x86_defs); i++)
-        (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name);
-}
-
-static int cpu_x86_register (CPUX86State *env, const char *cpu_model)
-{
-    x86_def_t def1, *def = &def1;
-
-    if (cpu_x86_find_by_name(def, cpu_model) < 0)
-        return -1;
-    if (def->vendor1) {
-        env->cpuid_vendor1 = def->vendor1;
-        env->cpuid_vendor2 = def->vendor2;
-        env->cpuid_vendor3 = def->vendor3;
-    } else {
-        env->cpuid_vendor1 = CPUID_VENDOR_INTEL_1;
-        env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2;
-        env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3;
-    }
-    env->cpuid_vendor_override = def->vendor_override;
-    env->cpuid_level = def->level;
-    if (def->family > 0x0f)
-        env->cpuid_version = 0xf00 | ((def->family - 0x0f) << 20);
-    else
-        env->cpuid_version = def->family << 8;
-    env->cpuid_version |= ((def->model & 0xf) << 4) | ((def->model >> 4) << 16);
-    env->cpuid_version |= def->stepping;
-    env->cpuid_features = def->features;
-    env->pat = 0x0007040600070406ULL;
-    env->cpuid_ext_features = def->ext_features;
-    env->cpuid_ext2_features = def->ext2_features;
-    env->cpuid_xlevel = def->xlevel;
-    env->cpuid_kvm_features = def->kvm_features;
-    {
-        const char *model_id = def->model_id;
-        int c, len, i;
-        if (!model_id)
-            model_id = "";
-        len = strlen(model_id);
-        for(i = 0; i < 48; i++) {
-            if (i >= len)
-                c = '\0';
-            else
-                c = (uint8_t)model_id[i];
-            env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
-        }
-    }
-    return 0;
-}
-
 /* NOTE: must be called outside the CPU execute loop */
 void cpu_reset(CPUX86State *env)
 {
@@ -1626,249 +1090,6 @@ static void mce_init(CPUX86State *cenv)
     }
 }
 
-static void host_cpuid(uint32_t function, uint32_t count,
-                       uint32_t *eax, uint32_t *ebx,
-                       uint32_t *ecx, uint32_t *edx)
-{
-#if defined(CONFIG_KVM)
-    uint32_t vec[4];
-
-#ifdef __x86_64__
-    asm volatile("cpuid"
-                 : "=a"(vec[0]), "=b"(vec[1]),
-                   "=c"(vec[2]), "=d"(vec[3])
-                 : "0"(function), "c"(count) : "cc");
-#else
-    asm volatile("pusha \n\t"
-                 "cpuid \n\t"
-                 "mov %%eax, 0(%2) \n\t"
-                 "mov %%ebx, 4(%2) \n\t"
-                 "mov %%ecx, 8(%2) \n\t"
-                 "mov %%edx, 12(%2) \n\t"
-                 "popa"
-                 : : "a"(function), "c"(count), "S"(vec)
-                 : "memory", "cc");
-#endif
-
-    if (eax)
-	*eax = vec[0];
-    if (ebx)
-	*ebx = vec[1];
-    if (ecx)
-	*ecx = vec[2];
-    if (edx)
-	*edx = vec[3];
-#endif
-}
-
-static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx,
-                             uint32_t *ecx, uint32_t *edx)
-{
-    *ebx = env->cpuid_vendor1;
-    *edx = env->cpuid_vendor2;
-    *ecx = env->cpuid_vendor3;
-
-    /* sysenter isn't supported on compatibility mode on AMD, syscall
-     * isn't supported in compatibility mode on Intel.
-     * Normally we advertise the actual cpu vendor, but you can override
-     * this if you want to use KVM's sysenter/syscall emulation
-     * in compatibility mode and when doing cross vendor migration
-     */
-    if (kvm_enabled() && env->cpuid_vendor_override) {
-        host_cpuid(0, 0, NULL, ebx, ecx, edx);
-    }
-}
-
-void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
-                   uint32_t *eax, uint32_t *ebx,
-                   uint32_t *ecx, uint32_t *edx)
-{
-    /* test if maximum index reached */
-    if (index & 0x80000000) {
-        if (index > env->cpuid_xlevel)
-            index = env->cpuid_level;
-    } else {
-        if (index > env->cpuid_level)
-            index = env->cpuid_level;
-    }
-
-    switch(index) {
-    case 0:
-        *eax = env->cpuid_level;
-        get_cpuid_vendor(env, ebx, ecx, edx);
-        break;
-    case 1:
-        *eax = env->cpuid_version;
-        *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
-        *ecx = env->cpuid_ext_features;
-        *edx = env->cpuid_features;
-        if (env->nr_cores * env->nr_threads > 1) {
-            *ebx |= (env->nr_cores * env->nr_threads) << 16;
-            *edx |= 1 << 28;    /* HTT bit */
-        }
-        break;
-    case 2:
-        /* cache info: needed for Pentium Pro compatibility */
-        *eax = 1;
-        *ebx = 0;
-        *ecx = 0;
-        *edx = 0x2c307d;
-        break;
-    case 4:
-        /* cache info: needed for Core compatibility */
-        if (env->nr_cores > 1) {
-        	*eax = (env->nr_cores - 1) << 26;
-        } else {
-        	*eax = 0;
-        }
-        switch (count) {
-            case 0: /* L1 dcache info */
-                *eax |= 0x0000121;
-                *ebx = 0x1c0003f;
-                *ecx = 0x000003f;
-                *edx = 0x0000001;
-                break;
-            case 1: /* L1 icache info */
-                *eax |= 0x0000122;
-                *ebx = 0x1c0003f;
-                *ecx = 0x000003f;
-                *edx = 0x0000001;
-                break;
-            case 2: /* L2 cache info */
-                *eax |= 0x0000143;
-                if (env->nr_threads > 1) {
-                    *eax |= (env->nr_threads - 1) << 14;
-                }
-                *ebx = 0x3c0003f;
-                *ecx = 0x0000fff;
-                *edx = 0x0000001;
-                break;
-            default: /* end of info */
-                *eax = 0;
-                *ebx = 0;
-                *ecx = 0;
-                *edx = 0;
-                break;
-        }
-        break;
-    case 5:
-        /* mwait info: needed for Core compatibility */
-        *eax = 0; /* Smallest monitor-line size in bytes */
-        *ebx = 0; /* Largest monitor-line size in bytes */
-        *ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
-        *edx = 0;
-        break;
-    case 6:
-        /* Thermal and Power Leaf */
-        *eax = 0;
-        *ebx = 0;
-        *ecx = 0;
-        *edx = 0;
-        break;
-    case 9:
-        /* Direct Cache Access Information Leaf */
-        *eax = 0; /* Bits 0-31 in DCA_CAP MSR */
-        *ebx = 0;
-        *ecx = 0;
-        *edx = 0;
-        break;
-    case 0xA:
-        /* Architectural Performance Monitoring Leaf */
-        *eax = 0;
-        *ebx = 0;
-        *ecx = 0;
-        *edx = 0;
-        break;
-    case 0x80000000:
-        *eax = env->cpuid_xlevel;
-        *ebx = env->cpuid_vendor1;
-        *edx = env->cpuid_vendor2;
-        *ecx = env->cpuid_vendor3;
-        break;
-    case 0x80000001:
-        *eax = env->cpuid_version;
-        *ebx = 0;
-        *ecx = env->cpuid_ext3_features;
-        *edx = env->cpuid_ext2_features;
-
-        /* The Linux kernel checks for the CMPLegacy bit and
-         * discards multiple thread information if it is set.
-         * So dont set it here for Intel to make Linux guests happy.
-         */
-        if (env->nr_cores * env->nr_threads > 1) {
-            uint32_t tebx, tecx, tedx;
-            get_cpuid_vendor(env, &tebx, &tecx, &tedx);
-            if (tebx != CPUID_VENDOR_INTEL_1 ||
-                tedx != CPUID_VENDOR_INTEL_2 ||
-                tecx != CPUID_VENDOR_INTEL_3) {
-                *ecx |= 1 << 1;    /* CmpLegacy bit */
-            }
-        }
-
-        if (kvm_enabled()) {
-            /* Nested SVM not yet supported in upstream QEMU */
-            *ecx &= ~CPUID_EXT3_SVM;
-        }
-        break;
-    case 0x80000002:
-    case 0x80000003:
-    case 0x80000004:
-        *eax = env->cpuid_model[(index - 0x80000002) * 4 + 0];
-        *ebx = env->cpuid_model[(index - 0x80000002) * 4 + 1];
-        *ecx = env->cpuid_model[(index - 0x80000002) * 4 + 2];
-        *edx = env->cpuid_model[(index - 0x80000002) * 4 + 3];
-        break;
-    case 0x80000005:
-        /* cache info (L1 cache) */
-        *eax = 0x01ff01ff;
-        *ebx = 0x01ff01ff;
-        *ecx = 0x40020140;
-        *edx = 0x40020140;
-        break;
-    case 0x80000006:
-        /* cache info (L2 cache) */
-        *eax = 0;
-        *ebx = 0x42004200;
-        *ecx = 0x02008140;
-        *edx = 0;
-        break;
-    case 0x80000008:
-        /* virtual & phys address size in low 2 bytes. */
-/* XXX: This value must match the one used in the MMU code. */ 
-        if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
-            /* 64 bit processor */
-/* XXX: The physical address space is limited to 42 bits in exec.c. */
-            *eax = 0x00003028;	/* 48 bits virtual, 40 bits physical */
-        } else {
-            if (env->cpuid_features & CPUID_PSE36)
-                *eax = 0x00000024; /* 36 bits physical */
-            else
-                *eax = 0x00000020; /* 32 bits physical */
-        }
-        *ebx = 0;
-        *ecx = 0;
-        *edx = 0;
-        if (env->nr_cores * env->nr_threads > 1) {
-            *ecx |= (env->nr_cores * env->nr_threads) - 1;
-        }
-        break;
-    case 0x8000000A:
-        *eax = 0x00000001; /* SVM Revision */
-        *ebx = 0x00000010; /* nr of ASIDs */
-        *ecx = 0;
-        *edx = 0; /* optional features */
-        break;
-    default:
-        /* reserved values: zero */
-        *eax = 0;
-        *ebx = 0;
-        *ecx = 0;
-        *edx = 0;
-        break;
-    }
-}
-
-
 int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
                             target_ulong *base, unsigned int *limit,
                             unsigned int *flags)
-- 
1.6.4

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

* [Qemu-devel] [PATCH 02/13] cpuid: replace magic number with named constant
  2010-02-02 10:08 [Qemu-devel] [PATCH 00/13] i386 cpuid: cleanup and fixes Andre Przywara
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 01/13] cpuid: move CPUID functions into separate file Andre Przywara
@ 2010-02-02 10:08 ` Andre Przywara
  2010-03-06 18:25   ` Aurelien Jarno
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 03/13] cpuid: moved host_cpuid function and remove prototype Andre Przywara
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 18+ messages in thread
From: Andre Przywara @ 2010-02-02 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: john.cooper, Andre Przywara

CPUID leaf Fn8000_0001.EDX contains a copy of many Fn0000_0001.EDX bits.
Define a name for the mask to improve readability and avoid typos.

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
---
 target-i386/cpuid.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index aaa14ba..0a17020 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -130,6 +130,7 @@ typedef struct x86_def_t {
           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 EXT2_FEATURE_MASK 0x0183F3FF
 static x86_def_t x86_defs[] = {
 #ifdef TARGET_X86_64
     {
@@ -147,7 +148,7 @@ static x86_def_t x86_defs[] = {
         /* this feature is needed for Solaris and isn't fully implemented */
             CPUID_PSE36,
         .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT,
-        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | 
+        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_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,
@@ -170,7 +171,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 & EXT2_FEATURE_MASK) | 
             CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
             CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
             CPUID_EXT2_FFXSR,
@@ -220,7 +221,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 & EXT2_FEATURE_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,
@@ -308,7 +309,7 @@ static x86_def_t x86_defs[] = {
         .stepping = 3,
         .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME |
                     CPUID_MTRR | CPUID_MCA,
-        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | CPUID_EXT2_MMXEXT |
+        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | CPUID_EXT2_MMXEXT |
                           CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
         .xlevel = 0x80000008,
         /* XXX: put another string ? */
@@ -330,7 +331,7 @@ 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 & EXT2_FEATURE_MASK) | CPUID_EXT2_NX,
         /* Missing: .ext3_features = CPUID_EXT3_LAHF_LM */
         .xlevel = 0x8000000A,
         .model_id = "Intel(R) Atom(TM) CPU N270   @ 1.60GHz",
-- 
1.6.4

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

* [Qemu-devel] [PATCH 03/13] cpuid: moved host_cpuid function and remove prototype
  2010-02-02 10:08 [Qemu-devel] [PATCH 00/13] i386 cpuid: cleanup and fixes Andre Przywara
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 01/13] cpuid: move CPUID functions into separate file Andre Przywara
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 02/13] cpuid: replace magic number with named constant Andre Przywara
@ 2010-02-02 10:08 ` Andre Przywara
  2010-03-06 18:26   ` Aurelien Jarno
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 04/13] cpuid: Replace strtok with get_opt_name Andre Przywara
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 18+ messages in thread
From: Andre Przywara @ 2010-02-02 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: john.cooper, Andre Przywara

the host_cpuid function was located at the end of the file and had
a prototype before it's first use. Move it up and remove the
prototype.

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
---
 target-i386/cpuid.c |   70 ++++++++++++++++++++++++--------------------------
 1 files changed, 34 insertions(+), 36 deletions(-)

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 0a17020..cc080f4 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -338,8 +338,40 @@ static x86_def_t x86_defs[] = {
     },
 };
 
-static void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax,
-                               uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
+static void host_cpuid(uint32_t function, uint32_t count,
+                       uint32_t *eax, uint32_t *ebx,
+                       uint32_t *ecx, uint32_t *edx)
+{
+#if defined(CONFIG_KVM)
+    uint32_t vec[4];
+
+#ifdef __x86_64__
+    asm volatile("cpuid"
+                 : "=a"(vec[0]), "=b"(vec[1]),
+                   "=c"(vec[2]), "=d"(vec[3])
+                 : "0"(function), "c"(count) : "cc");
+#else
+    asm volatile("pusha \n\t"
+                 "cpuid \n\t"
+                 "mov %%eax, 0(%2) \n\t"
+                 "mov %%ebx, 4(%2) \n\t"
+                 "mov %%ecx, 8(%2) \n\t"
+                 "mov %%edx, 12(%2) \n\t"
+                 "popa"
+                 : : "a"(function), "c"(count), "S"(vec)
+                 : "memory", "cc");
+#endif
+
+    if (eax)
+	*eax = vec[0];
+    if (ebx)
+	*ebx = vec[1];
+    if (ecx)
+	*ecx = vec[2];
+    if (edx)
+	*edx = vec[3];
+#endif
+}
 
 static int cpu_x86_fill_model_id(char *str)
 {
@@ -578,40 +610,6 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
     return 0;
 }
 
-static void host_cpuid(uint32_t function, uint32_t count,
-                       uint32_t *eax, uint32_t *ebx,
-                       uint32_t *ecx, uint32_t *edx)
-{
-#if defined(CONFIG_KVM)
-    uint32_t vec[4];
-
-#ifdef __x86_64__
-    asm volatile("cpuid"
-                 : "=a"(vec[0]), "=b"(vec[1]),
-                   "=c"(vec[2]), "=d"(vec[3])
-                 : "0"(function), "c"(count) : "cc");
-#else
-    asm volatile("pusha \n\t"
-                 "cpuid \n\t"
-                 "mov %%eax, 0(%2) \n\t"
-                 "mov %%ebx, 4(%2) \n\t"
-                 "mov %%ecx, 8(%2) \n\t"
-                 "mov %%edx, 12(%2) \n\t"
-                 "popa"
-                 : : "a"(function), "c"(count), "S"(vec)
-                 : "memory", "cc");
-#endif
-
-    if (eax)
-	*eax = vec[0];
-    if (ebx)
-	*ebx = vec[1];
-    if (ecx)
-	*ecx = vec[2];
-    if (edx)
-	*edx = vec[3];
-#endif
-}
 
 static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx,
                              uint32_t *ecx, uint32_t *edx)
-- 
1.6.4

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

* [Qemu-devel] [PATCH 04/13] cpuid: Replace strtok with get_opt_name
  2010-02-02 10:08 [Qemu-devel] [PATCH 00/13] i386 cpuid: cleanup and fixes Andre Przywara
                   ` (2 preceding siblings ...)
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 03/13] cpuid: moved host_cpuid function and remove prototype Andre Przywara
@ 2010-02-02 10:08 ` Andre Przywara
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 05/13] cpuid: add missing CPUID feature flag names Andre Przywara
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 18+ messages in thread
From: Andre Przywara @ 2010-02-02 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: john.cooper, Andre Przywara

To avoid the non-reentrant capable strtok() use the QEMU defined
get_opt_name() to parse the -cpu parameter list. Since there is a
name clash between linux-user/mmap.c:qemu_malloc() and
qemu-malloc.c:qemu_malloc() I copied the small function from
qemu-option.c into cpuid.c. Not the best solution, bit IMO the
least intrusive and smallest one.

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
---
 target-i386/cpuid.c |   34 ++++++++++++++++++++++++----------
 1 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index cc080f4..0238718 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -24,6 +24,23 @@
 #include "cpu.h"
 #include "kvm.h"
 
+static const char *get_opt_name(char *buf, int buf_size,
+                                const char *p, char delim)
+{
+    char *q;
+
+    q = buf;
+    while (*p != '\0' && *p != delim) {
+        if (q && (q - buf) < buf_size - 1)
+            *q++ = *p;
+        p++;
+    }
+    if (q)
+        *q = '\0';
+
+    return p;
+}
+
 /* feature flags taken from "Intel Processor Identification and the CPUID
  * Instruction" and AMD's "CPUID Specification". In cases of disagreement
  * about feature names, the Linux name is used. */
@@ -423,8 +440,8 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
     unsigned int i;
     x86_def_t *def;
 
-    char *s = strdup(cpu_model);
-    char *featurestr, *name = strtok(s, ",");
+    const char* s;
+    char featurestr[64];
     uint32_t plus_features = 0, plus_ext_features = 0,
         plus_ext2_features = 0, plus_ext3_features = 0, plus_kvm_features = 0;
     uint32_t minus_features = 0, minus_ext_features = 0,
@@ -432,14 +449,15 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
         minus_kvm_features = 0;
     uint32_t numvalue;
 
+    s = get_opt_name(featurestr, 64, cpu_model, ',');
     def = NULL;
     for (i = 0; i < ARRAY_SIZE(x86_defs); i++) {
-        if (strcmp(name, x86_defs[i].name) == 0) {
+        if (strcmp(featurestr, x86_defs[i].name) == 0) {
             def = &x86_defs[i];
             break;
         }
     }
-    if (kvm_enabled() && strcmp(name, "host") == 0) {
+    if (kvm_enabled() && strcmp(featurestr, "host") == 0) {
         cpu_x86_fill_host(x86_cpu_def);
     } else if (!def) {
         goto error;
@@ -453,10 +471,9 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
         &plus_ext_features, &plus_ext2_features, &plus_ext3_features,
         &plus_kvm_features);
 
-    featurestr = strtok(NULL, ",");
-
-    while (featurestr) {
+    while (*s != 0) {
         char *val;
+        s = get_opt_name(featurestr, 64, s + 1, ',');
         if (featurestr[0] == '+') {
             add_flagname_to_bitmaps(featurestr + 1, &plus_features,
                                     &plus_ext_features, &plus_ext2_features,
@@ -536,7 +553,6 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
                             "(+feature|-feature|feature=xyz)\n", featurestr);
             goto error;
         }
-        featurestr = strtok(NULL, ",");
     }
     x86_cpu_def->features |= plus_features;
     x86_cpu_def->ext_features |= plus_ext_features;
@@ -548,11 +564,9 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
     x86_cpu_def->ext2_features &= ~minus_ext2_features;
     x86_cpu_def->ext3_features &= ~minus_ext3_features;
     x86_cpu_def->kvm_features &= ~minus_kvm_features;
-    free(s);
     return 0;
 
 error:
-    free(s);
     return -1;
 }
 
-- 
1.6.4

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

* [Qemu-devel] [PATCH 05/13] cpuid: add missing CPUID feature flag names
  2010-02-02 10:08 [Qemu-devel] [PATCH 00/13] i386 cpuid: cleanup and fixes Andre Przywara
                   ` (3 preceding siblings ...)
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 04/13] cpuid: Replace strtok with get_opt_name Andre Przywara
@ 2010-02-02 10:08 ` Andre Przywara
  2010-03-06 18:26   ` Aurelien Jarno
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 06/13] cpuid: list all known x86 CPUID feature flags Andre Przywara
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 18+ messages in thread
From: Andre Przywara @ 2010-02-02 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: john.cooper, Andre Przywara

Some CPUID feature flags had no string value, so they could not be
switched on or off from the command line.
Add names for the missing ones mentioned in the current public CPUID
specification from both Intel and AMD. Those only mentioned in the
Linux kernel source I put as comments.

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
---
 target-i386/cpuid.c |   15 ++++++++-------
 1 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 0238718..19d58e1 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -52,11 +52,11 @@ static const char *feature_name[] = {
     "fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe",
 };
 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, NULL, NULL, NULL, NULL, NULL, "hypervisor",
+    "pni" /* Intel,AMD sse3 */, "pclmuldq", "dtes64", "monitor",
+        "ds_cpl", "vmx", "smx", "est",
+    "tm2", "ssse3", "cid", NULL, NULL /* FMA */, "cx16", "xtpr", "pdcm",
+    NULL, NULL, "dca", "sse4_1", "sse4_2", "x2apic", "movbe", "popcnt",
+    NULL, "aes", "xsave", "osxsave", NULL /* AVX */, NULL, NULL, "hypervisor",
 };
 static const char *ext2_feature_name[] = {
     "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
@@ -71,8 +71,9 @@ static const char *ext3_feature_name[] = {
     "lahf_lm" /* AMD LahfSahf */, "cmp_legacy",
         "svm", "extapic" /* AMD ExtApicSpace */,
         "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
-    "3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL,
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    "3dnowprefetch", "osvw", "ibs", NULL /* SSE-5 */,
+        "skinit", "wdt", NULL, NULL,
+    NULL, NULL, NULL, "nodeid_msr", NULL, NULL, NULL, NULL,
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 };
 
-- 
1.6.4

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

* [Qemu-devel] [PATCH 06/13] cpuid: list all known x86 CPUID feature flags
  2010-02-02 10:08 [Qemu-devel] [PATCH 00/13] i386 cpuid: cleanup and fixes Andre Przywara
                   ` (4 preceding siblings ...)
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 05/13] cpuid: add missing CPUID feature flag names Andre Przywara
@ 2010-02-02 10:08 ` Andre Przywara
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 07/13] cpuid: remove unnecessary kvm_trim function Andre Przywara
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 18+ messages in thread
From: Andre Przywara @ 2010-02-02 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: john.cooper, Andre Przywara

-cpu ? currently gives us a list of known CPU models. Add "host" if
using KVM and a list of known CPUID feature flags to the output.

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
---
 target-i386/cpuid.c |   22 +++++++++++++++++++++-
 1 files changed, 21 insertions(+), 1 deletions(-)

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 19d58e1..3f56c50 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -573,10 +573,30 @@ error:
 
 void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
 {
-    unsigned int i;
+    unsigned int i, j;
+    const char **stringlist[] = {feature_name, ext_feature_name,
+                                 ext2_feature_name, ext3_feature_name};
 
     for (i = 0; i < ARRAY_SIZE(x86_defs); i++)
         (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name);
+    if (kvm_enabled()) {
+        (*cpu_fprintf)(f, "x86 %16s\n", "host");
+    }
+
+    (*cpu_fprintf)(f, "x86 recognized feature flags:\n    ");
+    for (j = 0; j < 4; j++) {
+        for (i = 0; i < 32; i++) {
+            if (j == 2 && ((1 << i) & EXT2_FEATURE_MASK))
+                continue;
+            if (stringlist[j][i] == NULL)
+                continue;
+            (*cpu_fprintf)(f, "%s ", stringlist[j][i]);
+            if (i == 15)
+                (*cpu_fprintf)(f, "\n    ");
+        }
+        (*cpu_fprintf)(f, "\n    ");
+    }
+    return;
 }
 
 int cpu_x86_register (CPUX86State *env, const char *cpu_model)
-- 
1.6.4

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

* [Qemu-devel] [PATCH 07/13] cpuid: remove unnecessary kvm_trim function
  2010-02-02 10:08 [Qemu-devel] [PATCH 00/13] i386 cpuid: cleanup and fixes Andre Przywara
                   ` (5 preceding siblings ...)
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 06/13] cpuid: list all known x86 CPUID feature flags Andre Przywara
@ 2010-02-02 10:08 ` Andre Przywara
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 08/13] cpuid: simplify CPUID flag search function Andre Przywara
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 18+ messages in thread
From: Andre Przywara @ 2010-02-02 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: john.cooper, Andre Przywara

Correct me if I am wrong, but kvm_trim looks like a really bloated
implementation of a bitwise AND. So remove this function and replace
it with the real stuff(TM).

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
---
 target-i386/kvm.c |   27 ++++++---------------------
 1 files changed, 6 insertions(+), 21 deletions(-)

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 5b093ce..daa65c1 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -125,19 +125,6 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, int reg)
 
 #endif
 
-static void kvm_trim_features(uint32_t *features, uint32_t supported)
-{
-    int i;
-    uint32_t mask;
-
-    for (i = 0; i < 32; ++i) {
-        mask = 1U << i;
-        if ((*features & mask) && !(supported & mask)) {
-            *features &= ~mask;
-        }
-    }
-}
-
 #ifdef CONFIG_KVM_PARA
 struct kvm_para_features {
         int cap;
@@ -186,18 +173,16 @@ int kvm_arch_init_vcpu(CPUState *env)
 
     env->mp_state = KVM_MP_STATE_RUNNABLE;
 
-    kvm_trim_features(&env->cpuid_features,
-        kvm_arch_get_supported_cpuid(env, 1, R_EDX));
+    env->cpuid_features &= kvm_arch_get_supported_cpuid(env, 1, R_EDX);
 
     i = env->cpuid_ext_features & CPUID_EXT_HYPERVISOR;
-    kvm_trim_features(&env->cpuid_ext_features,
-        kvm_arch_get_supported_cpuid(env, 1, R_ECX));
+    env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(env, 1, R_ECX);
     env->cpuid_ext_features |= i;
 
-    kvm_trim_features(&env->cpuid_ext2_features,
-        kvm_arch_get_supported_cpuid(env, 0x80000001, R_EDX));
-    kvm_trim_features(&env->cpuid_ext3_features,
-        kvm_arch_get_supported_cpuid(env, 0x80000001, R_ECX));
+    env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(env, 0x80000001,
+                                                             R_EDX);
+    env->cpuid_ext3_features &= kvm_arch_get_supported_cpuid(env, 0x80000001,
+                                                             R_ECX);
 
     cpuid_i = 0;
 
-- 
1.6.4

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

* [Qemu-devel] [PATCH 08/13] cpuid: simplify CPUID flag search function
  2010-02-02 10:08 [Qemu-devel] [PATCH 00/13] i386 cpuid: cleanup and fixes Andre Przywara
                   ` (6 preceding siblings ...)
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 07/13] cpuid: remove unnecessary kvm_trim function Andre Przywara
@ 2010-02-02 10:08 ` Andre Przywara
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 09/13] cpuid: propagate further CPUID leafs when -cpu host Andre Przywara
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 18+ messages in thread
From: Andre Przywara @ 2010-02-02 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: john.cooper, Andre Przywara

avoid code duplication and handle the CPUID flag name search in a
loop.

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
---
 target-i386/cpuid.c |   38 +++++++++++++-------------------------
 1 files changed, 13 insertions(+), 25 deletions(-)

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 3f56c50..635c2f4 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -90,34 +90,22 @@ static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
                                     uint32_t *ext3_features,
                                     uint32_t *kvm_features)
 {
-    int i;
+    int i, j;
     int found = 0;
-
-    for ( i = 0 ; i < 32 ; i++ )
-        if (feature_name[i] && !strcmp (flagname, feature_name[i])) {
-            *features |= 1 << i;
-            found = 1;
-        }
-    for ( i = 0 ; i < 32 ; i++ )
-        if (ext_feature_name[i] && !strcmp (flagname, ext_feature_name[i])) {
-            *ext_features |= 1 << i;
-            found = 1;
-        }
-    for ( i = 0 ; i < 32 ; i++ )
-        if (ext2_feature_name[i] && !strcmp (flagname, ext2_feature_name[i])) {
-            *ext2_features |= 1 << i;
-            found = 1;
-        }
-    for ( i = 0 ; i < 32 ; i++ )
-        if (ext3_feature_name[i] && !strcmp (flagname, ext3_feature_name[i])) {
-            *ext3_features |= 1 << i;
-            found = 1;
-        }
-    for ( i = 0 ; i < 32 ; i++ )
-        if (kvm_feature_name[i] && !strcmp (flagname, kvm_feature_name[i])) {
-            *kvm_features |= 1 << i;
-            found = 1;
+    const char ** feature_names[5] = {feature_name, ext_feature_name,
+                                      ext2_feature_name, ext3_feature_name,
+                                      kvm_feature_name};
+    uint32_t* feature_flags[5] = {features, ext_features, ext2_features,
+                                  ext3_features, kvm_features};
+
+    for (j = 0; j < 5; j++) {
+        for ( i = 0 ; i < 32 ; i++ ) {
+            if (feature_names[j][i] && !strcmp(flagname, feature_names[j][i])) {
+                *feature_flags[j] |= 1 << i;
+                found = 1;
+            }
         }
+    }
 
     if (!found) {
         fprintf(stderr, "CPU feature %s not found\n", flagname);
-- 
1.6.4

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

* [Qemu-devel] [PATCH 09/13] cpuid: propagate further CPUID leafs when -cpu host
  2010-02-02 10:08 [Qemu-devel] [PATCH 00/13] i386 cpuid: cleanup and fixes Andre Przywara
                   ` (7 preceding siblings ...)
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 08/13] cpuid: simplify CPUID flag search function Andre Przywara
@ 2010-02-02 10:08 ` Andre Przywara
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 10/13] cpuid: add TCG feature bit trimming Andre Przywara
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 18+ messages in thread
From: Andre Przywara @ 2010-02-02 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: john.cooper, Andre Przywara

-cpu host currently only propagates the CPU's family/model/stepping,
the brand name and the feature bits.
Add a whitelist of safe CPUID leafs to let the guest see the actual
CPU's cache details and other things.

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
---
 target-i386/cpu.h   |    5 ++++-
 target-i386/cpuid.c |   28 ++++++++++++++++++++++------
 2 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index f826d3d..982f815 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -581,6 +581,9 @@ typedef struct {
 
 #define NB_MMU_MODES 2
 
+#define CPUID_FLAGS_VENDOR_OVERRIDE 1
+#define CPUID_FLAGS_HOST 2
+
 typedef struct CPUX86State {
     /* standard registers */
     target_ulong regs[CPU_NB_REGS];
@@ -685,7 +688,7 @@ typedef struct CPUX86State {
     uint32_t cpuid_ext2_features;
     uint32_t cpuid_ext3_features;
     uint32_t cpuid_apic_id;
-    int cpuid_vendor_override;
+    uint32_t cpuid_flags;
 
     /* MTRRs */
     uint64_t mtrr_fixed[11];
diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 635c2f4..6aa1f3f 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -122,7 +122,7 @@ typedef struct x86_def_t {
     uint32_t features, ext_features, ext2_features, ext3_features, kvm_features;
     uint32_t xlevel;
     char model_id[48];
-    int vendor_override;
+    uint32_t flags;
 } x86_def_t;
 
 #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
@@ -419,7 +419,7 @@ static int cpu_x86_fill_host(x86_def_t *x86_cpu_def)
     x86_cpu_def->ext2_features = edx;
     x86_cpu_def->ext3_features = ecx;
     cpu_x86_fill_model_id(x86_cpu_def->model_id);
-    x86_cpu_def->vendor_override = 0;
+    x86_cpu_def->flags = CPUID_FLAGS_HOST;
 
     return 0;
 }
@@ -529,7 +529,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
                     x86_cpu_def->vendor2 |= ((uint8_t)val[i + 4]) << (8 * i);
                     x86_cpu_def->vendor3 |= ((uint8_t)val[i + 8]) << (8 * i);
                 }
-                x86_cpu_def->vendor_override = 1;
+                x86_cpu_def->flags |= CPUID_FLAGS_VENDOR_OVERRIDE;
             } else if (!strcmp(featurestr, "model_id")) {
                 pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id),
                         val);
@@ -602,7 +602,7 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
         env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2;
         env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3;
     }
-    env->cpuid_vendor_override = def->vendor_override;
+    env->cpuid_flags = def->flags;
     env->cpuid_level = def->level;
     if (def->family > 0x0f)
         env->cpuid_version = 0xf00 | ((def->family - 0x0f) << 20);
@@ -647,22 +647,38 @@ static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx,
      * this if you want to use KVM's sysenter/syscall emulation
      * in compatibility mode and when doing cross vendor migration
      */
-    if (kvm_enabled() && env->cpuid_vendor_override) {
+    if (kvm_enabled() &&
+        (env->cpuid_flags & CPUID_FLAGS_VENDOR_OVERRIDE) == 0) {
         host_cpuid(0, 0, NULL, ebx, ecx, edx);
     }
 }
 
+#define CPUID_LEAF_PROPAGATE ((1 << 0x02) | (1 << 0x04) | (1 << 0x05) |\
+                              (1 << 0x0D))
+#define CPUID_LEAF_PROPAGATE_EXTENDED ((1 << 0x05) | (1 << 0x06) |\
+                                       (1 << 0x08) | (1 << 0x19) | (1 << 0x1A))
+
 void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
                    uint32_t *eax, uint32_t *ebx,
                    uint32_t *ecx, uint32_t *edx)
 {
-    /* test if maximum index reached */
     if (index & 0x80000000) {
+    /* test if maximum index reached */
         if (index > env->cpuid_xlevel)
             index = env->cpuid_level;
+        if ((env->cpuid_flags & CPUID_FLAGS_HOST) &&
+            ((1 << (index - 0x80000000)) & CPUID_LEAF_PROPAGATE_EXTENDED)) {
+            host_cpuid(index, count, eax, ebx, ecx, edx);
+            return;
+        }
     } else {
         if (index > env->cpuid_level)
             index = env->cpuid_level;
+        if ((env->cpuid_flags & CPUID_FLAGS_HOST) &&
+            ((1 << index) & CPUID_LEAF_PROPAGATE)) {
+            host_cpuid(index, count, eax, ebx, ecx, edx);
+            return;
+        }
     }
 
     switch(index) {
-- 
1.6.4

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

* [Qemu-devel] [PATCH 10/13] cpuid: add TCG feature bit trimming
  2010-02-02 10:08 [Qemu-devel] [PATCH 00/13] i386 cpuid: cleanup and fixes Andre Przywara
                   ` (8 preceding siblings ...)
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 09/13] cpuid: propagate further CPUID leafs when -cpu host Andre Przywara
@ 2010-02-02 10:08 ` Andre Przywara
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 11/13] cpuid: Always expose 32 and 64-bit CPUs Andre Przywara
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 18+ messages in thread
From: Andre Przywara @ 2010-02-02 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: john.cooper, Andre Przywara

In KVM we trim the user provided CPUID bits to match the host CPU's
one. Introduce a similar feature to QEMU/TCG. Create a mask of TCG's
capabilities and apply it to the user bits.
This allows to let the CPU models reflect their native archetypes.

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
---
 target-i386/cpuid.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 6aa1f3f..6e6ee54 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -137,6 +137,21 @@ typedef struct x86_def_t {
           CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
           CPUID_PAE | CPUID_SEP | CPUID_APIC)
 #define EXT2_FEATURE_MASK 0x0183F3FF
+
+#define TCG_FEATURES (CPUID_FP87 | CPUID_PSE | CPUID_TSC | CPUID_MSR | \
+          CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | CPUID_SEP | \
+          CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
+          CPUID_PSE36 | CPUID_CLFLUSH | CPUID_ACPI | CPUID_MMX | \
+          CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS)
+#define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | \
+          CPUID_EXT_CX16 | CPUID_EXT_POPCNT | CPUID_EXT_XSAVE | \
+          CPUID_EXT_HYPERVISOR)
+#define TCG_EXT2_FEATURES ((TCG_FEATURES & EXT2_FEATURE_MASK) | \
+          CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
+          CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT)
+#define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
+          CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
+
 static x86_def_t x86_defs[] = {
 #ifdef TARGET_X86_64
     {
@@ -616,6 +631,17 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
     env->cpuid_ext2_features = def->ext2_features;
     env->cpuid_xlevel = def->xlevel;
     env->cpuid_kvm_features = def->kvm_features;
+    env->cpuid_ext3_features = def->ext3_features;
+    if (!kvm_enabled()) {
+        env->cpuid_features &= TCG_FEATURES;
+        env->cpuid_ext_features &= TCG_EXT_FEATURES;
+        env->cpuid_ext2_features &= (TCG_EXT2_FEATURES
+#ifdef TARGET_X86_64
+            | CPUID_EXT2_SYSCALL | CPUID_EXT2_LM
+#endif
+            );
+        env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
+    }
     {
         const char *model_id = def->model_id;
         int c, len, i;
-- 
1.6.4

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

* [Qemu-devel] [PATCH 11/13] cpuid: Always expose 32 and 64-bit CPUs
  2010-02-02 10:08 [Qemu-devel] [PATCH 00/13] i386 cpuid: cleanup and fixes Andre Przywara
                   ` (9 preceding siblings ...)
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 10/13] cpuid: add TCG feature bit trimming Andre Przywara
@ 2010-02-02 10:08 ` Andre Przywara
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 12/13] cpuid: Add kvm32 CPU model Andre Przywara
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 13/13] cpuid: fix CPUID levels Andre Przywara
  12 siblings, 0 replies; 18+ messages in thread
From: Andre Przywara @ 2010-02-02 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: john.cooper, Andre Przywara

Since 64-bit capability is just another CPUID bit we now properly
mask, there is no reason anymore to hide the 64-bit capable CPU
models from a 32-bit only QEMU. All 64-bit CPUs can be used
perfectly in 32-bit legacy mode anyway, so these models also make
sense for 32-bit.

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
---
 target-i386/cpuid.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 6e6ee54..b03a363 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -153,7 +153,6 @@ typedef struct x86_def_t {
           CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
 
 static x86_def_t x86_defs[] = {
-#ifdef TARGET_X86_64
     {
         .name = "qemu64",
         .level = 4,
@@ -252,7 +251,6 @@ static x86_def_t x86_defs[] = {
         .xlevel = 0x80000008,
         .model_id = "Common KVM processor"
     },
-#endif
     {
         .name = "qemu32",
         .level = 4,
-- 
1.6.4

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

* [Qemu-devel] [PATCH 12/13] cpuid: Add kvm32 CPU model
  2010-02-02 10:08 [Qemu-devel] [PATCH 00/13] i386 cpuid: cleanup and fixes Andre Przywara
                   ` (10 preceding siblings ...)
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 11/13] cpuid: Always expose 32 and 64-bit CPUs Andre Przywara
@ 2010-02-02 10:08 ` Andre Przywara
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 13/13] cpuid: fix CPUID levels Andre Przywara
  12 siblings, 0 replies; 18+ messages in thread
From: Andre Przywara @ 2010-02-02 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: john.cooper, Andre Przywara

Create a kvm32 CPU model that describes a least common denominator
for KVM capable guest CPUs. Useful for migration purposes.

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
---
 target-i386/cpuid.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index b03a363..65dcb23 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -263,6 +263,20 @@ static x86_def_t x86_defs[] = {
         .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
     },
     {
+        .name = "kvm32",
+        .level = 5,
+        .family = 15,
+        .model = 6,
+        .stepping = 1,
+        .features = PPRO_FEATURES |
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36,
+        .ext_features = CPUID_EXT_SSE3,
+        .ext2_features = PPRO_FEATURES & EXT2_FEATURE_MASK,
+        .ext3_features = 0,
+        .xlevel = 0x80000008,
+        .model_id = "Common 32-bit KVM processor"
+    },
+    {
         .name = "coreduo",
         .level = 10,
         .family = 6,
-- 
1.6.4

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

* [Qemu-devel] [PATCH 13/13] cpuid: fix CPUID levels
  2010-02-02 10:08 [Qemu-devel] [PATCH 00/13] i386 cpuid: cleanup and fixes Andre Przywara
                   ` (11 preceding siblings ...)
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 12/13] cpuid: Add kvm32 CPU model Andre Przywara
@ 2010-02-02 10:08 ` Andre Przywara
  12 siblings, 0 replies; 18+ messages in thread
From: Andre Przywara @ 2010-02-02 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: john.cooper, Andre Przywara

Bump up the xlevel number for qemu32 to allow parsing of the processor
name string for this model.
Similiarly the 486 processor should have at least the feature bit
leaf enabled.

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
---
 target-i386/cpuid.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 65dcb23..725efe3 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -259,7 +259,7 @@ static x86_def_t x86_defs[] = {
         .stepping = 3,
         .features = PPRO_FEATURES,
         .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
-        .xlevel = 0,
+        .xlevel = 0x80000004,
         .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
     },
     {
@@ -297,7 +297,7 @@ static x86_def_t x86_defs[] = {
     },
     {
         .name = "486",
-        .level = 0,
+        .level = 1,
         .family = 4,
         .model = 0,
         .stepping = 0,
-- 
1.6.4

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

* Re: [Qemu-devel] [PATCH 01/13] cpuid: move CPUID functions into separate file
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 01/13] cpuid: move CPUID functions into separate file Andre Przywara
@ 2010-03-06 18:25   ` Aurelien Jarno
  0 siblings, 0 replies; 18+ messages in thread
From: Aurelien Jarno @ 2010-03-06 18:25 UTC (permalink / raw)
  To: Andre Przywara; +Cc: john.cooper, qemu-devel

On Tue, Feb 02, 2010 at 11:08:09AM +0100, Andre Przywara wrote:
> about 40% of target-i386/helper.c consist of CPUID related functions.
> Only one of them is a real TCG helper function. So move the whole
> CPUID stuff out of this into a separate file to get better
> maintainable parts.
> This is only code reordering and should not affect QEMU's
> functionality.
> 
> Signed-off-by: Andre Przywara <andre.przywara@amd.com>

This looks like a good idea, however, it doesn't apply anymore. Care to
resend it after rebasing it?

> ---
>  Makefile.target      |    3 +
>  target-i386/cpu.h    |    3 +
>  target-i386/cpuid.c  |  821 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  target-i386/helper.c |  779 -----------------------------------------------
>  4 files changed, 827 insertions(+), 779 deletions(-)
>  create mode 100644 target-i386/cpuid.c
> 
> diff --git a/Makefile.target b/Makefile.target
> index 5c0ef1f..37875b8 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -49,6 +49,9 @@ libobj-y += tcg/tcg.o
>  libobj-$(CONFIG_SOFTFLOAT) += fpu/softfloat.o
>  libobj-$(CONFIG_NOSOFTFLOAT) += fpu/softfloat-native.o
>  libobj-y += op_helper.o helper.o
> +ifeq ($(TARGET_BASE_ARCH), i386)
> +libobj-y += cpuid.o
> +endif
>  libobj-$(CONFIG_NEED_MMU) += mmu.o
>  libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
>  libobj-$(TARGET_ALPHA) += alpha_palcode.o
> diff --git a/target-i386/cpu.h b/target-i386/cpu.h
> index 216b00e..f826d3d 100644
> --- a/target-i386/cpu.h
> +++ b/target-i386/cpu.h
> @@ -825,9 +825,12 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
>                               int is_write, int mmu_idx, int is_softmmu);
>  #define cpu_handle_mmu_fault cpu_x86_handle_mmu_fault
>  void cpu_x86_set_a20(CPUX86State *env, int a20_state);
> +
> +/* cpuid.c */
>  void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
>                     uint32_t *eax, uint32_t *ebx,
>                     uint32_t *ecx, uint32_t *edx);
> +int cpu_x86_register (CPUX86State *env, const char *cpu_model);
>  
>  static inline int hw_breakpoint_enabled(unsigned long dr7, int index)
>  {
> diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
> new file mode 100644
> index 0000000..aaa14ba
> --- /dev/null
> +++ b/target-i386/cpuid.c
> @@ -0,0 +1,821 @@
> +/*
> + *  i386 CPUID helper functions
> + *
> + *  Copyright (c) 2003 Fabrice Bellard
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> + */
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <inttypes.h>
> +
> +#include "cpu.h"
> +#include "kvm.h"
> +
> +/* feature flags taken from "Intel Processor Identification and the CPUID
> + * Instruction" and AMD's "CPUID Specification". In cases of disagreement
> + * about feature names, the Linux name is used. */
> +static const char *feature_name[] = {
> +    "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
> +    "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
> +    "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */,
> +        NULL, "ds" /* Intel dts */, "acpi", "mmx",
> +    "fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe",
> +};
> +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, NULL, NULL, NULL, NULL, NULL, "hypervisor",
> +};
> +static const char *ext2_feature_name[] = {
> +    "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
> +    "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall",
> +        "mtrr", "pge", "mca", "cmov",
> +    "pat", "pse36", NULL, NULL /* Linux mp */,
> +        "nx" /* Intel xd */, NULL, "mmxext", "mmx",
> +    "fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp",
> +        NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow",
> +};
> +static const char *ext3_feature_name[] = {
> +    "lahf_lm" /* AMD LahfSahf */, "cmp_legacy",
> +        "svm", "extapic" /* AMD ExtApicSpace */,
> +        "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
> +    "3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL,
> +    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> +};
> +
> +static const char *kvm_feature_name[] = {
> +    "kvmclock", "kvm_nopiodelay", "kvm_mmu", NULL, NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> +};
> +
> +static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
> +                                    uint32_t *ext_features,
> +                                    uint32_t *ext2_features,
> +                                    uint32_t *ext3_features,
> +                                    uint32_t *kvm_features)
> +{
> +    int i;
> +    int found = 0;
> +
> +    for ( i = 0 ; i < 32 ; i++ )
> +        if (feature_name[i] && !strcmp (flagname, feature_name[i])) {
> +            *features |= 1 << i;
> +            found = 1;
> +        }
> +    for ( i = 0 ; i < 32 ; i++ )
> +        if (ext_feature_name[i] && !strcmp (flagname, ext_feature_name[i])) {
> +            *ext_features |= 1 << i;
> +            found = 1;
> +        }
> +    for ( i = 0 ; i < 32 ; i++ )
> +        if (ext2_feature_name[i] && !strcmp (flagname, ext2_feature_name[i])) {
> +            *ext2_features |= 1 << i;
> +            found = 1;
> +        }
> +    for ( i = 0 ; i < 32 ; i++ )
> +        if (ext3_feature_name[i] && !strcmp (flagname, ext3_feature_name[i])) {
> +            *ext3_features |= 1 << i;
> +            found = 1;
> +        }
> +    for ( i = 0 ; i < 32 ; i++ )
> +        if (kvm_feature_name[i] && !strcmp (flagname, kvm_feature_name[i])) {
> +            *kvm_features |= 1 << i;
> +            found = 1;
> +        }
> +
> +    if (!found) {
> +        fprintf(stderr, "CPU feature %s not found\n", flagname);
> +    }
> +}
> +
> +typedef struct x86_def_t {
> +    const char *name;
> +    uint32_t level;
> +    uint32_t vendor1, vendor2, vendor3;
> +    int family;
> +    int model;
> +    int stepping;
> +    uint32_t features, ext_features, ext2_features, ext3_features, kvm_features;
> +    uint32_t xlevel;
> +    char model_id[48];
> +    int vendor_override;
> +} x86_def_t;
> +
> +#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
> +#define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
> +          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC)
> +#define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
> +          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)
> +static x86_def_t x86_defs[] = {
> +#ifdef TARGET_X86_64
> +    {
> +        .name = "qemu64",
> +        .level = 4,
> +        .vendor1 = CPUID_VENDOR_AMD_1,
> +        .vendor2 = CPUID_VENDOR_AMD_2,
> +        .vendor3 = CPUID_VENDOR_AMD_3,
> +        .family = 6,
> +        .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_POPCNT,
> +        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | 
> +            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
> +        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
> +            CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
> +        .xlevel = 0x8000000A,
> +        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
> +    },
> +    {
> +        .name = "phenom",
> +        .level = 5,
> +        .vendor1 = CPUID_VENDOR_AMD_1,
> +        .vendor2 = CPUID_VENDOR_AMD_2,
> +        .vendor3 = CPUID_VENDOR_AMD_3,
> +        .family = 16,
> +        .model = 2,
> +        .stepping = 3,
> +        /* Missing: CPUID_VME, CPUID_HT */
> +        .features = PPRO_FEATURES | 
> +            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
> +            CPUID_PSE36,
> +        .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) | 
> +            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
> +            CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
> +            CPUID_EXT2_FFXSR,
> +        /* Missing: CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
> +                    CPUID_EXT3_CR8LEG,
> +                    CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
> +                    CPUID_EXT3_OSVW, CPUID_EXT3_IBS */
> +        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
> +            CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
> +        .xlevel = 0x8000001A,
> +        .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor"
> +    },
> +    {
> +        .name = "core2duo",
> +        .level = 10,
> +        .family = 6,
> +        .model = 15,
> +        .stepping = 11,
> +	/* The original CPU also implements these features:
> +               CPUID_VME, CPUID_DTS, CPUID_ACPI, CPUID_SS, CPUID_HT,
> +               CPUID_TM, CPUID_PBE */
> +        .features = PPRO_FEATURES |
> +            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
> +            CPUID_PSE36,
> +	/* The original CPU also implements these ext features:
> +               CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST,
> +               CPUID_EXT_TM2, CPUID_EXT_CX16, CPUID_EXT_XTPR, CPUID_EXT_PDCM */
> +        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3,
> +        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
> +        .ext3_features = CPUID_EXT3_LAHF_LM,
> +        .xlevel = 0x80000008,
> +        .model_id = "Intel(R) Core(TM)2 Duo CPU     T7700  @ 2.40GHz",
> +    },
> +    {
> +        .name = "kvm64",
> +        .level = 5,
> +        .vendor1 = CPUID_VENDOR_INTEL_1,
> +        .vendor2 = CPUID_VENDOR_INTEL_2,
> +        .vendor3 = CPUID_VENDOR_INTEL_3,
> +        .family = 15,
> +        .model = 6,
> +        .stepping = 1,
> +        /* Missing: CPUID_VME, CPUID_HT */
> +        .features = PPRO_FEATURES |
> +            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
> +            CPUID_PSE36,
> +        /* 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) |
> +            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,
> +                    CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
> +                    CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */
> +        .ext3_features = 0,
> +        .xlevel = 0x80000008,
> +        .model_id = "Common KVM processor"
> +    },
> +#endif
> +    {
> +        .name = "qemu32",
> +        .level = 4,
> +        .family = 6,
> +        .model = 3,
> +        .stepping = 3,
> +        .features = PPRO_FEATURES,
> +        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
> +        .xlevel = 0,
> +        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
> +    },
> +    {
> +        .name = "coreduo",
> +        .level = 10,
> +        .family = 6,
> +        .model = 14,
> +        .stepping = 8,
> +        /* The original CPU also implements these features:
> +               CPUID_DTS, CPUID_ACPI, CPUID_SS, CPUID_HT,
> +               CPUID_TM, CPUID_PBE */
> +        .features = PPRO_FEATURES | CPUID_VME |
> +            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA,
> +        /* The original CPU also implements these ext features:
> +               CPUID_EXT_VMX, CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_XTPR,
> +               CPUID_EXT_PDCM */
> +        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR,
> +        .ext2_features = CPUID_EXT2_NX,
> +        .xlevel = 0x80000008,
> +        .model_id = "Genuine Intel(R) CPU           T2600  @ 2.16GHz",
> +    },
> +    {
> +        .name = "486",
> +        .level = 0,
> +        .family = 4,
> +        .model = 0,
> +        .stepping = 0,
> +        .features = I486_FEATURES,
> +        .xlevel = 0,
> +    },
> +    {
> +        .name = "pentium",
> +        .level = 1,
> +        .family = 5,
> +        .model = 4,
> +        .stepping = 3,
> +        .features = PENTIUM_FEATURES,
> +        .xlevel = 0,
> +    },
> +    {
> +        .name = "pentium2",
> +        .level = 2,
> +        .family = 6,
> +        .model = 5,
> +        .stepping = 2,
> +        .features = PENTIUM2_FEATURES,
> +        .xlevel = 0,
> +    },
> +    {
> +        .name = "pentium3",
> +        .level = 2,
> +        .family = 6,
> +        .model = 7,
> +        .stepping = 3,
> +        .features = PENTIUM3_FEATURES,
> +        .xlevel = 0,
> +    },
> +    {
> +        .name = "athlon",
> +        .level = 2,
> +        .vendor1 = CPUID_VENDOR_AMD_1,
> +        .vendor2 = CPUID_VENDOR_AMD_2,
> +        .vendor3 = CPUID_VENDOR_AMD_3,
> +        .family = 6,
> +        .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,
> +        .xlevel = 0x80000008,
> +        /* XXX: put another string ? */
> +        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
> +    },
> +    {
> +        .name = "n270",
> +        /* original is on level 10 */
> +        .level = 5,
> +        .family = 6,
> +        .model = 28,
> +        .stepping = 2,
> +        .features = PPRO_FEATURES |
> +            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME,
> +            /* Missing: CPUID_DTS | CPUID_ACPI | CPUID_SS |
> +             * CPUID_HT | CPUID_TM | CPUID_PBE */
> +            /* Some CPUs got no CPUID_SEP */
> +        .ext_features = CPUID_EXT_MONITOR |
> +            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,
> +        /* 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,
> +                               uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
> +
> +static int cpu_x86_fill_model_id(char *str)
> +{
> +    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
> +    int i;
> +
> +    for (i = 0; i < 3; i++) {
> +        host_cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx);
> +        memcpy(str + i * 16 +  0, &eax, 4);
> +        memcpy(str + i * 16 +  4, &ebx, 4);
> +        memcpy(str + i * 16 +  8, &ecx, 4);
> +        memcpy(str + i * 16 + 12, &edx, 4);
> +    }
> +    return 0;
> +}
> +
> +static int cpu_x86_fill_host(x86_def_t *x86_cpu_def)
> +{
> +    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
> +
> +    x86_cpu_def->name = "host";
> +    host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
> +    x86_cpu_def->level = eax;
> +    x86_cpu_def->vendor1 = ebx;
> +    x86_cpu_def->vendor2 = edx;
> +    x86_cpu_def->vendor3 = ecx;
> +
> +    host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
> +    x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
> +    x86_cpu_def->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
> +    x86_cpu_def->stepping = eax & 0x0F;
> +    x86_cpu_def->ext_features = ecx;
> +    x86_cpu_def->features = edx;
> +
> +    host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx);
> +    x86_cpu_def->xlevel = eax;
> +
> +    host_cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx);
> +    x86_cpu_def->ext2_features = edx;
> +    x86_cpu_def->ext3_features = ecx;
> +    cpu_x86_fill_model_id(x86_cpu_def->model_id);
> +    x86_cpu_def->vendor_override = 0;
> +
> +    return 0;
> +}
> +
> +static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
> +{
> +    unsigned int i;
> +    x86_def_t *def;
> +
> +    char *s = strdup(cpu_model);
> +    char *featurestr, *name = strtok(s, ",");
> +    uint32_t plus_features = 0, plus_ext_features = 0,
> +        plus_ext2_features = 0, plus_ext3_features = 0, plus_kvm_features = 0;
> +    uint32_t minus_features = 0, minus_ext_features = 0,
> +        minus_ext2_features = 0, minus_ext3_features = 0,
> +        minus_kvm_features = 0;
> +    uint32_t numvalue;
> +
> +    def = NULL;
> +    for (i = 0; i < ARRAY_SIZE(x86_defs); i++) {
> +        if (strcmp(name, x86_defs[i].name) == 0) {
> +            def = &x86_defs[i];
> +            break;
> +        }
> +    }
> +    if (kvm_enabled() && strcmp(name, "host") == 0) {
> +        cpu_x86_fill_host(x86_cpu_def);
> +    } else if (!def) {
> +        goto error;
> +    } else {
> +        memcpy(x86_cpu_def, def, sizeof(*def));
> +    }
> +
> +    plus_kvm_features = ~0; /* not supported bits will be filtered out later */
> +
> +    add_flagname_to_bitmaps("hypervisor", &plus_features,
> +        &plus_ext_features, &plus_ext2_features, &plus_ext3_features,
> +        &plus_kvm_features);
> +
> +    featurestr = strtok(NULL, ",");
> +
> +    while (featurestr) {
> +        char *val;
> +        if (featurestr[0] == '+') {
> +            add_flagname_to_bitmaps(featurestr + 1, &plus_features,
> +                                    &plus_ext_features, &plus_ext2_features,
> +                                    &plus_ext3_features, &plus_kvm_features);
> +        } else if (featurestr[0] == '-') {
> +            add_flagname_to_bitmaps(featurestr + 1, &minus_features,
> +                                    &minus_ext_features, &minus_ext2_features,
> +                                    &minus_ext3_features, &minus_kvm_features);
> +        } else if ((val = strchr(featurestr, '='))) {
> +            *val = 0; val++;
> +            if (!strcmp(featurestr, "family")) {
> +                char *err;
> +                numvalue = strtoul(val, &err, 0);
> +                if (!*val || *err) {
> +                    fprintf(stderr, "bad numerical value %s\n", val);
> +                    goto error;
> +                }
> +                x86_cpu_def->family = numvalue;
> +            } else if (!strcmp(featurestr, "model")) {
> +                char *err;
> +                numvalue = strtoul(val, &err, 0);
> +                if (!*val || *err || numvalue > 0xff) {
> +                    fprintf(stderr, "bad numerical value %s\n", val);
> +                    goto error;
> +                }
> +                x86_cpu_def->model = numvalue;
> +            } else if (!strcmp(featurestr, "stepping")) {
> +                char *err;
> +                numvalue = strtoul(val, &err, 0);
> +                if (!*val || *err || numvalue > 0xf) {
> +                    fprintf(stderr, "bad numerical value %s\n", val);
> +                    goto error;
> +                }
> +                x86_cpu_def->stepping = numvalue ;
> +            } else if (!strcmp(featurestr, "level")) {
> +                char *err;
> +                numvalue = strtoul(val, &err, 0);
> +                if (!*val || *err) {
> +                    fprintf(stderr, "bad numerical value %s\n", val);
> +                    goto error;
> +                }
> +                x86_cpu_def->level = numvalue;
> +            } else if (!strcmp(featurestr, "xlevel")) {
> +                char *err;
> +                numvalue = strtoul(val, &err, 0);
> +                if (!*val || *err) {
> +                    fprintf(stderr, "bad numerical value %s\n", val);
> +                    goto error;
> +                }
> +                if (numvalue < 0x80000000) {
> +                	numvalue += 0x80000000;
> +                }
> +                x86_cpu_def->xlevel = numvalue;
> +            } else if (!strcmp(featurestr, "vendor")) {
> +                if (strlen(val) != 12) {
> +                    fprintf(stderr, "vendor string must be 12 chars long\n");
> +                    goto error;
> +                }
> +                x86_cpu_def->vendor1 = 0;
> +                x86_cpu_def->vendor2 = 0;
> +                x86_cpu_def->vendor3 = 0;
> +                for(i = 0; i < 4; i++) {
> +                    x86_cpu_def->vendor1 |= ((uint8_t)val[i    ]) << (8 * i);
> +                    x86_cpu_def->vendor2 |= ((uint8_t)val[i + 4]) << (8 * i);
> +                    x86_cpu_def->vendor3 |= ((uint8_t)val[i + 8]) << (8 * i);
> +                }
> +                x86_cpu_def->vendor_override = 1;
> +            } else if (!strcmp(featurestr, "model_id")) {
> +                pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id),
> +                        val);
> +            } else {
> +                fprintf(stderr, "unrecognized feature %s\n", featurestr);
> +                goto error;
> +            }
> +        } else {
> +            fprintf(stderr, "feature string `%s' not in format "
> +                            "(+feature|-feature|feature=xyz)\n", featurestr);
> +            goto error;
> +        }
> +        featurestr = strtok(NULL, ",");
> +    }
> +    x86_cpu_def->features |= plus_features;
> +    x86_cpu_def->ext_features |= plus_ext_features;
> +    x86_cpu_def->ext2_features |= plus_ext2_features;
> +    x86_cpu_def->ext3_features |= plus_ext3_features;
> +    x86_cpu_def->kvm_features |= plus_kvm_features;
> +    x86_cpu_def->features &= ~minus_features;
> +    x86_cpu_def->ext_features &= ~minus_ext_features;
> +    x86_cpu_def->ext2_features &= ~minus_ext2_features;
> +    x86_cpu_def->ext3_features &= ~minus_ext3_features;
> +    x86_cpu_def->kvm_features &= ~minus_kvm_features;
> +    free(s);
> +    return 0;
> +
> +error:
> +    free(s);
> +    return -1;
> +}
> +
> +void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
> +{
> +    unsigned int i;
> +
> +    for (i = 0; i < ARRAY_SIZE(x86_defs); i++)
> +        (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name);
> +}
> +
> +int cpu_x86_register (CPUX86State *env, const char *cpu_model)
> +{
> +    x86_def_t def1, *def = &def1;
> +
> +    if (cpu_x86_find_by_name(def, cpu_model) < 0)
> +        return -1;
> +    if (def->vendor1) {
> +        env->cpuid_vendor1 = def->vendor1;
> +        env->cpuid_vendor2 = def->vendor2;
> +        env->cpuid_vendor3 = def->vendor3;
> +    } else {
> +        env->cpuid_vendor1 = CPUID_VENDOR_INTEL_1;
> +        env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2;
> +        env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3;
> +    }
> +    env->cpuid_vendor_override = def->vendor_override;
> +    env->cpuid_level = def->level;
> +    if (def->family > 0x0f)
> +        env->cpuid_version = 0xf00 | ((def->family - 0x0f) << 20);
> +    else
> +        env->cpuid_version = def->family << 8;
> +    env->cpuid_version |= ((def->model & 0xf) << 4) | ((def->model >> 4) << 16);
> +    env->cpuid_version |= def->stepping;
> +    env->cpuid_features = def->features;
> +    env->pat = 0x0007040600070406ULL;
> +    env->cpuid_ext_features = def->ext_features;
> +    env->cpuid_ext2_features = def->ext2_features;
> +    env->cpuid_xlevel = def->xlevel;
> +    env->cpuid_kvm_features = def->kvm_features;
> +    {
> +        const char *model_id = def->model_id;
> +        int c, len, i;
> +        if (!model_id)
> +            model_id = "";
> +        len = strlen(model_id);
> +        for(i = 0; i < 48; i++) {
> +            if (i >= len)
> +                c = '\0';
> +            else
> +                c = (uint8_t)model_id[i];
> +            env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
> +        }
> +    }
> +    return 0;
> +}
> +
> +static void host_cpuid(uint32_t function, uint32_t count,
> +                       uint32_t *eax, uint32_t *ebx,
> +                       uint32_t *ecx, uint32_t *edx)
> +{
> +#if defined(CONFIG_KVM)
> +    uint32_t vec[4];
> +
> +#ifdef __x86_64__
> +    asm volatile("cpuid"
> +                 : "=a"(vec[0]), "=b"(vec[1]),
> +                   "=c"(vec[2]), "=d"(vec[3])
> +                 : "0"(function), "c"(count) : "cc");
> +#else
> +    asm volatile("pusha \n\t"
> +                 "cpuid \n\t"
> +                 "mov %%eax, 0(%2) \n\t"
> +                 "mov %%ebx, 4(%2) \n\t"
> +                 "mov %%ecx, 8(%2) \n\t"
> +                 "mov %%edx, 12(%2) \n\t"
> +                 "popa"
> +                 : : "a"(function), "c"(count), "S"(vec)
> +                 : "memory", "cc");
> +#endif
> +
> +    if (eax)
> +	*eax = vec[0];
> +    if (ebx)
> +	*ebx = vec[1];
> +    if (ecx)
> +	*ecx = vec[2];
> +    if (edx)
> +	*edx = vec[3];
> +#endif
> +}
> +
> +static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx,
> +                             uint32_t *ecx, uint32_t *edx)
> +{
> +    *ebx = env->cpuid_vendor1;
> +    *edx = env->cpuid_vendor2;
> +    *ecx = env->cpuid_vendor3;
> +
> +    /* sysenter isn't supported on compatibility mode on AMD, syscall
> +     * isn't supported in compatibility mode on Intel.
> +     * Normally we advertise the actual cpu vendor, but you can override
> +     * this if you want to use KVM's sysenter/syscall emulation
> +     * in compatibility mode and when doing cross vendor migration
> +     */
> +    if (kvm_enabled() && env->cpuid_vendor_override) {
> +        host_cpuid(0, 0, NULL, ebx, ecx, edx);
> +    }
> +}
> +
> +void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
> +                   uint32_t *eax, uint32_t *ebx,
> +                   uint32_t *ecx, uint32_t *edx)
> +{
> +    /* test if maximum index reached */
> +    if (index & 0x80000000) {
> +        if (index > env->cpuid_xlevel)
> +            index = env->cpuid_level;
> +    } else {
> +        if (index > env->cpuid_level)
> +            index = env->cpuid_level;
> +    }
> +
> +    switch(index) {
> +    case 0:
> +        *eax = env->cpuid_level;
> +        get_cpuid_vendor(env, ebx, ecx, edx);
> +        break;
> +    case 1:
> +        *eax = env->cpuid_version;
> +        /* CLFLUSH size in quad words, Linux wants it. */
> +        *ebx = (env->cpuid_apic_id << 24) | 8 << 8;
> +        *ecx = env->cpuid_ext_features;
> +        *edx = env->cpuid_features;
> +        if (env->nr_cores * env->nr_threads > 1) {
> +            *ebx |= (env->nr_cores * env->nr_threads) << 16;
> +            *edx |= 1 << 28;    /* HTT bit */
> +        }
> +        break;
> +    case 2:
> +        /* cache info: needed for Pentium Pro compatibility */
> +        *eax = 1;
> +        *ebx = 0;
> +        *ecx = 0;
> +        *edx = 0x2c307d;
> +        break;
> +    case 4:
> +        /* cache info: needed for Core compatibility */
> +        if (env->nr_cores > 1) {
> +        	*eax = (env->nr_cores - 1) << 26;
> +        } else {
> +        	*eax = 0;
> +        }
> +        switch (count) {
> +            case 0: /* L1 dcache info */
> +                *eax |= 0x0000121;
> +                *ebx = 0x1c0003f;
> +                *ecx = 0x000003f;
> +                *edx = 0x0000001;
> +                break;
> +            case 1: /* L1 icache info */
> +                *eax |= 0x0000122;
> +                *ebx = 0x1c0003f;
> +                *ecx = 0x000003f;
> +                *edx = 0x0000001;
> +                break;
> +            case 2: /* L2 cache info */
> +                *eax |= 0x0000143;
> +                if (env->nr_threads > 1) {
> +                    *eax |= (env->nr_threads - 1) << 14;
> +                }
> +                *ebx = 0x3c0003f;
> +                *ecx = 0x0000fff;
> +                *edx = 0x0000001;
> +                break;
> +            default: /* end of info */
> +                *eax = 0;
> +                *ebx = 0;
> +                *ecx = 0;
> +                *edx = 0;
> +                break;
> +        }
> +        break;
> +    case 5:
> +        /* mwait info: needed for Core compatibility */
> +        *eax = 0; /* Smallest monitor-line size in bytes */
> +        *ebx = 0; /* Largest monitor-line size in bytes */
> +        *ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
> +        *edx = 0;
> +        break;
> +    case 6:
> +        /* Thermal and Power Leaf */
> +        *eax = 0;
> +        *ebx = 0;
> +        *ecx = 0;
> +        *edx = 0;
> +        break;
> +    case 9:
> +        /* Direct Cache Access Information Leaf */
> +        *eax = 0; /* Bits 0-31 in DCA_CAP MSR */
> +        *ebx = 0;
> +        *ecx = 0;
> +        *edx = 0;
> +        break;
> +    case 0xA:
> +        /* Architectural Performance Monitoring Leaf */
> +        *eax = 0;
> +        *ebx = 0;
> +        *ecx = 0;
> +        *edx = 0;
> +        break;
> +    case 0x80000000:
> +        *eax = env->cpuid_xlevel;
> +        *ebx = env->cpuid_vendor1;
> +        *edx = env->cpuid_vendor2;
> +        *ecx = env->cpuid_vendor3;
> +        break;
> +    case 0x80000001:
> +        *eax = env->cpuid_version;
> +        *ebx = 0;
> +        *ecx = env->cpuid_ext3_features;
> +        *edx = env->cpuid_ext2_features;
> +
> +        /* The Linux kernel checks for the CMPLegacy bit and
> +         * discards multiple thread information if it is set.
> +         * So dont set it here for Intel to make Linux guests happy.
> +         */
> +        if (env->nr_cores * env->nr_threads > 1) {
> +            uint32_t tebx, tecx, tedx;
> +            get_cpuid_vendor(env, &tebx, &tecx, &tedx);
> +            if (tebx != CPUID_VENDOR_INTEL_1 ||
> +                tedx != CPUID_VENDOR_INTEL_2 ||
> +                tecx != CPUID_VENDOR_INTEL_3) {
> +                *ecx |= 1 << 1;    /* CmpLegacy bit */
> +            }
> +        }
> +
> +        if (kvm_enabled()) {
> +            /* Nested SVM not yet supported in upstream QEMU */
> +            *ecx &= ~CPUID_EXT3_SVM;
> +        }
> +        break;
> +    case 0x80000002:
> +    case 0x80000003:
> +    case 0x80000004:
> +        *eax = env->cpuid_model[(index - 0x80000002) * 4 + 0];
> +        *ebx = env->cpuid_model[(index - 0x80000002) * 4 + 1];
> +        *ecx = env->cpuid_model[(index - 0x80000002) * 4 + 2];
> +        *edx = env->cpuid_model[(index - 0x80000002) * 4 + 3];
> +        break;
> +    case 0x80000005:
> +        /* cache info (L1 cache) */
> +        *eax = 0x01ff01ff;
> +        *ebx = 0x01ff01ff;
> +        *ecx = 0x40020140;
> +        *edx = 0x40020140;
> +        break;
> +    case 0x80000006:
> +        /* cache info (L2 cache) */
> +        *eax = 0;
> +        *ebx = 0x42004200;
> +        *ecx = 0x02008140;
> +        *edx = 0;
> +        break;
> +    case 0x80000008:
> +        /* virtual & phys address size in low 2 bytes. */
> +/* XXX: This value must match the one used in the MMU code. */ 
> +        if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
> +            /* 64 bit processor */
> +/* XXX: The physical address space is limited to 42 bits in exec.c. */
> +            *eax = 0x00003028;	/* 48 bits virtual, 40 bits physical */
> +        } else {
> +            if (env->cpuid_features & CPUID_PSE36)
> +                *eax = 0x00000024; /* 36 bits physical */
> +            else
> +                *eax = 0x00000020; /* 32 bits physical */
> +        }
> +        *ebx = 0;
> +        *ecx = 0;
> +        *edx = 0;
> +        if (env->nr_cores * env->nr_threads > 1) {
> +            *ecx |= (env->nr_cores * env->nr_threads) - 1;
> +        }
> +        break;
> +    case 0x8000000A:
> +        *eax = 0x00000001; /* SVM Revision */
> +        *ebx = 0x00000010; /* nr of ASIDs */
> +        *ecx = 0;
> +        *edx = 0; /* optional features */
> +        break;
> +    default:
> +        /* reserved values: zero */
> +        *eax = 0;
> +        *ebx = 0;
> +        *ecx = 0;
> +        *edx = 0;
> +        break;
> +    }
> +}
> diff --git a/target-i386/helper.c b/target-i386/helper.c
> index 70762bb..b120051 100644
> --- a/target-i386/helper.c
> +++ b/target-i386/helper.c
> @@ -30,542 +30,6 @@
>  
>  //#define DEBUG_MMU
>  
> -/* feature flags taken from "Intel Processor Identification and the CPUID
> - * Instruction" and AMD's "CPUID Specification". In cases of disagreement
> - * about feature names, the Linux name is used. */
> -static const char *feature_name[] = {
> -    "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
> -    "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
> -    "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */, NULL, "ds" /* Intel dts */, "acpi", "mmx",
> -    "fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe",
> -};
> -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, NULL, NULL, NULL, NULL, NULL, "hypervisor",
> -};
> -static const char *ext2_feature_name[] = {
> -    "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
> -    "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall", "mtrr", "pge", "mca", "cmov",
> -    "pat", "pse36", NULL, NULL /* Linux mp */, "nx" /* Intel xd */, NULL, "mmxext", "mmx",
> -    "fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp", NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow",
> -};
> -static const char *ext3_feature_name[] = {
> -    "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
> -    "3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL,
> -    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> -    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> -};
> -
> -static const char *kvm_feature_name[] = {
> -    "kvmclock", "kvm_nopiodelay", "kvm_mmu", NULL, NULL, NULL, NULL, NULL,
> -    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> -    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> -    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> -};
> -
> -static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
> -                                    uint32_t *ext_features,
> -                                    uint32_t *ext2_features,
> -                                    uint32_t *ext3_features,
> -                                    uint32_t *kvm_features)
> -{
> -    int i;
> -    int found = 0;
> -
> -    for ( i = 0 ; i < 32 ; i++ )
> -        if (feature_name[i] && !strcmp (flagname, feature_name[i])) {
> -            *features |= 1 << i;
> -            found = 1;
> -        }
> -    for ( i = 0 ; i < 32 ; i++ )
> -        if (ext_feature_name[i] && !strcmp (flagname, ext_feature_name[i])) {
> -            *ext_features |= 1 << i;
> -            found = 1;
> -        }
> -    for ( i = 0 ; i < 32 ; i++ )
> -        if (ext2_feature_name[i] && !strcmp (flagname, ext2_feature_name[i])) {
> -            *ext2_features |= 1 << i;
> -            found = 1;
> -        }
> -    for ( i = 0 ; i < 32 ; i++ )
> -        if (ext3_feature_name[i] && !strcmp (flagname, ext3_feature_name[i])) {
> -            *ext3_features |= 1 << i;
> -            found = 1;
> -        }
> -    for ( i = 0 ; i < 32 ; i++ )
> -        if (kvm_feature_name[i] && !strcmp (flagname, kvm_feature_name[i])) {
> -            *kvm_features |= 1 << i;
> -            found = 1;
> -        }
> -
> -    if (!found) {
> -        fprintf(stderr, "CPU feature %s not found\n", flagname);
> -    }
> -}
> -
> -typedef struct x86_def_t {
> -    const char *name;
> -    uint32_t level;
> -    uint32_t vendor1, vendor2, vendor3;
> -    int family;
> -    int model;
> -    int stepping;
> -    uint32_t features, ext_features, ext2_features, ext3_features, kvm_features;
> -    uint32_t xlevel;
> -    char model_id[48];
> -    int vendor_override;
> -} x86_def_t;
> -
> -#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
> -#define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
> -          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC)
> -#define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
> -          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)
> -static x86_def_t x86_defs[] = {
> -#ifdef TARGET_X86_64
> -    {
> -        .name = "qemu64",
> -        .level = 4,
> -        .vendor1 = CPUID_VENDOR_AMD_1,
> -        .vendor2 = CPUID_VENDOR_AMD_2,
> -        .vendor3 = CPUID_VENDOR_AMD_3,
> -        .family = 6,
> -        .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_POPCNT,
> -        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | 
> -            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
> -        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
> -            CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
> -        .xlevel = 0x8000000A,
> -        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
> -    },
> -    {
> -        .name = "phenom",
> -        .level = 5,
> -        .vendor1 = CPUID_VENDOR_AMD_1,
> -        .vendor2 = CPUID_VENDOR_AMD_2,
> -        .vendor3 = CPUID_VENDOR_AMD_3,
> -        .family = 16,
> -        .model = 2,
> -        .stepping = 3,
> -        /* Missing: CPUID_VME, CPUID_HT */
> -        .features = PPRO_FEATURES | 
> -            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
> -            CPUID_PSE36,
> -        .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) | 
> -            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
> -            CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
> -            CPUID_EXT2_FFXSR,
> -        /* Missing: CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
> -                    CPUID_EXT3_CR8LEG,
> -                    CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
> -                    CPUID_EXT3_OSVW, CPUID_EXT3_IBS */
> -        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
> -            CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
> -        .xlevel = 0x8000001A,
> -        .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor"
> -    },
> -    {
> -        .name = "core2duo",
> -        .level = 10,
> -        .family = 6,
> -        .model = 15,
> -        .stepping = 11,
> -	/* The original CPU also implements these features:
> -               CPUID_VME, CPUID_DTS, CPUID_ACPI, CPUID_SS, CPUID_HT,
> -               CPUID_TM, CPUID_PBE */
> -        .features = PPRO_FEATURES |
> -            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
> -            CPUID_PSE36,
> -	/* The original CPU also implements these ext features:
> -               CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST,
> -               CPUID_EXT_TM2, CPUID_EXT_CX16, CPUID_EXT_XTPR, CPUID_EXT_PDCM */
> -        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3,
> -        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
> -        .ext3_features = CPUID_EXT3_LAHF_LM,
> -        .xlevel = 0x80000008,
> -        .model_id = "Intel(R) Core(TM)2 Duo CPU     T7700  @ 2.40GHz",
> -    },
> -    {
> -        .name = "kvm64",
> -        .level = 5,
> -        .vendor1 = CPUID_VENDOR_INTEL_1,
> -        .vendor2 = CPUID_VENDOR_INTEL_2,
> -        .vendor3 = CPUID_VENDOR_INTEL_3,
> -        .family = 15,
> -        .model = 6,
> -        .stepping = 1,
> -        /* Missing: CPUID_VME, CPUID_HT */
> -        .features = PPRO_FEATURES |
> -            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
> -            CPUID_PSE36,
> -        /* 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) |
> -            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,
> -                    CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
> -                    CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */
> -        .ext3_features = 0,
> -        .xlevel = 0x80000008,
> -        .model_id = "Common KVM processor"
> -    },
> -#endif
> -    {
> -        .name = "qemu32",
> -        .level = 4,
> -        .family = 6,
> -        .model = 3,
> -        .stepping = 3,
> -        .features = PPRO_FEATURES,
> -        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
> -        .xlevel = 0,
> -        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
> -    },
> -    {
> -        .name = "coreduo",
> -        .level = 10,
> -        .family = 6,
> -        .model = 14,
> -        .stepping = 8,
> -        /* The original CPU also implements these features:
> -               CPUID_DTS, CPUID_ACPI, CPUID_SS, CPUID_HT,
> -               CPUID_TM, CPUID_PBE */
> -        .features = PPRO_FEATURES | CPUID_VME |
> -            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA,
> -        /* The original CPU also implements these ext features:
> -               CPUID_EXT_VMX, CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_XTPR,
> -               CPUID_EXT_PDCM */
> -        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR,
> -        .ext2_features = CPUID_EXT2_NX,
> -        .xlevel = 0x80000008,
> -        .model_id = "Genuine Intel(R) CPU           T2600  @ 2.16GHz",
> -    },
> -    {
> -        .name = "486",
> -        .level = 0,
> -        .family = 4,
> -        .model = 0,
> -        .stepping = 0,
> -        .features = I486_FEATURES,
> -        .xlevel = 0,
> -    },
> -    {
> -        .name = "pentium",
> -        .level = 1,
> -        .family = 5,
> -        .model = 4,
> -        .stepping = 3,
> -        .features = PENTIUM_FEATURES,
> -        .xlevel = 0,
> -    },
> -    {
> -        .name = "pentium2",
> -        .level = 2,
> -        .family = 6,
> -        .model = 5,
> -        .stepping = 2,
> -        .features = PENTIUM2_FEATURES,
> -        .xlevel = 0,
> -    },
> -    {
> -        .name = "pentium3",
> -        .level = 2,
> -        .family = 6,
> -        .model = 7,
> -        .stepping = 3,
> -        .features = PENTIUM3_FEATURES,
> -        .xlevel = 0,
> -    },
> -    {
> -        .name = "athlon",
> -        .level = 2,
> -        .vendor1 = CPUID_VENDOR_AMD_1,
> -        .vendor2 = CPUID_VENDOR_AMD_2,
> -        .vendor3 = CPUID_VENDOR_AMD_3,
> -        .family = 6,
> -        .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,
> -        .xlevel = 0x80000008,
> -        /* XXX: put another string ? */
> -        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
> -    },
> -    {
> -        .name = "n270",
> -        /* original is on level 10 */
> -        .level = 5,
> -        .family = 6,
> -        .model = 28,
> -        .stepping = 2,
> -        .features = PPRO_FEATURES |
> -            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME,
> -            /* Missing: CPUID_DTS | CPUID_ACPI | CPUID_SS |
> -             * CPUID_HT | CPUID_TM | CPUID_PBE */
> -            /* Some CPUs got no CPUID_SEP */
> -        .ext_features = CPUID_EXT_MONITOR |
> -            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,
> -        /* 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,
> -                               uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
> -
> -static int cpu_x86_fill_model_id(char *str)
> -{
> -    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
> -    int i;
> -
> -    for (i = 0; i < 3; i++) {
> -        host_cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx);
> -        memcpy(str + i * 16 +  0, &eax, 4);
> -        memcpy(str + i * 16 +  4, &ebx, 4);
> -        memcpy(str + i * 16 +  8, &ecx, 4);
> -        memcpy(str + i * 16 + 12, &edx, 4);
> -    }
> -    return 0;
> -}
> -
> -static int cpu_x86_fill_host(x86_def_t *x86_cpu_def)
> -{
> -    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
> -
> -    x86_cpu_def->name = "host";
> -    host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
> -    x86_cpu_def->level = eax;
> -    x86_cpu_def->vendor1 = ebx;
> -    x86_cpu_def->vendor2 = edx;
> -    x86_cpu_def->vendor3 = ecx;
> -
> -    host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
> -    x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
> -    x86_cpu_def->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
> -    x86_cpu_def->stepping = eax & 0x0F;
> -    x86_cpu_def->ext_features = ecx;
> -    x86_cpu_def->features = edx;
> -
> -    host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx);
> -    x86_cpu_def->xlevel = eax;
> -
> -    host_cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx);
> -    x86_cpu_def->ext2_features = edx;
> -    x86_cpu_def->ext3_features = ecx;
> -    cpu_x86_fill_model_id(x86_cpu_def->model_id);
> -    x86_cpu_def->vendor_override = 0;
> -
> -    return 0;
> -}
> -
> -static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
> -{
> -    unsigned int i;
> -    x86_def_t *def;
> -
> -    char *s = strdup(cpu_model);
> -    char *featurestr, *name = strtok(s, ",");
> -    uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0, plus_kvm_features = 0;
> -    uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0, minus_kvm_features = 0;
> -    uint32_t numvalue;
> -
> -    def = NULL;
> -    for (i = 0; i < ARRAY_SIZE(x86_defs); i++) {
> -        if (strcmp(name, x86_defs[i].name) == 0) {
> -            def = &x86_defs[i];
> -            break;
> -        }
> -    }
> -    if (kvm_enabled() && strcmp(name, "host") == 0) {
> -        cpu_x86_fill_host(x86_cpu_def);
> -    } else if (!def) {
> -        goto error;
> -    } else {
> -        memcpy(x86_cpu_def, def, sizeof(*def));
> -    }
> -
> -    plus_kvm_features = ~0; /* not supported bits will be filtered out later */
> -
> -    add_flagname_to_bitmaps("hypervisor", &plus_features,
> -        &plus_ext_features, &plus_ext2_features, &plus_ext3_features,
> -        &plus_kvm_features);
> -
> -    featurestr = strtok(NULL, ",");
> -
> -    while (featurestr) {
> -        char *val;
> -        if (featurestr[0] == '+') {
> -            add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features, &plus_kvm_features);
> -        } else if (featurestr[0] == '-') {
> -            add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features, &minus_kvm_features);
> -        } else if ((val = strchr(featurestr, '='))) {
> -            *val = 0; val++;
> -            if (!strcmp(featurestr, "family")) {
> -                char *err;
> -                numvalue = strtoul(val, &err, 0);
> -                if (!*val || *err) {
> -                    fprintf(stderr, "bad numerical value %s\n", val);
> -                    goto error;
> -                }
> -                x86_cpu_def->family = numvalue;
> -            } else if (!strcmp(featurestr, "model")) {
> -                char *err;
> -                numvalue = strtoul(val, &err, 0);
> -                if (!*val || *err || numvalue > 0xff) {
> -                    fprintf(stderr, "bad numerical value %s\n", val);
> -                    goto error;
> -                }
> -                x86_cpu_def->model = numvalue;
> -            } else if (!strcmp(featurestr, "stepping")) {
> -                char *err;
> -                numvalue = strtoul(val, &err, 0);
> -                if (!*val || *err || numvalue > 0xf) {
> -                    fprintf(stderr, "bad numerical value %s\n", val);
> -                    goto error;
> -                }
> -                x86_cpu_def->stepping = numvalue ;
> -            } else if (!strcmp(featurestr, "level")) {
> -                char *err;
> -                numvalue = strtoul(val, &err, 0);
> -                if (!*val || *err) {
> -                    fprintf(stderr, "bad numerical value %s\n", val);
> -                    goto error;
> -                }
> -                x86_cpu_def->level = numvalue;
> -            } else if (!strcmp(featurestr, "xlevel")) {
> -                char *err;
> -                numvalue = strtoul(val, &err, 0);
> -                if (!*val || *err) {
> -                    fprintf(stderr, "bad numerical value %s\n", val);
> -                    goto error;
> -                }
> -                if (numvalue < 0x80000000) {
> -                	numvalue += 0x80000000;
> -                }
> -                x86_cpu_def->xlevel = numvalue;
> -            } else if (!strcmp(featurestr, "vendor")) {
> -                if (strlen(val) != 12) {
> -                    fprintf(stderr, "vendor string must be 12 chars long\n");
> -                    goto error;
> -                }
> -                x86_cpu_def->vendor1 = 0;
> -                x86_cpu_def->vendor2 = 0;
> -                x86_cpu_def->vendor3 = 0;
> -                for(i = 0; i < 4; i++) {
> -                    x86_cpu_def->vendor1 |= ((uint8_t)val[i    ]) << (8 * i);
> -                    x86_cpu_def->vendor2 |= ((uint8_t)val[i + 4]) << (8 * i);
> -                    x86_cpu_def->vendor3 |= ((uint8_t)val[i + 8]) << (8 * i);
> -                }
> -                x86_cpu_def->vendor_override = 1;
> -            } else if (!strcmp(featurestr, "model_id")) {
> -                pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id),
> -                        val);
> -            } else {
> -                fprintf(stderr, "unrecognized feature %s\n", featurestr);
> -                goto error;
> -            }
> -        } else {
> -            fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
> -            goto error;
> -        }
> -        featurestr = strtok(NULL, ",");
> -    }
> -    x86_cpu_def->features |= plus_features;
> -    x86_cpu_def->ext_features |= plus_ext_features;
> -    x86_cpu_def->ext2_features |= plus_ext2_features;
> -    x86_cpu_def->ext3_features |= plus_ext3_features;
> -    x86_cpu_def->kvm_features |= plus_kvm_features;
> -    x86_cpu_def->features &= ~minus_features;
> -    x86_cpu_def->ext_features &= ~minus_ext_features;
> -    x86_cpu_def->ext2_features &= ~minus_ext2_features;
> -    x86_cpu_def->ext3_features &= ~minus_ext3_features;
> -    x86_cpu_def->kvm_features &= ~minus_kvm_features;
> -    free(s);
> -    return 0;
> -
> -error:
> -    free(s);
> -    return -1;
> -}
> -
> -void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
> -{
> -    unsigned int i;
> -
> -    for (i = 0; i < ARRAY_SIZE(x86_defs); i++)
> -        (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name);
> -}
> -
> -static int cpu_x86_register (CPUX86State *env, const char *cpu_model)
> -{
> -    x86_def_t def1, *def = &def1;
> -
> -    if (cpu_x86_find_by_name(def, cpu_model) < 0)
> -        return -1;
> -    if (def->vendor1) {
> -        env->cpuid_vendor1 = def->vendor1;
> -        env->cpuid_vendor2 = def->vendor2;
> -        env->cpuid_vendor3 = def->vendor3;
> -    } else {
> -        env->cpuid_vendor1 = CPUID_VENDOR_INTEL_1;
> -        env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2;
> -        env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3;
> -    }
> -    env->cpuid_vendor_override = def->vendor_override;
> -    env->cpuid_level = def->level;
> -    if (def->family > 0x0f)
> -        env->cpuid_version = 0xf00 | ((def->family - 0x0f) << 20);
> -    else
> -        env->cpuid_version = def->family << 8;
> -    env->cpuid_version |= ((def->model & 0xf) << 4) | ((def->model >> 4) << 16);
> -    env->cpuid_version |= def->stepping;
> -    env->cpuid_features = def->features;
> -    env->pat = 0x0007040600070406ULL;
> -    env->cpuid_ext_features = def->ext_features;
> -    env->cpuid_ext2_features = def->ext2_features;
> -    env->cpuid_xlevel = def->xlevel;
> -    env->cpuid_kvm_features = def->kvm_features;
> -    {
> -        const char *model_id = def->model_id;
> -        int c, len, i;
> -        if (!model_id)
> -            model_id = "";
> -        len = strlen(model_id);
> -        for(i = 0; i < 48; i++) {
> -            if (i >= len)
> -                c = '\0';
> -            else
> -                c = (uint8_t)model_id[i];
> -            env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
> -        }
> -    }
> -    return 0;
> -}
> -
>  /* NOTE: must be called outside the CPU execute loop */
>  void cpu_reset(CPUX86State *env)
>  {
> @@ -1626,249 +1090,6 @@ static void mce_init(CPUX86State *cenv)
>      }
>  }
>  
> -static void host_cpuid(uint32_t function, uint32_t count,
> -                       uint32_t *eax, uint32_t *ebx,
> -                       uint32_t *ecx, uint32_t *edx)
> -{
> -#if defined(CONFIG_KVM)
> -    uint32_t vec[4];
> -
> -#ifdef __x86_64__
> -    asm volatile("cpuid"
> -                 : "=a"(vec[0]), "=b"(vec[1]),
> -                   "=c"(vec[2]), "=d"(vec[3])
> -                 : "0"(function), "c"(count) : "cc");
> -#else
> -    asm volatile("pusha \n\t"
> -                 "cpuid \n\t"
> -                 "mov %%eax, 0(%2) \n\t"
> -                 "mov %%ebx, 4(%2) \n\t"
> -                 "mov %%ecx, 8(%2) \n\t"
> -                 "mov %%edx, 12(%2) \n\t"
> -                 "popa"
> -                 : : "a"(function), "c"(count), "S"(vec)
> -                 : "memory", "cc");
> -#endif
> -
> -    if (eax)
> -	*eax = vec[0];
> -    if (ebx)
> -	*ebx = vec[1];
> -    if (ecx)
> -	*ecx = vec[2];
> -    if (edx)
> -	*edx = vec[3];
> -#endif
> -}
> -
> -static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx,
> -                             uint32_t *ecx, uint32_t *edx)
> -{
> -    *ebx = env->cpuid_vendor1;
> -    *edx = env->cpuid_vendor2;
> -    *ecx = env->cpuid_vendor3;
> -
> -    /* sysenter isn't supported on compatibility mode on AMD, syscall
> -     * isn't supported in compatibility mode on Intel.
> -     * Normally we advertise the actual cpu vendor, but you can override
> -     * this if you want to use KVM's sysenter/syscall emulation
> -     * in compatibility mode and when doing cross vendor migration
> -     */
> -    if (kvm_enabled() && env->cpuid_vendor_override) {
> -        host_cpuid(0, 0, NULL, ebx, ecx, edx);
> -    }
> -}
> -
> -void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
> -                   uint32_t *eax, uint32_t *ebx,
> -                   uint32_t *ecx, uint32_t *edx)
> -{
> -    /* test if maximum index reached */
> -    if (index & 0x80000000) {
> -        if (index > env->cpuid_xlevel)
> -            index = env->cpuid_level;
> -    } else {
> -        if (index > env->cpuid_level)
> -            index = env->cpuid_level;
> -    }
> -
> -    switch(index) {
> -    case 0:
> -        *eax = env->cpuid_level;
> -        get_cpuid_vendor(env, ebx, ecx, edx);
> -        break;
> -    case 1:
> -        *eax = env->cpuid_version;
> -        *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
> -        *ecx = env->cpuid_ext_features;
> -        *edx = env->cpuid_features;
> -        if (env->nr_cores * env->nr_threads > 1) {
> -            *ebx |= (env->nr_cores * env->nr_threads) << 16;
> -            *edx |= 1 << 28;    /* HTT bit */
> -        }
> -        break;
> -    case 2:
> -        /* cache info: needed for Pentium Pro compatibility */
> -        *eax = 1;
> -        *ebx = 0;
> -        *ecx = 0;
> -        *edx = 0x2c307d;
> -        break;
> -    case 4:
> -        /* cache info: needed for Core compatibility */
> -        if (env->nr_cores > 1) {
> -        	*eax = (env->nr_cores - 1) << 26;
> -        } else {
> -        	*eax = 0;
> -        }
> -        switch (count) {
> -            case 0: /* L1 dcache info */
> -                *eax |= 0x0000121;
> -                *ebx = 0x1c0003f;
> -                *ecx = 0x000003f;
> -                *edx = 0x0000001;
> -                break;
> -            case 1: /* L1 icache info */
> -                *eax |= 0x0000122;
> -                *ebx = 0x1c0003f;
> -                *ecx = 0x000003f;
> -                *edx = 0x0000001;
> -                break;
> -            case 2: /* L2 cache info */
> -                *eax |= 0x0000143;
> -                if (env->nr_threads > 1) {
> -                    *eax |= (env->nr_threads - 1) << 14;
> -                }
> -                *ebx = 0x3c0003f;
> -                *ecx = 0x0000fff;
> -                *edx = 0x0000001;
> -                break;
> -            default: /* end of info */
> -                *eax = 0;
> -                *ebx = 0;
> -                *ecx = 0;
> -                *edx = 0;
> -                break;
> -        }
> -        break;
> -    case 5:
> -        /* mwait info: needed for Core compatibility */
> -        *eax = 0; /* Smallest monitor-line size in bytes */
> -        *ebx = 0; /* Largest monitor-line size in bytes */
> -        *ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
> -        *edx = 0;
> -        break;
> -    case 6:
> -        /* Thermal and Power Leaf */
> -        *eax = 0;
> -        *ebx = 0;
> -        *ecx = 0;
> -        *edx = 0;
> -        break;
> -    case 9:
> -        /* Direct Cache Access Information Leaf */
> -        *eax = 0; /* Bits 0-31 in DCA_CAP MSR */
> -        *ebx = 0;
> -        *ecx = 0;
> -        *edx = 0;
> -        break;
> -    case 0xA:
> -        /* Architectural Performance Monitoring Leaf */
> -        *eax = 0;
> -        *ebx = 0;
> -        *ecx = 0;
> -        *edx = 0;
> -        break;
> -    case 0x80000000:
> -        *eax = env->cpuid_xlevel;
> -        *ebx = env->cpuid_vendor1;
> -        *edx = env->cpuid_vendor2;
> -        *ecx = env->cpuid_vendor3;
> -        break;
> -    case 0x80000001:
> -        *eax = env->cpuid_version;
> -        *ebx = 0;
> -        *ecx = env->cpuid_ext3_features;
> -        *edx = env->cpuid_ext2_features;
> -
> -        /* The Linux kernel checks for the CMPLegacy bit and
> -         * discards multiple thread information if it is set.
> -         * So dont set it here for Intel to make Linux guests happy.
> -         */
> -        if (env->nr_cores * env->nr_threads > 1) {
> -            uint32_t tebx, tecx, tedx;
> -            get_cpuid_vendor(env, &tebx, &tecx, &tedx);
> -            if (tebx != CPUID_VENDOR_INTEL_1 ||
> -                tedx != CPUID_VENDOR_INTEL_2 ||
> -                tecx != CPUID_VENDOR_INTEL_3) {
> -                *ecx |= 1 << 1;    /* CmpLegacy bit */
> -            }
> -        }
> -
> -        if (kvm_enabled()) {
> -            /* Nested SVM not yet supported in upstream QEMU */
> -            *ecx &= ~CPUID_EXT3_SVM;
> -        }
> -        break;
> -    case 0x80000002:
> -    case 0x80000003:
> -    case 0x80000004:
> -        *eax = env->cpuid_model[(index - 0x80000002) * 4 + 0];
> -        *ebx = env->cpuid_model[(index - 0x80000002) * 4 + 1];
> -        *ecx = env->cpuid_model[(index - 0x80000002) * 4 + 2];
> -        *edx = env->cpuid_model[(index - 0x80000002) * 4 + 3];
> -        break;
> -    case 0x80000005:
> -        /* cache info (L1 cache) */
> -        *eax = 0x01ff01ff;
> -        *ebx = 0x01ff01ff;
> -        *ecx = 0x40020140;
> -        *edx = 0x40020140;
> -        break;
> -    case 0x80000006:
> -        /* cache info (L2 cache) */
> -        *eax = 0;
> -        *ebx = 0x42004200;
> -        *ecx = 0x02008140;
> -        *edx = 0;
> -        break;
> -    case 0x80000008:
> -        /* virtual & phys address size in low 2 bytes. */
> -/* XXX: This value must match the one used in the MMU code. */ 
> -        if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
> -            /* 64 bit processor */
> -/* XXX: The physical address space is limited to 42 bits in exec.c. */
> -            *eax = 0x00003028;	/* 48 bits virtual, 40 bits physical */
> -        } else {
> -            if (env->cpuid_features & CPUID_PSE36)
> -                *eax = 0x00000024; /* 36 bits physical */
> -            else
> -                *eax = 0x00000020; /* 32 bits physical */
> -        }
> -        *ebx = 0;
> -        *ecx = 0;
> -        *edx = 0;
> -        if (env->nr_cores * env->nr_threads > 1) {
> -            *ecx |= (env->nr_cores * env->nr_threads) - 1;
> -        }
> -        break;
> -    case 0x8000000A:
> -        *eax = 0x00000001; /* SVM Revision */
> -        *ebx = 0x00000010; /* nr of ASIDs */
> -        *ecx = 0;
> -        *edx = 0; /* optional features */
> -        break;
> -    default:
> -        /* reserved values: zero */
> -        *eax = 0;
> -        *ebx = 0;
> -        *ecx = 0;
> -        *edx = 0;
> -        break;
> -    }
> -}
> -
> -
>  int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
>                              target_ulong *base, unsigned int *limit,
>                              unsigned int *flags)
> -- 
> 1.6.4
> 
> 
> 
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 02/13] cpuid: replace magic number with named constant
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 02/13] cpuid: replace magic number with named constant Andre Przywara
@ 2010-03-06 18:25   ` Aurelien Jarno
  0 siblings, 0 replies; 18+ messages in thread
From: Aurelien Jarno @ 2010-03-06 18:25 UTC (permalink / raw)
  To: Andre Przywara; +Cc: john.cooper, qemu-devel

On Tue, Feb 02, 2010 at 11:08:10AM +0100, Andre Przywara wrote:
> CPUID leaf Fn8000_0001.EDX contains a copy of many Fn0000_0001.EDX bits.
> Define a name for the mask to improve readability and avoid typos.
> 
> Signed-off-by: Andre Przywara <andre.przywara@amd.com>

Acked-by: Aurelien Jarno <aurelien@aurel32.net>

> ---
>  target-i386/cpuid.c |   11 ++++++-----
>  1 files changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
> index aaa14ba..0a17020 100644
> --- a/target-i386/cpuid.c
> +++ b/target-i386/cpuid.c
> @@ -130,6 +130,7 @@ typedef struct x86_def_t {
>            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 EXT2_FEATURE_MASK 0x0183F3FF
>  static x86_def_t x86_defs[] = {
>  #ifdef TARGET_X86_64
>      {
> @@ -147,7 +148,7 @@ static x86_def_t x86_defs[] = {
>          /* this feature is needed for Solaris and isn't fully implemented */
>              CPUID_PSE36,
>          .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT,
> -        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | 
> +        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_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,
> @@ -170,7 +171,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 & EXT2_FEATURE_MASK) | 
>              CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
>              CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
>              CPUID_EXT2_FFXSR,
> @@ -220,7 +221,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 & EXT2_FEATURE_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,
> @@ -308,7 +309,7 @@ static x86_def_t x86_defs[] = {
>          .stepping = 3,
>          .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME |
>                      CPUID_MTRR | CPUID_MCA,
> -        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | CPUID_EXT2_MMXEXT |
> +        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | CPUID_EXT2_MMXEXT |
>                            CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
>          .xlevel = 0x80000008,
>          /* XXX: put another string ? */
> @@ -330,7 +331,7 @@ 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 & EXT2_FEATURE_MASK) | CPUID_EXT2_NX,
>          /* Missing: .ext3_features = CPUID_EXT3_LAHF_LM */
>          .xlevel = 0x8000000A,
>          .model_id = "Intel(R) Atom(TM) CPU N270   @ 1.60GHz",
> -- 
> 1.6.4
> 
> 
> 
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 03/13] cpuid: moved host_cpuid function and remove prototype
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 03/13] cpuid: moved host_cpuid function and remove prototype Andre Przywara
@ 2010-03-06 18:26   ` Aurelien Jarno
  0 siblings, 0 replies; 18+ messages in thread
From: Aurelien Jarno @ 2010-03-06 18:26 UTC (permalink / raw)
  To: Andre Przywara; +Cc: john.cooper, qemu-devel

On Tue, Feb 02, 2010 at 11:08:11AM +0100, Andre Przywara wrote:
> the host_cpuid function was located at the end of the file and had
> a prototype before it's first use. Move it up and remove the
> prototype.
> 
> Signed-off-by: Andre Przywara <andre.przywara@amd.com>

Acked-by: Aurelien Jarno <aurelien@aurel32.net>

> ---
>  target-i386/cpuid.c |   70 ++++++++++++++++++++++++--------------------------
>  1 files changed, 34 insertions(+), 36 deletions(-)
> 
> diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
> index 0a17020..cc080f4 100644
> --- a/target-i386/cpuid.c
> +++ b/target-i386/cpuid.c
> @@ -338,8 +338,40 @@ static x86_def_t x86_defs[] = {
>      },
>  };
>  
> -static void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax,
> -                               uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
> +static void host_cpuid(uint32_t function, uint32_t count,
> +                       uint32_t *eax, uint32_t *ebx,
> +                       uint32_t *ecx, uint32_t *edx)
> +{
> +#if defined(CONFIG_KVM)
> +    uint32_t vec[4];
> +
> +#ifdef __x86_64__
> +    asm volatile("cpuid"
> +                 : "=a"(vec[0]), "=b"(vec[1]),
> +                   "=c"(vec[2]), "=d"(vec[3])
> +                 : "0"(function), "c"(count) : "cc");
> +#else
> +    asm volatile("pusha \n\t"
> +                 "cpuid \n\t"
> +                 "mov %%eax, 0(%2) \n\t"
> +                 "mov %%ebx, 4(%2) \n\t"
> +                 "mov %%ecx, 8(%2) \n\t"
> +                 "mov %%edx, 12(%2) \n\t"
> +                 "popa"
> +                 : : "a"(function), "c"(count), "S"(vec)
> +                 : "memory", "cc");
> +#endif
> +
> +    if (eax)
> +	*eax = vec[0];
> +    if (ebx)
> +	*ebx = vec[1];
> +    if (ecx)
> +	*ecx = vec[2];
> +    if (edx)
> +	*edx = vec[3];
> +#endif
> +}
>  
>  static int cpu_x86_fill_model_id(char *str)
>  {
> @@ -578,40 +610,6 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
>      return 0;
>  }
>  
> -static void host_cpuid(uint32_t function, uint32_t count,
> -                       uint32_t *eax, uint32_t *ebx,
> -                       uint32_t *ecx, uint32_t *edx)
> -{
> -#if defined(CONFIG_KVM)
> -    uint32_t vec[4];
> -
> -#ifdef __x86_64__
> -    asm volatile("cpuid"
> -                 : "=a"(vec[0]), "=b"(vec[1]),
> -                   "=c"(vec[2]), "=d"(vec[3])
> -                 : "0"(function), "c"(count) : "cc");
> -#else
> -    asm volatile("pusha \n\t"
> -                 "cpuid \n\t"
> -                 "mov %%eax, 0(%2) \n\t"
> -                 "mov %%ebx, 4(%2) \n\t"
> -                 "mov %%ecx, 8(%2) \n\t"
> -                 "mov %%edx, 12(%2) \n\t"
> -                 "popa"
> -                 : : "a"(function), "c"(count), "S"(vec)
> -                 : "memory", "cc");
> -#endif
> -
> -    if (eax)
> -	*eax = vec[0];
> -    if (ebx)
> -	*ebx = vec[1];
> -    if (ecx)
> -	*ecx = vec[2];
> -    if (edx)
> -	*edx = vec[3];
> -#endif
> -}
>  
>  static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx,
>                               uint32_t *ecx, uint32_t *edx)
> -- 
> 1.6.4
> 
> 
> 
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 05/13] cpuid: add missing CPUID feature flag names
  2010-02-02 10:08 ` [Qemu-devel] [PATCH 05/13] cpuid: add missing CPUID feature flag names Andre Przywara
@ 2010-03-06 18:26   ` Aurelien Jarno
  0 siblings, 0 replies; 18+ messages in thread
From: Aurelien Jarno @ 2010-03-06 18:26 UTC (permalink / raw)
  To: Andre Przywara; +Cc: john.cooper, qemu-devel

On Tue, Feb 02, 2010 at 11:08:13AM +0100, Andre Przywara wrote:
> Some CPUID feature flags had no string value, so they could not be
> switched on or off from the command line.
> Add names for the missing ones mentioned in the current public CPUID
> specification from both Intel and AMD. Those only mentioned in the
> Linux kernel source I put as comments.
> 
> Signed-off-by: Andre Przywara <andre.przywara@amd.com>

Acked-by: Aurelien Jarno <aurelien@aurel32.net>

> ---
>  target-i386/cpuid.c |   15 ++++++++-------
>  1 files changed, 8 insertions(+), 7 deletions(-)
> 
> diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
> index 0238718..19d58e1 100644
> --- a/target-i386/cpuid.c
> +++ b/target-i386/cpuid.c
> @@ -52,11 +52,11 @@ static const char *feature_name[] = {
>      "fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe",
>  };
>  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, NULL, NULL, NULL, NULL, NULL, "hypervisor",
> +    "pni" /* Intel,AMD sse3 */, "pclmuldq", "dtes64", "monitor",
> +        "ds_cpl", "vmx", "smx", "est",
> +    "tm2", "ssse3", "cid", NULL, NULL /* FMA */, "cx16", "xtpr", "pdcm",
> +    NULL, NULL, "dca", "sse4_1", "sse4_2", "x2apic", "movbe", "popcnt",
> +    NULL, "aes", "xsave", "osxsave", NULL /* AVX */, NULL, NULL, "hypervisor",
>  };
>  static const char *ext2_feature_name[] = {
>      "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
> @@ -71,8 +71,9 @@ static const char *ext3_feature_name[] = {
>      "lahf_lm" /* AMD LahfSahf */, "cmp_legacy",
>          "svm", "extapic" /* AMD ExtApicSpace */,
>          "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
> -    "3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL,
> -    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> +    "3dnowprefetch", "osvw", "ibs", NULL /* SSE-5 */,
> +        "skinit", "wdt", NULL, NULL,
> +    NULL, NULL, NULL, "nodeid_msr", NULL, NULL, NULL, NULL,
>      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
>  };
>  
> -- 
> 1.6.4
> 
> 
> 
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

end of thread, other threads:[~2010-03-06 18:26 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-02-02 10:08 [Qemu-devel] [PATCH 00/13] i386 cpuid: cleanup and fixes Andre Przywara
2010-02-02 10:08 ` [Qemu-devel] [PATCH 01/13] cpuid: move CPUID functions into separate file Andre Przywara
2010-03-06 18:25   ` Aurelien Jarno
2010-02-02 10:08 ` [Qemu-devel] [PATCH 02/13] cpuid: replace magic number with named constant Andre Przywara
2010-03-06 18:25   ` Aurelien Jarno
2010-02-02 10:08 ` [Qemu-devel] [PATCH 03/13] cpuid: moved host_cpuid function and remove prototype Andre Przywara
2010-03-06 18:26   ` Aurelien Jarno
2010-02-02 10:08 ` [Qemu-devel] [PATCH 04/13] cpuid: Replace strtok with get_opt_name Andre Przywara
2010-02-02 10:08 ` [Qemu-devel] [PATCH 05/13] cpuid: add missing CPUID feature flag names Andre Przywara
2010-03-06 18:26   ` Aurelien Jarno
2010-02-02 10:08 ` [Qemu-devel] [PATCH 06/13] cpuid: list all known x86 CPUID feature flags Andre Przywara
2010-02-02 10:08 ` [Qemu-devel] [PATCH 07/13] cpuid: remove unnecessary kvm_trim function Andre Przywara
2010-02-02 10:08 ` [Qemu-devel] [PATCH 08/13] cpuid: simplify CPUID flag search function Andre Przywara
2010-02-02 10:08 ` [Qemu-devel] [PATCH 09/13] cpuid: propagate further CPUID leafs when -cpu host Andre Przywara
2010-02-02 10:08 ` [Qemu-devel] [PATCH 10/13] cpuid: add TCG feature bit trimming Andre Przywara
2010-02-02 10:08 ` [Qemu-devel] [PATCH 11/13] cpuid: Always expose 32 and 64-bit CPUs Andre Przywara
2010-02-02 10:08 ` [Qemu-devel] [PATCH 12/13] cpuid: Add kvm32 CPU model Andre Przywara
2010-02-02 10:08 ` [Qemu-devel] [PATCH 13/13] cpuid: fix CPUID levels Andre Przywara

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.