* [PATCH AUTOSEL 5.3 25/68] kvm: x86: Fix a spurious -E2BIG in __do_cpuid_func
2019-10-09 17:04 [PATCH AUTOSEL 5.3 01/68] KVM: arm/arm64: vgic: Use the appropriate TRACE_INCLUDE_PATH Sasha Levin
@ 2019-10-09 17:05 ` Sasha Levin
2019-10-09 17:05 ` [PATCH AUTOSEL 5.3 26/68] kvm: x86: Improve emulation of CPUID leaves 0BH and 1FH Sasha Levin
` (2 subsequent siblings)
3 siblings, 0 replies; 9+ messages in thread
From: Sasha Levin @ 2019-10-09 17:05 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Jim Mattson, Paolo Bonzini, Peter Shier, Sean Christopherson,
Sasha Levin, kvm
From: Jim Mattson <jmattson@google.com>
[ Upstream commit a1a640b8c0cd8a2a7f84ab694f04bc64dc6988af ]
Don't return -E2BIG from __do_cpuid_func when processing function 0BH
or 1FH and the last interesting subleaf occupies the last allocated
entry in the result array.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Fixes: 831bf664e9c1fc ("KVM: Refactor and simplify kvm_dev_ioctl_get_supported_cpuid")
Signed-off-by: Jim Mattson <jmattson@google.com>
Reviewed-by: Peter Shier <pshier@google.com>
Reviewed-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/x86/kvm/cpuid.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index e7d25f4364664..429648ae5653f 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -612,16 +612,20 @@ static inline int __do_cpuid_func(struct kvm_cpuid_entry2 *entry, u32 function,
*/
case 0x1f:
case 0xb: {
- int i, level_type;
+ int i;
- /* read more entries until level_type is zero */
- for (i = 1; ; ++i) {
+ /*
+ * We filled in entry[0] for CPUID(EAX=<function>,
+ * ECX=00H) above. If its level type (ECX[15:8]) is
+ * zero, then the leaf is unimplemented, and we're
+ * done. Otherwise, continue to populate entries
+ * until the level type (ECX[15:8]) of the previously
+ * added entry is zero.
+ */
+ for (i = 1; entry[i - 1].ecx & 0xff00; ++i) {
if (*nent >= maxnent)
goto out;
- level_type = entry[i - 1].ecx & 0xff00;
- if (!level_type)
- break;
do_host_cpuid(&entry[i], function, i);
++*nent;
}
--
2.20.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH AUTOSEL 5.3 26/68] kvm: x86: Improve emulation of CPUID leaves 0BH and 1FH
2019-10-09 17:04 [PATCH AUTOSEL 5.3 01/68] KVM: arm/arm64: vgic: Use the appropriate TRACE_INCLUDE_PATH Sasha Levin
2019-10-09 17:05 ` [PATCH AUTOSEL 5.3 25/68] kvm: x86: Fix a spurious -E2BIG in __do_cpuid_func Sasha Levin
@ 2019-10-09 17:05 ` Sasha Levin
2019-10-09 17:05 ` [PATCH AUTOSEL 5.3 27/68] kvm: x86: Use AMD CPUID semantics for AMD vCPUs Sasha Levin
2019-10-09 17:05 ` [PATCH AUTOSEL 5.3 28/68] KVM: x86: Expose XSAVEERPTR to the guest Sasha Levin
3 siblings, 0 replies; 9+ messages in thread
From: Sasha Levin @ 2019-10-09 17:05 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Jim Mattson, Marc Orr, Peter Shier, Jacob Xu, Sean Christopherson,
Paolo Bonzini, Sasha Levin, kvm
From: Jim Mattson <jmattson@google.com>
[ Upstream commit 43561123ab3759eb6ff47693aec1a307af0aef83 ]
For these CPUID leaves, the EDX output is not dependent on the ECX
input (i.e. the SIGNIFCANT_INDEX flag doesn't apply to
EDX). Furthermore, the low byte of the ECX output is always identical
to the low byte of the ECX input. KVM does not produce the correct ECX
and EDX outputs for any undefined subleaves beyond the first.
Special-case these CPUID leaves in kvm_cpuid, so that the ECX and EDX
outputs are properly generated for all undefined subleaves.
Fixes: 0771671749b59a ("KVM: Enhance guest cpuid management")
Fixes: a87f2d3a6eadab ("KVM: x86: Add Intel CPUID.1F cpuid emulation support")
Signed-off-by: Jim Mattson <jmattson@google.com>
Reviewed-by: Marc Orr <marcorr@google.com>
Reviewed-by: Peter Shier <pshier@google.com>
Reviewed-by: Jacob Xu <jacobhxu@google.com>
Cc: Sean Christopherson <sean.j.christopherson@intel.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/x86/kvm/cpuid.c | 83 +++++++++++++++++++++++++-------------------
1 file changed, 47 insertions(+), 36 deletions(-)
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 429648ae5653f..a8a46e0b3d13b 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -962,53 +962,64 @@ struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu,
EXPORT_SYMBOL_GPL(kvm_find_cpuid_entry);
/*
- * If no match is found, check whether we exceed the vCPU's limit
- * and return the content of the highest valid _standard_ leaf instead.
- * This is to satisfy the CPUID specification.
+ * If the basic or extended CPUID leaf requested is higher than the
+ * maximum supported basic or extended leaf, respectively, then it is
+ * out of range.
*/
-static struct kvm_cpuid_entry2* check_cpuid_limit(struct kvm_vcpu *vcpu,
- u32 function, u32 index)
+static bool cpuid_function_in_range(struct kvm_vcpu *vcpu, u32 function)
{
- struct kvm_cpuid_entry2 *maxlevel;
-
- maxlevel = kvm_find_cpuid_entry(vcpu, function & 0x80000000, 0);
- if (!maxlevel || maxlevel->eax >= function)
- return NULL;
- if (function & 0x80000000) {
- maxlevel = kvm_find_cpuid_entry(vcpu, 0, 0);
- if (!maxlevel)
- return NULL;
- }
- return kvm_find_cpuid_entry(vcpu, maxlevel->eax, index);
+ struct kvm_cpuid_entry2 *max;
+
+ max = kvm_find_cpuid_entry(vcpu, function & 0x80000000, 0);
+ return max && function <= max->eax;
}
bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
u32 *ecx, u32 *edx, bool check_limit)
{
u32 function = *eax, index = *ecx;
- struct kvm_cpuid_entry2 *best;
- bool entry_found = true;
-
- best = kvm_find_cpuid_entry(vcpu, function, index);
-
- if (!best) {
- entry_found = false;
- if (!check_limit)
- goto out;
+ struct kvm_cpuid_entry2 *entry;
+ struct kvm_cpuid_entry2 *max;
+ bool found;
- best = check_cpuid_limit(vcpu, function, index);
+ entry = kvm_find_cpuid_entry(vcpu, function, index);
+ found = entry;
+ /*
+ * Intel CPUID semantics treats any query for an out-of-range
+ * leaf as if the highest basic leaf (i.e. CPUID.0H:EAX) were
+ * requested.
+ */
+ if (!entry && check_limit && !cpuid_function_in_range(vcpu, function)) {
+ max = kvm_find_cpuid_entry(vcpu, 0, 0);
+ if (max) {
+ function = max->eax;
+ entry = kvm_find_cpuid_entry(vcpu, function, index);
+ }
}
-
-out:
- if (best) {
- *eax = best->eax;
- *ebx = best->ebx;
- *ecx = best->ecx;
- *edx = best->edx;
- } else
+ if (entry) {
+ *eax = entry->eax;
+ *ebx = entry->ebx;
+ *ecx = entry->ecx;
+ *edx = entry->edx;
+ } else {
*eax = *ebx = *ecx = *edx = 0;
- trace_kvm_cpuid(function, *eax, *ebx, *ecx, *edx, entry_found);
- return entry_found;
+ /*
+ * When leaf 0BH or 1FH is defined, CL is pass-through
+ * and EDX is always the x2APIC ID, even for undefined
+ * subleaves. Index 1 will exist iff the leaf is
+ * implemented, so we pass through CL iff leaf 1
+ * exists. EDX can be copied from any existing index.
+ */
+ if (function == 0xb || function == 0x1f) {
+ entry = kvm_find_cpuid_entry(vcpu, function, 1);
+ if (entry) {
+ *ecx = index & 0xff;
+ *edx = entry->edx;
+ }
+ }
+ }
+ trace_kvm_cpuid(function, *eax, *ebx, *ecx, *edx, found);
+ return found;
}
EXPORT_SYMBOL_GPL(kvm_cpuid);
--
2.20.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH AUTOSEL 5.3 27/68] kvm: x86: Use AMD CPUID semantics for AMD vCPUs
2019-10-09 17:04 [PATCH AUTOSEL 5.3 01/68] KVM: arm/arm64: vgic: Use the appropriate TRACE_INCLUDE_PATH Sasha Levin
2019-10-09 17:05 ` [PATCH AUTOSEL 5.3 25/68] kvm: x86: Fix a spurious -E2BIG in __do_cpuid_func Sasha Levin
2019-10-09 17:05 ` [PATCH AUTOSEL 5.3 26/68] kvm: x86: Improve emulation of CPUID leaves 0BH and 1FH Sasha Levin
@ 2019-10-09 17:05 ` Sasha Levin
2019-10-09 17:05 ` [PATCH AUTOSEL 5.3 28/68] KVM: x86: Expose XSAVEERPTR to the guest Sasha Levin
3 siblings, 0 replies; 9+ messages in thread
From: Sasha Levin @ 2019-10-09 17:05 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Jim Mattson, Marc Orr, Peter Shier, Jacob Xu, Sean Christopherson,
Paolo Bonzini, Sasha Levin, kvm
From: Jim Mattson <jmattson@google.com>
[ Upstream commit 5f41a37b151f6459e0b650a2f4d1d59b6c02d1ab ]
When the guest CPUID information represents an AMD vCPU, return all
zeroes for queries of undefined CPUID leaves, whether or not they are
in range.
Signed-off-by: Jim Mattson <jmattson@google.com>
Fixes: bd22f5cfcfe8f6 ("KVM: move and fix substitue search for missing CPUID entries")
Reviewed-by: Marc Orr <marcorr@google.com>
Reviewed-by: Peter Shier <pshier@google.com>
Reviewed-by: Jacob Xu <jacobhxu@google.com>
Cc: Sean Christopherson <sean.j.christopherson@intel.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/x86/kvm/cpuid.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index a8a46e0b3d13b..fd1b8db8bf242 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -987,9 +987,11 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
/*
* Intel CPUID semantics treats any query for an out-of-range
* leaf as if the highest basic leaf (i.e. CPUID.0H:EAX) were
- * requested.
+ * requested. AMD CPUID semantics returns all zeroes for any
+ * undefined leaf, whether or not the leaf is in range.
*/
- if (!entry && check_limit && !cpuid_function_in_range(vcpu, function)) {
+ if (!entry && check_limit && !guest_cpuid_is_amd(vcpu) &&
+ !cpuid_function_in_range(vcpu, function)) {
max = kvm_find_cpuid_entry(vcpu, 0, 0);
if (max) {
function = max->eax;
--
2.20.1
^ permalink raw reply related [flat|nested] 9+ messages in thread