mirror of https://gitee.com/openkylin/qemu.git
target-i386: Implement CPUID[0xB] (Extended Topology Enumeration)
I looked at a dozen Intel CPU that have this CPUID and all of them always had Core offset as 1 (a wasted bit when hyperthreading is disabled) and Package offset at least 4 (wasted bits at <= 4 cores). QEMU uses more compact IDs and it doesn't make much sense to change it now. I keep the SMT and Core sub-leaves even if there is just one thread/core; it makes the code simpler and there should be no harm. Signed-off-by: Radim Krčmář <rkrcmar@redhat.com> Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
This commit is contained in:
parent
d86c145114
commit
5232d00a04
|
@ -357,7 +357,12 @@ int e820_get_num_entries(void);
|
||||||
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||||
|
|
||||||
#define PC_COMPAT_2_6 \
|
#define PC_COMPAT_2_6 \
|
||||||
HW_COMPAT_2_6
|
HW_COMPAT_2_6 \
|
||||||
|
{\
|
||||||
|
.driver = TYPE_X86_CPU,\
|
||||||
|
.property = "cpuid-0xb",\
|
||||||
|
.value = "off",\
|
||||||
|
},
|
||||||
|
|
||||||
#define PC_COMPAT_2_5 \
|
#define PC_COMPAT_2_5 \
|
||||||
PC_COMPAT_2_6 \
|
PC_COMPAT_2_6 \
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
|
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "hw/qdev-properties.h"
|
#include "hw/qdev-properties.h"
|
||||||
|
#include "hw/i386/topology.h"
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
#include "hw/hw.h"
|
#include "hw/hw.h"
|
||||||
|
@ -2492,6 +2493,36 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
||||||
*edx = 0;
|
*edx = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 0xB:
|
||||||
|
/* Extended Topology Enumeration Leaf */
|
||||||
|
if (!cpu->enable_cpuid_0xb) {
|
||||||
|
*eax = *ebx = *ecx = *edx = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ecx = count & 0xff;
|
||||||
|
*edx = cpu->apic_id;
|
||||||
|
|
||||||
|
switch (count) {
|
||||||
|
case 0:
|
||||||
|
*eax = apicid_core_offset(smp_cores, smp_threads);
|
||||||
|
*ebx = smp_threads;
|
||||||
|
*ecx |= CPUID_TOPOLOGY_LEVEL_SMT;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
*eax = apicid_pkg_offset(smp_cores, smp_threads);
|
||||||
|
*ebx = smp_cores * smp_threads;
|
||||||
|
*ecx |= CPUID_TOPOLOGY_LEVEL_CORE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*eax = 0;
|
||||||
|
*ebx = 0;
|
||||||
|
*ecx |= CPUID_TOPOLOGY_LEVEL_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(!(*eax & ~0x1f));
|
||||||
|
*ebx &= 0xffff; /* The count doesn't need to be reliable. */
|
||||||
|
break;
|
||||||
case 0xD: {
|
case 0xD: {
|
||||||
KVMState *s = cs->kvm_state;
|
KVMState *s = cs->kvm_state;
|
||||||
uint64_t ena_mask;
|
uint64_t ena_mask;
|
||||||
|
@ -3251,6 +3282,7 @@ static Property x86_cpu_properties[] = {
|
||||||
DEFINE_PROP_UINT32("xlevel", X86CPU, env.cpuid_xlevel, 0),
|
DEFINE_PROP_UINT32("xlevel", X86CPU, env.cpuid_xlevel, 0),
|
||||||
DEFINE_PROP_UINT32("xlevel2", X86CPU, env.cpuid_xlevel2, 0),
|
DEFINE_PROP_UINT32("xlevel2", X86CPU, env.cpuid_xlevel2, 0),
|
||||||
DEFINE_PROP_STRING("hv-vendor-id", X86CPU, hyperv_vendor_id),
|
DEFINE_PROP_STRING("hv-vendor-id", X86CPU, hyperv_vendor_id),
|
||||||
|
DEFINE_PROP_BOOL("cpuid-0xb", X86CPU, enable_cpuid_0xb, true),
|
||||||
DEFINE_PROP_END_OF_LIST()
|
DEFINE_PROP_END_OF_LIST()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -636,6 +636,11 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
|
||||||
#define CPUID_MWAIT_IBE (1U << 1) /* Interrupts can exit capability */
|
#define CPUID_MWAIT_IBE (1U << 1) /* Interrupts can exit capability */
|
||||||
#define CPUID_MWAIT_EMX (1U << 0) /* enumeration supported */
|
#define CPUID_MWAIT_EMX (1U << 0) /* enumeration supported */
|
||||||
|
|
||||||
|
/* CPUID[0xB].ECX level types */
|
||||||
|
#define CPUID_TOPOLOGY_LEVEL_INVALID (0U << 8)
|
||||||
|
#define CPUID_TOPOLOGY_LEVEL_SMT (1U << 8)
|
||||||
|
#define CPUID_TOPOLOGY_LEVEL_CORE (2U << 8)
|
||||||
|
|
||||||
#ifndef HYPERV_SPINLOCK_NEVER_RETRY
|
#ifndef HYPERV_SPINLOCK_NEVER_RETRY
|
||||||
#define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF
|
#define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF
|
||||||
#endif
|
#endif
|
||||||
|
@ -1173,6 +1178,9 @@ struct X86CPU {
|
||||||
*/
|
*/
|
||||||
bool enable_pmu;
|
bool enable_pmu;
|
||||||
|
|
||||||
|
/* Compatibility bits for old machine types: */
|
||||||
|
bool enable_cpuid_0xb;
|
||||||
|
|
||||||
/* in order to simplify APIC support, we leave this pointer to the
|
/* in order to simplify APIC support, we leave this pointer to the
|
||||||
user */
|
user */
|
||||||
struct DeviceState *apic_state;
|
struct DeviceState *apic_state;
|
||||||
|
|
Loading…
Reference in New Issue