aboutsummaryrefslogtreecommitdiff
path: root/target-i386/helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-i386/helper.c')
-rw-r--r--target-i386/helper.c65
1 files changed, 59 insertions, 6 deletions
diff --git a/target-i386/helper.c b/target-i386/helper.c
index cb9113e8c8..d7563f7bbd 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -273,9 +273,9 @@ static x86_def_t x86_defs[] = {
{
.name = "athlon",
.level = 2,
- .vendor1 = 0x68747541, /* "Auth" */
- .vendor2 = 0x69746e65, /* "enti" */
- .vendor3 = 0x444d4163, /* "cAMD" */
+ .vendor1 = CPUID_VENDOR_AMD_1,
+ .vendor2 = CPUID_VENDOR_AMD_2,
+ .vendor3 = CPUID_VENDOR_AMD_3,
.family = 6,
.model = 2,
.stepping = 3,
@@ -308,6 +308,54 @@ static x86_def_t x86_defs[] = {
},
};
+static void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax,
+ uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
+
+static int cpu_x86_fill_model_id(char *str)
+{
+ uint32_t eax, ebx, ecx, edx;
+ 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, ebx, ecx, edx;
+
+ x86_cpu_def->name = "host";
+ host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
+ x86_cpu_def->level = eax;
+ x86_cpu_def->vendor1 = ebx;
+ x86_cpu_def->vendor2 = edx;
+ x86_cpu_def->vendor3 = ecx;
+
+ host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
+ x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
+ x86_cpu_def->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
+ x86_cpu_def->stepping = eax & 0x0F;
+ x86_cpu_def->ext_features = ecx;
+ x86_cpu_def->features = edx;
+
+ host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx);
+ x86_cpu_def->xlevel = eax;
+
+ host_cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx);
+ x86_cpu_def->ext2_features = edx;
+ x86_cpu_def->ext3_features = ecx;
+ cpu_x86_fill_model_id(x86_cpu_def->model_id);
+ x86_cpu_def->vendor_override = 0;
+
+ return 0;
+}
+
static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
{
unsigned int i;
@@ -326,9 +374,14 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
break;
}
}
- if (!def)
- goto error;
- memcpy(x86_cpu_def, def, sizeof(*def));
+ if (!def) {
+ if (strcmp(name, "host") != 0) {
+ goto error;
+ }
+ cpu_x86_fill_host(x86_cpu_def);
+ } else {
+ memcpy(x86_cpu_def, def, sizeof(*def));
+ }
add_flagname_to_bitmaps("hypervisor", &plus_features,
&plus_ext_features, &plus_ext2_features, &plus_ext3_features);