All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes
@ 2010-03-11 13:38 Andre Przywara
  2010-03-11 13:38 ` [Qemu-devel] [PATCH 01/13] x86/cpuid: move CPUID functions into separate file Andre Przywara
                   ` (13 more replies)
  0 siblings, 14 replies; 16+ messages in thread
From: Andre Przywara @ 2010-03-11 13:38 UTC (permalink / raw)
  To: anthony; +Cc: qemu-devel, aurelien

Hi,

a rebased and refined version of my CPUID cleanup series. This should
now apply on top of git head. Compared to the last post this leaves
out the bits already done by John Cooper's patch. Also I added a separate
patch to deal with an accidently removed line (patch 3/13).

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.
Additionally the rest of the patches beautifies or simplifies some code.
Feature additions are:
 5/13: add missing CPUID feature bit names (updated)
 8/13: -cpu host propagates more CPUID leafs, so that the cache topology
       will be visibile in the guest
 9/13: add CPUID feature bit trimming for TCG: Features not supported by
       the emulator will be masked out.
10/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 9/13.
11/13: add kvm32 CPU model: Per popular request add a counterpart to kvm64
       describing a basic hardware virtualization capable CPU for migration
       purposes.
13/13: Set the feature bits of qemu{32,64} to the set supported by TCG.

The last patch is actually debatable, as it changes the default CPUID bits
seen by guest. On the other hand it is only consequent to do so, as
qemu{32,64} are meant to be artifical CPUs.

More details in the commit messages.

Please review, comment and apply.

Regards,
Andre.

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

* [Qemu-devel] [PATCH 01/13] x86/cpuid: move CPUID functions into separate file
  2010-03-11 13:38 [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Andre Przywara
@ 2010-03-11 13:38 ` Andre Przywara
  2010-03-11 13:38 ` [Qemu-devel] [PATCH 02/13] x86/cpuid: replace magic number with named constant Andre Przywara
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Andre Przywara @ 2010-03-11 13:38 UTC (permalink / raw)
  To: anthony; +Cc: Andre Przywara, qemu-devel, aurelien

about half 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    |    9 +-
 target-i386/cpuid.c  | 1137 ++++++++++++++++++++++++++++++++++++++++++++++++++
 target-i386/helper.c | 1112 ------------------------------------------------
 4 files changed, 1146 insertions(+), 1115 deletions(-)
 create mode 100644 target-i386/cpuid.c

diff --git a/Makefile.target b/Makefile.target
index 320f807..eb54d75 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
 
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index ef7d951..c540213 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -822,14 +822,17 @@ void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32);
 int cpu_x86_signal_handler(int host_signum, void *pinfo,
                            void *puc);
 
+/* 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);
+
 /* helper.c */
 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);
-void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
-                   uint32_t *eax, uint32_t *ebx,
-                   uint32_t *ecx, uint32_t *edx);
 
 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..ca1aedd
--- /dev/null
+++ b/target-i386/cpuid.c
@@ -0,0 +1,1137 @@
+/*
+ *  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"
+
+#include "qemu-option.h"
+#include "qemu-config.h"
+
+/* feature flags taken from "Intel Processor Identification and the CPUID
+ * Instruction" and AMD's "CPUID Specification".  In cases of disagreement
+ * between feature naming conventions, aliases may be added.
+ */
+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|sse3" /* Intel,AMD sse3 */, NULL, NULL, "monitor",
+    "ds_cpl", "vmx", NULL /* Linux smx */, "est",
+    "tm2", "ssse3", "cid", NULL,
+    NULL, "cx16", "xtpr", NULL,
+    NULL, NULL, "dca", "sse4.1|sse4_1",
+    "sse4.2|sse4_2", "x2apic", 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,
+};
+
+/* collects per-function cpuid data
+ */
+typedef struct model_features_t {
+    uint32_t *guest_feat;
+    uint32_t *host_feat;
+    uint32_t check_feat;
+    const char **flag_names;
+    uint32_t cpuid;
+    } model_features_t;
+
+int check_cpuid = 0;
+int enforce_cpuid = 0;
+
+static void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax,
+                       uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
+
+#define iswhite(c) ((c) && ((c) <= ' ' || '~' < (c)))
+
+/* general substring compare of *[s1..e1) and *[s2..e2).  sx is start of
+ * a substring.  ex if !NULL points to the first char after a substring,
+ * otherwise the string is assumed to sized by a terminating nul.
+ * Return lexical ordering of *s1:*s2.
+ */
+static int sstrcmp(const char *s1, const char *e1, const char *s2,
+    const char *e2)
+{
+    for (;;) {
+        if (!*s1 || !*s2 || *s1 != *s2)
+            return (*s1 - *s2);
+        ++s1, ++s2;
+        if (s1 == e1 && s2 == e2)
+            return (0);
+        else if (s1 == e1)
+            return (*s2);
+        else if (s2 == e2)
+            return (*s1);
+    }
+}
+
+/* compare *[s..e) to *altstr.  *altstr may be a simple string or multiple
+ * '|' delimited (possibly empty) strings in which case search for a match
+ * within the alternatives proceeds left to right.  Return 0 for success,
+ * non-zero otherwise.
+ */
+static int altcmp(const char *s, const char *e, const char *altstr)
+{
+    const char *p, *q;
+
+    for (q = p = altstr; ; ) {
+        while (*p && *p != '|')
+            ++p;
+        if ((q == p && !*s) || (q != p && !sstrcmp(s, e, q, p)))
+            return (0);
+        if (!*p)
+            return (1);
+        else
+            q = ++p;
+    }
+}
+
+/* search featureset for flag *[s..e), if found set corresponding bit in
+ * *pval and return success, otherwise return zero
+ */
+static int lookup_feature(uint32_t *pval, const char *s, const char *e,
+    const char **featureset)
+{
+    uint32_t mask;
+    const char **ppc;
+
+    for (mask = 1, ppc = featureset; mask; mask <<= 1, ++ppc)
+        if (*ppc && !altcmp(s, e, *ppc)) {
+            *pval |= mask;
+            break;
+        }
+    return (mask ? 1 : 0);
+}
+
+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)
+{
+    if (!lookup_feature(features, flagname, NULL, feature_name) &&
+        !lookup_feature(ext_features, flagname, NULL, ext_feature_name) &&
+        !lookup_feature(ext2_features, flagname, NULL, ext2_feature_name) &&
+        !lookup_feature(ext3_features, flagname, NULL, ext3_feature_name) &&
+        !lookup_feature(kvm_features, flagname, NULL, kvm_feature_name))
+            fprintf(stderr, "CPU feature %s not found\n", flagname);
+}
+
+typedef struct x86_def_t {
+    struct x86_def_t *next;
+    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;
+    uint32_t flags;
+} 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)
+
+/* maintains list of cpu model definitions
+ */
+static x86_def_t *x86_defs = {NULL};
+
+/* built-in cpu model definitions (deprecated)
+ */
+static x86_def_t builtin_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 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 unavailable_host_feature(struct model_features_t *f, uint32_t mask)
+{
+    int i;
+
+    for (i = 0; i < 32; ++i)
+        if (1 << i & mask) {
+            fprintf(stderr, "warning: host cpuid %04x_%04x lacks requested"
+                " flag '%s' [0x%08x]\n",
+                f->cpuid >> 16, f->cpuid & 0xffff,
+                f->flag_names[i] ? f->flag_names[i] : "[reserved]", mask);
+            break;
+        }
+    return 0;
+}
+
+/* best effort attempt to inform user requested cpu flags aren't making
+ * their way to the guest.  Note: ft[].check_feat ideally should be
+ * specified via a guest_def field to suppress report of extraneous flags.
+ */
+static int check_features_against_host(x86_def_t *guest_def)
+{
+    x86_def_t host_def;
+    uint32_t mask;
+    int rv, i;
+    struct model_features_t ft[] = {
+        {&guest_def->features, &host_def.features,
+            ~0, feature_name, 0x00000000},
+        {&guest_def->ext_features, &host_def.ext_features,
+            ~CPUID_EXT_HYPERVISOR, ext_feature_name, 0x00000001},
+        {&guest_def->ext2_features, &host_def.ext2_features,
+            ~PPRO_FEATURES, ext2_feature_name, 0x80000000},
+        {&guest_def->ext3_features, &host_def.ext3_features,
+            ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001}};
+
+    cpu_x86_fill_host(&host_def);
+    for (rv = 0, i = 0; i < sizeof (ft) / sizeof (ft[0]); ++i)
+        for (mask = 1; mask; mask <<= 1)
+            if (ft[i].check_feat & mask && *ft[i].guest_feat & mask &&
+                !(*ft[i].host_feat & mask)) {
+                    unavailable_host_feature(&ft[i], mask);
+                    rv = 1;
+                }
+    return rv;
+}
+
+static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
+{
+    unsigned int i;
+    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;
+
+    for (def = x86_defs; def; def = def->next)
+        if (!strcmp(name, def->name))
+            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 if (!strcmp(featurestr, "check")) {
+            check_cpuid = 1;
+        } else if (!strcmp(featurestr, "enforce")) {
+            check_cpuid = enforce_cpuid = 1;
+        } 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;
+    if (check_cpuid) {
+        if (check_features_against_host(x86_cpu_def) && enforce_cpuid)
+            goto error;
+    }
+    free(s);
+    return 0;
+
+error:
+    free(s);
+    return -1;
+}
+
+/* generate a composite string into buf of all cpuid names in featureset
+ * selected by fbits.  indicate truncation at bufsize in the event of overflow.
+ * if flags, suppress names undefined in featureset.
+ */
+static void listflags(char *buf, int bufsize, uint32_t fbits,
+    const char **featureset, uint32_t flags)
+{
+    const char **p = &featureset[31];
+    char *q, *b, bit;
+    int nc;
+
+    b = 4 <= bufsize ? buf + (bufsize -= 3) - 1 : NULL;
+    *buf = '\0';
+    for (q = buf, bit = 31; fbits && bufsize; --p, fbits &= ~(1 << bit), --bit)
+        if (fbits & 1 << bit && (*p || !flags)) {
+            if (*p)
+                nc = snprintf(q, bufsize, "%s%s", q == buf ? "" : " ", *p);
+            else
+                nc = snprintf(q, bufsize, "%s[%d]", q == buf ? "" : " ", bit);
+            if (bufsize <= nc) {
+                if (b) {
+                    memcpy(b, "...", sizeof("..."));
+                }
+                return;
+            }
+            q += nc;
+            bufsize -= nc;
+        }
+}
+
+/* generate CPU information:
+ * -?        list model names
+ * -?model   list model names/IDs
+ * -?dump    output all model (x86_def_t) data
+ * -?cpuid   list all recognized cpuid flag names
+ */ 
+void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+                  const char *optarg)
+{
+    unsigned char model = !strcmp("?model", optarg);
+    unsigned char dump = !strcmp("?dump", optarg);
+    unsigned char cpuid = !strcmp("?cpuid", optarg);
+    x86_def_t *def;
+    char buf[256];
+
+    if (cpuid) {
+        (*cpu_fprintf)(f, "Recognized CPUID flags:\n");
+        listflags(buf, sizeof (buf), (uint32_t)~0, feature_name, 1);
+        (*cpu_fprintf)(f, "  f_edx: %s\n", buf);
+        listflags(buf, sizeof (buf), (uint32_t)~0, ext_feature_name, 1);
+        (*cpu_fprintf)(f, "  f_ecx: %s\n", buf);
+        listflags(buf, sizeof (buf), (uint32_t)~0, ext2_feature_name, 1);
+        (*cpu_fprintf)(f, "  extf_edx: %s\n", buf);
+        listflags(buf, sizeof (buf), (uint32_t)~0, ext3_feature_name, 1);
+        (*cpu_fprintf)(f, "  extf_ecx: %s\n", buf);
+        return;
+    }
+    for (def = x86_defs; def; def = def->next) {
+        snprintf(buf, sizeof (buf), def->flags ? "[%s]": "%s", def->name);
+        if (model || dump) {
+            (*cpu_fprintf)(f, "x86 %16s  %-48s\n", buf, def->model_id);
+        } else {
+            (*cpu_fprintf)(f, "x86 %16s\n", buf);
+        }
+        if (dump) {
+            memcpy(buf, &def->vendor1, sizeof (def->vendor1));
+            memcpy(buf + 4, &def->vendor2, sizeof (def->vendor2));
+            memcpy(buf + 8, &def->vendor3, sizeof (def->vendor3));
+            buf[12] = '\0';
+            (*cpu_fprintf)(f,
+                "  family %d model %d stepping %d level %d xlevel 0x%x"
+                " vendor \"%s\"\n",
+                def->family, def->model, def->stepping, def->level,
+                def->xlevel, buf);
+            listflags(buf, sizeof (buf), def->features, feature_name, 0);
+            (*cpu_fprintf)(f, "  feature_edx %08x (%s)\n", def->features,
+                buf);
+            listflags(buf, sizeof (buf), def->ext_features, ext_feature_name,
+                0);
+            (*cpu_fprintf)(f, "  feature_ecx %08x (%s)\n", def->ext_features,
+                buf);
+            listflags(buf, sizeof (buf), def->ext2_features, ext2_feature_name,
+                0);
+            (*cpu_fprintf)(f, "  extfeature_edx %08x (%s)\n",
+                def->ext2_features, buf);
+            listflags(buf, sizeof (buf), def->ext3_features, ext3_feature_name,
+                0);
+            (*cpu_fprintf)(f, "  extfeature_ecx %08x (%s)\n",
+                def->ext3_features, buf);
+            (*cpu_fprintf)(f, "\n");
+        }
+    }
+}
+
+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;
+}
+
+#if !defined(CONFIG_USER_ONLY)
+/* copy vendor id string to 32 bit register, nul pad as needed
+ */
+static void cpyid(const char *s, uint32_t *id)
+{
+    char *d = (char *)id;
+    char i;
+
+    for (i = sizeof (*id); i--; )
+        *d++ = *s ? *s++ : '\0';
+}
+
+/* interpret radix and convert from string to arbitrary scalar,
+ * otherwise flag failure
+ */
+#define setscalar(pval, str, perr)                      \
+{                                                       \
+    char *pend;                                         \
+    unsigned long ul;                                   \
+                                                        \
+    ul = strtoul(str, &pend, 0);                        \
+    *str && !*pend ? (*pval = ul) : (*perr = 1);        \
+}
+
+/* map cpuid options to feature bits, otherwise return failure
+ * (option tags in *str are delimited by whitespace)
+ */
+static void setfeatures(uint32_t *pval, const char *str,
+    const char **featureset, int *perr)
+{
+    const char *p, *q;
+
+    for (q = p = str; *p || *q; q = p) {
+        while (iswhite(*p))
+            q = ++p; 
+        while (*p && !iswhite(*p))
+            ++p;
+        if (!*q && !*p)
+            return;
+        if (!lookup_feature(pval, q, p, featureset)) {
+            fprintf(stderr, "error: feature \"%.*s\" not available in set\n",
+                (int)(p - q), q);
+            *perr = 1;
+            return;
+        }
+    }
+}
+
+/* map config file options to x86_def_t form
+ */
+static int cpudef_setfield(const char *name, const char *str, void *opaque)
+{
+    x86_def_t *def = opaque;
+    int err = 0;
+
+    if (!strcmp(name, "name")) {
+        def->name = strdup(str);
+    } else if (!strcmp(name, "model_id")) {
+        strncpy(def->model_id, str, sizeof (def->model_id));
+    } else if (!strcmp(name, "level")) {
+        setscalar(&def->level, str, &err)
+    } else if (!strcmp(name, "vendor")) {
+        cpyid(&str[0], &def->vendor1);
+        cpyid(&str[4], &def->vendor2);
+        cpyid(&str[8], &def->vendor3);
+    } else if (!strcmp(name, "family")) {
+        setscalar(&def->family, str, &err)
+    } else if (!strcmp(name, "model")) {
+        setscalar(&def->model, str, &err)
+    } else if (!strcmp(name, "stepping")) {
+        setscalar(&def->stepping, str, &err)
+    } else if (!strcmp(name, "feature_edx")) {
+        setfeatures(&def->features, str, feature_name, &err);
+    } else if (!strcmp(name, "feature_ecx")) {
+        setfeatures(&def->ext_features, str, ext_feature_name, &err);
+    } else if (!strcmp(name, "extfeature_edx")) {
+        setfeatures(&def->ext2_features, str, ext2_feature_name, &err);
+    } else if (!strcmp(name, "extfeature_ecx")) {
+        setfeatures(&def->ext3_features, str, ext3_feature_name, &err);
+    } else if (!strcmp(name, "xlevel")) {
+        setscalar(&def->xlevel, str, &err)
+    } else {
+        fprintf(stderr, "error: unknown option [%s = %s]\n", name, str);
+        return (1);
+    }
+    if (err) {
+        fprintf(stderr, "error: bad option value [%s = %s]\n", name, str);
+        return (1);
+    }
+    return (0);
+}
+
+/* register config file entry as x86_def_t
+ */
+static int cpudef_register(QemuOpts *opts, void *opaque)
+{
+    x86_def_t *def = qemu_mallocz(sizeof (x86_def_t));
+
+    qemu_opt_foreach(opts, cpudef_setfield, def, 1);
+    def->next = x86_defs;
+    x86_defs = def;
+    return (0);
+}
+#endif /* !CONFIG_USER_ONLY */
+
+/* register "cpudef" models defined in configuration file.  Here we first
+ * preload any built-in definitions
+ */
+void x86_cpudef_setup(void)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) {
+        builtin_x86_defs[i].next = x86_defs;
+        builtin_x86_defs[i].flags = 1;
+        x86_defs = &builtin_x86_defs[i];
+    }
+#if !defined(CONFIG_USER_ONLY)
+    qemu_opts_foreach(&qemu_cpudef_opts, cpudef_register, NULL, 0);
+#endif
+}
+
+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;
+    }
+}
diff --git a/target-i386/helper.c b/target-i386/helper.c
index ce2b5eb..d85e059 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -29,875 +29,6 @@
 #include "kvm.h"
 
 //#define DEBUG_MMU
-#include "qemu-option.h"
-#include "qemu-config.h"
-
-/* feature flags taken from "Intel Processor Identification and the CPUID
- * Instruction" and AMD's "CPUID Specification".  In cases of disagreement
- * between feature naming conventions, aliases may be added.
- */
-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|sse3" /* Intel,AMD sse3 */, NULL, NULL, "monitor",
-    "ds_cpl", "vmx", NULL /* Linux smx */, "est",
-    "tm2", "ssse3", "cid", NULL,
-    NULL, "cx16", "xtpr", NULL,
-    NULL, NULL, "dca", "sse4.1|sse4_1",
-    "sse4.2|sse4_2", "x2apic", 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,
-};
-
-/* collects per-function cpuid data
- */
-typedef struct model_features_t {
-    uint32_t *guest_feat;
-    uint32_t *host_feat;
-    uint32_t check_feat;
-    const char **flag_names;
-    uint32_t cpuid;
-    } model_features_t;
-
-int check_cpuid = 0;
-int enforce_cpuid = 0;
-
-static void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax,
-                       uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
-
-#define iswhite(c) ((c) && ((c) <= ' ' || '~' < (c)))
-
-/* general substring compare of *[s1..e1) and *[s2..e2).  sx is start of
- * a substring.  ex if !NULL points to the first char after a substring,
- * otherwise the string is assumed to sized by a terminating nul.
- * Return lexical ordering of *s1:*s2.
- */
-static int sstrcmp(const char *s1, const char *e1, const char *s2,
-    const char *e2)
-{
-    for (;;) {
-        if (!*s1 || !*s2 || *s1 != *s2)
-            return (*s1 - *s2);
-        ++s1, ++s2;
-        if (s1 == e1 && s2 == e2)
-            return (0);
-        else if (s1 == e1)
-            return (*s2);
-        else if (s2 == e2)
-            return (*s1);
-    }
-}
-
-/* compare *[s..e) to *altstr.  *altstr may be a simple string or multiple
- * '|' delimited (possibly empty) strings in which case search for a match
- * within the alternatives proceeds left to right.  Return 0 for success,
- * non-zero otherwise.
- */
-static int altcmp(const char *s, const char *e, const char *altstr)
-{
-    const char *p, *q;
-
-    for (q = p = altstr; ; ) {
-        while (*p && *p != '|')
-            ++p;
-        if ((q == p && !*s) || (q != p && !sstrcmp(s, e, q, p)))
-            return (0);
-        if (!*p)
-            return (1);
-        else
-            q = ++p;
-    }
-}
-
-/* search featureset for flag *[s..e), if found set corresponding bit in
- * *pval and return success, otherwise return zero
- */
-static int lookup_feature(uint32_t *pval, const char *s, const char *e,
-    const char **featureset)
-{
-    uint32_t mask;
-    const char **ppc;
-
-    for (mask = 1, ppc = featureset; mask; mask <<= 1, ++ppc)
-        if (*ppc && !altcmp(s, e, *ppc)) {
-            *pval |= mask;
-            break;
-        }
-    return (mask ? 1 : 0);
-}
-
-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)
-{
-    if (!lookup_feature(features, flagname, NULL, feature_name) &&
-        !lookup_feature(ext_features, flagname, NULL, ext_feature_name) &&
-        !lookup_feature(ext2_features, flagname, NULL, ext2_feature_name) &&
-        !lookup_feature(ext3_features, flagname, NULL, ext3_feature_name) &&
-        !lookup_feature(kvm_features, flagname, NULL, kvm_feature_name))
-            fprintf(stderr, "CPU feature %s not found\n", flagname);
-}
-
-typedef struct x86_def_t {
-    struct x86_def_t *next;
-    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;
-    uint32_t flags;
-} 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)
-
-/* maintains list of cpu model definitions
- */
-static x86_def_t *x86_defs = {NULL};
-
-/* built-in cpu model definitions (deprecated)
- */
-static x86_def_t builtin_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 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 unavailable_host_feature(struct model_features_t *f, uint32_t mask)
-{
-    int i;
-
-    for (i = 0; i < 32; ++i)
-        if (1 << i & mask) {
-            fprintf(stderr, "warning: host cpuid %04x_%04x lacks requested"
-                " flag '%s' [0x%08x]\n",
-                f->cpuid >> 16, f->cpuid & 0xffff,
-                f->flag_names[i] ? f->flag_names[i] : "[reserved]", mask);
-            break;
-        }
-    return 0;
-}
-
-/* best effort attempt to inform user requested cpu flags aren't making
- * their way to the guest.  Note: ft[].check_feat ideally should be
- * specified via a guest_def field to suppress report of extraneous flags.
- */
-static int check_features_against_host(x86_def_t *guest_def)
-{
-    x86_def_t host_def;
-    uint32_t mask;
-    int rv, i;
-    struct model_features_t ft[] = {
-        {&guest_def->features, &host_def.features,
-            ~0, feature_name, 0x00000000},
-        {&guest_def->ext_features, &host_def.ext_features,
-            ~CPUID_EXT_HYPERVISOR, ext_feature_name, 0x00000001},
-        {&guest_def->ext2_features, &host_def.ext2_features,
-            ~PPRO_FEATURES, ext2_feature_name, 0x80000000},
-        {&guest_def->ext3_features, &host_def.ext3_features,
-            ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001}};
-
-    cpu_x86_fill_host(&host_def);
-    for (rv = 0, i = 0; i < sizeof (ft) / sizeof (ft[0]); ++i)
-        for (mask = 1; mask; mask <<= 1)
-            if (ft[i].check_feat & mask && *ft[i].guest_feat & mask &&
-                !(*ft[i].host_feat & mask)) {
-                    unavailable_host_feature(&ft[i], mask);
-                    rv = 1;
-                }
-    return rv;
-}
-
-static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
-{
-    unsigned int i;
-    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;
-
-    for (def = x86_defs; def; def = def->next)
-        if (!strcmp(name, def->name))
-            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 if (!strcmp(featurestr, "check")) {
-            check_cpuid = 1;
-        } else if (!strcmp(featurestr, "enforce")) {
-            check_cpuid = enforce_cpuid = 1;
-        } 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;
-    if (check_cpuid) {
-        if (check_features_against_host(x86_cpu_def) && enforce_cpuid)
-            goto error;
-    }
-    free(s);
-    return 0;
-
-error:
-    free(s);
-    return -1;
-}
-
-/* generate a composite string into buf of all cpuid names in featureset
- * selected by fbits.  indicate truncation at bufsize in the event of overflow.
- * if flags, suppress names undefined in featureset.
- */
-static void listflags(char *buf, int bufsize, uint32_t fbits,
-    const char **featureset, uint32_t flags)
-{
-    const char **p = &featureset[31];
-    char *q, *b, bit;
-    int nc;
-
-    b = 4 <= bufsize ? buf + (bufsize -= 3) - 1 : NULL;
-    *buf = '\0';
-    for (q = buf, bit = 31; fbits && bufsize; --p, fbits &= ~(1 << bit), --bit)
-        if (fbits & 1 << bit && (*p || !flags)) {
-            if (*p)
-                nc = snprintf(q, bufsize, "%s%s", q == buf ? "" : " ", *p);
-            else
-                nc = snprintf(q, bufsize, "%s[%d]", q == buf ? "" : " ", bit);
-            if (bufsize <= nc) {
-                if (b) {
-                    memcpy(b, "...", sizeof("..."));
-                }
-                return;
-            }
-            q += nc;
-            bufsize -= nc;
-        }
-}
-
-/* generate CPU information:
- * -?        list model names
- * -?model   list model names/IDs
- * -?dump    output all model (x86_def_t) data
- * -?cpuid   list all recognized cpuid flag names
- */ 
-void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
-                  const char *optarg)
-{
-    unsigned char model = !strcmp("?model", optarg);
-    unsigned char dump = !strcmp("?dump", optarg);
-    unsigned char cpuid = !strcmp("?cpuid", optarg);
-    x86_def_t *def;
-    char buf[256];
-
-    if (cpuid) {
-        (*cpu_fprintf)(f, "Recognized CPUID flags:\n");
-        listflags(buf, sizeof (buf), (uint32_t)~0, feature_name, 1);
-        (*cpu_fprintf)(f, "  f_edx: %s\n", buf);
-        listflags(buf, sizeof (buf), (uint32_t)~0, ext_feature_name, 1);
-        (*cpu_fprintf)(f, "  f_ecx: %s\n", buf);
-        listflags(buf, sizeof (buf), (uint32_t)~0, ext2_feature_name, 1);
-        (*cpu_fprintf)(f, "  extf_edx: %s\n", buf);
-        listflags(buf, sizeof (buf), (uint32_t)~0, ext3_feature_name, 1);
-        (*cpu_fprintf)(f, "  extf_ecx: %s\n", buf);
-        return;
-    }
-    for (def = x86_defs; def; def = def->next) {
-        snprintf(buf, sizeof (buf), def->flags ? "[%s]": "%s", def->name);
-        if (model || dump) {
-            (*cpu_fprintf)(f, "x86 %16s  %-48s\n", buf, def->model_id);
-        } else {
-            (*cpu_fprintf)(f, "x86 %16s\n", buf);
-        }
-        if (dump) {
-            memcpy(buf, &def->vendor1, sizeof (def->vendor1));
-            memcpy(buf + 4, &def->vendor2, sizeof (def->vendor2));
-            memcpy(buf + 8, &def->vendor3, sizeof (def->vendor3));
-            buf[12] = '\0';
-            (*cpu_fprintf)(f,
-                "  family %d model %d stepping %d level %d xlevel 0x%x"
-                " vendor \"%s\"\n",
-                def->family, def->model, def->stepping, def->level,
-                def->xlevel, buf);
-            listflags(buf, sizeof (buf), def->features, feature_name, 0);
-            (*cpu_fprintf)(f, "  feature_edx %08x (%s)\n", def->features,
-                buf);
-            listflags(buf, sizeof (buf), def->ext_features, ext_feature_name,
-                0);
-            (*cpu_fprintf)(f, "  feature_ecx %08x (%s)\n", def->ext_features,
-                buf);
-            listflags(buf, sizeof (buf), def->ext2_features, ext2_feature_name,
-                0);
-            (*cpu_fprintf)(f, "  extfeature_edx %08x (%s)\n",
-                def->ext2_features, buf);
-            listflags(buf, sizeof (buf), def->ext3_features, ext3_feature_name,
-                0);
-            (*cpu_fprintf)(f, "  extfeature_ecx %08x (%s)\n",
-                def->ext3_features, buf);
-            (*cpu_fprintf)(f, "\n");
-        }
-    }
-}
-
-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;
-}
-
-#if !defined(CONFIG_USER_ONLY)
-/* copy vendor id string to 32 bit register, nul pad as needed
- */
-static void cpyid(const char *s, uint32_t *id)
-{
-    char *d = (char *)id;
-    char i;
-
-    for (i = sizeof (*id); i--; )
-        *d++ = *s ? *s++ : '\0';
-}
-
-/* interpret radix and convert from string to arbitrary scalar,
- * otherwise flag failure
- */
-#define setscalar(pval, str, perr)                      \
-{                                                       \
-    char *pend;                                         \
-    unsigned long ul;                                   \
-                                                        \
-    ul = strtoul(str, &pend, 0);                        \
-    *str && !*pend ? (*pval = ul) : (*perr = 1);        \
-}
-
-/* map cpuid options to feature bits, otherwise return failure
- * (option tags in *str are delimited by whitespace)
- */
-static void setfeatures(uint32_t *pval, const char *str,
-    const char **featureset, int *perr)
-{
-    const char *p, *q;
-
-    for (q = p = str; *p || *q; q = p) {
-        while (iswhite(*p))
-            q = ++p; 
-        while (*p && !iswhite(*p))
-            ++p;
-        if (!*q && !*p)
-            return;
-        if (!lookup_feature(pval, q, p, featureset)) {
-            fprintf(stderr, "error: feature \"%.*s\" not available in set\n",
-                (int)(p - q), q);
-            *perr = 1;
-            return;
-        }
-    }
-}
-
-/* map config file options to x86_def_t form
- */
-static int cpudef_setfield(const char *name, const char *str, void *opaque)
-{
-    x86_def_t *def = opaque;
-    int err = 0;
-
-    if (!strcmp(name, "name")) {
-        def->name = strdup(str);
-    } else if (!strcmp(name, "model_id")) {
-        strncpy(def->model_id, str, sizeof (def->model_id));
-    } else if (!strcmp(name, "level")) {
-        setscalar(&def->level, str, &err)
-    } else if (!strcmp(name, "vendor")) {
-        cpyid(&str[0], &def->vendor1);
-        cpyid(&str[4], &def->vendor2);
-        cpyid(&str[8], &def->vendor3);
-    } else if (!strcmp(name, "family")) {
-        setscalar(&def->family, str, &err)
-    } else if (!strcmp(name, "model")) {
-        setscalar(&def->model, str, &err)
-    } else if (!strcmp(name, "stepping")) {
-        setscalar(&def->stepping, str, &err)
-    } else if (!strcmp(name, "feature_edx")) {
-        setfeatures(&def->features, str, feature_name, &err);
-    } else if (!strcmp(name, "feature_ecx")) {
-        setfeatures(&def->ext_features, str, ext_feature_name, &err);
-    } else if (!strcmp(name, "extfeature_edx")) {
-        setfeatures(&def->ext2_features, str, ext2_feature_name, &err);
-    } else if (!strcmp(name, "extfeature_ecx")) {
-        setfeatures(&def->ext3_features, str, ext3_feature_name, &err);
-    } else if (!strcmp(name, "xlevel")) {
-        setscalar(&def->xlevel, str, &err)
-    } else {
-        fprintf(stderr, "error: unknown option [%s = %s]\n", name, str);
-        return (1);
-    }
-    if (err) {
-        fprintf(stderr, "error: bad option value [%s = %s]\n", name, str);
-        return (1);
-    }
-    return (0);
-}
-
-/* register config file entry as x86_def_t
- */
-static int cpudef_register(QemuOpts *opts, void *opaque)
-{
-    x86_def_t *def = qemu_mallocz(sizeof (x86_def_t));
-
-    qemu_opt_foreach(opts, cpudef_setfield, def, 1);
-    def->next = x86_defs;
-    x86_defs = def;
-    return (0);
-}
-#endif /* !CONFIG_USER_ONLY */
-
-/* register "cpudef" models defined in configuration file.  Here we first
- * preload any built-in definitions
- */
-void x86_cpudef_setup(void)
-{
-    int i;
-
-    for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) {
-        builtin_x86_defs[i].next = x86_defs;
-        builtin_x86_defs[i].flags = 1;
-        x86_defs = &builtin_x86_defs[i];
-    }
-#if !defined(CONFIG_USER_ONLY)
-    qemu_opts_foreach(&qemu_cpudef_opts, cpudef_register, NULL, 0);
-#endif
-}
 
 /* NOTE: must be called outside the CPU execute loop */
 void cpu_reset(CPUX86State *env)
@@ -1959,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] 16+ messages in thread

* [Qemu-devel] [PATCH 02/13] x86/cpuid: replace magic number with named constant
  2010-03-11 13:38 [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Andre Przywara
  2010-03-11 13:38 ` [Qemu-devel] [PATCH 01/13] x86/cpuid: move CPUID functions into separate file Andre Przywara
@ 2010-03-11 13:38 ` Andre Przywara
  2010-03-11 13:38 ` [Qemu-devel] [PATCH 03/13] x86/cpuid: fix missing feature set bits Andre Przywara
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Andre Przywara @ 2010-03-11 13:38 UTC (permalink / raw)
  To: anthony; +Cc: Andre Przywara, qemu-devel, aurelien

CPUID leaf Fn8000_0001.EDX contains a copy of many Fn0000_0001.EDX bits.
Define a name for this 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 ca1aedd..5e4f057 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -196,6 +196,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
 
 /* maintains list of cpu model definitions
  */
@@ -220,7 +221,7 @@ static x86_def_t builtin_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,
@@ -243,7 +244,7 @@ static x86_def_t builtin_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,
@@ -293,7 +294,7 @@ static x86_def_t builtin_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,
@@ -380,7 +381,7 @@ static x86_def_t builtin_x86_defs[] = {
         .model = 2,
         .stepping = 3,
         .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA,
-        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
+        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
         .xlevel = 0x80000008,
         /* XXX: put another string ? */
         .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
@@ -401,7 +402,7 @@ static x86_def_t builtin_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] 16+ messages in thread

* [Qemu-devel] [PATCH 03/13] x86/cpuid: fix missing feature set bits
  2010-03-11 13:38 [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Andre Przywara
  2010-03-11 13:38 ` [Qemu-devel] [PATCH 01/13] x86/cpuid: move CPUID functions into separate file Andre Przywara
  2010-03-11 13:38 ` [Qemu-devel] [PATCH 02/13] x86/cpuid: replace magic number with named constant Andre Przywara
@ 2010-03-11 13:38 ` Andre Przywara
  2010-03-11 13:38 ` [Qemu-devel] [PATCH 04/13] x86/cpuid: moved host_cpuid function and remove prototype Andre Przywara
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Andre Przywara @ 2010-03-11 13:38 UTC (permalink / raw)
  To: anthony; +Cc: Andre Przywara, qemu-devel, aurelien

This one was accidently removed with commit
bb0300dc57c10b3721451b0ff566a03f9276cc77

Signed-off-by: Andre Przywara <andre.przywara@amd.com>

---
 target-i386/cpuid.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 5e4f057..1bceb4b 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -754,6 +754,7 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
     env->pat = 0x0007040600070406ULL;
     env->cpuid_ext_features = def->ext_features;
     env->cpuid_ext2_features = def->ext2_features;
+    env->cpuid_ext3_features = def->ext3_features;
     env->cpuid_xlevel = def->xlevel;
     env->cpuid_kvm_features = def->kvm_features;
     {
-- 
1.6.4

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

* [Qemu-devel] [PATCH 04/13] x86/cpuid: moved host_cpuid function and remove prototype
  2010-03-11 13:38 [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Andre Przywara
                   ` (2 preceding siblings ...)
  2010-03-11 13:38 ` [Qemu-devel] [PATCH 03/13] x86/cpuid: fix missing feature set bits Andre Przywara
@ 2010-03-11 13:38 ` Andre Przywara
  2010-03-11 13:38 ` [Qemu-devel] [PATCH 05/13] x86/cpuid: add missing CPUID feature flag names Andre Przywara
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Andre Przywara @ 2010-03-11 13:38 UTC (permalink / raw)
  To: anthony; +Cc: Andre Przywara, qemu-devel, aurelien

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 |   71 ++++++++++++++++++++++++--------------------------
 1 files changed, 34 insertions(+), 37 deletions(-)

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 1bceb4b..fa36942 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -92,8 +92,40 @@ typedef struct model_features_t {
 int check_cpuid = 0;
 int enforce_cpuid = 0;
 
-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
+}
 
 #define iswhite(c) ((c) && ((c) <= ' ' || '~' < (c)))
 
@@ -896,41 +928,6 @@ void x86_cpudef_setup(void)
 #endif
 }
 
-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] 16+ messages in thread

* [Qemu-devel] [PATCH 05/13] x86/cpuid: add missing CPUID feature flag names
  2010-03-11 13:38 [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Andre Przywara
                   ` (3 preceding siblings ...)
  2010-03-11 13:38 ` [Qemu-devel] [PATCH 04/13] x86/cpuid: moved host_cpuid function and remove prototype Andre Przywara
@ 2010-03-11 13:38 ` Andre Przywara
  2010-03-11 13:39 ` [Qemu-devel] [PATCH 06/13] x86/cpuid: add "host" to the list of supported CPU models Andre Przywara
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Andre Przywara @ 2010-03-11 13:38 UTC (permalink / raw)
  To: anthony; +Cc: Andre Przywara, qemu-devel, aurelien

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 |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index fa36942..56ae71a 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -42,14 +42,14 @@ static const char *feature_name[] = {
     "ht" /* Intel htt */, "tm", "ia64", "pbe",
 };
 static const char *ext_feature_name[] = {
-    "pni|sse3" /* Intel,AMD sse3 */, NULL, NULL, "monitor",
-    "ds_cpl", "vmx", NULL /* Linux smx */, "est",
+    "pni|sse3" /* Intel,AMD sse3 */, "pclmuldq", "dtes64", "monitor",
+    "ds_cpl", "vmx", "smx", "est",
     "tm2", "ssse3", "cid", NULL,
-    NULL, "cx16", "xtpr", NULL,
+    "fma", "cx16", "xtpr", "pdcm",
     NULL, NULL, "dca", "sse4.1|sse4_1",
-    "sse4.2|sse4_2", "x2apic", NULL, "popcnt",
-    NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, "hypervisor",
+    "sse4.2|sse4_2", "x2apic", "movbe", "popcnt",
+    NULL, "aes", "xsave", "osxsave",
+    "avx", NULL, NULL, "hypervisor",
 };
 static const char *ext2_feature_name[] = {
     "fpu", "vme", "de", "pse",
@@ -64,9 +64,9 @@ static const char *ext2_feature_name[] = {
 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,
+    "3dnowprefetch", "osvw", "ibs", "xop",
     "skinit", "wdt", NULL, NULL,
-    NULL, NULL, NULL, NULL,
+    "fma4", NULL, "cvt16", "nodeid_msr",
     NULL, NULL, NULL, NULL,
     NULL, NULL, NULL, NULL,
     NULL, NULL, NULL, NULL,
-- 
1.6.4

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

* [Qemu-devel] [PATCH 06/13] x86/cpuid: add "host" to the list of supported CPU models
  2010-03-11 13:38 [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Andre Przywara
                   ` (4 preceding siblings ...)
  2010-03-11 13:38 ` [Qemu-devel] [PATCH 05/13] x86/cpuid: add missing CPUID feature flag names Andre Przywara
@ 2010-03-11 13:39 ` Andre Przywara
  2010-03-11 13:39 ` [Qemu-devel] [PATCH 07/13] x86/cpuid: remove unnecessary kvm_trim function Andre Przywara
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Andre Przywara @ 2010-03-11 13:39 UTC (permalink / raw)
  To: anthony; +Cc: Andre Przywara, qemu-devel, aurelien

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

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 56ae71a..1e1c25b 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -757,6 +757,9 @@ void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
             (*cpu_fprintf)(f, "\n");
         }
     }
+    if (kvm_enabled()) {
+        (*cpu_fprintf)(f, "x86 %16s\n", "[host]");
+    }
 }
 
 int cpu_x86_register (CPUX86State *env, const char *cpu_model)
-- 
1.6.4

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

* [Qemu-devel] [PATCH 07/13] x86/cpuid: remove unnecessary kvm_trim function
  2010-03-11 13:38 [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Andre Przywara
                   ` (5 preceding siblings ...)
  2010-03-11 13:39 ` [Qemu-devel] [PATCH 06/13] x86/cpuid: add "host" to the list of supported CPU models Andre Przywara
@ 2010-03-11 13:39 ` Andre Przywara
  2010-03-11 13:39 ` [Qemu-devel] [PATCH 08/13] x86/cpuid: propagate further CPUID leafs when -cpu host Andre Przywara
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Andre Przywara @ 2010-03-11 13:39 UTC (permalink / raw)
  To: anthony; +Cc: Andre Przywara, qemu-devel, aurelien

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 40f8303..f77e488 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -133,19 +133,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;
@@ -191,18 +178,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] 16+ messages in thread

* [Qemu-devel] [PATCH 08/13] x86/cpuid: propagate further CPUID leafs when -cpu host
  2010-03-11 13:38 [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Andre Przywara
                   ` (6 preceding siblings ...)
  2010-03-11 13:39 ` [Qemu-devel] [PATCH 07/13] x86/cpuid: remove unnecessary kvm_trim function Andre Przywara
@ 2010-03-11 13:39 ` Andre Przywara
  2010-03-11 13:39 ` [Qemu-devel] [PATCH 09/13] x86/cpuid: add TCG feature bit trimming Andre Przywara
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Andre Przywara @ 2010-03-11 13:39 UTC (permalink / raw)
  To: anthony; +Cc: Andre Przywara, qemu-devel, aurelien

-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   |    6 +++++-
 target-i386/cpuid.c |   32 ++++++++++++++++++++++++--------
 2 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index c540213..72addd7 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -581,6 +581,10 @@ typedef struct {
 
 #define NB_MMU_MODES 2
 
+#define CPUID_FLAGS_BUILTIN          (1 << 0)
+#define CPUID_FLAGS_VENDOR_OVERRIDE  (1 << 1)
+#define CPUID_FLAGS_HOST             (1 << 2) 
+
 typedef struct CPUX86State {
     /* standard registers */
     target_ulong regs[CPU_NB_REGS];
@@ -685,7 +689,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 1e1c25b..14a10e9 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -213,7 +213,6 @@ 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;
 
@@ -481,7 +480,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;
 }
@@ -625,7 +624,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);
@@ -723,7 +722,8 @@ void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
         return;
     }
     for (def = x86_defs; def; def = def->next) {
-        snprintf(buf, sizeof (buf), def->flags ? "[%s]": "%s", def->name);
+        snprintf(buf, sizeof (buf),
+                 def->flags & CPUID_FLAGS_BUILTIN ? "[%s]": "%s", def->name);
         if (model || dump) {
             (*cpu_fprintf)(f, "x86 %16s  %-48s\n", buf, def->model_id);
         } else {
@@ -777,7 +777,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);
@@ -923,7 +923,7 @@ void x86_cpudef_setup(void)
 
     for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) {
         builtin_x86_defs[i].next = x86_defs;
-        builtin_x86_defs[i].flags = 1;
+        builtin_x86_defs[i].flags |= CPUID_FLAGS_BUILTIN;
         x86_defs = &builtin_x86_defs[i];
     }
 #if !defined(CONFIG_USER_ONLY)
@@ -944,22 +944,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) {
         host_cpuid(0, 0, NULL, ebx, ecx, edx);
     }
 }
 
+/* safe CPUID leafs to propagate to guest if -cpu host is specified */
+#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] 16+ messages in thread

* [Qemu-devel] [PATCH 09/13] x86/cpuid: add TCG feature bit trimming
  2010-03-11 13:38 [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Andre Przywara
                   ` (7 preceding siblings ...)
  2010-03-11 13:39 ` [Qemu-devel] [PATCH 08/13] x86/cpuid: propagate further CPUID leafs when -cpu host Andre Przywara
@ 2010-03-11 13:39 ` Andre Przywara
  2010-03-11 13:39 ` [Qemu-devel] [PATCH 10/13] x86/cpuid: Always expose 32 and 64-bit CPUs Andre Przywara
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Andre Przywara @ 2010-03-11 13:39 UTC (permalink / raw)
  To: anthony; +Cc: Andre Przywara, qemu-devel, aurelien

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 |   24 ++++++++++++++++++++++++
 1 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 14a10e9..a6b2362 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -229,6 +229,20 @@ typedef struct x86_def_t {
           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)
+
 /* maintains list of cpu model definitions
  */
 static x86_def_t *x86_defs = {NULL};
@@ -792,6 +806,16 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
     env->cpuid_ext3_features = def->ext3_features;
     env->cpuid_xlevel = def->xlevel;
     env->cpuid_kvm_features = def->kvm_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] 16+ messages in thread

* [Qemu-devel] [PATCH 10/13] x86/cpuid: Always expose 32 and 64-bit CPUs
  2010-03-11 13:38 [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Andre Przywara
                   ` (8 preceding siblings ...)
  2010-03-11 13:39 ` [Qemu-devel] [PATCH 09/13] x86/cpuid: add TCG feature bit trimming Andre Przywara
@ 2010-03-11 13:39 ` Andre Przywara
  2010-03-11 13:39 ` [Qemu-devel] [PATCH 11/13] x86/cpuid: Add kvm32 CPU model Andre Przywara
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Andre Przywara @ 2010-03-11 13:39 UTC (permalink / raw)
  To: anthony; +Cc: Andre Przywara, qemu-devel, aurelien

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 a6b2362..e7e9228 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -250,7 +250,6 @@ static x86_def_t *x86_defs = {NULL};
 /* built-in cpu model definitions (deprecated)
  */
 static x86_def_t builtin_x86_defs[] = {
-#ifdef TARGET_X86_64
     {
         .name = "qemu64",
         .level = 4,
@@ -349,7 +348,6 @@ static x86_def_t builtin_x86_defs[] = {
         .xlevel = 0x80000008,
         .model_id = "Common KVM processor"
     },
-#endif
     {
         .name = "qemu32",
         .level = 4,
-- 
1.6.4

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

* [Qemu-devel] [PATCH 11/13] x86/cpuid: Add kvm32 CPU model
  2010-03-11 13:38 [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Andre Przywara
                   ` (9 preceding siblings ...)
  2010-03-11 13:39 ` [Qemu-devel] [PATCH 10/13] x86/cpuid: Always expose 32 and 64-bit CPUs Andre Przywara
@ 2010-03-11 13:39 ` Andre Przywara
  2010-03-11 13:39 ` [Qemu-devel] [PATCH 12/13] x86/cpuid: fix CPUID levels Andre Przywara
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Andre Przywara @ 2010-03-11 13:39 UTC (permalink / raw)
  To: anthony; +Cc: Andre Przywara, qemu-devel, aurelien

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 e7e9228..e3c36be 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -360,6 +360,20 @@ static x86_def_t builtin_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] 16+ messages in thread

* [Qemu-devel] [PATCH 12/13] x86/cpuid: fix CPUID levels
  2010-03-11 13:38 [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Andre Przywara
                   ` (10 preceding siblings ...)
  2010-03-11 13:39 ` [Qemu-devel] [PATCH 11/13] x86/cpuid: Add kvm32 CPU model Andre Przywara
@ 2010-03-11 13:39 ` Andre Przywara
  2010-03-11 13:39 ` [Qemu-devel] [PATCH 13/13] x86/cpuid: Update qemu64/32 CPU models Andre Przywara
  2010-03-13 15:50 ` [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Aurelien Jarno
  13 siblings, 0 replies; 16+ messages in thread
From: Andre Przywara @ 2010-03-11 13:39 UTC (permalink / raw)
  To: anthony; +Cc: Andre Przywara, qemu-devel, aurelien

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 e3c36be..076f6cc 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -356,7 +356,7 @@ static x86_def_t builtin_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,
     },
     {
@@ -394,7 +394,7 @@ static x86_def_t builtin_x86_defs[] = {
     },
     {
         .name = "486",
-        .level = 0,
+        .level = 1,
         .family = 4,
         .model = 0,
         .stepping = 0,
-- 
1.6.4

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

* [Qemu-devel] [PATCH 13/13] x86/cpuid: Update qemu64/32 CPU models
  2010-03-11 13:38 [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Andre Przywara
                   ` (11 preceding siblings ...)
  2010-03-11 13:39 ` [Qemu-devel] [PATCH 12/13] x86/cpuid: fix CPUID levels Andre Przywara
@ 2010-03-11 13:39 ` Andre Przywara
  2010-03-13  0:06   ` Jamie Lokier
  2010-03-13 15:50 ` [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Aurelien Jarno
  13 siblings, 1 reply; 16+ messages in thread
From: Andre Przywara @ 2010-03-11 13:39 UTC (permalink / raw)
  To: anthony; +Cc: Andre Przywara, qemu-devel, aurelien

Since we now have a real TCG feature set, use it to describe the
artificial qemu CPUs (both 64 and 32-bit). If new features are added
to TCG, the capability of qemu64/32 will automatically be adjusted.

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

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 076f6cc..ec43596 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -227,6 +227,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_FEATURES_64 (CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX)
 #define EXT2_FEATURE_MASK 0x0183F3FF
 
 #define TCG_FEATURES (CPUID_FP87 | CPUID_PSE | CPUID_TSC | CPUID_MSR | \
@@ -259,16 +260,12 @@ static x86_def_t builtin_x86_defs[] = {
         .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 & 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,
+        .features = TCG_FEATURES,
+        .ext_features = TCG_EXT_FEATURES,
+        /* 3DNow! is deprecated, so leave it out of the default feature set */
+        .ext2_features = (TCG_EXT2_FEATURES | EXT2_FEATURES_64) &
+                        ~(CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT),
+        .ext3_features = TCG_EXT3_FEATURES,
         .xlevel = 0x8000000A,
         .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
     },
@@ -354,8 +351,12 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 3,
         .stepping = 3,
-        .features = PPRO_FEATURES,
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
+        .features = TCG_FEATURES,
+        .ext_features = TCG_EXT_FEATURES,
+        /* 3DNow! is deprecated, so leave it out of the default feature set */
+        .ext2_features = TCG_EXT2_FEATURES &
+                       ~(CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT),
+        .ext3_features = TCG_EXT3_FEATURES,
         .xlevel = 0x80000004,
         .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
     },
-- 
1.6.4

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

* Re: [Qemu-devel] [PATCH 13/13] x86/cpuid: Update qemu64/32 CPU models
  2010-03-11 13:39 ` [Qemu-devel] [PATCH 13/13] x86/cpuid: Update qemu64/32 CPU models Andre Przywara
@ 2010-03-13  0:06   ` Jamie Lokier
  0 siblings, 0 replies; 16+ messages in thread
From: Jamie Lokier @ 2010-03-13  0:06 UTC (permalink / raw)
  To: Andre Przywara; +Cc: aurelien, qemu-devel

Andre Przywara wrote:
> Since we now have a real TCG feature set, use it to describe the
> artificial qemu CPUs (both 64 and 32-bit). If new features are added
> to TCG, the capability of qemu64/32 will automatically be adjusted.
> 
> Signed-off-by: Andre Przywara <andre.przywara@amd.com>

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

Those comments seem to have disappeared.  Are they useful - or even correct any more?

> +        .features = TCG_FEATURES,
> +        .ext_features = TCG_EXT_FEATURES,
> +        /* 3DNow! is deprecated, so leave it out of the default feature set */
> +        .ext2_features = (TCG_EXT2_FEATURES | EXT2_FEATURES_64) &
> +                        ~(CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT),
> +        .ext3_features = TCG_EXT3_FEATURES,

3DNow! is an old capability, but why is that a reason to single it out
for omission?

Is there any harm in it being enabled?

-- Jamie

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

* Re: [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes
  2010-03-11 13:38 [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Andre Przywara
                   ` (12 preceding siblings ...)
  2010-03-11 13:39 ` [Qemu-devel] [PATCH 13/13] x86/cpuid: Update qemu64/32 CPU models Andre Przywara
@ 2010-03-13 15:50 ` Aurelien Jarno
  13 siblings, 0 replies; 16+ messages in thread
From: Aurelien Jarno @ 2010-03-13 15:50 UTC (permalink / raw)
  To: Andre Przywara; +Cc: qemu-devel

On Thu, Mar 11, 2010 at 02:38:54PM +0100, Andre Przywara wrote:
> Hi,
> 
> a rebased and refined version of my CPUID cleanup series. This should
> now apply on top of git head. Compared to the last post this leaves
> out the bits already done by John Cooper's patch. Also I added a separate
> patch to deal with an accidently removed line (patch 3/13).
> 
> 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.
> Additionally the rest of the patches beautifies or simplifies some code.
> Feature additions are:
>  5/13: add missing CPUID feature bit names (updated)
>  8/13: -cpu host propagates more CPUID leafs, so that the cache topology
>        will be visibile in the guest
>  9/13: add CPUID feature bit trimming for TCG: Features not supported by
>        the emulator will be masked out.
> 10/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 9/13.
> 11/13: add kvm32 CPU model: Per popular request add a counterpart to kvm64
>        describing a basic hardware virtualization capable CPU for migration
>        purposes.
> 13/13: Set the feature bits of qemu{32,64} to the set supported by TCG.
> 
> The last patch is actually debatable, as it changes the default CPUID bits
> seen by guest. On the other hand it is only consequent to do so, as
> qemu{32,64} are meant to be artifical CPUs.
> 
> More details in the commit messages.
> 
> Please review, comment and apply.
> 

Thanks, I have applied all patches except:
- 08: I prefer someone knowing KVM better than me reviews it
- 11: same
- 13: See comment from Jamie

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

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

end of thread, other threads:[~2010-03-13 15:50 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-11 13:38 [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Andre Przywara
2010-03-11 13:38 ` [Qemu-devel] [PATCH 01/13] x86/cpuid: move CPUID functions into separate file Andre Przywara
2010-03-11 13:38 ` [Qemu-devel] [PATCH 02/13] x86/cpuid: replace magic number with named constant Andre Przywara
2010-03-11 13:38 ` [Qemu-devel] [PATCH 03/13] x86/cpuid: fix missing feature set bits Andre Przywara
2010-03-11 13:38 ` [Qemu-devel] [PATCH 04/13] x86/cpuid: moved host_cpuid function and remove prototype Andre Przywara
2010-03-11 13:38 ` [Qemu-devel] [PATCH 05/13] x86/cpuid: add missing CPUID feature flag names Andre Przywara
2010-03-11 13:39 ` [Qemu-devel] [PATCH 06/13] x86/cpuid: add "host" to the list of supported CPU models Andre Przywara
2010-03-11 13:39 ` [Qemu-devel] [PATCH 07/13] x86/cpuid: remove unnecessary kvm_trim function Andre Przywara
2010-03-11 13:39 ` [Qemu-devel] [PATCH 08/13] x86/cpuid: propagate further CPUID leafs when -cpu host Andre Przywara
2010-03-11 13:39 ` [Qemu-devel] [PATCH 09/13] x86/cpuid: add TCG feature bit trimming Andre Przywara
2010-03-11 13:39 ` [Qemu-devel] [PATCH 10/13] x86/cpuid: Always expose 32 and 64-bit CPUs Andre Przywara
2010-03-11 13:39 ` [Qemu-devel] [PATCH 11/13] x86/cpuid: Add kvm32 CPU model Andre Przywara
2010-03-11 13:39 ` [Qemu-devel] [PATCH 12/13] x86/cpuid: fix CPUID levels Andre Przywara
2010-03-11 13:39 ` [Qemu-devel] [PATCH 13/13] x86/cpuid: Update qemu64/32 CPU models Andre Przywara
2010-03-13  0:06   ` Jamie Lokier
2010-03-13 15:50 ` [Qemu-devel] [PATCH 00/13] x86/cpuid: cleanups and fixes Aurelien Jarno

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.