KVM: x86: Do not return host topology information from KVM_GET_SUPPORTED_CPUID
[ Upstream commit 45e966fcca
]
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: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
0027164b24
commit
196c6f0c3e
@ -6433,6 +6433,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
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@ -511,15 +511,21 @@ struct kvm_cpuid_array {
|
|||||||
int nent;
|
int nent;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct kvm_cpuid_entry2 *do_host_cpuid(struct kvm_cpuid_array *array,
|
static struct kvm_cpuid_entry2 *get_next_cpuid(struct kvm_cpuid_array *array)
|
||||||
u32 function, u32 index)
|
|
||||||
{
|
{
|
||||||
struct kvm_cpuid_entry2 *entry;
|
|
||||||
|
|
||||||
if (array->nent >= array->maxnent)
|
if (array->nent >= array->maxnent)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
entry = &array->entries[array->nent++];
|
return &array->entries[array->nent++];
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kvm_cpuid_entry2 *do_host_cpuid(struct kvm_cpuid_array *array,
|
||||||
|
u32 function, u32 index)
|
||||||
|
{
|
||||||
|
struct kvm_cpuid_entry2 *entry = get_next_cpuid(array);
|
||||||
|
|
||||||
|
if (!entry)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
entry->function = function;
|
entry->function = function;
|
||||||
entry->index = index;
|
entry->index = index;
|
||||||
@ -698,22 +704,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:
|
||||||
entry->eax &= supported_xcr0;
|
entry->eax &= supported_xcr0;
|
||||||
@ -866,6 +863,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;
|
||||||
/* Support memory encryption cpuid if host supports it */
|
/* Support memory encryption cpuid if host supports it */
|
||||||
case 0x8000001F:
|
case 0x8000001F:
|
||||||
|
Reference in New Issue
Block a user