diff --git a/libkvm/libkvm-x86.c b/libkvm/libkvm-x86.c
index dcef548..10f6614 100644
--- a/libkvm/libkvm-x86.c
+++ b/libkvm/libkvm-x86.c
@@ -379,6 +379,37 @@ int kvm_set_msrs(kvm_context_t kvm, int vcpu, struct kvm_msr_entry *msrs,
     return r;
 }
 
+/*
+ * Returns available host cpuid entries.  User must free.
+ */
+struct kvm_cpuid2 *kvm_get_host_cpuid_entries(kvm_context_t kvm)
+{
+	struct kvm_cpuid2 sizer, *cpuids;
+	int r, e;
+
+	sizer.nent = 0;
+	r = ioctl(kvm->fd, KVM_GET_SUPPORTED_CPUID, &sizer);
+	if (r != -1 && errno != EAGAIN)
+		return NULL;
+
+	cpuids = malloc(sizeof *cpuids + sizer.nent * sizeof *cpuids->entries);
+	if (!cpuids) {
+		errno = ENOMEM;
+		return NULL;
+	}
+
+	cpuids->nent = sizer.nent;
+	r = ioctl(kvm->fd, KVM_GET_SUPPORTED_CPUID, cpuids);
+	if (r == -1) {
+		e = errno;
+		free(cpuids);
+		errno = e;
+		return NULL;
+	}
+	return cpuids;
+}
+
+
 static void print_seg(FILE *file, const char *name, struct kvm_segment *seg)
 {
     	fprintf(stderr,
diff --git a/libkvm/libkvm.h b/libkvm/libkvm.h
index e79e4fd..5b7f063 100644
--- a/libkvm/libkvm.h
+++ b/libkvm/libkvm.h
@@ -27,6 +27,9 @@ typedef struct kvm_context *kvm_context_t;
 struct kvm_msr_list *kvm_get_msr_list(kvm_context_t);
 int kvm_get_msrs(kvm_context_t, int vcpu, struct kvm_msr_entry *msrs, int n);
 int kvm_set_msrs(kvm_context_t, int vcpu, struct kvm_msr_entry *msrs, int n);
+struct kvm_cpuid2 *kvm_get_host_cpuid_entries(kvm_context_t);
+void get_host_cpuid_entry(uint32_t function, uint32_t index,
+				struct kvm_cpuid_entry2 *e);
 #endif
 
 /*!
diff --git a/qemu/qemu-kvm-x86.c b/qemu/qemu-kvm-x86.c
index 01748ed..4c1c159 100644
--- a/qemu/qemu-kvm-x86.c
+++ b/qemu/qemu-kvm-x86.c
@@ -23,6 +23,7 @@
 #define MSR_IA32_TSC		0x10
 
 static struct kvm_msr_list *kvm_msr_list;
+static struct kvm_cpuid2 *kvm_host_cpuid_entries;
 extern unsigned int kvm_shadow_memory;
 static int kvm_has_msr_star;
 
@@ -57,7 +58,12 @@ int kvm_arch_qemu_create_context(void)
     for (i = 0; i < kvm_msr_list->nmsrs; ++i)
 	if (kvm_msr_list->indices[i] == MSR_STAR)
 	    kvm_has_msr_star = 1;
-	return 0;
+
+    kvm_host_cpuid_entries = kvm_get_host_cpuid_entries(kvm_context);
+    if (!kvm_host_cpuid_entries)
+	return -1;
+
+    return 0;
 }
 
 static void set_msr_entry(struct kvm_msr_entry *entry, uint32_t index,
@@ -461,13 +467,61 @@ void kvm_arch_save_regs(CPUState *env)
     }
 }
 
+void get_host_cpuid_entry(uint32_t function, uint32_t index,
+				struct kvm_cpuid_entry2 *e)
+{
+    int i;
+    struct kvm_cpuid_entry2 *entries;
+
+    memset(e, 0, (sizeof *e));
+    e->function = function;
+    e->index = index;
+
+    if (!kvm_host_cpuid_entries)
+	return;
+
+    entries = kvm_host_cpuid_entries->entries;
+
+    for (i=0; i<kvm_host_cpuid_entries->nent; i++) {
+	struct kvm_cpuid_entry2 *ent = &entries[i];
+	if (ent->function != function)
+	    continue; 
+	if ((ent->flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX) && 
+						(ent->index != index))
+	    continue;
+	if ((ent->flags & KVM_CPUID_FLAG_STATEFUL_FUNC) &&
+		!(ent->flags & KVM_CPUID_FLAG_STATE_READ_NEXT))
+	    continue;
+
+	memcpy(e, ent, sizeof (*e));
+
+	if (ent->flags & KVM_CPUID_FLAG_STATEFUL_FUNC) {
+	    int j;
+	    ent->flags &= ~KVM_CPUID_FLAG_STATE_READ_NEXT;
+	    for (j=i+1; ;j=(j+1)%(kvm_host_cpuid_entries->nent)) {
+		struct kvm_cpuid_entry2 *entj = &entries[j];
+		if (entj->function == ent->function) {
+		    entj->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT;
+		    break;
+		}
+	    }
+	}
+	break;
+    }
+}
+
 static void do_cpuid_ent(struct kvm_cpuid_entry2 *e, uint32_t function,
-                         uint32_t count, CPUState *env)
+                         uint32_t index, CPUState *env)
 {
+    if (env->cpuid_host_cpu) {
+        get_host_cpuid_entry(function, index, e);
+	return;
+    }
+    e->function = function;
+    e->index = index;
     env->regs[R_EAX] = function;
-    env->regs[R_ECX] = count;
+    env->regs[R_ECX] = index;
     qemu_kvm_cpuid_on_env(env);
-    e->function = function;
     e->eax = env->regs[R_EAX];
     e->ebx = env->regs[R_EBX];
     e->ecx = env->regs[R_ECX];
@@ -518,6 +572,10 @@ int kvm_arch_qemu_init_env(CPUState *cenv)
 
     copy = *cenv;
 
+    if (copy.cpuid_host_cpu) 
+        if (!kvm_host_cpuid_entries)
+	   return -EINVAL;
+
 #ifdef KVM_CPUID_SIGNATURE
     /* Paravirtualization CPUIDs */
     memcpy(signature, "KVMKVMKVM\0\0\0", 12);
@@ -535,34 +593,32 @@ int kvm_arch_qemu_init_env(CPUState *cenv)
     pv_ent->eax = get_para_features(kvm_context);
 #endif
 
-    copy.regs[R_EAX] = 0;
-    qemu_kvm_cpuid_on_env(&copy);
-    limit = copy.regs[R_EAX];
+    limit = copy.cpuid_level;
 
     for (i = 0; i <= limit; ++i) {
-        if (i == 4 || i == 0xb || i == 0xd) {
+        if ( i == 2 || i == 4 || i == 0xb || i == 0xd) {
             for (j = 0; ; ++j) {
                 do_cpuid_ent(&cpuid_ent[cpuid_nent], i, j, &copy);
 
                 cpuid_ent[cpuid_nent].flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
                 cpuid_ent[cpuid_nent].index = j;
-
                 cpuid_nent++;
 
-                if (i == 4 && copy.regs[R_EAX] == 0)
+                if (i == 2 && (cpuid_ent[cpuid_nent-1].eax & 0xff) == (j+1)) {
+                    break;
+		}
+                if (i == 4 && (cpuid_ent[cpuid_nent-1].eax & 0x1f) == 0)
                     break;
-                if (i == 0xb && !(copy.regs[R_ECX] & 0xff00))
+                if (i == 0xb && !(cpuid_ent[cpuid_nent-1].ecx & 0xff00))
                     break;
-                if (i == 0xd && copy.regs[R_EAX] == 0)
+                if (i == 0xd && cpuid_ent[cpuid_nent-1].eax == 0)
                     break;
             }
         } else
             do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, 0, &copy);
     }
 
-    copy.regs[R_EAX] = 0x80000000;
-    qemu_kvm_cpuid_on_env(&copy);
-    limit = copy.regs[R_EAX];
+    limit = copy.cpuid_xlevel;
 
     for (i = 0x80000000; i <= limit; ++i)
 	do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, 0, &copy);
diff --git a/qemu/target-i386/cpu.h b/qemu/target-i386/cpu.h
index 944e386..0a0fccf 100644
--- a/qemu/target-i386/cpu.h
+++ b/qemu/target-i386/cpu.h
@@ -628,6 +628,7 @@ typedef struct CPUX86State {
     uint32_t cpuid_ext2_features;
     uint32_t cpuid_ext3_features;
     uint32_t cpuid_apic_id;
+    uint32_t cpuid_host_cpu;
 
 #ifdef USE_KQEMU
     int kqemu_enabled;
diff --git a/qemu/target-i386/helper.c b/qemu/target-i386/helper.c
index cda0390..43de18f 100644
--- a/qemu/target-i386/helper.c
+++ b/qemu/target-i386/helper.c
@@ -119,6 +119,9 @@ typedef struct x86_def_t {
 static x86_def_t x86_defs[] = {
 #ifdef TARGET_X86_64
     {
+        .name = "host",
+    },
+    {
         .name = "qemu64",
         .level = 2,
         .vendor1 = CPUID_VENDOR_AMD_1,
@@ -372,10 +375,57 @@ void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
         (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name);
 }
 
+static int cpu_host_x86_register (CPUX86State *env)
+{
+    struct kvm_cpuid_entry2 e;
+    env->cpuid_host_cpu = 1;
+
+    get_host_cpuid_entry(0, 0, &e);
+    env->cpuid_level = e.eax;
+    env->cpuid_vendor1 = e.ebx;
+    env->cpuid_vendor2 = e.ecx;
+    env->cpuid_vendor3 = e.edx;
+
+    get_host_cpuid_entry(1, 0, &e);
+    env->cpuid_version = e.eax;
+    env->cpuid_features = e.edx;
+    env->cpuid_ext_features = e.ecx;
+
+    get_host_cpuid_entry(0x80000000, 0, &e);
+    env->cpuid_xlevel = e.eax;
+
+    get_host_cpuid_entry(0x80000001, 0, &e);
+    env->cpuid_ext3_features = e.ecx;
+    env->cpuid_ext2_features = e.edx;
+
+    get_host_cpuid_entry(0x80000002, 0, &e);
+    env->cpuid_model[0] = e.eax;
+    env->cpuid_model[1] = e.ebx;
+    env->cpuid_model[2] = e.ecx;
+    env->cpuid_model[3] = e.edx;
+
+    get_host_cpuid_entry(0x80000003, 0, &e);
+    env->cpuid_model[4] = e.eax;
+    env->cpuid_model[5] = e.ebx;
+    env->cpuid_model[6] = e.ecx;
+    env->cpuid_model[7] = e.edx;
+
+    get_host_cpuid_entry(0x80000004, 0, &e);
+    env->cpuid_model[8] = e.eax;
+    env->cpuid_model[9] = e.ebx;
+    env->cpuid_model[10] = e.ecx;
+    env->cpuid_model[11] = e.edx;
+
+    return 0;
+}
+
 static int cpu_x86_register (CPUX86State *env, const char *cpu_model)
 {
     x86_def_t def1, *def = &def1;
 
+    if (0 == strcmp(cpu_model, "host")) 
+	return cpu_host_x86_register(env);
+
     if (cpu_x86_find_by_name(def, cpu_model) < 0)
         return -1;
     if (def->vendor1) {
