static const char *kvm_feature_name[] = {
"kvmclock", "kvm_nopiodelay", "kvm_mmu", "kvmclock",
- "kvm_asyncpf", "kvm_steal_time", "kvm_pv_eoi", NULL,
+ "kvm_asyncpf", "kvm_steal_time", "kvm_pv_eoi", "kvm_pv_unhalt",
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
};
#undef REGISTER
+typedef struct ExtSaveArea {
+ uint32_t feature, bits;
+ uint32_t offset, size;
+} ExtSaveArea;
+
+static const ExtSaveArea ext_save_areas[] = {
+ [2] = { .feature = FEAT_1_ECX, .bits = CPUID_EXT_AVX,
+ .offset = 0x100, .size = 0x240 },
+};
const char *get_register_name_32(unsigned int reg)
{
int stepping;
FeatureWordArray features;
char model_id[48];
+ bool cache_info_passthrough;
} x86_def_t;
#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
.level = 4,
.vendor = CPUID_VENDOR_AMD,
.family = 6,
- .model = 2,
+ .model = 6,
.stepping = 3,
.features[FEAT_1_EDX] =
PPRO_FEATURES |
.level = 4,
.vendor = CPUID_VENDOR_INTEL,
.family = 6,
- .model = 3,
+ .model = 6,
.stepping = 3,
.features[FEAT_1_EDX] =
PPRO_FEATURES,
assert(kvm_enabled());
x86_cpu_def->name = "host";
+ x86_cpu_def->cache_info_passthrough = true;
host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
x86_cpu_vendor_words2str(x86_cpu_def->vendor, ebx, edx, ecx);
env->features[FEAT_C000_0001_EDX] = def->features[FEAT_C000_0001_EDX];
env->features[FEAT_7_0_EBX] = def->features[FEAT_7_0_EBX];
env->cpuid_xlevel2 = def->xlevel2;
+ cpu->cache_info_passthrough = def->cache_info_passthrough;
object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp);
}
Error **errp)
{
X86CPU *cpu = NULL;
- CPUX86State *env;
gchar **model_pieces;
char *name, *features;
char *typename;
qdev_set_parent_bus(DEVICE(cpu), qdev_get_child_bus(icc_bridge, "icc"));
object_unref(OBJECT(cpu));
#endif
- env = &cpu->env;
- env->cpu_model_str = cpu_model;
cpu_x86_register(cpu, name, &error);
if (error) {
break;
case 2:
/* cache info: needed for Pentium Pro compatibility */
+ if (cpu->cache_info_passthrough) {
+ host_cpuid(index, 0, eax, ebx, ecx, edx);
+ break;
+ }
*eax = 1; /* Number of CPUID[EAX=2] calls required */
*ebx = 0;
*ecx = 0;
break;
case 4:
/* cache info: needed for Core compatibility */
- if (cs->nr_cores > 1) {
- *eax = (cs->nr_cores - 1) << 26;
+ if (cpu->cache_info_passthrough) {
+ host_cpuid(index, count, eax, ebx, ecx, edx);
+ *eax &= ~0xFC000000;
} else {
*eax = 0;
- }
- switch (count) {
+ switch (count) {
case 0: /* L1 dcache info */
*eax |= CPUID_4_TYPE_DCACHE | \
CPUID_4_LEVEL(1) | \
*ecx = 0;
*edx = 0;
break;
+ }
+ }
+
+ /* QEMU gives out its own APIC IDs, never pass down bits 31..26. */
+ if ((*eax & 31) && cs->nr_cores > 1) {
+ *eax |= (cs->nr_cores - 1) << 26;
}
break;
case 5:
*edx = 0;
}
break;
- case 0xD:
+ case 0xD: {
+ KVMState *s = cs->kvm_state;
+ uint64_t kvm_mask;
+ int i;
+
/* Processor Extended State */
- if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) {
- *eax = 0;
- *ebx = 0;
- *ecx = 0;
- *edx = 0;
+ *eax = 0;
+ *ebx = 0;
+ *ecx = 0;
+ *edx = 0;
+ if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE) || !kvm_enabled()) {
break;
}
- if (kvm_enabled()) {
- KVMState *s = cs->kvm_state;
+ kvm_mask =
+ kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EAX) |
+ ((uint64_t)kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EDX) << 32);
- *eax = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EAX);
- *ebx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EBX);
- *ecx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_ECX);
- *edx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EDX);
- } else {
- *eax = 0;
- *ebx = 0;
- *ecx = 0;
- *edx = 0;
+ if (count == 0) {
+ *ecx = 0x240;
+ for (i = 2; i < ARRAY_SIZE(ext_save_areas); i++) {
+ const ExtSaveArea *esa = &ext_save_areas[i];
+ if ((env->features[esa->feature] & esa->bits) == esa->bits &&
+ (kvm_mask & (1 << i)) != 0) {
+ if (i < 32) {
+ *eax |= 1 << i;
+ } else {
+ *edx |= 1 << (i - 32);
+ }
+ *ecx = MAX(*ecx, esa->offset + esa->size);
+ }
+ }
+ *eax |= kvm_mask & (XSTATE_FP | XSTATE_SSE);
+ *ebx = *ecx;
+ } else if (count == 1) {
+ *eax = kvm_arch_get_supported_cpuid(s, 0xd, 1, R_EAX);
+ } else if (count < ARRAY_SIZE(ext_save_areas)) {
+ const ExtSaveArea *esa = &ext_save_areas[count];
+ if ((env->features[esa->feature] & esa->bits) == esa->bits &&
+ (kvm_mask & (1 << count)) != 0) {
+ *eax = esa->offset;
+ *ebx = esa->size;
+ }
}
break;
+ }
case 0x80000000:
*eax = env->cpuid_xlevel;
*ebx = env->cpuid_vendor1;
break;
case 0x80000005:
/* cache info (L1 cache) */
+ if (cpu->cache_info_passthrough) {
+ host_cpuid(index, 0, eax, ebx, ecx, edx);
+ break;
+ }
*eax = (L1_DTLB_2M_ASSOC << 24) | (L1_DTLB_2M_ENTRIES << 16) | \
(L1_ITLB_2M_ASSOC << 8) | (L1_ITLB_2M_ENTRIES);
*ebx = (L1_DTLB_4K_ASSOC << 24) | (L1_DTLB_4K_ENTRIES << 16) | \
break;
case 0x80000006:
/* cache info (L2 cache) */
+ if (cpu->cache_info_passthrough) {
+ host_cpuid(index, 0, eax, ebx, ecx, edx);
+ break;
+ }
*eax = (AMD_ENC_ASSOC(L2_DTLB_2M_ASSOC) << 28) | \
(L2_DTLB_2M_ENTRIES << 16) | \
(AMD_ENC_ASSOC(L2_ITLB_2M_ASSOC) << 12) | \
env->fpuc = 0x37f;
env->mxcsr = 0x1f80;
+ env->xstate_bv = XSTATE_FP | XSTATE_SSE;
env->pat = 0x0007040600070406ULL;
env->msr_ia32_misc_enable = MSR_IA32_MISC_ENABLE_DEFAULT;