Commit 45e966fc authored by Paolo Bonzini's avatar Paolo Bonzini

KVM: x86: Do not return host topology information from KVM_GET_SUPPORTED_CPUID

Passing the host topology to the guest is almost certainly wrong
and will confuse the scheduler.  In addition, several fields of
these CPUID leaves vary on each processor; it is simply impossible to
return the right values from KVM_GET_SUPPORTED_CPUID in such a way that
they can be passed to KVM_SET_CPUID2.

The values that will most likely prevent confusion are all zeroes.
Userspace will have to override it anyway if it wishes to present a
specific topology to the guest.

Cc: stable@vger.kernel.org
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 74905e3d
...@@ -8310,6 +8310,20 @@ CPU[EAX=1]:ECX[24] (TSC_DEADLINE) is not reported by ``KVM_GET_SUPPORTED_CPUID`` ...@@ -8310,6 +8310,20 @@ CPU[EAX=1]:ECX[24] (TSC_DEADLINE) is not reported by ``KVM_GET_SUPPORTED_CPUID``
It can be enabled if ``KVM_CAP_TSC_DEADLINE_TIMER`` is present and the kernel It can be enabled if ``KVM_CAP_TSC_DEADLINE_TIMER`` is present and the kernel
has enabled in-kernel emulation of the local APIC. has enabled in-kernel emulation of the local APIC.
CPU topology
~~~~~~~~~~~~
Several CPUID values include topology information for the host CPU:
0x0b and 0x1f for Intel systems, 0x8000001e for AMD systems. Different
versions of KVM return different values for this information and userspace
should not rely on it. Currently they return all zeroes.
If userspace wishes to set up a guest topology, it should be careful that
the values of these three leaves differ for each CPU. In particular,
the APIC ID is found in EDX for all subleaves of 0x0b and 0x1f, and in EAX
for 0x8000001e; the latter also encodes the core id and node id in bits
7:0 of EBX and ECX respectively.
Obsolete ioctls and capabilities Obsolete ioctls and capabilities
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
......
...@@ -770,16 +770,22 @@ struct kvm_cpuid_array { ...@@ -770,16 +770,22 @@ struct kvm_cpuid_array {
int nent; int nent;
}; };
static struct kvm_cpuid_entry2 *get_next_cpuid(struct kvm_cpuid_array *array)
{
if (array->nent >= array->maxnent)
return NULL;
return &array->entries[array->nent++];
}
static struct kvm_cpuid_entry2 *do_host_cpuid(struct kvm_cpuid_array *array, static struct kvm_cpuid_entry2 *do_host_cpuid(struct kvm_cpuid_array *array,
u32 function, u32 index) u32 function, u32 index)
{ {
struct kvm_cpuid_entry2 *entry; struct kvm_cpuid_entry2 *entry = get_next_cpuid(array);
if (array->nent >= array->maxnent) if (!entry)
return NULL; return NULL;
entry = &array->entries[array->nent++];
memset(entry, 0, sizeof(*entry)); memset(entry, 0, sizeof(*entry));
entry->function = function; entry->function = function;
entry->index = index; entry->index = index;
...@@ -956,22 +962,13 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) ...@@ -956,22 +962,13 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
entry->edx = edx.full; entry->edx = edx.full;
break; break;
} }
/*
* Per Intel's SDM, the 0x1f is a superset of 0xb,
* thus they can be handled by common code.
*/
case 0x1f: case 0x1f:
case 0xb: case 0xb:
/* /*
* Populate entries until the level type (ECX[15:8]) of the * No topology; a valid topology is indicated by the presence
* previous entry is zero. Note, CPUID EAX.{0x1f,0xb}.0 is * of subleaf 1.
* the starting entry, filled by the primary do_host_cpuid().
*/ */
for (i = 1; entry->ecx & 0xff00; ++i) { entry->eax = entry->ebx = entry->ecx = 0;
entry = do_host_cpuid(array, function, i);
if (!entry)
goto out;
}
break; break;
case 0xd: { case 0xd: {
u64 permitted_xcr0 = kvm_caps.supported_xcr0 & xstate_get_guest_group_perm(); u64 permitted_xcr0 = kvm_caps.supported_xcr0 & xstate_get_guest_group_perm();
...@@ -1202,6 +1199,9 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) ...@@ -1202,6 +1199,9 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
entry->ebx = entry->ecx = entry->edx = 0; entry->ebx = entry->ecx = entry->edx = 0;
break; break;
case 0x8000001e: case 0x8000001e:
/* Do not return host topology information. */
entry->eax = entry->ebx = entry->ecx = 0;
entry->edx = 0; /* reserved */
break; break;
case 0x8000001F: case 0x8000001F:
if (!kvm_cpu_cap_has(X86_FEATURE_SEV)) { if (!kvm_cpu_cap_has(X86_FEATURE_SEV)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment